Snapshot cdeccf6fdd8c2d494ea2867cb37a025bf8879baf

Change-Id: Ia2de32ccb97a9641462c72363b0a8c4288f4f36d
diff --git a/bta/Android.mk b/bta/Android.mk
new file mode 100644
index 0000000..7d1c19e
--- /dev/null
+++ b/bta/Android.mk
@@ -0,0 +1,104 @@
+ifneq ($(TARGET_SIMULATOR),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+ifeq ($(BOARD_HAVE_BLUETOOTH_BCM),true)
+LOCAL_CFLAGS += \
+	-DBOARD_HAVE_BLUETOOTH_BCM
+endif
+LOCAL_CFLAGS += -DBUILDCFG $(bdroid_CFLAGS)
+
+LOCAL_PRELINK_MODULE:=false
+LOCAL_SRC_FILES:= \
+    ./dm/bta_dm_ci.c \
+    ./dm/bta_dm_act.c \
+    ./dm/bta_dm_pm.c \
+    ./dm/bta_dm_main.c \
+    ./dm/bta_dm_cfg.c \
+    ./dm/bta_dm_api.c \
+    ./dm/bta_dm_sco.c \
+    ./gatt/bta_gattc_api.c \
+    ./gatt/bta_gatts_act.c \
+    ./gatt/bta_gatts_main.c \
+    ./gatt/bta_gattc_utils.c \
+    ./gatt/bta_gattc_ci.c \
+    ./gatt/bta_gatts_api.c \
+    ./gatt/bta_gattc_main.c \
+    ./gatt/bta_gattc_act.c \
+    ./gatt/bta_gattc_cache.c \
+    ./gatt/bta_gatts_utils.c \
+    ./ag/bta_ag_sdp.c \
+    ./ag/bta_ag_sco.c \
+    ./ag/bta_ag_cfg.c \
+    ./ag/bta_ag_main.c \
+    ./ag/bta_ag_api.c \
+    ./ag/bta_ag_rfc.c \
+    ./ag/bta_ag_act.c \
+    ./ag/bta_ag_cmd.c \
+    ./ag/bta_ag_ci.c \
+    ./ag/bta_ag_at.c \
+    ./hh/bta_hh_cfg.c \
+    ./hh/bta_hh_act.c \
+    ./hh/bta_hh_api.c \
+    ./hh/bta_hh_utils.c \
+    ./hh/bta_hh_main.c \
+    ./pb/bta_pbs_cfg.c \
+    ./fs/bta_fs_ci.c \
+    ./fs/bta_fs_cfg.c \
+    ./pan/bta_pan_main.c \
+    ./pan/bta_pan_ci.c \
+    ./pan/bta_pan_act.c \
+    ./pan/bta_pan_api.c \
+    ./av/bta_av_act.c \
+    ./av/bta_av_ci.c \
+    ./av/bta_av_api.c \
+    ./av/bta_av_aact.c \
+    ./av/bta_av_main.c \
+    ./av/bta_av_cfg.c \
+    ./av/bta_av_ssm.c \
+    ./av/bta_av_sbc.c \
+    ./ar/bta_ar.c \
+    ./hl/bta_hl_act.c \
+    ./hl/bta_hl_api.c \
+    ./hl/bta_hl_main.c \
+    ./hl/bta_hl_utils.c \
+    ./hl/bta_hl_sdp.c \
+    ./hl/bta_hl_ci.c \
+    ./sys/bta_sys_main.c \
+    ./sys/bta_sys_ci.c \
+    ./sys/bta_sys_conn.c \
+    ./sys/bta_sys_cfg.c \
+    ./sys/ptim.c \
+    ./sys/bd.c \
+    ./sys/utl.c \
+    ./jv/bta_jv_act.c \
+    ./jv/bta_jv_cfg.c \
+    ./jv/bta_jv_main.c \
+    ./jv/bta_jv_api.c
+
+LOCAL_MODULE := libbt-brcm_bta
+LOCAL_MODULE_CLASS := STATIC_LIBRARIES
+LOCAL_MODULE_TAGS := optional
+LOCAL_SHARED_LIBRARIES := libcutils libc
+
+LOCAL_C_INCLUDES+= . \
+                   $(LOCAL_PATH)/include \
+                   $(LOCAL_PATH)/sys \
+                   $(LOCAL_PATH)/dm \
+                   $(LOCAL_PATH)/../gki/common \
+                   $(LOCAL_PATH)/../gki/ulinux \
+                   $(LOCAL_PATH)/../include \
+                   $(LOCAL_PATH)/../stack/include \
+                   $(LOCAL_PATH)/../stack/btm \
+                   $(LOCAL_PATH)/../hcis \
+                   $(LOCAL_PATH)/../hcis/patchram \
+                   $(LOCAL_PATH)/../udrv/include \
+                   $(LOCAL_PATH)/../brcm/include \
+                   $(bdroid_C_INCLUDES) \
+
+
+include $(BUILD_STATIC_LIBRARY)
+
+endif  # TARGET_SIMULATOR != true
diff --git a/bta/ag/bta_ag_act.c b/bta/ag/bta_ag_act.c
new file mode 100644
index 0000000..5f72444
--- /dev/null
+++ b/bta/ag/bta_ag_act.c
@@ -0,0 +1,867 @@
+/******************************************************************************
+ *
+ *  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 action functions for the audio gateway.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_co.h"
+#include "bta_ag_int.h"
+#include "port_api.h"
+#include "utl.h"
+#include <string.h>
+#include "bta_dm_int.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/* maximum length of data to read from RFCOMM */
+#define BTA_AG_RFC_READ_MAX     512
+
+/* maximum AT command length */
+#define BTA_AG_CMD_MAX          512
+
+const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX] =
+{
+    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
+    UUID_SERVCLASS_AG_HANDSFREE
+};
+
+const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX] =
+{
+    BTM_SEC_SERVICE_HEADSET_AG,
+    BTM_SEC_SERVICE_AG_HANDSFREE
+};
+
+const tBTA_SERVICE_ID bta_ag_svc_id[BTA_AG_NUM_IDX] =
+{
+    BTA_HSP_SERVICE_ID,
+    BTA_HFP_SERVICE_ID
+};
+
+const tBTA_SERVICE_MASK bta_ag_svc_mask[BTA_AG_NUM_IDX] =
+{
+    BTA_HSP_SERVICE_MASK,
+    BTA_HFP_SERVICE_MASK
+};
+
+typedef void (*tBTA_AG_ATCMD_CBACK)(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+                                    char *p_arg, INT16 int_arg);
+
+const tBTA_AG_ATCMD_CBACK bta_ag_at_cback_tbl[BTA_AG_NUM_IDX] =
+{
+    bta_ag_at_hsp_cback,
+    bta_ag_at_hfp_cback
+};
+
+/*******************************************************************************
+**
+** Function         bta_ag_cback_open
+**
+** Description      Send open callback event to application.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_cback_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data, tBTA_AG_STATUS status)
+{
+    tBTA_AG_OPEN    open;
+
+    /* call app callback with open event */
+    open.hdr.handle = bta_ag_scb_to_idx(p_scb);
+    open.hdr.app_id = p_scb->app_id;
+    open.status = status;
+    open.service_id = bta_ag_svc_id[p_scb->conn_service];
+    if(p_data)
+    {
+        /* if p_data is provided then we need to pick the bd address from the open api structure */
+        bdcpy(open.bd_addr, p_data->api_open.bd_addr);
+    }
+    else
+    {
+        bdcpy(open.bd_addr, p_scb->peer_addr);
+    }
+
+    (*bta_ag_cb.p_cback)(BTA_AG_OPEN_EVT, (tBTA_AG *) &open);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_register
+**
+** Description      This function initializes values of the AG cb and sets up
+**                  the SDP record for the services.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_REGISTER reg;
+
+    /* initialize control block */
+    p_scb->reg_services = p_data->api_register.services;
+    p_scb->serv_sec_mask = p_data->api_register.sec_mask;
+    p_scb->features = p_data->api_register.features;
+    p_scb->app_id = p_data->api_register.app_id;
+
+    /* create SDP records */
+    bta_ag_create_records(p_scb, p_data);
+
+    /* start RFCOMM servers */
+    bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+    /* call app callback with register event */
+    reg.hdr.handle = bta_ag_scb_to_idx(p_scb);
+    reg.hdr.app_id = p_scb->app_id;
+    reg.status = BTA_AG_SUCCESS;
+    (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) &reg);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_deregister
+**
+** Description      This function removes the sdp records, closes the RFCOMM
+**                  servers, and deallocates the service control block.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* set dealloc */
+    p_scb->dealloc = TRUE;
+
+    /* remove sdp records */
+    bta_ag_del_records(p_scb, p_data);
+
+    /* remove rfcomm servers */
+    bta_ag_close_servers(p_scb, p_scb->reg_services);
+
+    /* dealloc */
+    bta_ag_scb_dealloc(p_scb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_start_dereg
+**
+** Description      Start a deregister event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* set dealloc */
+    p_scb->dealloc = TRUE;
+
+    /* remove sdp records */
+    bta_ag_del_records(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_start_open
+**
+** Description      This starts an AG open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    BD_ADDR pending_bd_addr;
+
+    /* store parameters */
+    if (p_data)
+    {
+        bdcpy(p_scb->peer_addr, p_data->api_open.bd_addr);
+        p_scb->open_services = p_data->api_open.services;
+        p_scb->cli_sec_mask = p_data->api_open.sec_mask;
+    }
+
+    /* Check if RFCOMM has any incoming connection to avoid collision. */
+    if (PORT_IsOpening (pending_bd_addr))
+    {
+        /* Let the incoming connection goes through.                        */
+        /* Issue collision for this scb for now.                            */
+        /* We will decide what to do when we find incoming connetion later. */
+        bta_ag_collision_cback (0, BTA_ID_AG, 0, p_scb->peer_addr);
+        return;
+    }
+
+    /* close servers */
+    bta_ag_close_servers(p_scb, p_scb->reg_services);
+
+    /* set role */
+    p_scb->role = BTA_AG_INT;
+
+    /* do service search */
+    bta_ag_do_disc(p_scb, p_scb->open_services);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_disc_int_res
+**
+** Description      This function handles a discovery result when initiator.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16 event = BTA_AG_DISC_FAIL_EVT;
+
+    APPL_TRACE_DEBUG1 ("bta_ag_disc_int_res: Status: %d", p_data->disc_result.status);
+
+    /* if found service */
+    if (p_data->disc_result.status == SDP_SUCCESS ||
+        p_data->disc_result.status == SDP_DB_FULL)
+    {
+        /* get attributes */
+        if (bta_ag_sdp_find_attr(p_scb, p_scb->open_services))
+        {
+            /* set connected service */
+            p_scb->conn_service = bta_ag_service_to_idx(p_scb->open_services);
+
+            /* send ourselves sdp ok event */
+            event = BTA_AG_DISC_OK_EVT;
+        }
+    }
+
+    /* free discovery db */
+    bta_ag_free_db(p_scb, p_data);
+
+    /* if service not found check if we should search for other service */
+    if ((event == BTA_AG_DISC_FAIL_EVT) &&
+        (p_data->disc_result.status == SDP_SUCCESS ||
+         p_data->disc_result.status == SDP_DB_FULL ||
+         p_data->disc_result.status == SDP_NO_RECS_MATCH))
+    {
+        if ((p_scb->open_services & BTA_HFP_SERVICE_MASK) &&
+            (p_scb->open_services & BTA_HSP_SERVICE_MASK))
+        {
+            /* search for HSP */
+            p_scb->open_services &= ~BTA_HFP_SERVICE_MASK;
+            bta_ag_do_disc(p_scb, p_scb->open_services);
+        }
+        else if ((p_scb->open_services & BTA_HSP_SERVICE_MASK) &&
+                 (p_scb->hsp_version == HSP_VERSION_1_2))
+        {
+            /* search for UUID_SERVCLASS_HEADSET for HSP 1.0 device */
+            p_scb->hsp_version = HSP_VERSION_1_0;
+            bta_ag_do_disc(p_scb, p_scb->open_services);
+        }
+        else
+        {
+            /* send ourselves sdp ok/fail event */
+            bta_ag_sm_execute(p_scb, event, p_data);
+        }
+    }
+    else
+    {
+        /* send ourselves sdp ok/fail event */
+        bta_ag_sm_execute(p_scb, event, p_data);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_disc_acp_res
+**
+** Description      This function handles a discovery result when acceptor.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* if found service */
+    if (p_data->disc_result.status == SDP_SUCCESS ||
+        p_data->disc_result.status == SDP_DB_FULL)
+    {
+        /* get attributes */
+        bta_ag_sdp_find_attr(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
+    }
+
+    /* free discovery db */
+    bta_ag_free_db(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_disc_fail
+**
+** Description      This function handles a discovery failure.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* reopen registered servers */
+    bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+    /* reinitialize stuff */
+
+    /* call open cback w. failure */
+    bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_SDP);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_open_fail
+**
+** Description      open connection failed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* call open cback w. failure */
+    bta_ag_cback_open(p_scb, p_data, BTA_AG_FAIL_RESOURCES);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_fail
+**
+** Description      RFCOMM connection failed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* reinitialize stuff */
+    p_scb->conn_handle = 0;
+    p_scb->conn_service = 0;
+    p_scb->peer_features = 0;
+#if (BTM_WBS_INCLUDED == TRUE )
+    p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+    p_scb->sco_codec = BTA_AG_CODEC_NONE;
+#endif
+    p_scb->role = 0;
+    p_scb->svc_conn = FALSE;
+    p_scb->hsp_version = HSP_VERSION_1_2;
+
+    /* reopen registered servers */
+    bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+    /* call open cback w. failure */
+    bta_ag_cback_open(p_scb, NULL, BTA_AG_FAIL_RFCOMM);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_close
+**
+** Description      RFCOMM connection closed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_HDR    close;
+    tBTA_SERVICE_MASK services;
+    int i, num_active_conn = 0;
+
+#ifdef  _WIN32_WCE
+    /* The BTE RFCOMM automatically removes the connection when closed, but BTW does not */
+    if (p_scb->conn_handle != 0)
+        RFCOMM_RemoveConnection (p_scb->conn_handle);
+#endif
+
+    /* reinitialize stuff */
+    p_scb->conn_service = 0;
+    p_scb->peer_features = 0;
+#if (BTM_WBS_INCLUDED == TRUE )
+    p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+    p_scb->sco_codec = BTA_AG_CODEC_NONE;
+#endif
+    p_scb->role = 0;
+    p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+    p_scb->svc_conn = FALSE;
+    p_scb->hsp_version = HSP_VERSION_1_2;
+    bta_ag_at_reinit(&p_scb->at_cb);
+
+    /* stop timers */
+    bta_sys_stop_timer(&p_scb->act_timer);
+#if (BTM_WBS_INCLUDED == TRUE)
+    bta_sys_stop_timer(&p_scb->cn_timer);
+#endif
+
+    close.handle = bta_ag_scb_to_idx(p_scb);
+    close.app_id = p_scb->app_id;
+
+    bta_sys_conn_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+    /* call close call-out */
+    bta_ag_co_data_close(close.handle);
+
+    /* call close cback */
+    (*bta_ag_cb.p_cback)(BTA_AG_CLOSE_EVT, (tBTA_AG *) &close);
+
+    /* if not deregistering (deallocating) reopen registered servers */
+    if (p_scb->dealloc == FALSE)
+    {
+        /* Clear peer bd_addr so instance can be reused */
+        bdcpy(p_scb->peer_addr, bd_addr_null);
+
+        /* start only unopened server */
+        services = p_scb->reg_services;
+        for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++)
+        {
+            if(p_scb->serv_handle[i])
+                services &= ~((tBTA_SERVICE_MASK)1 << (BTA_HSP_SERVICE_ID + i));
+        }
+        bta_ag_start_servers(p_scb, services);
+
+        p_scb->conn_handle = 0;
+
+        /* Make sure SCO state is BTA_AG_SCO_SHUTDOWN_ST */
+        bta_ag_sco_shutdown(p_scb, NULL);
+
+        /* Check if all the SLCs are down */
+        for (i = 0; i < BTA_AG_NUM_SCB; i++)
+        {
+            if (bta_ag_cb.scb[i].in_use && bta_ag_cb.scb[i].svc_conn)
+                num_active_conn++;
+        }
+
+        if(!num_active_conn)
+        {
+            bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+        }
+
+    }
+    /* else close port and deallocate scb */
+    else
+    {
+        RFCOMM_RemoveServer(p_scb->conn_handle);
+        bta_ag_scb_dealloc(p_scb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_open
+**
+** Description      Handle RFCOMM channel open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* initialize AT feature variables */
+    p_scb->clip_enabled = FALSE;
+    p_scb->ccwa_enabled = FALSE;
+    p_scb->cmer_enabled = FALSE;
+    p_scb->cmee_enabled = FALSE;
+    p_scb->inband_enabled = ((p_scb->features & BTA_AG_FEAT_INBAND) == BTA_AG_FEAT_INBAND);
+
+    /* set up AT command interpreter */
+    p_scb->at_cb.p_at_tbl = (tBTA_AG_AT_CMD *) bta_ag_at_tbl[p_scb->conn_service];
+    p_scb->at_cb.p_cmd_cback = (tBTA_AG_AT_CMD_CBACK *) bta_ag_at_cback_tbl[p_scb->conn_service];
+    p_scb->at_cb.p_err_cback = (tBTA_AG_AT_ERR_CBACK *) bta_ag_at_err_cback;
+    p_scb->at_cb.p_user = p_scb;
+    p_scb->at_cb.cmd_max_len = BTA_AG_CMD_MAX;
+    bta_ag_at_init(&p_scb->at_cb);
+
+    /* call app open call-out */
+    bta_ag_co_data_open(bta_ag_scb_to_idx(p_scb), bta_ag_svc_id[p_scb->conn_service]);
+
+    bta_sys_conn_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+    bta_ag_cback_open(p_scb, NULL, BTA_AG_SUCCESS);
+
+    if (p_scb->conn_service == BTA_AG_HFP)
+    {
+        /* if hfp start timer for service level conn */
+        bta_sys_start_timer(&p_scb->act_timer, BTA_AG_SVC_TOUT_EVT, p_bta_ag_cfg->conn_tout);
+    }
+    else
+    {
+        /* else service level conn is open */
+        bta_ag_svc_conn_open(p_scb, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_acp_open
+**
+** Description      Handle RFCOMM channel open when accepting connection.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16          lcid;
+    int             i;
+    tBTA_AG_SCB     *ag_scb, *other_scb;
+    BD_ADDR         dev_addr;
+    int             status;
+
+    /* set role */
+    p_scb->role = BTA_AG_ACP;
+
+    APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: serv_handle0 = %d serv_handle1 = %d",
+                       p_scb->serv_handle[0], p_scb->serv_handle[1]);
+
+    /* get bd addr of peer */
+    if (PORT_SUCCESS != (status=PORT_CheckConnection(p_data->rfc.port_handle, dev_addr, &lcid)))
+    {
+        APPL_TRACE_DEBUG1 ("bta_ag_rfc_acp_open error PORT_CheckConnection returned status %d", status);
+    }
+
+    /* Collision Handling */
+    for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+    {
+        if ((ag_scb->in_use) && (ag_scb->colli_tmr_on))
+        {
+            /* stop collision timer */
+            ag_scb->colli_tmr_on = FALSE;
+            bta_sys_stop_timer (&ag_scb->colli_timer);
+
+            if (bdcmp (dev_addr, ag_scb->peer_addr) == 0)
+            {
+                /* If incoming and outgoing device are same, nothing more to do.            */
+                /* Outgoing conn will be aborted because we have successful incoming conn.  */
+            }
+            else
+            {
+                /* Resume outgoing connection. */
+                other_scb = bta_ag_get_other_idle_scb (p_scb);
+                if (other_scb)
+                {
+                    bdcpy(other_scb->peer_addr, ag_scb->peer_addr);
+                    other_scb->open_services = ag_scb->open_services;
+                    other_scb->cli_sec_mask = ag_scb->cli_sec_mask;
+
+                    bta_ag_resume_open (other_scb);
+                }
+            }
+
+            break;
+        }
+    }
+
+    bdcpy (p_scb->peer_addr, dev_addr);
+
+    /* determine connected service from port handle */
+    for (i = 0; i < BTA_AG_NUM_IDX; i++)
+    {
+        APPL_TRACE_DEBUG3 ("bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d",
+                           i, p_scb->serv_handle[i], p_data->rfc.port_handle);
+
+        if (p_scb->serv_handle[i] == p_data->rfc.port_handle)
+        {
+            p_scb->conn_service = i;
+            p_scb->conn_handle = p_data->rfc.port_handle;
+            break;
+        }
+    }
+
+    APPL_TRACE_DEBUG2 ("bta_ag_rfc_acp_open: conn_service = %d conn_handle = %d",
+                       p_scb->conn_service, p_scb->conn_handle);
+
+    /* close any unopened server */
+    bta_ag_close_servers(p_scb, (p_scb->reg_services & ~bta_ag_svc_mask[p_scb->conn_service]));
+
+    /* do service discovery to get features */
+    bta_ag_do_disc(p_scb, bta_ag_svc_mask[p_scb->conn_service]);
+
+    /* continue with common open processing */
+    bta_ag_rfc_open(p_scb, p_data);
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_data
+**
+** Description      Read and process data from RFCOMM.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16  len;
+    char    buf[BTA_AG_RFC_READ_MAX];
+
+    memset(buf, 0, BTA_AG_RFC_READ_MAX);
+
+    /* do the following */
+    for(;;)
+    {
+        /* read data from rfcomm; if bad status, we're done */
+        if (PORT_ReadData(p_scb->conn_handle, buf, BTA_AG_RFC_READ_MAX, &len) != PORT_SUCCESS)
+        {
+            break;
+        }
+
+        /* if no data, we're done */
+        if (len == 0)
+        {
+            break;
+        }
+
+        /* run AT command interpreter on data */
+        bta_ag_at_parse(&p_scb->at_cb, buf, len);
+
+        /* no more data to read, we're done */
+        if (len < BTA_AG_RFC_READ_MAX)
+        {
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_start_close
+**
+** Description      Start the process of closing SCO and RFCOMM connection.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* Take the link out of sniff and set L2C idle time to 0 */
+    bta_dm_pm_active(p_scb->peer_addr);
+    L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0);
+
+    /* if SCO is open close SCO and wait on RFCOMM close */
+    if (bta_ag_sco_is_open(p_scb))
+    {
+        p_scb->post_sco = BTA_AG_POST_SCO_CLOSE_RFC;
+    }
+    else
+    {
+        p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+        bta_ag_rfc_do_close(p_scb, p_data);
+    }
+
+    /* always do SCO shutdown to handle all SCO corner cases */
+    bta_ag_sco_shutdown(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_post_sco_open
+**
+** Description      Perform post-SCO open action, if any
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    switch (p_scb->post_sco)
+    {
+        case BTA_AG_POST_SCO_RING:
+            bta_ag_send_ring(p_scb, p_data);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        case BTA_AG_POST_SCO_CALL_CONN:
+            bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        default:
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_post_sco_close
+**
+** Description      Perform post-SCO close action, if any
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    switch (p_scb->post_sco)
+    {
+        case BTA_AG_POST_SCO_CLOSE_RFC:
+            bta_ag_rfc_do_close(p_scb, p_data);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        case BTA_AG_POST_SCO_CALL_CONN:
+            bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_CONN_RES);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        case BTA_AG_POST_SCO_CALL_ORIG:
+            bta_ag_send_call_inds(p_scb, BTA_AG_OUT_CALL_ORIG_RES);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        case BTA_AG_POST_SCO_CALL_END:
+            bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
+            p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+            break;
+
+        case BTA_AG_POST_SCO_CALL_END_INCALL:
+            bta_ag_send_call_inds(p_scb, BTA_AG_END_CALL_RES);
+
+            /* Sending callsetup IND and Ring were defered to after SCO close. */
+            bta_ag_send_call_inds(p_scb, BTA_AG_IN_CALL_RES);
+
+            if (bta_ag_inband_enabled(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_RING;
+                bta_ag_sco_open(p_scb, p_data);
+            }
+            else
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+                bta_ag_send_ring(p_scb, p_data);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_svc_conn_open
+**
+** Description      Service level connection opened
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_CONN evt;
+
+    if (!p_scb->svc_conn)
+    {
+        /* set state variable */
+        p_scb->svc_conn = TRUE;
+
+        /* Clear AT+BIA mask from previous SLC if any. */
+        p_scb->bia_masked_out = 0;
+
+        /* stop timer */
+        bta_sys_stop_timer(&p_scb->act_timer);
+
+        /* call callback */
+        evt.hdr.handle = bta_ag_scb_to_idx(p_scb);
+        evt.hdr.app_id = p_scb->app_id;
+        evt.peer_feat = p_scb->peer_features;
+#if (BTM_WBS_INCLUDED == TRUE )
+        evt.peer_codec  = p_scb->peer_codecs;
+#endif
+
+        if ((p_scb->call_ind != BTA_AG_CALL_INACTIVE) ||
+            (p_scb->callsetup_ind != BTA_AG_CALLSETUP_NONE))
+        {
+            bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+        }
+
+        (*bta_ag_cb.p_cback)(BTA_AG_CONN_EVT, (tBTA_AG *) &evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_ci_rx_data
+**
+** Description      Send result code
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16 len;
+    tBTA_AG_CI_RX_WRITE *p_rx_write_msg = (tBTA_AG_CI_RX_WRITE *)p_data;
+    char *p_data_area = (char *)(p_rx_write_msg+1);     /* Point to data area after header */
+
+    /* send to RFCOMM */
+    PORT_WriteData(p_scb->conn_handle, p_data_area, strlen(p_data_area), &len);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rcvd_slc_ready
+**
+** Description      Handles SLC ready call-in in case of pass-through mode.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    APPL_TRACE_DEBUG1("bta_ag_rcvd_slc_ready: handle = %d", bta_ag_scb_to_idx(p_scb));
+
+    if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
+    {
+        /* In pass-through mode, BTA knows that SLC is ready only through call-in. */
+        bta_ag_svc_conn_open(p_scb, NULL);
+    }
+}
+
diff --git a/bta/ag/bta_ag_api.c b/bta/ag/bta_ag_api.c
new file mode 100644
index 0000000..07dceb9
--- /dev/null
+++ b/bta/ag/bta_ag_api.c
@@ -0,0 +1,323 @@
+/******************************************************************************
+ *
+ *  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 is the implementation of the API for the audio gateway (AG)
+ *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "gki.h"
+#include <string.h>
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_ag_reg =
+{
+    bta_ag_hdl_event,
+    BTA_AgDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_AgEnable
+**
+** Description      Enable the audio gateway service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_AG_ENABLE_EVT. This function must
+**                  be called before other function in the AG API are
+**                  called.
+**
+** Returns          BTA_SUCCESS if OK, BTA_FAILURE otherwise.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK *p_cback)
+{
+    tBTA_AG_API_ENABLE  *p_buf;
+    UINT8       idx;
+
+    /* Error if AG is already enabled, or AG is in the middle of disabling. */
+    for (idx = 0; idx < BTA_AG_NUM_SCB; idx++)
+    {
+        if (bta_ag_cb.scb[idx].in_use)
+        {
+            APPL_TRACE_ERROR0 ("BTA_AgEnable: FAILED, AG already enabled.");
+            return BTA_FAILURE;
+        }
+    }
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_AG, &bta_ag_reg);
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_AG_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AG_API_ENABLE))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_API_ENABLE_EVT;
+        p_buf->parse_mode = parse_mode;
+        p_buf->p_cback = p_cback;
+        bta_sys_sendmsg(p_buf);
+    }
+
+    return BTA_SUCCESS;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgDisable
+**
+** Description      Disable the audio gateway service
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AG_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgRegister
+**
+** Description      Register an Audio Gateway service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,tBTA_AG_FEAT features,
+                  char * p_service_names[], UINT8 app_id)
+{
+    tBTA_AG_API_REGISTER    *p_buf;
+    int                     i;
+
+    if ((p_buf = (tBTA_AG_API_REGISTER *) GKI_getbuf(sizeof(tBTA_AG_API_REGISTER))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_API_REGISTER_EVT;
+        p_buf->features = features;
+        p_buf->sec_mask = sec_mask;
+        p_buf->services = services;
+        p_buf->app_id = app_id;
+        for (i = 0; i < BTA_AG_NUM_IDX; i++)
+        {
+            if(p_service_names[i])
+            {
+                BCM_STRNCPY_S(p_buf->p_name[i], BTA_SERVICE_NAME_LEN+1, p_service_names[i], BTA_SERVICE_NAME_LEN);
+                p_buf->p_name[i][BTA_SERVICE_NAME_LEN] = 0;
+            }
+            else
+            {
+                p_buf->p_name[i][0] = 0;
+            }
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgDeregister
+**
+** Description      Deregister an audio gateway service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgDeregister(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AG_API_DEREGISTER_EVT;
+        p_buf->layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgOpen
+**
+** Description      Opens a connection to a headset or hands-free device.
+**                  When connection is open callback function is called
+**                  with a BTA_AG_OPEN_EVT. Only the data connection is
+**                  opened. The audio connection is not opened.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask, tBTA_SERVICE_MASK services)
+{
+    tBTA_AG_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_AG_API_OPEN *) GKI_getbuf(sizeof(tBTA_AG_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_API_OPEN_EVT;
+        p_buf->hdr.layer_specific = handle;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        p_buf->services = services;
+        p_buf->sec_mask = sec_mask;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgClose
+**
+** Description      Close the current connection to a headset or a handsfree
+**                  Any current audio connection will also be closed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgClose(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AG_API_CLOSE_EVT;
+        p_buf->layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgAudioOpen
+**
+** Description      Opens an audio connection to the currently connected
+**                  headset or hnadsfree.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgAudioOpen(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AG_API_AUDIO_OPEN_EVT;
+        p_buf->layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgAudioClose
+**
+** Description      Close the currently active audio connection to a headset
+**                  or hnadsfree. The data connection remains open
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgAudioClose(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AG_API_AUDIO_CLOSE_EVT;
+        p_buf->layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_AgResult
+**
+** Description      Send an AT result code to a headset or hands-free device.
+**                  This function is only used when the AG parse mode is set
+**                  to BTA_AG_PARSE.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data)
+{
+    tBTA_AG_API_RESULT  *p_buf;
+
+    if ((p_buf = (tBTA_AG_API_RESULT *) GKI_getbuf(sizeof(tBTA_AG_API_RESULT))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_API_RESULT_EVT;
+        p_buf->hdr.layer_specific = handle;
+        p_buf->result = result;
+        if(p_data)
+        {
+            memcpy(&p_buf->data, p_data, sizeof(p_buf->data));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AgSetCodec
+**
+** Description      Specify the codec type to be used for the subsequent
+**                  audio connection.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec)
+{
+    tBTA_AG_API_SETCODEC    *p_buf;
+
+    if ((p_buf = (tBTA_AG_API_SETCODEC *) GKI_getbuf(sizeof(tBTA_AG_API_SETCODEC))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_API_SETCODEC_EVT;
+        p_buf->hdr.layer_specific = handle;
+        p_buf->codec = codec;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
diff --git a/bta/ag/bta_ag_at.c b/bta/ag/bta_ag_at.c
new file mode 100644
index 0000000..74d3948
--- /dev/null
+++ b/bta/ag/bta_ag_at.c
@@ -0,0 +1,243 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  BTA AG AT command interpreter.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "gki.h"
+#include "bta_ag_at.h"
+#include "utl.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/******************************************************************************
+**
+** Function         bta_ag_at_init
+**
+** Description      Initialize the AT command parser control block.
+**
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_at_init(tBTA_AG_AT_CB *p_cb)
+{
+    p_cb->p_cmd_buf = NULL;
+    p_cb->cmd_pos = 0;
+}
+
+/******************************************************************************
+**
+** Function         bta_ag_at_reinit
+**
+** Description      Re-initialize the AT command parser control block.  This
+**                  function resets the AT command parser state and frees
+**                  any GKI buffer.
+**
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb)
+{
+    if (p_cb->p_cmd_buf != NULL)
+    {
+        GKI_freebuf(p_cb->p_cmd_buf);
+        p_cb->p_cmd_buf = NULL;
+    }
+    p_cb->cmd_pos = 0;
+}
+/******************************************************************************
+**
+** Function         bta_ag_process_at
+**
+** Description      Parse AT commands.  This function will take the input
+**                  character string and parse it for AT commands according to
+**                  the AT command table passed in the control block.
+**
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_process_at(tBTA_AG_AT_CB *p_cb)
+{
+    UINT16      idx;
+    UINT8       arg_type;
+    char        *p_arg;
+    INT16       int_arg = 0;
+    /* loop through at command table looking for match */
+    for (idx = 0; p_cb->p_at_tbl[idx].p_cmd[0] != 0; idx++)
+    {
+        if (!utl_strucmp(p_cb->p_at_tbl[idx].p_cmd, p_cb->p_cmd_buf))
+        {
+            break;
+        }
+    }
+
+    /* if there is a match; verify argument type */
+    if (p_cb->p_at_tbl[idx].p_cmd[0] != 0)
+    {
+        /* start of argument is p + strlen matching command */
+        p_arg = p_cb->p_cmd_buf + strlen(p_cb->p_at_tbl[idx].p_cmd);
+
+        /* if no argument */
+        if (p_arg[0] == 0)
+        {
+            arg_type = BTA_AG_AT_NONE;
+        }
+        /* else if arg is '?' and it is last character */
+        else if (p_arg[0] == '?' && p_arg[1] == 0)
+        {
+            /* we have a read */
+            arg_type = BTA_AG_AT_READ;
+        }
+        /* else if arg is '=' */
+        else if (p_arg[0] == '=' && p_arg[1] != 0)
+        {
+            if (p_arg[1] == '?' && p_arg[2] == 0)
+            {
+                /* we have a test */
+                arg_type = BTA_AG_AT_TEST;
+            }
+            else
+            {
+                /* we have a set */
+                arg_type = BTA_AG_AT_SET;
+
+                /* skip past '=' */
+                p_arg++;
+            }
+        }
+        else
+        /* else it is freeform argument */
+        {
+            arg_type = BTA_AG_AT_FREE;
+        }
+
+        /* if arguments match command capabilities */
+        if ((arg_type & p_cb->p_at_tbl[idx].arg_type) != 0)
+        {
+            /* if it's a set integer check max, min range */
+            if (arg_type == BTA_AG_AT_SET &&
+                p_cb->p_at_tbl[idx].fmt == BTA_AG_AT_INT)
+            {
+                int_arg = utl_str2int(p_arg);
+                if (int_arg < (INT16) p_cb->p_at_tbl[idx].min ||
+                    int_arg > (INT16) p_cb->p_at_tbl[idx].max)
+                {
+                    /* arg out of range; error */
+                    (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
+                }
+                else
+                {
+
+                    (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+                }
+            }
+            else
+            {
+                (*p_cb->p_cmd_cback)(p_cb->p_user, idx, arg_type, p_arg, int_arg);
+            }
+        }
+        /* else error */
+        else
+        {
+            (*p_cb->p_err_cback)(p_cb->p_user, FALSE, NULL);
+        }
+    }
+    /* else no match call error callback */
+    else
+    {
+        (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
+    }
+}
+
+/******************************************************************************
+**
+** Function         bta_ag_at_parse
+**
+** Description      Parse AT commands.  This function will take the input
+**                  character string and parse it for AT commands according to
+**                  the AT command table passed in the control block.
+**
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len)
+{
+    int i = 0;
+    char* p_save;
+
+    if (p_cb->p_cmd_buf == NULL)
+    {
+        p_cb->p_cmd_buf = (char *) GKI_getbuf(p_cb->cmd_max_len);
+        p_cb->cmd_pos = 0;
+    }
+
+    for (i = 0; i < len;)
+    {
+        while (p_cb->cmd_pos < p_cb->cmd_max_len-1 && i < len)
+        {
+            /* Skip null characters between AT commands. */
+            if ((p_cb->cmd_pos == 0) && (p_buf[i] == 0))
+            {
+                i++;
+                continue;
+            }
+
+            p_cb->p_cmd_buf[p_cb->cmd_pos] = p_buf[i++];
+            if ( p_cb->p_cmd_buf[p_cb->cmd_pos] == '\r' || p_cb->p_cmd_buf[p_cb->cmd_pos] == '\n')
+            {
+                p_cb->p_cmd_buf[p_cb->cmd_pos] = 0;
+                if ((p_cb->cmd_pos > 2)                                      &&
+                    (p_cb->p_cmd_buf[0] == 'A' || p_cb->p_cmd_buf[0] == 'a') &&
+                    (p_cb->p_cmd_buf[1] == 'T' || p_cb->p_cmd_buf[1] == 't'))
+                {
+                    p_save = p_cb->p_cmd_buf;
+                    p_cb->p_cmd_buf += 2;
+                    bta_ag_process_at(p_cb);
+                    p_cb->p_cmd_buf = p_save;
+                }
+
+                p_cb->cmd_pos = 0;
+
+            }
+            else if( p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1A || p_cb->p_cmd_buf[p_cb->cmd_pos] == 0x1B )
+            {
+                p_cb->p_cmd_buf[++p_cb->cmd_pos] = 0;
+                (*p_cb->p_err_cback)(p_cb->p_user, TRUE, p_cb->p_cmd_buf);
+                p_cb->cmd_pos = 0;
+            }
+            else
+            {
+                ++p_cb->cmd_pos;
+            }
+        }
+
+        if (i < len)
+            p_cb->cmd_pos = 0;
+    }
+}
+
diff --git a/bta/ag/bta_ag_at.h b/bta/ag/bta_ag_at.h
new file mode 100644
index 0000000..90d7b0f
--- /dev/null
+++ b/bta/ag/bta_ag_at.h
@@ -0,0 +1,121 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Interface file for BTA AG AT command interpreter.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_AT_H
+#define BTA_AG_AT_H
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/* AT command argument capabilities */
+#define BTA_AG_AT_NONE          0x01        /* no argument */
+#define BTA_AG_AT_SET           0x02        /* set value */
+#define BTA_AG_AT_READ          0x04        /* read value */
+#define BTA_AG_AT_TEST          0x08        /* test value range */
+#define BTA_AG_AT_FREE          0x10        /* freeform argument */
+
+/* AT command argument format */
+#define BTA_AG_AT_STR           0           /* string */
+#define BTA_AG_AT_INT           1           /* integer */
+
+/*****************************************************************************
+**  Data types
+*****************************************************************************/
+
+/* AT command table element */
+typedef struct
+{
+    const char  *p_cmd;         /* AT command string */
+    UINT8       arg_type;       /* allowable argument type syntax */
+    UINT8       fmt;            /* whether arg is int or string */
+    UINT8       min;            /* minimum value for int arg */
+    INT16       max;            /* maximum value for int arg */
+} tBTA_AG_AT_CMD;
+
+/* callback function executed when command is parsed */
+typedef void (tBTA_AG_AT_CMD_CBACK)(void *p_user, UINT16 cmd, UINT8 arg_type,
+                                    char *p_arg, INT16 int_arg);
+
+/* callback function executed to send "ERROR" result code */
+typedef void (tBTA_AG_AT_ERR_CBACK)(void *p_user, BOOLEAN unknown, char *p_arg);
+
+/* AT command parsing control block */
+typedef struct
+{
+    tBTA_AG_AT_CMD          *p_at_tbl;      /* AT command table */
+    tBTA_AG_AT_CMD_CBACK    *p_cmd_cback;   /* command callback */
+    tBTA_AG_AT_ERR_CBACK    *p_err_cback;   /* error callback */
+    void                    *p_user;        /* user-defined data */
+    char                    *p_cmd_buf;     /* temp parsing buffer */
+    UINT16                  cmd_pos;        /* position in temp buffer */
+    UINT16                  cmd_max_len;    /* length of temp buffer to allocate */
+    UINT8                   state;          /* parsing state */
+} tBTA_AG_AT_CB;
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+
+/*****************************************************************************
+**
+** Function         bta_ag_at_init
+**
+** Description      Initialize the AT command parser control block.
+**
+**
+** Returns          void
+**
+*****************************************************************************/
+extern void bta_ag_at_init(tBTA_AG_AT_CB *p_cb);
+
+/*****************************************************************************
+**
+** Function         bta_ag_at_reinit
+**
+** Description      Re-initialize the AT command parser control block.  This
+**                  function resets the AT command parser state and frees
+**                  any GKI buffer.
+**
+**
+** Returns          void
+**
+*****************************************************************************/
+extern void bta_ag_at_reinit(tBTA_AG_AT_CB *p_cb);
+
+/*****************************************************************************
+**
+** Function         bta_ag_at_parse
+**
+** Description      Parse AT commands.  This function will take the input
+**                  character string and parse it for AT commands according to
+**                  the AT command table passed in the control block.
+**
+**
+** Returns          void
+**
+*****************************************************************************/
+extern void bta_ag_at_parse(tBTA_AG_AT_CB *p_cb, char *p_buf, UINT16 len);
+
+#endif /* BTA_AG_AT_H */
+
diff --git a/bta/ag/bta_ag_cfg.c b/bta/ag/bta_ag_cfg.c
new file mode 100644
index 0000000..e02f9f6
--- /dev/null
+++ b/bta/ag/bta_ag_cfg.c
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ *  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 compile-time configurable constants for the audio
+ *  gateway.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_ag_api.h"
+
+#ifndef BTA_AG_CIND_INFO
+#define BTA_AG_CIND_INFO     "(\"call\",(0,1)),(\"callsetup\",(0-3)),(\"service\",(0-3)),(\"signal\",(0-6)),(\"roam\",(0,1)),(\"battchg\",(0-5)),(\"callheld\",(0-2)),(\"bearer\",(0-7))"
+#endif
+
+#ifndef BTA_AG_CHLD_VAL_ECC
+#define BTA_AG_CHLD_VAL_ECC  "(0,1,1x,2,2x,3,4)"
+#endif
+
+#ifndef BTA_AG_CHLD_VAL
+#define BTA_AG_CHLD_VAL  "(0,1,2,3,4)"
+#endif
+
+#ifndef BTA_AG_CONN_TIMEOUT
+#define BTA_AG_CONN_TIMEOUT     5000
+#endif
+
+#ifndef BTA_AG_SCO_PKT_TYPES
+/* S1 packet type setting from HFP 1.5 spec */
+#define BTA_AG_SCO_PKT_TYPES    /* BTM_SCO_LINK_ALL_PKT_MASK */ (BTM_SCO_LINK_ONLY_MASK          | \
+                                                                 BTM_SCO_PKT_TYPES_MASK_EV3      | \
+                                                                 BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
+                                                                 BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
+                                                                 BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
+#endif
+
+const tBTA_AG_CFG bta_ag_cfg =
+{
+    BTA_AG_CIND_INFO,
+    BTA_AG_CONN_TIMEOUT,
+    BTA_AG_SCO_PKT_TYPES,
+    BTA_AG_CHLD_VAL_ECC,
+    BTA_AG_CHLD_VAL
+};
+
+tBTA_AG_CFG *p_bta_ag_cfg = (tBTA_AG_CFG *) &bta_ag_cfg;
diff --git a/bta/ag/bta_ag_ci.c b/bta/ag/bta_ag_ci.c
new file mode 100644
index 0000000..fd39e34
--- /dev/null
+++ b/bta/ag/bta_ag_ci.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ *  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 is the implementation file for audio gateway call-in functions.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_ci.h"
+#include "gki.h"
+
+/******************************************************************************
+**
+** Function         bta_ag_ci_rx_write
+**
+** Description      This function is called to send data to the AG when the AG
+**                  is configured for AT command pass-through.  The function
+**                  copies data to an event buffer and sends it.
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len)
+{
+    tBTA_AG_CI_RX_WRITE *p_buf;
+    UINT16 len_remaining = len;
+    char *p_data_area;
+
+    if (len > (RFCOMM_DATA_POOL_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1))
+        len = RFCOMM_DATA_POOL_BUF_SIZE - sizeof(tBTA_AG_CI_RX_WRITE) - 1;
+
+    while (len_remaining)
+    {
+        if (len_remaining < len)
+            len = len_remaining;
+
+        if ((p_buf = (tBTA_AG_CI_RX_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_AG_CI_RX_WRITE) + len + 1))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_CI_RX_WRITE_EVT;
+        p_buf->hdr.layer_specific = handle;
+
+        p_data_area = (char *)(p_buf+1);        /* Point to data area after header */
+        strncpy(p_data_area, p_data, len);
+        p_data_area[len] = 0;
+
+        bta_sys_sendmsg(p_buf);
+        } else {
+        APPL_TRACE_ERROR1("ERROR: Unable to allocate buffer to hold AT response code. len=%i", len);
+            break;
+        }
+
+        len_remaining-=len;
+        p_data+=len;
+    }
+}
+
+/******************************************************************************
+**
+** Function         bta_ag_ci_slc_ready
+**
+** Description      This function is called to notify AG that SLC is up at
+**                  the application. This funcion is only used when the app
+**                  is running in pass-through mode.
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ag_ci_slc_ready(UINT16 handle)
+{
+    tBTA_AG_DATA *p_buf;
+
+    if ((p_buf = (tBTA_AG_DATA *)GKI_getbuf(sizeof(tBTA_AG_DATA))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AG_CI_SLC_READY_EVT;
+        p_buf->hdr.layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
diff --git a/bta/ag/bta_ag_cmd.c b/bta/ag/bta_ag_cmd.c
new file mode 100644
index 0000000..d552eed
--- /dev/null
+++ b/bta/ag/bta_ag_cmd.c
@@ -0,0 +1,1836 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 functions for processing AT commands and results.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_at.h"
+#include "port_api.h"
+#include "utl.h"
+#include <stdio.h>
+#include <string.h>
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/* ring timeout */
+#define BTA_AG_RING_TOUT        10000
+
+#define BTA_AG_CMD_MAX_VAL      32767  /* Maximum value is signed 16-bit value */
+
+
+
+/* clip type constants */
+#define BTA_AG_CLIP_TYPE_MIN        128
+#define BTA_AG_CLIP_TYPE_MAX        175
+#define BTA_AG_CLIP_TYPE_DEFAULT    129
+#define BTA_AG_CLIP_TYPE_VOIP       255
+
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+#define BTA_AG_AT_MULTI_LEN            2
+#define AT_SET_RES_CB(res_cb, c, p, i) {res_cb.code = c; res_cb.p_arg = p; res_cb.int_arg = i;}
+
+/* type for AT result code block */
+typedef struct
+{
+    UINT8 code;
+    char *p_arg;
+    INT16 int_arg;
+} tBTA_AG_RESULT_CB;
+
+/* type for multiple AT result codes block */
+typedef struct
+{
+    UINT8 num_result;
+    tBTA_AG_RESULT_CB res_cb[BTA_AG_AT_MULTI_LEN];
+} tBTA_AG_MULTI_RESULT_CB;
+#endif
+
+/* enumeration of HSP AT commands matches HSP command interpreter table */
+enum
+{
+    BTA_AG_HS_CMD_CKPD,
+    BTA_AG_HS_CMD_VGS,
+    BTA_AG_HS_CMD_VGM
+};
+
+/* enumeration of HFP AT commands matches HFP command interpreter table */
+enum
+{
+    BTA_AG_HF_CMD_A,
+    BTA_AG_HF_CMD_D,
+    BTA_AG_HF_CMD_VGS,
+    BTA_AG_HF_CMD_VGM,
+    BTA_AG_HF_CMD_CCWA,
+    BTA_AG_HF_CMD_CHLD,
+    BTA_AG_HF_CMD_CHUP,
+    BTA_AG_HF_CMD_CIND,
+    BTA_AG_HF_CMD_CLIP,
+    BTA_AG_HF_CMD_CMER,
+    BTA_AG_HF_CMD_VTS,
+    BTA_AG_HF_CMD_BINP,
+    BTA_AG_HF_CMD_BLDN,
+    BTA_AG_HF_CMD_BVRA,
+    BTA_AG_HF_CMD_BRSF,
+    BTA_AG_HF_CMD_NREC,
+    BTA_AG_HF_CMD_CNUM,
+    BTA_AG_HF_CMD_BTRH,
+    BTA_AG_HF_CMD_CLCC,
+    BTA_AG_HF_CMD_COPS,
+    BTA_AG_HF_CMD_CMEE,
+    BTA_AG_HF_CMD_BIA,
+    BTA_AG_HF_CMD_CBC,
+    BTA_AG_HF_CMD_BCC,
+    BTA_AG_HF_CMD_BCS,
+    BTA_AG_HF_CMD_BAC
+};
+
+/* AT command interpreter table for HSP */
+const tBTA_AG_AT_CMD bta_ag_hsp_cmd[] =
+{
+    {"+CKPD",   BTA_AG_AT_SET,                      BTA_AG_AT_INT, 200, 200},
+    {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
+};
+
+/* AT command interpreter table for HFP */
+const tBTA_AG_AT_CMD bta_ag_hfp_cmd[] =
+{
+    {"A",       BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"D",       (BTA_AG_AT_NONE | BTA_AG_AT_FREE),  BTA_AG_AT_STR,   0,   0},
+    {"+VGS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+VGM",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,  15},
+    {"+CCWA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    /* Consider CHLD as str to take care of indexes for ECC */
+    {"+CHLD",   (BTA_AG_AT_SET | BTA_AG_AT_TEST),   BTA_AG_AT_STR,   0,   4},
+    {"+CHUP",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+CIND",   (BTA_AG_AT_READ | BTA_AG_AT_TEST),  BTA_AG_AT_STR,   0,   0},
+    {"+CLIP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+CMER",   BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"+VTS",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"+BINP",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   1,   1},
+    {"+BLDN",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BVRA",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+BRSF",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
+    {"+NREC",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   0},
+    {"+CNUM",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BTRH",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_INT,   0,   2},
+    {"+CLCC",   BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+COPS",   (BTA_AG_AT_READ | BTA_AG_AT_SET),   BTA_AG_AT_STR,   0,   0},
+    {"+CMEE",   BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   1},
+    {"+BIA",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   20},
+    {"+CBC",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   100},
+    {"+BCC",    BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0},
+    {"+BCS",    BTA_AG_AT_SET,                      BTA_AG_AT_INT,   0,   BTA_AG_CMD_MAX_VAL},
+    {"+BAC",    BTA_AG_AT_SET,                      BTA_AG_AT_STR,   0,   0},
+    {"",        BTA_AG_AT_NONE,                     BTA_AG_AT_STR,   0,   0}
+};
+
+/* AT result code table element */
+typedef struct
+{
+    const char  *p_res;         /* AT result string */
+    UINT8       fmt;            /* whether argument is int or string */
+} tBTA_AG_RESULT;
+
+/* AT result code argument types */
+enum
+{
+    BTA_AG_RES_FMT_NONE,       /* no argument */
+    BTA_AG_RES_FMT_INT,        /* integer argument */
+    BTA_AG_RES_FMT_STR         /* string argument */
+};
+
+/* enumeration of AT result codes, matches constant table */
+enum
+{
+    BTA_AG_RES_OK,
+    BTA_AG_RES_ERROR,
+    BTA_AG_RES_RING,
+    BTA_AG_RES_VGS,
+    BTA_AG_RES_VGM,
+    BTA_AG_RES_CCWA,
+    BTA_AG_RES_CHLD,
+    BTA_AG_RES_CIND,
+    BTA_AG_RES_CLIP,
+    BTA_AG_RES_CIEV,
+    BTA_AG_RES_BINP,
+    BTA_AG_RES_BVRA,
+    BTA_AG_RES_BRSF,
+    BTA_AG_RES_BSIR,
+    BTA_AG_RES_CNUM,
+    BTA_AG_RES_BTRH,
+    BTA_AG_RES_CLCC,
+    BTA_AG_RES_COPS,
+    BTA_AG_RES_CMEE,
+    BTA_AG_RES_BCS,
+    BTA_AG_RES_UNAT
+};
+
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
+#define COLON_IDX_4_VGSVGM    4
+#endif
+/* AT result code constant table  (Indexed by result code) */
+const tBTA_AG_RESULT bta_ag_result_tbl[] =
+{
+    {"OK",      BTA_AG_RES_FMT_NONE},
+    {"ERROR",   BTA_AG_RES_FMT_NONE},
+    {"RING",    BTA_AG_RES_FMT_NONE},
+    {"+VGS: ",  BTA_AG_RES_FMT_INT},
+    {"+VGM: ",  BTA_AG_RES_FMT_INT},
+    {"+CCWA: ", BTA_AG_RES_FMT_STR},
+    {"+CHLD: ", BTA_AG_RES_FMT_STR},
+    {"+CIND: ", BTA_AG_RES_FMT_STR},
+    {"+CLIP: ", BTA_AG_RES_FMT_STR},
+    {"+CIEV: ", BTA_AG_RES_FMT_STR},
+    {"+BINP: ", BTA_AG_RES_FMT_STR},
+    {"+BVRA: ", BTA_AG_RES_FMT_INT},
+    {"+BRSF: ", BTA_AG_RES_FMT_INT},
+    {"+BSIR: ", BTA_AG_RES_FMT_INT},
+    {"+CNUM: ", BTA_AG_RES_FMT_STR},
+    {"+BTRH: ", BTA_AG_RES_FMT_INT},
+    {"+CLCC: ", BTA_AG_RES_FMT_STR},
+    {"+COPS: ", BTA_AG_RES_FMT_STR},
+    {"+CME ERROR: ", BTA_AG_RES_FMT_INT},
+    {"+BCS: ",  BTA_AG_RES_FMT_INT},
+    {"",        BTA_AG_RES_FMT_STR}
+};
+
+const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX] =
+{
+    bta_ag_hsp_cmd,
+    bta_ag_hfp_cmd
+};
+
+/* callback event lookup table for HSP */
+const tBTA_AG_EVT bta_ag_hsp_cb_evt[] =
+{
+    BTA_AG_AT_CKPD_EVT,     /* BTA_AG_HS_CMD_CKPD */
+    BTA_AG_SPK_EVT,         /* BTA_AG_HS_CMD_VGS */
+    BTA_AG_MIC_EVT          /* BTA_AG_HS_CMD_VGM */
+};
+
+/* callback event lookup table for HFP  (Indexed by command) */
+const tBTA_AG_EVT bta_ag_hfp_cb_evt[] =
+{
+    BTA_AG_AT_A_EVT,        /* BTA_AG_HF_CMD_A */
+    BTA_AG_AT_D_EVT,        /* BTA_AG_HF_CMD_D */
+    BTA_AG_SPK_EVT,         /* BTA_AG_HF_CMD_VGS */
+    BTA_AG_MIC_EVT,         /* BTA_AG_HF_CMD_VGM */
+    0,                      /* BTA_AG_HF_CMD_CCWA */
+    BTA_AG_AT_CHLD_EVT,     /* BTA_AG_HF_CMD_CHLD */
+    BTA_AG_AT_CHUP_EVT,     /* BTA_AG_HF_CMD_CHUP */
+    BTA_AG_AT_CIND_EVT,     /* BTA_AG_HF_CMD_CIND */
+    0,                      /* BTA_AG_HF_CMD_CLIP */
+    0,                      /* BTA_AG_HF_CMD_CMER */
+    BTA_AG_AT_VTS_EVT,      /* BTA_AG_HF_CMD_VTS */
+    BTA_AG_AT_BINP_EVT,     /* BTA_AG_HF_CMD_BINP */
+    BTA_AG_AT_BLDN_EVT,     /* BTA_AG_HF_CMD_BLDN */
+    BTA_AG_AT_BVRA_EVT,     /* BTA_AG_HF_CMD_BVRA */
+    0,                      /* BTA_AG_HF_CMD_BRSF */
+    BTA_AG_AT_NREC_EVT,     /* BTA_AG_HF_CMD_NREC */
+    BTA_AG_AT_CNUM_EVT,     /* BTA_AG_HF_CMD_CNUM */
+    BTA_AG_AT_BTRH_EVT,     /* BTA_AG_HF_CMD_BTRH */
+    BTA_AG_AT_CLCC_EVT,     /* BTA_AG_HF_CMD_CLCC */
+    BTA_AG_AT_COPS_EVT,     /* BTA_AG_HF_CMD_COPS */
+    0,                      /* BTA_AG_HF_CMD_CMEE */
+    0,                      /* BTA_AG_HF_CMD_BIA */
+    BTA_AG_AT_CBC_EVT,      /* BTA_AG_HF_CMD_CBC */
+    0,                      /* BTA_AG_HF_CMD_BCC */
+    BTA_AG_AT_BCS_EVT,      /* BTA_AG_HF_CMD_BCS */
+    BTA_AG_AT_BAC_EVT       /* BTA_AG_HF_CMD_BAC */
+};
+
+/* translation of API result code values to internal values */
+const UINT8 bta_ag_trans_result[] =
+{
+    BTA_AG_RES_VGS,     /* BTA_AG_SPK_RES */
+    BTA_AG_RES_VGM,     /* BTA_AG_MIC_RES */
+    BTA_AG_RES_BSIR,    /* BTA_AG_INBAND_RING_RES */
+    BTA_AG_RES_CIND,    /* BTA_AG_CIND_RES */
+    BTA_AG_RES_BINP,    /* BTA_AG_BINP_RES */
+    BTA_AG_RES_CIEV,    /* BTA_AG_IND_RES */
+    BTA_AG_RES_BVRA,    /* BTA_AG_BVRA_RES */
+    BTA_AG_RES_CNUM,    /* BTA_AG_CNUM_RES */
+    BTA_AG_RES_BTRH,    /* BTA_AG_BTRH_RES */
+    BTA_AG_RES_CLCC,    /* BTA_AG_CLCC_RES */
+    BTA_AG_RES_COPS,    /* BTA_AG_COPS_RES */
+    0,                  /* BTA_AG_IN_CALL_RES */
+    0,                  /* BTA_AG_IN_CALL_CONN_RES */
+    BTA_AG_RES_CCWA,    /* BTA_AG_CALL_WAIT_RES */
+    0,                  /* BTA_AG_OUT_CALL_ORIG_RES */
+    0,                  /* BTA_AG_OUT_CALL_ALERT_RES */
+    0,                  /* BTA_AG_OUT_CALL_CONN_RES */
+    0,                  /* BTA_AG_CALL_CANCEL_RES */
+    0,                  /* BTA_AG_END_CALL_RES */
+    0,                  /* BTA_AG_IN_CALL_HELD_RES */
+    BTA_AG_RES_UNAT     /* BTA_AG_UNAT_RES */
+};
+
+/* callsetup indicator value lookup table */
+const UINT8 bta_ag_callsetup_ind_tbl[] =
+{
+    0,                          /* BTA_AG_SPK_RES */
+    0,                          /* BTA_AG_MIC_RES */
+    0,                          /* BTA_AG_INBAND_RING_RES */
+    0,                          /* BTA_AG_CIND_RES */
+    0,                          /* BTA_AG_BINP_RES */
+    0,                          /* BTA_AG_IND_RES */
+    0,                          /* BTA_AG_BVRA_RES */
+    0,                          /* BTA_AG_CNUM_RES */
+    0,                          /* BTA_AG_BTRH_RES */
+    0,                          /* BTA_AG_CLCC_RES */
+    0,                          /* BTA_AG_COPS_RES */
+    BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_IN_CALL_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_IN_CALL_CONN_RES */
+    BTA_AG_CALLSETUP_INCOMING,  /* BTA_AG_CALL_WAIT_RES */
+    BTA_AG_CALLSETUP_OUTGOING,  /* BTA_AG_OUT_CALL_ORIG_RES */
+    BTA_AG_CALLSETUP_ALERTING,  /* BTA_AG_OUT_CALL_ALERT_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_OUT_CALL_CONN_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_CALL_CANCEL_RES */
+    BTA_AG_CALLSETUP_NONE,      /* BTA_AG_END_CALL_RES */
+    BTA_AG_CALLSETUP_NONE       /* BTA_AG_IN_CALL_HELD_RES */
+};
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_result
+**
+** Description      Send an AT result code.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_result(tBTA_AG_SCB *p_scb, UINT8 code, char *p_arg,
+                               INT16 int_arg)
+{
+    char    buf[BTA_AG_AT_MAX_LEN + 16];
+    char    *p = buf;
+    UINT16  len;
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    memset(buf, NULL, sizeof(buf));
+#endif
+    /* init with \r\n */
+    *p++ = '\r';
+    *p++ = '\n';
+
+    /* copy result code string */
+    BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[code].p_res);
+#if defined(BTA_HSP_RESULT_REPLACE_COLON) && (BTA_HSP_RESULT_REPLACE_COLON == TRUE)
+    if(p_scb->conn_service == BTA_AG_HSP)
+    {
+        /* If HSP then ":"symbol should be changed as "=" for HSP compatibility */
+        switch(code)
+        {
+        case BTA_AG_RES_VGS:
+        case BTA_AG_RES_VGM:
+            if(*(p+COLON_IDX_4_VGSVGM) == ':')
+            {
+                #if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG0("[HSP] ':'symbol is changed as '=' for HSP compatibility");
+                #endif
+                *(p+COLON_IDX_4_VGSVGM) = '=';
+            }
+            break;
+        }
+    }
+#endif
+    p += strlen(bta_ag_result_tbl[code].p_res);
+
+    /* copy argument if any */
+    if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_INT)
+    {
+        p += utl_itoa((UINT16) int_arg, p);
+    }
+    else if (bta_ag_result_tbl[code].fmt == BTA_AG_RES_FMT_STR)
+    {
+        BCM_STRCPY_S(p, sizeof(buf), p_arg);
+        p += strlen(p_arg);
+    }
+
+    /* finish with \r\n */
+    *p++ = '\r';
+    *p++ = '\n';
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("bta_ag_send_result: %s", buf);
+#endif
+
+    /* send to RFCOMM */
+    PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
+}
+
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_ag_send_multi_result
+**
+** Description      Send multiple AT result codes.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_multi_result(tBTA_AG_SCB *p_scb, tBTA_AG_MULTI_RESULT_CB *m_res_cb)
+{
+    char    buf[BTA_AG_AT_MAX_LEN * BTA_AG_AT_MULTI_LEN + 16];
+    char    *p = buf;
+    UINT16  len;
+    UINT8   res_idx = 0;
+
+    if((!m_res_cb) || (m_res_cb->num_result == 0) || (m_res_cb->num_result > BTA_AG_AT_MULTI_LEN))
+    {
+        APPL_TRACE_DEBUG0("m_res_cb is NULL or num_result is out of range.");
+        return;
+    }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    memset(buf, NULL, sizeof(buf));
+#endif
+
+    while(res_idx < m_res_cb->num_result)
+    {
+        /* init with \r\n */
+        *p++ = '\r';
+        *p++ = '\n';
+
+        /* copy result code string */
+        BCM_STRCPY_S(p, sizeof(buf), bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+        p += strlen(bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].p_res);
+
+        /* copy argument if any */
+        if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_INT)
+        {
+            p += utl_itoa((UINT16) m_res_cb->res_cb[res_idx].int_arg, p);
+        }
+        else if (bta_ag_result_tbl[m_res_cb->res_cb[res_idx].code].fmt == BTA_AG_RES_FMT_STR)
+        {
+            BCM_STRCPY_S(p, sizeof(buf), m_res_cb->res_cb[res_idx].p_arg);
+            p += strlen(m_res_cb->res_cb[res_idx].p_arg);
+        }
+
+        /* finish with \r\n */
+        *p++ = '\r';
+        *p++ = '\n';
+
+        res_idx++;
+    }
+
+#if defined(BTA_AG_RESULT_DEBUG) && (BTA_AG_RESULT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("send_result: %s", buf);
+#endif
+
+    /* send to RFCOMM */
+    PORT_WriteData(p_scb->conn_handle, buf, (UINT16) (p - buf), &len);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_ok
+**
+** Description      Send an OK result code.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_ok(tBTA_AG_SCB *p_scb)
+{
+    bta_ag_send_result(p_scb, BTA_AG_RES_OK, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_error
+**
+** Description      Send an ERROR result code.
+**                      errcode - used to send verbose errocode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_error(tBTA_AG_SCB *p_scb, INT16 errcode)
+{
+    /* If HFP and extended audio gateway error codes are enabled */
+    if (p_scb->conn_service == BTA_AG_HFP && p_scb->cmee_enabled)
+        bta_ag_send_result(p_scb, BTA_AG_RES_CMEE, NULL, errcode);
+    else
+        bta_ag_send_result(p_scb, BTA_AG_RES_ERROR, NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_ind
+**
+** Description      Send an indicator CIEV result code.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_send_ind(tBTA_AG_SCB *p_scb, UINT16 id, UINT16 value, BOOLEAN on_demand)
+{
+    char    str[12];
+    char    *p = str;
+
+    /* If the indicator is masked out, just return */
+    /* Mandatory indicators can not be masked out. */
+    if ((p_scb->bia_masked_out & ((UINT32)1 << id)) &&
+        ((id != BTA_AG_IND_CALL) && (id != BTA_AG_IND_CALLSETUP) && (id != BTA_AG_IND_CALLHELD)))
+        return;
+
+    /* Ensure we do not send duplicate indicators if not requested by app */
+    /* If it was requested by app, transmit CIEV even if it is duplicate. */
+    if (id == BTA_AG_IND_CALL)
+    {
+        if ((value == p_scb->call_ind) && (on_demand == FALSE))
+            return;
+
+        p_scb->call_ind = (UINT8)value;
+    }
+
+    if ((id == BTA_AG_IND_CALLSETUP) && (on_demand == FALSE))
+    {
+        if (value == p_scb->callsetup_ind)
+            return;
+
+        p_scb->callsetup_ind = (UINT8)value;
+    }
+
+    if ((id == BTA_AG_IND_SERVICE) && (on_demand == FALSE))
+    {
+        if (value == p_scb->service_ind)
+            return;
+
+        p_scb->service_ind = (UINT8)value;
+    }
+    if ((id == BTA_AG_IND_SIGNAL) && (on_demand == FALSE))
+    {
+        if (value == p_scb->signal_ind)
+            return;
+
+        p_scb->signal_ind = (UINT8)value;
+    }
+    if ((id == BTA_AG_IND_ROAM) && (on_demand == FALSE))
+    {
+        if (value == p_scb->roam_ind)
+            return;
+
+        p_scb->roam_ind = (UINT8)value;
+    }
+    if ((id == BTA_AG_IND_BATTCHG) && (on_demand == FALSE))
+    {
+        if (value == p_scb->battchg_ind)
+            return;
+
+        p_scb->battchg_ind = (UINT8)value;
+    }
+
+    if ((id == BTA_AG_IND_CALLHELD) && (on_demand == FALSE))
+    {
+        /* call swap could result in sending callheld=1 multiple times */
+        if ((value != 1) && (value == p_scb->callheld_ind))
+            return;
+
+        p_scb->callheld_ind = (UINT8)value;
+    }
+
+    if (p_scb->cmer_enabled)
+    {
+        p += utl_itoa(id, p);
+        *p++ = ',';
+        utl_itoa(value, p);
+        bta_ag_send_result(p_scb, BTA_AG_RES_CIEV, str, 0);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_parse_cmer
+**
+** Description      Parse AT+CMER parameter string.
+**
+**
+** Returns          TRUE if parsed ok, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_parse_cmer(char *p_s, BOOLEAN *p_enabled)
+{
+    INT16   n[4] = {-1, -1, -1, -1};
+    int     i;
+    char    *p;
+
+    for (i = 0; i < 4; i++)
+    {
+        /* skip to comma delimiter */
+        for (p = p_s; *p != ',' && *p != 0; p++);
+
+        /* get integer value */
+        *p = 0;
+        n[i] = utl_str2int(p_s);
+        p_s = p + 1;
+        if (p_s == 0)
+        {
+            break;
+        }
+    }
+
+    /* process values */
+    if (n[0] < 0 || n[3] < 0)
+    {
+        return FALSE;
+    }
+
+    if ((n[0] == 3) && ((n[3] == 1) || (n[3] == 0)))
+    {
+        *p_enabled = (BOOLEAN) n[3];
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_parse_chld
+**
+** Description      Parse AT+CHLD parameter string.
+**
+**
+** Returns          Returns idx (1-7), or 0 if ECC not enabled or idx doesn't exist
+**
+*******************************************************************************/
+static UINT8 bta_ag_parse_chld(tBTA_AG_SCB *p_scb, char *p_s)
+{
+    UINT8   retval = 0;
+    INT16   idx = -1;
+
+    if (p_s[1] != 0)
+    {
+        /* p_idxstr++;  point to beginning of call number */
+        idx = utl_str2int(&p_s[1]);
+        if (idx != -1 && idx < 255)
+            retval = (UINT8)idx;
+    }
+
+    return (retval);
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         bta_ag_parse_bac
+**
+** Description      Parse AT+BAC parameter string.
+**
+** Returns          Returns bitmap of supported codecs.
+**
+*******************************************************************************/
+static tBTA_AG_PEER_CODEC bta_ag_parse_bac(tBTA_AG_SCB *p_scb, char *p_s)
+{
+    tBTA_AG_PEER_CODEC  retval = BTA_AG_CODEC_NONE;
+    UINT16  uuid_codec;
+    BOOLEAN cont = FALSE;       /* Continue processing */
+    char *p;
+
+    while(p_s)
+    {
+        /* skip to comma delimiter */
+        for(p = p_s; *p != ',' && *p != 0; p++);
+
+        /* get integre value */
+        if (*p != 0)
+        {
+            *p = 0;
+            cont = TRUE;
+        }
+        else
+            cont = FALSE;
+
+        uuid_codec = utl_str2int(p_s);
+        switch(uuid_codec)
+        {
+            case UUID_CODEC_CVSD:   retval |= BTA_AG_CODEC_CVSD;     break;
+            case UUID_CODEC_MSBC:   retval |= BTA_AG_CODEC_MSBC;     break;
+            default:
+                APPL_TRACE_ERROR1("Unknown Codec UUID(%d) received", uuid_codec);
+                return BTA_AG_CODEC_NONE;
+        }
+
+        if (cont)
+            p_s = p + 1;
+        else
+            break;
+    }
+
+    return (retval);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_process_unat_res
+**
+** Description      Process the unat response data and remove extra carriage return
+**                  and line feed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+
+static void bta_ag_process_unat_res(char *unat_result)
+{
+    UINT8   str_leng;
+    UINT8   i = 0;
+    UINT8   j = 0;
+    UINT8   pairs_of_nl_cr;
+    char    trim_data[BTA_AG_AT_MAX_LEN];
+
+
+
+    str_leng = strlen(unat_result);
+
+    /* If no extra CR and LF, just return */
+    if(str_leng < 4)
+        return;
+
+    /* Remove the carriage return and left feed */
+    while(unat_result[0] =='\r' && unat_result[1] =='\n'
+        && unat_result[str_leng-2] =='\r' && unat_result[str_leng-1] =='\n')
+    {
+        pairs_of_nl_cr = 1;
+        for (i=0;i<(str_leng-4*pairs_of_nl_cr);i++)
+        {
+            trim_data[j++] = unat_result[i+pairs_of_nl_cr*2];
+        }
+        /* Add EOF */
+        trim_data[j] = '\0';
+        str_leng = str_leng - 4;
+        BCM_STRNCPY_S(unat_result, BTA_AG_AT_MAX_LEN+1, trim_data,str_leng+1);
+        i=0;
+        j=0;
+
+        if(str_leng <4)
+            return;
+
+
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_inband_enabled
+**
+** Description      Determine whether in-band ring can be used.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb)
+{
+    /* if feature is enabled and no other scbs connected */
+    if (p_scb->inband_enabled && !bta_ag_other_scb_open(p_scb))
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_call_inds
+**
+** Description      Send call and callsetup indicators.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result)
+{
+    UINT8 call = p_scb->call_ind;
+    UINT8 callsetup;
+
+    /* set new call and callsetup values based on BTA_AgResult */
+    callsetup = bta_ag_callsetup_ind_tbl[result];
+
+    if (result == BTA_AG_END_CALL_RES)
+    {
+        call = BTA_AG_CALL_INACTIVE;
+    }
+    else if (result == BTA_AG_IN_CALL_CONN_RES || result == BTA_AG_OUT_CALL_CONN_RES
+             || result == BTA_AG_IN_CALL_HELD_RES)
+    {
+        call = BTA_AG_CALL_ACTIVE;
+    }
+    else
+    {
+        call = p_scb->call_ind;
+    }
+
+    /* Send indicator function tracks if the values have actually changed */
+    bta_ag_send_ind(p_scb, BTA_AG_IND_CALL, call, FALSE);
+    bta_ag_send_ind(p_scb, BTA_AG_IND_CALLSETUP, callsetup, FALSE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_at_hsp_cback
+**
+** Description      AT command processing callback for HSP.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+                                char *p_arg, INT16 int_arg)
+{
+    tBTA_AG_VAL val;
+
+    APPL_TRACE_DEBUG4("AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+                      int_arg, p_arg);
+
+    /* send OK */
+    bta_ag_send_ok(p_scb);
+
+    val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+    val.hdr.app_id = p_scb->app_id;
+    val.num = (UINT16) int_arg;
+    BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+    val.str[BTA_AG_AT_MAX_LEN] = 0;
+
+    /* call callback with event */
+    (*bta_ag_cb.p_cback)(bta_ag_hsp_cb_evt[cmd], (tBTA_AG *) &val);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_at_hfp_cback
+**
+** Description      AT command processing callback for HFP.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+                                char *p_arg, INT16 int_arg)
+{
+    tBTA_AG_VAL     val;
+    tBTA_AG_EVT   event;
+    tBTA_AG_SCB     *ag_scb;
+    UINT32          i, ind_id;
+    UINT32          bia_masked_out;
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_PEER_CODEC  codec_type, codec_sent;
+#endif
+
+    APPL_TRACE_DEBUG4("HFP AT cmd:%d arg_type:%d arg:%d arg:%s", cmd, arg_type,
+                      int_arg, p_arg);
+
+    val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+    val.hdr.app_id = p_scb->app_id;
+    val.num = int_arg;
+    BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+    val.str[BTA_AG_AT_MAX_LEN] = 0;
+
+    event = bta_ag_hfp_cb_evt[cmd];
+
+    switch (cmd)
+    {
+        case BTA_AG_HF_CMD_A:
+        case BTA_AG_HF_CMD_VGS:
+        case BTA_AG_HF_CMD_VGM:
+        case BTA_AG_HF_CMD_CHUP:
+        case BTA_AG_HF_CMD_CBC:
+            /* send OK */
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_HF_CMD_BLDN:
+            /* Do not send OK, App will send error or OK depending on
+            ** last dial number enabled or not */
+            break;
+
+        case BTA_AG_HF_CMD_D:
+            /* Do not send OK for Dial cmds
+            ** Let application decide whether to send OK or ERROR*/
+
+            /* if mem dial cmd, make sure string contains only digits */
+            if(p_arg[0] == '>')
+            {
+                if(!utl_isintstr(p_arg+1))
+                {
+                    event = 0;
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
+                }
+            }
+            else if (p_arg[0] == 'V')   /* ATDV : Dial VoIP Call */
+            {
+                /* We do not check string. Code will be added later if needed. */
+                if(!((p_scb->peer_features & BTA_AG_PEER_FEAT_VOIP) && (p_scb->features & BTA_AG_FEAT_VOIP)))
+                {
+                    event = 0;
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+                }
+            }
+            /* If dial cmd, make sure string contains only dial digits
+            ** Dial digits are 0-9, A-C, *, #, + */
+            else
+            {
+                if(!utl_isdialstr(p_arg))
+                {
+                    event = 0;
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_DSTR);
+                }
+            }
+            break;
+
+        case BTA_AG_HF_CMD_CCWA:
+            /* store setting */
+            p_scb->ccwa_enabled = (BOOLEAN) int_arg;
+
+            /* send OK */
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_HF_CMD_CHLD:
+            if (arg_type == BTA_AG_AT_TEST)
+            {
+                /* don't call callback */
+                event = 0;
+
+                /* send CHLD string */
+                /* Form string based on supported 1.5 feature */
+                if ((p_scb->peer_version >= HFP_VERSION_1_5) &&
+                    (p_scb->features & BTA_AG_FEAT_ECC) &&
+                    (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC))
+                    bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val_ecc, 0);
+                else
+                    bta_ag_send_result(p_scb, BTA_AG_RES_CHLD, p_bta_ag_cfg->chld_val, 0);
+
+                /* send OK */
+                bta_ag_send_ok(p_scb);
+
+                /* if service level conn. not already open, now it's open */
+                bta_ag_svc_conn_open(p_scb, NULL);
+
+            }
+            else
+            {
+                val.idx = bta_ag_parse_chld(p_scb, val.str);
+
+                if(val.idx && !((p_scb->features & BTA_AG_FEAT_ECC) && (p_scb->peer_features & BTA_AG_PEER_FEAT_ECC)))
+                {
+                    /* we do not support ECC, but HF is sending us a CHLD with call index*/
+                    event = 0;
+                    bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+
+                }
+                else
+                {
+
+                /* If it is swap between calls, set call held indicator to 3(out of valid 0-2)
+                ** Application will set it back to 1
+                ** callheld indicator will be sent across to the peer. */
+                if(val.str[0] == '2')
+                {
+                    for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+                    {
+                        if (ag_scb->in_use)
+                        {
+                            if((ag_scb->call_ind == BTA_AG_CALL_ACTIVE)
+                                && (ag_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
+                                ag_scb->callheld_ind = BTA_AG_CALLHELD_NOACTIVE + 1;
+                        }
+                    }
+                }
+                }
+
+                /* Do not send OK. Let app decide after parsing the val str */
+                /* bta_ag_send_ok(p_scb); */
+            }
+            break;
+
+        case BTA_AG_HF_CMD_CIND:
+            if (arg_type == BTA_AG_AT_TEST)
+            {
+                /* don't call callback */
+                event = 0;
+
+                /* send CIND string, send OK */
+                bta_ag_send_result(p_scb, BTA_AG_RES_CIND, p_bta_ag_cfg->cind_info, 0);
+                bta_ag_send_ok(p_scb);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_CLIP:
+            /* store setting, send OK */
+            p_scb->clip_enabled = (BOOLEAN) int_arg;
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_HF_CMD_CMER:
+            /* if parsed ok store setting, send OK */
+            if (bta_ag_parse_cmer(p_arg, &p_scb->cmer_enabled))
+            {
+                bta_ag_send_ok(p_scb);
+
+                /* if service level conn. not already open and our features and
+                ** peer features do not have 3-way, service level conn. now open
+                */
+                if (!p_scb->svc_conn &&
+                    !((p_scb->features & BTA_AG_FEAT_3WAY) && (p_scb->peer_features & BTA_AG_PEER_FEAT_3WAY)))
+                {
+                    bta_ag_svc_conn_open(p_scb, NULL);
+                }
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_VTS:
+            /* check argument */
+            if (strlen(p_arg) == 1)
+            {
+                bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BINP:
+            /* if feature not set don't call callback, send ERROR */
+            if (!(p_scb->features & BTA_AG_FEAT_VTAG))
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BVRA:
+            /* if feature not supported don't call callback, send ERROR. App will send OK */
+            if (!(p_scb->features & BTA_AG_FEAT_VREC))
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BRSF:
+            /* store peer features */
+            p_scb->peer_features = (UINT16) int_arg;
+
+            /* send BRSF, send OK */
+            bta_ag_send_result(p_scb, BTA_AG_RES_BRSF, NULL,
+                               (INT16) (p_scb->features & BTA_AG_BSRF_FEAT_SPEC));
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_HF_CMD_NREC:
+            /* if feature send OK, else don't call callback, send ERROR */
+            if (p_scb->features & BTA_AG_FEAT_ECNR)
+            {
+                bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BTRH:
+            /* if feature send BTRH, send OK:, else don't call callback, send ERROR */
+            if (p_scb->features & BTA_AG_FEAT_BTRH)
+            {
+                /* If set command; send response and notify app */
+                if (arg_type == BTA_AG_AT_SET)
+                {
+                    for (i = 0, ag_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, ag_scb++)
+                    {
+                        if (ag_scb->in_use)
+                        {
+                            bta_ag_send_result(ag_scb, BTA_AG_RES_BTRH, NULL, int_arg);
+                        }
+                    }
+                    bta_ag_send_ok(p_scb);
+                }
+                else /* Read Command */
+                {
+                    val.num = BTA_AG_BTRH_READ;
+                }
+            }
+            else
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_COPS:
+            if (arg_type == BTA_AG_AT_SET)
+            {
+                /* don't call callback */
+                event = 0;
+
+                /* send OK */
+                bta_ag_send_ok(p_scb);
+            }
+            break;
+
+        case BTA_AG_HF_CMD_CMEE:
+            if (p_scb->features & BTA_AG_FEAT_EXTERR)
+            {
+                /* store setting */
+                p_scb->cmee_enabled = (BOOLEAN) int_arg;
+
+                /* send OK */
+                bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            /* don't call callback */
+            event = 0;
+            break;
+
+        case BTA_AG_HF_CMD_BIA:
+            /* don't call callback */
+            event = 0;
+
+            bia_masked_out = p_scb->bia_masked_out;
+
+            /* Parse the indicator mask */
+            for (i = 0, ind_id = 1; (val.str[i] != 0) && (ind_id <= 20); i++, ind_id++)
+            {
+                if (val.str[i] == ',')
+                    continue;
+
+                if (val.str[i] == '0')
+                    bia_masked_out |= ((UINT32)1 << ind_id);
+                else if (val.str[i] == '1')
+                    bia_masked_out &= ~((UINT32)1 << ind_id);
+                else
+                    break;
+
+                i++;
+                if ( (val.str[i] != 0) && (val.str[i] != ',') )
+                    break;
+            }
+            if (val.str[i] == 0)
+            {
+                p_scb->bia_masked_out = bia_masked_out;
+                bta_ag_send_ok (p_scb);
+            }
+            else
+                bta_ag_send_error (p_scb, BTA_AG_ERR_INVALID_INDEX);
+            break;
+
+        case BTA_AG_HF_CMD_CNUM:
+            break;
+        case BTA_AG_HF_CMD_CLCC:
+            if(!(p_scb->features & BTA_AG_FEAT_ECS))
+            {
+                event = 0;
+                bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+            }
+            break;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+        case BTA_AG_HF_CMD_BAC:
+            bta_ag_send_ok(p_scb);
+
+            /* store available codecs from the peer */
+            if((p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC) && (p_scb->features & BTA_AG_FEAT_CODEC))
+            {
+                p_scb->peer_codecs = bta_ag_parse_bac(p_scb, p_arg);
+                p_scb->codec_updated = TRUE;
+
+                if (p_scb->peer_codecs & BTA_AG_CODEC_MSBC)
+                {
+                    p_scb->sco_codec = UUID_CODEC_MSBC;
+                    APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to MSBC");
+                }
+                else
+                {
+                    p_scb->sco_codec = UUID_CODEC_CVSD;
+                    APPL_TRACE_DEBUG0("Received AT+BAC, updating sco codec to CVSD");
+                }
+
+                /* Received BAC while in codec negotiation. */
+                if ((bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST) && (bta_ag_cb.sco.p_curr_scb == p_scb))
+                {
+                    bta_ag_codec_negotiate (p_scb);
+                }
+            }
+            else
+            {
+                p_scb->peer_codecs = BTA_AG_CODEC_NONE;
+                APPL_TRACE_ERROR0("Unexpected CMD:AT+BAC, Codec Negotiation is not supported");
+            }
+            break;
+
+        case BTA_AG_HF_CMD_BCS:
+            /* stop cn timer */
+            bta_sys_stop_timer(&p_scb->cn_timer);
+
+            switch(int_arg)
+            {
+                case UUID_CODEC_CVSD:   codec_type = BTA_AG_CODEC_CVSD;     break;
+                case UUID_CODEC_MSBC:   codec_type = BTA_AG_CODEC_MSBC;     break;
+                default:
+                    APPL_TRACE_ERROR1("Unknown codec_uuid %d", int_arg);
+                    codec_type = 0xFFFF;
+                    break;
+            }
+
+            if (p_scb->codec_fallback)
+                codec_sent = BTA_AG_CODEC_CVSD;
+            else
+                codec_sent = p_scb->sco_codec;
+
+            if(codec_type == codec_sent)
+                bta_ag_sco_codec_nego(p_scb, TRUE);
+            else
+                bta_ag_sco_codec_nego(p_scb, FALSE);
+
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_HF_CMD_BCC:
+            bta_ag_send_ok(p_scb);
+            bta_ag_sco_open(p_scb, NULL);
+            break;
+#endif
+
+        default:
+            break;
+    }
+
+    /* call callback */
+    if (event != 0)
+    {
+        (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &val);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_at_err_cback
+**
+** Description      AT command parser error callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg)
+{
+    tBTA_AG_VAL     val;
+
+    if(unknown && (!strlen(p_arg)))
+    {
+        APPL_TRACE_DEBUG0("Empty AT cmd string received");
+        bta_ag_send_ok(p_scb);
+        return;
+    }
+
+    /* if unknown AT command and configured to pass these to app */
+    if (unknown && (p_scb->features & BTA_AG_FEAT_UNAT))
+    {
+        val.hdr.handle = bta_ag_scb_to_idx(p_scb);
+        val.hdr.app_id = p_scb->app_id;
+        val.num = 0;
+        BCM_STRNCPY_S(val.str, sizeof(val.str), p_arg, BTA_AG_AT_MAX_LEN);
+        val.str[BTA_AG_AT_MAX_LEN] = 0;
+        (*bta_ag_cb.p_cback)(BTA_AG_AT_UNAT_EVT, (tBTA_AG *) &val);
+    }
+    else
+    {
+        bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_SUPPORTED);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_hsp_result
+**
+** Description      Handle API result for HSP connections.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_hsp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
+{
+    UINT8 code = bta_ag_trans_result[p_result->result];
+
+    APPL_TRACE_DEBUG1("bta_ag_hsp_result : res = %d", p_result->result);
+
+    switch(p_result->result)
+    {
+        case BTA_AG_SPK_RES:
+        case BTA_AG_MIC_RES:
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+            break;
+
+        case BTA_AG_IN_CALL_RES:
+            /* tell sys to stop av if any */
+            bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+            /* if sco already opened or no inband ring send ring now */
+            if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
+                (p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            /* else open sco, send ring after sco opened */
+            else
+            {
+                /* HSPv1.2: AG shall not send RING if using in-band ring tone. */
+                if (p_scb->hsp_version >= HSP_VERSION_1_2)
+                    p_scb->post_sco = BTA_AG_POST_SCO_NONE;
+                else
+                    p_scb->post_sco = BTA_AG_POST_SCO_RING;
+
+                bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            break;
+
+        case BTA_AG_IN_CALL_CONN_RES:
+        case BTA_AG_OUT_CALL_ORIG_RES:
+            /* if incoming call connected stop ring timer */
+            if (p_result->result == BTA_AG_IN_CALL_CONN_RES)
+            {
+                bta_sys_stop_timer(&p_scb->act_timer);
+            }
+
+            if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                /* if audio connected to this scb open sco */
+                if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
+                {
+                    bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+                /* else if no audio at call close sco */
+                else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
+                {
+                    bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+            }
+            break;
+
+        case BTA_AG_END_CALL_RES:
+            /* stop ring timer */
+            bta_sys_stop_timer(&p_scb->act_timer);
+
+            /* close sco */
+            if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            else
+            {
+                /* if av got suspended by this call, let it resume. */
+                bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+            }
+            break;
+
+        case BTA_AG_INBAND_RING_RES:
+            p_scb->inband_enabled = p_result->data.state;
+            APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
+            break;
+
+        case BTA_AG_UNAT_RES:
+            if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+            {
+                if (p_result->data.str[0] != 0)
+                {
+                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+                }
+
+                if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+                    bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, BTA_AG_ERR_INV_CHAR_IN_TSTR);
+            }
+            break;
+
+        default:
+            /* ignore all others */
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_hfp_result
+**
+** Description      Handle API result for HFP connections.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_hfp_result(tBTA_AG_SCB *p_scb, tBTA_AG_API_RESULT *p_result)
+{
+    UINT8 code = bta_ag_trans_result[p_result->result];
+
+    APPL_TRACE_DEBUG1("bta_ag_hfp_result : res = %d", p_result->result);
+
+    switch(p_result->result)
+    {
+        case BTA_AG_SPK_RES:
+        case BTA_AG_MIC_RES:
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+            break;
+
+        case BTA_AG_IN_CALL_RES:
+            /* tell sys to stop av if any */
+            bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+            /* store caller id string.
+             * append type info at the end.
+             * make sure a valid type info is passed.
+             * otherwise add 129 as default type */
+            if ((p_result->data.num < BTA_AG_CLIP_TYPE_MIN) || (p_result->data.num > BTA_AG_CLIP_TYPE_MAX))
+            {
+                if (p_result->data.num != BTA_AG_CLIP_TYPE_VOIP)
+                    p_result->data.num = BTA_AG_CLIP_TYPE_DEFAULT;
+            }
+
+            APPL_TRACE_DEBUG1("CLIP type :%d", p_result->data.num);
+            p_scb->clip[0] = 0;
+            if (p_result->data.str[0] != 0)
+                sprintf(p_scb->clip,"%s,%d", p_result->data.str, p_result->data.num);
+
+            /* send callsetup indicator */
+            if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END)
+            {
+                /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO close. */
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_END_INCALL;
+            }
+            else
+            {
+                bta_ag_send_call_inds(p_scb, p_result->result);
+
+                /* if sco already opened or no inband ring send ring now */
+                if (bta_ag_sco_is_open(p_scb) || !bta_ag_inband_enabled(p_scb) ||
+                    (p_scb->features & BTA_AG_FEAT_NOSCO))
+                {
+                    bta_ag_send_ring(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+                /* else open sco, send ring after sco opened */
+                else
+                {
+                    p_scb->post_sco = BTA_AG_POST_SCO_RING;
+                    bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+            }
+            break;
+
+        case BTA_AG_IN_CALL_CONN_RES:
+            /* stop ring timer */
+            bta_sys_stop_timer(&p_scb->act_timer);
+
+            /* if sco not opened and we need to open it, open sco first
+            ** then send indicators
+            */
+            if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+                !bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
+                bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            /* else if sco open and we need to close it, close sco first
+            ** then send indicators
+            */
+            else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
+                     bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_CONN;
+                bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            /* else send indicators now */
+            else
+            {
+                bta_ag_send_call_inds(p_scb, p_result->result);
+            }
+            break;
+
+        case BTA_AG_IN_CALL_HELD_RES:
+            /* stop ring timer */
+            bta_sys_stop_timer(&p_scb->act_timer);
+
+            bta_ag_send_call_inds(p_scb, p_result->result);
+
+            break;
+
+        case BTA_AG_OUT_CALL_ORIG_RES:
+            /* if sco open and we need to close it, close sco first
+            ** then send indicators; else send indicators now
+            */
+            if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE &&
+                bta_ag_sco_is_open(p_scb) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_ORIG;
+                bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            else
+            {
+                bta_ag_send_call_inds(p_scb, p_result->result);
+                if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+                    !(p_scb->features & BTA_AG_FEAT_NOSCO))
+                {
+                    bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+            }
+            break;
+
+        case BTA_AG_OUT_CALL_ALERT_RES:
+            /* send indicators */
+            bta_ag_send_call_inds(p_scb, p_result->result);
+            if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb) &&
+                !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            break;
+
+        case BTA_AG_OUT_CALL_CONN_RES:
+            /* send indicators */
+            bta_ag_send_call_inds(p_scb, p_result->result);
+
+            /* open or close sco */
+            if (!(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                if (p_result->data.audio_handle == bta_ag_scb_to_idx(p_scb))
+                {
+                    bta_ag_sco_open(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+                else if (p_result->data.audio_handle == BTA_AG_HANDLE_NONE)
+                {
+                    bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+                }
+            }
+            break;
+
+        case BTA_AG_CALL_CANCEL_RES:
+            /* send indicators */
+            bta_ag_send_call_inds(p_scb, p_result->result);
+            break;
+
+        case BTA_AG_END_CALL_RES:
+            /* stop ring timer */
+            bta_sys_stop_timer(&p_scb->act_timer);
+
+            /* if sco open, close sco then send indicator values */
+            if ((bta_ag_sco_is_open(p_scb) || bta_ag_sco_is_opening(p_scb)) && !(p_scb->features & BTA_AG_FEAT_NOSCO))
+            {
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
+                bta_ag_sco_close(p_scb, (tBTA_AG_DATA *) p_result);
+            }
+            else if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END_INCALL)
+            {
+                /* sco closing for outgoing call because of incoming call */
+                /* Send only callsetup end indicator after sco close */
+                p_scb->post_sco = BTA_AG_POST_SCO_CALL_END;
+            }
+            else
+            {
+                bta_ag_send_call_inds(p_scb, p_result->result);
+
+                /* if av got suspended by this call, let it resume. */
+                bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+            }
+            break;
+
+        case BTA_AG_INBAND_RING_RES:
+            p_scb->inband_enabled = p_result->data.state;
+            APPL_TRACE_DEBUG1("inband_enabled set to %d", p_scb->inband_enabled);
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+            break;
+
+        case BTA_AG_CIND_RES:
+            /* store local values */
+            p_scb->call_ind = p_result->data.str[0] - '0';
+            p_scb->callsetup_ind = p_result->data.str[2] - '0';
+            p_scb->service_ind = p_result->data.str[4] - '0';
+            p_scb->signal_ind = p_result->data.str[6] - '0';
+            p_scb->roam_ind = p_result->data.str[8] - '0';
+            p_scb->battchg_ind = p_result->data.str[10] - '0';
+            APPL_TRACE_DEBUG2("cind call:%d callsetup:%d", p_scb->call_ind, p_scb->callsetup_ind);
+
+            bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+            bta_ag_send_ok(p_scb);
+            break;
+
+        case BTA_AG_BINP_RES:
+        case BTA_AG_CNUM_RES:
+        case BTA_AG_CLCC_RES:
+        case BTA_AG_COPS_RES:
+            if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+            {
+                if (p_result->data.str[0] != 0)
+                {
+                   bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+                }
+
+                if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+                    bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, p_result->data.errcode);
+            }
+            break;
+
+
+        case BTA_AG_UNAT_RES:
+            if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+            {
+                if (p_result->data.str[0] != 0)
+                {
+                    bta_ag_process_unat_res(p_result->data.str);
+                    APPL_TRACE_DEBUG1("BTA_AG_RES :%s",p_result->data.str);
+                    bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+                }
+
+                if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+                    bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, p_result->data.errcode);
+            }
+            break;
+
+        case BTA_AG_CALL_WAIT_RES:
+            if (p_scb->ccwa_enabled)
+            {
+                bta_ag_send_result(p_scb, code, p_result->data.str, 0);
+            }
+            bta_ag_send_call_inds(p_scb, p_result->result);
+            break;
+
+        case BTA_AG_IND_RES:
+            bta_ag_send_ind(p_scb, p_result->data.ind.id, p_result->data.ind.value, FALSE);
+            break;
+
+        case BTA_AG_BVRA_RES:
+            bta_ag_send_result(p_scb, code, NULL, p_result->data.state);
+            break;
+
+        case BTA_AG_BTRH_RES:
+            if (p_result->data.ok_flag != BTA_AG_OK_ERROR)
+            {
+                /* Don't respond to read if not in response & hold state */
+                if (p_result->data.num != BTA_AG_BTRH_NO_RESP)
+                {
+                    bta_ag_send_result(p_scb, code, NULL, p_result->data.num);
+                }
+
+                /* In case of a response to a read request we need to send OK */
+                if (p_result->data.ok_flag == BTA_AG_OK_DONE)
+                    bta_ag_send_ok(p_scb);
+            }
+            else
+            {
+                bta_ag_send_error(p_scb, p_result->data.errcode);
+            }
+            break;
+
+       default:
+            break;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_result
+**
+** Description      Handle API result.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    if (p_scb->conn_service == BTA_AG_HSP)
+    {
+        bta_ag_hsp_result(p_scb, &p_data->api_result);
+    }
+    else
+    {
+        bta_ag_hfp_result(p_scb, &p_data->api_result);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_setcodec
+**
+** Description      Handle API SetCodec
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_PEER_CODEC codec_type = p_data->api_setcodec.codec;
+
+    /* Check if the requested codec type is valid */
+    if((codec_type != BTA_AG_CODEC_NONE) &&
+       (codec_type != BTA_AG_CODEC_CVSD) &&
+       (codec_type != BTA_AG_CODEC_MSBC))
+    {
+        APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
+        return;
+    }
+
+    if((p_scb->peer_codecs & codec_type) || (codec_type == BTA_AG_CODEC_NONE) || (codec_type == BTA_AG_CODEC_CVSD))
+    {
+        p_scb->sco_codec = codec_type;
+        p_scb->codec_updated = TRUE;
+        APPL_TRACE_DEBUG1("bta_ag_setcodec: Updated codec type %d", codec_type);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_ag_setcodec error: unsupported codec type %d", codec_type);
+    }
+#endif
+}
+
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         bta_ag_send_bcs
+**
+** Description      Send +BCS AT command to peer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16 codec_uuid;
+
+    if (p_scb->codec_fallback)
+    {
+        codec_uuid = UUID_CODEC_CVSD;
+    }
+    else
+    {
+        switch(p_scb->sco_codec)
+        {
+            case BTA_AG_CODEC_NONE:     codec_uuid = UUID_CODEC_CVSD;   break;
+            case BTA_AG_CODEC_CVSD:     codec_uuid = UUID_CODEC_CVSD;   break;
+            case BTA_AG_CODEC_MSBC:     codec_uuid = UUID_CODEC_MSBC;   break;
+            default:
+                APPL_TRACE_ERROR1("bta_ag_send_bcs: unknown codec %d, use CVSD", p_scb->sco_codec);
+                codec_uuid = UUID_CODEC_CVSD;
+                break;
+        }
+    }
+
+    /* send +BCS */
+    bta_ag_send_result(p_scb, BTA_AG_RES_BCS, NULL, codec_uuid);
+
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_send_ring
+**
+** Description      Send RING result code to peer.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if defined(BTA_AG_MULTI_RESULT_INCLUDED) && (BTA_AG_MULTI_RESULT_INCLUDED == TRUE)
+    tBTA_AG_MULTI_RESULT_CB m_res_cb;
+
+    if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
+    {
+        memset(&m_res_cb, NULL, sizeof(tBTA_AG_MULTI_RESULT_CB));
+
+        m_res_cb.num_result = 2;
+        AT_SET_RES_CB(m_res_cb.res_cb[0], BTA_AG_RES_RING, NULL, 0)
+        AT_SET_RES_CB(m_res_cb.res_cb[1], BTA_AG_RES_CLIP, p_scb->clip, 0)
+
+        bta_ag_send_multi_result(p_scb, &m_res_cb);
+    }
+    else
+    {
+        /* send RING ONLY */
+        bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+    }
+#else
+    /* send RING */
+    bta_ag_send_result(p_scb, BTA_AG_RES_RING, NULL, 0);
+
+    /* if HFP and clip enabled and clip data send CLIP */
+    if (p_scb->conn_service == BTA_AG_HFP && p_scb->clip_enabled && p_scb->clip[0] != 0)
+    {
+        bta_ag_send_result(p_scb, BTA_AG_RES_CLIP, p_scb->clip, 0);
+    }
+#endif
+
+    /* restart ring timer */
+    bta_sys_start_timer(&p_scb->act_timer, BTA_AG_RING_TOUT_EVT, BTA_AG_RING_TOUT);
+}
+
+
diff --git a/bta/ag/bta_ag_int.h b/bta/ag/bta_ag_int.h
new file mode 100644
index 0000000..b0d1b1d
--- /dev/null
+++ b/bta/ag/bta_ag_int.h
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ *  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 is the private interface file for the BTA audio gateway.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_INT_H
+#define BTA_AG_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_at.h"
+
+/* Send RING & CLIP in one AT cmd */
+#ifndef BTA_AG_MULTI_RESULT_INCLUDED
+#define BTA_AG_MULTI_RESULT_INCLUDED      FALSE
+#endif
+
+/* Replace : in VGS and VGM for HSP */
+#ifndef BTA_HSP_RESULT_REPLACE_COLON
+#define BTA_HSP_RESULT_REPLACE_COLON      TRUE
+#endif
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+#define HFP_VERSION_1_1         0x0101
+#define HFP_VERSION_1_5         0x0105
+#define HFP_VERSION_1_6         0x0106
+
+#define HSP_VERSION_1_0         0x0100
+#define HSP_VERSION_1_2         0x0102
+
+/* Number of SCBs (AG service instances that can be registered) */
+#ifndef BTA_AG_NUM_SCB
+#define BTA_AG_NUM_SCB          2
+#endif
+
+/* Timer to wait for retry in case of collision */
+#ifndef BTA_AG_COLLISION_TIMER
+#define BTA_AG_COLLISION_TIMER  2000
+#endif
+
+/* RFCOMM MTU SIZE */
+#define BTA_AG_MTU              256
+
+/* Internal profile indexes */
+#define BTA_AG_HSP              0       /* index for HSP */
+#define BTA_AG_HFP              1       /* index for HFP */
+#define BTA_AG_NUM_IDX          2       /* number of profile indexes */
+
+/* profile role for connection */
+#define BTA_AG_ACP              0       /* accepted connection */
+#define BTA_AG_INT              1       /* initiating connection */
+
+/* feature mask that matches spec */
+#define BTA_AG_BSRF_FEAT_SPEC        (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR    | \
+                                      BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND  | \
+                                      BTA_AG_FEAT_VTAG | BTA_AG_FEAT_REJECT  | \
+                                      BTA_AG_FEAT_ECS  | BTA_AG_FEAT_ECC     | \
+                                      BTA_AG_FEAT_EXTERR | BTA_AG_FEAT_CODEC | \
+                                      BTA_AG_FEAT_VOIP)
+
+#define BTA_AG_SDP_FEAT_SPEC         (BTA_AG_FEAT_3WAY | BTA_AG_FEAT_ECNR    | \
+                                      BTA_AG_FEAT_VREC | BTA_AG_FEAT_INBAND  | \
+                                      BTA_AG_FEAT_VTAG)
+
+enum
+{
+    /* these events are handled by the state machine */
+    BTA_AG_API_REGISTER_EVT = BTA_SYS_EVT_START(BTA_ID_AG),
+    BTA_AG_API_DEREGISTER_EVT,
+    BTA_AG_API_OPEN_EVT,
+    BTA_AG_API_CLOSE_EVT,
+    BTA_AG_API_AUDIO_OPEN_EVT,
+    BTA_AG_API_AUDIO_CLOSE_EVT,
+    BTA_AG_API_RESULT_EVT,
+    BTA_AG_API_SETCODEC_EVT,
+    BTA_AG_RFC_OPEN_EVT,
+    BTA_AG_RFC_CLOSE_EVT,
+    BTA_AG_RFC_SRV_CLOSE_EVT,
+    BTA_AG_RFC_DATA_EVT,
+    BTA_AG_SCO_OPEN_EVT,
+    BTA_AG_SCO_CLOSE_EVT,
+    BTA_AG_DISC_ACP_RES_EVT,
+    BTA_AG_DISC_INT_RES_EVT,
+    BTA_AG_DISC_OK_EVT,
+    BTA_AG_DISC_FAIL_EVT,
+    BTA_AG_CI_RX_WRITE_EVT,
+    BTA_AG_RING_TOUT_EVT,
+    BTA_AG_SVC_TOUT_EVT,
+    BTA_AG_CI_SCO_DATA_EVT,
+    BTA_AG_CI_SLC_READY_EVT,
+    BTA_AG_MAX_EVT,
+
+    /* these events are handled outside of the state machine */
+    BTA_AG_API_ENABLE_EVT,
+    BTA_AG_API_DISABLE_EVT
+};
+
+/* Actions to perform after a SCO event */
+enum
+{
+    BTA_AG_POST_SCO_NONE,       /* no action */
+    BTA_AG_POST_SCO_CLOSE_RFC,  /* close RFCOMM channel after SCO closes */
+    BTA_AG_POST_SCO_RING,       /* send RING result code after SCO opens */
+    BTA_AG_POST_SCO_CALL_CONN,  /* send call indicators after SCO opens/closes */
+    BTA_AG_POST_SCO_CALL_ORIG,  /* send call indicators after SCO closes */
+    BTA_AG_POST_SCO_CALL_END,   /* send call indicators after SCO closes */
+    BTA_AG_POST_SCO_CALL_END_INCALL   /* send call indicators for end call & incoming call after SCO closes */
+};
+
+/* sco states */
+enum
+{
+    BTA_AG_SCO_SHUTDOWN_ST,     /* no sco listening, all sco connections closed */
+    BTA_AG_SCO_LISTEN_ST,       /* sco listening */
+#if (BTM_WBS_INCLUDED == TRUE )
+    BTA_AG_SCO_CODEC_ST,        /* sco codec negotiation */
+#endif
+    BTA_AG_SCO_OPENING_ST,      /* sco connection opening */
+    BTA_AG_SCO_OPEN_CL_ST,      /* opening sco connection being closed */
+    BTA_AG_SCO_OPEN_XFER_ST,    /* opening sco connection being transferred */
+    BTA_AG_SCO_OPEN_ST,         /* sco open */
+    BTA_AG_SCO_CLOSING_ST,      /* sco closing */
+    BTA_AG_SCO_CLOSE_OP_ST,     /* closing sco being opened */
+    BTA_AG_SCO_CLOSE_XFER_ST,   /* closing sco being transferred */
+    BTA_AG_SCO_SHUTTING_ST      /* sco shutting down */
+};
+
+/*****************************************************************************
+**  Data types
+*****************************************************************************/
+
+/* data type for BTA_AG_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_AG_PARSE_MODE  parse_mode;
+    tBTA_AG_CBACK      *p_cback;
+} tBTA_AG_API_ENABLE;
+
+/* data type for BTA_AG_API_REGISTER_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    char                p_name[2][BTA_SERVICE_NAME_LEN+1];
+    tBTA_SERVICE_MASK   services;
+    tBTA_SEC            sec_mask;
+    tBTA_AG_FEAT        features;
+    UINT8               app_id;
+} tBTA_AG_API_REGISTER;
+
+/* data type for BTA_AG_API_OPEN_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    tBTA_SERVICE_MASK   services;
+    tBTA_SEC            sec_mask;
+} tBTA_AG_API_OPEN;
+
+/* data type for BTA_AG_API_RESULT_EVT */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_AG_RES       result;
+    tBTA_AG_RES_DATA  data;
+} tBTA_AG_API_RESULT;
+
+/* data type for BTA_AG_API_SETCODEC_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_AG_PEER_CODEC  codec;
+} tBTA_AG_API_SETCODEC;
+
+/* data type for BTA_AG_DISC_RESULT_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          status;
+} tBTA_AG_DISC_RESULT;
+
+/* data type for RFCOMM events */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          port_handle;
+} tBTA_AG_RFC;
+
+/* data type for BTA_AG_CI_RX_WRITE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+//    char            p_data[BTA_AG_MTU+1];
+} tBTA_AG_CI_RX_WRITE;
+
+/* union of all event datatypes */
+typedef union
+{
+    BT_HDR                  hdr;
+    tBTA_AG_API_ENABLE      api_enable;
+    tBTA_AG_API_REGISTER    api_register;
+    tBTA_AG_API_OPEN        api_open;
+    tBTA_AG_API_RESULT      api_result;
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_API_SETCODEC    api_setcodec;
+#endif
+    tBTA_AG_DISC_RESULT     disc_result;
+    tBTA_AG_RFC             rfc;
+    tBTA_AG_CI_RX_WRITE     ci_rx_write;
+} tBTA_AG_DATA;
+
+/* type for each profile */
+typedef struct
+{
+    UINT32          sdp_handle;
+    UINT8           scn;
+} tBTA_AG_PROFILE;
+
+/* type for each service control block */
+typedef struct
+{
+    char                clip[BTA_AG_AT_MAX_LEN+1]; /* number string used for CLIP */
+    UINT16              serv_handle[BTA_AG_NUM_IDX]; /* RFCOMM server handles */
+    tBTA_AG_AT_CB       at_cb;          /* AT command interpreter */
+    TIMER_LIST_ENT      act_timer;     /* ring timer */
+    BD_ADDR             peer_addr;      /* peer bd address */
+    tSDP_DISCOVERY_DB   *p_disc_db;     /* pointer to discovery database */
+    tBTA_SERVICE_MASK   reg_services;   /* services specified in register API */
+    tBTA_SERVICE_MASK   open_services;  /* services specified in open API */
+    UINT16              conn_handle;    /* RFCOMM handle of connected service */
+    tBTA_SEC            serv_sec_mask;  /* server security mask */
+    tBTA_SEC            cli_sec_mask;   /* client security mask */
+    tBTA_AG_FEAT        features;       /* features registered by application */
+    tBTA_AG_PEER_FEAT   peer_features;  /* peer device features */
+    UINT16              peer_version;   /* profile version of peer device */
+    UINT16              hsp_version;    /* HSP profile version */
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_PEER_CODEC  peer_codecs;    /* codecs for eSCO supported by the peer */
+    tBTA_AG_PEER_CODEC  sco_codec;      /* codec to be used for eSCO connection */
+    tBTA_AG_PEER_CODEC  inuse_codec;    /* codec being used for the current SCO connection */
+    BOOLEAN             codec_updated;  /* set to TRUE whenever the app updates codec type */
+    BOOLEAN             codec_fallback; /* If sco nego fails for mSBC, fallback to CVSD */
+    TIMER_LIST_ENT      cn_timer;       /* codec negotiation timer */
+#endif
+    UINT16              sco_idx;        /* SCO handle */
+    BOOLEAN             in_use;         /* scb in use */
+    BOOLEAN             dealloc;        /* TRUE if service shutting down */
+    BOOLEAN             clip_enabled;   /* set to TRUE if HF enables CLIP reporting */
+    BOOLEAN             ccwa_enabled;   /* set to TRUE if HF enables CCWA reporting */
+    BOOLEAN             cmer_enabled;   /* set to TRUE if HF enables CMER reporting */
+    BOOLEAN             cmee_enabled;   /* set to TRUE if HF enables CME ERROR reporting */
+    BOOLEAN             inband_enabled; /* set to TRUE if inband ring enabled */
+    BOOLEAN             svc_conn;       /* set to TRUE when service level connection up */
+    TIMER_LIST_ENT      colli_timer;    /* Collision timer */
+    BOOLEAN             colli_tmr_on;   /* TRUE if collision timer is active */
+    UINT8               state;          /* state machine state */
+    UINT8               conn_service;   /* connected service */
+    UINT8               peer_scn;       /* peer scn */
+    UINT8               app_id;         /* application id */
+    UINT8               role;           /* initiator/acceptor role */
+    UINT8               post_sco;       /* action to perform after sco event */
+    UINT8               call_ind;       /* CIEV call indicator value */
+    UINT8               callsetup_ind;  /* CIEV callsetup indicator value */
+    UINT8               service_ind;    /* CIEV service indicator value */
+    UINT8               signal_ind;     /* CIEV signal indicator value */
+    UINT8               roam_ind;       /* CIEV roam indicator value */
+    UINT8               battchg_ind;    /* CIEV battery charge indicator value */
+    UINT8               callheld_ind;   /* CIEV call held indicator value */
+    BOOLEAN             retry_with_sco_only; /* indicator to try with SCO only when eSCO fails */
+    UINT32              bia_masked_out; /* indicators HF does not want us to send */
+} tBTA_AG_SCB;
+
+/* type for sco data */
+typedef struct
+{
+    tBTM_ESCO_CONN_REQ_EVT_DATA  conn_data;     /* SCO data for pending conn request */
+    tBTA_AG_SCB                 *p_curr_scb;    /* SCB associated with SCO connection */
+    tBTA_AG_SCB                 *p_xfer_scb;    /* SCB associated with SCO transfer */
+    UINT16                      cur_idx;        /* SCO handle */
+    UINT8                       state;          /* SCO state variable */
+    BOOLEAN                     param_updated;  /* if params were updated to non-default */
+    tBTM_ESCO_PARAMS            params;         /* ESCO parameters */
+} tBTA_AG_SCO_CB;
+
+
+/* type for AG control block */
+typedef struct
+{
+    tBTA_AG_SCB         scb[BTA_AG_NUM_SCB];        /* service control blocks */
+    tBTA_AG_PROFILE     profile[BTA_AG_NUM_IDX];    /* profile-specific data */
+    tBTA_AG_SCO_CB      sco;                        /* SCO data */
+    tBTA_AG_CBACK       *p_cback;                   /* application callback */
+    tBTA_AG_PARSE_MODE  parse_mode;                 /* parse/pass-through mode */
+} tBTA_AG_CB;
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* constant lookup tables */
+extern const UINT16 bta_ag_uuid[BTA_AG_NUM_IDX];
+extern const UINT8 bta_ag_sec_id[BTA_AG_NUM_IDX];
+extern const tBTA_AG_AT_CMD *bta_ag_at_tbl[BTA_AG_NUM_IDX];
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AG_CB bta_ag_cb;
+#else
+extern tBTA_AG_CB *bta_ag_cb_ptr;
+#define bta_ag_cb (*bta_ag_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_AG_CFG *p_bta_ag_cfg;
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+
+/* main functions */
+extern void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb);
+extern UINT16 bta_ag_scb_to_idx(tBTA_AG_SCB *p_scb);
+extern tBTA_AG_SCB *bta_ag_scb_by_idx(UINT16 idx);
+extern UINT8 bta_ag_service_to_idx(tBTA_SERVICE_MASK services);
+extern UINT16 bta_ag_idx_by_bdaddr(BD_ADDR peer_addr);
+extern BOOLEAN bta_ag_other_scb_open(tBTA_AG_SCB *p_curr_scb);
+extern tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb);
+extern void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data);
+extern BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg);
+extern void bta_ag_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
+                                    UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_ag_resume_open (tBTA_AG_SCB *p_scb);
+
+/* SDP functions */
+extern BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
+                                 tBTA_AG_FEAT features, UINT32 sdp_handle);
+extern void bta_ag_create_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_del_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service);
+extern void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service);
+extern void bta_ag_free_db(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* RFCOMM functions */
+extern void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services);
+extern void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services);
+extern BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb);
+extern void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* SCO functions */
+extern BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb);
+extern BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb);
+extern void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data);
+
+/* AT command functions */
+extern void bta_ag_at_hsp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+                                char *p_arg, INT16 int_arg);
+extern void bta_ag_at_hfp_cback(tBTA_AG_SCB *p_scb, UINT16 cmd, UINT8 arg_type,
+                                char *p_arg, INT16 int_arg);
+extern void bta_ag_at_err_cback(tBTA_AG_SCB *p_scb, BOOLEAN unknown, char *p_arg);
+extern BOOLEAN bta_ag_inband_enabled(tBTA_AG_SCB *p_scb);
+extern void bta_ag_send_call_inds(tBTA_AG_SCB *p_scb, tBTA_AG_RES result);
+
+/* Action functions */
+extern void bta_ag_register(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_deregister(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_dereg(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_start_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_int_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_acp_res(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_disc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_open_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_fail(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_acp_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rfc_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#if (BTM_WBS_INCLUDED == TRUE )
+extern void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result);
+extern void bta_ag_codec_negotiate (tBTA_AG_SCB *p_scb);
+#endif
+extern void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_post_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_post_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_svc_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_result(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_setcodec(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#if (BTM_WBS_INCLUDED == TRUE )
+extern void bta_ag_send_bcs(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#endif
+extern void bta_ag_send_ring(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param);
+extern void bta_ag_ci_rx_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+extern void bta_ag_rcvd_slc_ready(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+#endif /* BTA_AG_INT_H */
diff --git a/bta/ag/bta_ag_main.c b/bta/ag/bta_ag_main.c
new file mode 100644
index 0000000..9b28067
--- /dev/null
+++ b/bta/ag/bta_ag_main.c
@@ -0,0 +1,1012 @@
+/******************************************************************************
+ *
+ *  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 is the main implementation file for the BTA audio gateway.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_co.h"
+#include "bta_ag_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+#ifndef BTA_AG_DEBUG
+#define BTA_AG_DEBUG FALSE
+#endif
+
+#if BTA_AG_DEBUG == TRUE
+static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result);
+static char *bta_ag_state_str(UINT8 state);
+#endif
+
+/* state machine states */
+enum
+{
+    BTA_AG_INIT_ST,
+    BTA_AG_OPENING_ST,
+    BTA_AG_OPEN_ST,
+    BTA_AG_CLOSING_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_AG_REGISTER,
+    BTA_AG_DEREGISTER,
+    BTA_AG_START_OPEN,
+    BTA_AG_RFC_DO_OPEN,
+    BTA_AG_RFC_DO_CLOSE,
+    BTA_AG_START_DEREG,
+    BTA_AG_START_CLOSE,
+    BTA_AG_RFC_OPEN,
+    BTA_AG_OPEN_FAIL,
+    BTA_AG_RFC_ACP_OPEN,
+    BTA_AG_RFC_CLOSE,
+    BTA_AG_RFC_FAIL,
+    BTA_AG_RFC_DATA,
+    BTA_AG_DISC_INT_RES,
+    BTA_AG_DISC_FAIL,
+    BTA_AG_DISC_ACP_RES,
+    BTA_AG_FREE_DB,
+    BTA_AG_SCO_CONN_OPEN,
+    BTA_AG_SCO_CONN_CLOSE,
+    BTA_AG_SCO_LISTEN,
+    BTA_AG_SCO_OPEN,
+    BTA_AG_SCO_CLOSE,
+    BTA_AG_SCO_SHUTDOWN,
+    BTA_AG_POST_SCO_OPEN,
+    BTA_AG_POST_SCO_CLOSE,
+    BTA_AG_SVC_CONN_OPEN,
+    BTA_AG_RESULT,
+    BTA_AG_SETCODEC,
+    BTA_AG_SEND_RING,
+    BTA_AG_CI_SCO_DATA,
+    BTA_AG_CI_RX_DATA,
+    BTA_AG_RCVD_SLC_READY,
+    BTA_AG_NUM_ACTIONS
+};
+
+#define BTA_AG_IGNORE       BTA_AG_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_AG_ACTION)(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data);
+
+/* action functions */
+const tBTA_AG_ACTION bta_ag_action[] =
+{
+    bta_ag_register,
+    bta_ag_deregister,
+    bta_ag_start_open,
+    bta_ag_rfc_do_open,
+    bta_ag_rfc_do_close,
+    bta_ag_start_dereg,
+    bta_ag_start_close,
+    bta_ag_rfc_open,
+    bta_ag_open_fail,
+    bta_ag_rfc_acp_open,
+    bta_ag_rfc_close,
+    bta_ag_rfc_fail,
+    bta_ag_rfc_data,
+    bta_ag_disc_int_res,
+    bta_ag_disc_fail,
+    bta_ag_disc_acp_res,
+    bta_ag_free_db,
+    bta_ag_sco_conn_open,
+    bta_ag_sco_conn_close,
+    bta_ag_sco_listen,
+    bta_ag_sco_open,
+    bta_ag_sco_close,
+    bta_ag_sco_shutdown,
+    bta_ag_post_sco_open,
+    bta_ag_post_sco_close,
+    bta_ag_svc_conn_open,
+    bta_ag_result,
+    bta_ag_setcodec,
+    bta_ag_send_ring,
+    bta_ag_ci_sco_data,
+    bta_ag_ci_rx_data,
+    bta_ag_rcvd_slc_ready
+};
+
+/* state table information */
+#define BTA_AG_ACTIONS              2       /* number of actions */
+#define BTA_AG_NEXT_STATE           2       /* position of next state */
+#define BTA_AG_NUM_COLS             3       /* number of columns in state tables */
+
+/* state table for init state */
+const UINT8 bta_ag_st_init[][BTA_AG_NUM_COLS] =
+{
+/* Event                    Action 1                Action 2                Next state */
+/* API_REGISTER_EVT */      {BTA_AG_REGISTER,       BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_DEREGISTER_EVT */    {BTA_AG_DEREGISTER,     BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_OPEN_EVT */          {BTA_AG_START_OPEN,     BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_CLOSE_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_AUDIO_OPEN_EVT */    {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_AUDIO_CLOSE_EVT */   {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_RESULT_EVT */        {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* API_SETCODEC_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_OPEN_EVT */          {BTA_AG_RFC_ACP_OPEN,   BTA_AG_SCO_LISTEN,      BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */     {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_DATA_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* SCO_OPEN_EVT */          {BTA_AG_SCO_CONN_OPEN,  BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* SCO_CLOSE_EVT */         {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* DISC_ACP_RES_EVT */      {BTA_AG_FREE_DB,        BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* DISC_INT_RES_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* DISC_OK_EVT */           {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* DISC_FAIL_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* CI_RX_WRITE_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_INIT_ST}
+};
+
+/* state table for opening state */
+const UINT8 bta_ag_st_opening[][BTA_AG_NUM_COLS] =
+{
+/* Event                    Action 1                Action 2                Next state */
+/* API_REGISTER_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_DEREGISTER_EVT */    {BTA_AG_RFC_DO_CLOSE,   BTA_AG_START_DEREG,     BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */          {BTA_AG_OPEN_FAIL,      BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_CLOSE_EVT */         {BTA_AG_RFC_DO_CLOSE,   BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */    {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_AUDIO_CLOSE_EVT */   {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_RESULT_EVT */        {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* API_SETCODEC_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* RFC_OPEN_EVT */          {BTA_AG_RFC_OPEN,       BTA_AG_SCO_LISTEN,      BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */         {BTA_AG_RFC_FAIL,       BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */     {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* RFC_DATA_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* SCO_OPEN_EVT */          {BTA_AG_SCO_CONN_OPEN,  BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* SCO_CLOSE_EVT */         {BTA_AG_SCO_CONN_CLOSE, BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* DISC_ACP_RES_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* DISC_INT_RES_EVT */      {BTA_AG_DISC_INT_RES,   BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* DISC_OK_EVT */           {BTA_AG_RFC_DO_OPEN,    BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* DISC_FAIL_EVT */         {BTA_AG_DISC_FAIL,      BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* CI_RX_WRITE_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST},
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPENING_ST}
+};
+
+/* state table for open state */
+const UINT8 bta_ag_st_open[][BTA_AG_NUM_COLS] =
+{
+/* Event                    Action 1                Action 2                Next state */
+/* API_REGISTER_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* API_DEREGISTER_EVT */    {BTA_AG_START_CLOSE,    BTA_AG_START_DEREG,     BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */          {BTA_AG_OPEN_FAIL,      BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* API_CLOSE_EVT */         {BTA_AG_START_CLOSE,    BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */    {BTA_AG_SCO_OPEN,       BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* API_AUDIO_CLOSE_EVT */   {BTA_AG_SCO_CLOSE,      BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* API_RESULT_EVT */        {BTA_AG_RESULT,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* API_SETCODEC_EVT */      {BTA_AG_SETCODEC,       BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* RFC_OPEN_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* RFC_CLOSE_EVT */         {BTA_AG_RFC_CLOSE,      BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */     {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* RFC_DATA_EVT */          {BTA_AG_RFC_DATA,       BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* SCO_OPEN_EVT */          {BTA_AG_SCO_CONN_OPEN,  BTA_AG_POST_SCO_OPEN,   BTA_AG_OPEN_ST},
+/* SCO_CLOSE_EVT */         {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE,  BTA_AG_OPEN_ST},
+/* DISC_ACP_RES_EVT */      {BTA_AG_DISC_ACP_RES,   BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* DISC_INT_RES_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* DISC_OK_EVT */           {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* DISC_FAIL_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* CI_RX_WRITE_EVT */       {BTA_AG_CI_RX_DATA,     BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* RING_TOUT_EVT */         {BTA_AG_SEND_RING,      BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* SVC_TOUT_EVT */          {BTA_AG_START_CLOSE,    BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* CI_SCO_DATA_EVT */       {BTA_AG_CI_SCO_DATA,    BTA_AG_IGNORE,          BTA_AG_OPEN_ST},
+/* CI_SLC_READY_EVT */      {BTA_AG_RCVD_SLC_READY, BTA_AG_IGNORE,          BTA_AG_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 bta_ag_st_closing[][BTA_AG_NUM_COLS] =
+{
+/* Event                    Action 1                Action 2                Next state */
+/* API_REGISTER_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_DEREGISTER_EVT */    {BTA_AG_START_DEREG,    BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_OPEN_EVT */          {BTA_AG_OPEN_FAIL,      BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_CLOSE_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_AUDIO_OPEN_EVT */    {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_AUDIO_CLOSE_EVT */   {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_RESULT_EVT */        {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* API_SETCODEC_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* RFC_OPEN_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* RFC_CLOSE_EVT */         {BTA_AG_RFC_CLOSE,      BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* RFC_SRV_CLOSE_EVT */     {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* RFC_DATA_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* SCO_OPEN_EVT */          {BTA_AG_SCO_CONN_OPEN,  BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* SCO_CLOSE_EVT */         {BTA_AG_SCO_CONN_CLOSE, BTA_AG_POST_SCO_CLOSE,  BTA_AG_CLOSING_ST},
+/* DISC_ACP_RES_EVT */      {BTA_AG_FREE_DB,        BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* DISC_INT_RES_EVT */      {BTA_AG_FREE_DB,        BTA_AG_IGNORE,          BTA_AG_INIT_ST},
+/* DISC_OK_EVT */           {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* DISC_FAIL_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* CI_RX_WRITE_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* RING_TOUT_EVT */         {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* SVC_TOUT_EVT */          {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* CI_SCO_DATA_EVT */       {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST},
+/* CI_SLC_READY_EVT */      {BTA_AG_IGNORE,         BTA_AG_IGNORE,          BTA_AG_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AG_ST_TBL)[BTA_AG_NUM_COLS];
+
+/* state table */
+const tBTA_AG_ST_TBL bta_ag_st_tbl[] =
+{
+    bta_ag_st_init,
+    bta_ag_st_opening,
+    bta_ag_st_open,
+    bta_ag_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* AG control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AG_CB  bta_ag_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_timer_cback
+**
+** Description      AG timer callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_timer_cback(void *p)
+{
+    BT_HDR          *p_buf;
+    TIMER_LIST_ENT  *p_tle = (TIMER_LIST_ENT *) p;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = p_tle->event;
+        p_buf->layer_specific = bta_ag_scb_to_idx((tBTA_AG_SCB *) p_tle->param);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_scb_alloc
+**
+** Description      Allocate an AG service control block.
+**
+**
+** Returns          pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+static tBTA_AG_SCB *bta_ag_scb_alloc(void)
+{
+    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
+    int             i;
+
+    for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+    {
+        if (!p_scb->in_use)
+        {
+            /* initialize variables */
+            p_scb->in_use = TRUE;
+            p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+            /* set up timers */
+            p_scb->act_timer.param = (UINT32) p_scb;
+            p_scb->act_timer.p_cback = bta_ag_timer_cback;
+
+            APPL_TRACE_DEBUG1("bta_ag_scb_alloc %d", bta_ag_scb_to_idx(p_scb));
+            break;
+        }
+    }
+
+    if (i == BTA_AG_NUM_SCB)
+    {
+        /* out of scbs */
+        p_scb = NULL;
+        APPL_TRACE_WARNING0("Out of ag scbs");
+    }
+    return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_scb_dealloc
+**
+** Description      Deallocate a service control block.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_scb_dealloc(tBTA_AG_SCB *p_scb)
+{
+    UINT8   idx;
+    BOOLEAN allocated = FALSE;
+
+    APPL_TRACE_DEBUG1("bta_ag_scb_dealloc %d", bta_ag_scb_to_idx(p_scb));
+
+    /* stop timers */
+    bta_sys_stop_timer(&p_scb->act_timer);
+#if (BTM_WBS_INCLUDED == TRUE)
+    bta_sys_stop_timer(&p_scb->cn_timer);
+#endif
+
+    /* initialize control block */
+    memset(p_scb, 0, sizeof(tBTA_AG_SCB));
+    p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+    /* If all scbs are deallocated, callback with disable event */
+    if (!bta_sys_is_register (BTA_ID_AG))
+    {
+        for (idx = 0; idx < BTA_AG_NUM_SCB; idx++)
+        {
+            if (bta_ag_cb.scb[idx].in_use)
+            {
+                allocated = TRUE;
+                break;
+            }
+        }
+
+        if (!allocated)
+        {
+            (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_scb_to_idx
+**
+** Description      Given a pointer to an scb, return its index.
+**
+**
+** Returns          Index of scb.
+**
+*******************************************************************************/
+UINT16 bta_ag_scb_to_idx(tBTA_AG_SCB *p_scb)
+{
+    /* use array arithmetic to determine index */
+    return ((UINT16) (p_scb - bta_ag_cb.scb)) + 1;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_scb_by_idx
+**
+** Description      Given an scb index return pointer to scb.
+**
+**
+** Returns          Pointer to scb or NULL if not allocated.
+**
+*******************************************************************************/
+tBTA_AG_SCB *bta_ag_scb_by_idx(UINT16 idx)
+{
+    tBTA_AG_SCB     *p_scb;
+
+    /* verify index */
+    if (idx > 0 && idx <= BTA_AG_NUM_SCB)
+    {
+        p_scb = &bta_ag_cb.scb[idx - 1];
+        if (!p_scb->in_use)
+        {
+            p_scb = NULL;
+            APPL_TRACE_WARNING1("ag scb idx %d not allocated", idx);
+        }
+    }
+    else
+    {
+        p_scb = NULL;
+        APPL_TRACE_DEBUG1("ag scb idx %d out of range", idx);
+    }
+    return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_service_to_idx
+**
+** Description      Given a BTA service mask convert to profile index.
+**
+**
+** Returns          Profile ndex of scb.
+**
+*******************************************************************************/
+UINT8 bta_ag_service_to_idx(tBTA_SERVICE_MASK services)
+{
+    if (services & BTA_HFP_SERVICE_MASK)
+    {
+        return BTA_AG_HFP;
+    }
+    else
+    {
+        return BTA_AG_HSP;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_idx_by_bdaddr
+**
+** Description      Find SCB associated with peer BD address.
+**
+**
+** Returns          Index of SCB or zero if none found.
+**
+*******************************************************************************/
+UINT16 bta_ag_idx_by_bdaddr(BD_ADDR peer_addr)
+{
+    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
+    UINT16          i;
+
+    if (peer_addr != NULL)
+    {
+        for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+        {
+            if (p_scb->in_use && !bdcmp(peer_addr, p_scb->peer_addr))
+            {
+                return (i + 1);
+            }
+        }
+    }
+
+    /* no scb found */
+    APPL_TRACE_WARNING0("No ag scb for peer addr");
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_other_scb_open
+**
+** Description      Check whether any other scb is in open state.
+**
+**
+** Returns          TRUE if another scb is in open state, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_other_scb_open(tBTA_AG_SCB *p_curr_scb)
+{
+    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
+    int             i;
+
+    for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+    {
+        if (p_scb->in_use && p_scb != p_curr_scb && p_scb->state == BTA_AG_OPEN_ST)
+        {
+            return TRUE;
+        }
+    }
+
+    /* no other scb found */
+    APPL_TRACE_DEBUG0("No other ag scb open");
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_get_other_idle_scb
+**
+** Description      Return other scb if it is in INIT st.
+**
+**
+** Returns          Pointer to other scb if INIT st, NULL otherwise.
+**
+*******************************************************************************/
+tBTA_AG_SCB *bta_ag_get_other_idle_scb (tBTA_AG_SCB *p_curr_scb)
+{
+    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
+    UINT8   xx;
+
+    for (xx = 0; xx < BTA_AG_NUM_SCB; xx++, p_scb++)
+    {
+        if (p_scb->in_use && (p_scb != p_curr_scb) && (p_scb->state == BTA_AG_INIT_ST))
+        {
+            return p_scb;
+        }
+    }
+
+    /* no other scb found */
+    APPL_TRACE_DEBUG0("bta_ag_get_other_idle_scb: No idle AG scb");
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_colli_timer_cback
+**
+** Description      AG connection collision timer callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_colli_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    tBTA_AG_SCB *p_scb;
+
+    APPL_TRACE_DEBUG0 ("bta_ag_colli_timer_cback");
+
+    if (p_tle)
+    {
+        p_scb = (tBTA_AG_SCB *)p_tle->param;
+
+        if (p_scb)
+        {
+            p_scb->colli_tmr_on = FALSE;
+
+            /* If the peer haven't opened AG connection     */
+            /* we will restart opening process.             */
+            bta_ag_resume_open (p_scb);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_collision_cback
+**
+** Description      Get notified about collision.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_collision_cback (tBTA_SYS_CONN_STATUS status, UINT8 id,
+                                    UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT16  handle;
+    tBTA_AG_SCB *p_scb;
+
+    /* Check if we have opening scb for the peer device. */
+    handle = bta_ag_idx_by_bdaddr (peer_addr);
+    p_scb = bta_ag_scb_by_idx (handle);
+
+    if (p_scb && (p_scb->state == BTA_AG_OPENING_ST))
+    {
+        if (id == BTA_ID_SYS)   /* ACL collision */
+        {
+            APPL_TRACE_WARNING0 ("AG found collision (ACL) ...");
+        }
+        else if (id == BTA_ID_AG)   /* RFCOMM collision */
+        {
+            APPL_TRACE_WARNING0 ("AG found collision (RFCOMM) ...");
+        }
+        else
+        {
+            APPL_TRACE_WARNING0 ("AG found collision (\?\?\?) ...");
+        }
+
+        p_scb->state = BTA_AG_INIT_ST;
+
+        /* Cancel SDP if it had been started. */
+        if(p_scb->p_disc_db)
+        {
+            (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
+            bta_ag_free_db(p_scb, NULL);
+        }
+
+        /* reopen registered servers */
+        /* Collision may be detected before or after we close servers. */
+        if (bta_ag_is_server_closed (p_scb))
+            bta_ag_start_servers(p_scb, p_scb->reg_services);
+
+        /* Start timer to han */
+        p_scb->colli_timer.p_cback = (TIMER_CBACK*)&bta_ag_colli_timer_cback;
+        p_scb->colli_timer.param = (INT32)p_scb;
+        bta_sys_start_timer(&p_scb->colli_timer, 0, BTA_AG_COLLISION_TIMER);
+        p_scb->colli_tmr_on = TRUE;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_resume_open
+**
+** Description      Resume opening process.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_resume_open (tBTA_AG_SCB *p_scb)
+{
+    if (p_scb)
+    {
+        APPL_TRACE_DEBUG1 ("bta_ag_resume_open, Handle(%d)", bta_ag_scb_to_idx(p_scb));
+
+        /* resume opening process.  */
+        if (p_scb->state == BTA_AG_INIT_ST)
+        {
+            p_scb->state = BTA_AG_OPENING_ST;
+            bta_ag_start_open (p_scb, NULL);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0 ("bta_ag_resume_open, Null p_scb");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_api_enable
+**
+** Description      Handle an API enable event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_api_enable(tBTA_AG_DATA *p_data)
+{
+    /* initialize control block */
+    memset(&bta_ag_cb, 0, sizeof(tBTA_AG_CB));
+
+    /* store callback function */
+    bta_ag_cb.p_cback = p_data->api_enable.p_cback;
+    bta_ag_cb.parse_mode = p_data->api_enable.parse_mode;
+
+    /* call init call-out */
+    bta_ag_co_init();
+
+    bta_sys_collision_register (BTA_ID_AG, bta_ag_collision_cback);
+
+    /* call callback with enable event */
+    (*bta_ag_cb.p_cback)(BTA_AG_ENABLE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_api_disable
+**
+** Description      Handle an API disable event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_api_disable(tBTA_AG_DATA *p_data)
+{
+    /* deregister all scbs in use */
+    tBTA_AG_SCB     *p_scb = &bta_ag_cb.scb[0];
+    BOOLEAN         do_dereg = FALSE;
+    int             i;
+
+    if (!bta_sys_is_register (BTA_ID_AG))
+    {
+        APPL_TRACE_ERROR0("BTA AG is already disabled, ignoring ...");
+        return;
+    }
+
+    /* De-register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_deregister(BTA_ID_AG);
+    GKI_sched_unlock();
+
+    for (i = 0; i < BTA_AG_NUM_SCB; i++, p_scb++)
+    {
+        if (p_scb->in_use)
+        {
+            bta_ag_sm_execute(p_scb, BTA_AG_API_DEREGISTER_EVT, p_data);
+            do_dereg = TRUE;
+        }
+    }
+
+    if (!do_dereg)
+    {
+        /* Done, send callback evt to app */
+        (*bta_ag_cb.p_cback)(BTA_AG_DISABLE_EVT, NULL);
+    }
+
+    bta_sys_collision_register (BTA_ID_AG, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_api_register
+**
+** Description      Handle an API event registers a new service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_api_register(tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_SCB     *p_scb;
+    tBTA_AG_REGISTER reg;
+
+    /* allocate an scb */
+    if ((p_scb = bta_ag_scb_alloc()) != NULL)
+    {
+        bta_ag_sm_execute(p_scb, p_data->hdr.event, p_data);
+    }
+    else
+    {
+        reg.status = BTA_AG_FAIL_RESOURCES;
+        (*bta_ag_cb.p_cback)(BTA_AG_REGISTER_EVT, (tBTA_AG *) &reg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_api_result
+**
+** Description      Handle an API result event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_api_result(tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_SCB     *p_scb;
+    int             i;
+
+    if (p_data->hdr.layer_specific != BTA_AG_HANDLE_ALL)
+    {
+        if ((p_scb = bta_ag_scb_by_idx(p_data->hdr.layer_specific)) != NULL)
+        {
+            bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+        }
+    }
+    else
+    {
+        for (i = 0, p_scb = &bta_ag_cb.scb[0]; i < BTA_AG_NUM_SCB; i++, p_scb++)
+        {
+            if (p_scb->in_use)
+            {
+                bta_ag_sm_execute(p_scb, BTA_AG_API_RESULT_EVT, p_data);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sm_execute
+**
+** Description      State machine event handling function for AG
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sm_execute(tBTA_AG_SCB *p_scb, UINT16 event, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+#if BTA_AG_DEBUG == TRUE
+    UINT16  in_event = event;
+    UINT8   in_state = p_scb->state;
+
+    /* Ignore displaying of AT results when not connected (Ignored in state machine) */
+    if (in_event != BTA_AG_API_RESULT_EVT || p_scb->state == BTA_AG_OPEN_ST)
+    {
+        APPL_TRACE_EVENT5("AG evt (hdl 0x%04x): State %d (%s), Event 0x%04x (%s)",
+                           bta_ag_scb_to_idx(p_scb),
+                           p_scb->state, bta_ag_state_str(p_scb->state),
+                           event, bta_ag_evt_str(event, p_data->api_result.result));
+    }
+#else
+    APPL_TRACE_EVENT3("AG evt (hdl 0x%04x): State %d, Event 0x%04x",
+                      bta_ag_scb_to_idx(p_scb), p_scb->state, event);
+#endif
+
+    event &= 0x00FF;
+    if (event >= (BTA_AG_MAX_EVT & 0x00FF))
+    {
+        APPL_TRACE_ERROR0("AG evt out of range, ignoring...");
+        return;
+    }
+
+    /* look up the state table for the current state */
+    state_table = bta_ag_st_tbl[p_scb->state];
+
+    /* set next state */
+    p_scb->state = state_table[event][BTA_AG_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_AG_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_AG_IGNORE)
+        {
+            (*bta_ag_action[action])(p_scb, p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+#if BTA_AG_DEBUG == TRUE
+    if (p_scb->state != in_state)
+    {
+        APPL_TRACE_EVENT3("BTA AG State Change: [%s] -> [%s] after Event [%s]",
+                      bta_ag_state_str(in_state),
+                      bta_ag_state_str(p_scb->state),
+                      bta_ag_evt_str(in_event, p_data->api_result.result));
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_hdl_event
+**
+** Description      Data gateway main event handling function.
+**
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_ag_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_AG_SCB *p_scb;
+
+    switch (p_msg->event)
+    {
+        /* handle enable event */
+        case BTA_AG_API_ENABLE_EVT:
+            bta_ag_api_enable((tBTA_AG_DATA *) p_msg);
+            break;
+
+        /* handle disable event */
+        case BTA_AG_API_DISABLE_EVT:
+            bta_ag_api_disable((tBTA_AG_DATA *) p_msg);
+            break;
+
+        /* handle register event */
+        case BTA_AG_API_REGISTER_EVT:
+            bta_ag_api_register((tBTA_AG_DATA *) p_msg);
+            break;
+
+        /* handle result event */
+        case BTA_AG_API_RESULT_EVT:
+            bta_ag_api_result((tBTA_AG_DATA *) p_msg);
+            break;
+
+        /* all others reference scb by handle */
+        default:
+            if ((p_scb = bta_ag_scb_by_idx(p_msg->layer_specific)) != NULL)
+            {
+                bta_ag_sm_execute(p_scb, p_msg->event, (tBTA_AG_DATA *) p_msg);
+            }
+            break;
+    }
+    return TRUE;
+}
+
+#if BTA_AG_DEBUG == TRUE
+static char *bta_ag_evt_str(UINT16 event, tBTA_AG_RES result)
+{
+    switch (event)
+    {
+    case BTA_AG_API_REGISTER_EVT:
+        return "Register Request";
+    case BTA_AG_API_DEREGISTER_EVT:
+        return "Deregister Request";
+    case BTA_AG_API_OPEN_EVT:
+        return "Open SLC Request";
+    case BTA_AG_API_CLOSE_EVT:
+        return "Close SLC Request";
+    case BTA_AG_API_AUDIO_OPEN_EVT:
+        return "Open Audio Request";
+    case BTA_AG_API_AUDIO_CLOSE_EVT:
+        return "Close Audio Request";
+    case BTA_AG_API_RESULT_EVT:
+        switch (result)
+        {
+        case BTA_AG_SPK_RES:            return ("AT Result  BTA_AG_SPK_RES");
+        case BTA_AG_MIC_RES:            return ("AT Result  BTA_AG_MIC_RES");
+        case BTA_AG_INBAND_RING_RES:    return ("AT Result  BTA_AG_INBAND_RING_RES");
+        case BTA_AG_CIND_RES:           return ("AT Result  BTA_AG_CIND_RES");
+        case BTA_AG_BINP_RES:           return ("AT Result  BTA_AG_BINP_RES");
+        case BTA_AG_IND_RES:            return ("AT Result  BTA_AG_IND_RES");
+        case BTA_AG_BVRA_RES:           return ("AT Result  BTA_AG_BVRA_RES");
+        case BTA_AG_CNUM_RES:           return ("AT Result  BTA_AG_CNUM_RES");
+        case BTA_AG_BTRH_RES:           return ("AT Result  BTA_AG_BTRH_RES");
+        case BTA_AG_CLCC_RES:           return ("AT Result  BTA_AG_CLCC_RES");
+        case BTA_AG_COPS_RES:           return ("AT Result  BTA_AG_COPS_RES");
+        case BTA_AG_IN_CALL_RES:        return ("AT Result  BTA_AG_IN_CALL_RES");
+        case BTA_AG_IN_CALL_CONN_RES:   return ("AT Result  BTA_AG_IN_CALL_CONN_RES");
+        case BTA_AG_CALL_WAIT_RES:      return ("AT Result  BTA_AG_CALL_WAIT_RES");
+        case BTA_AG_OUT_CALL_ORIG_RES:  return ("AT Result  BTA_AG_OUT_CALL_ORIG_RES");
+        case BTA_AG_OUT_CALL_ALERT_RES: return ("AT Result  BTA_AG_OUT_CALL_ALERT_RES");
+        case BTA_AG_OUT_CALL_CONN_RES:  return ("AT Result  BTA_AG_OUT_CALL_CONN_RES");
+        case BTA_AG_CALL_CANCEL_RES:    return ("AT Result  BTA_AG_CALL_CANCEL_RES");
+        case BTA_AG_END_CALL_RES:       return ("AT Result  BTA_AG_END_CALL_RES");
+        case BTA_AG_UNAT_RES:           return ("AT Result  BTA_AG_UNAT_RES");
+        default:                        return ("Unknown AG Result");
+        }
+    case BTA_AG_API_SETCODEC_EVT:
+        return "Set Codec Request";
+    case BTA_AG_RFC_OPEN_EVT:
+        return "RFC Opened";
+    case BTA_AG_RFC_CLOSE_EVT:
+        return "RFC Closed";
+    case BTA_AG_RFC_SRV_CLOSE_EVT:
+        return "RFC SRV Closed";
+    case BTA_AG_RFC_DATA_EVT:
+        return "RFC Data";
+    case BTA_AG_SCO_OPEN_EVT:
+        return "Audio Opened";
+    case BTA_AG_SCO_CLOSE_EVT:
+        return "Audio Closed";
+    case BTA_AG_DISC_ACP_RES_EVT:
+        return "Discovery ACP Result";
+    case BTA_AG_DISC_INT_RES_EVT:
+        return "Discovery INT Result";
+    case BTA_AG_DISC_OK_EVT:
+        return "Discovery OK";
+    case BTA_AG_DISC_FAIL_EVT:
+        return "Discovery Failed";
+    case BTA_AG_CI_RX_WRITE_EVT:
+        return "CI RX Write";
+    case BTA_AG_RING_TOUT_EVT:
+        return "Ring Timeout";
+    case BTA_AG_SVC_TOUT_EVT:
+        return "Service Timeout";
+    case BTA_AG_API_ENABLE_EVT:
+        return "Enable AG";
+    case BTA_AG_API_DISABLE_EVT:
+        return "Disable AG";
+    case BTA_AG_CI_SCO_DATA_EVT:
+        return "SCO data Callin";
+    case BTA_AG_CI_SLC_READY_EVT:
+        return "SLC Ready Callin";
+    default:
+        return "Unknown AG Event";
+    }
+}
+
+static char *bta_ag_state_str(UINT8 state)
+{
+    switch (state)
+    {
+    case BTA_AG_INIT_ST:
+        return "Initial";
+    case BTA_AG_OPENING_ST:
+        return "Opening";
+    case BTA_AG_OPEN_ST:
+        return "Open";
+    case BTA_AG_CLOSING_ST:
+        return "Closing";
+    default:
+        return "Unknown AG State";
+    }
+}
+
+#endif
diff --git a/bta/ag/bta_ag_rfc.c b/bta/ag/bta_ag_rfc.c
new file mode 100644
index 0000000..3575020
--- /dev/null
+++ b/bta/ag/bta_ag_rfc.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 the audio gateway functions controlling the RFCOMM
+ *  connections.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "bta_ag_co.h"
+#include "btm_api.h"
+#include "port_api.h"
+#include "rfcdefs.h"
+#include "gki.h"
+#include "bd.h"
+
+/* Event mask for RfCOMM port callback */
+#define BTA_AG_PORT_EV_MASK         PORT_EV_RXCHAR
+
+/* each scb has its own rfcomm callbacks */
+void bta_ag_port_cback_1(UINT32 code, UINT16 port_handle);
+void bta_ag_port_cback_2(UINT32 code, UINT16 port_handle);
+void bta_ag_port_cback_3(UINT32 code, UINT16 port_handle);
+
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 port_handle);
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 port_handle);
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 port_handle);
+
+int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len);
+int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len);
+int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len);
+
+/* rfcomm callback function tables */
+typedef tPORT_CALLBACK *tBTA_AG_PORT_CBACK;
+const tBTA_AG_PORT_CBACK bta_ag_port_cback_tbl[] =
+{
+    bta_ag_port_cback_1,
+    bta_ag_port_cback_2,
+    bta_ag_port_cback_3
+};
+
+const tBTA_AG_PORT_CBACK bta_ag_mgmt_cback_tbl[] =
+{
+    bta_ag_mgmt_cback_1,
+    bta_ag_mgmt_cback_2,
+    bta_ag_mgmt_cback_3
+};
+
+typedef tPORT_DATA_CALLBACK *tBTA_AG_DATA_CBACK;
+const tBTA_AG_DATA_CBACK bta_ag_data_cback_tbl[] =
+{
+    bta_ag_data_cback_1,
+    bta_ag_data_cback_2,
+    bta_ag_data_cback_3
+};
+
+/*******************************************************************************
+**
+** Function         bta_ag_port_cback
+**
+** Description      RFCOMM Port callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_port_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
+{
+    BT_HDR      *p_buf;
+    tBTA_AG_SCB *p_scb;
+
+    if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
+    {
+        /* ignore port events for port handles other than connected handle */
+        if (port_handle != p_scb->conn_handle)
+        {
+            APPL_TRACE_DEBUG3("ag_port_cback ignoring handle:%d conn_handle = %d other handle = %d",
+                              port_handle, p_scb->conn_handle, handle);
+            return;
+        }
+
+        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+        {
+            p_buf->event = BTA_AG_RFC_DATA_EVT;
+            p_buf->layer_specific = handle;
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_mgmt_cback
+**
+** Description      RFCOMM management callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_mgmt_cback(UINT32 code, UINT16 port_handle, UINT16 handle)
+{
+    tBTA_AG_RFC     *p_buf;
+    tBTA_AG_SCB     *p_scb;
+    UINT16          event;
+    UINT8           i;
+    BOOLEAN         found_handle = FALSE;
+
+    APPL_TRACE_DEBUG3("ag_mgmt_cback : code = %d, port_handle = %d, handle = %d",
+                        code, port_handle, handle);
+
+    if ((p_scb = bta_ag_scb_by_idx(handle)) != NULL)
+    {
+        /* ignore close event for port handles other than connected handle */
+        if ((code != PORT_SUCCESS) && (port_handle != p_scb->conn_handle))
+        {
+            APPL_TRACE_DEBUG1("ag_mgmt_cback ignoring handle:%d", port_handle);
+            return;
+        }
+
+        if (code == PORT_SUCCESS)
+        {
+            if (p_scb->conn_handle)     /* Outgoing connection */
+            {
+                if (port_handle == p_scb->conn_handle)
+                    found_handle = TRUE;
+            }
+            else                        /* Incoming connection */
+            {
+                for (i = 0; i < BTA_AG_NUM_IDX; i++)
+                {
+                    if (port_handle == p_scb->serv_handle[i])
+                        found_handle = TRUE;
+                }
+            }
+
+            if (!found_handle)
+            {
+                APPL_TRACE_ERROR1 ("bta_ag_mgmt_cback: PORT_SUCCESS, ignoring handle = %d", port_handle);
+                return;
+            }
+
+            event = BTA_AG_RFC_OPEN_EVT;
+        }
+        /* distinguish server close events */
+        else if (port_handle == p_scb->conn_handle)
+        {
+            event = BTA_AG_RFC_CLOSE_EVT;
+        }
+        else
+        {
+            event = BTA_AG_RFC_SRV_CLOSE_EVT;
+        }
+
+        if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
+        {
+            p_buf->hdr.event = event;
+            p_buf->hdr.layer_specific = handle;
+            p_buf->port_handle = port_handle;
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_data_cback
+**
+** Description      RFCOMM data callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static int bta_ag_data_cback(UINT16 port_handle, void *p_data, UINT16 len, UINT16 handle)
+{
+    /* call data call-out directly */
+    bta_ag_co_tx_write(handle, (UINT8 *) p_data, len);
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_port_cback_1 to 3
+**                  bta_ag_mgmt_cback_1 to 3
+**
+** Description      RFCOMM callback functions.  This is an easy way to
+**                  distinguish scb from the callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_mgmt_cback_1(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 1);}
+void bta_ag_mgmt_cback_2(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 2);}
+void bta_ag_mgmt_cback_3(UINT32 code, UINT16 handle) {bta_ag_mgmt_cback(code, handle, 3);}
+void bta_ag_port_cback_1(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 1);}
+void bta_ag_port_cback_2(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 2);}
+void bta_ag_port_cback_3(UINT32 code, UINT16 handle) {bta_ag_port_cback(code, handle, 3);}
+
+/*******************************************************************************
+**
+** Function         bta_ag_data_cback_1 to 3
+**
+** Description      RFCOMM data callback functions.  This is an easy way to
+**                  distinguish scb from the callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+int bta_ag_data_cback_1(UINT16 port_handle, void *p_data, UINT16 len)
+{
+    return bta_ag_data_cback(port_handle, p_data, len, 1);
+}
+int bta_ag_data_cback_2(UINT16 port_handle, void *p_data, UINT16 len)
+{
+    return bta_ag_data_cback(port_handle, p_data, len, 2);
+}
+int bta_ag_data_cback_3(UINT16 port_handle, void *p_data, UINT16 len)
+{
+    return bta_ag_data_cback(port_handle, p_data, len, 3);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_setup_port
+**
+** Description      Setup RFCOMM port for use by AG.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_setup_port(tBTA_AG_SCB *p_scb, UINT16 handle)
+{
+    UINT16 i = bta_ag_scb_to_idx(p_scb) - 1;
+
+    /* set up data callback if using pass through mode */
+    if (bta_ag_cb.parse_mode == BTA_AG_PASS_THROUGH)
+    {
+        PORT_SetDataCallback(handle, bta_ag_data_cback_tbl[i]);
+    }
+
+    PORT_SetEventMask(handle, BTA_AG_PORT_EV_MASK);
+    PORT_SetEventCallback(handle, bta_ag_port_cback_tbl[i]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_start_servers
+**
+** Description      Setup RFCOMM servers for use by AG.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_start_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
+{
+    int i;
+    int bta_ag_port_status;
+
+    services >>= BTA_HSP_SERVICE_ID;
+    for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+    {
+        /* if service is set in mask */
+        if (services & 1)
+        {
+            BTM_SetSecurityLevel(FALSE, "", bta_ag_sec_id[i], p_scb->serv_sec_mask,
+                BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, bta_ag_cb.profile[i].scn);
+
+            bta_ag_port_status =  RFCOMM_CreateConnection(bta_ag_uuid[i], bta_ag_cb.profile[i].scn,
+                TRUE, BTA_AG_MTU, (UINT8 *) bd_addr_any, &(p_scb->serv_handle[i]),
+                bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+
+            if( bta_ag_port_status  == PORT_SUCCESS )
+            {
+                bta_ag_setup_port(p_scb, p_scb->serv_handle[i]);
+            }
+            else
+            {
+                /* TODO: CR#137125 to handle to error properly */
+                APPL_TRACE_DEBUG1("bta_ag_start_servers: RFCOMM_CreateConnection returned error:%d", bta_ag_port_status);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_close_servers
+**
+** Description      Close RFCOMM servers port for use by AG.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_close_servers(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK services)
+{
+    int i;
+
+    services >>= BTA_HSP_SERVICE_ID;
+    for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+    {
+        /* if service is set in mask */
+        if (services & 1)
+        {
+            RFCOMM_RemoveServer(p_scb->serv_handle[i]);
+            p_scb->serv_handle[i] = 0;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_is_server_closed
+**
+** Description      Returns TRUE if all servers are closed.
+**
+**
+** Returns          TRUE if all servers are closed, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN bta_ag_is_server_closed (tBTA_AG_SCB *p_scb)
+{
+    UINT8 xx;
+    BOOLEAN is_closed = TRUE;
+
+    for (xx = 0; xx < BTA_AG_NUM_IDX; xx++)
+    {
+        if (p_scb->serv_handle[xx] != 0)
+            is_closed = FALSE;
+    }
+
+    return is_closed;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_do_open
+**
+** Description      Open an RFCOMM connection to the peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_do_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    BTM_SetSecurityLevel(TRUE, "", bta_ag_sec_id[p_scb->conn_service],
+        p_scb->cli_sec_mask, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, p_scb->peer_scn);
+
+    if (RFCOMM_CreateConnection(bta_ag_uuid[p_scb->conn_service], p_scb->peer_scn,
+            FALSE, BTA_AG_MTU, p_scb->peer_addr, &(p_scb->conn_handle),
+            bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]) == PORT_SUCCESS)
+    {
+        bta_ag_setup_port(p_scb, p_scb->conn_handle);
+        APPL_TRACE_DEBUG1("bta_ag_rfc_do_open : conn_handle = %d", p_scb->conn_handle);
+    }
+    /* RFCOMM create connection failed; send ourselves RFCOMM close event */
+    else
+    {
+        bta_ag_sm_execute(p_scb, BTA_AG_RFC_CLOSE_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_rfc_do_close
+**
+** Description      Close RFCOMM connection.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_rfc_do_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_RFC     *p_buf;
+
+    if (p_scb->conn_handle)
+    {
+        RFCOMM_RemoveConnection(p_scb->conn_handle);
+    }
+    else
+    {
+        /* Close API was called while AG is in Opening state.               */
+        /* Need to trigger the state machine to send callback to the app    */
+        /* and move back to INIT state.                                     */
+        if ((p_buf = (tBTA_AG_RFC *) GKI_getbuf(sizeof(tBTA_AG_RFC))) != NULL)
+        {
+            p_buf->hdr.event = BTA_AG_RFC_CLOSE_EVT;
+            p_buf->hdr.layer_specific = bta_ag_scb_to_idx(p_scb);
+            bta_sys_sendmsg(p_buf);
+        }
+
+        /* Cancel SDP if it had been started. */
+        /*
+        if(p_scb->p_disc_db)
+        {
+            (void)SDP_CancelServiceSearch (p_scb->p_disc_db);
+        }
+        */
+    }
+
+#ifdef _WIN32_WCE
+    {
+        /* Windows versions of RFCOMM does NOT generate a closed callback when we close */
+        tPORT_CALLBACK *rfc_mgmt_cback = bta_ag_mgmt_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1];
+
+        if (rfc_mgmt_cback)
+        {
+            (rfc_mgmt_cback)(PORT_CLOSED, p_scb->conn_handle);
+        }
+    }
+#endif
+}
+
diff --git a/bta/ag/bta_ag_sco.c b/bta/ag/bta_ag_sco.c
new file mode 100644
index 0000000..0c811b4
--- /dev/null
+++ b/bta/ag/bta_ag_sco.c
@@ -0,0 +1,1662 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 functions for managing the SCO connection used in AG.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_ag_api.h"
+#include "bta_ag_co.h"
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#include "bta_dm_co.h"
+#endif
+#include "bta_ag_int.h"
+#include "btm_api.h"
+#include "gki.h"
+
+#ifndef BTA_AG_SCO_DEBUG
+#define BTA_AG_SCO_DEBUG FALSE
+#endif
+
+#ifndef BTA_AG_CODEC_NEGO_TIMEOUT
+#define BTA_AG_CODEC_NEGO_TIMEOUT   3000
+#endif
+
+#if BTA_AG_SCO_DEBUG == TRUE
+static char *bta_ag_sco_evt_str(UINT8 event);
+static char *bta_ag_sco_state_str(UINT8 state);
+#endif
+
+#define BTA_AG_NO_EDR_ESCO  (BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 | \
+                             BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 | \
+                             BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 | \
+                             BTM_SCO_PKT_TYPES_MASK_NO_3_EV5)
+
+/* sco events */
+enum
+{
+    BTA_AG_SCO_LISTEN_E,        /* listen request */
+    BTA_AG_SCO_OPEN_E,          /* open request */
+    BTA_AG_SCO_XFER_E,          /* transfer request */
+#if (BTM_WBS_INCLUDED == TRUE )
+    BTA_AG_SCO_CN_DONE_E,       /* codec negotiation done */
+    BTA_AG_SCO_REOPEN_E,        /* Retry with other codec when failed */
+#endif
+    BTA_AG_SCO_CLOSE_E,         /* close request */
+    BTA_AG_SCO_SHUTDOWN_E,      /* shutdown request */
+    BTA_AG_SCO_CONN_OPEN_E,     /* sco open */
+    BTA_AG_SCO_CONN_CLOSE_E,    /* sco closed */
+    BTA_AG_SCO_CI_DATA_E        /* SCO data ready */
+};
+
+#if (BTM_WBS_INCLUDED == TRUE )
+#define BTA_AG_NUM_CODECS   2
+static const tBTM_ESCO_PARAMS bta_ag_esco_params[BTA_AG_NUM_CODECS] =
+{
+    /* CVSD */
+    {
+        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
+        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
+        0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+        BTM_VOICE_SETTING_CVSD,             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
+       (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+        BTM_SCO_PKT_TYPES_MASK_HV2      +
+        BTM_SCO_PKT_TYPES_MASK_HV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV3      +
+        BTM_SCO_PKT_TYPES_MASK_EV4      +
+        BTM_SCO_PKT_TYPES_MASK_EV5      +
+        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+        BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
+    },
+    /* mSBC */
+    {
+        BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec), 8000        */
+        BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec), 8000        */
+        13,                                 /* 13 ms                                    */
+        BTM_VOICE_SETTING_TRANS,            /* Inp Linear, Transparent, 2s Comp, 16bit  */
+       (BTM_SCO_PKT_TYPES_MASK_EV3      |   /* Packet Types : EV3 + 2-EV3               */
+        BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
+        BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+        BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+        BTM_ESCO_RETRANS_QUALITY       /* Retransmission effort                      */
+    }
+};
+#else
+static const tBTM_ESCO_PARAMS bta_ag_esco_params =
+{
+    BTM_64KBITS_RATE,                   /* TX Bandwidth (64 kbits/sec)              */
+    BTM_64KBITS_RATE,                   /* RX Bandwidth (64 kbits/sec)              */
+    0x000a,                             /* 10 ms (HS/HF can use EV3, 2-EV3, 3-EV3)  */
+    0x0060,                             /* Inp Linear, Air CVSD, 2s Comp, 16bit     */
+    (BTM_SCO_PKT_TYPES_MASK_HV1      +  /* Packet Types                             */
+     BTM_SCO_PKT_TYPES_MASK_HV2      +
+     BTM_SCO_PKT_TYPES_MASK_HV3      +
+     BTM_SCO_PKT_TYPES_MASK_EV3      +
+     BTM_SCO_PKT_TYPES_MASK_EV4      +
+     BTM_SCO_PKT_TYPES_MASK_EV5      +
+     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 +
+     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5),
+     BTM_ESCO_RETRANS_POWER       /* Retransmission effort                      */
+};
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_conn_cback
+**
+** Description      BTM SCO connection callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_sco_conn_cback(UINT16 sco_idx)
+{
+    UINT16  handle;
+    BT_HDR  *p_buf;
+    tBTA_AG_SCB *p_scb;
+
+    /* match callback to scb; first check current sco scb */
+    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
+    {
+        handle = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
+    }
+    /* then check for scb connected to this peer */
+    else
+    {
+        /* Check if SLC is up */
+        handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_idx));
+        p_scb = bta_ag_scb_by_idx(handle);
+        if(p_scb && !p_scb->svc_conn)
+            handle = 0;
+    }
+
+    if (handle != 0)
+    {
+        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+        {
+            p_buf->event = BTA_AG_SCO_OPEN_EVT;
+            p_buf->layer_specific = handle;
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+    /* no match found; disconnect sco, init sco variables */
+    else
+    {
+        bta_ag_cb.sco.p_curr_scb = NULL;
+        bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
+        BTM_RemoveSco(sco_idx);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_disc_cback
+**
+** Description      BTM SCO disconnection callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_sco_disc_cback(UINT16 sco_idx)
+{
+    BT_HDR  *p_buf;
+    UINT16  handle = 0;
+
+    APPL_TRACE_DEBUG3 ("bta_ag_sco_disc_cback(): sco_idx: 0x%x  p_cur_scb: 0x%08x  sco.state: %d", sco_idx, bta_ag_cb.sco.p_curr_scb, bta_ag_cb.sco.state);
+
+    APPL_TRACE_DEBUG4 ("bta_ag_sco_disc_cback(): scb[0] addr: 0x%08x  in_use: %u  sco_idx: 0x%x  sco state: %u",
+                       &bta_ag_cb.scb[0], bta_ag_cb.scb[0].in_use, bta_ag_cb.scb[0].sco_idx, bta_ag_cb.scb[0].state);
+    APPL_TRACE_DEBUG4 ("bta_ag_sco_disc_cback(): scb[1] addr: 0x%08x  in_use: %u  sco_idx: 0x%x  sco state: %u",
+                       &bta_ag_cb.scb[1], bta_ag_cb.scb[1].in_use, bta_ag_cb.scb[1].sco_idx, bta_ag_cb.scb[1].state);
+
+    /* match callback to scb */
+    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb->in_use)
+    {
+        /* We only care about callbacks for the active SCO */
+        if (bta_ag_cb.sco.p_curr_scb->sco_idx != sco_idx)
+        {
+            if (bta_ag_cb.sco.p_curr_scb->sco_idx != 0xFFFF)
+                return;
+        }
+        handle  = bta_ag_scb_to_idx(bta_ag_cb.sco.p_curr_scb);
+    }
+
+    if (handle != 0)
+    {
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+        tBTM_STATUS status = BTM_ConfigScoPath(BTM_SCO_ROUTE_PCM, NULL, NULL, TRUE);
+        APPL_TRACE_DEBUG1("bta_ag_sco_disc_cback sco close config status = %d", status);
+	    /* SCO clean up here */
+        bta_dm_sco_co_close();
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+        /* Restore settings */
+        if(bta_ag_cb.sco.p_curr_scb->inuse_codec == BTA_AG_CODEC_MSBC)
+        {
+            BTM_SetWBSCodec (BTM_SCO_CODEC_NONE);
+            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+
+            /* If SCO open was initiated by AG and failed for mSBC, try CVSD again. */
+            if (bta_ag_sco_is_opening (bta_ag_cb.sco.p_curr_scb))
+            {
+                bta_ag_cb.sco.p_curr_scb->codec_fallback = TRUE;
+                APPL_TRACE_DEBUG0("Fallback to CVSD");
+            }
+        }
+
+        bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
+#endif
+
+        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+        {
+            p_buf->event = BTA_AG_SCO_CLOSE_EVT;
+            p_buf->layer_specific = handle;
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+    /* no match found */
+    else
+    {
+        APPL_TRACE_DEBUG0("no scb for ag_sco_disc_cback");
+
+        /* sco could be closed after scb dealloc'ed */
+        if (bta_ag_cb.sco.p_curr_scb != NULL)
+        {
+            bta_ag_cb.sco.p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+            bta_ag_cb.sco.p_curr_scb = NULL;
+            bta_ag_cb.sco.state = BTA_AG_SCO_SHUTDOWN_ST;
+        }
+    }
+}
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         bta_ag_sco_read_cback
+**
+** Description      Callback function is the callback function for incoming
+**                  SCO data over HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_sco_read_cback (UINT16 sco_inx, BT_HDR *p_data, tBTM_SCO_DATA_FLAG status)
+{
+    if (status != BTM_SCO_DATA_CORRECT)
+    {
+        APPL_TRACE_DEBUG1("bta_ag_sco_read_cback: status(%d)", status);
+    }
+
+    /* Callout function must free the data. */
+    bta_dm_sco_co_in_data (p_data, status);
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_ag_remove_sco
+**
+** Description      Removes the specified SCO from the system.
+**                  If only_active is TRUE, then SCO is only removed if connected
+**
+** Returns          BOOLEAN   - TRUE if Sco removal was started
+**
+*******************************************************************************/
+static BOOLEAN bta_ag_remove_sco(tBTA_AG_SCB *p_scb, BOOLEAN only_active)
+{
+    BOOLEAN     removed_started = FALSE;
+    tBTM_STATUS	status;
+
+    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+    {
+        if (!only_active || p_scb->sco_idx == bta_ag_cb.sco.cur_idx)
+        {
+            status = BTM_RemoveSco(p_scb->sco_idx);
+
+            APPL_TRACE_DEBUG2("ag remove sco: inx 0x%04x, status:0x%x", p_scb->sco_idx, status);
+
+            if (status == BTM_CMD_STARTED)
+            {
+                /* Sco is connected; set current control block */
+                bta_ag_cb.sco.p_curr_scb = p_scb;
+
+                removed_started = TRUE;
+            }
+            /* If no connection reset the sco handle */
+            else if ( (status == BTM_SUCCESS) || (status == BTM_UNKNOWN_ADDR) )
+            {
+                p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+            }
+        }
+    }
+    return removed_started;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_esco_connreq_cback
+**
+** Description      BTM eSCO connection requests and eSCO change requests
+**                  Only the connection requests are processed by BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_esco_connreq_cback(tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
+{
+    tBTA_AG_SCB         *p_scb;
+    UINT16               handle;
+    UINT16               sco_inx = p_data->conn_evt.sco_inx;
+
+    /* Only process connection requests */
+    if (event == BTM_ESCO_CONN_REQ_EVT)
+    {
+        if ((handle = bta_ag_idx_by_bdaddr(BTM_ReadScoBdAddr(sco_inx))) != 0 &&
+            ((p_scb = bta_ag_scb_by_idx(handle)) != NULL) && p_scb->svc_conn)
+        {
+            p_scb->sco_idx = sco_inx;
+
+            /* If no other SCO active, allow this one */
+            if (!bta_ag_cb.sco.p_curr_scb)
+            {
+                APPL_TRACE_EVENT1("bta_ag_esco_connreq_cback: Accept Conn Request (sco_inx 0x%04x)", sco_inx);
+                bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
+
+                bta_ag_cb.sco.state = BTA_AG_SCO_OPENING_ST;
+                bta_ag_cb.sco.p_curr_scb = p_scb;
+                bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+            }
+            else    /* Begin a transfer: Close current SCO before responding */
+            {
+                APPL_TRACE_DEBUG0("bta_ag_esco_connreq_cback: Begin XFER");
+                bta_ag_cb.sco.p_xfer_scb = p_scb;
+                bta_ag_cb.sco.conn_data = p_data->conn_evt;
+                bta_ag_cb.sco.state = BTA_AG_SCO_OPEN_XFER_ST;
+
+                if (!bta_ag_remove_sco(bta_ag_cb.sco.p_curr_scb, TRUE))
+                {
+                    APPL_TRACE_ERROR1("bta_ag_esco_connreq_cback: Nothing to remove so accept Conn Request (sco_inx 0x%04x)", sco_inx);
+                    bta_ag_cb.sco.p_xfer_scb = NULL;
+                    bta_ag_cb.sco.state = BTA_AG_SCO_LISTEN_ST;
+
+                    bta_ag_sco_conn_rsp(p_scb, &p_data->conn_evt);
+                }
+            }
+        }
+        /* If error occurred send reject response immediately */
+        else
+        {
+            APPL_TRACE_WARNING0("no scb for bta_ag_esco_connreq_cback or no resources");
+            BTM_EScoConnRsp(p_data->conn_evt.sco_inx, HCI_ERR_HOST_REJECT_RESOURCES, NULL);
+        }
+    }
+    /* Received a change in the esco link */
+    else if (event == BTM_ESCO_CHG_EVT)
+    {
+        APPL_TRACE_EVENT5("eSCO change event (inx %d): rtrans %d, rxlen %d, txlen %d, txint %d",
+            p_data->chg_evt.sco_inx,
+            p_data->chg_evt.retrans_window, p_data->chg_evt.rx_pkt_len,
+            p_data->chg_evt.tx_pkt_len, p_data->chg_evt.tx_interval);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_cback_sco
+**
+** Description      Call application callback function with SCO event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_cback_sco(tBTA_AG_SCB *p_scb, UINT8 event)
+{
+    tBTA_AG_HDR    sco;
+
+    sco.handle = bta_ag_scb_to_idx(p_scb);
+    sco.app_id = p_scb->app_id;
+
+    /* call close cback */
+    (*bta_ag_cb.p_cback)(event, (tBTA_AG *) &sco);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_create_sco
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_create_sco(tBTA_AG_SCB *p_scb, BOOLEAN is_orig)
+{
+    tBTM_STATUS       status;
+    UINT8            *p_bd_addr = NULL;
+    tBTM_ESCO_PARAMS params;
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_PEER_CODEC  esco_codec = BTM_SCO_CODEC_CVSD;
+    int codec_index = 0;
+#endif
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    tBTM_SCO_ROUTE_TYPE sco_route;
+    tBTA_CODEC_INFO     codec_info = {BTA_SCO_CODEC_PCM};
+    UINT32              pcm_sample_rate;
+#endif
+
+    /* Make sure this sco handle is not already in use */
+    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+    {
+        APPL_TRACE_WARNING1("bta_ag_create_sco: Index 0x%04x Already In Use!",
+                             p_scb->sco_idx);
+        return;
+    }
+
+#if (BTM_WBS_INCLUDED == TRUE )
+    if ((p_scb->sco_codec == BTM_SCO_CODEC_MSBC) &&
+        !p_scb->codec_fallback &&
+        !p_scb->retry_with_sco_only)
+        esco_codec = BTM_SCO_CODEC_MSBC;
+
+    if (p_scb->codec_fallback)
+    {
+        p_scb->codec_fallback = FALSE;
+
+        /* Force AG to send +BCS for the next audio connection. */
+        p_scb->codec_updated = TRUE;
+    }
+
+    if (esco_codec == BTM_SCO_CODEC_MSBC)
+        codec_index = esco_codec - 1;
+
+    params = bta_ag_esco_params[codec_index];
+#else
+    params = bta_ag_esco_params;
+#endif
+
+    if(bta_ag_cb.sco.param_updated) /* If we do not use the default parameters */
+        params = bta_ag_cb.sco.params;
+
+    if(!bta_ag_cb.sco.param_updated)
+    {
+#if (BTM_WBS_INCLUDED == TRUE)
+        if (!codec_index)   /* For non-WBS */
+#endif
+        {
+            /* Use the application packet types (5 slot EV packets not allowed) */
+            params.packet_types = p_bta_ag_cfg->sco_pkt_types     |
+                                  BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+                                  BTM_SCO_PKT_TYPES_MASK_NO_3_EV5;
+        }
+    }
+
+    /* if initiating set current scb and peer bd addr */
+    if (is_orig)
+    {
+        /* Attempt to use eSCO if remote host supports HFP >= 1.5 */
+        /* Need to find out from SIG if HSP can use eSCO; for now use SCO */
+        if (p_scb->conn_service == BTA_AG_HFP && p_scb->peer_version >= HFP_VERSION_1_5 && !p_scb->retry_with_sco_only)
+        {
+
+            BTM_SetEScoMode(BTM_LINK_TYPE_ESCO, &params);
+            /* If ESCO or EDR ESCO, retry with SCO only in case of failure */
+            if((params.packet_types & BTM_ESCO_LINK_ONLY_MASK)
+               ||!((params.packet_types & ~(BTM_ESCO_LINK_ONLY_MASK | BTM_SCO_LINK_ONLY_MASK)) ^ BTA_AG_NO_EDR_ESCO))
+            {
+#if (BTM_WBS_INCLUDED == TRUE )
+                if (esco_codec != BTA_AG_CODEC_MSBC)
+                {
+                    p_scb->retry_with_sco_only = TRUE;
+                    APPL_TRACE_API0("Setting retry_with_sco_only to TRUE");
+                }
+                else    /* Do not use SCO when using mSBC */
+                {
+                    p_scb->retry_with_sco_only = FALSE;
+                    APPL_TRACE_API0("Setting retry_with_sco_only to FALSE");
+                }
+#else
+                p_scb->retry_with_sco_only = TRUE;
+                APPL_TRACE_API0("Setting retry_with_sco_only to TRUE");
+#endif
+            }
+        }
+        else
+        {
+            if(p_scb->retry_with_sco_only)
+                APPL_TRACE_API0("retrying with SCO only");
+            p_scb->retry_with_sco_only = FALSE;
+
+            BTM_SetEScoMode(BTM_LINK_TYPE_SCO, &params);
+        }
+
+        bta_ag_cb.sco.p_curr_scb = p_scb;
+
+        /* tell sys to stop av if any */
+        bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+        /* Allow any platform specific pre-SCO set up to take place */
+        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+#if (BTM_WBS_INCLUDED == TRUE)
+        if (esco_codec == BTA_AG_CODEC_MSBC)
+            pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_16K;
+        else
+#endif
+            pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
+
+        sco_route = bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id);
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+        if (esco_codec == BTA_AG_CODEC_MSBC)
+        {
+            /* Enable mSBC codec in fw */
+            BTM_SetWBSCodec (esco_codec);
+        }
+
+        /* Specify PCM input for SBC codec in fw */
+        BTM_ConfigI2SPCM (esco_codec, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT);
+
+        /* This setting may not be necessary */
+        /* To be verified with stable 2049 boards */
+        if (esco_codec == BTA_AG_CODEC_MSBC)
+            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_TRANS);
+        else
+            BTM_WriteVoiceSettings (BTM_VOICE_SETTING_CVSD);
+
+        /* save the current codec because sco_codec can be updated while SCO is open. */
+        p_scb->inuse_codec = esco_codec;
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+        /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
+        BTM_ConfigScoPath(sco_route, bta_ag_sco_read_cback, NULL, TRUE);
+#endif
+        bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+    }
+    else
+        p_scb->retry_with_sco_only = FALSE;
+
+    p_bd_addr = p_scb->peer_addr;
+
+    status = BTM_CreateSco(p_bd_addr, is_orig, params.packet_types,
+                           &p_scb->sco_idx, bta_ag_sco_conn_cback,
+                           bta_ag_sco_disc_cback);
+    if (status == BTM_CMD_STARTED)
+    {
+        if (!is_orig)
+        {
+            BTM_RegForEScoEvts(p_scb->sco_idx, bta_ag_esco_connreq_cback);
+        }
+        else    /* Initiating the connection, set the current sco handle */
+        {
+            bta_ag_cb.sco.cur_idx = p_scb->sco_idx;
+        }
+    }
+
+    APPL_TRACE_API4("ag create sco: orig %d, inx 0x%04x, status 0x%x, pkt types 0x%04x",
+                      is_orig, p_scb->sco_idx, status, params.packet_types);
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         bta_ag_cn_timer_cback
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_cn_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    tBTA_AG_SCB *p_scb;
+
+    if (p_tle)
+    {
+        p_scb = (tBTA_AG_SCB *)p_tle->param;
+
+        if (p_scb)
+        {
+            /* Announce that codec negotiation failed. */
+            bta_ag_sco_codec_nego(p_scb, FALSE);
+
+            /* call app callback */
+            bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_codec_negotiate
+**
+** Description      Initiate codec negotiation by sending AT command.
+**                  If not necessary, skip negotiation.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_codec_negotiate(tBTA_AG_SCB *p_scb)
+{
+    bta_ag_cb.sco.p_curr_scb = p_scb;
+
+    if (p_scb->codec_updated || p_scb->codec_fallback)
+    {
+        /* Change the power mode to Active until sco open is completed. */
+        bta_sys_busy(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+        /* Send +BCS to the peer */
+        bta_ag_send_bcs(p_scb, NULL);
+
+        /* Start timer to handle timeout */
+        p_scb->cn_timer.p_cback = (TIMER_CBACK*)&bta_ag_cn_timer_cback;
+        p_scb->cn_timer.param = (INT32)p_scb;
+        bta_sys_start_timer(&p_scb->cn_timer, 0, BTA_AG_CODEC_NEGO_TIMEOUT);
+    }
+    else
+    {
+        /* use same codec type as previous SCO connection, skip codec negotiation */
+        bta_ag_sco_codec_nego(p_scb, TRUE);
+    }
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_event
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_sco_event(tBTA_AG_SCB *p_scb, UINT8 event)
+{
+    tBTA_AG_SCO_CB *p_sco = &bta_ag_cb.sco;
+#if (BTM_WBS_INCLUDED == TRUE )
+    tBTA_AG_SCB *p_cn_scb = NULL;   /* For codec negotiation */
+#endif
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    BT_HDR  *p_buf;
+#endif
+#if BTA_AG_SCO_DEBUG == TRUE
+    UINT8   in_state = p_sco->state;
+
+    APPL_TRACE_EVENT5("BTA ag sco evt (hdl 0x%04x): State %d (%s), Event %d (%s)",
+                        p_scb->sco_idx,
+                        p_sco->state, bta_ag_sco_state_str(p_sco->state),
+                        event, bta_ag_sco_evt_str(event));
+#else
+    APPL_TRACE_EVENT3("BTA ag sco evt (hdl 0x%04x): State %d, Event %d",
+                      p_scb->sco_idx, p_sco->state, event);
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    if (event == BTA_AG_SCO_CI_DATA_E)
+    {
+        while (TRUE)
+        {
+            bta_dm_sco_co_out_data(&p_buf);
+            if (p_buf)
+            {
+                if (p_sco->state == BTA_AG_SCO_OPEN_ST)
+                    BTM_WriteScoData(p_sco->p_curr_scb->sco_idx, p_buf);
+                else
+                    GKI_freebuf(p_buf);
+            }
+            else
+                break;
+        }
+
+        return;
+    }
+#endif
+
+    switch (p_sco->state)
+    {
+        case BTA_AG_SCO_SHUTDOWN_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTDOWN_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_LISTEN_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection (Additional channel) */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    break;
+
+                case BTA_AG_SCO_OPEN_E:
+                    /* remove listening connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+                    /* start codec negotiation */
+                    p_sco->state = BTA_AG_SCO_CODEC_ST;
+                    p_cn_scb = p_scb;
+#else
+                    /* create sco connection to peer */
+                    bta_ag_create_sco(p_scb, TRUE);
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* remove listening connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
+
+                    if (p_scb == p_sco->p_curr_scb)
+                        p_sco->p_curr_scb = NULL;
+
+                    /* If last SCO instance then finish shutting down */
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
+                    break;
+
+                case BTA_AG_SCO_CLOSE_E:
+                    /* remove listening connection */
+                    /* Ignore the event. We need to keep listening SCO for the active SLC */
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* sco failed; create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_LISTEN_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+        case BTA_AG_SCO_CODEC_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection (Additional channel) */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    break;
+
+                case BTA_AG_SCO_CN_DONE_E:
+                    /* create sco connection to peer */
+                    bta_ag_create_sco(p_scb, TRUE);
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    break;
+
+                case BTA_AG_SCO_XFER_E:
+                    /* save xfer scb */
+                    p_sco->p_xfer_scb = p_scb;
+                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* remove listening connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
+
+                    if (p_scb == p_sco->p_curr_scb)
+                        p_sco->p_curr_scb = NULL;
+
+                    /* If last SCO instance then finish shutting down */
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
+                    break;
+
+                case BTA_AG_SCO_CLOSE_E:
+                    /* sco open is not started yet. just go back to listening */
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* sco failed; create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_CODEC_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+#endif
+
+        case BTA_AG_SCO_OPENING_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* second headset has now joined */
+                    /* create sco listen connection (Additional channel) */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        bta_ag_create_sco(p_scb, FALSE);
+                    }
+                    break;
+
+#if (BTM_WBS_INCLUDED == TRUE)
+                case BTA_AG_SCO_REOPEN_E:
+                    /* start codec negotiation */
+                    p_sco->state = BTA_AG_SCO_CODEC_ST;
+                    p_cn_scb = p_scb;
+                    break;
+#endif
+
+                case BTA_AG_SCO_XFER_E:
+                    /* save xfer scb */
+                    p_sco->p_xfer_scb = p_scb;
+                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+                    break;
+
+                case BTA_AG_SCO_CLOSE_E:
+                    p_sco->state = BTA_AG_SCO_OPEN_CL_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* If not opening scb, just close it */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        /* remove listening connection */
+                        bta_ag_remove_sco(p_scb, FALSE);
+                    }
+                    else
+                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+                    break;
+
+                case BTA_AG_SCO_CONN_OPEN_E:
+                    p_sco->state = BTA_AG_SCO_OPEN_ST;
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* sco failed; create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_OPENING_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_OPEN_CL_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_XFER_E:
+                    /* save xfer scb */
+                    p_sco->p_xfer_scb = p_scb;
+
+                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+                    break;
+
+                case BTA_AG_SCO_OPEN_E:
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* If not opening scb, just close it */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        /* remove listening connection */
+                        bta_ag_remove_sco(p_scb, FALSE);
+                    }
+                    else
+                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+                    break;
+
+                case BTA_AG_SCO_CONN_OPEN_E:
+                    /* close sco connection */
+                    bta_ag_remove_sco(p_scb, TRUE);
+
+                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* sco failed; create sco listen connection */
+
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_CL_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_OPEN_XFER_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_CLOSE_E:
+                    /* close sco connection */
+                    bta_ag_remove_sco(p_scb, TRUE);
+
+                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* remove all connection */
+                    bta_ag_remove_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* closed sco; place in listen mode and
+                       accept the transferred connection */
+                    bta_ag_create_sco(p_scb, FALSE);    /* Back into listen mode */
+
+                    /* Accept sco connection with xfer scb */
+                    bta_ag_sco_conn_rsp(p_sco->p_xfer_scb, &p_sco->conn_data);
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+                    p_sco->p_curr_scb = p_sco->p_xfer_scb;
+                    p_sco->cur_idx = p_sco->p_xfer_scb->sco_idx;
+                    p_sco->p_xfer_scb = NULL;
+                     break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_XFER_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_OPEN_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* second headset has now joined */
+                    /* create sco listen connection (Additional channel) */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        bta_ag_create_sco(p_scb, FALSE);
+                    }
+                    break;
+
+                case BTA_AG_SCO_XFER_E:
+                    /* close current sco connection */
+                    bta_ag_remove_sco(p_sco->p_curr_scb, TRUE);
+
+                    /* save xfer scb */
+                    p_sco->p_xfer_scb = p_scb;
+
+                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+                    break;
+
+                case BTA_AG_SCO_CLOSE_E:
+                    /* close sco connection if active */
+                    if (bta_ag_remove_sco(p_scb, TRUE))
+                    {
+                        p_sco->state = BTA_AG_SCO_CLOSING_ST;
+                    }
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* remove all listening connections */
+                    bta_ag_remove_sco(p_scb, FALSE);
+
+                    /* If SCO was active on this scb, close it */
+                    if (p_scb == p_sco->p_curr_scb)
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+                    }
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* peer closed sco; create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_OPEN_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_CLOSING_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection (Additional channel) */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        bta_ag_create_sco(p_scb, FALSE);
+                    }
+                    break;
+
+                case BTA_AG_SCO_OPEN_E:
+                    p_sco->state = BTA_AG_SCO_CLOSE_OP_ST;
+                    break;
+
+                case BTA_AG_SCO_XFER_E:
+                    /* save xfer scb */
+                    p_sco->p_xfer_scb = p_scb;
+
+                    p_sco->state = BTA_AG_SCO_CLOSE_XFER_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* If not closing scb, just close it */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        /* remove listening connection */
+                        bta_ag_remove_sco(p_scb, FALSE);
+                    }
+                    else
+                        p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* peer closed sco; create sco listen connection */
+                    bta_ag_create_sco(p_scb, FALSE);
+
+                    p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSING_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_CLOSE_OP_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_CLOSE_E:
+                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+#if (BTM_WBS_INCLUDED == TRUE )
+                    /* start codec negotiation */
+                    p_sco->state = BTA_AG_SCO_CODEC_ST;
+                    p_cn_scb = p_scb;
+#else
+                    /* open sco connection */
+                    bta_ag_create_sco(p_scb, TRUE);
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+                    break;
+
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection (Additional channel) */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        bta_ag_create_sco(p_scb, FALSE);
+                    }
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_OP_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_CLOSE_XFER_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_CONN_OPEN_E:
+                    /* close sco connection so headset can be transferred
+                       Probably entered this state from "opening state" */
+                    bta_ag_remove_sco(p_scb, TRUE);
+                    break;
+
+                case BTA_AG_SCO_CLOSE_E:
+                    /* clear xfer scb */
+                    p_sco->p_xfer_scb = NULL;
+
+                    p_sco->state = BTA_AG_SCO_CLOSING_ST;
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    /* clear xfer scb */
+                    p_sco->p_xfer_scb = NULL;
+
+                    p_sco->state = BTA_AG_SCO_SHUTTING_ST;
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* closed sco; place old sco in listen mode,
+                       take current sco out of listen, and
+                       create originating sco for current */
+                    bta_ag_create_sco(p_scb, FALSE);
+                    bta_ag_remove_sco(p_sco->p_xfer_scb, FALSE);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+                    /* start codec negotiation */
+                    p_sco->state = BTA_AG_SCO_CODEC_ST;
+                    p_cn_scb = p_sco->p_xfer_scb;
+                    p_sco->p_xfer_scb = NULL;
+#else
+                    /* create sco connection to peer */
+                    bta_ag_create_sco(p_sco->p_xfer_scb, TRUE);
+                    p_sco->p_xfer_scb = NULL;
+                    p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_CLOSE_XFER_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        case BTA_AG_SCO_SHUTTING_ST:
+            switch (event)
+            {
+                case BTA_AG_SCO_CONN_OPEN_E:
+                    /* close sco connection; wait for conn close event */
+                    bta_ag_remove_sco(p_scb, TRUE);
+                    break;
+
+                case BTA_AG_SCO_CONN_CLOSE_E:
+                    /* If last SCO instance then finish shutting down */
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
+                    else    /* Other instance is still listening */
+                    {
+                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    }
+
+                    if (p_scb == p_sco->p_curr_scb)
+                    {
+                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+                        p_sco->p_curr_scb = NULL;
+                    }
+                    break;
+
+                case BTA_AG_SCO_LISTEN_E:
+                    /* create sco listen connection (Additional channel) */
+                    if (p_scb != p_sco->p_curr_scb)
+                    {
+                        bta_ag_create_sco(p_scb, FALSE);
+                    }
+                    break;
+
+                case BTA_AG_SCO_SHUTDOWN_E:
+                    if (!bta_ag_other_scb_open(p_scb))
+                    {
+                        p_sco->state = BTA_AG_SCO_SHUTDOWN_ST;
+                    }
+                    else    /* Other instance is still listening */
+                    {
+                        p_sco->state = BTA_AG_SCO_LISTEN_ST;
+                    }
+
+                    if (p_scb == p_sco->p_curr_scb)
+                    {
+                        p_sco->p_curr_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+                        p_sco->p_curr_scb = NULL;
+                    }
+                    break;
+
+                default:
+                    APPL_TRACE_WARNING1("BTA_AG_SCO_SHUTTING_ST: Ignoring event %d", event);
+                    break;
+            }
+            break;
+
+        default:
+            break;
+    }
+#if BTA_AG_SCO_DEBUG == TRUE
+    if (p_sco->state != in_state)
+    {
+        APPL_TRACE_EVENT3("BTA AG SCO State Change: [%s] -> [%s] after Event [%s]",
+                      bta_ag_sco_state_str(in_state),
+                      bta_ag_sco_state_str(p_sco->state),
+                      bta_ag_sco_evt_str(event));
+    }
+#endif
+
+#if (BTM_WBS_INCLUDED == TRUE )
+    if (p_cn_scb)
+    {
+        bta_ag_codec_negotiate(p_cn_scb);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_is_open
+**
+** Description      Check if sco is open for this scb.
+**
+**
+** Returns          TRUE if sco open for this scb, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sco_is_open(tBTA_AG_SCB *p_scb)
+{
+    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_ST) &&
+            (bta_ag_cb.sco.p_curr_scb == p_scb));
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_is_opening
+**
+** Description      Check if sco is in Opening state.
+**
+**
+** Returns          TRUE if sco is in Opening state for this scb, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sco_is_opening(tBTA_AG_SCB *p_scb)
+{
+#if (BTM_WBS_INCLUDED == TRUE )
+    return (((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) ||
+            (bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST)) &&
+            (bta_ag_cb.sco.p_curr_scb == p_scb));
+#else
+    return ((bta_ag_cb.sco.state == BTA_AG_SCO_OPENING_ST) &&
+            (bta_ag_cb.sco.p_curr_scb == p_scb));
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_listen
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_listen(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    bta_ag_sco_event(p_scb, BTA_AG_SCO_LISTEN_E);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_open
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT8 event;
+
+    /* if another scb using sco, this is a transfer */
+    if (bta_ag_cb.sco.p_curr_scb != NULL && bta_ag_cb.sco.p_curr_scb != p_scb)
+    {
+        event = BTA_AG_SCO_XFER_E;
+    }
+    /* else it is an open */
+    else
+    {
+        event = BTA_AG_SCO_OPEN_E;
+    }
+
+    bta_ag_sco_event(p_scb, event);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_close
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    /* if scb is in use */
+#if (BTM_WBS_INCLUDED == TRUE )
+    /* sco_idx is not allocated in SCO_CODEC_ST, we still need to move to listening state. */
+    if ((p_scb->sco_idx != BTM_INVALID_SCO_INDEX) || (bta_ag_cb.sco.state == BTA_AG_SCO_CODEC_ST))
+#else
+    if (p_scb->sco_idx != BTM_INVALID_SCO_INDEX)
+#endif
+    {
+        APPL_TRACE_DEBUG1("bta_ag_sco_close: sco_inx = %d", p_scb->sco_idx);
+        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
+    }
+}
+
+#if (BTM_WBS_INCLUDED == TRUE )
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_codec_nego
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_codec_nego(tBTA_AG_SCB *p_scb, BOOLEAN result)
+{
+    if(result == TRUE)
+    {
+        /* Subsequent sco connection will skip codec negotiation */
+        p_scb->codec_updated = FALSE;
+
+        bta_ag_sco_event(p_scb, BTA_AG_SCO_CN_DONE_E);
+    }
+    else    /* codec negotiation failed */
+        bta_ag_sco_event(p_scb, BTA_AG_SCO_CLOSE_E);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_shutdown
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_shutdown(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    bta_ag_sco_event(p_scb, BTA_AG_SCO_SHUTDOWN_E);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_conn_open
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_open(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_OPEN_E);
+
+    bta_sys_sco_open(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+    bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_ON);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    /* open SCO codec if SCO is routed through transport */
+    bta_dm_sco_co_open(bta_ag_scb_to_idx(p_scb), BTA_SCO_OUT_PKT_SIZE, BTA_AG_CI_SCO_DATA_EVT);
+#endif
+
+    /* call app callback */
+    bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_OPEN_EVT);
+
+    p_scb->retry_with_sco_only = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_conn_close
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    UINT16 handle = bta_ag_scb_to_idx(p_scb);
+
+    /* clear current scb */
+    bta_ag_cb.sco.p_curr_scb = NULL;
+    p_scb->sco_idx = BTM_INVALID_SCO_INDEX;
+
+#if (BTM_WBS_INCLUDED == TRUE)
+    /* codec_fallback is set when AG is initiator and connection failed for mSBC. */
+    if (p_scb->codec_fallback && p_scb->svc_conn)
+    {
+        bta_ag_sco_event(p_scb, BTA_AG_SCO_REOPEN_E);
+    }
+    else if (p_scb->retry_with_sco_only && p_scb->svc_conn)
+    {
+        /* retry_with_sco_only is set when AG is initiator and connection failed for eSCO */
+        bta_ag_create_sco(p_scb, TRUE);
+    }
+#else
+    /* retry_with_sco_only, will be set only when AG is initiator
+    ** and AG is first trying to establish an eSCO connection */
+    if (p_scb->retry_with_sco_only && p_scb->svc_conn)
+    {
+        bta_ag_create_sco(p_scb, TRUE);
+    }
+#endif
+    else
+    {
+        /* Indicate if the closing of audio is because of transfer */
+        if (bta_ag_cb.sco.p_xfer_scb)
+            bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF_XFER);
+        else
+            bta_ag_co_audio_state(handle, p_scb->app_id, BTA_AG_CO_AUD_STATE_OFF);
+
+        bta_ag_sco_event(p_scb, BTA_AG_SCO_CONN_CLOSE_E);
+
+        bta_sys_sco_close(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+        /* if av got suspended by this call, let it resume. */
+        /* In case call stays alive regardless of sco, av should not be affected. */
+        if(((p_scb->call_ind == BTA_AG_CALL_INACTIVE) && (p_scb->callsetup_ind == BTA_AG_CALLSETUP_NONE))
+            || (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END))
+        {
+            bta_sys_sco_unuse(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+        }
+
+        /* call app callback */
+        bta_ag_cback_sco(p_scb, BTA_AG_AUDIO_CLOSE_EVT);
+    }
+    p_scb->retry_with_sco_only = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sco_conn_rsp
+**
+** Description      Process the SCO connection request
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sco_conn_rsp(tBTA_AG_SCB *p_scb, tBTM_ESCO_CONN_REQ_EVT_DATA *p_data)
+{
+    tBTM_ESCO_PARAMS    resp;
+    UINT8               hci_status = HCI_SUCCESS;
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    tBTA_CODEC_INFO     codec_info = {BTA_SCO_CODEC_PCM};
+    UINT32              pcm_sample_rate;
+#endif
+
+    if (bta_ag_cb.sco.state == BTA_AG_SCO_LISTEN_ST     ||
+        bta_ag_cb.sco.state == BTA_AG_SCO_CLOSE_XFER_ST ||
+        bta_ag_cb.sco.state == BTA_AG_SCO_OPEN_XFER_ST)
+    {
+        /* If script overrided sco parameter by BTA_CMD_SET_ESCO_PARAM */
+        if (bta_ag_cb.sco.param_updated)
+        {
+            resp = bta_ag_cb.sco.params;
+        }
+        else
+        {
+            resp.rx_bw = BTM_64KBITS_RATE;
+            resp.tx_bw = BTM_64KBITS_RATE;
+            resp.max_latency = 10;
+            resp.voice_contfmt = 0x60;
+            resp.retrans_effort = BTM_ESCO_RETRANS_POWER;
+
+            if (p_data->link_type == BTM_LINK_TYPE_SCO)
+            {
+                resp.packet_types = (BTM_SCO_LINK_ONLY_MASK          |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV3 |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV3 |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
+            }
+            else    /* Allow controller to use all types available except 5-slot EDR */
+            {
+                resp.packet_types = (BTM_SCO_LINK_ALL_PKT_MASK |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_2_EV5 |
+                                     BTM_SCO_PKT_TYPES_MASK_NO_3_EV5);
+            }
+        }
+
+        /* tell sys to stop av if any */
+        bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
+
+        /* Allow any platform specific pre-SCO set up to take place */
+        bta_ag_co_audio_state(bta_ag_scb_to_idx(p_scb), p_scb->app_id, BTA_AG_CO_AUD_STATE_SETUP);
+
+#if (BTM_WBS_INCLUDED == TRUE )
+        /* When HS initiated SCO, it cannot be WBS. */
+        BTM_ConfigI2SPCM (BTM_SCO_CODEC_CVSD, (UINT8)HCI_BRCM_I2SPCM_IS_DEFAULT_ROLE, (UINT8)HCI_BRCM_I2SPCM_SAMPLE_DEFAULT, (UINT8)HCI_BRCM_I2SPCM_CLOCK_DEFAULT);
+#endif
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+        pcm_sample_rate = BTA_DM_SCO_SAMP_RATE_8K;
+
+        /* initialize SCO setup, no voice setting for AG, data rate <==> sample rate */
+        BTM_ConfigScoPath(bta_dm_sco_co_init(pcm_sample_rate, pcm_sample_rate, &codec_info, p_scb->app_id),
+            bta_ag_sco_read_cback, NULL, TRUE);
+#endif
+    }
+    else
+        hci_status = HCI_ERR_HOST_REJECT_DEVICE;
+
+#if (BTM_WBS_INCLUDED == TRUE )
+    /* If SCO open was initiated from HS, it must be CVSD */
+    p_scb->inuse_codec = BTA_AG_CODEC_NONE;
+#endif
+
+    BTM_EScoConnRsp(p_data->sco_inx, hci_status, &resp);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_ci_sco_data
+**
+** Description      Process the SCO data ready callin event
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_ci_sco_data(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+#if (BTM_SCO_HCI_INCLUDED == TRUE )
+    bta_ag_sco_event(p_scb, BTA_AG_SCO_CI_DATA_E);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_set_esco_param
+**
+** Description      Update esco parameters from script wrapper.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_set_esco_param(BOOLEAN set_reset, tBTM_ESCO_PARAMS *param)
+{
+    if(set_reset == FALSE)    /* reset the parameters to default */
+    {
+        bta_ag_cb.sco.param_updated = FALSE;
+        APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Resetting ESCO parameters to default");
+    }
+    else
+    {
+        bta_ag_cb.sco.param_updated = TRUE;
+        bta_ag_cb.sco.params = *param;
+        APPL_TRACE_DEBUG0("bta_ag_set_esco_param : Setting ESCO parameters");
+    }
+}
+
+/*******************************************************************************
+**  Debugging functions
+*******************************************************************************/
+
+#if BTA_AG_SCO_DEBUG == TRUE
+static char *bta_ag_sco_evt_str(UINT8 event)
+{
+    switch (event)
+    {
+    case BTA_AG_SCO_LISTEN_E:
+        return "Listen Request";
+    case BTA_AG_SCO_OPEN_E:
+        return "Open Request";
+    case BTA_AG_SCO_XFER_E:
+        return "Transfer Request";
+#if (BTM_WBS_INCLUDED == TRUE )
+    case BTA_AG_SCO_CN_DONE_E:
+        return "Codec Negotiation Done";
+    case BTA_AG_SCO_REOPEN_E:
+        return "Reopen Request";
+#endif
+    case BTA_AG_SCO_CLOSE_E:
+        return "Close Request";
+    case BTA_AG_SCO_SHUTDOWN_E:
+        return "Shutdown Request";
+    case BTA_AG_SCO_CONN_OPEN_E:
+        return "Opened";
+    case BTA_AG_SCO_CONN_CLOSE_E:
+        return "Closed";
+    case BTA_AG_SCO_CI_DATA_E  :
+        return "Sco Data";
+    default:
+        return "Unknown SCO Event";
+    }
+}
+
+static char *bta_ag_sco_state_str(UINT8 state)
+{
+    switch (state)
+    {
+    case BTA_AG_SCO_SHUTDOWN_ST:
+        return "Shutdown";
+    case BTA_AG_SCO_LISTEN_ST:
+        return "Listening";
+#if (BTM_WBS_INCLUDED == TRUE )
+    case BTA_AG_SCO_CODEC_ST:
+        return "Codec Negotiation";
+#endif
+    case BTA_AG_SCO_OPENING_ST:
+        return "Opening";
+    case BTA_AG_SCO_OPEN_CL_ST:
+        return "Open while closing";
+    case BTA_AG_SCO_OPEN_XFER_ST:
+        return "Opening while Transferring";
+    case BTA_AG_SCO_OPEN_ST:
+        return "Open";
+    case BTA_AG_SCO_CLOSING_ST:
+        return "Closing";
+    case BTA_AG_SCO_CLOSE_OP_ST:
+        return "Close while Opening";
+    case BTA_AG_SCO_CLOSE_XFER_ST:
+        return "Close while Transferring";
+    case BTA_AG_SCO_SHUTTING_ST:
+        return "Shutting Down";
+    default:
+        return "Unknown SCO State";
+    }
+}
+
+#endif
diff --git a/bta/ag/bta_ag_sdp.c b/bta/ag/bta_ag_sdp.c
new file mode 100644
index 0000000..d708cf2
--- /dev/null
+++ b/bta/ag/bta_ag_sdp.c
@@ -0,0 +1,500 @@
+/******************************************************************************
+ *
+ *  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 the audio gateway functions performing SDP
+ *  operations.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_ag_api.h"
+#include "bta_ag_int.h"
+#include "sdp_api.h"
+#include "btm_api.h"
+#include "gki.h"
+
+/* Number of protocol elements in protocol element list. */
+#define BTA_AG_NUM_PROTO_ELEMS      2
+
+/* Number of elements in service class id list. */
+#define BTA_AG_NUM_SVC_ELEMS        2
+
+/* size of database for service discovery */
+#ifndef BTA_AG_DISC_BUF_SIZE
+#define BTA_AG_DISC_BUF_SIZE        GKI_MAX_BUF_SIZE
+#endif
+
+/* declare sdp callback functions */
+void bta_ag_sdp_cback_1(UINT16 status);
+void bta_ag_sdp_cback_2(UINT16 status);
+void bta_ag_sdp_cback_3(UINT16 status);
+
+/* SDP callback function table */
+typedef tSDP_DISC_CMPL_CB *tBTA_AG_SDP_CBACK;
+const tBTA_AG_SDP_CBACK bta_ag_sdp_cback_tbl[] =
+{
+    bta_ag_sdp_cback_1,
+    bta_ag_sdp_cback_2,
+    bta_ag_sdp_cback_3
+};
+
+/*******************************************************************************
+**
+** Function         bta_ag_sdp_cback
+**
+** Description      SDP callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ag_sdp_cback(UINT16 status, UINT8 idx)
+{
+    tBTA_AG_DISC_RESULT *p_buf;
+    UINT16              event;
+    tBTA_AG_SCB         *p_scb;
+
+    APPL_TRACE_DEBUG1("bta_ag_sdp_cback status:0x%x", status);
+
+    if ((p_scb = bta_ag_scb_by_idx(idx)) != NULL)
+    {
+        /* set event according to int/acp */
+        if (p_scb->role == BTA_AG_ACP)
+        {
+            event = BTA_AG_DISC_ACP_RES_EVT;
+        }
+        else
+        {
+            event = BTA_AG_DISC_INT_RES_EVT;
+        }
+
+        if ((p_buf = (tBTA_AG_DISC_RESULT *) GKI_getbuf(sizeof(tBTA_AG_DISC_RESULT))) != NULL)
+        {
+            p_buf->hdr.event = event;
+            p_buf->hdr.layer_specific = idx;
+            p_buf->status = status;
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sdp_cback_1 to 3
+**
+** Description      SDP callback functions.  Since there is no way to
+**                  distinguish scb from the callback we need separate
+**                  callbacks for each scb.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_sdp_cback_1(UINT16 status) {bta_ag_sdp_cback(status, 1);}
+void bta_ag_sdp_cback_2(UINT16 status) {bta_ag_sdp_cback(status, 2);}
+void bta_ag_sdp_cback_3(UINT16 status) {bta_ag_sdp_cback(status, 3);}
+
+/******************************************************************************
+**
+** Function         bta_ag_add_record
+**
+** Description      This function is called by a server application to add
+**                  HSP or HFP information to an SDP record.  Prior to
+**                  calling this function the application must call
+**                  SDP_CreateRecord() to create an SDP record.
+**
+** Returns          TRUE if function execution succeeded,
+**                  FALSE if function execution failed.
+**
+******************************************************************************/
+BOOLEAN bta_ag_add_record(UINT16 service_uuid, char *p_service_name, UINT8 scn,
+                          tBTA_AG_FEAT features, UINT32 sdp_handle)
+{
+    tSDP_PROTOCOL_ELEM  proto_elem_list[BTA_AG_NUM_PROTO_ELEMS];
+    UINT16              svc_class_id_list[BTA_AG_NUM_SVC_ELEMS];
+    UINT16              browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
+    UINT16              version;
+    UINT16              profile_uuid;
+    UINT8               network;
+    BOOLEAN             result = TRUE;
+    BOOLEAN             codec_supported = FALSE;
+    UINT8               buf[2];
+
+    APPL_TRACE_DEBUG1("bta_ag_add_record uuid: %x", service_uuid);
+
+    memset( proto_elem_list, 0 , BTA_AG_NUM_PROTO_ELEMS*sizeof(tSDP_PROTOCOL_ELEM));
+
+    /* add the protocol element sequence */
+    proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+    proto_elem_list[0].num_params = 0;
+    proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_RFCOMM;
+    proto_elem_list[1].num_params = 1;
+    proto_elem_list[1].params[0] = scn;
+    result &= SDP_AddProtocolList(sdp_handle, BTA_AG_NUM_PROTO_ELEMS, proto_elem_list);
+
+    /* add service class id list */
+    svc_class_id_list[0] = service_uuid;
+    svc_class_id_list[1] = UUID_SERVCLASS_GENERIC_AUDIO;
+    result &= SDP_AddServiceClassIdList(sdp_handle, BTA_AG_NUM_SVC_ELEMS, svc_class_id_list);
+
+    /* add profile descriptor list */
+    if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
+    {
+        profile_uuid = UUID_SERVCLASS_HF_HANDSFREE;
+        version = HFP_VERSION_1_6;
+    }
+    else
+    {
+        profile_uuid = UUID_SERVCLASS_HEADSET;
+        version = HSP_VERSION_1_2;
+    }
+    result &= SDP_AddProfileDescriptorList(sdp_handle, profile_uuid, version);
+
+    /* add service name */
+    if (p_service_name != NULL && p_service_name[0] != 0)
+    {
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SERVICE_NAME, TEXT_STR_DESC_TYPE,
+                    (UINT32)(strlen(p_service_name)+1), (UINT8 *) p_service_name);
+    }
+
+    /* add features and network */
+    if (service_uuid == UUID_SERVCLASS_AG_HANDSFREE)
+    {
+        network = (features & BTA_AG_FEAT_REJECT) ? 1 : 0;
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_DATA_STORES_OR_NETWORK,
+                    UINT_DESC_TYPE, 1, &network);
+
+        if (features & BTA_AG_FEAT_CODEC)
+            codec_supported = TRUE;
+
+        features &= BTA_AG_SDP_FEAT_SPEC;
+
+        /* Codec bit position is different in SDP and in BRSF */
+        if (codec_supported)
+            features |= 0x0020;
+
+        UINT16_TO_BE_FIELD(buf, features);
+        result &= SDP_AddAttribute(sdp_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE, 2, buf);
+    }
+
+    /* add browse group list */
+    result &= SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
+
+    return result;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_create_records
+**
+** Description      Create SDP records for registered services.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_create_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    int                 i;
+    tBTA_SERVICE_MASK   services;
+
+    services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
+    for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1)
+    {
+        /* if service is set in mask */
+        if (services & 1)
+        {
+            /* add sdp record if not already registered */
+            if (bta_ag_cb.profile[i].sdp_handle == 0)
+            {
+                bta_ag_cb.profile[i].sdp_handle = SDP_CreateRecord();
+                bta_ag_cb.profile[i].scn = BTM_AllocateSCN();
+                bta_ag_add_record(bta_ag_uuid[i], p_data->api_register.p_name[i],
+                    bta_ag_cb.profile[i].scn, p_data->api_register.features,
+                    bta_ag_cb.profile[i].sdp_handle);
+                bta_sys_add_uuid(bta_ag_uuid[i]);
+            }
+        }
+    }
+
+    p_scb->hsp_version = HSP_VERSION_1_2;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_del_records
+**
+** Description      Delete SDP records for any registered services.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_del_records(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    tBTA_AG_SCB         *p = &bta_ag_cb.scb[0];
+    tBTA_SERVICE_MASK   services;
+    tBTA_SERVICE_MASK   others = 0;
+    int                 i;
+
+    /* get services of all other registered servers */
+    for (i = 0; i < BTA_AG_NUM_IDX; i++, p++)
+    {
+        if (p_scb == p)
+        {
+            continue;
+        }
+
+        if (p->in_use && p->dealloc == FALSE)
+        {
+            others |= p->reg_services;
+        }
+    }
+
+    others >>= BTA_HSP_SERVICE_ID;
+    services = p_scb->reg_services >> BTA_HSP_SERVICE_ID;
+    for (i = 0; i < BTA_AG_NUM_IDX && services != 0; i++, services >>= 1, others >>= 1)
+    {
+        /* if service registered for this scb and not registered for any other scb */
+        if (((services & 1) == 1) && ((others & 1) == 0))
+        {
+            APPL_TRACE_DEBUG1("bta_ag_del_records %d", i);
+            if (bta_ag_cb.profile[i].sdp_handle != 0)
+            {
+                SDP_DeleteRecord(bta_ag_cb.profile[i].sdp_handle);
+                bta_ag_cb.profile[i].sdp_handle = 0;
+            }
+            BTM_FreeSCN(bta_ag_cb.profile[i].scn);
+            BTM_SecClrService(bta_ag_sec_id[i]);
+            bta_sys_remove_uuid(bta_ag_uuid[i]);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_sdp_find_attr
+**
+** Description      Process SDP discovery results to find requested attributes
+**                  for requested service.
+**
+**
+** Returns          TRUE if results found, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_ag_sdp_find_attr(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service)
+{
+    tSDP_DISC_REC       *p_rec = NULL;
+    tSDP_DISC_ATTR      *p_attr;
+    tSDP_PROTOCOL_ELEM  pe;
+    UINT16              uuid;
+    BOOLEAN             result = FALSE;
+
+    if (service & BTA_HFP_SERVICE_MASK)
+    {
+        uuid = UUID_SERVCLASS_HF_HANDSFREE;
+        p_scb->peer_version = HFP_VERSION_1_1;   /* Default version */
+    }
+    else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+    {
+        uuid = UUID_SERVCLASS_HEADSET_HS;
+        p_scb->peer_version = 0x0100;   /* Default version */
+    }
+    else
+    {
+        return result;
+    }
+
+    /* loop through all records we found */
+    while (TRUE)
+    {
+        /* get next record; if none found, we're done */
+        if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL)
+        {
+            if (uuid == UUID_SERVCLASS_HEADSET_HS)
+            {
+                /* Search again in case the peer device is HSP v1.0 */
+                uuid = UUID_SERVCLASS_HEADSET;
+                if ((p_rec = SDP_FindServiceInDb(p_scb->p_disc_db, uuid, p_rec)) == NULL)
+                {
+                    break;
+                }
+            }
+            else
+                break;
+        }
+
+        /* get scn from proto desc list if initiator */
+        if (p_scb->role == BTA_AG_INT)
+        {
+            if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_RFCOMM, &pe))
+            {
+                p_scb->peer_scn = (UINT8) pe.params[0];
+            }
+            else
+            {
+                continue;
+            }
+        }
+
+        /* get profile version (if failure, version parameter is not updated) */
+        SDP_FindProfileVersionInRec(p_rec, uuid, &p_scb->peer_version);
+
+        /* get features if HFP */
+        if (service & BTA_HFP_SERVICE_MASK)
+        {
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+            {
+                /* Found attribute. Get value. */
+                /* There might be race condition between SDP and BRSF.  */
+                /* Do not update if we already received BRSF.           */
+                if (p_scb->peer_features == 0)
+                    p_scb->peer_features = p_attr->attr_value.v.u16;
+            }
+        }
+        else    /* HSP */
+        {
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL)) != NULL)
+            {
+                /* Remote volume control of HSP */
+                if (p_attr->attr_value.v.u8)
+                    p_scb->peer_features |= BTA_AG_PEER_FEAT_VOL;
+                else
+                    p_scb->peer_features &= ~BTA_AG_PEER_FEAT_VOL;
+            }
+
+        }
+
+        /* found what we needed */
+        result = TRUE;
+        break;
+    }
+    return result;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_do_disc
+**
+** Description      Do service discovery.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_do_disc(tBTA_AG_SCB *p_scb, tBTA_SERVICE_MASK service)
+{
+    tSDP_UUID       uuid_list[2];
+    UINT16          num_uuid = 1;
+    UINT16          attr_list[4];
+    UINT8           num_attr;
+    BOOLEAN         db_inited = FALSE;
+
+    /* HFP initiator; get proto list and features */
+    if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+    {
+        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+        attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+        attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+        attr_list[3] = ATTR_ID_SUPPORTED_FEATURES;
+        num_attr = 4;
+        uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+    }
+    /* HFP acceptor; get features */
+    else if (service & BTA_HFP_SERVICE_MASK && p_scb->role == BTA_AG_ACP)
+    {
+        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+        attr_list[1] = ATTR_ID_BT_PROFILE_DESC_LIST;
+        attr_list[2] = ATTR_ID_SUPPORTED_FEATURES;
+        num_attr = 3;
+        uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HF_HANDSFREE;
+    }
+    /* HSP initiator; get proto list */
+    else if (service & BTA_HSP_SERVICE_MASK && p_scb->role == BTA_AG_INT)
+    {
+        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+        attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+        attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+        attr_list[3] = ATTR_ID_REMOTE_AUDIO_VOLUME_CONTROL;
+        num_attr = 4;
+
+        uuid_list[0].uu.uuid16 = UUID_SERVCLASS_HEADSET;        /* Legacy from HSP v1.0 */
+        if (p_scb->hsp_version >= HSP_VERSION_1_2)
+        {
+            uuid_list[1].uu.uuid16 = UUID_SERVCLASS_HEADSET_HS;
+            num_uuid = 2;
+        }
+    }
+    /* HSP acceptor; no discovery */
+    else
+    {
+        return;
+    }
+
+    /* allocate buffer for sdp database */
+    p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AG_DISC_BUF_SIZE);
+
+    if(p_scb->p_disc_db)
+    {
+        /* set up service discovery database; attr happens to be attr_list len */
+        uuid_list[0].len = LEN_UUID_16;
+        uuid_list[1].len = LEN_UUID_16;
+        db_inited = SDP_InitDiscoveryDb(p_scb->p_disc_db, BTA_AG_DISC_BUF_SIZE, num_uuid,
+                            uuid_list, num_attr, attr_list);
+    }
+
+    if(db_inited)
+    {
+        /*Service discovery not initiated */
+        db_inited = SDP_ServiceSearchAttributeRequest(p_scb->peer_addr, p_scb->p_disc_db,
+                                      bta_ag_sdp_cback_tbl[bta_ag_scb_to_idx(p_scb) - 1]);
+    }
+
+    if(!db_inited)
+    {
+        /*free discover db */
+        bta_ag_free_db(p_scb, NULL);
+        /* sent failed event */
+        bta_ag_sm_execute(p_scb, BTA_AG_DISC_FAIL_EVT, NULL);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_ag_free_db
+**
+** Description      Free discovery database.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ag_free_db(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
+{
+    if (p_scb->p_disc_db != NULL)
+    {
+        GKI_freebuf(p_scb->p_disc_db);
+        p_scb->p_disc_db = NULL;
+    }
+}
diff --git a/bta/ar/bta_ar.c b/bta/ar/bta_ar.c
new file mode 100644
index 0000000..89b732a
--- /dev/null
+++ b/bta/ar/bta_ar.c
@@ -0,0 +1,348 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2008-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 is the implementation for the audio/video registration module.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include "bta_ar_api.h"
+#include "bta_ar_int.h"
+
+
+/* AV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AR_CB  bta_ar_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ar_id
+**
+** Description      This function maps sys_id to ar id mask.
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_ar_id(tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = 0;
+    if (sys_id == BTA_ID_AV)
+    {
+        mask = BTA_AR_AV_MASK;
+    }
+    else if (sys_id == BTA_ID_AVK)
+    {
+        mask = BTA_AR_AVK_MASK;
+    }
+
+    return mask;
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_init
+**
+** Description      This function is called to register to AVDTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_init(void)
+{
+    /* initialize control block */
+    memset(&bta_ar_cb, 0, sizeof(tBTA_AR_CB));
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_reg_avdt
+**
+** Description      This function is called to register to AVDTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_ar_avdt_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    /* route the AVDT registration callback to av or avk */
+    if (bta_ar_cb.p_av_conn_cback)
+        (*bta_ar_cb.p_av_conn_cback)(handle, bd_addr, event, p_data);
+    if (bta_ar_cb.p_avk_conn_cback)
+        (*bta_ar_cb.p_avk_conn_cback)(handle, bd_addr, event, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_reg_avdt
+**
+** Description      AR module registration to AVDT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_reg_avdt(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback, tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = 0;
+
+    if (sys_id == BTA_ID_AV)
+    {
+        bta_ar_cb.p_av_conn_cback = p_cback;
+        mask = BTA_AR_AV_MASK;
+    }
+    else if (sys_id == BTA_ID_AVK)
+    {
+        bta_ar_cb.p_avk_conn_cback = p_cback;
+        mask = BTA_AR_AVK_MASK;
+    }
+#if (BTA_AR_DEBUG == TRUE)
+    else
+    {
+        APPL_TRACE_ERROR1("bta_ar_reg_avdt: the registration is from wrong sys_id:%d", sys_id);
+    }
+#endif
+
+    if (mask)
+    {
+        if (bta_ar_cb.avdt_registered == 0)
+        {
+            AVDT_Register(p_reg, bta_ar_avdt_cback);
+        }
+        bta_ar_cb.avdt_registered |= mask;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_dereg_avdt
+**
+** Description      This function is called to de-register from AVDTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = 0;
+
+    if (sys_id == BTA_ID_AV)
+    {
+        bta_ar_cb.p_av_conn_cback = NULL;
+        mask = BTA_AR_AV_MASK;
+    }
+    else if (sys_id == BTA_ID_AVK)
+    {
+        bta_ar_cb.p_avk_conn_cback = NULL;
+        mask = BTA_AR_AVK_MASK;
+    }
+    bta_ar_cb.avdt_registered &= ~mask;
+
+    if (bta_ar_cb.avdt_registered == 0)
+        AVDT_Deregister();
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_avdt_conn
+**
+** Description      This function is called to let ar know that some AVDTP profile
+**                  is connected for this sys_id.
+**                  If the other sys modules started a timer for PENDING_EVT,
+**                  the timer can be stopped now.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr)
+{
+    UINT8       event = BTA_AR_AVDT_CONN_EVT;
+    tAVDT_CTRL  data;
+
+    if (sys_id == BTA_ID_AV)
+    {
+        if (bta_ar_cb.p_avk_conn_cback)
+        {
+            (*bta_ar_cb.p_avk_conn_cback)(0, bd_addr, event, &data);
+        }
+    }
+    else if (sys_id == BTA_ID_AVK)
+    {
+        if (bta_ar_cb.p_av_conn_cback)
+        {
+            (*bta_ar_cb.p_av_conn_cback)(0, bd_addr, event, &data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_reg_avct
+**
+** Description      This function is called to register to AVCTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_reg_avct(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask, tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = bta_ar_id (sys_id);
+
+    if (mask)
+    {
+        if (bta_ar_cb.avct_registered == 0)
+        {
+            AVCT_Register(mtu, mtu_br, sec_mask);
+        }
+        bta_ar_cb.avct_registered |= mask;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_ar_dereg_avct
+**
+** Description      This function is called to deregister from AVCTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_ar_dereg_avct(tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = bta_ar_id (sys_id);
+
+    bta_ar_cb.avct_registered &= ~mask;
+
+    if (bta_ar_cb.avct_registered == 0)
+        AVCT_Deregister();
+}
+
+/******************************************************************************
+**
+** Function         bta_ar_reg_avrc
+**
+** Description      This function is called to register an SDP record for AVRCP.
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ar_reg_avrc(UINT16 service_uuid, char *service_name, char *provider_name,
+					 UINT16 categories, tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = bta_ar_id (sys_id);
+    UINT8   temp[8], *p;
+
+    if (!mask || !categories)
+        return;
+
+    if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+    {
+        if (bta_ar_cb.sdp_tg_handle == 0)
+        {
+            bta_ar_cb.tg_registered = mask;
+            bta_ar_cb.sdp_tg_handle = SDP_CreateRecord();
+            AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_tg_handle);
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+            bta_sys_add_uuid(service_uuid);
+#endif
+        }
+        /* only one TG is allowed (first-come, first-served).
+         * If sdp_tg_handle is non-0, ignore this request */
+    }
+    else if ((service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL) || (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_CONTROL))
+    {
+        bta_ar_cb.ct_categories [mask - 1] = categories;
+        categories = bta_ar_cb.ct_categories[0]|bta_ar_cb.ct_categories[1];
+        if (bta_ar_cb.sdp_ct_handle == 0)
+        {
+            bta_ar_cb.sdp_ct_handle = SDP_CreateRecord();
+            AVRC_AddRecord(service_uuid, service_name, provider_name, categories, bta_ar_cb.sdp_ct_handle);
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+            bta_sys_add_uuid(service_uuid);
+#endif
+        }
+        else
+        {
+            /* multiple CTs are allowed.
+             * Change supported categories on the second one */
+            p = temp;
+            UINT16_TO_BE_STREAM(p, categories);
+            SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+                      (UINT32)2, (UINT8*)temp);
+        }
+    }
+}
+
+/******************************************************************************
+**
+** Function         bta_ar_dereg_avrc
+**
+** Description      This function is called to de-register/delete an SDP record for AVRCP.
+**
+** Returns          void
+**
+******************************************************************************/
+void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id)
+{
+    UINT8   mask = bta_ar_id (sys_id);
+    UINT16  categories = 0;
+    UINT8   temp[8], *p;
+
+    if (!mask)
+        return;
+
+    if (service_uuid == UUID_SERVCLASS_AV_REM_CTRL_TARGET)
+    {
+        if (bta_ar_cb.sdp_tg_handle && mask == bta_ar_cb.tg_registered)
+        {
+            bta_ar_cb.tg_registered = 0;
+            SDP_DeleteRecord(bta_ar_cb.sdp_tg_handle);
+            bta_ar_cb.sdp_tg_handle = 0;
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+            bta_sys_remove_uuid(service_uuid);
+#endif
+        }
+    }
+    else if (service_uuid == UUID_SERVCLASS_AV_REMOTE_CONTROL)
+    {
+        if (bta_ar_cb.sdp_ct_handle)
+        {
+            bta_ar_cb.ct_categories [mask - 1] = 0;
+            categories = bta_ar_cb.ct_categories[0]|bta_ar_cb.ct_categories[1];
+            if (!categories)
+            {
+                /* no CT is still registered - cleaup */
+                SDP_DeleteRecord(bta_ar_cb.sdp_ct_handle);
+                bta_ar_cb.sdp_ct_handle = 0;
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+                bta_sys_remove_uuid(service_uuid);
+#endif
+            }
+            else
+            {
+                /* change supported categories to the remaning one */
+                p = temp;
+                UINT16_TO_BE_STREAM(p, categories);
+                SDP_AddAttribute(bta_ar_cb.sdp_ct_handle, ATTR_ID_SUPPORTED_FEATURES, UINT_DESC_TYPE,
+                          (UINT32)2, (UINT8*)temp);
+            }
+        }
+    }
+
+}
diff --git a/bta/ar/bta_ar_int.h b/bta/ar/bta_ar_int.h
new file mode 100644
index 0000000..d230448
--- /dev/null
+++ b/bta/ar/bta_ar_int.h
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2008-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 is the private interface file for the BTA audio/video registration
+ *  module.
+ *
+ ******************************************************************************/
+#ifndef BTA_AR_INT_H
+#define BTA_AR_INT_H
+
+#include "bta_av_api.h"
+
+
+#ifndef BTA_AR_DEBUG
+#define BTA_AR_DEBUG    FALSE
+#endif
+
+#define BTA_AR_AV_MASK      0x01
+#define BTA_AR_AVK_MASK     0x02
+
+/* data associated with BTA_AR */
+typedef struct
+{
+    tAVDT_CTRL_CBACK *p_av_conn_cback;       /* av connection callback function */
+    tAVDT_CTRL_CBACK *p_avk_conn_cback;      /* avk connection callback function */
+    UINT8           avdt_registered;
+    UINT8           avct_registered;
+	UINT32          sdp_tg_handle;
+	UINT32          sdp_ct_handle;
+    UINT16          ct_categories[2];
+    UINT8           tg_registered;
+    tBTA_AV_HNDL    hndl;       /* Handle associated with the stream that rejected the connection. */
+} tBTA_AR_CB;
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AR_CB bta_ar_cb;
+#else
+extern tBTA_AR_CB *bta_ar_cb_ptr;
+#define bta_ar_cb (*bta_ar_cb_ptr)
+#endif
+
+#endif /* BTA_AR_INT_H */
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
new file mode 100644
index 0000000..741a5a0
--- /dev/null
+++ b/bta/av/bta_av_aact.c
@@ -0,0 +1,2733 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 action functions for advanced audio/video stream
+ *  state machine. these functions are shared by both audio and video
+ *  streams.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_int.h"
+#include "avdt_api.h"
+#include "bd.h"
+#include "utl.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/* the delay time in milliseconds to start service discovery on AVRCP */
+#ifndef BTA_AV_RC_DISC_TIME_VAL
+#define BTA_AV_RC_DISC_TIME_VAL     3500
+#endif
+
+/* the timer in milliseconds to guard against link busy and AVDT_CloseReq failed to be sent */
+#ifndef BTA_AV_CLOSE_REQ_TIME_VAL
+#define BTA_AV_CLOSE_REQ_TIME_VAL   4000
+#endif
+
+/* number to retry on reconfigure failure - some headsets requirs this number to be more than 1 */
+#ifndef BTA_AV_RECONFIG_RETRY
+#define BTA_AV_RECONFIG_RETRY       6
+#endif
+
+/* state machine states */
+enum
+{
+    BTA_AV_INIT_SST,
+    BTA_AV_INCOMING_SST,
+    BTA_AV_OPENING_SST,
+    BTA_AV_OPEN_SST,
+    BTA_AV_RCFG_SST,
+    BTA_AV_CLOSING_SST
+};
+
+
+/* the call out functions for audio stream */
+const tBTA_AV_CO_FUNCTS bta_av_a2d_cos =
+{
+    bta_av_co_audio_init,
+    bta_av_co_audio_disc_res,
+    bta_av_co_audio_getconfig,
+    bta_av_co_audio_setconfig,
+    bta_av_co_audio_open,
+    bta_av_co_audio_close,
+    bta_av_co_audio_start,
+    bta_av_co_audio_stop,
+    bta_av_co_audio_src_data_path,
+    bta_av_co_audio_delay
+};
+
+/* ssm action functions for audio stream */
+const tBTA_AV_SACT bta_av_a2d_action[] =
+{
+    bta_av_do_disc_a2d,     /* BTA_AV_DO_DISC  */
+    bta_av_cleanup,         /* BTA_AV_CLEANUP */
+    bta_av_free_sdb,        /* BTA_AV_FREE_SDB */
+    bta_av_config_ind,      /* BTA_AV_CONFIG_IND */
+    bta_av_disconnect_req,  /* BTA_AV_DISCONNECT_REQ */
+    bta_av_security_req,    /* BTA_AV_SECURITY_REQ */
+    bta_av_security_rsp,    /* BTA_AV_SECURITY_RSP */
+    bta_av_setconfig_rsp,   /* BTA_AV_SETCONFIG_RSP */
+    bta_av_st_rc_timer,     /* BTA_AV_ST_RC_TIMER */
+    bta_av_str_opened,      /* BTA_AV_STR_OPENED */
+    bta_av_security_ind,    /* BTA_AV_SECURITY_IND */
+    bta_av_security_cfm,    /* BTA_AV_SECURITY_CFM */
+    bta_av_do_close,        /* BTA_AV_DO_CLOSE */
+    bta_av_connect_req,     /* BTA_AV_CONNECT_REQ */
+    bta_av_sdp_failed,      /* BTA_AV_SDP_FAILED */
+    bta_av_disc_results,    /* BTA_AV_DISC_RESULTS */
+    bta_av_disc_res_as_acp, /* BTA_AV_DISC_RES_AS_ACP */
+    bta_av_open_failed,     /* BTA_AV_OPEN_FAILED */
+    bta_av_getcap_results,  /* BTA_AV_GETCAP_RESULTS */
+    bta_av_setconfig_rej,   /* BTA_AV_SETCONFIG_REJ */
+    bta_av_discover_req,    /* BTA_AV_DISCOVER_REQ */
+    bta_av_conn_failed,     /* BTA_AV_CONN_FAILED */
+    bta_av_do_start,        /* BTA_AV_DO_START */
+    bta_av_str_stopped,     /* BTA_AV_STR_STOPPED */
+    bta_av_reconfig,        /* BTA_AV_RECONFIG */
+    bta_av_data_path,       /* BTA_AV_DATA_PATH */
+    bta_av_start_ok,        /* BTA_AV_START_OK */
+    bta_av_start_failed,    /* BTA_AV_START_FAILED */
+    bta_av_str_closed,      /* BTA_AV_STR_CLOSED */
+    bta_av_clr_cong,        /* BTA_AV_CLR_CONG */
+    bta_av_suspend_cfm,     /* BTA_AV_SUSPEND_CFM */
+    bta_av_rcfg_str_ok,     /* BTA_AV_RCFG_STR_OK */
+    bta_av_rcfg_failed,     /* BTA_AV_RCFG_FAILED */
+    bta_av_rcfg_connect,    /* BTA_AV_RCFG_CONNECT */
+    bta_av_rcfg_discntd,    /* BTA_AV_RCFG_DISCNTD */
+    bta_av_suspend_cont,    /* BTA_AV_SUSPEND_CONT */
+    bta_av_rcfg_cfm,        /* BTA_AV_RCFG_CFM */
+    bta_av_rcfg_open,       /* BTA_AV_RCFG_OPEN */
+    bta_av_security_rej,    /* BTA_AV_SECURITY_REJ */
+    bta_av_open_rc,         /* BTA_AV_OPEN_RC */
+    bta_av_chk_2nd_start,   /* BTA_AV_CHK_2ND_START */
+    bta_av_save_caps,       /* BTA_AV_SAVE_CAPS */
+    bta_av_set_use_rc,      /* BTA_AV_SET_USE_RC */
+    bta_av_cco_close,       /* BTA_AV_CCO_CLOSE */
+    bta_av_switch_role,     /* BTA_AV_SWITCH_ROLE */
+    bta_av_role_res,        /* BTA_AV_ROLE_RES */
+    bta_av_delay_co,        /* BTA_AV_DELAY_CO */
+    bta_av_open_at_inc,     /* BTA_AV_OPEN_AT_INC */
+    NULL
+};
+
+/* these tables translate AVDT events to SSM events */
+static const UINT16 bta_av_stream_evt_ok[] = {
+    BTA_AV_STR_DISC_OK_EVT,         /* AVDT_DISCOVER_CFM_EVT */
+    BTA_AV_STR_GETCAP_OK_EVT,       /* AVDT_GETCAP_CFM_EVT */
+    BTA_AV_STR_OPEN_OK_EVT,         /* AVDT_OPEN_CFM_EVT */
+    BTA_AV_STR_OPEN_OK_EVT,         /* AVDT_OPEN_IND_EVT */
+    BTA_AV_STR_CONFIG_IND_EVT,      /* AVDT_CONFIG_IND_EVT */
+    BTA_AV_STR_START_OK_EVT,        /* AVDT_START_CFM_EVT */
+    BTA_AV_STR_START_OK_EVT,        /* AVDT_START_IND_EVT */
+    BTA_AV_STR_SUSPEND_CFM_EVT,     /* AVDT_SUSPEND_CFM_EVT */
+    BTA_AV_STR_SUSPEND_CFM_EVT,     /* AVDT_SUSPEND_IND_EVT */
+    BTA_AV_STR_CLOSE_EVT,           /* AVDT_CLOSE_CFM_EVT */
+    BTA_AV_STR_CLOSE_EVT,           /* AVDT_CLOSE_IND_EVT */
+    BTA_AV_STR_RECONFIG_CFM_EVT,    /* AVDT_RECONFIG_CFM_EVT */
+    0,                              /* AVDT_RECONFIG_IND_EVT */
+    BTA_AV_STR_SECURITY_CFM_EVT,    /* AVDT_SECURITY_CFM_EVT */
+    BTA_AV_STR_SECURITY_IND_EVT,    /* AVDT_SECURITY_IND_EVT */
+    BTA_AV_STR_WRITE_CFM_EVT,       /* AVDT_WRITE_CFM_EVT */
+    BTA_AV_AVDT_CONNECT_EVT,        /* AVDT_CONNECT_IND_EVT */
+    BTA_AV_AVDT_DISCONNECT_EVT,     /* AVDT_DISCONNECT_IND_EVT */
+#if (AVDT_REPORTING == TRUE)
+    BTA_AV_AVDT_RPT_CONN_EVT,       /* AVDT_REPORT_CONN_EVT */
+    BTA_AV_AVDT_RPT_CONN_EVT,       /* AVDT_REPORT_DISCONN_EVT */
+#endif
+    BTA_AV_AVDT_DELAY_RPT_EVT,      /* AVDT_DELAY_REPORT_EVT */
+    0                               /* AVDT_DELAY_REPORT_CFM_EVT */
+};
+
+static const UINT16 bta_av_stream_evt_fail[] = {
+    BTA_AV_STR_DISC_FAIL_EVT,       /* AVDT_DISCOVER_CFM_EVT */
+    BTA_AV_STR_GETCAP_FAIL_EVT,     /* AVDT_GETCAP_CFM_EVT */
+    BTA_AV_STR_OPEN_FAIL_EVT,       /* AVDT_OPEN_CFM_EVT */
+    BTA_AV_STR_OPEN_OK_EVT,         /* AVDT_OPEN_IND_EVT */
+    BTA_AV_STR_CONFIG_IND_EVT,      /* AVDT_CONFIG_IND_EVT */
+    BTA_AV_STR_START_FAIL_EVT,      /* AVDT_START_CFM_EVT */
+    BTA_AV_STR_START_OK_EVT,        /* AVDT_START_IND_EVT */
+    BTA_AV_STR_SUSPEND_CFM_EVT,     /* AVDT_SUSPEND_CFM_EVT */
+    BTA_AV_STR_SUSPEND_CFM_EVT,     /* AVDT_SUSPEND_IND_EVT */
+    BTA_AV_STR_CLOSE_EVT,           /* AVDT_CLOSE_CFM_EVT */
+    BTA_AV_STR_CLOSE_EVT,           /* AVDT_CLOSE_IND_EVT */
+    BTA_AV_STR_RECONFIG_CFM_EVT,    /* AVDT_RECONFIG_CFM_EVT */
+    0,                              /* AVDT_RECONFIG_IND_EVT */
+    BTA_AV_STR_SECURITY_CFM_EVT,    /* AVDT_SECURITY_CFM_EVT */
+    BTA_AV_STR_SECURITY_IND_EVT,    /* AVDT_SECURITY_IND_EVT */
+    BTA_AV_STR_WRITE_CFM_EVT,       /* AVDT_WRITE_CFM_EVT */
+    BTA_AV_AVDT_CONNECT_EVT,        /* AVDT_CONNECT_IND_EVT */
+    BTA_AV_AVDT_DISCONNECT_EVT,     /* AVDT_DISCONNECT_IND_EVT */
+#if (AVDT_REPORTING == TRUE)
+    BTA_AV_AVDT_RPT_CONN_EVT,       /* AVDT_REPORT_CONN_EVT */
+    BTA_AV_AVDT_RPT_CONN_EVT,       /* AVDT_REPORT_DISCONN_EVT */
+#endif
+    BTA_AV_AVDT_DELAY_RPT_EVT,      /* AVDT_DELAY_REPORT_EVT */
+    0                               /* AVDT_DELAY_REPORT_CFM_EVT */
+};
+
+static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+static void bta_av_stream1_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#if BTA_AV_NUM_STRS > 2
+static void bta_av_stream2_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 3
+static void bta_av_stream3_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 4
+static void bta_av_stream4_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+#if BTA_AV_NUM_STRS > 5
+static void bta_av_stream5_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+#endif
+/* the array of callback functions to receive events from AVDT control channel */
+tAVDT_CTRL_CBACK * const bta_av_dt_cback[] =
+{
+    bta_av_stream0_cback
+    ,bta_av_stream1_cback
+#if BTA_AV_NUM_STRS > 2
+    ,bta_av_stream2_cback
+#endif
+#if BTA_AV_NUM_STRS > 3
+    ,bta_av_stream3_cback
+#endif
+#if BTA_AV_NUM_STRS > 4
+    ,bta_av_stream4_cback
+#endif
+#if BTA_AV_NUM_STRS > 5
+    ,bta_av_stream5_cback
+#endif
+};
+
+/*******************************************************************************
+**
+** Function         bta_av_save_addr
+**
+** Description      copy the bd_addr and maybe reset the supported flags
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_save_addr(tBTA_AV_SCB *p_scb, const BD_ADDR b)
+{
+    APPL_TRACE_DEBUG2("bta_av_save_addr r:%d, s:%d",
+        p_scb->recfg_sup, p_scb->suspend_sup);
+    if(bdcmp(p_scb->peer_addr, b) != 0)
+    {
+        APPL_TRACE_ERROR0("reset flags");
+        /* a new addr, reset the supported flags */
+        p_scb->recfg_sup    = TRUE;
+        p_scb->suspend_sup  = TRUE;
+    }
+
+    /* do this copy anyway, just in case the first addr matches
+     * the control block one by accident */
+    bdcpy(p_scb->peer_addr, b);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_st_rc_timer
+**
+** Description      start the AVRC timer if no RC connection & CT is supported &
+**                  RC is used or
+**                  as ACP (we do not really know if we want AVRC)
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+
+    APPL_TRACE_DEBUG2("bta_av_st_rc_timer rc_handle:%d, use_rc: %d",
+        p_scb->rc_handle, p_scb->use_rc);
+    /* for outgoing RC connection as INT/CT */
+    if( (p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE) &&
+        /*(bta_av_cb.features & BTA_AV_FEAT_RCCT) &&*/
+        (p_scb->use_rc == TRUE || (p_scb->role & BTA_AV_ROLE_AD_ACP)) )
+    {
+        if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) == 0)
+            bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+        else
+            p_scb->wait |= BTA_AV_WAIT_CHECK_RC;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_next_getcap
+**
+** Description      The function gets the capabilities of the next available
+**                  stream found in the discovery results.
+**
+** Returns          TRUE if we sent request to AVDT, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_av_next_getcap(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    int     i;
+    tAVDT_GETCAP_REQ    *p_req;
+    BOOLEAN     sent_cmd = FALSE;
+
+    for (i = p_scb->sep_info_idx; i < p_scb->num_seps; i++)
+    {
+        /* steam not in use, is a sink, and is the right media type (audio/video) */
+        if ((p_scb->sep_info[i].in_use == FALSE) &&
+            (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+            (p_scb->sep_info[i].media_type == p_scb->media_type))
+        {
+            p_scb->sep_info_idx = i;
+
+            /* we got a stream; get its capabilities */
+            if (p_scb->p_cap == NULL)
+            {
+                p_scb->p_cap = (tAVDT_CFG *) GKI_getbuf(sizeof(tAVDT_CFG));
+            }
+            if (p_scb->p_cap == NULL)
+            {
+                i = p_scb->num_seps;
+                break;
+            }
+            if (p_scb->avdt_version >= AVDT_VERSION_SYNC)
+            {
+                p_req = AVDT_GetAllCapReq;
+            }
+            else
+            {
+                p_req = AVDT_GetCapReq;
+            }
+            (*p_req)(p_scb->peer_addr,
+                           p_scb->sep_info[i].seid,
+                           p_scb->p_cap, bta_av_dt_cback[p_scb->hdi]);
+            sent_cmd = TRUE;
+            break;
+        }
+    }
+
+    /* if no streams available then stream open fails */
+    if (!sent_cmd)
+    {
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_GETCAP_FAIL_EVT, p_data);
+    }
+
+    return sent_cmd;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_proc_stream_evt
+**
+** Description      Utility function to compose stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data, int index)
+{
+    tBTA_AV_STR_MSG     *p_msg;
+    UINT16              sec_len = 0;
+    tBTA_AV_SCB         *p_scb = bta_av_cb.p_scb[index];
+    int                 xx;
+
+    if (p_data)
+    {
+        if (event == AVDT_SECURITY_IND_EVT)
+        {
+            sec_len = (p_data->security_ind.len < BTA_AV_SECURITY_MAX_LEN) ?
+                       p_data->security_ind.len : BTA_AV_SECURITY_MAX_LEN;
+        }
+        else if (event == AVDT_SECURITY_CFM_EVT && p_data->hdr.err_code == 0)
+        {
+            sec_len = (p_data->security_cfm.len < BTA_AV_SECURITY_MAX_LEN) ?
+                       p_data->security_cfm.len : BTA_AV_SECURITY_MAX_LEN;
+        }
+    }
+
+    if (p_scb && (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG) + sec_len))) != NULL)
+    {
+
+        /* copy event data, bd addr, and handle to event message buffer */
+        p_msg->hdr.offset = 0;
+
+        if (bd_addr != NULL)
+        {
+            bdcpy(p_msg->bd_addr, bd_addr);
+            APPL_TRACE_DEBUG6("  bd_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]);
+        }
+
+        if (p_data != NULL)
+        {
+            memcpy(&p_msg->msg, p_data, sizeof (tAVDT_CTRL));
+            /* copy config params to event message buffer */
+            switch (event)
+            {
+            case AVDT_CONFIG_IND_EVT:
+            /* We might have 2 SEP signallings(A2DP + VDP) with one peer device on one L2CAP.
+             * If we already have a signalling connection with the bd_addr and the streaming
+             * SST is at INIT state, change it to INCOMING state to handle the signalling
+             * from the 2nd SEP.                                                                */
+            if ((bta_av_find_lcb(bd_addr, BTA_AV_LCB_FIND) != NULL) && (bta_av_is_scb_init(p_scb)))
+            {
+                bta_av_set_scb_sst_incoming (p_scb);
+
+                /* When ACP_CONNECT_EVT was received, we put first available scb to incoming state.
+                 * Later when we receive AVDT_CONFIG_IND_EVT, we use a new p_scb and set its state to
+                 * incoming which we do it above.
+                 * We also have to set the old p_scb state to init to be used later             */
+                for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+                {
+                    if ((bta_av_cb.p_scb[xx]) && (xx != index))
+                    {
+                        if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+                        {
+                            bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+                            bta_av_cb.p_scb[xx]->coll_mask = 0;
+                            break;
+                        }
+                    }
+                }
+            }
+
+            memcpy(&p_msg->cfg, p_data->config_ind.p_cfg, sizeof(tAVDT_CFG));
+            break;
+
+            case AVDT_SECURITY_IND_EVT:
+                p_msg->msg.security_ind.p_data = (UINT8 *) (p_msg + 1);
+                memcpy(p_msg->msg.security_ind.p_data, p_data->security_ind.p_data, sec_len);
+                break;
+
+            case AVDT_SECURITY_CFM_EVT:
+                p_msg->msg.security_cfm.p_data = (UINT8 *) (p_msg + 1);
+                if (p_data->hdr.err_code == 0)
+                {
+                    memcpy(p_msg->msg.security_cfm.p_data, p_data->security_cfm.p_data, sec_len);
+                }
+                break;
+            case AVDT_SUSPEND_IND_EVT:
+                    p_msg->msg.hdr.err_code = 0;
+                break;
+
+            default:
+                break;
+            }
+        }
+        else
+            p_msg->msg.hdr.err_code = 0;
+
+        /* look up application event */
+        if ((p_data == NULL) || (p_data->hdr.err_code == 0))
+        {
+            p_msg->hdr.event = bta_av_stream_evt_ok[event];
+        }
+        else
+        {
+            p_msg->hdr.event = bta_av_stream_evt_fail[event];
+        }
+
+        p_msg->initiator = FALSE;
+        if (event == AVDT_SUSPEND_CFM_EVT)
+            p_msg->initiator = TRUE;
+
+        APPL_TRACE_EVENT1("hndl:x%x", p_scb->hndl);
+        p_msg->hdr.layer_specific = p_scb->hndl;
+        p_msg->handle   = handle;
+        p_msg->avdt_event = event;
+        bta_sys_sendmsg(p_msg);
+    }
+
+/* coverity[var_deref_model]: Variable "p_data" tracked as NULL was passed to function "bta_av_conn_cback" that dereferences it.
+ * false-positive: bta_av_conn_cback only processes AVDT_CONNECT_IND_EVT and AVDT_DISCONNECT_IND_EVT event
+ *                 these 2 events always have associated p_data
+ */
+    bta_av_conn_cback(handle, bd_addr, event, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_stream0_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_stream0_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream0_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_stream1_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_stream1_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream1_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 1);
+}
+
+#if BTA_AV_NUM_STRS > 2
+/*******************************************************************************
+**
+** Function         bta_av_stream2_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_stream2_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream2_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 2);
+}
+#endif
+
+#if BTA_AV_NUM_STRS > 3
+/*******************************************************************************
+**
+** Function         bta_av_stream3_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_stream3_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream3_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 3);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_stream4_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+#if BTA_AV_NUM_STRS > 4
+static void bta_av_stream4_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream4_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 4);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_stream5_cback
+**
+** Description      This is the AVDTP callback function for stream events.
+**
+** Returns          void
+**
+*******************************************************************************/
+#if BTA_AV_NUM_STRS > 5
+static void bta_av_stream5_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    APPL_TRACE_EVENT2("bta_av_stream5_cback avdt_handle: %d event=0x%x", handle, event);
+    bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 5);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_a2d_sdp_cback
+**
+** Description      A2DP service discovery callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_a2d_sdp_cback(BOOLEAN found, tA2D_Service *p_service)
+{
+    tBTA_AV_SDP_RES *p_msg;
+    tBTA_AV_SCB     *p_scb;
+
+    if ((p_msg = (tBTA_AV_SDP_RES *) GKI_getbuf(sizeof(tBTA_AV_SDP_RES))) != NULL)
+    {
+        p_msg->hdr.event = (found) ? BTA_AV_SDP_DISC_OK_EVT : BTA_AV_SDP_DISC_FAIL_EVT;
+
+        p_scb = bta_av_hndl_to_scb(bta_av_cb.handle);
+        if (p_scb)
+        {
+            if (found && (p_service != NULL))
+                p_scb->avdt_version = p_service->avdt_version;
+            else
+                p_scb->avdt_version = 0x00;
+
+            p_msg->hdr.layer_specific = bta_av_cb.handle;
+            bta_sys_sendmsg(p_msg);
+        }
+        else
+        {
+            APPL_TRACE_ERROR1 ("bta_av_a2d_sdp_cback, no scb found for handle(0x%x)", bta_av_cb.handle);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_adjust_seps_idx
+**
+** Description      adjust the sep_idx
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_av_adjust_seps_idx(tBTA_AV_SCB *p_scb)
+{
+    int             xx;
+
+    APPL_TRACE_DEBUG1("bta_av_adjust_seps_idx codec_type: %d", p_scb->codec_type);
+    for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+    {
+        APPL_TRACE_DEBUG2("av_handle: %d codec_type: %d",
+            p_scb->seps[xx].av_handle, p_scb->seps[xx].codec_type);
+        if(p_scb->seps[xx].av_handle && p_scb->codec_type == p_scb->seps[xx].codec_type)
+        {
+            p_scb->sep_idx      = xx;
+            p_scb->avdt_handle  = p_scb->seps[xx].av_handle;
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_switch_role
+**
+** Description      Switch role was not started and a timer was started.
+**                  another attempt to switch role now - still opening.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_switch_role (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RS_RES      switch_res = BTA_AV_RS_NONE;
+    tBTA_AV_API_OPEN  *p_buf = &p_scb->q_info.open;
+
+    APPL_TRACE_DEBUG1("bta_av_switch_role wait:x%x", p_scb->wait);
+    if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
+        p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RETRY;
+
+    /* clear the masks set when the timer is started */
+    p_scb->wait &= ~(BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START);
+
+    if (p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+    {
+        if (bta_av_switch_if_needed(p_scb) || !bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+        {
+            p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+        }
+        else
+        {
+            /* this should not happen in theory. Just in case...
+             * continue to do_disc_a2d */
+            switch_res = BTA_AV_RS_DONE;
+        }
+    }
+    else
+    {
+        /* report failure on OPEN */
+        switch_res = BTA_AV_RS_FAIL;
+    }
+
+    if (switch_res != BTA_AV_RS_NONE)
+    {
+        if (bta_av_cb.rs_idx == (p_scb->hdi + 1))
+        {
+            bta_av_cb.rs_idx = 0;
+        }
+        p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_RETRY;
+        p_scb->q_tag = 0;
+        p_buf->switch_res = switch_res;
+        bta_av_do_disc_a2d(p_scb, (tBTA_AV_DATA *)p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_role_res
+**
+** Description      Handle the role changed event
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    BOOLEAN         initiator = FALSE;
+    tBTA_AV_START   start;
+    tBTA_AV_OPEN    av_open;
+
+    APPL_TRACE_DEBUG3("bta_av_role_res q_tag:%d, wait:x%x, role:x%x", p_scb->q_tag, p_scb->wait, p_scb->role);
+    if (p_scb->role & BTA_AV_ROLE_START_INT)
+        initiator = TRUE;
+
+    if (p_scb->q_tag == BTA_AV_Q_TAG_START)
+    {
+        if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_STARTED)
+        {
+            p_scb->role &= ~BTA_AV_ROLE_START_INT;
+            p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+            if (p_data->role_res.hci_status != HCI_SUCCESS)
+            {
+                bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+                /* start failed because of role switch. */
+                start.chnl   = p_scb->chnl;
+                start.status = BTA_AV_FAIL_ROLE;
+                start.hndl   = p_scb->hndl;
+                start.initiator = initiator;
+                (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+            }
+            else
+            {
+                bta_av_start_ok(p_scb, p_data);
+            }
+        }
+        else if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_START)
+            p_scb->wait |= BTA_AV_WAIT_ROLE_SW_FAILED;
+    }
+    else if (p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+    {
+        if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_RES_OPEN)
+        {
+            p_scb->role &= ~BTA_AV_ROLE_START_INT;
+            p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+
+            if (p_data->role_res.hci_status != HCI_SUCCESS)
+            {
+                /* Open failed because of role switch. */
+                bdcpy(av_open.bd_addr, p_scb->peer_addr);
+                av_open.chnl   = p_scb->chnl;
+                av_open.hndl   = p_scb->hndl;
+                start.status = BTA_AV_FAIL_ROLE;
+                (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *)&av_open);
+            }
+            else
+            {
+                /* Continue av open process */
+                p_scb->q_info.open.switch_res = BTA_AV_RS_DONE;
+                bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
+            }
+        }
+        else
+        {
+            APPL_TRACE_WARNING2 ("Unexpected role switch event: q_tag = %d wait = %d", p_scb->q_tag, p_scb->wait);
+        }
+    }
+
+    APPL_TRACE_DEBUG2("wait:x%x, role:x%x", p_scb->wait, p_scb->role);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_delay_co
+**
+** Description      Call the delay call-out function to report the delay report
+**                  from SNK
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_delay_co (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    p_scb->p_cos->delay(p_scb->hndl, p_data->str_msg.msg.delay_rpt_cmd.delay);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_do_disc_a2d
+**
+** Description      Do service discovery for A2DP.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    BOOLEAN     ok_continue = FALSE;
+    tA2D_SDP_DB_PARAMS  db_params;
+    UINT16              attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+                                       ATTR_ID_PROTOCOL_DESC_LIST,
+                                       ATTR_ID_BT_PROFILE_DESC_LIST};
+
+    APPL_TRACE_DEBUG3("bta_av_do_disc_a2d use_rc: %d rs:%d, oc:%d",
+        p_data->api_open.use_rc, p_data->api_open.switch_res, bta_av_cb.audio_open_cnt);
+
+    memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+
+    switch(p_data->api_open.switch_res)
+    {
+    case BTA_AV_RS_NONE:
+        if (bta_av_switch_if_needed(p_scb) || !bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+        {
+            /* waiting for role switch result. save the api to control block */
+            memcpy(&p_scb->q_info.open, &p_data->api_open, sizeof(tBTA_AV_API_OPEN));
+            p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+            p_scb->q_tag = BTA_AV_Q_TAG_OPEN;
+        }
+        else
+        {
+            ok_continue = TRUE;
+        }
+        break;
+
+    case BTA_AV_RS_FAIL:
+        /* report a new failure event  */
+        p_scb->open_status = BTA_AV_FAIL_ROLE;
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_FAIL_EVT, NULL);
+        break;
+
+    case BTA_AV_RS_OK:
+        p_data = (tBTA_AV_DATA *)&p_scb->q_info.open;
+        /* continue to open if link role is ok */
+        if (bta_av_link_role_ok(p_scb, A2D_SET_MULTL_BIT))
+        {
+            ok_continue = TRUE;
+        }
+        else
+        {
+            p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_OPEN;
+        }
+        break;
+
+    case BTA_AV_RS_DONE:
+        ok_continue = TRUE;
+        break;
+    }
+
+    APPL_TRACE_DEBUG3("ok_continue: %d wait:x%x, q_tag: %d", ok_continue, p_scb->wait, p_scb->q_tag);
+    if (!ok_continue)
+        return;
+
+    /* clear the role switch bits */
+    p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+
+    if (p_scb->wait & BTA_AV_WAIT_CHECK_RC)
+    {
+        p_scb->wait &= ~BTA_AV_WAIT_CHECK_RC;
+        bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+    }
+
+    if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+    {
+    L2CA_SetDesireRole(L2CAP_ROLE_DISALLOW_SWITCH);
+
+    if (bta_av_cb.audio_open_cnt == 1)
+    {
+        /* there's already an A2DP connection. do not allow switch */
+        bta_sys_clear_default_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH);
+    }
+    }
+    /* store peer addr other parameters */
+    bta_av_save_addr(p_scb, p_data->api_open.bd_addr);
+    p_scb->sec_mask = p_data->api_open.sec_mask;
+    p_scb->use_rc = p_data->api_open.use_rc;
+
+    bta_sys_app_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+
+    /* allocate discovery database */
+    if (p_scb->p_disc_db == NULL)
+    {
+        p_scb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AV_DISC_BUF_SIZE);
+    }
+
+    /* only one A2D find service is active at a time */
+    bta_av_cb.handle = p_scb->hndl;
+
+    if(p_scb->p_disc_db)
+    {
+        /* set up parameters */
+        db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+        db_params.num_attr = 3;
+        db_params.p_db = p_scb->p_disc_db;
+        db_params.p_attrs = attr_list;
+
+        if(A2D_FindService(UUID_SERVCLASS_AUDIO_SINK, p_scb->peer_addr, &db_params,
+                        bta_av_a2d_sdp_cback) == A2D_SUCCESS)
+        {
+            return;
+        }
+    }
+
+    /* when the code reaches here, either the DB is NULL
+     * or A2D_FindService is not successful */
+    bta_av_a2d_sdp_cback(FALSE, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_cleanup
+**
+** Description      cleanup AV stream control block.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_cleanup(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CONN_CHG msg;
+    int             xx;
+    UINT8           role = BTA_AV_ROLE_AD_INT;
+
+    APPL_TRACE_DEBUG0("bta_av_cleanup");
+
+    /* free any buffers */
+    utl_freebuf((void **) &p_scb->p_cap);
+    utl_freebuf((void **) &p_scb->p_disc_db);
+    p_scb->avdt_version = 0;
+
+    /* initialize some control block variables */
+    p_scb->open_status = BTA_AV_SUCCESS;
+
+    /* if de-registering shut everything down */
+    msg.hdr.layer_specific  = p_scb->hndl;
+    p_scb->started  = FALSE;
+    p_scb->cong = FALSE;
+    p_scb->role = role;
+    p_scb->cur_psc_mask = 0;
+    p_scb->wait = 0;
+    p_scb->num_disc_snks = 0;
+    bta_sys_stop_timer(&p_scb->timer);
+    if (p_scb->deregistring)
+    {
+        /* remove stream */
+        for(xx=0; xx<BTA_AV_MAX_SEPS; xx++)
+        {
+            if(p_scb->seps[xx].av_handle)
+                AVDT_RemoveStream(p_scb->seps[xx].av_handle);
+            p_scb->seps[xx].av_handle = 0;
+        }
+
+        bta_av_dereg_comp((tBTA_AV_DATA *) &msg);
+    }
+    else
+    {
+        /* report stream closed to main SM */
+        msg.is_up = FALSE;
+        bdcpy(msg.peer_addr, p_scb->peer_addr);
+        bta_av_conn_chg((tBTA_AV_DATA *) &msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_free_sdb
+**
+** Description      Free service discovery db buffer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_free_sdb(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    utl_freebuf((void **) &p_scb->p_disc_db);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_config_ind
+**
+** Description      Handle a stream configuration indication from the peer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CI_SETCONFIG setconfig;
+    tAVDT_SEP_INFO       *p_info;
+    tAVDT_CFG            *p_evt_cfg = &p_data->str_msg.cfg;
+    UINT8   psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
+
+    p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
+    memcpy(p_scb->cfg.codec_info, p_evt_cfg->codec_info, AVDT_CODEC_SIZE);
+    p_scb->codec_type = p_evt_cfg->codec_info[BTA_AV_CODEC_TYPE_IDX];
+    bta_av_save_addr(p_scb, p_data->str_msg.bd_addr);
+
+    /* Clear collision mask */
+    p_scb->coll_mask = 0;
+    bta_sys_stop_timer(&bta_av_cb.acp_sig_tmr);
+
+    /* if no codec parameters in configuration, fail */
+    if ((p_evt_cfg->num_codec == 0) ||
+    /* or the peer requests for a service we do not support */
+        ((psc_mask != p_scb->cfg.psc_mask) &&
+        (psc_mask != (p_scb->cfg.psc_mask&~AVDT_PSC_DELAY_RPT))) )
+    {
+        setconfig.hndl      = p_scb->hndl; /* we may not need this */
+        setconfig.err_code  = AVDT_ERR_UNSUP_CFG;
+        bta_av_ssm_execute(p_scb, BTA_AV_CI_SETCONFIG_FAIL_EVT, (tBTA_AV_DATA *) &setconfig);
+    }
+    else
+    {
+        p_info = &p_scb->sep_info[0];
+        p_info->in_use = 0;
+        p_info->media_type = p_scb->media_type;
+        p_info->seid = p_data->str_msg.msg.config_ind.int_seid;
+        p_info->tsep = AVDT_TSEP_SNK;
+        p_scb->role      |= BTA_AV_ROLE_AD_ACP;
+        p_scb->cur_psc_mask = p_evt_cfg->psc_mask;
+        if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+            p_scb->use_rc = TRUE;
+        else
+            p_scb->use_rc = FALSE;
+
+        p_scb->num_seps  = 1;
+        p_scb->sep_info_idx = 0;
+        APPL_TRACE_DEBUG3("bta_av_config_ind: SEID: %d use_rc: %d cur_psc_mask:0x%x", p_info->seid, p_scb->use_rc, p_scb->cur_psc_mask);
+
+        p_scb->p_cos->setcfg(p_scb->hndl, p_scb->codec_type,
+                             p_evt_cfg->codec_info,
+                             p_info->seid,
+                             p_scb->peer_addr,
+                             p_evt_cfg->num_protect,
+                             p_evt_cfg->protect_info);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_disconnect_req
+**
+** Description      Disconnect AVDTP connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_disconnect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RCB *p_rcb;
+    APPL_TRACE_DEBUG1("bta_av_disconnect_req conn_lcb: 0x%x", bta_av_cb.conn_lcb);
+
+    bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+    bta_sys_stop_timer(&p_scb->timer);
+    if(bta_av_cb.conn_lcb)
+    {
+        p_rcb = bta_av_get_rcb_by_shdl((UINT8)(p_scb->hdi + 1));
+        if (p_rcb)
+            bta_av_del_rc(p_rcb);
+        AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+    }
+    else
+    {
+        bta_av_ssm_execute(p_scb, BTA_AV_AVDT_DISCONNECT_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_security_req
+**
+** Description      Send an AVDTP security request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_security_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+    {
+        AVDT_SecurityReq(p_scb->avdt_handle, p_data->api_protect_req.p_data,
+                         p_data->api_protect_req.len);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_security_rsp
+**
+** Description      Send an AVDTP security response.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_security_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+    {
+        AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->api_protect_rsp.error_code,
+                         p_data->api_protect_rsp.p_data, p_data->api_protect_rsp.len);
+    }
+    else
+    {
+        AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_NSC,
+                     NULL, 0);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_setconfig_rsp
+**
+** Description      setconfig is OK
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8   num = p_data->ci_setconfig.num_seid + 1;
+    UINT8   *p_seid = p_data->ci_setconfig.p_seid;
+    int     i;
+
+    /* we like this codec_type. find the sep_idx */
+    bta_av_adjust_seps_idx(p_scb);
+    APPL_TRACE_DEBUG2("bta_av_setconfig_rsp: sep_idx: %d cur_psc_mask:0x%x", p_scb->sep_idx, p_scb->cur_psc_mask);
+    AVDT_ConfigRsp(p_scb->avdt_handle, p_scb->avdt_label, p_data->ci_setconfig.err_code,
+                   p_data->ci_setconfig.category);
+
+    bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+
+    if(p_data->ci_setconfig.err_code == AVDT_SUCCESS)
+    {
+        p_scb->wait = BTA_AV_WAIT_ACP_CAPS_ON;
+        if(p_data->ci_setconfig.recfg_needed)
+            p_scb->role |= BTA_AV_ROLE_SUSPEND_OPT;
+        APPL_TRACE_ERROR3("bta_av_setconfig_rsp recfg_needed:%d role:x%x num:%d",
+            p_data->ci_setconfig.recfg_needed, p_scb->role, num);
+        /* callout module tells BTA the number of "good" SEPs and their SEIDs.
+         * getcap on these SEID */
+        p_scb->num_seps = num;
+
+        if (p_scb->cur_psc_mask & AVDT_PSC_DELAY_RPT)
+            p_scb->avdt_version = AVDT_VERSION_SYNC;
+
+
+        if (p_scb->codec_type == BTA_AV_CODEC_SBC || num > 1)
+        {
+            /* if SBC is used by the SNK as INT, discover req is not sent in bta_av_config_ind.
+             * call disc_res now */
+            p_scb->p_cos->disc_res(p_scb->hndl, num, num, p_scb->peer_addr);
+        }
+        else
+        {
+            /* we do not know the peer device and it is using non-SBC codec
+             * we need to know all the SEPs on SNK */
+            bta_av_discover_req(p_scb, NULL);
+            return;
+        }
+
+        for (i = 1; i < num; i++)
+        {
+            APPL_TRACE_DEBUG2("sep_info[%d] SEID: %d", i, p_seid[i-1]);
+            /* initialize the sep_info[] to get capabilities */
+            p_scb->sep_info[i].in_use = FALSE;
+            p_scb->sep_info[i].tsep = AVDT_TSEP_SNK;
+            p_scb->sep_info[i].media_type = p_scb->media_type;
+            p_scb->sep_info[i].seid = p_seid[i-1];
+        }
+        bta_av_next_getcap(p_scb, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_str_opened
+**
+** Description      Stream opened OK (incoming/outgoing).
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CONN_CHG msg;
+    tBTA_AV_OPEN    open;
+    UINT8 *p;
+    UINT16 mtu;
+
+    msg.hdr.layer_specific = p_scb->hndl;
+    msg.is_up = TRUE;
+    bdcpy(msg.peer_addr, p_scb->peer_addr);
+    p_scb->l2c_cid      = AVDT_GetL2CapChannel(p_scb->avdt_handle);
+    bta_av_conn_chg((tBTA_AV_DATA *) &msg);
+    /* set the congestion flag, so AV would not send media packets by accident */
+    p_scb->cong = TRUE;
+
+
+    p_scb->stream_mtu = p_data->str_msg.msg.open_ind.peer_mtu - AVDT_MEDIA_HDR_SIZE;
+    mtu = bta_av_chk_mtu(p_scb, p_scb->stream_mtu);
+    APPL_TRACE_DEBUG3("bta_av_str_opened l2c_cid: 0x%x stream_mtu: %d mtu: %d",
+        p_scb->l2c_cid, p_scb->stream_mtu, mtu);
+    if(mtu == 0 || mtu > p_scb->stream_mtu)
+        mtu = p_scb->stream_mtu;
+
+    /* Set the media channel as medium priority */
+    L2CA_SetTxPriority(p_scb->l2c_cid, L2CAP_CHNL_PRIORITY_MEDIUM);
+    L2CA_SetChnlFlushability (p_scb->l2c_cid, TRUE);
+
+    bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+    memset(&p_scb->q_info, 0, sizeof(tBTA_AV_Q_INFO));
+
+    p_scb->l2c_bufs = 0;
+    p_scb->p_cos->open(p_scb->hndl,
+        p_scb->codec_type, p_scb->cfg.codec_info, mtu);
+
+    {
+        /* TODO check if other audio channel is open.
+         * If yes, check if reconfig is needed
+         * Rigt now we do not do this kind of checking.
+         * BTA-AV is INT for 2nd audio connection.
+         * The application needs to make sure the current codec_info is proper.
+         * If one audio connection is open and another SNK attempts to connect to AV,
+         * the connection will be rejected.
+         */
+        /* check if other audio channel is started. If yes, start */
+        bdcpy(open.bd_addr, p_scb->peer_addr);
+        open.chnl   = p_scb->chnl;
+        open.hndl   = p_scb->hndl;
+        open.status = BTA_AV_SUCCESS;
+        open.starting = bta_av_chk_start(p_scb);
+        open.edr    = 0;
+        if( NULL != (p = BTM_ReadRemoteFeatures(p_scb->peer_addr)))
+        {
+            if(HCI_EDR_ACL_2MPS_SUPPORTED(p))
+                open.edr |= BTA_AV_EDR_2MBPS;
+            if(HCI_EDR_ACL_3MPS_SUPPORTED(p))
+                open.edr |= BTA_AV_EDR_3MBPS;
+        }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+        bta_ar_avdt_conn(BTA_ID_AV, open.bd_addr);
+#endif
+        (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
+        if(open.starting)
+        {
+            bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_security_ind
+**
+** Description      Handle an AVDTP security indication.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_security_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_PROTECT_REQ protect_req;
+
+    p_scb->avdt_label = p_data->str_msg.msg.hdr.label;
+
+    if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+    {
+        protect_req.chnl    = p_scb->chnl;
+        protect_req.hndl    = p_scb->hndl;
+        /*
+        APPL_TRACE_EVENT1("sec ind handle: x%x", protect_req.hndl);
+        */
+        protect_req.p_data  = p_data->str_msg.msg.security_ind.p_data;
+        protect_req.len     = p_data->str_msg.msg.security_ind.len;
+
+        (*bta_av_cb.p_cback)(BTA_AV_PROTECT_REQ_EVT, (tBTA_AV *) &protect_req);
+    }
+    /* app doesn't support security indication; respond with failure */
+    else
+    {
+        AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_NSC, NULL, 0);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_security_cfm
+**
+** Description      Handle an AVDTP security confirm.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_security_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_PROTECT_RSP protect_rsp;
+
+    if (bta_av_cb.features & BTA_AV_FEAT_PROTECT)
+    {
+        protect_rsp.chnl    = p_scb->chnl;
+        protect_rsp.hndl    = p_scb->hndl;
+        protect_rsp.p_data  = p_data->str_msg.msg.security_cfm.p_data;
+        protect_rsp.len     = p_data->str_msg.msg.security_cfm.len;
+        protect_rsp.err_code= p_data->str_msg.msg.hdr.err_code;
+
+        (*bta_av_cb.p_cback)(BTA_AV_PROTECT_RSP_EVT, (tBTA_AV *) &protect_rsp);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_do_close
+**
+** Description      Close stream.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    /* stop stream if started */
+    if (p_scb->co_started)
+    {
+        bta_av_str_stopped(p_scb, NULL);
+    }
+    bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+
+    /* close stream */
+    p_scb->started = FALSE;
+
+    /* drop the buffers queued in L2CAP */
+    L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+    AVDT_CloseReq(p_scb->avdt_handle);
+    /* just in case that the link is congested, link is flow controled by peer or
+     * for whatever reason the the close request can not be sent in time.
+     * when this timer expires, AVDT_DisconnectReq will be called to disconnect the link
+     */
+    bta_sys_start_timer(&p_scb->timer,
+                        (UINT16)BTA_AV_API_CLOSE_EVT,
+                        BTA_AV_CLOSE_REQ_TIME_VAL);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_connect_req
+**
+** Description      Connect AVDTP connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    utl_freebuf((void **) &p_scb->p_disc_db);
+
+    if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+    {
+        /* SNK initiated L2C connection while SRC was doing SDP.    */
+        /* Wait until timeout to check if SNK starts signalling.    */
+        APPL_TRACE_EVENT1("bta_av_connect_req: coll_mask = 0x%2X", p_scb->coll_mask);
+        return;
+    }
+
+    AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sdp_failed
+**
+** Description      Service discovery failed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    if (!p_scb->open_status)
+        p_scb->open_status = BTA_AV_FAIL_SDP;
+
+    utl_freebuf((void **) &p_scb->p_disc_db);
+    bta_av_str_closed(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_disc_results
+**
+** Description      Handle the AVDTP discover results.  Search through the
+**                  results and find the first available stream, and get
+**                  its capabilities.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8 num_snks = 0, i;
+
+    /* store number of stream endpoints returned */
+    p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
+
+    for (i = 0; i < p_scb->num_seps; i++)
+    {
+        /* steam not in use, is a sink, and is audio */
+        if ((p_scb->sep_info[i].in_use == FALSE) &&
+            (p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+            (p_scb->sep_info[i].media_type == p_scb->media_type))
+        {
+            num_snks++;
+        }
+    }
+
+    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+    p_scb->num_disc_snks = num_snks;
+
+    /* if we got any */
+    if (p_scb->num_seps > 0)
+    {
+        /* initialize index into discovery results */
+        p_scb->sep_info_idx = 0;
+
+        /* get the capabilities of the first available stream */
+        bta_av_next_getcap(p_scb, p_data);
+    }
+    /* else we got discover response but with no streams; we're done */
+    else
+    {
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_disc_res_as_acp
+**
+** Description      Handle the AVDTP discover results.  Search through the
+**                  results and find the first available stream, and get
+**                  its capabilities.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_disc_res_as_acp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8 num_snks = 0, i;
+
+    /* store number of stream endpoints returned */
+    p_scb->num_seps = p_data->str_msg.msg.discover_cfm.num_seps;
+
+
+
+    for (i = 0; i < p_scb->num_seps; i++)
+    {
+        /* steam is a sink, and is audio */
+        if ((p_scb->sep_info[i].tsep == AVDT_TSEP_SNK) &&
+            (p_scb->sep_info[i].media_type == p_scb->media_type))
+        {
+            p_scb->sep_info[i].in_use = FALSE;
+            num_snks++;
+        }
+    }
+
+    p_scb->p_cos->disc_res(p_scb->hndl, p_scb->num_seps, num_snks, p_scb->peer_addr);
+    p_scb->num_disc_snks = num_snks;
+
+    /* if we got any */
+    if (p_scb->num_seps > 0)
+    {
+        /* initialize index into discovery results */
+        p_scb->sep_info_idx = 0;
+
+        /* get the capabilities of the first available stream */
+        bta_av_next_getcap(p_scb, p_data);
+    }
+    /* else we got discover response but with no streams; we're done */
+    else
+    {
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_save_caps
+**
+** Description      report the SNK SEP capabilities to application
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_save_caps(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tAVDT_CFG   cfg;
+    tAVDT_SEP_INFO  *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
+    UINT8       old_wait = p_scb->wait;
+    BOOLEAN     getcap_done = FALSE;
+
+    APPL_TRACE_DEBUG3("bta_av_save_caps num_seps:%d sep_info_idx:%d wait:x%x",
+        p_scb->num_seps, p_scb->sep_info_idx, p_scb->wait);
+    memcpy(&cfg, p_scb->p_cap, sizeof(tAVDT_CFG));
+    /* let application know the capability of the SNK */
+    p_scb->p_cos->getcfg(p_scb->hndl, cfg.codec_info[BTA_AV_CODEC_TYPE_IDX],
+        cfg.codec_info, &p_scb->sep_info_idx, p_info->seid,
+        &cfg.num_protect, cfg.protect_info);
+
+    p_scb->sep_info_idx++;
+    if(p_scb->num_seps > p_scb->sep_info_idx)
+    {
+        /* Some devices have seps at the end of the discover list, which is not */
+        /* matching media type(video not audio).                                */
+        /* In this case, we are done with getcap without sending another        */
+        /* request to AVDT.                                                     */
+        if (!bta_av_next_getcap(p_scb, p_data))
+            getcap_done = TRUE;
+    }
+    else
+        getcap_done = TRUE;
+
+    if (getcap_done)
+    {
+        /* we are done getting capabilities. restore the p_cb->sep_info_idx */
+        p_scb->sep_info_idx = 0;
+        p_scb->wait &= ~(BTA_AV_WAIT_ACP_CAPS_ON|BTA_AV_WAIT_ACP_CAPS_STARTED);
+        if (old_wait & BTA_AV_WAIT_ACP_CAPS_STARTED)
+        {
+            bta_av_start_ok (p_scb, NULL);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_set_use_rc
+**
+** Description      set to use AVRC for this stream control block.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_set_use_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    p_scb->use_rc = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_cco_close
+**
+** Description      call close call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_cco_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT16 mtu;
+    mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
+
+    p_scb->p_cos->close(p_scb->hndl, p_scb->codec_type, mtu);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_open_failed
+**
+** Description      Failed to open an AVDT stream
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    p_scb->open_status = BTA_AV_FAIL_STREAM;
+    bta_av_cco_close(p_scb, p_data);
+    AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_getcap_results
+**
+** Description      Handle the AVDTP get capabilities results.  Check the codec
+**                  type and see if it matches ours.  If it does not, get the
+**                  capabilities of the next stream, if any.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tAVDT_CFG   cfg;
+    UINT8       media_type;
+    tAVDT_SEP_INFO  *p_info = &p_scb->sep_info[p_scb->sep_info_idx];
+
+    memcpy(&cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
+    cfg.num_codec = 1;
+    cfg.num_protect = p_scb->p_cap->num_protect;
+    memcpy(cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
+    memcpy(cfg.protect_info, p_scb->p_cap->protect_info, AVDT_PROTECT_SIZE);
+    media_type = p_scb->p_cap->codec_info[BTA_AV_MEDIA_TYPE_IDX] >> 4;
+
+    APPL_TRACE_DEBUG1("num_codec %d", p_scb->p_cap->num_codec);
+    APPL_TRACE_DEBUG2("media type x%x, x%x", media_type, p_scb->media_type);
+#if AVDT_MULTIPLEXING == TRUE
+    APPL_TRACE_DEBUG2("mux x%x, x%x", cfg.mux_mask, p_scb->p_cap->mux_mask);
+#endif
+
+    /* if codec present and we get a codec configuration */
+    if ((p_scb->p_cap->num_codec != 0) &&
+        (media_type == p_scb->media_type) &&
+        (p_scb->p_cos->getcfg(p_scb->hndl, p_scb->p_cap->codec_info[BTA_AV_CODEC_TYPE_IDX],
+            cfg.codec_info, &p_scb->sep_info_idx, p_info->seid,
+            &cfg.num_protect, cfg.protect_info) == 0))
+    {
+#if AVDT_MULTIPLEXING == TRUE
+        cfg.mux_mask &= p_scb->p_cap->mux_mask;
+        APPL_TRACE_DEBUG1("mux_mask used x%x", cfg.mux_mask);
+#endif
+        /* save copy of codec type and configuration */
+        p_scb->codec_type = cfg.codec_info[BTA_AV_CODEC_TYPE_IDX];
+        memcpy(&p_scb->cfg, &cfg, sizeof(tAVDT_CFG));
+        bta_av_adjust_seps_idx(p_scb);
+        /* use only the services peer supports */
+        cfg.psc_mask &= p_scb->p_cap->psc_mask;
+        p_scb->cur_psc_mask = cfg.psc_mask;
+
+        /* open the stream */
+        AVDT_OpenReq(p_scb->seps[p_scb->sep_idx].av_handle, p_scb->peer_addr,
+                     p_scb->sep_info[p_scb->sep_info_idx].seid, &cfg);
+
+        if (!bta_av_is_rcfg_sst(p_scb))
+        {
+            /* free capabilities buffer */
+            utl_freebuf((void **) &p_scb->p_cap);
+        }
+    }
+    else
+    {
+        /* try the next stream, if any */
+        p_scb->sep_info_idx++;
+        bta_av_next_getcap(p_scb, p_data);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_setconfig_rej
+**
+** Description      Send AVDTP set config reject.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_setconfig_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_REJECT reject;
+
+    APPL_TRACE_DEBUG0("bta_av_setconfig_rej");
+    AVDT_ConfigRsp(p_data->str_msg.handle, p_data->str_msg.msg.hdr.label, AVDT_ERR_BAD_STATE, 0);
+    bdcpy(reject.bd_addr, p_data->str_msg.bd_addr);
+    reject.hndl = p_scb->hndl;
+    (*bta_av_cb.p_cback)(BTA_AV_REJECT_EVT, (tBTA_AV *) &reject);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_discover_req
+**
+** Description      Send an AVDTP discover request to the peer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_discover_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    /* send avdtp discover request */
+
+    AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_conn_failed
+**
+** Description      AVDTP connection failed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_conn_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    p_scb->open_status = BTA_AV_FAIL_STREAM;
+    bta_av_str_closed(p_scb, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_do_start
+**
+** Description      Start stream.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+    UINT8       cur_role;
+
+    APPL_TRACE_DEBUG3("bta_av_do_start sco_occupied:%d, role:x%x, started:%d", bta_av_cb.sco_occupied, p_scb->role, p_scb->started);
+    if (bta_av_cb.sco_occupied)
+    {
+        bta_av_start_failed(p_scb, p_data);
+        return;
+    }
+
+    /* disallow role switch during streaming, only if we are the master role
+     * i.e. allow role switch, if we are slave.
+     * It would not hurt us, if the peer device wants us to be master */
+    if ((BTM_GetRole (p_scb->peer_addr, &cur_role) == BTM_SUCCESS) &&
+        (cur_role == BTM_ROLE_MASTER) )
+    {
+        policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+    }
+
+    bta_sys_clear_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+    if ((p_scb->started == FALSE) && ((p_scb->role & BTA_AV_ROLE_START_INT) == 0))
+    {
+        p_scb->role |= BTA_AV_ROLE_START_INT;
+        bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+
+        AVDT_StartReq(&p_scb->avdt_handle, 1);
+    }
+    else
+    {
+        bta_av_start_ok(p_scb, NULL);
+    }
+    APPL_TRACE_DEBUG2("started %d role:x%x", p_scb->started, p_scb->role);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_str_stopped
+**
+** Description      Stream stopped.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SUSPEND suspend_rsp;
+    UINT8   start = p_scb->started;
+    BOOLEAN sus_evt = TRUE;
+    BT_HDR  *p_buf;
+    UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+    APPL_TRACE_ERROR2("bta_av_str_stopped:audio_open_cnt=%d, p_data %x",
+            bta_av_cb.audio_open_cnt, p_data);
+
+    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+        policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+    bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+    if(p_scb->co_started)
+    {
+        bta_av_stream_chg(p_scb, FALSE);
+        p_scb->co_started = FALSE;
+
+        p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+        L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+    }
+
+    /* if q_info.a2d is not empty, drop it now */
+    if(BTA_AV_CHNL_AUDIO == p_scb->chnl)
+    {
+        while((p_buf = (BT_HDR*)GKI_dequeue (&p_scb->q_info.a2d)) != NULL)
+        GKI_freebuf(p_buf);
+
+    /* drop the audio buffers queued in L2CAP */
+        if(p_data && p_data->api_stop.flush)
+            L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+    }
+
+    suspend_rsp.chnl = p_scb->chnl;
+    suspend_rsp.hndl = p_scb->hndl;
+
+    if (p_data && p_data->api_stop.suspend)
+    {
+        APPL_TRACE_DEBUG2("suspending: %d, sup:%d", start, p_scb->suspend_sup);
+        if ((start)  && (p_scb->suspend_sup))
+        {
+            sus_evt = FALSE;
+            p_scb->l2c_bufs = 0;
+            AVDT_SuspendReq(&p_scb->avdt_handle, 1);
+        }
+
+        if(sus_evt)
+        {
+            suspend_rsp.status = BTA_AV_SUCCESS;
+            suspend_rsp.initiator = TRUE;
+            (*bta_av_cb.p_cback)(BTA_AV_SUSPEND_EVT, (tBTA_AV *) &suspend_rsp);
+        }
+    }
+    else
+    {
+        suspend_rsp.status = BTA_AV_SUCCESS;
+        suspend_rsp.initiator = TRUE;
+        APPL_TRACE_EVENT1("bta_av_str_stopped status %d", suspend_rsp.status);
+
+        (*bta_av_cb.p_cback)(BTA_AV_STOP_EVT, (tBTA_AV *) &suspend_rsp);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_reconfig
+**
+** Description      process the reconfigure request.
+**                  save the parameter in control block and
+**                  suspend, reconfigure or close the stream
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tAVDT_CFG   *p_cfg;
+    tBTA_AV_API_STOP    stop;
+    tBTA_AV_RECONFIG    evt;
+    tBTA_AV_API_RCFG    *p_rcfg = &p_data->api_reconfig;
+
+    APPL_TRACE_DEBUG4("bta_av_reconfig r:%d, s:%d idx: %d (o:%d)",
+        p_scb->recfg_sup, p_scb->suspend_sup,
+        p_scb->rcfg_idx, p_scb->sep_info_idx);
+
+    p_scb->num_recfg = 0;
+    /* store the new configuration in control block */
+    if (p_scb->p_cap == NULL)
+    {
+        p_scb->p_cap = (tAVDT_CFG *) GKI_getbuf(sizeof(tAVDT_CFG));
+    }
+    if((p_cfg = p_scb->p_cap) == NULL)
+    {
+        /* report failure */
+        evt.status = BTA_AV_FAIL_RESOURCES;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+
+        /* this event is not possible in this state.
+         * use it to bring the SSM back to open state */
+        bta_av_ssm_execute(p_scb, BTA_AV_SDP_DISC_OK_EVT, NULL);
+        return;
+    }
+
+    /*if(bta_av_cb.features & BTA_AV_FEAT_RCCT)*/
+        bta_sys_stop_timer(&p_scb->timer);
+
+    memcpy(p_cfg, &p_scb->cfg, sizeof(tAVDT_CFG));
+    p_cfg->num_protect = p_rcfg->num_protect;
+    memcpy(p_cfg->codec_info, p_rcfg->codec_info, AVDT_CODEC_SIZE);
+    memcpy(p_cfg->protect_info, p_rcfg->p_protect_info, p_rcfg->num_protect);
+    p_scb->rcfg_idx = p_rcfg->sep_info_idx;
+    p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+
+    /* if the requested index differs from the current one, we can only close/open */
+    if ((p_scb->rcfg_idx == p_scb->sep_info_idx) &&
+        (p_rcfg->suspend)&& (p_scb->recfg_sup) && (p_scb->suspend_sup))
+    {
+        if(p_scb->started)
+        {
+            stop.flush   = FALSE;
+            stop.suspend = TRUE;
+            bta_av_str_stopped(p_scb, (tBTA_AV_DATA *)&stop);
+        }
+        else
+        {
+            APPL_TRACE_DEBUG0("Reconfig");
+            AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
+            p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+        }
+    }
+    else
+    {
+        /* close the stream */
+        APPL_TRACE_DEBUG1("close/open num_protect: %d", p_cfg->num_protect);
+        if(p_scb->started)
+            bta_av_str_stopped(p_scb, NULL);
+            p_scb->started = FALSE;
+
+            /* drop the buffers queued in L2CAP */
+            L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+            AVDT_CloseReq(p_scb->avdt_handle);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_data_path
+**
+** Description      Handle stream data path.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    BT_HDR  *p_buf;
+    UINT32  data_len;
+    UINT32  timestamp;
+    BOOLEAN new_buf = FALSE;
+    UINT8   m_pt = 0x60 | p_scb->codec_type;
+
+    if (!p_scb->cong)
+    {
+        /*
+        APPL_TRACE_ERROR1("q: %d", p_scb->l2c_bufs);
+        */
+        //Always get the current number of bufs que'd up
+        p_scb->l2c_bufs = (UINT8)L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_GET);
+
+        p_buf = (BT_HDR *)GKI_dequeue (&p_scb->q_info.a2d);
+        if(p_buf)
+        {
+            /* use q_info.a2d data, read the timestamp */
+            timestamp = *(UINT32 *)(p_buf + 1);
+        }
+        else
+        {
+            new_buf = TRUE;
+            /* q_info.a2d empty, call co_data, dup data to other channels */
+            p_buf = (BT_HDR *)p_scb->p_cos->data(p_scb->codec_type, &data_len,
+                                             &timestamp);
+
+            if (p_buf)
+            {
+                /* use the offset area for the time stamp */
+                *(UINT32 *)(p_buf + 1) = timestamp;
+
+                /* dup the data to other channels */
+                bta_av_dup_audio_buf(p_scb, p_buf);
+            }
+        }
+
+        if(p_buf)
+        {
+            if(p_scb->l2c_bufs < (BTA_AV_QUEUE_DATA_CHK_NUM))
+            {
+                /* there's a buffer, just queue it to L2CAP */
+                /*  There's no need to increment it here, it is always read from L2CAP see above */
+                /* p_scb->l2c_bufs++; */
+                /*
+                APPL_TRACE_ERROR1("qw: %d", p_scb->l2c_bufs);
+                */
+                AVDT_WriteReq(p_scb->avdt_handle, p_buf, timestamp, m_pt);
+                p_scb->cong = TRUE;
+            }
+            else
+            {
+                /* there's a buffer, but L2CAP does not seem to be moving data */
+                if(new_buf)
+                {
+                    /* just got this buffer from co_data,
+                     * put it in queue */
+                    GKI_enqueue(&p_scb->q_info.a2d, p_buf);
+                }
+                else
+                {
+                    /* just dequeue it from the q_info.a2d */
+                    if(p_scb->q_info.a2d.count < 3)
+                    {
+                        /* put it back to the queue */
+                        GKI_enqueue_head (&p_scb->q_info.a2d, p_buf);
+                    }
+                    else
+                    {
+                        /* too many buffers in q_info.a2d, drop it. */
+                        bta_av_co_audio_drop(p_scb->hndl);
+                        GKI_freebuf(p_buf);
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_start_ok
+**
+** Description      Stream started.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_START   start;
+    tBTA_AV_API_STOP stop;
+    BOOLEAN         initiator = FALSE;
+    BOOLEAN         suspend = FALSE;
+    UINT16          flush_to;
+    UINT8           new_role = p_scb->role;
+    BT_HDR          hdr;
+
+    APPL_TRACE_DEBUG2("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
+
+    p_scb->started = TRUE;
+    if (p_scb->sco_suspend)
+    {
+        p_scb->sco_suspend = FALSE;
+    }
+
+    if (new_role & BTA_AV_ROLE_START_INT)
+        initiator = TRUE;
+
+    if (p_scb->wait & BTA_AV_WAIT_ROLE_SW_FAILED)
+    {
+        /* role switch has failed */
+        p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_FAILED;
+        p_data = (tBTA_AV_DATA *)&hdr;
+        hdr.offset = BTA_AV_RS_FAIL;
+    }
+    APPL_TRACE_DEBUG1("wait:x%x", p_scb->wait);
+
+    if (p_data && (p_data->hdr.offset != BTA_AV_RS_NONE))
+    {
+        p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+        if (p_data->hdr.offset == BTA_AV_RS_FAIL)
+        {
+            bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+            start.chnl   = p_scb->chnl;
+            start.status = BTA_AV_FAIL_ROLE;
+            start.hndl   = p_scb->hndl;
+            start.initiator = initiator;
+            (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+            return;
+        }
+    }
+
+    if (!bta_av_link_role_ok(p_scb, A2D_SET_ONE_BIT))
+        p_scb->q_tag = BTA_AV_Q_TAG_START;
+    else
+    {
+        /* The wait flag may be set here while we are already master on the link */
+        /* this could happen if a role switch complete event occurred during reconfig */
+        /* if we are now master on the link, there is no need to wait for the role switch, */
+        /* complete anymore so we can clear the wait for role switch flag */
+        p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+    }
+
+    if (p_scb->wait & (BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START))
+    {
+        p_scb->wait |= BTA_AV_WAIT_ROLE_SW_STARTED;
+        p_scb->q_tag = BTA_AV_Q_TAG_START;
+    }
+
+    if (p_scb->wait & BTA_AV_WAIT_ACP_CAPS_ON)
+    {
+        p_scb->wait |= BTA_AV_WAIT_ACP_CAPS_STARTED;
+    }
+
+    if (p_scb->wait)
+    {
+        APPL_TRACE_DEBUG2("wait:x%x q_tag:%d- not started", p_scb->wait, p_scb->q_tag);
+        return;
+    }
+
+    /* tell role manager to check M/S role */
+    bta_sys_conn_open(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+
+    bta_sys_busy(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+
+    if(p_scb->media_type == AVDT_MEDIA_AUDIO)
+    {
+        /* in normal logic, conns should be bta_av_cb.audio_count - 1,
+         * However, bta_av_stream_chg is not called to increase bta_av_cb.audio_count yet.
+         * If the code were to be re-arranged for some reasons, this number may need to be changed
+         */
+        p_scb->co_started = bta_av_cb.audio_open_cnt;
+        flush_to = p_bta_av_cfg->p_audio_flush_to[p_scb->co_started - 1];
+    }
+    else
+    {
+        flush_to = p_bta_av_cfg->video_flush_to;
+    }
+    L2CA_SetFlushTimeout(p_scb->peer_addr, flush_to );
+
+    /* clear the congestion flag */
+    p_scb->cong = FALSE;
+
+    if (new_role & BTA_AV_ROLE_START_INT)
+    {
+        new_role &= ~BTA_AV_ROLE_START_INT;
+    }
+    else if ((new_role & BTA_AV_ROLE_AD_ACP) && (new_role & BTA_AV_ROLE_SUSPEND_OPT))
+    {
+        suspend = TRUE;
+    }
+
+    if (!suspend)
+    {
+        p_scb->q_tag = BTA_AV_Q_TAG_STREAM;
+        bta_av_stream_chg(p_scb, TRUE);
+    }
+
+    {
+        p_scb->role = new_role;
+        p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
+        p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
+
+        p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type);
+        p_scb->co_started = TRUE;
+
+        APPL_TRACE_DEBUG3("bta_av_start_ok suspending: %d, role:x%x, init %d",
+            suspend, p_scb->role, initiator);
+
+        start.suspending = suspend;
+        start.initiator = initiator;
+        start.chnl   = p_scb->chnl;
+        start.status = BTA_AV_SUCCESS;
+        start.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+
+        if(suspend)
+        {
+            p_scb->role |= BTA_AV_ROLE_SUSPEND;
+            p_scb->cong = TRUE;  /* do not allow the media data to go through */
+            /* do not duplicate the media packets to this channel */
+            p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+            p_scb->co_started = FALSE;
+            stop.flush   = FALSE;
+            stop.suspend = TRUE;
+            bta_av_ssm_execute(p_scb, BTA_AV_AP_STOP_EVT, (tBTA_AV_DATA *)&stop);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_start_failed
+**
+** Description      Stream start failed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_START   start;
+
+    if(p_scb->started == FALSE && p_scb->co_started == FALSE)
+    {
+        /* if start failed, clear role */
+        p_scb->role &= ~BTA_AV_ROLE_START_INT;
+
+        bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+        start.chnl   = p_scb->chnl;
+        start.status = BTA_AV_FAIL;
+        start.initiator = TRUE;
+        start.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+    }
+
+    bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_SNIFF_MODE|HCI_ENABLE_MASTER_SLAVE_SWITCH), p_scb->peer_addr);
+    p_scb->sco_suspend = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_str_closed
+**
+** Description      Stream closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV     data;
+    tBTA_AV_EVT event;
+    UINT16      mtu;
+    UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+    if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+        policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+    bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+    if (bta_av_cb.audio_open_cnt <= 1)
+    {
+        /* last connection - restore the allow switch flag */
+        L2CA_SetDesireRole(L2CAP_ROLE_ALLOW_SWITCH);
+    }
+
+    if (p_scb->open_status)
+    {
+        /* must be failure when opening the stream */
+        bdcpy(data.open.bd_addr, p_scb->peer_addr);
+        data.open.status = p_scb->open_status;
+        data.open.chnl   = p_scb->chnl;
+        data.open.hndl   = p_scb->hndl;
+        event = BTA_AV_OPEN_EVT;
+        p_scb->open_status = BTA_AV_SUCCESS;
+
+        bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+        bta_av_cleanup(p_scb, p_data);
+        (*bta_av_cb.p_cback)(event, &data);
+    }
+    else
+    {
+        /* do stop if we were started */
+        if (p_scb->co_started)
+        {
+            bta_av_str_stopped(p_scb, NULL);
+        }
+
+        /* Update common mtu shared by remaining connectons */
+        mtu = bta_av_chk_mtu(p_scb, BTA_AV_MAX_A2DP_MTU);
+
+        {
+            p_scb->p_cos->close(p_scb->hndl, p_scb->codec_type, mtu);
+            data.close.chnl = p_scb->chnl;
+            data.close.hndl = p_scb->hndl;
+            event = BTA_AV_CLOSE_EVT;
+
+            bta_sys_conn_close(BTA_ID_AV, p_scb->app_id, p_scb->peer_addr);
+            bta_av_cleanup(p_scb, p_data);
+            (*bta_av_cb.p_cback)(event, &data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_clr_cong
+**
+** Description      Clear stream congestion flag.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_clr_cong (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    if(p_scb->co_started)
+        p_scb->cong = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_suspend_cfm
+**
+** Description      process the suspend response
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SUSPEND suspend_rsp;
+    UINT8           err_code = p_data->str_msg.msg.hdr.err_code;
+    UINT8 policy = HCI_ENABLE_SNIFF_MODE;
+
+    APPL_TRACE_DEBUG2 ("bta_av_suspend_cfm:audio_open_cnt = %d, err_code = %d",
+        bta_av_cb.audio_open_cnt, err_code);
+
+    suspend_rsp.status = BTA_AV_SUCCESS;
+    if(err_code)
+    {
+        p_scb->suspend_sup = FALSE;
+        suspend_rsp.status = BTA_AV_FAIL;
+
+        APPL_TRACE_ERROR0 ("bta_av_suspend_cfm: suspend failed, closing connection");
+
+        /* SUSPEND failed. Close connection. */
+        bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, NULL);
+    }
+    else
+    {
+        /* only set started to FALSE when suspend is successful */
+        p_scb->started = FALSE;
+    }
+
+    if(p_scb->role & BTA_AV_ROLE_SUSPEND)
+    {
+        p_scb->role &= ~BTA_AV_ROLE_SUSPEND;
+        p_scb->cong = FALSE;
+    }
+
+    bta_sys_idle(BTA_ID_AV, bta_av_cb.audio_open_cnt, p_scb->peer_addr);
+    if ((bta_av_cb.features & BTA_AV_FEAT_MASTER) == 0 || bta_av_cb.audio_open_cnt == 1)
+        policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+    bta_sys_set_policy(BTA_ID_AV, policy, p_scb->peer_addr);
+
+    /* in case that we received suspend_ind, we may need to call co_stop here */
+    if(p_scb->co_started)
+    {
+        bta_av_stream_chg(p_scb, FALSE);
+
+        {
+            p_scb->co_started = FALSE;
+            p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+        }
+        L2CA_SetFlushTimeout(p_scb->peer_addr, L2CAP_DEFAULT_FLUSH_TO);
+    }
+
+    {
+        suspend_rsp.chnl = p_scb->chnl;
+        suspend_rsp.hndl = p_scb->hndl;
+        suspend_rsp.initiator = p_data->str_msg.initiator;
+        (*bta_av_cb.p_cback)(BTA_AV_SUSPEND_EVT, (tBTA_AV *) &suspend_rsp);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_str_ok
+**
+** Description      report reconfigure successful
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_str_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RECONFIG    evt;
+
+    p_scb->l2c_cid      = AVDT_GetL2CapChannel(p_scb->avdt_handle);
+    APPL_TRACE_DEBUG1("bta_av_rcfg_str_ok: l2c_cid: %d", p_scb->l2c_cid);
+
+    /* rc listen */
+    bta_av_st_rc_timer(p_scb, NULL);
+    utl_freebuf((void **)&p_scb->p_cap);
+
+    /* No need to keep the role bits once reconfig is done. */
+    p_scb->role &= ~BTA_AV_ROLE_AD_ACP;
+    p_scb->role &= ~BTA_AV_ROLE_SUSPEND_OPT;
+    p_scb->role &= ~BTA_AV_ROLE_START_INT;
+
+    {
+        /* reconfigure success  */
+        evt.status = BTA_AV_SUCCESS;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_failed
+**
+** Description      process reconfigure failed
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RECONFIG evt;
+
+    APPL_TRACE_DEBUG2("bta_av_rcfg_failed num_recfg: %d, conn_lcb:0x%x",
+        p_scb->num_recfg, bta_av_cb.conn_lcb);
+    if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+    {
+        bta_av_cco_close(p_scb, p_data);
+        /* report failure */
+        evt.status = BTA_AV_FAIL_STREAM;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+        /* go to closing state */
+        bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, NULL);
+    }
+    else
+    {
+        /* open failed. try again */
+        p_scb->num_recfg++;
+        if(bta_av_cb.conn_lcb)
+        {
+            AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+        }
+        else
+        {
+            bta_av_connect_req(p_scb, NULL);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_connect
+**
+** Description      stream closed. reconnect the stream
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_connect (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    p_scb->cong    = FALSE;
+    p_scb->num_recfg++;
+    APPL_TRACE_DEBUG1("bta_av_rcfg_connect num_recfg: %d", p_scb->num_recfg);
+    if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+    {
+        /* let bta_av_rcfg_failed report fail */
+        bta_av_rcfg_failed(p_scb, NULL);
+    }
+    else
+        AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_discntd
+**
+** Description      AVDT disconnected. reconnect the stream
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_discntd (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RECONFIG    evt;
+
+    APPL_TRACE_DEBUG1("bta_av_rcfg_discntd num_recfg: %d", p_scb->num_recfg);
+    p_scb->num_recfg++;
+    if(p_scb->num_recfg > BTA_AV_RECONFIG_RETRY)
+    {
+        /* report failure */
+        evt.status = BTA_AV_FAIL_STREAM;
+        evt.chnl   = p_scb->chnl;
+        evt.hndl   = p_scb->hndl;
+        (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+        /* report close event & go to init state */
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
+    }
+    else
+        AVDT_ConnectReq(p_scb->peer_addr, p_scb->sec_mask, bta_av_dt_cback[p_scb->hdi]);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_suspend_cont
+**
+** Description      received the suspend response.
+**                  continue to reconfigure the stream
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8       err_code = p_data->str_msg.msg.hdr.err_code;
+    tBTA_AV_RECONFIG    evt;
+
+    p_scb->started = FALSE;
+    p_scb->cong    = FALSE;
+    if(err_code)
+    {
+        if(AVDT_ERR_CONNECT == err_code)
+        {
+            /* report failure */
+            evt.status = BTA_AV_FAIL;
+            (*bta_av_cb.p_cback)(BTA_AV_RECONFIG_EVT, (tBTA_AV *)&evt);
+            bta_av_ssm_execute(p_scb, BTA_AV_STR_DISC_FAIL_EVT, NULL);
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("suspend rejected, try close");
+            p_scb->suspend_sup = FALSE;
+
+            /* drop the buffers queued in L2CAP */
+            L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+
+            AVDT_CloseReq(p_scb->avdt_handle);
+        }
+    }
+    else
+    {
+        APPL_TRACE_DEBUG0("bta_av_suspend_cont calling AVDT_ReconfigReq");
+        /* reconfig the stream */
+
+        AVDT_ReconfigReq(p_scb->avdt_handle, p_scb->p_cap);
+        p_scb->p_cap->psc_mask = p_scb->cur_psc_mask;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_cfm
+**
+** Description      if reconfigure is successful, report the event
+**                  otherwise, close the stream.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    UINT8   err_code = p_data->str_msg.msg.hdr.err_code;
+
+    /*
+    APPL_TRACE_DEBUG0("bta_av_rcfg_cfm");
+    */
+    if(err_code)
+    {
+        APPL_TRACE_ERROR0("reconfig rejected, try close");
+        p_scb->recfg_sup = FALSE;
+        /* started flag is FALSE when reconfigure command is sent */
+        /* drop the buffers queued in L2CAP */
+        L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
+        AVDT_CloseReq(p_scb->avdt_handle);
+    }
+    else
+    {
+        /* take the SSM back to OPEN state */
+        bta_av_ssm_execute(p_scb, BTA_AV_STR_OPEN_OK_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rcfg_open
+**
+** Description      AVDT is connected. open the stream with the new configuration
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    APPL_TRACE_DEBUG1("bta_av_rcfg_open, num_disc_snks = %d", p_scb->num_disc_snks);
+
+    if (p_scb->num_disc_snks == 0)
+    {
+        /* Need to update call-out module so that it will be ready for discover */
+        p_scb->p_cos->stop(p_scb->hndl, p_scb->codec_type);
+
+        /* send avdtp discover request */
+        AVDT_DiscoverReq(p_scb->peer_addr, p_scb->sep_info, BTA_AV_NUM_SEPS, bta_av_dt_cback[p_scb->hdi]);
+    }
+    else
+    {
+        p_scb->codec_type = p_scb->p_cap->codec_info[BTA_AV_CODEC_TYPE_IDX];
+        memcpy(p_scb->cfg.codec_info, p_scb->p_cap->codec_info, AVDT_CODEC_SIZE);
+        /* we may choose to use a different SEP at reconfig.
+         * adjust the sep_idx now */
+        bta_av_adjust_seps_idx(p_scb);
+
+        /* open the stream with the new config */
+        p_scb->sep_info_idx = p_scb->rcfg_idx;
+        AVDT_OpenReq(p_scb->avdt_handle, p_scb->peer_addr,
+                     p_scb->sep_info[p_scb->sep_info_idx].seid, p_scb->p_cap);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_security_rej
+**
+** Description      Send an AVDTP security reject.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_security_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    AVDT_SecurityRsp(p_scb->avdt_handle, p_scb->avdt_label, AVDT_ERR_BAD_STATE,
+                     NULL, 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_chk_2nd_start
+**
+** Description      check if this is 2nd stream and if it needs to be started.
+**                  This function needs to be kept very similar to bta_av_chk_start
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_chk_2nd_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SCB *p_scbi;
+    int i;
+    BOOLEAN new_started = FALSE;
+
+
+    if ((p_scb->chnl == BTA_AV_CHNL_AUDIO) && (bta_av_cb.audio_open_cnt >= 2))
+    {
+        /* more than one audio channel is connected */
+        if (!(p_scb->role & BTA_AV_ROLE_SUSPEND_OPT))
+        {
+            /* this channel does not need to be reconfigured.
+             * if there is other channel streaming, start the stream now */
+            for(i=0; i<BTA_AV_NUM_STRS; i++)
+            {
+                p_scbi = bta_av_cb.p_scb[i];
+                if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+                {
+                    if (!new_started)
+                    {
+                        /* start the new stream */
+                        new_started = TRUE;
+                        bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+                    }
+                    /* may need to update the flush timeout of this already started stream */
+                    if (p_scbi->co_started != bta_av_cb.audio_open_cnt)
+                    {
+                        p_scbi->co_started = bta_av_cb.audio_open_cnt;
+                        L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_open_rc
+**
+** Description      Send a message to main SM to open RC channel.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_open_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_START   start;
+
+    APPL_TRACE_DEBUG3("bta_av_open_rc use_rc: %d, wait: x%x role:x%x", p_scb->use_rc, p_scb->wait, p_scb->role);
+    if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) && (p_scb->q_tag == BTA_AV_Q_TAG_START))
+    {
+        /* waiting for role switch for some reason & the timer expires */
+        if (!bta_av_link_role_ok(p_scb, A2D_SET_ONE_BIT))
+        {
+            APPL_TRACE_ERROR0 ("failed to start streaming for role management reasons!!");
+            bta_sys_stop_timer(&p_scb->timer);
+            start.chnl   = p_scb->chnl;
+            start.status = BTA_AV_FAIL_ROLE;
+            start.initiator = TRUE;
+            start.hndl   = p_scb->hndl;
+            p_scb->wait &= ~BTA_AV_WAIT_ROLE_SW_BITS;
+            bta_av_cb.rs_idx = 0;
+            (*bta_av_cb.p_cback)(BTA_AV_START_EVT, (tBTA_AV *) &start);
+        }
+        else
+        {
+            /* role switch is done. continue to start streaming */
+            bta_av_cb.rs_idx = 0;
+            p_data->hdr.offset = BTA_AV_RS_OK;
+            bta_av_start_ok (p_scb, p_data);
+        }
+        return;
+    }
+
+    if(p_scb->use_rc == TRUE || (p_scb->role & BTA_AV_ROLE_AD_ACP) )
+    {
+        if(bta_av_cb.disc)
+        {
+            /* AVRC discover db is in use */
+            if(p_scb->rc_handle == BTA_AV_RC_HANDLE_NONE)
+            {
+                /* AVRC channel is not connected. delay a little bit */
+                if ((p_scb->wait & BTA_AV_WAIT_ROLE_SW_BITS) == 0)
+                    bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RC_DISC_TIME_VAL);
+                else
+                    p_scb->wait |= BTA_AV_WAIT_CHECK_RC;
+            }
+        }
+        else
+        {
+            /* use main SM for AVRC SDP activities */
+            bta_av_rc_disc((UINT8)(p_scb->hdi + 1));
+        }
+    }
+    else
+    {
+        if(BTA_AV_RC_HANDLE_NONE != p_scb->rc_handle)
+        {
+            /* the open API said that this handle does not want a RC connection.
+             * disconnect it now */
+            AVRC_Close(p_scb->rc_handle);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_open_at_inc
+**
+** Description      This function is called if API open is called by application
+**                  while state-machine is at incoming state.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_API_OPEN  *p_buf;
+
+    memcpy (&(p_scb->open_api), &(p_data->api_open), sizeof(tBTA_AV_API_OPEN));
+
+    if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+    {
+        p_scb->coll_mask |= BTA_AV_COLL_API_CALLED;
+
+        /* API open will be handled at timeout if SNK did not start signalling. */
+        /* API open will be ignored if SNK starts signalling.                   */
+    }
+    else
+    {
+        /* SNK did not start signalling, API was called N seconds timeout. */
+        /* We need to switch to INIT state and start opening connection. */
+        p_scb->coll_mask = 0;
+        bta_av_set_scb_sst_init (p_scb);
+
+        if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+        {
+            memcpy(p_buf, &(p_scb->open_api), sizeof(tBTA_AV_API_OPEN));
+            bta_sys_sendmsg(p_buf);
+        }
+    }
+}
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
new file mode 100644
index 0000000..a47921a
--- /dev/null
+++ b/bta/av/bta_av_act.c
@@ -0,0 +1,1941 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 action functions for advanced audio/video main state
+ *  machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_api.h"
+#include "bta_av_int.h"
+#include "avdt_api.h"
+#include "bd.h"
+#include "utl.h"
+#include "l2c_api.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+/* the timer in milliseconds to wait for open req after setconfig for incoming connections */
+#ifndef BTA_AV_SIG_TIME_VAL
+#define BTA_AV_SIG_TIME_VAL 8000
+#endif
+
+/* In millisec to wait for signalling from SNK when it is initiated from SNK.   */
+/* If not, we will start signalling from SRC.                                   */
+#ifndef BTA_AV_ACP_SIG_TIME_VAL
+#define BTA_AV_ACP_SIG_TIME_VAL 2000
+#endif
+
+static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle);
+
+/*******************************************************************************
+**
+** Function         bta_av_get_rcb_by_shdl
+**
+** Description      find the RCB associated with the given SCB handle.
+**
+** Returns          tBTA_AV_RCB
+**
+*******************************************************************************/
+tBTA_AV_RCB * bta_av_get_rcb_by_shdl(UINT8 shdl)
+{
+    tBTA_AV_RCB *p_rcb = NULL;
+    int         i;
+
+    for (i=0; i<BTA_AV_NUM_RCB; i++)
+    {
+        if (bta_av_cb.rcb[i].shdl == shdl && bta_av_cb.rcb[i].handle != BTA_AV_RC_HANDLE_NONE)
+        {
+            p_rcb = &bta_av_cb.rcb[i];
+            break;
+        }
+    }
+    return p_rcb;
+}
+#define BTA_AV_STS_NO_RSP       0xFF    /* a number not used by tAVRC_STS */
+
+/*******************************************************************************
+**
+** Function         bta_av_del_rc
+**
+** Description      delete the given AVRC handle.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_del_rc(tBTA_AV_RCB *p_rcb)
+{
+    tBTA_AV_SCB  *p_scb;
+    UINT8        rc_handle;      /* connected AVRCP handle */
+
+    if(p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+    {
+        if(p_rcb->shdl)
+        {
+            p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+            if(p_scb)
+            {
+                APPL_TRACE_DEBUG3("bta_av_del_rc shdl:%d, srch:%d rc_handle:%d", p_rcb->shdl,
+                                  p_scb->rc_handle, p_rcb->handle);
+                if(p_scb->rc_handle == p_rcb->handle)
+                    p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
+                /* just in case the RC timer is active
+                if(bta_av_cb.features & BTA_AV_FEAT_RCCT && p_scb->chnl == BTA_AV_CHNL_AUDIO) */
+                    bta_sys_stop_timer(&p_scb->timer);
+            }
+        }
+
+        APPL_TRACE_EVENT4("bta_av_del_rc  handle: %d status=0x%x, rc_acp_handle:%d, idx:%d",
+            p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, bta_av_cb.rc_acp_idx);
+        rc_handle = p_rcb->handle;
+        if(!(p_rcb->status & BTA_AV_RC_CONN_MASK) ||
+            ((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT) )
+        {
+            p_rcb->status = 0;
+            p_rcb->handle = BTA_AV_RC_HANDLE_NONE;
+            p_rcb->shdl = 0;
+            p_rcb->lidx = 0;
+        }
+        /* else ACP && connected. do not clear the handle yet */
+        AVRC_Close(rc_handle);
+        if (rc_handle == bta_av_cb.rc_acp_handle)
+            bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
+        APPL_TRACE_EVENT4("end del_rc handle: %d status=0x%x, rc_acp_handle:%d, lidx:%d",
+            p_rcb->handle, p_rcb->status, bta_av_cb.rc_acp_handle, p_rcb->lidx);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_av_close_all_rc
+**
+** Description      close the all AVRC handle.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_close_all_rc(tBTA_AV_CB *p_cb)
+{
+    int i;
+
+    for(i=0; i<BTA_AV_NUM_RCB; i++)
+    {
+        if ((p_cb->disabling == TRUE) || (bta_av_cb.rcb[i].shdl != 0))
+            bta_av_del_rc(&bta_av_cb.rcb[i]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_del_sdp_rec
+**
+** Description      delete the given SDP record handle.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_del_sdp_rec(UINT32 *p_sdp_handle)
+{
+    if(*p_sdp_handle != 0)
+    {
+        SDP_DeleteRecord(*p_sdp_handle);
+        *p_sdp_handle = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_avrc_sdp_cback
+**
+** Description      AVRCP service discovery callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_avrc_sdp_cback(UINT16 status)
+{
+    BT_HDR *p_msg;
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_AV_SDP_AVRC_DISC_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_ctrl_cback
+**
+** Description      AVRCP control callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_rc_ctrl_cback(UINT8 handle, UINT8 event, UINT16 result, BD_ADDR peer_addr)
+{
+    tBTA_AV_RC_CONN_CHG *p_msg;
+    UINT16 msg_event = 0;
+
+#if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
+    APPL_TRACE_EVENT2("rc_ctrl handle: %d event=0x%x", handle, event);
+#else
+    APPL_TRACE_EVENT2("bta_av_rc_ctrl_cback handle: %d event=0x%x", handle, event);
+#endif
+    if (event == AVRC_OPEN_IND_EVT)
+    {
+        /* save handle of opened connection
+        bta_av_cb.rc_handle = handle;*/
+
+        msg_event = BTA_AV_AVRC_OPEN_EVT;
+    }
+    else if (event == AVRC_CLOSE_IND_EVT)
+    {
+        msg_event = BTA_AV_AVRC_CLOSE_EVT;
+    }
+
+    if (msg_event)
+    {
+        if ((p_msg = (tBTA_AV_RC_CONN_CHG *) GKI_getbuf(sizeof(tBTA_AV_RC_CONN_CHG))) != NULL)
+        {
+            p_msg->hdr.event = msg_event;
+            p_msg->handle    = handle;
+            if(peer_addr)
+                bdcpy(p_msg->peer_addr, peer_addr);
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_msg_cback
+**
+** Description      AVRCP message callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_rc_msg_cback(UINT8 handle, UINT8 label, UINT8 opcode, tAVRC_MSG *p_msg)
+{
+    tBTA_AV_RC_MSG  *p_buf;
+    UINT8           *p_data = NULL;
+    UINT8           **p_p_data = NULL;
+    UINT16          data_len = 0;
+
+#if (defined(BTA_AV_MIN_DEBUG_TRACES) && BTA_AV_MIN_DEBUG_TRACES == TRUE)
+    APPL_TRACE_ERROR2("rc_msg handle: %d opcode=0x%x", handle, opcode);
+#else
+    APPL_TRACE_EVENT2("bta_av_rc_msg_cback handle: %d opcode=0x%x", handle, opcode);
+#endif
+    /* determine size of buffer we need */
+    if (opcode == AVRC_OP_VENDOR && p_msg->vendor.p_vendor_data != NULL)
+    {
+        p_data = p_msg->vendor.p_vendor_data;
+        p_p_data = &p_msg->vendor.p_vendor_data;
+        data_len = (UINT16) p_msg->vendor.vendor_len;
+    }
+    else if (opcode == AVRC_OP_PASS_THRU && p_msg->pass.p_pass_data != NULL)
+    {
+        p_data = p_msg->pass.p_pass_data;
+        p_p_data = &p_msg->pass.p_pass_data;
+        data_len = (UINT16) p_msg->pass.pass_len;
+    }
+
+    if ((p_buf = (tBTA_AV_RC_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_RC_MSG) + data_len))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_AVRC_MSG_EVT;
+        p_buf->handle = handle;
+        p_buf->label = label;
+        p_buf->opcode = opcode;
+        memcpy(&p_buf->msg, p_msg, sizeof(tAVRC_MSG));
+        if (p_data != NULL)
+        {
+            memcpy((UINT8 *)(p_buf + 1), p_data, data_len);
+            *p_p_data = (UINT8 *)(p_buf + 1);
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_create
+**
+** Description      alloc RCB and call AVRC_Open
+**
+** Returns          the created rc handle
+**
+*******************************************************************************/
+UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx)
+{
+    tAVRC_CONN_CB ccb;
+    BD_ADDR_PTR   bda = (BD_ADDR_PTR)bd_addr_any;
+    UINT8         status = BTA_AV_RC_ROLE_ACP;
+    tBTA_AV_SCB  *p_scb = p_cb->p_scb[shdl - 1];
+    int i;
+    UINT8   rc_handle;
+    tBTA_AV_RCB *p_rcb;
+
+    if(role == AVCT_INT)
+    {
+        bda = p_scb->peer_addr;
+        status = BTA_AV_RC_ROLE_INT;
+    }
+    else
+    {
+        if ((p_rcb = bta_av_get_rcb_by_shdl(shdl)) != NULL )
+        {
+            APPL_TRACE_ERROR1("bta_av_rc_create ACP handle exist for shdl:%d", shdl);
+            return p_rcb->handle;
+        }
+    }
+
+    ccb.p_ctrl_cback = bta_av_rc_ctrl_cback;
+    ccb.p_msg_cback = bta_av_rc_msg_cback;
+    ccb.company_id = p_bta_av_cfg->company_id;
+    ccb.conn = role;
+    /* note: BTA_AV_FEAT_RCTG = AVRC_CT_TARGET, BTA_AV_FEAT_RCCT = AVRC_CT_CONTROL */
+    ccb.control = p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_RCCT | AVRC_CT_PASSIVE);
+
+
+    if (AVRC_Open(&rc_handle, &ccb, bda) != AVRC_SUCCESS)
+        return BTA_AV_RC_HANDLE_NONE;
+
+    i = rc_handle;
+    p_rcb = &p_cb->rcb[i];
+
+    if (p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+    {
+        APPL_TRACE_ERROR1("bta_av_rc_create found duplicated handle:%d", rc_handle);
+    }
+
+    p_rcb->handle = rc_handle;
+    p_rcb->status = status;
+    p_rcb->shdl = shdl;
+    p_rcb->lidx = lidx;
+    p_rcb->peer_features = 0;
+    if(lidx == (BTA_AV_NUM_LINKS + 1))
+    {
+        /* this LIDX is reserved for the AVRCP ACP connection */
+        p_cb->rc_acp_handle = p_rcb->handle;
+        p_cb->rc_acp_idx = (i + 1);
+        APPL_TRACE_DEBUG2("rc_acp_handle:%d idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+    }
+    APPL_TRACE_DEBUG6("create %d, role: %d, shdl:%d, rc_handle:%d, lidx:%d, status:0x%x",
+        i, role, shdl, p_rcb->handle, lidx, p_rcb->status);
+
+    return rc_handle;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_valid_group_navi_msg
+**
+** Description      Check if it is Group Navigation Msg for Metadata
+**
+** Returns          BTA_AV_RSP_ACCEPT or BTA_AV_RSP_NOT_IMPL.
+**
+*******************************************************************************/
+static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data)
+{
+    tBTA_AV_CODE ret=BTA_AV_RSP_NOT_IMPL;
+    UINT8 *p_ptr = p_data;
+    UINT16 u16;
+    UINT32 u32;
+
+    if (p_bta_av_cfg->avrc_group && len == BTA_GROUP_NAVI_MSG_OP_DATA_LEN)
+    {
+        BTA_AV_BE_STREAM_TO_CO_ID(u32, p_ptr);
+        BE_STREAM_TO_UINT16(u16, p_ptr);
+
+        if (u32 == AVRC_CO_METADATA)
+        {
+            if (u16 <= AVRC_PDU_PREV_GROUP)
+                ret = BTA_AV_RSP_ACCEPT;
+            else
+                ret = BTA_AV_RSP_REJ;
+        }
+    }
+
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_op_supported
+**
+** Description      Check if remote control operation is supported.
+**
+** Returns          BTA_AV_RSP_ACCEPT of supported, BTA_AV_RSP_NOT_IMPL if not.
+**
+*******************************************************************************/
+static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id)
+{
+    tBTA_AV_CODE ret_code = BTA_AV_RSP_NOT_IMPL;
+
+    if (p_bta_av_rc_id)
+    {
+        if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+        {
+            ret_code = BTA_AV_RSP_ACCEPT;
+        }
+        else if ((p_bta_av_cfg->rc_pass_rsp == BTA_AV_RSP_INTERIM) && p_bta_av_rc_id_ac)
+        {
+            if (p_bta_av_rc_id_ac[rc_id >> 4] & (1 << (rc_id & 0x0F)))
+            {
+                ret_code = BTA_AV_RSP_INTERIM;
+            }
+        }
+    }
+    return ret_code;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_find_lcb
+**
+** Description      Given BD_addr, find the associated LCB.
+**
+** Returns          NULL, if not found.
+**
+*******************************************************************************/
+tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    int     xx;
+    UINT8   mask;
+    tBTA_AV_LCB *p_lcb = NULL;
+
+    for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+    {
+        mask = 1 << xx; /* the used mask for this lcb */
+        if((mask & p_cb->conn_lcb) && 0 ==( bdcmp(p_cb->lcb[xx].addr, addr)))
+        {
+            p_lcb = &p_cb->lcb[xx];
+            if(op == BTA_AV_LCB_FREE)
+            {
+                p_cb->conn_lcb &= ~mask; /* clear the connect mask */
+                APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+            }
+            break;
+        }
+    }
+    return p_lcb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_opened
+**
+** Description      Set AVRCP state to opened.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_opened(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RC_OPEN rc_open;
+    tBTA_AV_SCB     *p_scb;
+    int         i;
+    UINT8       shdl = 0;
+    tBTA_AV_LCB *p_lcb;
+    tBTA_AV_RCB *p_rcb;
+    UINT8       tmp;
+    UINT8       disc = 0;
+
+    /* find the SCB & stop the timer */
+    for(i=0; i<BTA_AV_NUM_STRS; i++)
+    {
+        p_scb = p_cb->p_scb[i];
+        if(p_scb && bdcmp(p_scb->peer_addr, p_data->rc_conn_chg.peer_addr) == 0)
+        {
+            p_scb->rc_handle = p_data->rc_conn_chg.handle;
+            APPL_TRACE_DEBUG2("bta_av_rc_opened shdl:%d, srch %d", i + 1, p_scb->rc_handle);
+            shdl = i+1;
+            APPL_TRACE_ERROR1("use_rc:%d", p_scb->use_rc);
+            bta_sys_stop_timer(&p_scb->timer);
+            disc = p_scb->hndl;
+            break;
+        }
+    }
+
+    i = p_data->rc_conn_chg.handle;
+    if (p_cb->rcb[i].handle == BTA_AV_RC_HANDLE_NONE)
+    {
+        APPL_TRACE_ERROR1("not a valid handle:%d any more", i);
+        return;
+    }
+
+
+    if (p_cb->rcb[i].lidx == (BTA_AV_NUM_LINKS + 1) && shdl != 0)
+    {
+        /* rc is opened on the RC only ACP channel, but is for a specific
+         * SCB -> need to switch RCBs */
+        p_rcb = bta_av_get_rcb_by_shdl(shdl);
+        if (p_rcb)
+        {
+            p_rcb->shdl = p_cb->rcb[i].shdl;
+            tmp         = p_rcb->lidx;
+            p_rcb->lidx = p_cb->rcb[i].lidx;
+            p_cb->rcb[i].lidx = tmp;
+            p_cb->rc_acp_handle = p_rcb->handle;
+            p_cb->rc_acp_idx = (p_rcb - p_cb->rcb) + 1;
+            APPL_TRACE_DEBUG2("switching RCB rc_acp_handle:%d idx:%d",
+                               p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+        }
+    }
+
+    p_cb->rcb[i].shdl = shdl;
+    rc_open.rc_handle = i;
+    APPL_TRACE_ERROR4("bta_av_rc_opened rcb[%d] shdl:%d lidx:%d/%d",
+            i, shdl, p_cb->rcb[i].lidx, p_cb->lcb[BTA_AV_NUM_LINKS].lidx);
+    p_cb->rcb[i].status |= BTA_AV_RC_CONN_MASK;
+
+    if(!shdl && 0 == p_cb->lcb[BTA_AV_NUM_LINKS].lidx)
+    {
+        /* no associated SCB -> connected to an RC only device
+         * update the index to the extra LCB */
+        p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
+        bdcpy(p_lcb->addr, p_data->rc_conn_chg.peer_addr);
+        APPL_TRACE_DEBUG6("rc_only bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+                      p_lcb->addr[0], p_lcb->addr[1],
+                      p_lcb->addr[2], p_lcb->addr[3],
+                      p_lcb->addr[4], p_lcb->addr[5]);
+        p_lcb->lidx = BTA_AV_NUM_LINKS + 1;
+            p_cb->rcb[i].lidx = p_lcb->lidx;
+        p_lcb->conn_msk = 1;
+        APPL_TRACE_ERROR3("rcb[%d].lidx=%d, lcb.conn_msk=x%x",
+            i, p_cb->rcb[i].lidx, p_lcb->conn_msk);
+        disc = p_data->rc_conn_chg.handle|BTA_AV_CHNL_MSK;
+    }
+
+    bdcpy(rc_open.peer_addr, p_data->rc_conn_chg.peer_addr);
+    rc_open.peer_features = p_cb->rcb[i].peer_features;
+    rc_open.status = BTA_AV_SUCCESS;
+    APPL_TRACE_DEBUG2("local features:x%x peer_features:x%x", p_cb->features,
+                      rc_open.peer_features);
+    if(rc_open.peer_features == 0)
+    {
+        /* we have not done SDP on peer RC capabilities.
+         * peer must have initiated the RC connection */
+        rc_open.peer_features = BTA_AV_FEAT_RCCT;
+        bta_av_rc_disc(disc);
+    }
+    (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_remote_cmd
+**
+** Description      Send an AVRCP remote control command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_remote_cmd(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RCB    *p_rcb;
+    if (p_cb->features & BTA_AV_FEAT_RCCT)
+    {
+        if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+        {
+            p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+            if(p_rcb->status & BTA_AV_RC_CONN_MASK)
+            {
+                AVRC_PassCmd(p_rcb->handle, p_data->api_remote_cmd.label,
+                     &p_data->api_remote_cmd.msg);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_vendor_cmd
+**
+** Description      Send an AVRCP vendor specific command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_vendor_cmd(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RCB    *p_rcb;
+    if ( (p_cb->features & (BTA_AV_FEAT_RCCT | BTA_AV_FEAT_VENDOR)) ==
+         (BTA_AV_FEAT_RCCT | BTA_AV_FEAT_VENDOR))
+    {
+        if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+        {
+            p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+            AVRC_VendorCmd(p_rcb->handle, p_data->api_vendor.label, &p_data->api_vendor.msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_vendor_rsp
+**
+** Description      Send an AVRCP vendor specific response.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_vendor_rsp(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RCB    *p_rcb;
+    if ( (p_cb->features & (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_VENDOR)) ==
+         (BTA_AV_FEAT_RCTG | BTA_AV_FEAT_VENDOR))
+    {
+        if(p_data->hdr.layer_specific < BTA_AV_NUM_RCB)
+        {
+            p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+            AVRC_VendorRsp(p_rcb->handle, p_data->api_vendor.label, &p_data->api_vendor.msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_meta_rsp
+**
+** Description      Send an AVRCP metadata/advanced control command/response.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_meta_rsp(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_RCB *p_rcb;
+    BOOLEAN         free = TRUE;
+
+    if ((p_cb->features & BTA_AV_FEAT_METADATA) && (p_data->hdr.layer_specific < BTA_AV_NUM_RCB))
+    {
+        if ((p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCTG)) ||
+            (!p_data->api_meta_rsp.is_rsp && (p_cb->features & BTA_AV_FEAT_RCCT)) )
+        {
+            p_rcb = &p_cb->rcb[p_data->hdr.layer_specific];
+            AVRC_MsgReq(p_rcb->handle, p_data->api_meta_rsp.label, p_data->api_meta_rsp.rsp_code,
+                                      p_data->api_meta_rsp.p_pkt);
+            free = FALSE;
+        }
+    }
+
+    if (free)
+        GKI_freebuf (p_data->api_meta_rsp.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_free_rsp
+**
+** Description      free an AVRCP metadata command buffer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    GKI_freebuf (p_data->api_meta_rsp.p_pkt);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_meta_req
+**
+** Description      Send an AVRCP metadata command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_av_chk_notif_evt_id
+**
+** Description      make sure the requested player id is valid.
+**
+** Returns          BTA_AV_STS_NO_RSP, if no error
+**
+*******************************************************************************/
+static tAVRC_STS bta_av_chk_notif_evt_id(tAVRC_MSG_VENDOR *p_vendor)
+{
+    tAVRC_STS   status = BTA_AV_STS_NO_RSP;
+    UINT8       xx;
+    UINT16      u16;
+    UINT8       *p = p_vendor->p_vendor_data + 2;
+
+    BE_STREAM_TO_UINT16 (u16, p);
+    /* double check the fixed length */
+    if ((u16 != 5) || (p_vendor->vendor_len != 9))
+    {
+        status = AVRC_STS_INTERNAL_ERR;
+    }
+    else
+    {
+        /* make sure the player_id is valid */
+        for (xx=0; xx<p_bta_av_cfg->num_evt_ids; xx++)
+        {
+            if (*p == p_bta_av_cfg->p_meta_evt_ids[xx])
+            {
+                break;
+            }
+        }
+        if (xx == p_bta_av_cfg->num_evt_ids)
+        {
+            status = AVRC_STS_BAD_PARAM;
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_proc_meta_cmd
+**
+** Description      Process an AVRCP metadata command from the peer.
+**
+** Returns          TRUE to respond immediately
+**
+*******************************************************************************/
+tBTA_AV_EVT bta_av_proc_meta_cmd(tAVRC_RESPONSE  *p_rc_rsp, tBTA_AV_RC_MSG *p_msg, UINT8 *p_ctype)
+{
+    tBTA_AV_EVT evt = BTA_AV_META_MSG_EVT;
+    UINT8       u8, pdu, *p;
+    UINT16      u16;
+    tAVRC_MSG_VENDOR    *p_vendor = &p_msg->msg.vendor;
+
+    pdu = *(p_vendor->p_vendor_data);
+    p_rc_rsp->pdu = pdu;
+    *p_ctype = AVRC_RSP_REJ;
+    /* Metadata messages only use PANEL sub-unit type */
+    if (p_vendor->hdr.subunit_type != AVRC_SUB_PANEL)
+    {
+        APPL_TRACE_DEBUG0("SUBUNIT must be PANEL");
+        /* reject it */
+        evt=0;
+        p_vendor->hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+        AVRC_VendorRsp(p_msg->handle, p_msg->label, &p_msg->msg.vendor);
+    }
+    else
+    {
+        switch (pdu)
+        {
+        case AVRC_PDU_GET_CAPABILITIES:
+            /* process GetCapabilities command without reporting the event to app */
+            evt = 0;
+            u8 = *(p_vendor->p_vendor_data + 4);
+            p = p_vendor->p_vendor_data + 2;
+            p_rc_rsp->get_caps.capability_id = u8;
+            BE_STREAM_TO_UINT16 (u16, p);
+            if ((u16 != 1) || (p_vendor->vendor_len != 5))
+            {
+                p_rc_rsp->get_caps.status = AVRC_STS_INTERNAL_ERR;
+            }
+            else
+            {
+                p_rc_rsp->get_caps.status = AVRC_STS_NO_ERROR;
+                if (u8 == AVRC_CAP_COMPANY_ID)
+                {
+                    *p_ctype = AVRC_RSP_IMPL_STBL;
+                    p_rc_rsp->get_caps.count = p_bta_av_cfg->num_co_ids;
+                    memcpy(p_rc_rsp->get_caps.param.company_id, p_bta_av_cfg->p_meta_co_ids,
+                           (p_bta_av_cfg->num_co_ids << 2));
+                }
+                else if (u8 == AVRC_CAP_EVENTS_SUPPORTED)
+                {
+                    *p_ctype = AVRC_RSP_IMPL_STBL;
+                    p_rc_rsp->get_caps.count = p_bta_av_cfg->num_evt_ids;
+                    memcpy(p_rc_rsp->get_caps.param.event_id, p_bta_av_cfg->p_meta_evt_ids,
+                           p_bta_av_cfg->num_evt_ids);
+                }
+                else
+                {
+                    APPL_TRACE_DEBUG1("Invalid capability ID: 0x%x", u8);
+                    /* reject - unknown capability ID */
+                    p_rc_rsp->get_caps.status = AVRC_STS_BAD_PARAM;
+                }
+            }
+            break;
+
+
+        case AVRC_PDU_REGISTER_NOTIFICATION:
+            /* make sure the event_id is implemented */
+            p_rc_rsp->rsp.status = bta_av_chk_notif_evt_id (p_vendor);
+            if (p_rc_rsp->rsp.status != BTA_AV_STS_NO_RSP)
+                evt = 0;
+            break;
+
+        }
+    }
+
+    return evt;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_msg
+**
+** Description      Process an AVRCP message from the peer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_msg(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_EVT evt = 0;
+    tBTA_AV     av;
+    BT_HDR      *p_pkt = NULL;
+    tAVRC_MSG_VENDOR    *p_vendor = &p_data->rc_msg.msg.vendor;
+
+    if (p_data->rc_msg.opcode == AVRC_OP_PASS_THRU)
+    {
+    /* if this is a pass thru command */
+        if (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_CTRL)
+        {
+        /* check if operation is supported */
+            if (p_data->rc_msg.msg.pass.op_id == AVRC_ID_VENDOR)
+            {
+                p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+            }
+            else
+            {
+                p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id);
+            }
+
+            /* send response */
+            if (p_data->rc_msg.msg.hdr.ctype != BTA_AV_RSP_INTERIM)
+                AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.pass);
+
+            /* set up for callback if supported */
+            if (p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_ACCEPT || p_data->rc_msg.msg.hdr.ctype == BTA_AV_RSP_INTERIM)
+            {
+                evt = BTA_AV_REMOTE_CMD_EVT;
+                av.remote_cmd.rc_id = p_data->rc_msg.msg.pass.op_id;
+                av.remote_cmd.key_state = p_data->rc_msg.msg.pass.state;
+                av.remote_cmd.p_data = p_data->rc_msg.msg.pass.p_pass_data;
+                av.remote_cmd.len = p_data->rc_msg.msg.pass.pass_len;
+                memcpy(&av.remote_cmd.hdr, &p_data->rc_msg.msg.hdr, sizeof (tAVRC_HDR));
+                av.remote_cmd.label = p_data->rc_msg.label;
+            }
+        }
+        /* else if this is a pass thru response */
+        else if (p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_ACCEPT)
+        {
+            /* set up for callback */
+            evt = BTA_AV_REMOTE_RSP_EVT;
+            av.remote_rsp.rc_id = p_data->rc_msg.msg.pass.op_id;
+            av.remote_rsp.key_state = p_data->rc_msg.msg.pass.state;
+            av.remote_rsp.rsp_code = p_data->rc_msg.msg.hdr.ctype;
+            av.remote_rsp.label = p_data->rc_msg.label;
+        }
+        /* must be a bad ctype -> reject*/
+        else
+        {
+            p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+            AVRC_PassRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.pass);
+        }
+    }
+    /* else if this is a vendor specific command or response */
+    else if (p_data->rc_msg.opcode == AVRC_OP_VENDOR)
+    {
+        /* set up for callback */
+        av.vendor_cmd.code = p_data->rc_msg.msg.hdr.ctype;
+        av.vendor_cmd.company_id = p_vendor->company_id;
+        av.vendor_cmd.label = p_data->rc_msg.label;
+        av.vendor_cmd.p_data = p_vendor->p_vendor_data;
+        av.vendor_cmd.len = p_vendor->vendor_len;
+
+        /* if configured to support vendor specific and it's a command */
+        if ((p_cb->features & BTA_AV_FEAT_VENDOR)  &&
+            p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ)
+        {
+                evt = BTA_AV_VENDOR_CMD_EVT;
+        }
+        /* else if configured to support vendor specific and it's a response */
+        else if ((p_cb->features & BTA_AV_FEAT_VENDOR) &&
+                 p_data->rc_msg.msg.hdr.ctype >= AVRC_RSP_ACCEPT)
+        {
+                evt = BTA_AV_VENDOR_RSP_EVT;
+
+        }
+        /* else if not configured to support vendor specific and it's a command */
+        else if (!(p_cb->features & BTA_AV_FEAT_VENDOR)  &&
+            p_data->rc_msg.msg.hdr.ctype <= AVRC_CMD_GEN_INQ)
+        {
+           if(p_data->rc_msg.msg.vendor.p_vendor_data[0] == AVRC_PDU_INVALID)
+           {
+           /* reject it */
+              p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_REJ;
+              p_data->rc_msg.msg.vendor.p_vendor_data[4] = AVRC_STS_BAD_CMD;
+           }
+           else
+              p_data->rc_msg.msg.hdr.ctype = BTA_AV_RSP_NOT_IMPL;
+           AVRC_VendorRsp(p_data->rc_msg.handle, p_data->rc_msg.label, &p_data->rc_msg.msg.vendor);
+        }
+    }
+
+    /* call callback */
+    if (evt != 0)
+    {
+        av.remote_cmd.rc_handle = p_data->rc_msg.handle;
+        (*p_cb->p_cback)(evt, &av);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_close
+**
+** Description      close the specified AVRC handle.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_close (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    UINT16 handle = p_data->hdr.layer_specific;
+    tBTA_AV_SCB  *p_scb;
+    tBTA_AV_RCB *p_rcb;
+
+    if(handle < BTA_AV_NUM_RCB)
+    {
+        p_rcb = &p_cb->rcb[handle];
+
+        APPL_TRACE_DEBUG2("bta_av_rc_close handle: %d, status=0x%x", p_rcb->handle, p_rcb->status);
+        if(p_rcb->handle != BTA_AV_RC_HANDLE_NONE)
+        {
+            if(p_rcb->shdl)
+            {
+                p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+                if(p_scb)
+                {
+                    /* just in case the RC timer is active
+                    if(bta_av_cb.features & BTA_AV_FEAT_RCCT &&
+                       p_scb->chnl == BTA_AV_CHNL_AUDIO) */
+                        bta_sys_stop_timer(&p_scb->timer);
+                }
+            }
+
+            AVRC_Close(p_rcb->handle);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_get_shdl
+**
+** Returns          The index to p_scb[]
+**
+*******************************************************************************/
+static UINT8 bta_av_get_shdl(tBTA_AV_SCB *p_scb)
+{
+    int     i;
+    UINT8   shdl = 0;
+    /* find the SCB & stop the timer */
+    for(i=0; i<BTA_AV_NUM_STRS; i++)
+    {
+        if(p_scb == bta_av_cb.p_scb[i])
+        {
+            shdl = i+1;
+            break;
+        }
+    }
+    return shdl;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_stream_chg
+**
+** Description      audio streaming status changed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started)
+{
+    UINT8   started_msk;
+    int     i;
+    UINT8   *p_streams;
+    BOOLEAN no_streams = FALSE;
+    tBTA_AV_SCB *p_scbi;
+
+    started_msk = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+    APPL_TRACE_DEBUG3 ("bta_av_stream_chg started:%d started_msk:x%x chnl:x%x", started,
+                                                  started_msk, p_scb->chnl);
+    if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
+        p_streams = &bta_av_cb.audio_streams;
+    else
+        p_streams = &bta_av_cb.video_streams;
+
+    if (started)
+    {
+        /* Let L2CAP know this channel is processed with high priority */
+        L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_HIGH);
+        (*p_streams) |= started_msk;
+    }
+    else
+    {
+        (*p_streams) &= ~started_msk;
+    }
+
+    if (!started)
+    {
+        i=0;
+        if (BTA_AV_CHNL_AUDIO == p_scb->chnl)
+        {
+            if (bta_av_cb.video_streams == 0)
+                no_streams = TRUE;
+        }
+        else
+        {
+            no_streams = TRUE;
+            if ( bta_av_cb.audio_streams )
+            {
+                for (; i<BTA_AV_NUM_STRS; i++)
+                {
+                    p_scbi = bta_av_cb.p_scb[i];
+                    /* scb is used and started */
+                    if ( p_scbi && (bta_av_cb.audio_streams & BTA_AV_HNDL_TO_MSK(i))
+                        && bdcmp(p_scbi->peer_addr, p_scb->peer_addr) == 0)
+                    {
+                        no_streams = FALSE;
+                        break;
+                    }
+                }
+
+            }
+        }
+
+        APPL_TRACE_DEBUG4 ("no_streams:%d i:%d, audio_streams:x%x, video_streams:x%x", no_streams, i,
+                           bta_av_cb.audio_streams, bta_av_cb.video_streams);
+        if (no_streams)
+        {
+            /* Let L2CAP know this channel is processed with low priority */
+            L2CA_SetAclPriority(p_scb->peer_addr, L2CAP_PRIORITY_NORMAL);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_av_conn_chg
+**
+** Description      connetion status changed.
+**                  Open an AVRCP acceptor channel, if new conn.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_conn_chg(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tBTA_AV_SCB     *p_scb;
+    tBTA_AV_SCB     *p_scbi;
+    UINT8   mask;
+    UINT8   conn_msk;
+    UINT8   old_msk;
+    int i;
+    int index = (p_data->hdr.layer_specific & BTA_AV_HNDL_MSK) - 1;
+    tBTA_AV_LCB *p_lcb;
+    tBTA_AV_LCB *p_lcb_rc;
+    tBTA_AV_RCB *p_rcb, *p_rcb2;
+    BOOLEAN     chk_restore = FALSE;
+
+    p_scb = p_cb->p_scb[index];
+
+    mask = BTA_AV_HNDL_TO_MSK(index);
+    p_lcb = bta_av_find_lcb(p_data->conn_chg.peer_addr, BTA_AV_LCB_FIND);
+    conn_msk = 1 << (index + 1);
+    if(p_data->conn_chg.is_up)
+    {
+        /* set the conned mask for this channel */
+        if(p_scb)
+        {
+            if(p_lcb)
+            {
+                p_lcb->conn_msk |= conn_msk;
+                for (i=0; i<BTA_AV_NUM_RCB; i++)
+                {
+                    if (bta_av_cb.rcb[i].lidx == p_lcb->lidx)
+                    {
+                        bta_av_cb.rcb[i].shdl = index + 1;
+                        APPL_TRACE_DEBUG5("conn_chg up[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
+                                          bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+                                          bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+                        break;
+                    }
+                }
+            }
+            if (p_scb->chnl == BTA_AV_CHNL_AUDIO)
+            {
+                old_msk = p_cb->conn_audio;
+                p_cb->conn_audio |= mask;
+            }
+            else
+            {
+                old_msk = p_cb->conn_video;
+                p_cb->conn_video |= mask;
+            }
+
+            if ((old_msk & mask) == 0)
+            {
+                /* increase the audio open count, if not set yet */
+                bta_av_cb.audio_open_cnt++;
+            }
+
+
+            APPL_TRACE_DEBUG2("rc_acp_handle:%d rc_acp_idx:%d", p_cb->rc_acp_handle, p_cb->rc_acp_idx);
+            /* check if the AVRCP ACP channel is already connected */
+            if(p_lcb && p_cb->rc_acp_handle != BTA_AV_RC_HANDLE_NONE && p_cb->rc_acp_idx)
+            {
+                p_lcb_rc = &p_cb->lcb[BTA_AV_NUM_LINKS];
+                APPL_TRACE_DEBUG1("rc_acp is connected && conn_chg on same addr p_lcb_rc->conn_msk:x%x",
+                                  p_lcb_rc->conn_msk);
+                /* check if the RC is connected to the scb addr */
+                APPL_TRACE_DEBUG6 ("p_lcb_rc->addr: %02x:%02x:%02x:%02x:%02x:%02x",
+                       p_lcb_rc->addr[0], p_lcb_rc->addr[1], p_lcb_rc->addr[2], p_lcb_rc->addr[3],
+                       p_lcb_rc->addr[4], p_lcb_rc->addr[5]);
+                APPL_TRACE_DEBUG6 ("conn_chg.peer_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+                       p_data->conn_chg.peer_addr[0], p_data->conn_chg.peer_addr[1],
+                       p_data->conn_chg.peer_addr[2],
+                       p_data->conn_chg.peer_addr[3], p_data->conn_chg.peer_addr[4],
+                       p_data->conn_chg.peer_addr[5]);
+                if (p_lcb_rc->conn_msk && bdcmp(p_lcb_rc->addr, p_data->conn_chg.peer_addr) == 0)
+                {
+                    /* AVRCP is already connected.
+                     * need to update the association betwen SCB and RCB */
+                    p_lcb_rc->conn_msk = 0; /* indicate RC ONLY is not connected */
+                    p_lcb_rc->lidx = 0;
+                    p_scb->rc_handle = p_cb->rc_acp_handle;
+                    p_rcb = &p_cb->rcb[p_cb->rc_acp_idx - 1];
+                    p_rcb->shdl = bta_av_get_shdl(p_scb);
+                    APPL_TRACE_DEBUG3("update rc_acp shdl:%d/%d srch:%d", index + 1, p_rcb->shdl,
+                                      p_scb->rc_handle );
+
+                    p_rcb2 = bta_av_get_rcb_by_shdl(p_rcb->shdl);
+                    if (p_rcb2)
+                    {
+                        /* found the RCB that was created to associated with this SCB */
+                        p_cb->rc_acp_handle = p_rcb2->handle;
+                        p_cb->rc_acp_idx = (p_rcb2 - p_cb->rcb) + 1;
+                        APPL_TRACE_DEBUG2("new rc_acp_handle:%d, idx:%d", p_cb->rc_acp_handle,
+                                           p_cb->rc_acp_idx);
+                        p_rcb2->lidx = (BTA_AV_NUM_LINKS + 1);
+                        APPL_TRACE_DEBUG3("rc2 handle:%d lidx:%d/%d",p_rcb2->handle, p_rcb2->lidx,
+                                          p_cb->lcb[p_rcb2->lidx-1].lidx);
+                    }
+                    p_rcb->lidx = p_lcb->lidx;
+                    APPL_TRACE_DEBUG3("rc handle:%d lidx:%d/%d",p_rcb->handle, p_rcb->lidx,
+                                      p_cb->lcb[p_rcb->lidx-1].lidx);
+                }
+            }
+        }
+    }
+    else
+    {
+        if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt)
+        {
+            /* this channel is still marked as open. decrease the count */
+            bta_av_cb.audio_open_cnt--;
+        }
+
+        /* clear the conned mask for this channel */
+        p_cb->conn_audio &= ~mask;
+        p_cb->conn_video &= ~mask;
+        if(p_scb)
+        {
+            /* the stream is closed.
+             * clear the peer address, so it would not mess up the AVRCP for the next round of operation */
+            bdcpy(p_scb->peer_addr, bd_addr_null);
+            if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+            {
+                if(p_lcb)
+                {
+                    p_lcb->conn_msk &= ~conn_msk;
+                }
+                /* audio channel is down. make sure the INT channel is down */
+                /* just in case the RC timer is active
+                if(p_cb->features & BTA_AV_FEAT_RCCT) */
+                {
+                    bta_sys_stop_timer(&p_scb->timer);
+                }
+                /* one audio channel goes down. check if we need to restore high priority */
+                chk_restore = TRUE;
+            }
+        }
+
+        APPL_TRACE_DEBUG1("bta_av_conn_chg shdl:%d", index + 1);
+        for (i=0; i<BTA_AV_NUM_RCB; i++)
+        {
+            APPL_TRACE_DEBUG5("conn_chg dn[%d]: %d, status=0x%x, shdl:%d, lidx:%d", i,
+                              bta_av_cb.rcb[i].handle, bta_av_cb.rcb[i].status,
+                              bta_av_cb.rcb[i].shdl, bta_av_cb.rcb[i].lidx);
+            if(bta_av_cb.rcb[i].shdl == index + 1)
+            {
+                bta_av_del_rc(&bta_av_cb.rcb[i]);
+                break;
+            }
+        }
+
+        if(p_cb->conn_audio == 0 && p_cb->conn_video == 0)
+        {
+            /* if both channels are not connected,
+             * close all RC channels */
+            bta_av_close_all_rc(p_cb);
+        }
+
+        /* if the AVRCP is no longer listening, create the listening channel */
+        if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
+            bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+    }
+
+    APPL_TRACE_DEBUG6("bta_av_conn_chg audio:%x video:%x up:%d conn_msk:0x%x chk_restore:%d audio_open_cnt:%d",
+        p_cb->conn_audio, p_cb->conn_video, p_data->conn_chg.is_up, conn_msk, chk_restore, p_cb->audio_open_cnt);
+
+    if (chk_restore)
+    {
+        if (p_cb->audio_open_cnt == 1)
+        {
+            /* one audio channel goes down and there's one audio channel remains open.
+             * restore the switch role in default link policy */
+            bta_sys_set_default_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH);
+            /* allow role switch, if this is the last connection */
+            bta_av_restore_switch();
+        }
+        if (p_cb->audio_open_cnt)
+        {
+            /* adjust flush timeout settings to longer period */
+            for (i=0; i<BTA_AV_NUM_STRS; i++)
+            {
+                p_scbi = bta_av_cb.p_scb[i];
+                if (p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+                {
+                    /* may need to update the flush timeout of this already started stream */
+                    if (p_scbi->co_started != bta_av_cb.audio_open_cnt)
+                    {
+                        p_scbi->co_started = bta_av_cb.audio_open_cnt;
+                        L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_disable
+**
+** Description      disable AV.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_disable(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data)
+{
+    BT_HDR  hdr;
+    UINT16  xx;
+
+    p_cb->disabling = TRUE;
+
+    bta_av_close_all_rc(p_cb);
+
+    utl_freebuf((void **) &p_cb->p_disc_db);
+
+    /* disable audio/video - de-register all channels,
+     * expect BTA_AV_DEREG_COMP_EVT when deregister is complete */
+    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    {
+        hdr.layer_specific = xx + 1;
+        bta_av_api_deregister((tBTA_AV_DATA *)&hdr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_api_disconnect
+**
+** Description      .
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_api_disconnect(tBTA_AV_DATA *p_data)
+{
+    AVDT_DisconnectReq(p_data->api_discnt.bd_addr, bta_av_conn_cback);
+    bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sig_chg
+**
+** Description      process AVDT signal channel up/down.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_sig_chg(tBTA_AV_DATA *p_data)
+{
+    UINT16 event = p_data->str_msg.hdr.layer_specific;
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    int     xx;
+    UINT8   mask;
+    tBTA_AV_LCB *p_lcb = NULL;
+
+    APPL_TRACE_DEBUG1("bta_av_sig_chg event: %d", event);
+    if(event == AVDT_CONNECT_IND_EVT)
+    {
+        p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FIND);
+        if(!p_lcb)
+        {
+            /* if the address does not have an LCB yet, alloc one */
+            for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+            {
+                mask = 1 << xx;
+                APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+                if(!(mask & p_cb->conn_lcb))
+                {
+                    if (!p_cb->p_scb[xx])
+                    {
+                        /* We do not have scb for this avdt connection.     */
+                        /* Silently close the connection.                   */
+                        APPL_TRACE_ERROR0("av scb not available for avdt connection");
+                        AVDT_DisconnectReq (p_data->str_msg.bd_addr, NULL);
+                        return;
+                    }
+
+                    p_lcb = &p_cb->lcb[xx];
+                    p_lcb->lidx = xx + 1;
+                    bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
+                    p_lcb->conn_msk = 0; /* clear the connect mask */
+                    /* start listening when the signal channel is open */
+                    if (p_cb->features & BTA_AV_FEAT_RCTG)
+                    {
+                        bta_av_rc_create(p_cb, AVCT_ACP, 0, p_lcb->lidx);
+                    }
+                    /* this entry is not used yet. */
+                    p_cb->conn_lcb |= mask;     /* mark it as used */
+                    APPL_TRACE_DEBUG1("start sig timer %d", p_data->hdr.offset);
+                    if (p_data->hdr.offset == AVDT_ACP)
+                    {
+                        APPL_TRACE_DEBUG1("Incoming L2CAP acquired, set state as incoming", NULL);
+                        bdcpy(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr);
+                        p_cb->p_scb[xx]->use_rc = TRUE;     /* allowing RC for incoming connection */
+                        bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_ACP_CONNECT_EVT, p_data);
+
+                        /* The Pending Event should be sent as soon as the L2CAP signalling channel
+                         * is set up, which is NOW. Earlier this was done only after
+                         * BTA_AV_SIG_TIME_VAL milliseconds.
+                         * The following function shall send the event and start the recurring timer
+                         */
+                        bta_av_sig_timer(NULL);
+
+                        /* Possible collision : need to avoid outgoing processing while the timer is running */
+                        p_cb->p_scb[xx]->coll_mask = BTA_AV_COLL_INC_TMR;
+
+                        p_cb->acp_sig_tmr.param = (UINT32)xx;
+                        p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK*)&bta_av_acp_sig_timer_cback;
+                        bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
+                    }
+                    break;
+                }
+            }
+        }
+    }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+    else if (event == BTA_AR_AVDT_CONN_EVT)
+    {
+        bta_sys_stop_timer(&bta_av_cb.sig_tmr);
+    }
+#endif
+    else
+    {
+        /* disconnected. */
+        p_lcb = bta_av_find_lcb(p_data->str_msg.bd_addr, BTA_AV_LCB_FREE);
+        if(p_lcb && p_lcb->conn_msk)
+        {
+            APPL_TRACE_DEBUG1("conn_msk: 0x%x", p_lcb->conn_msk);
+            /* clean up ssm  */
+            for(xx=0; xx < BTA_AV_NUM_STRS; xx++)
+            {
+                mask = 1 << (xx + 1);
+                if ((mask & p_lcb->conn_msk) && (p_cb->p_scb[xx]) &&
+                    (bdcmp(p_cb->p_scb[xx]->peer_addr, p_data->str_msg.bd_addr) == 0))
+                {
+                    bta_av_ssm_execute(p_cb->p_scb[xx], BTA_AV_AVDT_DISCONNECT_EVT, NULL);
+                }
+            }
+        }
+    }
+    APPL_TRACE_DEBUG1("conn_lcb: 0x%x", p_cb->conn_lcb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sig_timer
+**
+** Description      process the signal channel timer. This timer is started
+**                  when the AVDTP signal channel is connected. If no profile
+**                  is connected, the timer goes off every BTA_AV_SIG_TIME_VAL
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_sig_timer(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    int     xx;
+    UINT8   mask;
+    tBTA_AV_LCB *p_lcb = NULL;
+    tBTA_AV_PEND pend;
+
+    APPL_TRACE_DEBUG0("bta_av_sig_timer");
+    for(xx=0; xx<BTA_AV_NUM_LINKS; xx++)
+    {
+        mask = 1 << xx;
+        if(mask & p_cb->conn_lcb)
+        {
+            /* this entry is used. check if it is connected */
+            p_lcb = &p_cb->lcb[xx];
+            if(!p_lcb->conn_msk)
+            {
+                bta_sys_start_timer(&p_cb->sig_tmr, BTA_AV_SIG_TIMER_EVT, BTA_AV_SIG_TIME_VAL);
+                bdcpy(pend.bd_addr, p_lcb->addr);
+                (*p_cb->p_cback)(BTA_AV_PENDING_EVT, (tBTA_AV *) &pend);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_acp_sig_timer_cback
+**
+** Description      Process the timeout when SRC is accepting connection
+**                  and SNK did not start signalling.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_acp_sig_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    UINT8   inx = (UINT8)p_tle->param;
+    tBTA_AV_CB  *p_cb = &bta_av_cb;
+    tBTA_AV_SCB *p_scb = p_cb->p_scb[inx];
+    tBTA_AV_API_OPEN  *p_buf;
+
+    if (p_scb)
+    {
+        APPL_TRACE_DEBUG1("bta_av_acp_sig_timer_cback, coll_mask = 0x%02X", p_scb->coll_mask);
+
+        if (p_scb->coll_mask & BTA_AV_COLL_INC_TMR)
+        {
+            p_scb->coll_mask &= ~BTA_AV_COLL_INC_TMR;
+
+            if (bta_av_is_scb_opening(p_scb))
+            {
+                if (p_scb->p_disc_db)
+                {
+                    /* We are still doing SDP. Run the timer again. */
+                    p_scb->coll_mask |= BTA_AV_COLL_INC_TMR;
+
+                    p_cb->acp_sig_tmr.param = (UINT32)inx;
+                    p_cb->acp_sig_tmr.p_cback = (TIMER_CBACK *)&bta_av_acp_sig_timer_cback;
+                    bta_sys_start_timer(&p_cb->acp_sig_tmr, 0, BTA_AV_ACP_SIG_TIME_VAL);
+                }
+                else
+                {
+                    /* SNK did not start signalling, resume signalling process. */
+                    bta_av_discover_req (p_scb, NULL);
+                }
+            }
+            else if (bta_av_is_scb_incoming(p_scb))
+            {
+                /* Stay in incoming state if SNK does not start signalling */
+
+                /* API open was called right after SNK opened L2C connection. */
+                if (p_scb->coll_mask & BTA_AV_COLL_API_CALLED)
+                {
+                    p_scb->coll_mask &= ~BTA_AV_COLL_API_CALLED;
+
+                    /* BTA_AV_API_OPEN_EVT */
+                    if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+                    {
+                        memcpy(p_buf, &(p_scb->open_api), sizeof(tBTA_AV_API_OPEN));
+                        bta_sys_sendmsg(p_buf);
+                    }
+                }
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_check_peer_features
+**
+** Description      checks
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_AV_FEAT bta_av_check_peer_features (UINT16 service_uuid)
+{
+    tBTA_AV_FEAT peer_features = 0;
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tSDP_DISC_REC       *p_rec = NULL;
+    tSDP_DISC_ATTR      *p_attr;
+    UINT16              peer_rc_version=0;
+    UINT16              categories = 0;
+
+    APPL_TRACE_DEBUG1("bta_av_check_peer_features service_uuid:x%x", service_uuid);
+    /* loop through all records we found */
+    while (TRUE)
+    {
+        /* get next record; if none found, we're done */
+        if ((p_rec = SDP_FindServiceInDb(p_cb->p_disc_db, service_uuid, p_rec)) == NULL)
+        {
+            break;
+        }
+
+        if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_CLASS_ID_LIST)) != NULL)
+        {
+            /* find peer features */
+            if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL))
+            {
+                peer_features |= BTA_AV_FEAT_RCCT;
+            }
+            if (SDP_FindServiceInDb(p_cb->p_disc_db, UUID_SERVCLASS_AV_REM_CTRL_TARGET, NULL))
+            {
+                peer_features |= BTA_AV_FEAT_RCTG;
+            }
+        }
+
+        if (( SDP_FindAttributeInRec(p_rec, ATTR_ID_BT_PROFILE_DESC_LIST)) != NULL)
+        {
+            /* get profile version (if failure, version parameter is not updated) */
+            SDP_FindProfileVersionInRec(p_rec, UUID_SERVCLASS_AV_REMOTE_CONTROL, &peer_rc_version);
+            APPL_TRACE_DEBUG1("peer_rc_version 0x%x", peer_rc_version);
+
+            if (peer_rc_version >= AVRC_REV_1_3)
+                peer_features |= (BTA_AV_FEAT_VENDOR | BTA_AV_FEAT_METADATA);
+
+            if (peer_rc_version >= AVRC_REV_1_4)
+            {
+                peer_features |= (BTA_AV_FEAT_ADV_CTRL);
+                /* get supported categories */
+                if ((p_attr = SDP_FindAttributeInRec(p_rec,
+                                ATTR_ID_SUPPORTED_FEATURES)) != NULL)
+                {
+                    categories = p_attr->attr_value.v.u16;
+                    if (categories & AVRC_SUPF_CT_BROWSE)
+                        peer_features |= (BTA_AV_FEAT_BROWSE);
+                }
+            }
+        }
+    }
+    APPL_TRACE_DEBUG1("peer_features:x%x", peer_features);
+    return peer_features;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_disc_done
+**
+** Description      Handle AVRCP service discovery results.  If matching
+**                  service found, open AVRCP connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_disc_done(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tBTA_AV_SCB  *p_scb = NULL;
+    tBTA_AV_LCB  *p_lcb;
+    tBTA_AV_RC_OPEN rc_open;
+    tBTA_AV_RC_FEAT rc_feat;
+    UINT8               rc_handle;
+    tBTA_AV_FEAT        peer_features;  /* peer features mask */
+
+    APPL_TRACE_DEBUG1("bta_av_rc_disc_done disc:x%x", p_cb->disc);
+    if (!p_cb->disc)
+    {
+        return;
+    }
+
+    if ((p_cb->disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK)
+    {
+        /* this is the rc handle/index to tBTA_AV_RCB */
+        rc_handle = p_cb->disc & (~BTA_AV_CHNL_MSK);
+    }
+    else
+    {
+        p_scb = p_cb->p_scb[(p_cb->disc & BTA_AV_HNDL_MSK) - 1];
+        if (p_scb)
+            rc_handle = p_scb->rc_handle;
+        else
+        {
+            p_cb->disc = 0;
+            return;
+        }
+    }
+
+    APPL_TRACE_DEBUG1("rc_handle %d", rc_handle);
+    peer_features = bta_av_check_peer_features (UUID_SERVCLASS_AV_REMOTE_CONTROL);
+    if ((p_cb->features & BTA_AV_FEAT_ADV_CTRL) && ((peer_features&BTA_AV_FEAT_ADV_CTRL) == 0))
+    {
+        /* if we support advance control and peer does not, check their support on TG role
+         * some implementation uses 1.3 on CT ans 1.4 on TG */
+        peer_features |= bta_av_check_peer_features (UUID_SERVCLASS_AV_REM_CTRL_TARGET);
+    }
+
+    p_cb->disc = 0;
+    utl_freebuf((void **) &p_cb->p_disc_db);
+
+    APPL_TRACE_DEBUG2("peer_features 0x%x, features 0x%x", peer_features, p_cb->features);
+
+    /* if we have no rc connection */
+    if (rc_handle == BTA_AV_RC_HANDLE_NONE)
+    {
+        if (p_scb)
+        {
+            /* if peer remote control service matches ours and USE_RC is TRUE */
+            if ((((p_cb->features & BTA_AV_FEAT_RCCT) && (peer_features & BTA_AV_FEAT_RCTG)) ||
+                 ((p_cb->features & BTA_AV_FEAT_RCTG) && (peer_features & BTA_AV_FEAT_RCCT))) )
+            {
+                p_lcb = bta_av_find_lcb(p_scb->peer_addr, BTA_AV_LCB_FIND);
+                if(p_lcb)
+                {
+                    rc_handle = bta_av_rc_create(p_cb, AVCT_INT, (UINT8)(p_scb->hdi + 1), p_lcb->lidx);
+                    p_cb->rcb[rc_handle].peer_features = peer_features;
+                }
+#if (BT_USE_TRACES == TRUE || BT_TRACE_APPL == TRUE)
+                else
+                {
+                    APPL_TRACE_ERROR0("can not find LCB!!");
+                }
+#endif
+            }
+            else if(p_scb->use_rc)
+            {
+                /* can not find AVRC on peer device. report failure */
+                p_scb->use_rc = FALSE;
+                bdcpy(rc_open.peer_addr, p_scb->peer_addr);
+                rc_open.peer_features = 0;
+                rc_open.status = BTA_AV_FAIL_SDP;
+                (*p_cb->p_cback)(BTA_AV_RC_OPEN_EVT, (tBTA_AV *) &rc_open);
+            }
+        }
+    }
+    else
+    {
+        p_cb->rcb[rc_handle].peer_features = peer_features;
+        rc_feat.rc_handle =  rc_handle;
+        rc_feat.peer_features = peer_features;
+        (*p_cb->p_cback)(BTA_AV_RC_FEAT_EVT, (tBTA_AV *) &rc_feat);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_closed
+**
+** Description      Set AVRCP state to closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_closed(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tBTA_AV_RC_CLOSE rc_close;
+    tBTA_AV_RC_CONN_CHG *p_msg = (tBTA_AV_RC_CONN_CHG *)p_data;
+    tBTA_AV_RCB    *p_rcb;
+    tBTA_AV_SCB    *p_scb;
+    int i;
+    BOOLEAN conn = FALSE;
+    tBTA_AV_LCB *p_lcb;
+
+    rc_close.rc_handle = BTA_AV_RC_HANDLE_NONE;
+    APPL_TRACE_DEBUG1("bta_av_rc_closed rc_handle:%d", p_msg->handle);
+    for(i=0; i<BTA_AV_NUM_RCB; i++)
+    {
+        p_rcb = &p_cb->rcb[i];
+        APPL_TRACE_DEBUG3("bta_av_rc_closed rcb[%d] rc_handle:%d, status=0x%x", i, p_rcb->handle, p_rcb->status);
+        if(p_rcb->handle == p_msg->handle)
+        {
+            rc_close.rc_handle = i;
+            p_rcb->status &= ~BTA_AV_RC_CONN_MASK;
+            p_rcb->peer_features = 0;
+            APPL_TRACE_DEBUG2("       shdl:%d, lidx:%d", p_rcb->shdl, p_rcb->lidx);
+            if(p_rcb->shdl)
+            {
+                p_scb = bta_av_cb.p_scb[p_rcb->shdl - 1];
+                if(p_scb)
+                {
+                    bdcpy(rc_close.peer_addr, p_scb->peer_addr);
+                    if(p_scb->rc_handle == p_rcb->handle)
+                        p_scb->rc_handle = BTA_AV_RC_HANDLE_NONE;
+                    APPL_TRACE_DEBUG2("shdl:%d, srch:%d", p_rcb->shdl, p_scb->rc_handle);
+                }
+                p_rcb->shdl = 0;
+            }
+            else if(p_rcb->lidx == (BTA_AV_NUM_LINKS + 1) )
+            {
+                /* if the RCB uses the extra LCB, use the addr for event and clean it */
+                p_lcb = &p_cb->lcb[BTA_AV_NUM_LINKS];
+                bdcpy(rc_close.peer_addr, p_msg->peer_addr);
+                APPL_TRACE_DEBUG6("rc_only closed bd_addr:%02x-%02x-%02x-%02x-%02x-%02x",
+                              p_msg->peer_addr[0], p_msg->peer_addr[1],
+                              p_msg->peer_addr[2], p_msg->peer_addr[3],
+                              p_msg->peer_addr[4], p_msg->peer_addr[5]);
+                p_lcb->conn_msk = 0;
+                p_lcb->lidx = 0;
+            }
+            p_rcb->lidx = 0;
+
+            if((p_rcb->status & BTA_AV_RC_ROLE_MASK) == BTA_AV_RC_ROLE_INT)
+            {
+                /* AVCT CCB is deallocated */
+                p_rcb->handle = BTA_AV_RC_HANDLE_NONE;
+                p_rcb->status = 0;
+            }
+            else
+            {
+                /* AVCT CCB is still there. dealloc */
+                bta_av_del_rc(p_rcb);
+
+                /* if the AVRCP is no longer listening, create the listening channel */
+                if (bta_av_cb.rc_acp_handle == BTA_AV_RC_HANDLE_NONE && bta_av_cb.features & BTA_AV_FEAT_RCTG)
+                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+            }
+        }
+        else if((p_rcb->handle != BTA_AV_RC_HANDLE_NONE) && (p_rcb->status & BTA_AV_RC_CONN_MASK))
+        {
+            /* at least one channel is still connected */
+            conn = TRUE;
+        }
+    }
+
+    if(!conn)
+    {
+        /* no AVRC channels are connected, go back to INIT state */
+        bta_av_sm_execute(p_cb, BTA_AV_AVRC_NONE_EVT, NULL);
+    }
+
+    if (rc_close.rc_handle == BTA_AV_RC_HANDLE_NONE)
+    {
+        rc_close.rc_handle = p_msg->handle;
+        bdcpy(rc_close.peer_addr, p_msg->peer_addr);
+    }
+    (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, (tBTA_AV *) &rc_close);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rc_disc
+**
+** Description      start AVRC SDP discovery.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_rc_disc(UINT8 disc)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tAVRC_SDP_DB_PARAMS db_params;
+      UINT16              attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST,
+                                       ATTR_ID_BT_PROFILE_DESC_LIST,
+                                       ATTR_ID_SUPPORTED_FEATURES};
+    UINT8       hdi;
+    tBTA_AV_SCB *p_scb;
+    UINT8       *p_addr = NULL;
+    UINT8       rc_handle;
+
+    APPL_TRACE_DEBUG2("bta_av_rc_disc 0x%x, %d", disc, bta_av_cb.disc);
+    if ((bta_av_cb.disc != 0) || (disc == 0))
+        return;
+
+    if ((disc & BTA_AV_CHNL_MSK) == BTA_AV_CHNL_MSK)
+    {
+        /* this is the rc handle/index to tBTA_AV_RCB */
+        rc_handle = disc & (~BTA_AV_CHNL_MSK);
+        if (p_cb->rcb[rc_handle].lidx)
+        {
+            p_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx-1].addr;
+        }
+    }
+    else
+    {
+        hdi = (disc & BTA_AV_HNDL_MSK) - 1;
+        p_scb = p_cb->p_scb[hdi];
+
+        if (p_scb)
+        {
+            APPL_TRACE_DEBUG1("rc_handle %d", p_scb->rc_handle);
+            p_addr = p_scb->peer_addr;
+        }
+    }
+
+    if (p_addr)
+    {
+        /* allocate discovery database */
+        if (p_cb->p_disc_db == NULL)
+        {
+            p_cb->p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_AV_DISC_BUF_SIZE);
+        }
+
+        if (p_cb->p_disc_db)
+        {
+            /* set up parameters */
+            db_params.db_len = BTA_AV_DISC_BUF_SIZE;
+            db_params.num_attr = 3;
+            db_params.p_db = p_cb->p_disc_db;
+            db_params.p_attrs = attr_list;
+
+            /* searching for UUID_SERVCLASS_AV_REMOTE_CONTROL gets both TG and CT */
+            if (AVRC_FindService(UUID_SERVCLASS_AV_REMOTE_CONTROL, p_addr, &db_params,
+                            bta_av_avrc_sdp_cback) == AVRC_SUCCESS)
+            {
+                p_cb->disc = disc;
+                APPL_TRACE_DEBUG1("disc %d", p_cb->disc);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_dereg_comp
+**
+** Description      deregister complete. free the stream control block.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_dereg_comp(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    tBTA_AV_SCB  *p_scb;
+    tBTA_UTL_COD    cod;
+    UINT8   mask;
+    BT_HDR  *p_buf;
+
+    /* find the stream control block */
+    p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
+
+    if(p_scb)
+    {
+        APPL_TRACE_DEBUG2("deregistered %d(h%d)", p_scb->chnl, p_scb->hndl);
+        mask = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+        if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+        {
+            p_cb->reg_audio  &= ~mask;
+            if ((p_cb->conn_audio & mask) && bta_av_cb.audio_open_cnt)
+            {
+                /* this channel is still marked as open. decrease the count */
+                bta_av_cb.audio_open_cnt--;
+            }
+            p_cb->conn_audio &= ~mask;
+
+            if (p_scb->q_tag == BTA_AV_Q_TAG_STREAM)
+            {
+            /* make sure no buffers are in q_info.a2d */
+            while((p_buf = (BT_HDR*)GKI_dequeue (&p_scb->q_info.a2d)) != NULL)
+                GKI_freebuf(p_buf);
+            }
+
+            /* remove the A2DP SDP record, if no more audio stream is left */
+            if(!p_cb->reg_audio)
+            {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+                bta_ar_dereg_avrc (UUID_SERVCLASS_AV_REMOTE_CONTROL, BTA_ID_AV);
+#endif
+                bta_av_del_sdp_rec(&p_cb->sdp_a2d_handle);
+                bta_sys_remove_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+            }
+        }
+        else
+        {
+            p_cb->reg_video  &= ~mask;
+            /* make sure that this channel is not connected */
+            p_cb->conn_video &= ~mask;
+            /* remove the VDP SDP record, (only one video stream at most) */
+            bta_av_del_sdp_rec(&p_cb->sdp_vdp_handle);
+            bta_sys_remove_uuid(UUID_SERVCLASS_VIDEO_SOURCE);
+        }
+
+        /* make sure that the timer is not active */
+        bta_sys_stop_timer(&p_scb->timer);
+        utl_freebuf((void **)&p_cb->p_scb[p_scb->hdi]);
+    }
+
+    APPL_TRACE_DEBUG3("audio 0x%x, video: 0x%x, disable:%d",
+        p_cb->reg_audio, p_cb->reg_video, p_cb->disabling);
+    /* if no stream control block is active */
+    if((p_cb->reg_audio + p_cb->reg_video) == 0)
+    {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+        /* deregister from AVDT */
+        bta_ar_dereg_avdt(BTA_ID_AV);
+
+        /* deregister from AVCT */
+        bta_ar_dereg_avrc (UUID_SERVCLASS_AV_REM_CTRL_TARGET, BTA_ID_AV);
+        bta_ar_dereg_avct(BTA_ID_AV);
+#endif
+
+        if(p_cb->disabling)
+        {
+            p_cb->disabling     = FALSE;
+            bta_av_cb.features  = 0;
+        }
+
+        /* Clear the Capturing service class bit */
+        cod.service = BTM_COD_SERVICE_CAPTURING;
+        utl_set_device_class(&cod, BTA_UTL_CLR_COD_SERVICE_CLASS);
+    }
+}
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_api.c b/bta/av/bta_av_api.c
new file mode 100644
index 0000000..a58e4a6
--- /dev/null
+++ b/bta/av/bta_av_api.c
@@ -0,0 +1,581 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2011-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 is the implementation of the API for the advanced audio/video (AV)
+ *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_av_api.h"
+#include "bta_av_int.h"
+#include "gki.h"
+#include <string.h>
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_av_reg =
+{
+    bta_av_hdl_event,
+    BTA_AvDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_AvEnable
+**
+** Description      Enable the advanced audio/video service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_AV_ENABLE_EVT. This function must
+**                  be called before other function in the AV API are
+**                  called.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features, tBTA_AV_CBACK *p_cback)
+{
+    tBTA_AV_API_ENABLE  *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_AV, &bta_av_reg);
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_AV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_AV_API_ENABLE))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_ENABLE_EVT;
+        p_buf->p_cback  = p_cback;
+        p_buf->features = features;
+        p_buf->sec_mask = sec_mask;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvDisable
+**
+** Description      Disable the advanced audio/video service.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    bta_sys_deregister(BTA_ID_AV);
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AV_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvRegister
+**
+** Description      Register the audio or video service to stack. When the
+**                  operation is complete the callback function will be
+**                  called with a BTA_AV_REGISTER_EVT. This function must
+**                  be called before AVDT stream is open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name, UINT8 app_id)
+{
+    tBTA_AV_API_REG  *p_buf;
+
+
+    if ((p_buf = (tBTA_AV_API_REG *) GKI_getbuf(sizeof(tBTA_AV_API_REG))) != NULL)
+    {
+        p_buf->hdr.layer_specific   = chnl;
+        p_buf->hdr.event = BTA_AV_API_REGISTER_EVT;
+        if(p_service_name)
+        {
+            BCM_STRNCPY_S(p_buf->p_service_name, sizeof(p_buf->p_service_name), p_service_name, BTA_SERVICE_NAME_LEN);
+            p_buf->p_service_name[BTA_SERVICE_NAME_LEN-1] = 0;
+        }
+        else
+        {
+            p_buf->p_service_name[0] = 0;
+        }
+        p_buf->app_id = app_id;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvDeregister
+**
+** Description      Deregister the audio or video service
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvDeregister(tBTA_AV_HNDL hndl)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->layer_specific   = hndl;
+        p_buf->event = BTA_AV_API_DEREGISTER_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvOpen
+**
+** Description      Opens an advanced audio/video connection to a peer device.
+**                  When connection is open callback function is called
+**                  with a BTA_AV_OPEN_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle, BOOLEAN use_rc, tBTA_SEC sec_mask)
+{
+    tBTA_AV_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_OPEN *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_OPEN_EVT;
+        p_buf->hdr.layer_specific   = handle;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        p_buf->use_rc = use_rc;
+        p_buf->sec_mask = sec_mask;
+        p_buf->switch_res = BTA_AV_RS_NONE;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvClose
+**
+** Description      Close the current streams.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvClose(tBTA_AV_HNDL handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AV_API_CLOSE_EVT;
+        p_buf->layer_specific   = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvDisconnect
+**
+** Description      Close the connection to the address.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvDisconnect(BD_ADDR bd_addr)
+{
+    tBTA_AV_API_DISCNT  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_DISCNT *) GKI_getbuf(sizeof(tBTA_AV_API_DISCNT))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_DISCONNECT_EVT;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvStart
+**
+** Description      Start audio/video stream data transfer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvStart(void)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_AV_API_START_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvStop
+**
+** Description      Stop audio/video stream data transfer.
+**                  If suspend is TRUE, this function sends AVDT suspend signal
+**                  to the connected peer(s).
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvStop(BOOLEAN suspend)
+{
+    tBTA_AV_API_STOP  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_STOP *) GKI_getbuf(sizeof(tBTA_AV_API_STOP))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_STOP_EVT;
+        p_buf->flush   = TRUE;
+        p_buf->suspend = suspend;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvReconfig
+**
+** Description      Reconfigure the audio/video stream.
+**                  If suspend is TRUE, this function tries the suspend/reconfigure
+**                  procedure first.
+**                  If suspend is FALSE or when suspend/reconfigure fails,
+**                  this function closes and re-opens the AVDT connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
+                    UINT8 *p_codec_info, UINT8 num_protect, UINT8 *p_protect_info)
+{
+    tBTA_AV_API_RCFG  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_RCFG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_RCFG) + num_protect))) != NULL)
+    {
+        p_buf->hdr.layer_specific   = hndl;
+        p_buf->hdr.event    = BTA_AV_API_RECONFIG_EVT;
+        p_buf->num_protect  = num_protect;
+        p_buf->suspend      = suspend;
+        p_buf->sep_info_idx = sep_info_idx;
+        p_buf->p_protect_info = (UINT8 *)(p_buf + 1);
+        memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
+        memcpy(p_buf->p_protect_info, p_protect_info, num_protect);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvProtectReq
+**
+** Description      Send a content protection request.  This function can only
+**                  be used if AV is enabled with feature BTA_AV_FEAT_PROTECT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len)
+{
+    tBTA_AV_API_PROTECT_REQ  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_PROTECT_REQ *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_PROTECT_REQ) + len))) != NULL)
+    {
+        p_buf->hdr.layer_specific   = hndl;
+        p_buf->hdr.event = BTA_AV_API_PROTECT_REQ_EVT;
+        p_buf->len       = len;
+        if (p_data == NULL)
+        {
+            p_buf->p_data = NULL;
+        }
+        else
+        {
+            p_buf->p_data = (UINT8 *) (p_buf + 1);
+            memcpy(p_buf->p_data, p_data, len);
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvProtectRsp
+**
+** Description      Send a content protection response.  This function must
+**                  be called if a BTA_AV_PROTECT_REQ_EVT is received.
+**                  This function can only be used if AV is enabled with
+**                  feature BTA_AV_FEAT_PROTECT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data, UINT16 len)
+{
+    tBTA_AV_API_PROTECT_RSP  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_PROTECT_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_PROTECT_RSP) + len))) != NULL)
+    {
+        p_buf->hdr.layer_specific   = hndl;
+        p_buf->hdr.event    = BTA_AV_API_PROTECT_RSP_EVT;
+        p_buf->len          = len;
+        p_buf->error_code   = error_code;
+        if (p_data == NULL)
+        {
+            p_buf->p_data = NULL;
+        }
+        else
+        {
+            p_buf->p_data = (UINT8 *) (p_buf + 1);
+            memcpy(p_buf->p_data, p_data, len);
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvRemoteCmd
+**
+** Description      Send a remote control command.  This function can only
+**                  be used if AV is enabled with feature BTA_AV_FEAT_RCCT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id, tBTA_AV_STATE key_state)
+{
+    tBTA_AV_API_REMOTE_CMD  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_REMOTE_CMD *) GKI_getbuf(sizeof(tBTA_AV_API_REMOTE_CMD))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_REMOTE_CMD_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        p_buf->msg.op_id = rc_id;
+        p_buf->msg.state = key_state;
+        p_buf->msg.p_pass_data = NULL;
+        p_buf->msg.pass_len = 0;
+        p_buf->label = label;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvVendorCmd
+**
+** Description      Send a vendor dependent remote control command.  This
+**                  function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_VENDOR.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code, UINT8 *p_data, UINT16 len)
+{
+    tBTA_AV_API_VENDOR  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_VENDOR *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_VENDOR_CMD_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        p_buf->msg.hdr.ctype = cmd_code;
+        p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
+        p_buf->msg.hdr.subunit_id = 0;
+        p_buf->msg.company_id = p_bta_av_cfg->company_id;
+        p_buf->label = label;
+        p_buf->msg.vendor_len = len;
+        if (p_data == NULL)
+        {
+            p_buf->msg.p_vendor_data = NULL;
+        }
+        else
+        {
+            p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
+            memcpy(p_buf->msg.p_vendor_data, p_data, len);
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvVendorRsp
+**
+** Description      Send a vendor dependent remote control response.
+**                  This function must be called if a BTA_AV_VENDOR_CMD_EVT
+**                  is received. This function can only be used if AV is
+**                  enabled with feature BTA_AV_FEAT_VENDOR.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code, UINT8 *p_data, UINT16 len, UINT32 company_id)
+{
+    tBTA_AV_API_VENDOR  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_VENDOR *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_VENDOR) + len))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_VENDOR_RSP_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        p_buf->msg.hdr.ctype = rsp_code;
+        p_buf->msg.hdr.subunit_type = AVRC_SUB_PANEL;
+        p_buf->msg.hdr.subunit_id = 0;
+        if(company_id)
+            p_buf->msg.company_id = company_id;
+        else
+            p_buf->msg.company_id = p_bta_av_cfg->company_id;
+        p_buf->label = label;
+        p_buf->msg.vendor_len = len;
+        if (p_data == NULL)
+        {
+            p_buf->msg.p_vendor_data = NULL;
+        }
+        else
+        {
+            p_buf->msg.p_vendor_data = (UINT8 *) (p_buf + 1);
+            memcpy(p_buf->msg.p_vendor_data, p_data, len);
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvOpenRc
+**
+** Description      Open an AVRCP connection toward the device with the
+**                  specified handle
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvOpenRc(tBTA_AV_HNDL handle)
+{
+    tBTA_AV_API_OPEN_RC  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_OPEN_RC *) GKI_getbuf(sizeof(tBTA_AV_API_OPEN_RC))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_RC_OPEN_EVT;
+        p_buf->hdr.layer_specific   = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvCloseRc
+**
+** Description      Close an AVRCP connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvCloseRc(UINT8 rc_handle)
+{
+    tBTA_AV_API_CLOSE_RC  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_CLOSE_RC *) GKI_getbuf(sizeof(tBTA_AV_API_CLOSE_RC))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_RC_CLOSE_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvMetaRsp
+**
+** Description      Send a Metadata/Advanced Control response. The message contained
+**                  in p_pkt can be composed with AVRC utility functions.
+**                  This function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_METADATA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+                               BT_HDR *p_pkt)
+{
+    tBTA_AV_API_META_RSP  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_META_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        p_buf->rsp_code = rsp_code;
+        p_buf->p_pkt = p_pkt;
+        p_buf->is_rsp = TRUE;
+        p_buf->label = label;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_AvMetaCmd
+**
+** Description      Send a Metadata/Advanced Control command. The message contained
+**                  in p_pkt can be composed with AVRC utility functions.
+**                  This function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_METADATA.
+**                  This message is sent only when the peer supports the TG role.
+*8                  The only command makes sense right now is the absolute volume command.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt)
+{
+    tBTA_AV_API_META_RSP  *p_buf;
+
+    if ((p_buf = (tBTA_AV_API_META_RSP *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_API_META_RSP)))) != NULL)
+    {
+        p_buf->hdr.event = BTA_AV_API_META_RSP_EVT;
+        p_buf->hdr.layer_specific   = rc_handle;
+        p_buf->p_pkt = p_pkt;
+        p_buf->rsp_code = cmd_code;
+        p_buf->is_rsp = FALSE;
+        p_buf->label = label;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
new file mode 100644
index 0000000..793c772
--- /dev/null
+++ b/bta/av/bta_av_cfg.c
@@ -0,0 +1,231 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 compile-time configurable constants for advanced
+ *  audio/video
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "bta_api.h"
+#include "bta_av_int.h"
+
+
+
+#ifndef BTA_AV_RC_PASS_RSP_CODE
+#define BTA_AV_RC_PASS_RSP_CODE     BTA_AV_RSP_NOT_IMPL
+#endif
+
+
+const UINT32  bta_av_meta_caps_co_ids[] = {
+    AVRC_CO_METADATA,
+    AVRC_CO_BROADCOM
+};
+
+/* AVRCP cupported categories */
+#define BTA_AV_RC_SUPF_CT       (AVRC_SUPF_CT_CAT2)
+
+
+/* Added to modify
+**	1. flush timeout
+**	2. Remove Group navigation support in SupportedFeatures
+**	3. GetCapabilities supported event_ids list
+**	4. GetCapabilities supported event_ids count
+*/
+#ifdef ANDROID_APP_INCLUDED
+/* Flushing partial avdtp packets can cause some headsets to disconnect the link
+   if receiving partial a2dp frames */
+const UINT16  bta_av_audio_flush_to[] = {
+     0, /* 1 stream */
+     0, /* 2 streams */
+     0, /* 3 streams */
+     0, /* 4 streams */
+     0  /* 5 streams */
+};     /* AVDTP audio transport channel flush timeout */
+
+/* Note: Android doesnt support AVRC_SUPF_TG_GROUP_NAVI  */
+#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1)
+
+
+/*
+ * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS   also needs to be changed.
+ */
+const UINT8  bta_av_meta_caps_evt_ids[] = {
+    AVRC_EVT_PLAY_STATUS_CHANGE,
+    AVRC_EVT_TRACK_CHANGE,
+    AVRC_EVT_PLAY_POS_CHANGED,
+    AVRC_EVT_APP_SETTING_CHANGE,
+};
+#ifndef BTA_AV_NUM_RC_EVT_IDS
+#define BTA_AV_NUM_RC_EVT_IDS   (sizeof(bta_av_meta_caps_evt_ids) / sizeof(bta_av_meta_caps_evt_ids[0]))
+#endif /* BTA_AV_NUM_RC_EVT_IDS */
+
+
+#else /* !ANDROID_APP_INCLUDED */
+
+/* Note: if AVRC_SUPF_TG_GROUP_NAVI is set, bta_av_cfg.avrc_group should be TRUE */
+#define BTA_AV_RC_SUPF_TG       (AVRC_SUPF_TG_CAT1)
+
+const UINT16  bta_av_audio_flush_to[] = {
+    120, /* 1 stream  */
+    100, /* 2 streams */
+     80, /* 3 streams */
+     60, /* 4 streams */
+     40  /* 5 streams */
+};     /* AVDTP audio transport channel flush timeout */
+
+
+/*
+ * If the number of event IDs is changed in this array, BTA_AV_ NUM_RC_EVT_IDS   also needs to be changed.
+ */
+const UINT8  bta_av_meta_caps_evt_ids[] = {
+    AVRC_EVT_PLAY_STATUS_CHANGE,
+    AVRC_EVT_TRACK_CHANGE,
+    AVRC_EVT_TRACK_REACHED_END,
+    AVRC_EVT_TRACK_REACHED_START,
+    AVRC_EVT_PLAY_POS_CHANGED,
+    AVRC_EVT_BATTERY_STATUS_CHANGE,
+    AVRC_EVT_SYSTEM_STATUS_CHANGE,
+    AVRC_EVT_APP_SETTING_CHANGE,
+};
+
+#ifndef BTA_AV_NUM_RC_EVT_IDS
+#define BTA_AV_NUM_RC_EVT_IDS   8
+#endif
+
+#endif /* ANDROID_APP_INCLUDED */
+
+/* the MTU for the AVRCP browsing channel */
+#ifndef BTA_AV_MAX_RC_BR_MTU
+#define BTA_AV_MAX_RC_BR_MTU      1008
+#endif
+
+const tBTA_AV_CFG bta_av_cfg =
+{
+    AVRC_CO_BROADCOM,       /* AVRCP Company ID */
+    48,                     /* AVRCP MTU at L2CAP for control channel */
+    BTA_AV_MAX_RC_BR_MTU,   /* AVRCP MTU at L2CAP for browsing channel */
+    BTA_AV_RC_SUPF_CT,      /* AVRCP controller categories */
+    BTA_AV_RC_SUPF_TG,      /* AVRCP target categories */
+    672,                    /* AVDTP signaling channel MTU at L2CAP */
+    BTA_AV_MAX_A2DP_MTU,    /* AVDTP audio transport channel MTU at L2CAP */
+    bta_av_audio_flush_to,  /* AVDTP audio transport channel flush timeout */
+    6,                      /* AVDTP audio channel max data queue size */
+    BTA_AV_MAX_VDP_MTU,     /* AVDTP video transport channel MTU at L2CAP */
+    600,                    /* AVDTP video transport channel flush timeout */
+    TRUE,                   /* TRUE, to accept AVRC 1.3 group nevigation command */
+    2,                      /* company id count in p_meta_co_ids */
+    BTA_AV_NUM_RC_EVT_IDS, /* event id count in p_meta_evt_ids */
+    BTA_AV_RC_PASS_RSP_CODE,/* the default response code for pass through commands */
+    bta_av_meta_caps_co_ids,/* the metadata Get Capabilities response for company id */
+    bta_av_meta_caps_evt_ids,/* the the metadata Get Capabilities response for event id */
+};
+
+tBTA_AV_CFG *p_bta_av_cfg = (tBTA_AV_CFG *) &bta_av_cfg;
+
+const UINT16 bta_av_rc_id[] =
+{
+    0x021F, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
+                         4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN, 7=LEFT_UP,
+                         8=LEFT_DOWN, 9=ROOT_MENU, 10=SETUP_MENU, 11=CONT_MENU,
+                         12=FAV_MENU, 13=EXIT */
+
+    0,      /* not used */
+
+    0x0000, /* bit mask: 0=0, 1=1, 2=2, 3=3,
+                         4=4, 5=5, 6=6, 7=7,
+                         8=8, 9=9, 10=DOT, 11=ENTER,
+                         12=CLEAR */
+
+    0x0003, /* bit mask: 0=CHAN_UP, 1=CHAN_DOWN, 2=PREV_CHAN, 3=SOUND_SEL,
+                         4=INPUT_SEL, 5=DISP_INFO, 6=HELP, 7=PAGE_UP,
+                         8=PAGE_DOWN */
+
+#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+    /* btui_app provides an example of how to leave the decision of rejecting a command or not
+     * based on which media player is currently addressed (this is only applicable for AVRCP 1.4 or later)
+     * If the decision is per player for a particular rc_id, the related bit is clear (not set) */
+    0x0070, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+                         4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+                         8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+                         12=BACKWARD */
+#else
+#if (defined BTA_AVRCP_FF_RW_SUPPORT) && (BTA_AVRCP_FF_RW_SUPPORT == TRUE)
+    0x1b70, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+                         4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+                         8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+                         12=BACKWARD */
+#else
+    0x1870, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+                         4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+                         8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+                         12=BACKWARD */
+#endif
+#endif
+
+    0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
+
+    0,      /* not used */
+
+    0x0000  /* bit mask: 0=not used, 1=F1, 2=F2, 3=F3,
+                         4=F4, 5=F5 */
+};
+
+#if (BTA_AV_RC_PASS_RSP_CODE == BTA_AV_RSP_INTERIM)
+const UINT16 bta_av_rc_id_ac[] =
+{
+    0x0000, /* bit mask: 0=SELECT, 1=UP, 2=DOWN, 3=LEFT,
+                         4=RIGHT, 5=RIGHT_UP, 6=RIGHT_DOWN, 7=LEFT_UP,
+                         8=LEFT_DOWN, 9=ROOT_MENU, 10=SETUP_MENU, 11=CONT_MENU,
+                         12=FAV_MENU, 13=EXIT */
+
+    0,      /* not used */
+
+    0x0000, /* bit mask: 0=0, 1=1, 2=2, 3=3,
+                         4=4, 5=5, 6=6, 7=7,
+                         8=8, 9=9, 10=DOT, 11=ENTER,
+                         12=CLEAR */
+
+    0x0000, /* bit mask: 0=CHAN_UP, 1=CHAN_DOWN, 2=PREV_CHAN, 3=SOUND_SEL,
+                         4=INPUT_SEL, 5=DISP_INFO, 6=HELP, 7=PAGE_UP,
+                         8=PAGE_DOWN */
+
+    /* btui_app provides an example of how to leave the decision of rejecting a command or not
+     * based on which media player is currently addressed (this is only applicable for AVRCP 1.4 or later)
+     * If the decision is per player for a particular rc_id, the related bit is set */
+    0x1800, /* bit mask: 0=POWER, 1=VOL_UP, 2=VOL_DOWN, 3=MUTE,
+                         4=PLAY, 5=STOP, 6=PAUSE, 7=RECORD,
+                         8=REWIND, 9=FAST_FOR, 10=EJECT, 11=FORWARD,
+                         12=BACKWARD */
+
+    0x0000, /* bit mask: 0=ANGLE, 1=SUBPICT */
+
+    0,      /* not used */
+
+    0x0000  /* bit mask: 0=not used, 1=F1, 2=F2, 3=F3,
+                         4=F4, 5=F5 */
+};
+UINT16 *p_bta_av_rc_id_ac = (UINT16 *) bta_av_rc_id_ac;
+#else
+UINT16 *p_bta_av_rc_id_ac = NULL;
+#endif
+
+UINT16 *p_bta_av_rc_id = (UINT16 *) bta_av_rc_id;
diff --git a/bta/av/bta_av_ci.c b/bta/av/bta_av_ci.c
new file mode 100644
index 0000000..a1c2ac0
--- /dev/null
+++ b/bta/av/bta_av_ci.c
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 is the implementation file for advanced audio/video call-in
+ *  functions.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_av_int.h"
+#include "bta_av_ci.h"
+
+#include <string.h>
+
+/*******************************************************************************
+**
+** Function         bta_av_ci_src_data_ready
+**
+** Description      This function sends an event to the AV indicating that
+**                  the phone has audio stream data ready to send and AV
+**                  should call bta_av_co_audio_src_data_path() or
+**                  bta_av_co_video_src_data_path().
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->layer_specific   = chnl;
+        p_buf->event = BTA_AV_CI_SRC_DATA_READY_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_ci_setconfig
+**
+** Description      This function must be called in response to function
+**                  bta_av_co_audio_setconfig() or bta_av_co_video_setconfig.
+**                  Parameter err_code is set to an AVDTP status value;
+**                  AVDT_SUCCESS if the codec configuration is ok,
+**                  otherwise error.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code, UINT8 category,
+                         UINT8 num_seid, UINT8 *p_seid, BOOLEAN recfg_needed)
+{
+    tBTA_AV_CI_SETCONFIG  *p_buf;
+
+    if ((p_buf = (tBTA_AV_CI_SETCONFIG *) GKI_getbuf(sizeof(tBTA_AV_CI_SETCONFIG))) != NULL)
+    {
+        p_buf->hdr.layer_specific   = hndl;
+        p_buf->hdr.event = (err_code == AVDT_SUCCESS) ?
+                           BTA_AV_CI_SETCONFIG_OK_EVT : BTA_AV_CI_SETCONFIG_FAIL_EVT;
+        p_buf->err_code = err_code;
+        p_buf->category = category;
+        p_buf->recfg_needed = recfg_needed;
+        p_buf->num_seid = num_seid;
+        if(p_seid && num_seid)
+        {
+            p_buf->p_seid   = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->p_seid, p_seid, num_seid);
+        }
+        else
+        {
+            p_buf->p_seid   = NULL;
+            p_buf->num_seid = 0;
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
new file mode 100644
index 0000000..05eb114
--- /dev/null
+++ b/bta/av/bta_av_int.h
@@ -0,0 +1,719 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the private interface file for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_INT_H
+#define BTA_AV_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_av_api.h"
+#include "avdt_api.h"
+#include "bta_av_co.h"
+
+#define BTA_AV_DEBUG TRUE
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+enum
+{
+    /* these events are handled by the AV main state machine */
+    BTA_AV_API_DISABLE_EVT = BTA_SYS_EVT_START(BTA_ID_AV),
+    BTA_AV_API_REMOTE_CMD_EVT,
+    BTA_AV_API_VENDOR_CMD_EVT,
+    BTA_AV_API_VENDOR_RSP_EVT,
+    BTA_AV_API_META_RSP_EVT,
+    BTA_AV_API_RC_CLOSE_EVT,
+    BTA_AV_AVRC_OPEN_EVT,
+    BTA_AV_AVRC_MSG_EVT,
+    BTA_AV_AVRC_NONE_EVT,
+
+    /* these events are handled by the AV stream state machine */
+    BTA_AV_API_OPEN_EVT,
+    BTA_AV_API_CLOSE_EVT,
+    BTA_AV_AP_START_EVT,        /* the following 2 events must be in the same order as the *API_*EVT */
+    BTA_AV_AP_STOP_EVT,
+    BTA_AV_API_RECONFIG_EVT,
+    BTA_AV_API_PROTECT_REQ_EVT,
+    BTA_AV_API_PROTECT_RSP_EVT,
+    BTA_AV_API_RC_OPEN_EVT,
+    BTA_AV_SRC_DATA_READY_EVT,
+    BTA_AV_CI_SETCONFIG_OK_EVT,
+    BTA_AV_CI_SETCONFIG_FAIL_EVT,
+    BTA_AV_SDP_DISC_OK_EVT,
+    BTA_AV_SDP_DISC_FAIL_EVT,
+    BTA_AV_STR_DISC_OK_EVT,
+    BTA_AV_STR_DISC_FAIL_EVT,
+    BTA_AV_STR_GETCAP_OK_EVT,
+    BTA_AV_STR_GETCAP_FAIL_EVT,
+    BTA_AV_STR_OPEN_OK_EVT,
+    BTA_AV_STR_OPEN_FAIL_EVT,
+    BTA_AV_STR_START_OK_EVT,
+    BTA_AV_STR_START_FAIL_EVT,
+    BTA_AV_STR_CLOSE_EVT,
+    BTA_AV_STR_CONFIG_IND_EVT,
+    BTA_AV_STR_SECURITY_IND_EVT,
+    BTA_AV_STR_SECURITY_CFM_EVT,
+    BTA_AV_STR_WRITE_CFM_EVT,
+    BTA_AV_STR_SUSPEND_CFM_EVT,
+    BTA_AV_STR_RECONFIG_CFM_EVT,
+    BTA_AV_AVRC_TIMER_EVT,
+    BTA_AV_AVDT_CONNECT_EVT,
+    BTA_AV_AVDT_DISCONNECT_EVT,
+    BTA_AV_ROLE_CHANGE_EVT,
+    BTA_AV_AVDT_DELAY_RPT_EVT,
+    BTA_AV_ACP_CONNECT_EVT,
+
+    /* these events are handled outside of the state machine */
+    BTA_AV_API_ENABLE_EVT,
+    BTA_AV_API_REGISTER_EVT,
+    BTA_AV_API_DEREGISTER_EVT,
+    BTA_AV_API_DISCONNECT_EVT,
+    BTA_AV_CI_SRC_DATA_READY_EVT,
+    BTA_AV_SIG_CHG_EVT,
+    BTA_AV_SIG_TIMER_EVT,
+    BTA_AV_SDP_AVRC_DISC_EVT,
+    BTA_AV_AVRC_CLOSE_EVT,
+    BTA_AV_CONN_CHG_EVT,
+    BTA_AV_DEREG_COMP_EVT,
+#if (AVDT_REPORTING == TRUE)
+    BTA_AV_AVDT_RPT_CONN_EVT,
+#endif
+    BTA_AV_API_START_EVT,       /* the following 2 events must be in the same order as the *AP_*EVT */
+    BTA_AV_API_STOP_EVT
+};
+
+/* events for AV control block state machine */
+#define BTA_AV_FIRST_SM_EVT     BTA_AV_API_DISABLE_EVT
+#define BTA_AV_LAST_SM_EVT      BTA_AV_AVRC_NONE_EVT
+
+/* events for AV stream control block state machine */
+#define BTA_AV_FIRST_SSM_EVT    BTA_AV_API_OPEN_EVT
+
+/* events that do not go through state machine */
+#define BTA_AV_FIRST_NSM_EVT    BTA_AV_API_ENABLE_EVT
+#define BTA_AV_LAST_NSM_EVT     BTA_AV_API_STOP_EVT
+
+/* API events passed to both SSMs (by bta_av_api_to_ssm) */
+#define BTA_AV_FIRST_A2S_API_EVT    BTA_AV_API_START_EVT
+#define BTA_AV_FIRST_A2S_SSM_EVT    BTA_AV_AP_START_EVT
+
+#define BTA_AV_LAST_EVT             BTA_AV_API_STOP_EVT
+
+/* maximum number of SEPS in stream discovery results */
+#define BTA_AV_NUM_SEPS         32
+
+/* initialization value for AVRC handle */
+#define BTA_AV_RC_HANDLE_NONE   0xFF
+
+/* size of database for service discovery */
+#define BTA_AV_DISC_BUF_SIZE        1000
+
+/* offset of media type in codec info byte array */
+#define BTA_AV_MEDIA_TYPE_IDX       1
+
+/* maximum length of AVDTP security data */
+#define BTA_AV_SECURITY_MAX_LEN     400
+
+/* check number of buffers queued at L2CAP when this amount of buffers are queued to L2CAP */
+#define BTA_AV_QUEUE_DATA_CHK_NUM   5
+
+/* the number of ACL links with AVDT */
+#define BTA_AV_NUM_LINKS            AVDT_NUM_LINKS
+
+#define BTA_AV_CO_ID_TO_BE_STREAM(p, u32) {*(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)(u32); }
+#define BTA_AV_BE_STREAM_TO_CO_ID(u32, p) {u32 = (((UINT32)(*((p) + 2))) + (((UINT32)(*((p) + 1))) << 8) + (((UINT32)(*(p))) << 16)); (p) += 3;}
+
+/* these bits are defined for bta_av_cb.multi_av */
+#define BTA_AV_MULTI_AV_SUPPORTED   0x01
+#define BTA_AV_MULTI_AV_IN_USE      0x02
+
+
+/*****************************************************************************
+**  Data types
+*****************************************************************************/
+
+/* function types for call-out functions */
+typedef BOOLEAN (*tBTA_AV_CO_INIT) (UINT8 *p_codec_type, UINT8 *p_codec_info,
+                                   UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+
+typedef void (*tBTA_AV_CO_DISC_RES) (tBTA_AV_HNDL hndl, UINT8 num_seps,
+                                     UINT8 num_snk, BD_ADDR addr);
+
+typedef UINT8 (*tBTA_AV_CO_GETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                     UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+                                     UINT8 *p_num_protect, UINT8 *p_protect_info);
+typedef void (*tBTA_AV_CO_SETCFG) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                    UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+                                    UINT8 num_protect, UINT8 *p_protect_info);
+typedef void (*tBTA_AV_CO_OPEN) (tBTA_AV_HNDL hndl,
+                                 tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+                                   UINT16 mtu);
+typedef void (*tBTA_AV_CO_CLOSE) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type, UINT16 mtu);
+typedef void (*tBTA_AV_CO_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+typedef void (*tBTA_AV_CO_STOP) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+typedef void * (*tBTA_AV_CO_DATAPATH) (tBTA_AV_CODEC codec_type,
+                                       UINT32 *p_len, UINT32 *p_timestamp);
+typedef void (*tBTA_AV_CO_DELAY) (tBTA_AV_HNDL hndl, UINT16 delay);
+
+/* the call-out functions for one stream */
+typedef struct
+{
+    tBTA_AV_CO_INIT     init;
+    tBTA_AV_CO_DISC_RES disc_res;
+    tBTA_AV_CO_GETCFG   getcfg;
+    tBTA_AV_CO_SETCFG   setcfg;
+    tBTA_AV_CO_OPEN     open;
+    tBTA_AV_CO_CLOSE    close;
+    tBTA_AV_CO_START    start;
+    tBTA_AV_CO_STOP     stop;
+    tBTA_AV_CO_DATAPATH data;
+    tBTA_AV_CO_DELAY    delay;
+} tBTA_AV_CO_FUNCTS;
+
+/* data type for BTA_AV_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_AV_CBACK       *p_cback;
+    tBTA_AV_FEAT        features;
+    tBTA_SEC            sec_mask;
+} tBTA_AV_API_ENABLE;
+
+/* data type for BTA_AV_API_REG_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    char                p_service_name[BTA_SERVICE_NAME_LEN+1];
+    UINT8               app_id;
+} tBTA_AV_API_REG;
+
+
+enum
+{
+    BTA_AV_RS_NONE,     /* straight API call */
+    BTA_AV_RS_OK,       /* the role switch result - successful */
+    BTA_AV_RS_FAIL,     /* the role switch result - failed */
+    BTA_AV_RS_DONE      /* the role switch is done - continue */
+};
+typedef UINT8 tBTA_AV_RS_RES;
+/* data type for BTA_AV_API_OPEN_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    BOOLEAN             use_rc;
+    tBTA_SEC            sec_mask;
+    tBTA_AV_RS_RES      switch_res;
+} tBTA_AV_API_OPEN;
+
+/* data type for BTA_AV_API_STOP_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BOOLEAN             suspend;
+    BOOLEAN             flush;
+} tBTA_AV_API_STOP;
+
+/* data type for BTA_AV_API_DISCONNECT_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+} tBTA_AV_API_DISCNT;
+
+/* data type for BTA_AV_API_PROTECT_REQ_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               *p_data;
+    UINT16              len;
+} tBTA_AV_API_PROTECT_REQ;
+
+/* data type for BTA_AV_API_PROTECT_RSP_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               *p_data;
+    UINT16              len;
+    UINT8               error_code;
+} tBTA_AV_API_PROTECT_RSP;
+
+/* data type for BTA_AV_API_REMOTE_CMD_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tAVRC_MSG_PASS      msg;
+    UINT8               label;
+} tBTA_AV_API_REMOTE_CMD;
+
+/* data type for BTA_AV_API_VENDOR_CMD_EVT and RSP */
+typedef struct
+{
+    BT_HDR              hdr;
+    tAVRC_MSG_VENDOR    msg;
+    UINT8               label;
+} tBTA_AV_API_VENDOR;
+
+/* data type for BTA_AV_API_RC_OPEN_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+} tBTA_AV_API_OPEN_RC;
+
+/* data type for BTA_AV_API_RC_CLOSE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+} tBTA_AV_API_CLOSE_RC;
+
+/* data type for BTA_AV_API_META_RSP_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BOOLEAN             is_rsp;
+    UINT8               label;
+    tBTA_AV_CODE        rsp_code;
+    BT_HDR              *p_pkt;
+} tBTA_AV_API_META_RSP;
+
+
+/* data type for BTA_AV_API_RECONFIG_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               codec_info[AVDT_CODEC_SIZE];    /* codec configuration */
+    UINT8               *p_protect_info;
+    UINT8               num_protect;
+    BOOLEAN             suspend;
+    UINT8               sep_info_idx;
+} tBTA_AV_API_RCFG;
+
+/* data type for BTA_AV_CI_SETCONFIG_OK_EVT and BTA_AV_CI_SETCONFIG_FAIL_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_AV_HNDL        hndl;
+    UINT8               err_code;
+    UINT8               category;
+    UINT8               num_seid;
+    UINT8               *p_seid;
+    BOOLEAN             recfg_needed;
+} tBTA_AV_CI_SETCONFIG;
+
+/* data type for all stream events from AVDTP */
+typedef struct {
+    BT_HDR              hdr;
+    tAVDT_CFG           cfg;        /* configuration/capabilities parameters */
+    tAVDT_CTRL          msg;        /* AVDTP callback message parameters */
+    BD_ADDR             bd_addr;    /* bd address */
+    UINT8               handle;
+    UINT8               avdt_event;
+    BOOLEAN             initiator; /* TRUE, if local device initiates the SUSPEND */
+} tBTA_AV_STR_MSG;
+
+/* data type for BTA_AV_AVRC_MSG_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tAVRC_MSG           msg;
+    UINT8               handle;
+    UINT8               label;
+    UINT8               opcode;
+} tBTA_AV_RC_MSG;
+
+/* data type for BTA_AV_AVRC_OPEN_EVT, BTA_AV_AVRC_CLOSE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             peer_addr;
+    UINT8               handle;
+} tBTA_AV_RC_CONN_CHG;
+
+/* data type for BTA_AV_CONN_CHG_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             peer_addr;
+    BOOLEAN             is_up;
+} tBTA_AV_CONN_CHG;
+
+/* data type for BTA_AV_ROLE_CHANGE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               new_role;
+    UINT8               hci_status;
+} tBTA_AV_ROLE_RES;
+
+/* data type for BTA_AV_SDP_DISC_OK_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              avdt_version;   /* AVDTP protocol version */
+} tBTA_AV_SDP_RES;
+
+/* type for SEP control block */
+typedef struct
+{
+    UINT8               av_handle;      /* AVDTP handle */
+    tBTA_AV_CODEC       codec_type;     /* codec type */
+} tBTA_AV_SEP;
+
+
+/* initiator/acceptor role for adaption */
+#define BTA_AV_ROLE_AD_INT          0x00       /* initiator */
+#define BTA_AV_ROLE_AD_ACP          0x01       /* acceptor */
+
+/* initiator/acceptor signaling roles */
+#define BTA_AV_ROLE_START_ACP       0x00
+#define BTA_AV_ROLE_START_INT       0x10    /* do not change this value */
+
+#define BTA_AV_ROLE_SUSPEND         0x20    /* suspending on start */
+#define BTA_AV_ROLE_SUSPEND_OPT     0x40    /* Suspend on Start option is set */
+
+/* union of all event datatypes */
+typedef union
+{
+    BT_HDR                  hdr;
+    tBTA_AV_API_ENABLE      api_enable;
+    tBTA_AV_API_REG         api_reg;
+    tBTA_AV_API_OPEN        api_open;
+    tBTA_AV_API_STOP        api_stop;
+    tBTA_AV_API_DISCNT      api_discnt;
+    tBTA_AV_API_PROTECT_REQ api_protect_req;
+    tBTA_AV_API_PROTECT_RSP api_protect_rsp;
+    tBTA_AV_API_REMOTE_CMD  api_remote_cmd;
+    tBTA_AV_API_VENDOR      api_vendor;
+    tBTA_AV_API_RCFG        api_reconfig;
+    tBTA_AV_CI_SETCONFIG    ci_setconfig;
+    tBTA_AV_STR_MSG         str_msg;
+    tBTA_AV_RC_MSG          rc_msg;
+    tBTA_AV_RC_CONN_CHG     rc_conn_chg;
+    tBTA_AV_CONN_CHG        conn_chg;
+    tBTA_AV_ROLE_RES        role_res;
+    tBTA_AV_SDP_RES         sdp_res;
+    tBTA_AV_API_META_RSP    api_meta_rsp;
+} tBTA_AV_DATA;
+
+typedef void (tBTA_AV_VDP_DATA_ACT)(void *p_scb);
+
+typedef struct
+{
+    tBTA_AV_VDP_DATA_ACT    *p_act;
+    UINT8                   *p_frame;
+    UINT16                  buf_size;
+    UINT32                  len;
+    UINT32                  offset;
+    UINT32                  timestamp;
+} tBTA_AV_VF_INFO;
+
+typedef union
+{
+    BUFFER_Q            a2d;            /* used for audio channels only */
+    tBTA_AV_VF_INFO     vdp;            /* used for video channels only */
+    tBTA_AV_API_OPEN    open;           /* used only before open and role switch
+                                           is needed on another AV channel */
+} tBTA_AV_Q_INFO;
+
+#define BTA_AV_Q_TAG_OPEN               0x01 /* after API_OPEN, before STR_OPENED */
+#define BTA_AV_Q_TAG_START              0x02 /* before start sending media packets */
+#define BTA_AV_Q_TAG_STREAM             0x03 /* during streaming */
+
+#define BTA_AV_WAIT_ACP_CAPS_ON         0x01 /* retriving the peer capabilities */
+#define BTA_AV_WAIT_ACP_CAPS_STARTED    0x02 /* started while retriving peer capabilities */
+#define BTA_AV_WAIT_ROLE_SW_RES_OPEN    0x04 /* waiting for role switch result after API_OPEN, before STR_OPENED */
+#define BTA_AV_WAIT_ROLE_SW_RES_START   0x08 /* waiting for role switch result before streaming */
+#define BTA_AV_WAIT_ROLE_SW_STARTED     0x10 /* started while waiting for role switch result */
+#define BTA_AV_WAIT_ROLE_SW_RETRY       0x20 /* set when retry on timeout */
+#define BTA_AV_WAIT_CHECK_RC            0x40 /* set when the timer is used by role switch */
+#define BTA_AV_WAIT_ROLE_SW_FAILED      0x80 /* role switch failed */
+
+#define BTA_AV_WAIT_ROLE_SW_BITS        (BTA_AV_WAIT_ROLE_SW_RES_OPEN|BTA_AV_WAIT_ROLE_SW_RES_START|BTA_AV_WAIT_ROLE_SW_STARTED|BTA_AV_WAIT_ROLE_SW_RETRY)
+
+/* Bitmap for collision, coll_mask */
+#define BTA_AV_COLL_INC_TMR             0x01 /* Timer is running for incoming L2C connection */
+#define BTA_AV_COLL_API_CALLED          0x02 /* API open was called while incoming timer is running */
+
+/* type for AV stream control block */
+typedef struct
+{
+    const tBTA_AV_ACT   *p_act_tbl;     /* the action table for stream state machine */
+    const tBTA_AV_CO_FUNCTS *p_cos;     /* the associated callout functions */
+    tSDP_DISCOVERY_DB   *p_disc_db;     /* pointer to discovery database */
+    tBTA_AV_SEP         seps[BTA_AV_MAX_SEPS];
+    tAVDT_CFG           *p_cap;         /* buffer used for get capabilities */
+    tBTA_AV_Q_INFO      q_info;
+    tAVDT_SEP_INFO      sep_info[BTA_AV_NUM_SEPS];      /* stream discovery results */
+    tAVDT_CFG           cfg;            /* local SEP configuration */
+    TIMER_LIST_ENT      timer;          /* delay timer for AVRC CT */
+    BD_ADDR             peer_addr;      /* peer BD address */
+    UINT16              l2c_cid;        /* L2CAP channel ID */
+    UINT16              stream_mtu;     /* MTU of stream */
+    UINT16              avdt_version;   /* the avdt version of peer device */
+    tBTA_SEC            sec_mask;       /* security mask */
+    tBTA_AV_CODEC       codec_type;     /* codec type */
+    UINT8               media_type;     /* Media type */
+    BOOLEAN             cong;           /* TRUE if AVDTP congested */
+    tBTA_AV_STATUS      open_status;    /* open failure status */
+    tBTA_AV_CHNL        chnl;           /* the channel: audio/video */
+    tBTA_AV_HNDL        hndl;           /* the handle: ((hdi + 1)|chnl) */
+    UINT16              cur_psc_mask;   /* Protocol service capabilities mask for current connection */
+    UINT8               avdt_handle;    /* AVDTP handle */
+    UINT8               hdi;            /* the index to SCB[] */
+    UINT8               num_seps;       /* number of seps returned by stream discovery */
+    UINT8               num_disc_snks;  /* number of discovered snks */
+    UINT8               sep_info_idx;   /* current index into sep_info */
+    UINT8               sep_idx;        /* current index into local seps[] */
+    UINT8               rcfg_idx;       /* reconfig requested index into sep_info */
+    UINT8               state;          /* state machine state */
+    UINT8               avdt_label;     /* AVDTP label */
+    UINT8               app_id;         /* application id */
+    UINT8               num_recfg;      /* number of reconfigure sent */
+    UINT8               role;
+    UINT8               l2c_bufs;       /* the number of buffers queued to L2CAP */
+    UINT8               rc_handle;      /* connected AVRCP handle */
+    BOOLEAN             use_rc;         /* TRUE if AVRCP is allowed */
+    BOOLEAN             started;        /* TRUE if stream started */
+    UINT8               co_started;     /* non-zero, if stream started from call-out perspective */
+    BOOLEAN             recfg_sup;      /* TRUE if the first attempt to reconfigure the stream was successfull, else False if command fails */
+    BOOLEAN             suspend_sup;    /* TRUE if Suspend stream is supported, else FALSE if suspend command fails */
+    BOOLEAN             deregistring;   /* TRUE if deregistering */
+    BOOLEAN             sco_suspend;    /* TRUE if SUSPEND is issued automatically for SCO */
+    UINT8               coll_mask;      /* Mask to check incoming and outgoing collision */
+    tBTA_AV_API_OPEN    open_api;       /* Saved OPEN api message */
+    UINT8               wait;           /* set 0x1, when getting Caps as ACP, set 0x2, when started */
+    UINT8               q_tag;          /* identify the associated q_info union member */
+} tBTA_AV_SCB;
+
+#define BTA_AV_RC_ROLE_MASK     0x10
+#define BTA_AV_RC_ROLE_INT      0x00
+#define BTA_AV_RC_ROLE_ACP      0x10
+
+#define BTA_AV_RC_CONN_MASK     0x20
+
+/* type for AV RCP control block */
+/* index to this control block is the rc handle */
+typedef struct
+{
+    UINT8   status;
+    UINT8   handle;
+    UINT8   shdl;   /* stream handle (hdi + 1) */
+    UINT8   lidx;   /* (index+1) to LCB */
+    tBTA_AV_FEAT        peer_features;  /* peer features mask */
+} tBTA_AV_RCB;
+#define BTA_AV_NUM_RCB      (BTA_AV_NUM_STRS  + 2)
+
+enum
+{
+    BTA_AV_LCB_FREE,
+    BTA_AV_LCB_FIND
+};
+
+/* type for AV ACL Link control block */
+typedef struct
+{
+    BD_ADDR             addr;           /* peer BD address */
+    UINT8               conn_msk;       /* handle mask of connected stream handle */
+    UINT8               lidx;           /* index + 1 */
+} tBTA_AV_LCB;
+
+/* type for stream state machine action functions */
+typedef void (*tBTA_AV_SACT)(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+
+
+/* type for AV control block */
+typedef struct
+{
+    tBTA_AV_SCB         *p_scb[BTA_AV_NUM_STRS];    /* stream control block */
+    tSDP_DISCOVERY_DB   *p_disc_db;     /* pointer to discovery database */
+    tBTA_AV_CBACK       *p_cback;       /* application callback function */
+    tBTA_AV_RCB         rcb[BTA_AV_NUM_RCB];  /* RCB control block */
+    tBTA_AV_LCB         lcb[BTA_AV_NUM_LINKS+1];  /* link control block */
+    TIMER_LIST_ENT      sig_tmr;        /* link timer */
+    TIMER_LIST_ENT      acp_sig_tmr;    /* timer to monitor signalling when accepting */
+    UINT32              sdp_a2d_handle; /* SDP record handle for audio src */
+    UINT32              sdp_vdp_handle; /* SDP record handle for video src */
+    tBTA_AV_FEAT        features;       /* features mask */
+    tBTA_SEC            sec_mask;       /* security mask */
+    tBTA_AV_HNDL        handle;         /* the handle for SDP activity */
+    BOOLEAN             disabling;      /* TRUE if api disabled called */
+    UINT8               disc;           /* (hdi+1) or (rc_handle|BTA_AV_CHNL_MSK) if p_disc_db is in use */
+    UINT8               state;          /* state machine state */
+    UINT8               conn_rc;        /* handle mask of connected RCP channels */
+    UINT8               conn_audio;     /* handle mask of connected audio channels */
+    UINT8               conn_video;     /* handle mask of connected video channels */
+    UINT8               conn_lcb;       /* index mask of used LCBs */
+    UINT8               audio_open_cnt; /* number of connected audio channels */
+    UINT8               reg_audio;      /* handle mask of registered audio channels */
+    UINT8               reg_video;      /* handle mask of registered video channels */
+    UINT8               rc_acp_handle;
+    UINT8               rc_acp_idx;     /* (index + 1) to RCB */
+    UINT8               rs_idx;         /* (index + 1) to SCB for the one waiting for RS on open */
+    BOOLEAN             sco_occupied;   /* TRUE if SCO is being used or call is in progress */
+    UINT8               audio_streams;  /* handle mask of streaming audio channels */
+    UINT8               video_streams;  /* handle mask of streaming video channels */
+} tBTA_AV_CB;
+
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* control block declaration */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_AV_CB bta_av_cb;
+#else
+extern tBTA_AV_CB *bta_av_cb_ptr;
+#define bta_av_cb (*bta_av_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_AV_CFG *p_bta_av_cfg;
+
+/* rc id config struct */
+extern UINT16 *p_bta_av_rc_id;
+extern UINT16 *p_bta_av_rc_id_ac;
+
+extern const tBTA_AV_SACT bta_av_a2d_action[];
+extern const tBTA_AV_CO_FUNCTS bta_av_a2d_cos;
+extern const tBTA_AV_SACT bta_av_vdp_action[];
+extern tAVDT_CTRL_CBACK * const bta_av_dt_cback[];
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+/* utility functions */
+extern tBTA_AV_SCB *bta_av_hndl_to_scb(UINT16 handle);
+extern BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb);
+extern void bta_av_restore_switch (void);
+extern UINT16 bta_av_chk_mtu(tBTA_AV_SCB *p_scb, UINT16 mtu);
+extern void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data);
+extern UINT8 bta_av_rc_create(tBTA_AV_CB *p_cb, UINT8 role, UINT8 shdl, UINT8 lidx);
+extern void bta_av_proc_stream_evt(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data, int index);
+extern void bta_av_stream_chg(tBTA_AV_SCB *p_scb, BOOLEAN started);
+extern BOOLEAN bta_av_is_scb_opening (tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_is_scb_incoming (tBTA_AV_SCB *p_scb);
+extern void bta_av_set_scb_sst_init (tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb);
+extern void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb);
+extern tBTA_AV_LCB * bta_av_find_lcb(BD_ADDR addr, UINT8 op);
+
+
+/* main functions */
+extern void bta_av_api_deregister(tBTA_AV_DATA *p_data);
+extern void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf);
+extern void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data);
+extern void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data);
+extern BOOLEAN bta_av_hdl_event(BT_HDR *p_msg);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+extern char *bta_av_evt_code(UINT16 evt_code);
+#endif
+extern BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb);
+extern BOOLEAN bta_av_link_role_ok(tBTA_AV_SCB *p_scb, UINT8 bits);
+extern BOOLEAN bta_av_is_rcfg_sst(tBTA_AV_SCB *p_scb);
+
+/* nsm action functions */
+extern void bta_av_api_disconnect(tBTA_AV_DATA *p_data);
+extern void bta_av_sig_chg(tBTA_AV_DATA *p_data);
+extern void bta_av_sig_timer(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_disc_done(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_closed(tBTA_AV_DATA *p_data);
+extern void bta_av_rc_disc(UINT8 disc);
+extern void bta_av_conn_chg(tBTA_AV_DATA *p_data);
+extern void bta_av_dereg_comp(tBTA_AV_DATA *p_data);
+
+/* sm action functions */
+extern void bta_av_disable (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_opened (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_remote_cmd (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_vendor_cmd (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_vendor_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_close (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_meta_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_free_rsp (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+extern void bta_av_rc_free_msg (tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+
+extern tBTA_AV_RCB * bta_av_get_rcb_by_shdl(UINT8 shdl);
+extern void bta_av_del_rc(tBTA_AV_RCB *p_rcb);
+
+/* ssm action functions */
+extern void bta_av_do_disc_a2d (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_cleanup (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_free_sdb (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_config_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disconnect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_setconfig_rsp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_st_rc_timer(tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_ind (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_do_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_connect_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_sdp_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disc_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_disc_res_as_acp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_getcap_results (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_setconfig_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_discover_req (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_conn_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_do_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_stopped (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_reconfig (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_data_path (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_start_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_start_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_str_closed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_clr_cong (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_suspend_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_str_ok (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_connect (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_discntd (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_suspend_cont (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_cfm (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rcfg_open (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_security_rej (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_chk_2nd_start (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_save_caps (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rej_conn (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_rej_conn (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_set_use_rc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_cco_close (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_switch_role (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_role_res (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_delay_co (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_open_at_inc (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+
+/* ssm action functions - vdp specific */
+extern void bta_av_do_disc_vdp (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_vdp_str_opened (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data);
+extern void bta_av_reg_vdp (tAVDT_CS *p_cs, char *p_service_name, void *p_data);
+
+#endif /* BTA_AV_INT_H */
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
new file mode 100644
index 0000000..085362d
--- /dev/null
+++ b/bta/av/bta_av_main.c
@@ -0,0 +1,1323 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the main implementation file for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_int.h"
+#include "utl.h"
+#include "bd.h"
+#include "l2c_api.h"
+#include "l2cdefs.h"
+#include "bta_av_co.h"
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* AVDTP protocol timeout values */
+#ifndef BTA_AV_RET_TOUT
+#define BTA_AV_RET_TOUT     4
+#endif
+
+#ifndef BTA_AV_SIG_TOUT
+#define BTA_AV_SIG_TOUT     4
+#endif
+
+#ifndef BTA_AV_IDLE_TOUT
+#define BTA_AV_IDLE_TOUT    10
+#endif
+
+/* the delay time in milliseconds to retry role switch */
+#ifndef BTA_AV_RS_TIME_VAL
+#define BTA_AV_RS_TIME_VAL     1000
+#endif
+
+/* state machine states */
+enum
+{
+    BTA_AV_INIT_ST,
+    BTA_AV_OPEN_ST
+};
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_AV_DISABLE,
+    BTA_AV_RC_OPENED,
+    BTA_AV_RC_REMOTE_CMD,
+    BTA_AV_RC_VENDOR_CMD,
+    BTA_AV_RC_VENDOR_RSP,
+    BTA_AV_RC_FREE_RSP,
+    BTA_AV_RC_FREE_MSG,
+    BTA_AV_RC_META_RSP,
+    BTA_AV_RC_MSG,
+    BTA_AV_RC_CLOSE,
+    BTA_AV_NUM_ACTIONS
+};
+
+#define BTA_AV_IGNORE       BTA_AV_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_AV_ACTION)(tBTA_AV_CB *p_cb, tBTA_AV_DATA *p_data);
+
+/* action functions */
+const tBTA_AV_ACTION bta_av_action[] =
+{
+    bta_av_disable,
+    bta_av_rc_opened,
+    bta_av_rc_remote_cmd,
+    bta_av_rc_vendor_cmd,
+    bta_av_rc_vendor_rsp,
+    bta_av_rc_free_rsp,
+    bta_av_rc_free_msg,
+    bta_av_rc_meta_rsp,
+    bta_av_rc_msg,
+    bta_av_rc_close,
+    NULL
+};
+
+/* state table information */
+#define BTA_AV_ACTION_COL           0       /* position of actions */
+#define BTA_AV_NEXT_STATE           1       /* position of next state */
+#define BTA_AV_NUM_COLS             2       /* number of columns in state tables */
+
+/* state table for init state */
+static const UINT8 bta_av_st_init[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Next state */
+/* API_DISABLE_EVT */       {BTA_AV_DISABLE,        BTA_AV_INIT_ST },
+/* API_REMOTE_CMD_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* API_VENDOR_CMD_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* API_VENDOR_RSP_EVT */    {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* API_META_RSP_EVT */      {BTA_AV_RC_FREE_RSP,    BTA_AV_INIT_ST },
+/* API_RC_CLOSE_EVT */      {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+/* AVRC_OPEN_EVT */         {BTA_AV_RC_OPENED,      BTA_AV_OPEN_ST },
+/* AVRC_MSG_EVT */          {BTA_AV_RC_FREE_MSG,    BTA_AV_INIT_ST },
+/* AVRC_NONE_EVT */         {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+};
+
+/* state table for open state */
+static const UINT8 bta_av_st_open[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Next state */
+/* API_DISABLE_EVT */       {BTA_AV_DISABLE,        BTA_AV_INIT_ST },
+/* API_REMOTE_CMD_EVT */    {BTA_AV_RC_REMOTE_CMD,  BTA_AV_OPEN_ST },
+/* API_VENDOR_CMD_EVT */    {BTA_AV_RC_VENDOR_CMD,  BTA_AV_OPEN_ST },
+/* API_VENDOR_RSP_EVT */    {BTA_AV_RC_VENDOR_RSP,  BTA_AV_OPEN_ST },
+/* API_META_RSP_EVT */      {BTA_AV_RC_META_RSP,    BTA_AV_OPEN_ST },
+/* API_RC_CLOSE_EVT */      {BTA_AV_RC_CLOSE,       BTA_AV_OPEN_ST },
+/* AVRC_OPEN_EVT */         {BTA_AV_RC_OPENED,      BTA_AV_OPEN_ST },
+/* AVRC_MSG_EVT */          {BTA_AV_RC_MSG,         BTA_AV_OPEN_ST },
+/* AVRC_NONE_EVT */         {BTA_AV_IGNORE,         BTA_AV_INIT_ST },
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AV_ST_TBL)[BTA_AV_NUM_COLS];
+
+/* state table */
+static const tBTA_AV_ST_TBL bta_av_st_tbl[] =
+{
+    bta_av_st_init,
+    bta_av_st_open
+};
+
+typedef void (*tBTA_AV_NSM_ACT)(tBTA_AV_DATA *p_data);
+static void bta_av_api_enable(tBTA_AV_DATA *p_data);
+static void bta_av_api_register(tBTA_AV_DATA *p_data);
+static void bta_av_ci_data(tBTA_AV_DATA *p_data);
+#if (AVDT_REPORTING == TRUE)
+static void bta_av_rpc_conn(tBTA_AV_DATA *p_data);
+#endif
+static void bta_av_api_to_ssm(tBTA_AV_DATA *p_data);
+
+static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
+                                 app_id, BD_ADDR peer_addr);
+static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+
+/* action functions */
+const tBTA_AV_NSM_ACT bta_av_nsm_act[] =
+{
+    bta_av_api_enable,      /* BTA_AV_API_ENABLE_EVT */
+    bta_av_api_register,    /* BTA_AV_API_REGISTER_EVT */
+    bta_av_api_deregister,  /* BTA_AV_API_DEREGISTER_EVT */
+    bta_av_api_disconnect,  /* BTA_AV_API_DISCONNECT_EVT */
+    bta_av_ci_data,         /* BTA_AV_CI_SRC_DATA_READY_EVT */
+    bta_av_sig_chg,         /* BTA_AV_SIG_CHG_EVT */
+    bta_av_sig_timer,       /* BTA_AV_SIG_TIMER_EVT */
+    bta_av_rc_disc_done,    /* BTA_AV_SDP_AVRC_DISC_EVT */
+    bta_av_rc_closed,       /* BTA_AV_AVRC_CLOSE_EVT */
+    bta_av_conn_chg,        /* BTA_AV_CONN_CHG_EVT */
+    bta_av_dereg_comp,      /* BTA_AV_DEREG_COMP_EVT */
+#if (AVDT_REPORTING == TRUE)
+    bta_av_rpc_conn,        /* BTA_AV_AVDT_RPT_CONN_EVT */
+#endif
+    bta_av_api_to_ssm,      /* BTA_AV_API_START_EVT */
+    bta_av_api_to_ssm,      /* BTA_AV_API_STOP_EVT */
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* AV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_AV_CB  bta_av_cb;
+#endif
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+static char *bta_av_st_code(UINT8 state);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_timer_cback
+**
+** Description      forward the event to stream state machine
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_timer_cback(void *p_tle)
+{
+    BT_HDR          *p_buf;
+    TIMER_LIST_ENT  *p = (TIMER_LIST_ENT *)p_tle;
+    int xx;
+    tBTA_AV_SCB *p_scb = NULL;
+
+    /* find the SCB that has the timer */
+    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    {
+        if(bta_av_cb.p_scb[xx] && &(bta_av_cb.p_scb[xx]->timer)== p)
+        {
+            p_scb = bta_av_cb.p_scb[xx];
+            break;
+        }
+    }
+
+    if (p_scb && (p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        /* send the event through the audio state machine.
+         * only when the audio SM is open, the main SM opens the RC connection as INT */
+        p_buf->event = p->event;
+        p_buf->layer_specific = p_scb->hndl;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_api_enable
+**
+** Description      Handle an API enable event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_enable(tBTA_AV_DATA *p_data)
+{
+    int i;
+    tBTA_AV_ENABLE      enable;
+
+    /* initialize control block */
+    memset(&bta_av_cb, 0, sizeof(tBTA_AV_CB));
+
+    for(i=0; i<BTA_AV_NUM_RCB; i++)
+        bta_av_cb.rcb[i].handle = BTA_AV_RC_HANDLE_NONE;
+
+    bta_av_cb.rc_acp_handle = BTA_AV_RC_HANDLE_NONE;
+
+    /* store parameters */
+    bta_av_cb.p_cback  = p_data->api_enable.p_cback;
+    bta_av_cb.features = p_data->api_enable.features;
+    bta_av_cb.sec_mask = p_data->api_enable.sec_mask;
+
+    enable.features = bta_av_cb.features;
+
+    /* Register for SCO change event */
+    if (!(bta_av_cb.features & BTA_AV_FEAT_NO_SCO_SSPD))
+    {
+        bta_sys_sco_register(bta_av_sco_chg_cback);
+    }
+
+    /* call callback with enable event */
+    (*bta_av_cb.p_cback)(BTA_AV_ENABLE_EVT, (tBTA_AV *)&enable);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_addr_to_scb
+**
+** Description      find the stream control block by the peer addr
+**
+** Returns          void
+**
+*******************************************************************************/
+static tBTA_AV_SCB * bta_av_addr_to_scb(BD_ADDR bd_addr)
+{
+    tBTA_AV_SCB * p_scb = NULL;
+    int         xx;
+
+    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    {
+        if(bta_av_cb.p_scb[xx])
+        {
+            if(!bdcmp(bd_addr, bta_av_cb.p_scb[xx]->peer_addr))
+            {
+                p_scb = bta_av_cb.p_scb[xx];
+                break;
+            }
+        }
+    }
+    return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_hndl_to_scb
+**
+** Description      find the stream control block by the handle
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_AV_SCB * bta_av_hndl_to_scb(UINT16 handle)
+{
+    tBTA_AV_HNDL hndl = (tBTA_AV_HNDL)handle;
+    tBTA_AV_SCB * p_scb = NULL;
+    UINT8 idx = (hndl & BTA_AV_HNDL_MSK);
+
+    if(idx && (idx <= BTA_AV_NUM_STRS) )
+    {
+        p_scb = bta_av_cb.p_scb[idx-1];
+    }
+    return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_alloc_scb
+**
+** Description      allocate stream control block,
+**                  register the service to stack
+**                  create SDP record
+**
+** Returns          void
+**
+*******************************************************************************/
+static tBTA_AV_SCB * bta_av_alloc_scb(tBTA_AV_CHNL chnl)
+{
+    tBTA_AV_SCB *p_ret = NULL;
+    int         xx;
+    tBTA_AV_STATUS sts = BTA_AV_SUCCESS;
+
+    if(chnl == BTA_AV_CHNL_VIDEO)
+    {
+        if(p_bta_av_cfg->p_act_tbl == NULL || p_bta_av_cfg->p_reg == NULL)
+        {
+            APPL_TRACE_ERROR0("Video streaming not supported");
+            sts = BTA_AV_FAIL;
+        }
+        else
+        {
+            /* allow only one Video channel */
+            if(bta_av_cb.reg_video)
+            {
+                APPL_TRACE_ERROR0("Already registered");
+                sts = BTA_AV_FAIL;
+            }
+        }
+    }
+    else if(chnl != BTA_AV_CHNL_AUDIO)
+    {
+        APPL_TRACE_ERROR1("bad channel: %d", chnl);
+        sts = BTA_AV_FAIL;
+    }
+
+    if(sts == BTA_AV_SUCCESS)
+    {
+        for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+        {
+            if(bta_av_cb.p_scb[xx] == NULL)
+            {
+                /* found an empty spot */
+                p_ret = (tBTA_AV_SCB *)GKI_getbuf(sizeof(tBTA_AV_SCB));
+                if(p_ret)
+                {
+                    memset(p_ret, 0, sizeof(tBTA_AV_SCB));
+                    p_ret->rc_handle = BTA_AV_RC_HANDLE_NONE;
+                    p_ret->chnl = chnl;
+                    p_ret->hndl = (tBTA_AV_HNDL)((xx + 1) | chnl);
+                    p_ret->hdi  = xx;
+                    bta_av_cb.p_scb[xx] = p_ret;
+                }
+                break;
+            }
+        }
+    }
+    return p_ret;
+}
+
+/*******************************************************************************
+*******************************************************************************/
+void bta_av_conn_cback(UINT8 handle, BD_ADDR bd_addr, UINT8 event, tAVDT_CTRL *p_data)
+{
+    tBTA_AV_STR_MSG     *p_msg;
+    UINT16  evt = 0;
+    tBTA_AV_SCB *p_scb = NULL;
+
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+    if (event == BTA_AR_AVDT_CONN_EVT ||
+        event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT)
+#else
+    if (event == AVDT_CONNECT_IND_EVT || event == AVDT_DISCONNECT_IND_EVT)
+#endif
+    {
+        evt = BTA_AV_SIG_CHG_EVT;
+        if(AVDT_DISCONNECT_IND_EVT == event)
+            p_scb = bta_av_addr_to_scb(bd_addr);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+        else if (AVDT_CONNECT_IND_EVT == event)
+        {
+            APPL_TRACE_DEBUG1("CONN_IND is ACP:%d", p_data->hdr.err_param);
+        }
+#endif
+
+        if (/*((p_scb && (p_scb->role & BTA_AV_ROLE_AD_ACP)) ||
+
+            //(AVDT_CONNECT_IND_EVT == event && AVDT_ACP == p_data->hdr.err_param))
+
+            (AVDT_CONNECT_IND_EVT == event))&& */
+            (p_msg = (tBTA_AV_STR_MSG *) GKI_getbuf((UINT16) (sizeof(tBTA_AV_STR_MSG)))) != NULL)
+        {
+            p_msg->hdr.event = evt;
+            p_msg->hdr.layer_specific = event;
+            p_msg->hdr.offset = p_data->hdr.err_param;
+            bdcpy(p_msg->bd_addr, bd_addr);
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+            if(p_scb)
+            {
+                APPL_TRACE_DEBUG2("scb hndl x%x, role x%x", p_scb->hndl, p_scb->role);
+            }
+#endif
+            APPL_TRACE_DEBUG6("conn_cback bd_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]);
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+
+}
+
+#if AVDT_REPORTING == TRUE
+/*******************************************************************************
+**
+** Function         bta_av_a2dp_report_cback
+**
+** Description      A2DP report callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_a2dp_report_cback(UINT8 handle, AVDT_REPORT_TYPE type,
+                                    tAVDT_REPORT_DATA *p_data)
+{
+    /* Do not need to handle report data for now.
+     * This empty function is here for conformance reasons. */
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_api_register
+**
+** Description      allocate stream control block,
+**                  register the service to stack
+**                  create SDP record
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_register(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_REGISTER    registr;
+    tBTA_AV_SCB         *p_scb;    /* stream control block */
+    tAVDT_REG       reg;
+    tAVDT_CS        cs;
+    char            *p_service_name;
+    tBTA_AV_CODEC   codec_type;
+    tBTA_UTL_COD    cod;
+    UINT8           index = 0;
+
+    memset(&cs,0,sizeof(tAVDT_CS));
+
+    registr.status = BTA_AV_FAIL_RESOURCES;
+    registr.app_id = p_data->api_reg.app_id;
+    registr.chnl   = (tBTA_AV_CHNL)p_data->hdr.layer_specific;
+    do
+    {
+        p_scb = bta_av_alloc_scb(registr.chnl);
+        if(p_scb == NULL)
+        {
+            APPL_TRACE_ERROR0("failed to alloc SCB");
+            break;
+        }
+
+        registr.hndl    = p_scb->hndl;
+        p_scb->app_id   = registr.app_id;
+
+        /* initialize the stream control block */
+        p_scb->timer.p_cback = (TIMER_CBACK*)&bta_av_timer_cback;
+        registr.status = BTA_AV_SUCCESS;
+
+        if((bta_av_cb.reg_audio + bta_av_cb.reg_video) == 0)
+        {
+            /* the first channel registered. register to AVDTP */
+            reg.ctrl_mtu = p_bta_av_cfg->sig_mtu;
+            reg.ret_tout = BTA_AV_RET_TOUT;
+            reg.sig_tout = BTA_AV_SIG_TOUT;
+            reg.idle_tout = BTA_AV_IDLE_TOUT;
+            reg.sec_mask = bta_av_cb.sec_mask;
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+            bta_ar_reg_avdt(&reg, bta_av_conn_cback, BTA_ID_AV);
+#endif
+            bta_sys_role_chg_register(&bta_av_sys_rs_cback);
+
+            /* create remote control TG service if required */
+            if (bta_av_cb.features & (BTA_AV_FEAT_RCTG))
+            {
+                /* register with no authorization; let AVDTP use authorization instead */
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
+                bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+                                bta_av_cb.sec_mask, BTA_ID_AV);
+#else
+                bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+                                (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
+#endif
+
+                bta_ar_reg_avrc(UUID_SERVCLASS_AV_REM_CTRL_TARGET, "AV Remote Control Target", NULL,
+                                p_bta_av_cfg->avrc_tg_cat, BTA_ID_AV);
+#endif
+            }
+
+            /* Set the Capturing service class bit */
+            cod.service = BTM_COD_SERVICE_CAPTURING;
+            utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+        } /* if 1st channel */
+
+        /* get stream configuration and create stream */
+        /* memset(&cs.cfg,0,sizeof(tAVDT_CFG)); */
+        cs.cfg.num_codec = 1;
+        cs.tsep = AVDT_TSEP_SRC;
+
+        /*
+         * memset of cs takes care setting call back pointers to null.
+        cs.p_data_cback = NULL;
+        cs.p_report_cback = NULL;
+        */
+        cs.nsc_mask = AVDT_NSC_RECONFIG |
+              ((bta_av_cb.features & BTA_AV_FEAT_PROTECT) ? 0 : AVDT_NSC_SECURITY);
+        APPL_TRACE_DEBUG1("nsc_mask: 0x%x", cs.nsc_mask);
+
+        if (p_data->api_reg.p_service_name[0] == 0)
+        {
+            p_service_name = NULL;
+        }
+        else
+        {
+            p_service_name = p_data->api_reg.p_service_name;
+        }
+
+        p_scb->suspend_sup  = TRUE;
+        p_scb->recfg_sup    = TRUE;
+
+        cs.p_ctrl_cback  = bta_av_dt_cback[p_scb->hdi];
+        if(registr.chnl == BTA_AV_CHNL_AUDIO)
+        {
+            /* set up the audio stream control block */
+            p_scb->p_act_tbl = (const tBTA_AV_ACT *)bta_av_a2d_action;
+            p_scb->p_cos     = &bta_av_a2d_cos;
+            p_scb->media_type= AVDT_MEDIA_AUDIO;
+            cs.cfg.psc_mask  = AVDT_PSC_TRANS;
+            cs.media_type    = AVDT_MEDIA_AUDIO;
+            cs.mtu           = p_bta_av_cfg->audio_mtu;
+            cs.flush_to      = L2CAP_DEFAULT_FLUSH_TO;
+#if AVDT_REPORTING == TRUE
+            if(bta_av_cb.features & BTA_AV_FEAT_REPORT)
+            {
+                cs.cfg.psc_mask |= AVDT_PSC_REPORT;
+                cs.p_report_cback = bta_av_a2dp_report_cback;
+#if AVDT_MULTIPLEXING == TRUE
+                cs.cfg.mux_tsid_report = 2;
+#endif
+            }
+#endif
+            if(bta_av_cb.features & BTA_AV_FEAT_DELAY_RPT)
+                cs.cfg.psc_mask |= AVDT_PSC_DELAY_RPT;
+
+            /* keep the configuration in the stream control block */
+            memcpy(&p_scb->cfg, &cs.cfg, sizeof(tAVDT_CFG));
+            while(index < BTA_AV_MAX_SEPS &&
+                (*bta_av_a2d_cos.init)(&codec_type, cs.cfg.codec_info,
+                &cs.cfg.num_protect, cs.cfg.protect_info, index) == TRUE)
+            {
+                if(AVDT_CreateStream(&p_scb->seps[index].av_handle, &cs) == AVDT_SUCCESS)
+                {
+                    p_scb->seps[index].codec_type = codec_type;
+                    APPL_TRACE_DEBUG3("audio[%d] av_handle: %d codec_type: %d",
+                        index, p_scb->seps[index].av_handle, p_scb->seps[index].codec_type);
+                    index++;
+                }
+                else
+                    break;
+            }
+
+            if(!bta_av_cb.reg_audio)
+            {
+                /* create the SDP records on the 1st audio channel */
+                bta_av_cb.sdp_a2d_handle = SDP_CreateRecord();
+                A2D_AddRecord(UUID_SERVCLASS_AUDIO_SOURCE, p_service_name, NULL,
+                                  A2D_SUPF_PLAYER, bta_av_cb.sdp_a2d_handle);
+                bta_sys_add_uuid(UUID_SERVCLASS_AUDIO_SOURCE);
+
+                /* start listening when A2DP is registered */
+                if (bta_av_cb.features & BTA_AV_FEAT_RCTG)
+                    bta_av_rc_create(&bta_av_cb, AVCT_ACP, 0, BTA_AV_NUM_LINKS + 1);
+
+                /* if the AV and AVK are both supported, it cannot support the CT role */
+                if (bta_av_cb.features & (BTA_AV_FEAT_RCCT))
+                {
+                    /* if TG is not supported, we need to register to AVCT now */
+                    if ((bta_av_cb.features & (BTA_AV_FEAT_RCTG)) == 0)
+                    {
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#if (BTA_AV_WITH_AVCTP_AUTHORIZATION == TRUE)
+                        bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+                                        bta_av_cb.sec_mask, BTA_ID_AV);
+#else
+                        bta_ar_reg_avct(p_bta_av_cfg->avrc_mtu, p_bta_av_cfg->avrc_br_mtu,
+                                        (UINT8)(bta_av_cb.sec_mask & (~BTA_SEC_AUTHORIZE)), BTA_ID_AV);
+#endif
+#endif
+                    }
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+                    /* create an SDP record as AVRC CT. */
+                    bta_ar_reg_avrc(UUID_SERVCLASS_AV_REMOTE_CONTROL, NULL, NULL,
+                           p_bta_av_cfg->avrc_ct_cat, BTA_ID_AV);
+#endif
+                }
+            }
+            bta_av_cb.reg_audio |= BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+            APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio);
+        }
+        else
+        {
+            bta_av_cb.reg_video = BTA_AV_HNDL_TO_MSK(p_scb->hdi);
+            bta_av_cb.sdp_vdp_handle = SDP_CreateRecord();
+            /* register the video channel */
+            /* no need to verify the function pointer here. it's verified prior */
+            (*p_bta_av_cfg->p_reg)(&cs, p_service_name, p_scb);
+        }
+    } while (0);
+
+    /* call callback with register event */
+    (*bta_av_cb.p_cback)(BTA_AV_REGISTER_EVT, (tBTA_AV *)&registr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_api_deregister
+**
+** Description      de-register a channel
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_api_deregister(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SCB *p_scb = bta_av_hndl_to_scb(p_data->hdr.layer_specific);
+
+    if(p_scb)
+    {
+        p_scb->deregistring = TRUE;
+        bta_av_ssm_execute(p_scb, BTA_AV_API_CLOSE_EVT, p_data);
+    }
+    else
+    {
+        bta_av_dereg_comp(p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_ci_data
+**
+** Description      forward the BTA_AV_CI_SRC_DATA_READY_EVT to stream state machine
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_ci_data(tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SCB *p_scb;
+    int     i;
+    UINT8   chnl = (UINT8)p_data->hdr.layer_specific;
+
+    for( i=0; i < BTA_AV_NUM_STRS; i++ )
+    {
+        p_scb = bta_av_cb.p_scb[i];
+
+        if(p_scb && p_scb->chnl == chnl)
+        {
+            bta_av_ssm_execute(p_scb, BTA_AV_SRC_DATA_READY_EVT, p_data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_rpc_conn
+**
+** Description      report report channel open
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (AVDT_REPORTING == TRUE)
+
+static void bta_av_rpc_conn(tBTA_AV_DATA *p_data)
+{
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_api_to_ssm
+**
+** Description      forward the API request to stream state machine
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_api_to_ssm(tBTA_AV_DATA *p_data)
+{
+    int xx;
+    UINT16 event = p_data->hdr.event - BTA_AV_FIRST_A2S_API_EVT + BTA_AV_FIRST_A2S_SSM_EVT;
+
+    for(xx=0; xx<BTA_AV_NUM_STRS; xx++)
+    {
+        bta_av_ssm_execute(bta_av_cb.p_scb[xx], event, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_chk_start
+**
+** Description      if this is audio channel, check if more than one audio
+**                  channel is connected & already started.
+**
+** Returns          TRUE, if need api_start
+**
+*******************************************************************************/
+BOOLEAN bta_av_chk_start(tBTA_AV_SCB *p_scb)
+{
+    BOOLEAN start = FALSE;
+    tBTA_AV_SCB *p_scbi;
+    int i;
+
+    if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+    {
+        if ((bta_av_cb.audio_open_cnt >= 2) &&
+            ((0 == (p_scb->role & BTA_AV_ROLE_AD_ACP)) ||       /* Outgoing connection or   */
+             (bta_av_cb.features & BTA_AV_FEAT_ACP_START)))     /* auto-starting option     */
+        {
+            /* more than one audio channel is connected */
+            /* if this is the 2nd stream as ACP, give INT a chance to issue the START command */
+            for(i=0; i<BTA_AV_NUM_STRS; i++)
+            {
+                p_scbi = bta_av_cb.p_scb[i];
+                if(p_scbi && p_scbi->chnl == BTA_AV_CHNL_AUDIO && p_scbi->co_started)
+                {
+                    start = TRUE;
+                    /* may need to update the flush timeout of this already started stream */
+                    if(p_scbi->co_started != bta_av_cb.audio_open_cnt)
+                    {
+                        p_scbi->co_started = bta_av_cb.audio_open_cnt;
+                        L2CA_SetFlushTimeout(p_scbi->peer_addr, p_bta_av_cfg->p_audio_flush_to[p_scbi->co_started - 1] );
+                    }
+                }
+            }
+        }
+    }
+    return start;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_restore_switch
+**
+** Description      assume that the caller of this function already makes
+**                  sure that there's only one ACL connection left
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_restore_switch (void)
+{
+    tBTA_AV_CB   *p_cb = &bta_av_cb;
+    int     i;
+    UINT8   mask;
+
+    APPL_TRACE_DEBUG1("reg_audio: 0x%x",bta_av_cb.reg_audio);
+    for(i=0; i<BTA_AV_NUM_STRS; i++)
+    {
+        mask = BTA_AV_HNDL_TO_MSK(i);
+        if (p_cb->conn_audio == mask)
+        {
+            if (p_cb->p_scb[i])
+            {
+                bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_cb->p_scb[i]->peer_addr);
+            }
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sys_rs_cback
+**
+** Description      Receives the role change event from dm
+**
+** Returns          (BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda)
+**
+*******************************************************************************/
+static void bta_av_sys_rs_cback (tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    int         i;
+    tBTA_AV_SCB *p_scb;
+    tBTA_AV_ROLE_RES  *p_buf;
+    UINT8       cur_role;
+    UINT8       peer_idx = 0;
+
+    APPL_TRACE_DEBUG1("bta_av_sys_rs_cback: %d", bta_av_cb.rs_idx);
+    for(i=0; i<BTA_AV_NUM_STRS; i++)
+    {
+        /* loop through all the SCBs to find matching peer addresses and report the role change event */
+        /* note that more than one SCB (a2dp & vdp) maybe waiting for this event */
+        p_scb = bta_av_cb.p_scb[i];
+        if (p_scb && (bdcmp (peer_addr, p_scb->peer_addr) == 0) &&
+            (p_buf = (tBTA_AV_ROLE_RES *) GKI_getbuf(sizeof(tBTA_AV_ROLE_RES))) != NULL)
+        {
+            APPL_TRACE_DEBUG3("new_role:%d, hci_status:x%x hndl: x%x", id, app_id, p_scb->hndl);
+            /*
+            if ((id != BTM_ROLE_MASTER) && (app_id != HCI_SUCCESS))
+            {
+                bta_sys_set_policy(BTA_ID_AV, (HCI_ENABLE_MASTER_SLAVE_SWITCH|HCI_ENABLE_SNIFF_MODE), p_scb->peer_addr);
+            }
+            */
+            p_buf->hdr.event = BTA_AV_ROLE_CHANGE_EVT;
+            p_buf->hdr.layer_specific = p_scb->hndl;
+            p_buf->new_role = id;
+            p_buf->hci_status = app_id;
+            bta_sys_sendmsg(p_buf);
+
+            peer_idx = p_scb->hdi + 1;  /* Handle index for the peer_addr */
+        }
+    }
+
+    /* restore role switch policy, if role switch failed */
+    if ((HCI_SUCCESS != app_id) &&
+        (BTM_GetRole (peer_addr, &cur_role) == BTM_SUCCESS) &&
+        (cur_role == BTM_ROLE_SLAVE) )
+    {
+        bta_sys_set_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, peer_addr);
+    }
+
+    /* if BTA_AvOpen() was called for other device, which caused the role switch of the peer_addr,  */
+    /* we need to continue opening process for the BTA_AvOpen().                                    */
+    if ((bta_av_cb.rs_idx != 0) && (bta_av_cb.rs_idx != peer_idx))
+    {
+        p_scb = bta_av_cb.p_scb[bta_av_cb.rs_idx - 1];
+        if (p_scb && p_scb->q_tag == BTA_AV_Q_TAG_OPEN)
+        {
+            APPL_TRACE_DEBUG3 ("bta_av_sys_rs_cback: rs_idx(%d), hndl:x%x q_tag: %d",
+                bta_av_cb.rs_idx, p_scb->hndl, p_scb->q_tag);
+
+            if(HCI_SUCCESS == app_id || HCI_ERR_NO_CONNECTION == app_id)
+                p_scb->q_info.open.switch_res = BTA_AV_RS_OK;
+            else
+                p_scb->q_info.open.switch_res = BTA_AV_RS_FAIL;
+
+            /* Continue av open process */
+            bta_av_do_disc_a2d (p_scb, (tBTA_AV_DATA *)&(p_scb->q_info.open));
+        }
+
+        bta_av_cb.rs_idx = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sco_chg_cback
+**
+** Description      receive & process the SCO connection up/down event from sys.
+**                  call setup also triggers this callback, to suspend av before sco
+**                  activity happens, or to resume av once call ends.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_av_sco_chg_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8
+                                 app_id, BD_ADDR peer_addr)
+{
+    tBTA_AV_SCB *p_scb;
+    int     i;
+    tBTA_AV_API_STOP stop;
+
+    APPL_TRACE_DEBUG2("bta_av_sco_chg_cback:%d status:%d", id, status);
+    if(id)
+    {
+        bta_av_cb.sco_occupied = TRUE;
+
+        /* either BTA_SYS_SCO_OPEN or BTA_SYS_SCO_CLOSE with remaining active SCO */
+        for(i=0; i<BTA_AV_NUM_STRS; i++)
+        {
+            p_scb = bta_av_cb.p_scb[i];
+
+            if( p_scb && p_scb->co_started && (p_scb->sco_suspend == FALSE))
+            {
+                APPL_TRACE_DEBUG1("suspending scb:%d", i);
+                /* scb is used and started, not suspended automatically */
+                p_scb->sco_suspend = TRUE;
+                stop.flush   = FALSE;
+                stop.suspend = TRUE;
+                bta_av_ssm_execute(p_scb, BTA_AV_AP_STOP_EVT, (tBTA_AV_DATA *)&stop);
+            }
+        }
+    }
+    else
+    {
+        bta_av_cb.sco_occupied = FALSE;
+
+        for(i=0; i<BTA_AV_NUM_STRS; i++)
+        {
+            p_scb = bta_av_cb.p_scb[i];
+
+            if( p_scb && p_scb->sco_suspend ) /* scb is used and suspended for SCO */
+            {
+                APPL_TRACE_DEBUG1("starting scb:%d", i);
+                bta_av_ssm_execute(p_scb, BTA_AV_AP_START_EVT, NULL);
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_switch_if_needed
+**
+** Description      This function checks if there is another existing AV
+**                  channel that is local as slave role.
+**                  If so, role switch and remove it from link policy.
+**
+** Returns          TRUE, if role switch is done
+**
+*******************************************************************************/
+BOOLEAN bta_av_switch_if_needed(tBTA_AV_SCB *p_scb)
+{
+    UINT8 role;
+    BOOLEAN needed = FALSE;
+    tBTA_AV_SCB *p_scbi;
+    int i;
+    UINT8       mask;
+
+    for(i=0; i<BTA_AV_NUM_STRS; i++)
+    {
+        mask = BTA_AV_HNDL_TO_MSK(i);
+        p_scbi = bta_av_cb.p_scb[i];
+        if( p_scbi && (p_scb->hdi != i) && /* not the original channel */
+            ((bta_av_cb.conn_audio & mask) ||/* connected audio */
+            (bta_av_cb.conn_video & mask)) ) /* connected video */
+        {
+            BTM_GetRole(p_scbi->peer_addr, &role);
+            /* this channel is open - clear the role switch link policy for this link */
+            if(BTM_ROLE_MASTER != role)
+            {
+                if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+                    bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scbi->peer_addr);
+                if (BTM_CMD_STARTED != BTM_SwitchRole(p_scbi->peer_addr, BTM_ROLE_MASTER, NULL))
+                {
+                    /* can not switch role on SCBI
+                     * start the timer on SCB - because this function is ONLY called when SCB gets API_OPEN */
+                    bta_sys_start_timer(&p_scb->timer, BTA_AV_AVRC_TIMER_EVT, BTA_AV_RS_TIME_VAL);
+                }
+                needed = TRUE;
+                /* mark the original channel as waiting for RS result */
+                bta_av_cb.rs_idx = p_scb->hdi + 1;
+                break;
+            }
+        }
+    }
+    return needed;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_link_role_ok
+**
+** Description      This function checks if the SCB has existing ACL connection
+**                  If so, check if the link role fits the requirements.
+**
+** Returns          TRUE, if role is ok
+**
+*******************************************************************************/
+BOOLEAN bta_av_link_role_ok(tBTA_AV_SCB *p_scb, UINT8 bits)
+{
+    UINT8 role;
+    BOOLEAN is_ok = TRUE;
+    BOOLEAN need_timer = FALSE;
+
+    if (BTM_GetRole(p_scb->peer_addr, &role) == BTM_SUCCESS)
+    {
+        APPL_TRACE_ERROR5("bta_av_link_role_ok hndl:x%x role:%d, conn_audio:x%x, bits:%d, features:x%x", p_scb->hndl, role, bta_av_cb.conn_audio, bits, bta_av_cb.features);
+        if (BTM_ROLE_MASTER != role && (A2D_BitsSet(bta_av_cb.conn_audio) > bits || (bta_av_cb.features & BTA_AV_FEAT_MASTER)))
+        {
+            if (bta_av_cb.features & BTA_AV_FEAT_MASTER)
+                bta_sys_clear_policy(BTA_ID_AV, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_scb->peer_addr);
+
+            if (BTM_CMD_STARTED != BTM_SwitchRole(p_scb->peer_addr, BTM_ROLE_MASTER, NULL))
+            {
+                /* can not switch role on SCB - start the timer on SCB */
+                need_timer = TRUE;
+            }
+            is_ok = FALSE;
+            p_scb->wait |= BTA_AV_WAIT_ROLE_SW_RES_START;
+
+        }
+    }
+
+    return is_ok;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_chk_mtu
+**
+** Description      if this is audio channel, check if more than one audio
+**                  channel is connected.
+**
+** Returns          The smallest mtu of the connected audio channels
+**
+*******************************************************************************/
+UINT16 bta_av_chk_mtu(tBTA_AV_SCB *p_scb, UINT16 mtu)
+{
+    UINT16 ret_mtu = BTA_AV_MAX_A2DP_MTU;
+    tBTA_AV_SCB *p_scbi;
+    int i;
+    UINT8   mask;
+
+    /* TODO_MV mess with the mtu according to the number of EDR/non-EDR headsets */
+    if(p_scb->chnl == BTA_AV_CHNL_AUDIO)
+    {
+        if(bta_av_cb.audio_open_cnt >= 2)
+        {
+            /* more than one audio channel is connected */
+            for(i=0; i<BTA_AV_NUM_STRS; i++)
+            {
+                p_scbi = bta_av_cb.p_scb[i];
+                if((p_scb != p_scbi) && p_scbi && (p_scbi->chnl == BTA_AV_CHNL_AUDIO) )
+                {
+                    mask = BTA_AV_HNDL_TO_MSK(i);
+                    APPL_TRACE_DEBUG3("[%d] mtu: %d, mask:0x%x",
+                        i, p_scbi->stream_mtu, mask);
+                    if(bta_av_cb.conn_audio & mask)
+                    {
+                        if(ret_mtu > p_scbi->stream_mtu)
+                            ret_mtu = p_scbi->stream_mtu;
+                    }
+                }
+            }
+        }
+        APPL_TRACE_DEBUG3("bta_av_chk_mtu audio count:%d, conn_audio:0x%x, ret:%d",
+            bta_av_cb.audio_open_cnt, bta_av_cb.conn_audio, ret_mtu);
+    }
+    return ret_mtu;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_dup_audio_buf
+**
+** Description      dup the audio data to the q_info.a2d of other audio channels
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_dup_audio_buf(tBTA_AV_SCB *p_scb, BT_HDR *p_buf)
+{
+    tBTA_AV_SCB *p_scbi;
+    BUFFER_Q    *pq;
+    int     i;
+    UINT16  size, copy_size;
+    BT_HDR *p_new;
+
+    if(!p_buf)
+        return;
+
+    if(bta_av_cb.audio_open_cnt >= 2)
+    {
+        size = GKI_get_buf_size(p_buf);
+        copy_size = BT_HDR_SIZE + p_buf->len + p_buf->offset;
+        /* more than one audio channel is connected */
+        for(i=0; i<BTA_AV_NUM_STRS; i++)
+        {
+            p_scbi = bta_av_cb.p_scb[i];
+            if( (p_scb->hdi != i) && /* not the original channel */
+                (bta_av_cb.conn_audio & BTA_AV_HNDL_TO_MSK(i)) && /* connected audio */
+                p_scbi && p_scbi->co_started ) /* scb is used and started */
+            {
+                /* enqueue the data only when the stream is started */
+                p_new = (BT_HDR *)GKI_getbuf(size);
+                if(p_new)
+                {
+                    memcpy(p_new, p_buf, copy_size);
+                    pq = &p_scbi->q_info.a2d;
+                    GKI_enqueue(pq, p_new);
+                    if(pq->count > p_bta_av_cfg->audio_mqs)
+                    {
+                        bta_av_co_audio_drop(p_scbi->hndl);
+                        GKI_freebuf(GKI_dequeue(pq));
+                    }
+                }
+            }
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sm_execute
+**
+** Description      State machine event handling function for AV
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_sm_execute(tBTA_AV_CB *p_cb, UINT16 event, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_ST_TBL      state_table;
+    UINT8               action;
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+    APPL_TRACE_EVENT4("AV event=0x%x(%s) state=%d(%s)",
+        event, bta_av_evt_code(event), p_cb->state, bta_av_st_code(p_cb->state));
+#else
+    APPL_TRACE_EVENT2("AV event=0x%x state=%d", event, p_cb->state);
+#endif
+
+    /* look up the state table for the current state */
+    state_table = bta_av_st_tbl[p_cb->state];
+
+    event &= 0x00FF;
+
+    /* set next state */
+    p_cb->state = state_table[event][BTA_AV_NEXT_STATE];
+    APPL_TRACE_EVENT1("next state=%d", p_cb->state);
+
+    /* execute action functions */
+    if ((action = state_table[event][BTA_AV_ACTION_COL]) != BTA_AV_IGNORE)
+    {
+        (*bta_av_action[action])(p_cb, p_data);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_av_hdl_event
+**
+** Description      Advanced audio/video main event handling function.
+**
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN bta_av_hdl_event(BT_HDR *p_msg)
+{
+    UINT16 event = p_msg->event;
+    UINT16 first_event = BTA_AV_FIRST_NSM_EVT;
+
+    if (event > BTA_AV_LAST_EVT)
+    {
+        return TRUE; /* to free p_msg */
+    }
+
+    if(event >= first_event)
+    {
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+        APPL_TRACE_EVENT2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
+#else
+        APPL_TRACE_EVENT1("AV nsm event=0x%x", event);
+#endif
+        /* non state machine events */
+        (*bta_av_nsm_act[event - BTA_AV_FIRST_NSM_EVT]) ((tBTA_AV_DATA *) p_msg);
+    }
+    else if (event >= BTA_AV_FIRST_SM_EVT && event <= BTA_AV_LAST_SM_EVT)
+    {
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+        APPL_TRACE_EVENT2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
+#else
+        APPL_TRACE_EVENT1("AV sm event=0x%x", event);
+#endif
+        /* state machine events */
+        bta_av_sm_execute(&bta_av_cb, p_msg->event, (tBTA_AV_DATA *) p_msg);
+    }
+    else
+    {
+        APPL_TRACE_EVENT1("handle=0x%x", p_msg->layer_specific);
+        /* stream state machine events */
+        bta_av_ssm_execute( bta_av_hndl_to_scb(p_msg->layer_specific),
+                                p_msg->event, (tBTA_AV_DATA *) p_msg);
+    }
+    return TRUE;
+}
+
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+/*******************************************************************************
+**
+** Function         bta_av_st_code
+**
+** Description
+**
+** Returns          char *
+**
+*******************************************************************************/
+static char *bta_av_st_code(UINT8 state)
+{
+    switch(state)
+    {
+    case BTA_AV_INIT_ST: return "INIT";
+    case BTA_AV_OPEN_ST: return "OPEN";
+    default:             return "unknown";
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_av_evt_code
+**
+** Description
+**
+** Returns          char *
+**
+*******************************************************************************/
+char *bta_av_evt_code(UINT16 evt_code)
+{
+    switch(evt_code)
+    {
+    case BTA_AV_API_DISABLE_EVT: return "API_DISABLE";
+    case BTA_AV_API_REMOTE_CMD_EVT: return "API_REMOTE_CMD";
+    case BTA_AV_API_VENDOR_CMD_EVT: return "API_VENDOR_CMD";
+    case BTA_AV_API_VENDOR_RSP_EVT: return "API_VENDOR_RSP";
+    case BTA_AV_API_META_RSP_EVT: return "API_META_RSP_EVT";
+    case BTA_AV_API_RC_CLOSE_EVT: return "API_RC_CLOSE";
+    case BTA_AV_AVRC_OPEN_EVT: return "AVRC_OPEN";
+    case BTA_AV_AVRC_MSG_EVT: return "AVRC_MSG";
+    case BTA_AV_AVRC_NONE_EVT: return "AVRC_NONE";
+
+    case BTA_AV_API_OPEN_EVT: return "API_OPEN";
+    case BTA_AV_API_CLOSE_EVT: return "API_CLOSE";
+    case BTA_AV_AP_START_EVT: return "AP_START";
+    case BTA_AV_AP_STOP_EVT: return "AP_STOP";
+    case BTA_AV_API_RECONFIG_EVT: return "API_RECONFIG";
+    case BTA_AV_API_PROTECT_REQ_EVT: return "API_PROTECT_REQ";
+    case BTA_AV_API_PROTECT_RSP_EVT: return "API_PROTECT_RSP";
+    case BTA_AV_API_RC_OPEN_EVT: return "API_RC_OPEN";
+    case BTA_AV_SRC_DATA_READY_EVT: return "SRC_DATA_READY";
+    case BTA_AV_CI_SETCONFIG_OK_EVT: return "CI_SETCONFIG_OK";
+    case BTA_AV_CI_SETCONFIG_FAIL_EVT: return "CI_SETCONFIG_FAIL";
+    case BTA_AV_SDP_DISC_OK_EVT: return "SDP_DISC_OK";
+    case BTA_AV_SDP_DISC_FAIL_EVT: return "SDP_DISC_FAIL";
+    case BTA_AV_STR_DISC_OK_EVT: return "STR_DISC_OK";
+    case BTA_AV_STR_DISC_FAIL_EVT: return "STR_DISC_FAIL";
+    case BTA_AV_STR_GETCAP_OK_EVT: return "STR_GETCAP_OK";
+    case BTA_AV_STR_GETCAP_FAIL_EVT: return "STR_GETCAP_FAIL";
+    case BTA_AV_STR_OPEN_OK_EVT: return "STR_OPEN_OK";
+    case BTA_AV_STR_OPEN_FAIL_EVT: return "STR_OPEN_FAIL";
+    case BTA_AV_STR_START_OK_EVT: return "STR_START_OK";
+    case BTA_AV_STR_START_FAIL_EVT: return "STR_START_FAIL";
+    case BTA_AV_STR_CLOSE_EVT: return "STR_CLOSE";
+    case BTA_AV_STR_CONFIG_IND_EVT: return "STR_CONFIG_IND";
+    case BTA_AV_STR_SECURITY_IND_EVT: return "STR_SECURITY_IND";
+    case BTA_AV_STR_SECURITY_CFM_EVT: return "STR_SECURITY_CFM";
+    case BTA_AV_STR_WRITE_CFM_EVT: return "STR_WRITE_CFM";
+    case BTA_AV_STR_SUSPEND_CFM_EVT: return "STR_SUSPEND_CFM";
+    case BTA_AV_STR_RECONFIG_CFM_EVT: return "STR_RECONFIG_CFM";
+    case BTA_AV_AVRC_TIMER_EVT: return "AVRC_TIMER";
+    case BTA_AV_AVDT_CONNECT_EVT: return "AVDT_CONNECT";
+    case BTA_AV_AVDT_DISCONNECT_EVT: return "AVDT_DISCONNECT";
+    case BTA_AV_ROLE_CHANGE_EVT: return "ROLE_CHANGE";
+    case BTA_AV_AVDT_DELAY_RPT_EVT: return "AVDT_DELAY_RPT";
+    case BTA_AV_ACP_CONNECT_EVT: return "ACP_CONNECT";
+
+    case BTA_AV_API_ENABLE_EVT: return "API_ENABLE";
+    case BTA_AV_API_REGISTER_EVT: return "API_REG";
+    case BTA_AV_API_DEREGISTER_EVT: return "API_DEREG";
+    case BTA_AV_API_DISCONNECT_EVT: return "API_DISCNT";
+    case BTA_AV_CI_SRC_DATA_READY_EVT: return "CI_DATA_READY";
+    case BTA_AV_SIG_CHG_EVT: return "SIG_CHG";
+    case BTA_AV_SIG_TIMER_EVT: return "SIG_TMR";
+    case BTA_AV_SDP_AVRC_DISC_EVT: return "SDP_AVRC_DISC";
+    case BTA_AV_AVRC_CLOSE_EVT: return "AVRC_CLOSE";
+    case BTA_AV_CONN_CHG_EVT: return "CONN_CHG";
+    case BTA_AV_DEREG_COMP_EVT: return "DEREG_COMP";
+#if (AVDT_REPORTING == TRUE)
+    case BTA_AV_AVDT_RPT_CONN_EVT: return "RPT_CONN";
+#endif
+    case BTA_AV_API_START_EVT: return "API_START";
+    case BTA_AV_API_STOP_EVT: return "API_STOP";
+    default:             return "unknown";
+    }
+}
+#endif
+
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/av/bta_av_sbc.c b/bta/av/bta_av_sbc.c
new file mode 100644
index 0000000..1517270
--- /dev/null
+++ b/bta/av/bta_av_sbc.c
@@ -0,0 +1,590 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 utility functions for dealing with SBC data frames
+ *  and codec capabilities.
+ *
+ ******************************************************************************/
+
+#include "a2d_api.h"
+#include "a2d_sbc.h"
+#include "bta_av_sbc.h"
+
+typedef int (tBTA_AV_SBC_ACT)(void *p_src, void *p_dst,
+                               UINT32 src_samples, UINT32 dst_samples,
+                               UINT32 *p_ret);
+
+typedef struct
+{
+    INT32               cur_pos;    /* current position */
+    UINT32              src_sps;    /* samples per second (source audio data) */
+    UINT32              dst_sps;    /* samples per second (converted audio data) */
+    tBTA_AV_SBC_ACT     *p_act;     /* the action function to do the conversion */
+    UINT16              bits;       /* number of bits per pcm sample */
+    UINT16              n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
+    INT16               worker1;
+    INT16               worker2;
+    UINT8               div;
+} tBTA_AV_SBC_UPS_CB;
+
+tBTA_AV_SBC_UPS_CB bta_av_sbc_ups_cb;
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_init_up_sample
+**
+** Description      initialize the up sample
+**
+**                  src_sps: samples per second (source audio data)
+**                  dst_sps: samples per second (converted audio data)
+**                  bits: number of bits per pcm sample
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+void bta_av_sbc_init_up_sample (UINT32 src_sps, UINT32 dst_sps, UINT16 bits, UINT16 n_channels)
+{
+    bta_av_sbc_ups_cb.cur_pos   = -1;
+    bta_av_sbc_ups_cb.src_sps   = src_sps;
+    bta_av_sbc_ups_cb.dst_sps   = dst_sps;
+    bta_av_sbc_ups_cb.bits      = bits;
+    bta_av_sbc_ups_cb.n_channels= n_channels;
+
+    if(n_channels == 1)
+    {
+        /* mono */
+        if(bits == 8)
+        {
+            bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8m;
+            bta_av_sbc_ups_cb.div   = 1;
+        }
+        else
+        {
+            bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16m;
+            bta_av_sbc_ups_cb.div   = 2;
+        }
+    }
+    else
+    {
+        /* stereo */
+        if(bits == 8)
+        {
+            bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_8s;
+            bta_av_sbc_ups_cb.div   = 2;
+        }
+        else
+        {
+            bta_av_sbc_ups_cb.p_act = bta_av_sbc_up_sample_16s;
+            bta_av_sbc_ups_cb.div   = 4;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (number of bytes)
+**                  dst_samples: The size of p_dst (number of bytes)
+**
+** Note:            An AE reported an issue with this function.
+**                  When called with bta_av_sbc_up_sample(src, uint8_array_dst..)
+**                  the byte before uint8_array_dst may get overwritten.
+**                  Using uint16_array_dst avoids the problem.
+**                  This issue is related to endian-ness and is hard to resolve
+**                  in a generic manner.
+** **************** Please use uint16 array as dst.
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample (void *p_src, void *p_dst,
+                         UINT32 src_samples, UINT32 dst_samples,
+                         UINT32 *p_ret)
+{
+    UINT32 src;
+    UINT32 dst;
+
+    if(bta_av_sbc_ups_cb.p_act)
+    {
+        src = src_samples/bta_av_sbc_ups_cb.div;
+        dst = dst_samples/bta_av_sbc_ups_cb.div;
+        return (*bta_av_sbc_ups_cb.p_act)(p_src, p_dst, src, dst, p_ret);
+    }
+    else
+    {
+        *p_ret = 0;
+        return 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_16s (16bits-stereo)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 4 bytes)
+**                  dst_samples: The size of p_dst (in uint of 4 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_16s (void *p_src, void *p_dst,
+                         UINT32 src_samples, UINT32 dst_samples,
+                         UINT32 *p_ret)
+{
+    INT16   *p_src_tmp = (INT16 *)p_src;
+    INT16   *p_dst_tmp = (INT16 *)p_dst;
+    INT16   *p_worker1 = &bta_av_sbc_ups_cb.worker1;
+    INT16   *p_worker2 = &bta_av_sbc_ups_cb.worker2;
+    UINT32  src_sps = bta_av_sbc_ups_cb.src_sps;
+    UINT32  dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+    while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+    {
+        *p_dst_tmp++    = *p_worker1;
+        *p_dst_tmp++    = *p_worker2;
+
+        bta_av_sbc_ups_cb.cur_pos -= src_sps;
+        dst_samples--;
+    }
+
+    bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+    while (src_samples-- && dst_samples)
+    {
+        *p_worker1 = *p_src_tmp++;
+        *p_worker2 = *p_src_tmp++;
+
+        do
+        {
+            *p_dst_tmp++    = *p_worker1;
+            *p_dst_tmp++    = *p_worker2;
+
+            bta_av_sbc_ups_cb.cur_pos -= src_sps;
+            dst_samples--;
+        } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+        bta_av_sbc_ups_cb.cur_pos += dst_sps;
+    }
+
+    if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+        bta_av_sbc_ups_cb.cur_pos = 0;
+
+    *p_ret = ((char *)p_src_tmp - (char *)p_src);
+    return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_16m (16bits-mono)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 2 bytes)
+**                  dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
+                              UINT32 src_samples, UINT32 dst_samples,
+                              UINT32 *p_ret)
+{
+    INT16   *p_src_tmp = (INT16 *)p_src;
+    INT16   *p_dst_tmp = (INT16 *)p_dst;
+    INT16   *p_worker = &bta_av_sbc_ups_cb.worker1;
+    UINT32  src_sps = bta_av_sbc_ups_cb.src_sps;
+    UINT32  dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+    while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+    {
+        *p_dst_tmp++ = *p_worker;
+        *p_dst_tmp++ = *p_worker;
+
+        bta_av_sbc_ups_cb.cur_pos -= src_sps;
+        dst_samples--;
+        dst_samples--;
+    }
+
+
+    bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+    while (src_samples-- && dst_samples)
+    {
+        *p_worker = *p_src_tmp++;
+
+        do
+        {
+            *p_dst_tmp++ = *p_worker;
+            *p_dst_tmp++ = *p_worker;
+
+            bta_av_sbc_ups_cb.cur_pos -= src_sps;
+            dst_samples--;
+            dst_samples--;
+
+        } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+        bta_av_sbc_ups_cb.cur_pos += dst_sps;
+    }
+
+    if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+        bta_av_sbc_ups_cb.cur_pos = 0;
+
+    *p_ret = ((char *)p_src_tmp - (char *)p_src);
+    return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_8s (8bits-stereo)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 2 bytes)
+**                  dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
+                             UINT32 src_samples, UINT32 dst_samples,
+                             UINT32 *p_ret)
+{
+    UINT8   *p_src_tmp = (UINT8 *)p_src;
+    INT16   *p_dst_tmp = (INT16 *)p_dst;
+    INT16   *p_worker1 = &bta_av_sbc_ups_cb.worker1;
+    INT16   *p_worker2 = &bta_av_sbc_ups_cb.worker2;
+    UINT32  src_sps = bta_av_sbc_ups_cb.src_sps;
+    UINT32  dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+    while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+    {
+        *p_dst_tmp++    = *p_worker1;
+        *p_dst_tmp++    = *p_worker2;
+
+        bta_av_sbc_ups_cb.cur_pos -= src_sps;
+        dst_samples--;
+        dst_samples--;
+    }
+
+    bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+    while (src_samples -- && dst_samples)
+    {
+        *p_worker1 = *(UINT8 *)p_src_tmp++;
+        *p_worker1 -= 0x80;
+        *p_worker1 <<= 8;
+        *p_worker2 = *(UINT8 *)p_src_tmp++;
+        *p_worker2 -= 0x80;
+        *p_worker2 <<= 8;
+
+        do
+        {
+            *p_dst_tmp++    = *p_worker1;
+            *p_dst_tmp++    = *p_worker2;
+
+            bta_av_sbc_ups_cb.cur_pos -= src_sps;
+            dst_samples--;
+            dst_samples--;
+        } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+        bta_av_sbc_ups_cb.cur_pos += dst_sps;
+    }
+
+    if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+        bta_av_sbc_ups_cb.cur_pos = 0;
+
+    *p_ret = ((char *)p_src_tmp - (char *)p_src);
+    return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_8m (8bits-mono)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (number of bytes)
+**                  dst_samples: The size of p_dst (number of bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
+                             UINT32 src_samples, UINT32 dst_samples,
+                             UINT32 *p_ret)
+{
+    UINT8   *p_src_tmp = (UINT8 *)p_src;
+    INT16   *p_dst_tmp = (INT16 *)p_dst;
+    INT16   *p_worker = &bta_av_sbc_ups_cb.worker1;
+    UINT32  src_sps = bta_av_sbc_ups_cb.src_sps;
+    UINT32  dst_sps = bta_av_sbc_ups_cb.dst_sps;
+
+    while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples)
+    {
+        *p_dst_tmp++ = *p_worker;
+        *p_dst_tmp++ = *p_worker;
+
+        bta_av_sbc_ups_cb.cur_pos -= src_sps;
+        dst_samples -= 4;
+    }
+
+
+    bta_av_sbc_ups_cb.cur_pos = dst_sps;
+
+    while (src_samples-- && dst_samples)
+    {
+        *p_worker = *(UINT8 *)p_src_tmp++;
+        *p_worker -= 0x80;
+        *p_worker <<= 8;
+
+        do
+        {
+            *p_dst_tmp++ = *p_worker;
+            *p_dst_tmp++ = *p_worker;
+
+            bta_av_sbc_ups_cb.cur_pos -= src_sps;
+            dst_samples -= 4;
+
+        } while (bta_av_sbc_ups_cb.cur_pos > 0 && dst_samples);
+
+        bta_av_sbc_ups_cb.cur_pos += dst_sps;
+    }
+
+    if (bta_av_sbc_ups_cb.cur_pos == (INT32)dst_sps)
+        bta_av_sbc_ups_cb.cur_pos = 0;
+
+    *p_ret = ((char *)p_src_tmp - (char *)p_src);
+    return ((char *)p_dst_tmp - (char *)p_dst);
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_cfg_for_cap
+**
+** Description      Determine the preferred SBC codec configuration for the
+**                  given codec capabilities.  The function is passed the
+**                  preferred codec configuration and the peer codec
+**                  capabilities for the stream.  The function attempts to
+**                  match the preferred capabilities with the configuration
+**                  as best it can.  The resulting codec configuration is
+**                  returned in the same memory used for the capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**                  Codec configuration in p_cap.
+**
+*******************************************************************************/
+UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p_pref)
+{
+    UINT8           status = A2D_SUCCESS;
+    tA2D_SBC_CIE    peer_cie;
+
+    /* parse peer capabilities */
+    if ((status = A2D_ParsSbcInfo(&peer_cie, p_peer, TRUE)) != 0)
+    {
+        return status;
+    }
+
+    /* Check if the peer supports our channel mode */
+    if (peer_cie.ch_mode & p_pref->ch_mode)
+    {
+        peer_cie.ch_mode = p_pref->ch_mode;
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: ch_mode(0x%02X) not supported", p_pref->ch_mode);
+        return A2D_FAIL;
+    }
+
+    /* Check if the peer supports our sampling freq */
+    if (peer_cie.samp_freq & p_pref->samp_freq)
+    {
+        peer_cie.samp_freq = p_pref->samp_freq;
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: samp_freq(0x%02X) not supported", p_pref->samp_freq);
+        return A2D_FAIL;
+    }
+
+    /* Check if the peer supports our block len */
+    if (peer_cie.block_len & p_pref->block_len)
+    {
+        peer_cie.block_len = p_pref->block_len;
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: block_len(0x%02X) not supported", p_pref->block_len);
+        return A2D_FAIL;
+    }
+
+    /* Check if the peer supports our num subbands */
+    if (peer_cie.num_subbands & p_pref->num_subbands)
+    {
+        peer_cie.num_subbands = p_pref->num_subbands;
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: num_subbands(0x%02X) not supported", p_pref->num_subbands);
+        return A2D_FAIL;
+    }
+
+    /* Check if the peer supports our alloc method */
+    if (peer_cie.alloc_mthd & p_pref->alloc_mthd)
+    {
+        peer_cie.alloc_mthd = p_pref->alloc_mthd;
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_av_sbc_cfg_for_cap: alloc_mthd(0x%02X) not supported", p_pref->alloc_mthd);
+        return A2D_FAIL;
+    }
+
+    /* max bitpool */
+    if (p_pref->max_bitpool != 0 && p_pref->max_bitpool < peer_cie.max_bitpool)
+    {
+        peer_cie.max_bitpool = p_pref->max_bitpool;
+    }
+
+    /* min bitpool */
+    if (p_pref->min_bitpool != 0 && p_pref->min_bitpool > peer_cie.min_bitpool)
+    {
+        peer_cie.min_bitpool = p_pref->min_bitpool;
+    }
+
+    if (status == A2D_SUCCESS)
+    {
+        /* build configuration */
+        A2D_BldSbcInfo(A2D_MEDIA_TYPE_AUDIO, &peer_cie, p_peer);
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_cfg_in_cap
+**
+** Description      This function checks whether an SBC codec configuration
+**                  is allowable for the given codec capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap)
+{
+    UINT8           status = 0;
+    tA2D_SBC_CIE    cfg_cie;
+
+    /* parse configuration */
+    if ((status = A2D_ParsSbcInfo(&cfg_cie, p_cfg, FALSE)) != 0)
+    {
+        return status;
+    }
+
+    /* verify that each parameter is in range */
+
+    /* sampling frequency */
+    if ((cfg_cie.samp_freq & p_cap->samp_freq) == 0)
+    {
+        status = A2D_NS_SAMP_FREQ;
+    }
+    /* channel mode */
+    else if ((cfg_cie.ch_mode & p_cap->ch_mode) == 0)
+    {
+        status = A2D_NS_CH_MODE;
+    }
+    /* block length */
+    else if ((cfg_cie.block_len & p_cap->block_len) == 0)
+    {
+        status = A2D_BAD_BLOCK_LEN;
+    }
+    /* subbands */
+    else if ((cfg_cie.num_subbands & p_cap->num_subbands) == 0)
+    {
+        status = A2D_NS_SUBBANDS;
+    }
+    /* allocation method */
+    else if ((cfg_cie.alloc_mthd & p_cap->alloc_mthd) == 0)
+    {
+        status = A2D_NS_ALLOC_MTHD;
+    }
+    /* max bitpool */
+    else if (cfg_cie.max_bitpool > p_cap->max_bitpool)
+    {
+        status = A2D_NS_MAX_BITPOOL;
+    }
+    /* min bitpool */
+    else if (cfg_cie.min_bitpool < p_cap->min_bitpool)
+    {
+        status = A2D_NS_MIN_BITPOOL;
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_bld_hdr
+**
+** Description      This function builds the packet header for MPF1.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt)
+{
+    UINT8   *p;
+
+    p_buf->offset -= BTA_AV_SBC_HDR_SIZE;
+    p = (UINT8 *) (p_buf + 1) + p_buf->offset;
+    p_buf->len += BTA_AV_SBC_HDR_SIZE;
+    A2D_BldSbcMplHdr(p, FALSE, FALSE, FALSE, (UINT8) fr_per_pkt);
+}
+
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
new file mode 100644
index 0000000..a35a4b0
--- /dev/null
+++ b/bta/av/bta_av_ssm.c
@@ -0,0 +1,599 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the stream state machine for the BTA advanced audio/video.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#if defined(BTA_AV_INCLUDED) && (BTA_AV_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_av_co.h"
+#include "bta_av_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine states */
+enum
+{
+    BTA_AV_INIT_SST,
+    BTA_AV_INCOMING_SST,
+    BTA_AV_OPENING_SST,
+    BTA_AV_OPEN_SST,
+    BTA_AV_RCFG_SST,
+    BTA_AV_CLOSING_SST
+};
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_AV_DO_DISC,
+    BTA_AV_CLEANUP,
+    BTA_AV_FREE_SDB,
+    BTA_AV_CONFIG_IND,
+    BTA_AV_DISCONNECT_REQ,
+    BTA_AV_SECURITY_REQ,
+    BTA_AV_SECURITY_RSP,
+    BTA_AV_SETCONFIG_RSP,
+    BTA_AV_ST_RC_TIMER,
+    BTA_AV_STR_OPENED,
+    BTA_AV_SECURITY_IND,
+    BTA_AV_SECURITY_CFM,
+    BTA_AV_DO_CLOSE,
+    BTA_AV_CONNECT_REQ,
+    BTA_AV_SDP_FAILED,
+    BTA_AV_DISC_RESULTS,
+    BTA_AV_DISC_RES_AS_ACP,
+    BTA_AV_OPEN_FAILED,
+    BTA_AV_GETCAP_RESULTS,
+    BTA_AV_SETCONFIG_REJ,
+    BTA_AV_DISCOVER_REQ,
+    BTA_AV_CONN_FAILED,
+    BTA_AV_DO_START,
+    BTA_AV_STR_STOPPED,
+    BTA_AV_RECONFIG,
+    BTA_AV_DATA_PATH,
+    BTA_AV_START_OK,
+    BTA_AV_START_FAILED,
+    BTA_AV_STR_CLOSED,
+    BTA_AV_CLR_CONG,
+    BTA_AV_SUSPEND_CFM,
+    BTA_AV_RCFG_STR_OK,
+    BTA_AV_RCFG_FAILED,
+    BTA_AV_RCFG_CONNECT,
+    BTA_AV_RCFG_DISCNTD,
+    BTA_AV_SUSPEND_CONT,
+    BTA_AV_RCFG_CFM,
+    BTA_AV_RCFG_OPEN,
+    BTA_AV_SECURITY_REJ,
+    BTA_AV_OPEN_RC,
+    BTA_AV_CHK_2ND_START,
+    BTA_AV_SAVE_CAPS,
+    BTA_AV_SET_USE_RC,
+    BTA_AV_CCO_CLOSE,
+    BTA_AV_SWITCH_ROLE,
+    BTA_AV_ROLE_RES,
+    BTA_AV_DELAY_CO,
+    BTA_AV_OPEN_AT_INC,
+    BTA_AV_NUM_SACTIONS
+};
+
+#define BTA_AV_SIGNORE       BTA_AV_NUM_SACTIONS
+
+
+/* state table information */
+/* #define BTA_AV_SACTION_COL           0       position of actions */
+#define BTA_AV_SACTIONS              2       /* number of actions */
+#define BTA_AV_SNEXT_STATE           2       /* position of next state */
+#define BTA_AV_NUM_COLS              3       /* number of columns in state tables */
+
+/* state table for init state */
+static const UINT8 bta_av_sst_init[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_DO_DISC,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_CLEANUP,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AP_START_EVT */          {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AP_STOP_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_SETCONFIG_REJ,  BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST }
+};
+
+/* state table for incoming state */
+static const UINT8 bta_av_sst_incoming[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_OPEN_AT_INC,    BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_CCO_CLOSE,      BTA_AV_DISCONNECT_REQ, BTA_AV_CLOSING_SST },
+/* AP_START_EVT */          {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AP_STOP_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SECURITY_REQ,   BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SECURITY_RSP,   BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SETCONFIG_RSP,  BTA_AV_ST_RC_TIMER,    BTA_AV_INCOMING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SETCONFIG_RSP,  BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_DISC_RES_AS_ACP,BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_SAVE_CAPS,      BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_STR_OPENED,     BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_CCO_CLOSE,      BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_CONFIG_IND,     BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SECURITY_IND,   BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SECURITY_CFM,   BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_CCO_CLOSE,      BTA_AV_CLEANUP,        BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST }
+};
+
+/* state table for opening state */
+static const UINT8 bta_av_sst_opening[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_DO_CLOSE,       BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_START_EVT */          {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AP_STOP_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SECURITY_REQ,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SECURITY_RSP,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_CONNECT_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_CONNECT_REQ,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_DISC_RESULTS,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_ST_RC_TIMER,    BTA_AV_STR_OPENED,     BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_OPEN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_CONFIG_IND,     BTA_AV_SIGNORE,        BTA_AV_INCOMING_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SECURITY_IND,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SECURITY_CFM,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_SWITCH_ROLE,    BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_DISCOVER_REQ,   BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_CONN_FAILED,    BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_ROLE_RES,       BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_OPENING_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPENING_SST }
+};
+
+/* state table for open state */
+static const UINT8 bta_av_sst_open[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_DO_CLOSE,       BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_START_EVT */          {BTA_AV_DO_START,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* AP_STOP_EVT */           {BTA_AV_STR_STOPPED,    BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_RECONFIG,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SECURITY_REQ,   BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SECURITY_RSP,   BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SET_USE_RC,     BTA_AV_OPEN_RC,        BTA_AV_OPEN_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_DATA_PATH,      BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_SAVE_CAPS,      BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_START_OK_EVT */      {BTA_AV_START_OK,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_START_FAILED,   BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_SETCONFIG_REJ,  BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SECURITY_IND,   BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SECURITY_CFM,   BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_CLR_CONG,       BTA_AV_DATA_PATH,      BTA_AV_OPEN_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SUSPEND_CFM,    BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_OPEN_RC,        BTA_AV_CHK_2ND_START,  BTA_AV_OPEN_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_ROLE_RES,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_OPEN_SST }
+};
+
+/* state table for reconfig state */
+static const UINT8 bta_av_sst_rcfg[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_START_EVT */          {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AP_STOP_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_FREE_SDB,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_DISC_RESULTS,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_GETCAP_RESULTS, BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_RCFG_STR_OK,    BTA_AV_SIGNORE,        BTA_AV_OPEN_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_RCFG_FAILED,    BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_RCFG_CONNECT,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_SETCONFIG_REJ,  BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SUSPEND_CONT,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_RCFG_CFM,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_RCFG_OPEN,      BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_RCFG_DISCNTD,   BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_DELAY_CO,       BTA_AV_SIGNORE,        BTA_AV_RCFG_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_RCFG_SST }
+};
+
+/* state table for closing state */
+static const UINT8 bta_av_sst_closing[][BTA_AV_NUM_COLS] =
+{
+/* Event                     Action 1               Action 2               Next state */
+/* AP_OPEN_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_CLOSE_EVT */          {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_START_EVT */          {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AP_STOP_EVT */           {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_RECONFIG_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_PROTECT_REQ_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_PROTECT_RSP_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* API_RC_OPEN_EVT  */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* SRC_DATA_READY_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* CI_SETCONFIG_OK_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* CI_SETCONFIG_FAIL_EVT */ {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* SDP_DISC_OK_EVT */       {BTA_AV_SDP_FAILED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* SDP_DISC_FAIL_EVT */     {BTA_AV_SDP_FAILED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* STR_DISC_OK_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_DISC_FAIL_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_GETCAP_OK_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_GETCAP_FAIL_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_OPEN_OK_EVT */       {BTA_AV_DO_CLOSE,       BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_OPEN_FAIL_EVT */     {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_START_OK_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_START_FAIL_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_CLOSE_EVT */         {BTA_AV_DISCONNECT_REQ, BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_CONFIG_IND_EVT */    {BTA_AV_SETCONFIG_REJ,  BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_SECURITY_IND_EVT */  {BTA_AV_SECURITY_REJ,   BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_SECURITY_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_WRITE_CFM_EVT */     {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_SUSPEND_CFM_EVT */   {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* STR_RECONFIG_CFM_EVT */  {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AVRC_TIMER_EVT */        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AVDT_CONNECT_EVT */      {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AVDT_DISCONNECT_EVT */   {BTA_AV_STR_CLOSED,     BTA_AV_SIGNORE,        BTA_AV_INIT_SST },
+/* ROLE_CHANGE_EVT*/        {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* AVDT_DELAY_RPT_EVT */    {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST },
+/* ACP_CONNECT_EVT */       {BTA_AV_SIGNORE,        BTA_AV_SIGNORE,        BTA_AV_CLOSING_SST }
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_AV_SST_TBL)[BTA_AV_NUM_COLS];
+
+/* state table */
+static const tBTA_AV_SST_TBL bta_av_sst_tbl[] =
+{
+    bta_av_sst_init,
+    bta_av_sst_incoming,
+    bta_av_sst_opening,
+    bta_av_sst_open,
+    bta_av_sst_rcfg,
+    bta_av_sst_closing
+};
+
+
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+static char *bta_av_sst_code(UINT8 state);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_is_rcfg_sst
+**
+** Description      Check if stream state machine is in reconfig state.
+**
+**
+** Returns          TRUE if stream state machine is in reconfig state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_rcfg_sst (tBTA_AV_SCB *p_scb)
+{
+    BOOLEAN is_rcfg_sst = FALSE;
+
+    if (p_scb != NULL)
+    {
+        if (p_scb->state == BTA_AV_RCFG_SST)
+            is_rcfg_sst = TRUE;
+    }
+
+    return is_rcfg_sst;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_ssm_execute
+**
+** Description      Stream state machine event handling function for AV
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_av_ssm_execute(tBTA_AV_SCB *p_scb, UINT16 event, tBTA_AV_DATA *p_data)
+{
+    tBTA_AV_SST_TBL     state_table;
+    UINT8               action;
+    int                 i, xx;
+
+    if(p_scb == NULL)
+    {
+        /* this stream is not registered */
+        APPL_TRACE_EVENT0("AV channel not registered");
+        return;
+    }
+
+    /* In case incoming connection is for VDP, we need to swap scb.        */
+    /* When ACP_CONNECT_EVT was received, we put first available scb to    */
+    /* to Incoming state. Later, when STR_CONFIG_IND_EVT is coming, we     */
+    /* know if it is A2DP or VDP.                                          */
+    if ((p_scb->state == BTA_AV_INIT_SST) && (event == BTA_AV_STR_CONFIG_IND_EVT))
+    {
+        for (xx = 0; xx < BTA_AV_NUM_STRS; xx++)
+        {
+            if (bta_av_cb.p_scb[xx])
+            {
+                if (bta_av_cb.p_scb[xx]->state == BTA_AV_INCOMING_SST)
+                {
+                    bta_av_cb.p_scb[xx]->state = BTA_AV_INIT_SST;
+                    bta_av_cb.p_scb[xx]->coll_mask = 0;
+                    p_scb->state = BTA_AV_INCOMING_SST;
+                    break;
+                }
+            }
+        }
+    }
+
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+    APPL_TRACE_EVENT5("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
+        p_scb->hndl, event, bta_av_evt_code(event), p_scb->state, bta_av_sst_code(p_scb->state));
+#else
+    APPL_TRACE_EVENT2("AV Sevent=0x%x state=%d", event, p_scb->state);
+#endif
+
+    /* look up the state table for the current state */
+    state_table = bta_av_sst_tbl[p_scb->state];
+
+    event -= BTA_AV_FIRST_SSM_EVT;
+
+    /* set next state */
+    p_scb->state = state_table[event][BTA_AV_SNEXT_STATE];
+
+    /* execute action functions */
+    for(i=0; i< BTA_AV_SACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_AV_SIGNORE)
+        {
+            (*p_scb->p_act_tbl[action])(p_scb, p_data);
+        }
+        else
+            break;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_is_scb_opening
+**
+** Description      Returns TRUE is scb is in opening state.
+**
+**
+** Returns          TRUE if scb is in opening state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_opening (tBTA_AV_SCB *p_scb)
+{
+    BOOLEAN is_opening = FALSE;
+
+    if (p_scb)
+    {
+        if (p_scb->state == BTA_AV_OPENING_SST)
+            is_opening = TRUE;
+    }
+
+    return is_opening;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_is_scb_incoming
+**
+** Description      Returns TRUE is scb is in incoming state.
+**
+**
+** Returns          TRUE if scb is in incoming state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_incoming (tBTA_AV_SCB *p_scb)
+{
+    BOOLEAN is_incoming = FALSE;
+
+    if (p_scb)
+    {
+        if (p_scb->state == BTA_AV_INCOMING_SST)
+            is_incoming = TRUE;
+    }
+
+    return is_incoming;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_set_scb_sst_init
+**
+** Description      Set SST state to INIT.
+**                  Use this function to change SST outside of state machine.
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_av_set_scb_sst_init (tBTA_AV_SCB *p_scb)
+{
+    if (p_scb)
+    {
+        p_scb->state = BTA_AV_INIT_SST;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_is_scb_init
+**
+** Description      Returns TRUE is scb is in init state.
+**
+**
+** Returns          TRUE if scb is in incoming state.
+**
+*******************************************************************************/
+BOOLEAN bta_av_is_scb_init (tBTA_AV_SCB *p_scb)
+{
+    BOOLEAN is_init = FALSE;
+
+    if (p_scb)
+    {
+        if (p_scb->state == BTA_AV_INIT_SST)
+            is_init = TRUE;
+    }
+
+    return is_init;
+}
+
+/*******************************************************************************
+**
+** Function         bta_av_set_scb_sst_incoming
+**
+** Description      Set SST state to incoming.
+**                  Use this function to change SST outside of state machine.
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_av_set_scb_sst_incoming (tBTA_AV_SCB *p_scb)
+{
+    if (p_scb)
+    {
+        p_scb->state = BTA_AV_INCOMING_SST;
+    }
+}
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
+/*******************************************************************************
+**
+** Function         bta_av_sst_code
+**
+** Description
+**
+** Returns          char *
+**
+*******************************************************************************/
+static char *bta_av_sst_code(UINT8 state)
+{
+    switch(state)
+    {
+    case BTA_AV_INIT_SST: return "INIT";
+    case BTA_AV_INCOMING_SST: return "INCOMING";
+    case BTA_AV_OPENING_SST: return "OPENING";
+    case BTA_AV_OPEN_SST: return "OPEN";
+    case BTA_AV_RCFG_SST: return "RCFG";
+    case BTA_AV_CLOSING_SST: return "CLOSING";
+    default:             return "unknown";
+    }
+}
+
+#endif
+#endif /* BTA_AV_INCLUDED */
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
new file mode 100644
index 0000000..29b4ec2
--- /dev/null
+++ b/bta/dm/bta_dm_act.c
@@ -0,0 +1,4886 @@
+/******************************************************************************
+ *
+ *  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 the action functions for device manager state
+ *  machine.
+ *
+ ******************************************************************************/
+
+#include "bt_types.h"
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_dm_co.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "btu.h"
+#include "sdp_api.h"
+#include "l2c_api.h"
+#include "wbt_api.h"
+#include "utl.h"
+#include <string.h>
+
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_inq_cmpl_cb (void * p_result);
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name);
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name);
+static void bta_dm_find_services ( BD_ADDR bd_addr);
+static void bta_dm_discover_next_device(void);
+static void bta_dm_sdp_callback (UINT16 sdp_status);
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator);
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name);
+static UINT8 bta_dm_link_key_request_cback (BD_ADDR bd_addr, LINK_KEY key);
+static UINT8 bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name, LINK_KEY key, UINT8 key_type);
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result);
+static void bta_dm_local_name_cback(BD_ADDR bd_addr);
+static BOOLEAN bta_dm_check_av(UINT16 event);
+#if (BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data);
+#else
+static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn, BD_FEATURES features, BOOLEAN is_new);
+#endif
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* Extended Inquiry Response */
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data);
+
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+static void bta_dm_set_eir (char *local_name);
+#endif /* BTM_EIR_SERVER_INCLUDED */
+
+#if (BTM_EIR_CLIENT_INCLUDED == TRUE)
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS  *p_result,
+                                        tBTA_SERVICE_MASK *p_services_to_search,
+                                        tBTA_SERVICE_MASK *p_services_found);
+#endif /* BTM_EIR_CLIENT_INCLUDED */
+
+static void bta_dm_rssi_cback (tBTM_RSSI_RESULTS *p_result);
+static void bta_dm_signal_strength_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_link_quality_cback (tBTM_LINK_QUALITY_RESULTS *p_result);
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle);
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch);
+static char *bta_dm_get_remname(void);
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result);
+
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr);
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr);
+
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status );
+
+static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr);
+static void bta_dm_delay_role_switch_cback (TIMER_LIST_ENT *p_tle);
+
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    #if ((defined SMP_INCLUDED) && (SMP_INCLUDED == TRUE))
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data);
+    #endif
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key);
+    #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+static void btm_dm_start_gatt_discovery ( BD_ADDR bd_addr);
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr);
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+    #endif
+#endif
+
+extern void sdpu_uuid16_to_uuid128(UINT16 uuid16, UINT8* p_uuid128);
+
+const UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+    UUID_SERVCLASS_PNP_INFORMATION,         /* Reserved */
+    UUID_SERVCLASS_SERIAL_PORT,             /* BTA_SPP_SERVICE_ID */
+    UUID_SERVCLASS_DIALUP_NETWORKING,       /* BTA_DUN_SERVICE_ID */
+    UUID_SERVCLASS_AUDIO_SOURCE,            /* BTA_A2DP_SOURCE_SERVICE_ID */
+    UUID_SERVCLASS_LAN_ACCESS_USING_PPP,    /* BTA_LAP_SERVICE_ID */
+    UUID_SERVCLASS_HEADSET,                 /* BTA_HSP_HS_SERVICE_ID */
+    UUID_SERVCLASS_HF_HANDSFREE,            /* BTA_HFP_HS_SERVICE_ID */
+    UUID_SERVCLASS_OBEX_OBJECT_PUSH,        /* BTA_OPP_SERVICE_ID */
+    UUID_SERVCLASS_OBEX_FILE_TRANSFER,      /* BTA_FTP_SERVICE_ID */
+    UUID_SERVCLASS_CORDLESS_TELEPHONY,      /* BTA_CTP_SERVICE_ID */
+    UUID_SERVCLASS_INTERCOM,                /* BTA_ICP_SERVICE_ID */
+    UUID_SERVCLASS_IRMC_SYNC,               /* BTA_SYNC_SERVICE_ID */
+    UUID_SERVCLASS_DIRECT_PRINTING,         /* BTA_BPP_SERVICE_ID */
+    UUID_SERVCLASS_IMAGING_RESPONDER,       /* BTA_BIP_SERVICE_ID */
+    UUID_SERVCLASS_PANU,                    /* BTA_PANU_SERVICE_ID */
+    UUID_SERVCLASS_NAP,                     /* BTA_NAP_SERVICE_ID */
+    UUID_SERVCLASS_GN,                      /* BTA_GN_SERVICE_ID */
+    UUID_SERVCLASS_SAP,                     /* BTA_SAP_SERVICE_ID */
+    UUID_SERVCLASS_AUDIO_SINK,              /* BTA_A2DP_SERVICE_ID */
+    UUID_SERVCLASS_AV_REMOTE_CONTROL,       /* BTA_AVRCP_SERVICE_ID */
+    UUID_SERVCLASS_HUMAN_INTERFACE,         /* BTA_HID_SERVICE_ID */
+    UUID_SERVCLASS_VIDEO_SINK,              /* BTA_VDP_SERVICE_ID */
+    UUID_SERVCLASS_PBAP_PSE,                /* BTA_PBAP_SERVICE_ID */
+    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,   /* BTA_HSP_SERVICE_ID */
+    UUID_SERVCLASS_AG_HANDSFREE,            /* BTA_HFP_SERVICE_ID */
+    UUID_SERVCLASS_MESSAGE_ACCESS,          /* BTA_MAP_SERVICE_ID */
+    UUID_SERVCLASS_MESSAGE_NOTIFICATION,    /* BTA_MN_SERVICE_ID */
+    UUID_SERVCLASS_HDP_PROFILE,             /* BTA_HDP_SERVICE_ID */
+    UUID_SERVCLASS_PBAP_PCE                 /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+    ,UUID_PROTOCOL_ATT                       /* BTA_GATT_SERVICE_ID */
+#endif
+};
+
+/*
+ * NOTE : The number of element in bta_service_id_to_btm_srv_id_lkup_tbl should be matching with
+ *        the value BTA_MAX_SERVICE_ID in bta_api.h
+ *
+ *        i.e., If you add new Service ID for BTA, the correct security ID of the new service
+ *              from Security service definitions (btm_api.h) should be added to this lookup table.
+ */
+const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl [BTA_MAX_SERVICE_ID] =
+{
+    0,                                      /* Reserved */
+    BTM_SEC_SERVICE_SERIAL_PORT,            /* BTA_SPP_SERVICE_ID */
+    BTM_SEC_SERVICE_DUN,                    /* BTA_DUN_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_AUDIO_SOURCE_SERVICE_ID */
+    BTM_SEC_SERVICE_LAN_ACCESS,             /* BTA_LAP_SERVICE_ID */
+    BTM_SEC_SERVICE_HEADSET_AG,             /* BTA_HSP_SERVICE_ID */
+    BTM_SEC_SERVICE_AG_HANDSFREE,           /* BTA_HFP_SERVICE_ID */
+    BTM_SEC_SERVICE_OBEX,                   /* BTA_OPP_SERVICE_ID */
+    BTM_SEC_SERVICE_OBEX_FTP,               /* BTA_FTP_SERVICE_ID */
+    BTM_SEC_SERVICE_CORDLESS,               /* BTA_CTP_SERVICE_ID */
+    BTM_SEC_SERVICE_INTERCOM,               /* BTA_ICP_SERVICE_ID */
+    BTM_SEC_SERVICE_IRMC_SYNC,              /* BTA_SYNC_SERVICE_ID */
+    BTM_SEC_SERVICE_BPP_JOB,                /* BTA_BPP_SERVICE_ID */
+    BTM_SEC_SERVICE_BIP,                    /* BTA_BIP_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_PANU,              /* BTA_PANU_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_NAP,               /* BTA_NAP_SERVICE_ID */
+    BTM_SEC_SERVICE_BNEP_GN,                /* BTA_GN_SERVICE_ID */
+    BTM_SEC_SERVICE_SAP,                    /* BTA_SAP_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_A2DP_SERVICE_ID */
+    BTM_SEC_SERVICE_AVCTP,                  /* BTA_AVRCP_SERVICE_ID */
+    BTM_SEC_SERVICE_HID_SEC_CTRL,           /* BTA_HID_SERVICE_ID */
+    BTM_SEC_SERVICE_AVDTP,                  /* BTA_VDP_SERVICE_ID */
+    BTM_SEC_SERVICE_PBAP,                   /* BTA_PBAP_SERVICE_ID */
+    BTM_SEC_SERVICE_HEADSET,                /* BTA_HSP_HS_SERVICE_ID */
+    BTM_SEC_SERVICE_HF_HANDSFREE,           /* BTA_HFP_HS_SERVICE_ID */
+    BTM_SEC_SERVICE_MAP,                    /* BTA_MAP_SERVICE_ID */
+    BTM_SEC_SERVICE_MAP,                    /* BTA_MN_SERVICE_ID */
+    BTM_SEC_SERVICE_HDP_SNK,                /* BTA_HDP_SERVICE_ID */
+    BTM_SEC_SERVICE_PBAP                    /* BTA_PCE_SERVICE_ID */
+#if BLE_INCLUDED && BTA_GATT_INCLUDED
+    ,BTM_SEC_SERVICE_ATT                    /* BTA_GATT_SERVICE_ID */
+#endif
+};
+
+/* bta security callback */
+const tBTM_APPL_INFO bta_security =
+{
+    &bta_dm_authorize_cback,
+    &bta_dm_pin_cback,
+    &bta_dm_new_link_key_cback,
+    &bta_dm_link_key_request_cback,
+    &bta_dm_authentication_complete_cback,
+    NULL,
+    &bta_dm_bond_cancel_complete_cback,
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    &bta_dm_sp_cback
+#else
+    NULL
+#endif
+#if BLE_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
+    ,&bta_dm_ble_smp_cback
+#endif
+    ,&bta_dm_ble_id_key_cback
+#endif
+
+};
+
+/* TBD... To be moved to some conf file..? */
+#define BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT   5
+const tBTA_DM_LMP_VER_INFO bta_role_switch_blacklist[BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT] =
+{
+        {0x000F,0x2000,0x04},
+        {0x00,0x00,0x00},
+        {0x00,0x00,0x00},
+        {0x00,0x00,0x00},
+        {0x00,0x00,0x00}
+};
+
+#define MAX_DISC_RAW_DATA_BUF       (4096)
+UINT8 g_disc_raw_data_buf[MAX_DISC_RAW_DATA_BUF];
+
+/*******************************************************************************
+**
+** Function         bta_dm_app_ready_timer_cback
+**
+** Description      allow sending EIR to controller
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+static void bta_dm_app_ready_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    bta_dm_set_eir (NULL);
+}
+#else
+#define bta_dm_app_ready_timer_cback (x)
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_enable
+**
+** Description      Initialises the BT device manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_enable(tBTA_DM_MSG *p_data)
+{
+    tBTA_SYS_HW_MSG *sys_enable_event;
+    tBTA_DM_SEC sec_event;
+
+
+    /* if already in use, return an error */
+    if( bta_dm_cb.is_bta_dm_active == TRUE  )
+    {
+        APPL_TRACE_WARNING0("bta_dm_enable - device already started by another application");
+        memset(&sec_event.enable, 0, sizeof ( tBTA_DM_ENABLE ));
+        sec_event.enable.status = BTA_FAILURE;
+        if( p_data->enable.p_sec_cback != NULL  )
+            p_data->enable.p_sec_cback (BTA_DM_ENABLE_EVT, &sec_event);
+        return;
+    }
+
+
+    /* first, register our callback to SYS HW manager */
+    bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+    /* make sure security callback is saved - if no callback, do not erase the previous one,
+    it could be an error recovery mechanism */
+    if( p_data->enable.p_sec_cback != NULL  )
+    bta_dm_cb.p_sec_cback = p_data->enable.p_sec_cback;
+    /* notify BTA DM is now active */
+    bta_dm_cb.is_bta_dm_active = TRUE;
+
+    /* send a message to BTA SYS */
+    if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        sys_enable_event->hdr.event = BTA_SYS_API_ENABLE_EVT;
+        sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+
+        bta_sys_sendmsg(sys_enable_event);
+
+    }
+
+
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sys_hw_cback
+**
+** Description     callback register to SYS to get HW status updates
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_sys_hw_cback( tBTA_SYS_HW_EVT status )
+{
+    DEV_CLASS   dev_class;
+    tBTA_DM_SEC_CBACK           *temp_cback;
+#if BLE_INCLUDED == TRUE
+    UINT8                   key_mask = 0;
+    BT_OCTET16              er;
+    tBTA_BLE_LOCAL_ID_KEYS  id_key;
+    tBT_UUID                app_uuid = {LEN_UUID_128,{0}};
+#endif
+    APPL_TRACE_DEBUG1(" bta_dm_sys_hw_cback with event: %i" , status );
+
+    /* On H/W error evt, report to the registered DM application callback */
+    if (status == BTA_SYS_HW_ERROR_EVT) {
+          if( bta_dm_cb.p_sec_cback != NULL )
+                bta_dm_cb.p_sec_cback(BTA_DM_HW_ERROR_EVT, NULL);
+          return;
+    }
+    if( status == BTA_SYS_HW_OFF_EVT )
+    {
+        if( bta_dm_cb.p_sec_cback != NULL )
+            bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+
+        /* reinitialize the control block */
+        memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+        /* unregister from SYS */
+        bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH );
+        /* notify BTA DM is now unactive */
+        bta_dm_cb.is_bta_dm_active = FALSE;
+    }
+    else
+    if( status == BTA_SYS_HW_ON_EVT )
+    {
+        /* FIXME: We should not unregister as the SYS shall invoke this callback on a H/W error.
+        * We need to revisit when this platform has more than one BLuetooth H/W chip */
+        //bta_sys_hw_unregister( BTA_SYS_HW_BLUETOOTH);
+
+        /* save security callback */
+        temp_cback = bta_dm_cb.p_sec_cback;
+        /* make sure the control block is properly initialized */
+        memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+        /* and retrieve the callback */
+        bta_dm_cb.p_sec_cback=temp_cback;
+        bta_dm_cb.is_bta_dm_active = TRUE;
+
+        /* hw is ready, go on with BTA DM initialization */
+        memset(&bta_dm_search_cb, 0x00, sizeof(bta_dm_search_cb));
+        memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+        memset(&bta_dm_di_cb, 0, sizeof(tBTA_DM_DI_CB));
+
+        memcpy(dev_class, bta_dm_cfg.dev_class, sizeof(dev_class));
+        BTM_SetDeviceClass (dev_class);
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+        /* load BLE local information: ID keys, ER if available */
+        bta_dm_co_ble_load_local_keys(&key_mask, er, &id_key);
+
+        if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ER)
+        {
+            BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ER, (tBTM_BLE_LOCAL_KEYS *)&er);
+        }
+        if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ID)
+        {
+            BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ID, (tBTM_BLE_LOCAL_KEYS *)&id_key);
+        }
+#if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+        memset (&app_uuid.uu.uuid128, 0x87, LEN_UUID_128);
+        BTA_GATTC_AppRegister(&app_uuid, bta_dm_gattc_callback);
+#endif
+#endif
+
+        BTM_SecRegister((tBTM_APPL_INFO*)&bta_security);
+        BTM_SetDefaultLinkSuperTout(bta_dm_cfg.link_timeout);
+        BTM_WritePageTimeout(bta_dm_cfg.page_timeout);
+        bta_dm_cb.cur_policy = bta_dm_cfg.policy_settings;
+        BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+        BTM_RegBusyLevelNotif (bta_dm_bl_change_cback, NULL, BTM_BL_UPDATE_MASK|BTM_BL_ROLE_CHG_MASK);
+#else
+        BTM_AclRegisterForChanges(bta_dm_acl_change_cback);
+#endif
+        /* Earlier, we used to invoke BTM_ReadLocalAddr which was just copying the bd_addr
+           from the control block and invoking the callback which was sending the DM_ENABLE_EVT.
+           But then we have a few HCI commands being invoked above which were still in progress
+           when the ENABLE_EVT was sent. So modified this to fetch the local name which forces
+           the DM_ENABLE_EVT to be sent only after all the init steps are complete */
+        BTM_ReadLocalDeviceNameFromController((tBTM_CMPL_CB *)bta_dm_local_name_cback);
+
+        bta_sys_rm_register((tBTA_SYS_CONN_CBACK*)bta_dm_rm_cback);
+
+        /* initialize bluetooth low power manager */
+        bta_dm_init_pm();
+
+        bta_sys_policy_register((tBTA_SYS_CONN_CBACK*)bta_dm_policy_cback);
+
+
+        // BLUEDROID REMOVE ??
+#if 0
+#if 1
+        /* Create broadcom primary DI record */
+        if(WBT_ExtCreateRecord())
+        {
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )
+            /* while app_ready_timer is running, BTA DM doesn't send EIR to controller */
+            bta_dm_cb.app_ready_timer.p_cback = (TIMER_CBACK*)&bta_dm_app_ready_timer_cback;
+            bta_sys_start_timer(&bta_dm_cb.app_ready_timer, 0, 100);
+
+            bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+#endif
+            bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = 0;    /* primary DI record */
+            bta_dm_di_cb.di_num ++;
+        }
+#else   /* Eventually implement pin code */
+        if (WBT_ExtCreateRecord())
+            WBT_ExtAddPinCode();
+#endif
+#endif
+    }
+    else
+        APPL_TRACE_DEBUG0(" --- ignored event");
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable
+**
+** Description      Disables the BT device manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable (tBTA_DM_MSG *p_data)
+{
+    /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
+    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0);
+
+    /* disable all active subsystems */
+    bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
+
+    BTM_SetDiscoverability(BTM_NON_DISCOVERABLE, 0, 0);
+    BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
+
+    bta_dm_disable_pm();
+
+    bta_dm_cb.disabling = TRUE;
+
+    bta_dm_search_cancel(NULL);
+
+    if(BTM_GetNumAclLinks()==0)
+    {
+#if (defined(BTA_DISABLE_DELAY) && BTA_DISABLE_DELAY > 0)
+        /* If BTA_DISABLE_DELAY is defined and greater than zero, then delay the shutdown by
+         * BTA_DISABLE_DELAY milliseconds
+         */
+        APPL_TRACE_WARNING2("%s BTA_DISABLE_DELAY set to %d ms",
+                            __FUNCTION__, BTA_DISABLE_DELAY);
+        bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, BTA_DISABLE_DELAY);
+#else
+        bta_dm_disable_conn_down_timer_cback(NULL);
+#endif
+    }
+    else
+    {
+        bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_timer_cback;
+        bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 5000);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_timer_cback
+**
+** Description      Called if the disable timer expires
+**                  Used to close ACL connections which are still active
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+    UINT8 i;
+
+    APPL_TRACE_EVENT0(" bta_dm_disable_timer_cback  ");
+
+    if(BTM_GetNumAclLinks())
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            btm_remove_acl(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+
+        }
+
+    }
+    else
+    {
+        bta_dm_cb.disabling = FALSE;
+
+        bta_sys_remove_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+        bta_dm_cb.p_sec_cback(BTA_DM_DISABLE_EVT, NULL);
+    }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_dev_name
+**
+** Description      Sets local device name
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_dev_name (tBTA_DM_MSG *p_data)
+{
+
+    BTM_SetLocalDeviceName((char*)p_data->set_name.name);
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+    bta_dm_set_eir ((char*)p_data->set_name.name);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_visibility
+**
+** Description      Sets discoverability, connectability and pairability
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_visibility (tBTA_DM_MSG *p_data)
+{
+
+
+    /* set modes for Discoverability and connectability if not ignore */
+    if (p_data->set_visibility.disc_mode != BTA_DM_IGNORE)
+        BTM_SetDiscoverability((UINT8)p_data->set_visibility.disc_mode,
+                                bta_dm_cb.inquiry_scan_window,
+                                bta_dm_cb.inquiry_scan_interval);
+
+    if (p_data->set_visibility.conn_mode != BTA_DM_IGNORE)
+        BTM_SetConnectability((UINT8)p_data->set_visibility.conn_mode,
+                                bta_dm_cb.page_scan_window,
+                                bta_dm_cb.page_scan_interval);
+
+    /* Send False or True if not ignore */
+    if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE )
+    {
+
+        if (p_data->set_visibility.pair_mode == BTA_DM_NON_PAIRABLE)
+            bta_dm_cb.disable_pair_mode = TRUE;
+        else
+            bta_dm_cb.disable_pair_mode = FALSE;
+
+    }
+
+    /* Send False or True if not ignore */
+    if (p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+    {
+
+        if (p_data->set_visibility.conn_paired_only == BTA_DM_CONN_ALL)
+            bta_dm_cb.conn_paired_only = FALSE;
+        else
+            bta_dm_cb.conn_paired_only = TRUE;
+
+    }
+
+    /* Change mode if either mode is not ignore */
+    if (p_data->set_visibility.pair_mode != BTA_DM_IGNORE || p_data->set_visibility.conn_paired_only != BTA_DM_IGNORE)
+        BTM_SetPairableMode((BOOLEAN)(!(bta_dm_cb.disable_pair_mode)),bta_dm_cb.conn_paired_only);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_afhchannels
+**
+** Description      This function sets the AFH first and
+**                  last disable channel, so channels within
+**                  that range are disabled.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_afhchannels (tBTA_DM_MSG *p_data)
+{
+    BTM_SetAfhChannels(p_data->set_afhchannels.first,p_data->set_afhchannels.last);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_vendor_spec_command
+**
+** Description      Send a vendor specific command to the controller
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_vendor_spec_command (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+
+    status = BTM_VendorSpecificCommand(p_data->vendor_command.opcode,p_data->vendor_command.param_len,p_data->vendor_command.p_param_buf, p_data->vendor_command.p_cback);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_tx_inqpower
+**
+** Description      write inquiry tx power.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_tx_inqpower(tBTA_DM_MSG *p_data)
+{
+    if (BTM_WriteInquiryTxPower (p_data->tx_inq_pwr.tx_power) == BTM_ILLEGAL_VALUE)
+    {
+        APPL_TRACE_ERROR1("Invalid Inquiry Tx Power: %d", p_data->tx_inq_pwr.tx_power);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_remove_device
+**
+** Description      Removes device, Disconnects ACL link if required.
+****
+*******************************************************************************/
+void bta_dm_remove_device (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_REMOVE_DEVICE *p_dev = &p_data->remove_dev;
+    int i;
+    tBTA_DM_SEC sec_event;
+
+    if (BTM_IsAclConnectionUp(p_dev->bd_addr))
+    {
+        /* Take the link down first, and mark the device for removal when disconnected */
+        btm_remove_acl( p_dev->bd_addr) ;
+
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_dev->bd_addr))
+            break;
+        }
+
+        if(i < bta_dm_cb.device_list.count)
+        {
+            bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_UNPAIRING;
+        }
+    }
+    else    /* Ok to remove the device in application layer */
+    {
+        BTM_SecDeleteDevice(p_dev->bd_addr);
+        if( bta_dm_cb.p_sec_cback )
+        {
+            bdcpy(sec_event.link_down.bd_addr, p_dev->bd_addr);
+            /* No connection, set status to success (acl disc code not valid) */
+            sec_event.link_down.status = HCI_SUCCESS;
+            bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &sec_event);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_device
+**
+** Description      This function adds a Link Key to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+****
+*******************************************************************************/
+void bta_dm_add_device (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_ADD_DEVICE *p_dev = &p_data->add_dev;
+    UINT8   *p_dc = NULL;
+    UINT8   *p_lc = NULL;
+    UINT32  trusted_services_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+    UINT8   index = 0;
+    UINT8   btm_mask_index = 0;
+
+    memset (trusted_services_mask, 0, sizeof(trusted_services_mask));
+
+    /* If not all zeros, the device class has been specified */
+    if (p_dev->dc_known)
+        p_dc = (UINT8 *)p_dev->dc;
+
+    if (p_dev->link_key_known)
+        p_lc = (UINT8 *)p_dev->link_key;
+
+    if (p_dev->is_trusted)
+    {
+        /* covert BTA service mask to BTM mask */
+        while (p_dev->tm && (index < BTA_MAX_SERVICE_ID))
+        {
+            if (p_dev->tm & (UINT32)(1<<index))
+            {
+
+                btm_mask_index =  bta_service_id_to_btm_srv_id_lkup_tbl[index] / BTM_SEC_ARRAY_BITS;
+                trusted_services_mask[btm_mask_index] |= (UINT32)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[index] - (UINT32)(btm_mask_index * 32)));
+
+                p_dev->tm &= (UINT32)(~(1<<index));
+
+            }
+            index++;
+        }
+    }
+
+    if (!BTM_SecAddDevice (p_dev->bd_addr, p_dc, p_dev->bd_name, p_dev->features,
+                           trusted_services_mask, p_lc, p_dev->key_type, p_dev->io_cap))
+    {
+        APPL_TRACE_ERROR2 ("BTA_DM: Error adding device %08x%04x",
+                (p_dev->bd_addr[0]<<24)+(p_dev->bd_addr[1]<<16)+(p_dev->bd_addr[2]<<8)+p_dev->bd_addr[3],
+                (p_dev->bd_addr[4]<<8)+p_dev->bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond
+**
+** Description      Bonds with peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_bond (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    tBTA_DM_SEC sec_event;
+    char        *p_name;
+
+    status = BTM_SecBond ( p_data->bond.bd_addr, 0, NULL, 0 );
+
+    if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED))
+    {
+
+        p_name = BTM_SecReadDevName(p_data->bond.bd_addr);
+        if (!p_name)
+            p_name = "";
+
+        memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+        bdcpy(sec_event.auth_cmpl.bd_addr, p_data->bond.bd_addr);
+        memcpy(sec_event.auth_cmpl.bd_name, p_name, (BD_NAME_LEN-1));
+        sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+
+/*      taken care of by memset [above]
+        sec_event.auth_cmpl.key_present = FALSE;
+        sec_event.auth_cmpl.success = FALSE;
+*/
+        sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
+        if (status == BTM_SUCCESS)
+            sec_event.auth_cmpl.success = TRUE;
+
+        bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond_cancel
+**
+** Description      Cancels bonding with a peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_bond_cancel (tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS status;
+    tBTA_DM_SEC sec_event;
+
+    APPL_TRACE_EVENT0(" bta_dm_bond_cancel ");
+    status = BTM_SecBondCancel ( p_data->bond_cancel.bd_addr );
+
+    if (bta_dm_cb.p_sec_cback && (status != BTM_CMD_STARTED && status != BTM_SUCCESS))
+    {
+        sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+        bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pin_reply
+**
+** Description      Send the pin_reply to a request from BTM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pin_reply (tBTA_DM_MSG *p_data)
+{
+    UINT32  trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+    UINT32  * current_trusted_mask;
+
+    current_trusted_mask = BTM_ReadTrustedMask(p_data->pin_reply.bd_addr);
+
+    if(current_trusted_mask)
+    {
+        memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
+    }
+    else
+    {
+        memset(trusted_mask, 0, sizeof(trusted_mask));
+    }
+
+    if(p_data->pin_reply.accept)
+    {
+
+        BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_SUCCESS, p_data->pin_reply.pin_len, p_data->pin_reply.p_pin, trusted_mask );
+    }
+    else
+    {
+        BTM_PINCodeReply(p_data->pin_reply.bd_addr, BTM_NOT_AUTHORIZED, 0, NULL, trusted_mask );
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_link_policy
+**
+** Description      remove/set link policy mask.
+**                  wake the link, is sniff/park is removed
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_link_policy (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    p_dev = bta_dm_find_peer_device(p_data->link_policy.bd_addr);
+    if(!p_dev)
+        return;
+
+    APPL_TRACE_DEBUG2(" bta_dm_link_policy set:%d, policy:0x%x",
+        p_data->link_policy.set, p_data->link_policy.policy_mask);
+    if(p_data->link_policy.set)
+    {
+        /* restore the default link policy */
+        p_dev->link_policy |= p_data->link_policy.policy_mask;
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+    }
+    else
+    {
+        /* clear the policy from the default link policy */
+        p_dev->link_policy &= (~p_data->link_policy.policy_mask);
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+
+        if(p_data->link_policy.policy_mask & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE))
+        {
+            /* if clearing sniff/park, wake the link */
+            bta_dm_pm_active(p_dev->peer_bdaddr);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_policy_cback
+**
+** Description      process the link policy changes
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_policy_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    tBTA_DM_PEER_DEVICE *p_dev = NULL;
+    UINT16  policy = app_id;
+    UINT32  mask = (UINT32)(1 << id);
+
+    if(peer_addr)
+        p_dev = bta_dm_find_peer_device(peer_addr);
+
+    APPL_TRACE_DEBUG2(" bta_dm_policy_cback cmd:%d, policy:0x%x",
+        status, policy);
+    switch(status)
+    {
+    case BTA_SYS_PLCY_SET:
+        if(!p_dev)
+            return;
+        /* restore the default link policy */
+        p_dev->link_policy |= policy;
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+        break;
+
+    case BTA_SYS_PLCY_CLR:
+        if(!p_dev)
+            return;
+        /* clear the policy from the default link policy */
+        p_dev->link_policy &= (~policy);
+        BTM_SetLinkPolicy(p_dev->peer_bdaddr, &(p_dev->link_policy));
+
+        if(policy & (HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE))
+        {
+            /* if clearing sniff/park, wake the link */
+            bta_dm_pm_active(p_dev->peer_bdaddr);
+        }
+        break;
+
+    case BTA_SYS_PLCY_DEF_SET:
+        /* want to restore/set the role switch policy */
+        bta_dm_cb.role_policy_mask &= ~mask;
+        if(0 == bta_dm_cb.role_policy_mask)
+        {
+            /* if nobody wants to insist on the role */
+            bta_dm_cb.cur_policy |= HCI_ENABLE_MASTER_SLAVE_SWITCH;
+            BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+        }
+        break;
+
+    case BTA_SYS_PLCY_DEF_CLR:
+        /* want to remove the role switch policy */
+        bta_dm_cb.role_policy_mask |= mask;
+        bta_dm_cb.cur_policy &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+        BTM_SetDefaultLinkPolicy(bta_dm_cb.cur_policy);
+        break;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_auth_reply
+**
+** Description      Send the authorization reply to a request from BTM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_auth_reply (tBTA_DM_MSG *p_data)
+{
+
+    UINT32  trusted_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
+    UINT8   btm_mask_index = 0;
+    UINT32  * current_trusted_mask;
+
+    current_trusted_mask = BTM_ReadTrustedMask(p_data->auth_reply.bd_addr);
+
+    if(current_trusted_mask)
+    {
+        memcpy(trusted_mask, current_trusted_mask, sizeof(trusted_mask));
+    }
+    else
+    {
+        memset(trusted_mask, 0, sizeof(trusted_mask));
+    }
+
+    if(p_data->auth_reply.response != BTA_DM_NOT_AUTH)
+    {
+        if(p_data->auth_reply.response == BTA_DM_AUTH_PERM)
+        {
+            if(p_data->auth_reply.service < BTA_MAX_SERVICE_ID)
+            {
+                /* convert BTA service id to BTM mask */
+                btm_mask_index =  bta_service_id_to_btm_srv_id_lkup_tbl[p_data->auth_reply.service] / 32;
+                trusted_mask[btm_mask_index] |= (UINT32)(1 << (bta_service_id_to_btm_srv_id_lkup_tbl[p_data->auth_reply.service] - (UINT32)(btm_mask_index * 32)));
+
+            }
+        }
+        BTM_DeviceAuthorized (p_data->auth_reply.bd_addr, BTM_SUCCESS,trusted_mask);
+    }
+    else
+    {
+        BTM_DeviceAuthorized (p_data->auth_reply.bd_addr, BTM_NOT_AUTHORIZED,trusted_mask);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_confirm
+**
+** Description      Send the user confirm request reply in response to a
+**                  request from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_confirm(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+    if(p_data->confirm.accept == TRUE)
+        res = BTM_SUCCESS;
+    BTM_ConfirmReqReply(res, p_data->confirm.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_passkey_cancel
+**
+** Description      Send the passkey cancel from SP initiator by sending a negative
+**                  passkey request replyreply.
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+void bta_dm_passkey_cancel(tBTA_DM_MSG *p_data)
+{
+    BTM_PasskeyReqReply(BTM_NOT_AUTHORIZED, p_data->passkey_cancel.bd_addr, 0);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_loc_oob
+**
+** Description      Retrieve the OOB data from the local LM
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_OOB_INCLUDED == TRUE)
+void bta_dm_loc_oob(tBTA_DM_MSG *p_data)
+{
+    BTM_ReadLocalOobData();
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req_act
+**
+** Description      respond to the IO capabilities request from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data)
+{
+    tBTM_AUTH_REQ   auth_req = BTM_AUTH_AP_NO;
+    if(p_data->ci_io_req.auth_req)
+        auth_req = BTM_AUTH_AP_YES;
+    BTM_IoCapRsp(p_data->ci_io_req.bd_addr, p_data->ci_io_req.io_cap,
+        p_data->ci_io_req.oob_data, auth_req);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob_act
+**
+** Description      respond to the OOB data request for the remote device from BTM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data)
+{
+    tBTM_STATUS res = BTM_NOT_AUTHORIZED;
+
+    if(p_data->ci_rmt_oob.accept == TRUE)
+        res = BTM_SUCCESS;
+    BTM_RemoteOobDataReply(res, p_data->ci_rmt_oob.bd_addr,
+        p_data->ci_rmt_oob.c, p_data->ci_rmt_oob.r );
+}
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_start
+**
+** Description      Starts an inquiry
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_start (tBTA_DM_MSG *p_data)
+{
+    tBTM_INQUIRY_CMPL result;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->search.num_uuid);
+#endif
+
+    APPL_TRACE_DEBUG1("bta_dm_search_start avoid_scatter=%d", bta_dm_cfg.avoid_scatter);
+    if (bta_dm_cfg.avoid_scatter &&
+        (p_data->search.rs_res == BTA_DM_RS_NONE) && bta_dm_check_av(BTA_DM_API_SEARCH_EVT))
+    {
+        memcpy(&bta_dm_cb.search_msg, &p_data->search, sizeof(tBTA_DM_API_SEARCH));
+        return;
+    }
+
+    BTM_ClearInqDb(NULL);
+    /* save search params */
+    bta_dm_search_cb.p_search_cback = p_data->search.p_cback;
+    bta_dm_search_cb.services = p_data->search.services;
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+
+    if ((bta_dm_search_cb.num_uuid = p_data->search.num_uuid) != 0 &&
+         p_data->search.p_uuid != NULL)
+    {
+        if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+        {
+            APPL_TRACE_ERROR0("bta_dm_search_start no resources");
+
+            result.status = BTA_FAILURE;
+            result.num_resp = 0;
+            bta_dm_inq_cmpl_cb ((void *)&result);
+            return;
+        }
+//        bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len);
+        memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->search.p_uuid, len);
+    }
+
+    if (p_data->search.inq_params.mode & BTM_LIMITED_INQUIRY)
+        p_data->search.inq_params.mode |= BTM_BLE_LIMITED_INQUIRY;
+    else
+        p_data->search.inq_params.mode |= BTM_BLE_GENERAL_INQUIRY;
+#endif
+    result.status = BTM_StartInquiry(   (tBTM_INQ_PARMS*)&p_data->search.inq_params,
+                        bta_dm_inq_results_cb,
+                        (tBTM_CMPL_CB*) bta_dm_inq_cmpl_cb);
+
+    APPL_TRACE_EVENT1("bta_dm_search_start status=%d", result.status);
+    if (result.status != BTM_CMD_STARTED)
+    {
+        result.num_resp = 0;
+        bta_dm_inq_cmpl_cb ((void *)&result);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel
+**
+** Description      Cancels an ongoing search for devices
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel (tBTA_DM_MSG *p_data)
+{
+
+    tBTA_DM_MSG * p_msg;
+
+    if(BTM_IsInquiryActive())
+    {
+        BTM_CancelInquiry();
+        bta_dm_search_cancel_notify(NULL);
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+
+        }
+    }
+    /* If no Service Search going on then issue cancel remote name in case it is active */
+    else if (!bta_dm_search_cb.name_discover_done)
+    {
+        BTM_CancelRemoteDeviceName();
+    }
+#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    if (bta_dm_search_cb.gatt_disc_active)
+    {
+        bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover
+**
+** Description      Discovers services on a remote device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_discover (tBTA_DM_MSG *p_data)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT16 len = (UINT16)(sizeof(tBT_UUID) * p_data->discover.num_uuid);
+#endif
+    APPL_TRACE_EVENT2("bta_dm_discover services_to_search=0x%04X, sdp_search=%d",
+                      p_data->discover.services, p_data->discover.sdp_search);
+
+    /* save the search condition */
+    bta_dm_search_cb.services = p_data->discover.services;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+    if ((bta_dm_search_cb.num_uuid = p_data->discover.num_uuid) != 0 &&
+        p_data->discover.p_uuid != NULL)
+    {
+        if ((bta_dm_search_cb.p_srvc_uuid = (tBT_UUID *)GKI_getbuf(len)) == NULL)
+        {
+            p_data->discover.p_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+            return;
+        }
+        memcpy(bta_dm_search_cb.p_srvc_uuid, p_data->discover.p_uuid, len);
+    }
+    bta_dm_search_cb.uuid_to_search = bta_dm_search_cb.num_uuid;
+#endif
+
+    bta_dm_search_cb.p_search_cback = p_data->discover.p_cback;
+    bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+    bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+    bta_dm_search_cb.service_index = 0;
+    bta_dm_search_cb.services_found = 0;
+    bta_dm_search_cb.peer_name[0] = 0;
+    bta_dm_search_cb.sdp_search = p_data->discover.sdp_search;
+    bta_dm_search_cb.p_btm_inq_info = BTM_InqDbRead (p_data->discover.bd_addr);
+
+    bta_dm_search_cb.name_discover_done = FALSE;
+    memcpy(&bta_dm_search_cb.uuid, &p_data->discover.uuid, sizeof(tSDP_UUID));
+    bta_dm_discover_device(p_data->discover.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc_cmpl
+**
+** Description      Sends event to application when DI discovery complete
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_di_disc_cmpl(tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_DI_DISC_CMPL    di_disc;
+
+    memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+    bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+
+    if((p_data->hdr.offset == SDP_SUCCESS)
+        || (p_data->hdr.offset == SDP_DB_FULL))
+    {
+        di_disc.num_record  = SDP_GetNumDiRecords(bta_dm_di_cb.p_di_db);
+    }
+    else
+        di_disc.result      = BTA_FAILURE;
+
+    bta_dm_di_cb.p_di_db = NULL;
+    bta_dm_search_cb.p_search_cback(BTA_DM_DI_DISC_CMPL_EVT, (tBTA_DM_SEARCH *) &di_disc);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc_callback
+**
+** Description      This function queries a remote device for DI information.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_di_disc_callback(UINT16 result)
+{
+    tBTA_DM_MSG * p_msg;
+
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event            = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific   = BTA_DM_API_DI_DISCOVER_EVT;
+        p_msg->hdr.offset           = result;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_di_disc
+**
+** Description      This function queries a remote device for DI information.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_di_disc (tBTA_DM_MSG *p_data)
+{
+    UINT16  result = BTA_FAILURE;
+    tBTA_DM_MSG *p_msg;
+
+    bta_dm_search_cb.p_search_cback = p_data->di_disc.p_cback;
+    bdcpy(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.bd_addr);
+    bta_dm_di_cb.p_di_db = p_data->di_disc.p_sdp_db;
+
+    if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+    {
+        if ( SDP_DiDiscover(bta_dm_search_cb.peer_bdaddr, p_data->di_disc.p_sdp_db,
+                    p_data->di_disc.len, bta_dm_di_disc_callback) == SDP_SUCCESS)
+        {
+            result = BTA_SUCCESS;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("No buffer to start DI discovery");
+    }
+
+    if ( result == BTA_FAILURE &&
+        (p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event            = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific   = BTA_DM_API_DI_DISCOVER_EVT;
+        p_data->hdr.offset          = result;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_read_remote_device_name
+**
+** Description      Initiate to get remote device name
+**
+** Returns          TRUE if started to get remote name
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_read_remote_device_name (BD_ADDR bd_addr)
+{
+    tBTM_STATUS  btm_status;
+
+    APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name");
+
+    bdcpy(bta_dm_search_cb.peer_bdaddr, bd_addr);
+    bta_dm_search_cb.peer_name[0] = 0;
+
+    btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+                                           (tBTM_CMPL_CB *) bta_dm_remname_cback);
+
+    if ( btm_status == BTM_CMD_STARTED )
+    {
+        APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is started");
+
+        return (TRUE);
+    }
+    else if ( btm_status == BTM_BUSY )
+    {
+        APPL_TRACE_DEBUG0("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName is busy");
+
+        /* Remote name discovery is on going now so BTM cannot notify through "bta_dm_remname_cback" */
+        /* adding callback to get notified that current reading remore name done */
+        BTM_SecAddRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+        return (TRUE);
+    }
+    else
+    {
+        APPL_TRACE_WARNING1("bta_dm_read_remote_device_name: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+        return (FALSE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_cmpl
+**
+** Description      Process the inquiry complete event from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_MSG * p_msg;
+    tBTA_DM_SEARCH  data;
+
+    APPL_TRACE_DEBUG0("bta_dm_inq_cmpl");
+
+    data.inq_cmpl.num_resps = p_data->inq_cmpl.num;
+    bta_dm_search_cb.p_search_cback(BTA_DM_INQ_CMPL_EVT, &data);
+
+    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbFirst()) != NULL)
+    {
+        /* start name and service discovery from the first device on inquiry result */
+        bta_dm_search_cb.name_discover_done = FALSE;
+        bta_dm_search_cb.peer_name[0]       = 0;
+        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+    }
+    else
+    {
+        /* no devices, search complete */
+        bta_dm_search_cb.services = 0;
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+        }
+    }
+
+/*******************************************************************************
+**
+** Function         bta_dm_rmt_name
+**
+** Description      Process the remote name result from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_rmt_name (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG0("bta_dm_rmt_name");
+
+    if( p_data->rem_name.result.disc_res.bd_name[0] && bta_dm_search_cb.p_btm_inq_info)
+    {
+        bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name = TRUE;
+    }
+
+    bta_dm_discover_device(bta_dm_search_cb.peer_bdaddr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disc_rmt_name
+**
+** Description      Process the remote name result from BTM when application
+**                  wants to find the name for a bdaddr
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data)
+{
+    tBTM_INQ_INFO *p_btm_inq_info;
+
+    APPL_TRACE_DEBUG0("bta_dm_disc_rmt_name");
+
+    p_btm_inq_info = BTM_InqDbRead (p_data->rem_name.result.disc_res.bd_addr);
+    if( p_btm_inq_info )
+    {
+        if( p_data->rem_name.result.disc_res.bd_name[0] )
+        {
+            p_btm_inq_info->appl_knows_rem_name = TRUE;
+        }
+    }
+
+    bta_dm_discover_device(p_data->rem_name.result.disc_res.bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sdp_result
+**
+** Description      Process the discovery result from sdp
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sdp_result (tBTA_DM_MSG *p_data)
+{
+
+    tSDP_DISC_REC   *p_sdp_rec = NULL;
+    tBTA_DM_MSG     *p_msg;
+    BOOLEAN          service_found = FALSE;
+    BOOLEAN          scn_found = FALSE;
+    UINT16           service = 0xFFFF;
+    tSDP_PROTOCOL_ELEM  pe;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBT_UUID           *p_uuid = bta_dm_search_cb.p_srvc_uuid;
+    tBTA_DM_SEARCH      result;
+    tBT_UUID            service_uuid;
+#endif
+
+    UINT32 num_uuids = 0;
+    UINT8  uuid_list[32][MAX_UUID_SIZE]; // assuming a max of 32 services
+
+    if((p_data->sdp_event.sdp_result == SDP_SUCCESS)
+        || (p_data->sdp_event.sdp_result == SDP_NO_RECS_MATCH)
+        || (p_data->sdp_event.sdp_result == SDP_DB_FULL))
+    {
+        APPL_TRACE_DEBUG1("sdp_result::0x%x", p_data->sdp_event.sdp_result);
+        do
+        {
+
+            service_found = FALSE;
+            p_sdp_rec = NULL;
+            if( bta_dm_search_cb.service_index == (BTA_USER_SERVICE_ID+1) )
+            {
+                p_sdp_rec = SDP_FindServiceUUIDInDb(bta_dm_search_cb.p_sdp_db, &bta_dm_search_cb.uuid, p_sdp_rec);
+
+                if (p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
+                {
+                    bta_dm_search_cb.peer_scn = (UINT8) pe.params[0];
+                    scn_found = TRUE;
+                }
+            }
+            else
+            {
+                service = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+                p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db, service, p_sdp_rec);
+            }
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+            /* finished with BR/EDR services, now we check the result for GATT based service UUID */
+            if (bta_dm_search_cb.service_index == BTA_MAX_SERVICE_ID)
+            {
+                if (bta_dm_search_cb.uuid_to_search != 0 && p_uuid != NULL)
+                {
+                    p_uuid +=  (bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search);
+                    /* only support 16 bits UUID for now */
+                    service = p_uuid->uu.uuid16;
+
+                }
+                /* all GATT based services */
+                do
+                {
+                    /* find a service record, report it */
+                    p_sdp_rec = SDP_FindServiceInDb(bta_dm_search_cb.p_sdp_db,
+                                                0, p_sdp_rec);
+                    if (p_sdp_rec)
+                    {
+                        if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+                        {
+                            /* send result back to app now, one by one */
+                            bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+                            BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+                            result.disc_ble_res.service.len = service_uuid.len;
+                            result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
+
+                            bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+                        }
+                    }
+
+                    if (bta_dm_search_cb.uuid_to_search > 0)
+                        break;
+
+                } while (p_sdp_rec);
+            }
+            else
+#endif
+            {
+            /* SDP_DB_FULL means some records with the
+               required attributes were received */
+            if(((p_data->sdp_event.sdp_result == SDP_DB_FULL) &&
+                    bta_dm_search_cb.services != BTA_ALL_SERVICE_MASK) ||
+                    (p_sdp_rec  != NULL))
+            {
+                /* If Plug and Play service record, check to see if Broadcom stack */
+                if (service == UUID_SERVCLASS_PNP_INFORMATION)
+                {
+                    if (p_sdp_rec)
+                    {
+                        if (SDP_FindAttributeInRec (p_sdp_rec, ATTR_ID_EXT_BRCM_VERSION))
+                        {
+                            service_found = TRUE;
+                        }
+                    }
+                }
+                else
+                {
+                    service_found = TRUE;
+                }
+
+                if (service_found)
+                {
+                    UINT16 tmp_svc = 0xFFFF;
+                    bta_dm_search_cb.services_found |=
+                        (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index-1));
+                    tmp_svc = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index-1];
+                    /* Add to the list of UUIDs */
+                    sdpu_uuid16_to_uuid128(tmp_svc, uuid_list[num_uuids]);
+                    num_uuids++;
+                }
+            }
+            }
+
+            if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK &&
+                bta_dm_search_cb.services_to_search == 0)
+            {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                if ( bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+                    bta_dm_search_cb.uuid_to_search > 0)
+                    bta_dm_search_cb.uuid_to_search --;
+
+                if (bta_dm_search_cb.uuid_to_search == 0 ||
+                    bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+                    bta_dm_search_cb.service_index++;
+            }
+            else /* regular one service per search or PNP search */
+                break;
+
+        }
+        while(bta_dm_search_cb.service_index <= BTA_MAX_SERVICE_ID);
+
+//        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+//        bta_dm_search_cb.p_sdp_db = NULL;
+        APPL_TRACE_DEBUG1("bta_dm_sdp_result services_found = %04x", bta_dm_search_cb.services_found);
+
+        /* Collect the 128-bit services here and put them into the list */
+        if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK)
+        {
+            p_sdp_rec = NULL;
+            do
+            {
+                tBT_UUID temp_uuid;
+                /* find a service record, report it */
+                p_sdp_rec = SDP_FindServiceInDb_128bit(bta_dm_search_cb.p_sdp_db, p_sdp_rec);
+                if (p_sdp_rec)
+                {
+                    if (SDP_FindServiceUUIDInRec_128bit(p_sdp_rec, &temp_uuid))
+                    {
+                        memcpy(uuid_list[num_uuids], temp_uuid.uu.uuid128, MAX_UUID_SIZE);
+                        num_uuids++;
+                    }
+                }
+            } while (p_sdp_rec);
+        }
+        /* if there are more services to search for */
+        if(bta_dm_search_cb.services_to_search)
+        {
+            /* Free up the p_sdp_db before checking the next one */
+            bta_dm_free_sdp_db(NULL);
+            bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+        }
+        else
+        {
+            /* callbacks */
+            /* start next bd_addr if necessary */
+
+            BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+
+            if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+            {
+                p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+                p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+                p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+                p_msg->disc_result.result.disc_res.raw_data_size = 0;
+                p_msg->disc_result.result.disc_res.num_uuids = num_uuids;
+                p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
+                if (num_uuids > 0) {
+                    p_msg->disc_result.result.disc_res.p_uuid_list = (UINT8*)GKI_getbuf(num_uuids*MAX_UUID_SIZE);
+                    if (p_msg->disc_result.result.disc_res.p_uuid_list) {
+                        memcpy(p_msg->disc_result.result.disc_res.p_uuid_list, uuid_list,
+                               num_uuids*MAX_UUID_SIZE);
+                    } else {
+                       p_msg->disc_result.result.disc_res.num_uuids = 0;
+                       APPL_TRACE_ERROR1("%s: Unable to allocate memory for uuid_list", __FUNCTION__);
+                    }
+                }
+                //copy the raw_data to the discovery result  structure
+                //
+                APPL_TRACE_DEBUG2("bta_dm_sdp_result (raw_data used = 0x%x raw_data_ptr = 0x%x)\r\n",bta_dm_search_cb.p_sdp_db->raw_used, bta_dm_search_cb.p_sdp_db->raw_data);
+
+                if (  bta_dm_search_cb.p_sdp_db != NULL && bta_dm_search_cb.p_sdp_db->raw_used != 0   &&
+                    bta_dm_search_cb.p_sdp_db->raw_data != NULL) {
+
+                    p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.p_sdp_db->raw_used);
+                    if ( NULL != p_msg->disc_result.result.disc_res.p_raw_data  ) {
+                        memcpy(     p_msg->disc_result.result.disc_res.p_raw_data,
+                                    bta_dm_search_cb.p_sdp_db->raw_data,
+                                    bta_dm_search_cb.p_sdp_db->raw_used );
+
+                        p_msg->disc_result.result.disc_res.raw_data_size =
+                            bta_dm_search_cb.p_sdp_db->raw_used;
+
+                    } else {
+                        APPL_TRACE_DEBUG1("bta_dm_sdp_result GKI Alloc failed to allocate %d bytes !!\r\n",bta_dm_search_cb.p_sdp_db->raw_used);
+                    }
+
+                    bta_dm_search_cb.p_sdp_db->raw_data = NULL;     //no need to free this - it is a global assigned.
+                    bta_dm_search_cb.p_sdp_db->raw_used = 0;
+                    bta_dm_search_cb.p_sdp_db->raw_size = 0;
+                }
+                else {
+                    APPL_TRACE_DEBUG0("bta_dm_sdp_result raw data size is 0 or raw_data is null!!\r\n");
+                }
+                /* Done with p_sdp_db. Free it */
+                bta_dm_free_sdp_db(NULL);
+                p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+
+                //Piggy back the SCN over result field
+                if( scn_found )
+                {
+                  p_msg->disc_result.result.disc_res.result = (3 + bta_dm_search_cb.peer_scn);
+                  p_msg->disc_result.result.disc_res.services |= BTA_USER_SERVICE_MASK;
+
+                  APPL_TRACE_EVENT1(" Piggy back the SCN over result field  SCN=%d", bta_dm_search_cb.peer_scn);
+
+                }
+                bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+                BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                        bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+                /* make sure the string is null terminated */
+                p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+                bta_sys_sendmsg(p_msg);
+            }
+
+        }
+
+    }
+    else
+    {
+        /* conn failed. No need for timer */
+        if(p_data->sdp_event.sdp_result == SDP_CONN_FAILED || p_data->sdp_event.sdp_result == SDP_CONN_REJECTED
+           || p_data->sdp_event.sdp_result == SDP_SECURITY_ERR)
+            bta_dm_search_cb.wait_disc = FALSE;
+
+        /* not able to connect go to next device */
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+
+        BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.result = BTA_FAILURE;
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is null terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cmpl
+**
+** Description      Sends event to application
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cmpl (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG0("bta_dm_search_cmpl");
+
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+    utl_freebuf((void **)&bta_dm_search_cb.p_srvc_uuid);
+#endif
+
+    if (p_data->hdr.layer_specific == BTA_DM_API_DI_DISCOVER_EVT)
+        bta_dm_di_disc_cmpl(p_data);
+    else
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_CMPL_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disc_result
+**
+** Description      Service discovery result when discovering services on a device
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disc_result (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_MSG *      p_msg;
+
+    APPL_TRACE_DEBUG0("bta_dm_disc_result");
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    /* if any BR/EDR service discovery has been done, report the event */
+    if ((bta_dm_search_cb.services & ((BTA_ALL_SERVICE_MASK | BTA_USER_SERVICE_MASK ) & ~BTA_BLE_SERVICE_MASK)))
+#endif
+    bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+
+    /* send a message to change state */
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_SEARCH_CMPL_EVT;
+        p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_result
+**
+** Description      Service discovery result while searching for devices
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_result (tBTA_DM_MSG *p_data)
+{
+    APPL_TRACE_DEBUG2("bta_dm_search_result searching:0x%04x, result:0x%04x",
+                       bta_dm_search_cb.services,
+                       p_data->disc_result.result.disc_res.services);
+
+    /* call back if application wants name discovery or found services that application is searching */
+    if (( !bta_dm_search_cb.services )
+      ||(( bta_dm_search_cb.services ) && ( p_data->disc_result.result.disc_res.services )))
+    {
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_RES_EVT, &p_data->disc_result.result);
+    }
+
+    /* if searching did not initiate to create link */
+    if(!bta_dm_search_cb.wait_disc )
+    {
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+        /* if service searching is done with EIR, don't search next device */
+        if( bta_dm_search_cb.p_btm_inq_info )
+#endif
+        bta_dm_discover_next_device();
+    }
+    else
+    {
+        /* wait until link is disconnected or timeout */
+        bta_dm_search_cb.sdp_results = TRUE;
+        bta_dm_search_cb.search_timer.p_cback = (TIMER_CBACK*)&bta_dm_search_timer_cback;
+        bta_sys_start_timer(&bta_dm_search_cb.search_timer, 0, 1000*(L2CAP_LINK_INACTIVITY_TOUT+1) );
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_timer_cback
+**
+** Description      Called when ACL disconnect time is over
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_search_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+    APPL_TRACE_EVENT0(" bta_dm_search_timer_cback  ");
+    bta_dm_search_cb.wait_disc = FALSE;
+
+    /* proceed with next device */
+    bta_dm_discover_next_device();
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_free_sdp_db
+**
+** Description      Frees SDP data base
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data)
+{
+    if(bta_dm_search_cb.p_sdp_db)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_queue_search
+**
+** Description      Queues search command while search is being cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_queue_search (tBTA_DM_MSG *p_data)
+{
+
+    bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_SEARCH));
+    memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_SEARCH));
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_queue_disc
+**
+** Description      Queues discovery command while search is being cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_queue_disc (tBTA_DM_MSG *p_data)
+{
+
+    bta_dm_search_cb.p_search_queue = (tBTA_DM_MSG *)GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER));
+    memcpy(bta_dm_search_cb.p_search_queue, p_data, sizeof(tBTA_DM_API_DISCOVER));
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_clear_queue
+**
+** Description      Clears the queue if API search cancel is called
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data)
+{
+
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_search_queue);
+        bta_dm_search_cb.p_search_queue = NULL;
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_cmpl
+**
+** Description      Search cancel is complete
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data)
+{
+
+    if(bta_dm_search_cb.p_search_queue)
+    {
+        bta_sys_sendmsg(bta_dm_search_cb.p_search_queue);
+        bta_dm_search_cb.p_search_queue = NULL;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_transac_cmpl
+**
+** Description      Current Service Discovery or remote name procedure is
+**                  completed after search cancellation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data)
+{
+
+    if(bta_dm_search_cb.p_sdp_db)
+    {
+        GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+        bta_dm_search_cb.p_sdp_db = NULL;
+    }
+
+    bta_dm_search_cancel_notify(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_cancel_notify
+**
+** Description      Notify application that search has been cancelled
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data)
+{
+    if (bta_dm_search_cb.p_search_cback)
+    {
+        bta_dm_search_cb.p_search_cback(BTA_DM_SEARCH_CANCEL_CMPL_EVT, NULL);
+    }
+    if (!bta_dm_search_cb.name_discover_done)
+    {
+        BTM_CancelRemoteDeviceName();
+    }
+#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    if (bta_dm_search_cb.gatt_disc_active)
+    {
+        bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+    }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_find_services
+**
+** Description      Starts discovery on a device
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_find_services ( BD_ADDR bd_addr)
+{
+
+    tSDP_UUID    uuid;
+    UINT16       attr_list[] = {ATTR_ID_SERVICE_CLASS_ID_LIST, ATTR_ID_EXT_BRCM_VERSION};
+    UINT16       num_attrs = 1;
+    tBTA_DM_MSG *p_msg;
+
+    memset (&uuid, 0, sizeof(tSDP_UUID));
+
+    while(bta_dm_search_cb.service_index < BTA_MAX_SERVICE_ID)
+    {
+        if( bta_dm_search_cb.services_to_search
+            & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)))
+        {
+            if((bta_dm_search_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_DM_SDP_DB_SIZE)) != NULL)
+            {
+                APPL_TRACE_DEBUG1("bta_dm_search_cb.services = %04x***********", bta_dm_search_cb.services);
+                /* try to search all services by search based on L2CAP UUID */
+                if(bta_dm_search_cb.services == BTA_ALL_SERVICE_MASK )
+                {
+                    APPL_TRACE_ERROR1("services_to_search = %08x",bta_dm_search_cb.services_to_search);
+                    if (bta_dm_search_cb.services_to_search & BTA_RES_SERVICE_MASK)
+                    {
+                        uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[0];
+                        bta_dm_search_cb.services_to_search &= ~BTA_RES_SERVICE_MASK;
+                    }
+                    else
+                    {
+                        uuid.uu.uuid16 = UUID_PROTOCOL_L2CAP;
+                        bta_dm_search_cb.services_to_search = 0;
+                    }
+                }
+                else
+                {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                    /* for LE only profile */
+                    if (bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID)
+                    {
+                        if (bta_dm_search_cb.uuid_to_search > 0 && bta_dm_search_cb.p_srvc_uuid)
+                        {
+                            memcpy(&uuid,
+                                   (const void *)(bta_dm_search_cb.p_srvc_uuid + \
+                                                  bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search),
+                                   sizeof(tBT_UUID));
+
+                            bta_dm_search_cb.uuid_to_search -- ;
+                        }
+                        else
+                            uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+
+                        /* last one? clear the BLE service bit if all discovery has been done */
+                        if (bta_dm_search_cb.uuid_to_search == 0)
+                            bta_dm_search_cb.services_to_search &=
+                            (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+
+                    }
+                    else
+#endif
+                    {
+                        /* remove the service from services to be searched  */
+                        bta_dm_search_cb.services_to_search &=
+                        (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(bta_dm_search_cb.service_index)));
+                        uuid.uu.uuid16 = bta_service_id_to_uuid_lkup_tbl[bta_dm_search_cb.service_index];
+                    }
+                }
+
+                if (uuid.len == 0)
+                uuid.len = LEN_UUID_16;
+
+#if 0
+                if (uuid.uu.uuid16 == UUID_SERVCLASS_PNP_INFORMATION)
+                {
+                    num_attrs = 2;
+                }
+#endif
+
+                if (bta_dm_search_cb.service_index == BTA_USER_SERVICE_ID)
+                {
+                    memcpy(&uuid, &bta_dm_search_cb.uuid, sizeof(tSDP_UUID));
+                }
+
+
+                APPL_TRACE_ERROR1("****************search UUID = %04x***********", uuid.uu.uuid16);
+                //SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list);
+                SDP_InitDiscoveryDb (bta_dm_search_cb.p_sdp_db, BTA_DM_SDP_DB_SIZE, 1, &uuid, 0, NULL);
+
+
+                memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+                bta_dm_search_cb.p_sdp_db->raw_data = g_disc_raw_data_buf;
+
+                bta_dm_search_cb.p_sdp_db->raw_size = MAX_DISC_RAW_DATA_BUF;
+
+                if (!SDP_ServiceSearchAttributeRequest (bd_addr, bta_dm_search_cb.p_sdp_db, &bta_dm_sdp_callback))
+                {
+                    /* if discovery not successful with this device
+                    proceed to next one */
+                    GKI_freebuf(bta_dm_search_cb.p_sdp_db);
+                    bta_dm_search_cb.p_sdp_db = NULL;
+                    bta_dm_search_cb.service_index = BTA_MAX_SERVICE_ID;
+
+                }
+                else
+                {
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+                    if ((bta_dm_search_cb.service_index == BTA_BLE_SERVICE_ID &&
+                         bta_dm_search_cb.uuid_to_search == 0) ||
+                         bta_dm_search_cb.service_index != BTA_BLE_SERVICE_ID)
+#endif
+                    bta_dm_search_cb.service_index++;
+                    return;
+                }
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("#### Failed to allocate SDP DB buffer! ####");
+            }
+        }
+
+        bta_dm_search_cb.service_index++;
+    }
+
+    /* no more services to be discovered */
+    if(bta_dm_search_cb.service_index >= BTA_MAX_SERVICE_ID)
+    {
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover_next_device
+**
+** Description      Starts discovery on the next device in Inquiry data base
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_discover_next_device(void)
+{
+
+    tBTA_DM_MSG * p_msg;
+
+    APPL_TRACE_DEBUG0("bta_dm_discover_next_device");
+
+    /* searching next device on inquiry result */
+    if((bta_dm_search_cb.p_btm_inq_info = BTM_InqDbNext(bta_dm_search_cb.p_btm_inq_info)) != NULL)
+    {
+        bta_dm_search_cb.name_discover_done = FALSE;
+        bta_dm_search_cb.peer_name[0]       = 0;
+        bta_dm_discover_device(bta_dm_search_cb.p_btm_inq_info->results.remote_bd_addr);
+    }
+    else
+    {
+        /* no devices, search complete */
+        bta_dm_search_cb.services = 0;
+
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event          = BTA_DM_SEARCH_CMPL_EVT;
+            p_msg->hdr.layer_specific = BTA_DM_API_DISCOVER_EVT;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_discover_device
+**
+** Description      Starts name and service discovery on the device
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_discover_device(BD_ADDR remote_bd_addr)
+{
+    tBTA_DM_MSG * p_msg;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBT_DEVICE_TYPE dev_type;
+    tBLE_ADDR_TYPE  addr_type;
+#endif
+
+    APPL_TRACE_DEBUG6("bta_dm_discover_device, BDA:0x%02X%02X%02X%02X%02X%02X",
+                        remote_bd_addr[0],remote_bd_addr[1],
+                        remote_bd_addr[2],remote_bd_addr[3],
+                        remote_bd_addr[4],remote_bd_addr[5]);
+
+    bdcpy(bta_dm_search_cb.peer_bdaddr, remote_bd_addr);
+
+    APPL_TRACE_DEBUG2("bta_dm_discover_device name_discover_done = %d p_btm_inq_info 0x%x ",
+                        bta_dm_search_cb.name_discover_done,
+                        bta_dm_search_cb.p_btm_inq_info
+                        );
+    if ( bta_dm_search_cb.p_btm_inq_info ) {
+
+        APPL_TRACE_DEBUG1("bta_dm_discover_device appl_knows_rem_name %d",
+                            bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name
+                            );
+    }
+
+    /* if name discovery is not done and application needs remote name */
+    if ((!bta_dm_search_cb.name_discover_done)
+       && (( bta_dm_search_cb.p_btm_inq_info == NULL )
+            ||(bta_dm_search_cb.p_btm_inq_info && (!bta_dm_search_cb.p_btm_inq_info->appl_knows_rem_name))))
+    {
+        if( bta_dm_read_remote_device_name(bta_dm_search_cb.peer_bdaddr) == TRUE )
+        {
+            return;
+        }
+        else
+        {
+            /* starting name discovery failed */
+            bta_dm_search_cb.name_discover_done = TRUE;
+        }
+    }
+
+    /* if application wants to discover service */
+    if ( bta_dm_search_cb.services )
+    {
+        /* initialize variables */
+        bta_dm_search_cb.service_index      = 0;
+        bta_dm_search_cb.services_found     = 0;
+        bta_dm_search_cb.services_to_search = bta_dm_search_cb.services;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+        bta_dm_search_cb.uuid_to_search     = bta_dm_search_cb.num_uuid;
+#endif
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+        if ((bta_dm_search_cb.p_btm_inq_info != NULL) &&
+			bta_dm_search_cb.services != BTA_USER_SERVICE_MASK
+            &&(bta_dm_search_cb.sdp_search == FALSE))
+        {
+            /* check if EIR provides the information of supported services */
+            bta_dm_eir_search_services( &bta_dm_search_cb.p_btm_inq_info->results,
+                                        &bta_dm_search_cb.services_to_search,
+                                        &bta_dm_search_cb.services_found );
+        }
+
+        /* if seaching with EIR is not completed */
+        if(bta_dm_search_cb.services_to_search)
+#endif
+        {
+            /* check whether connection already exists to the device
+               if connection exists, we don't have to wait for ACL
+               link to go down to start search on next device */
+            if(BTM_IsAclConnectionUp(bta_dm_search_cb.peer_bdaddr))
+                bta_dm_search_cb.wait_disc = FALSE;
+            else
+                bta_dm_search_cb.wait_disc = TRUE;
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+            if ( bta_dm_search_cb.p_btm_inq_info )
+            {
+                APPL_TRACE_DEBUG3("bta_dm_discover_device p_btm_inq_info 0x%x results.device_type 0x%x services_to_search 0x%x",
+                                    bta_dm_search_cb.p_btm_inq_info,
+                                    bta_dm_search_cb.p_btm_inq_info->results.device_type,
+                                    bta_dm_search_cb.services_to_search
+                                    );
+            }
+            BTM_ReadDevInfo(remote_bd_addr, &dev_type, &addr_type);
+
+            if (dev_type == BT_DEVICE_TYPE_BLE)
+            /*
+            if ( bta_dm_search_cb.p_btm_inq_info != NULL &&
+                 bta_dm_search_cb.p_btm_inq_info->results.device_type == BT_DEVICE_TYPE_BLE &&
+                 (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK))*/
+            {
+                if (bta_dm_search_cb.services_to_search & BTA_BLE_SERVICE_MASK)
+                {
+                    //set the raw data buffer here
+                    memset(g_disc_raw_data_buf, 0, sizeof(g_disc_raw_data_buf));
+                    bta_dm_search_cb.p_ble_rawdata = g_disc_raw_data_buf;
+
+                    bta_dm_search_cb.ble_raw_size = MAX_DISC_RAW_DATA_BUF;
+                    bta_dm_search_cb.ble_raw_used = 0;
+
+                    /* start GATT for service discovery */
+                    btm_dm_start_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
+                    return;
+                }
+            }
+            else
+#endif
+            {
+            bta_dm_search_cb.sdp_results = FALSE;
+            bta_dm_find_services(bta_dm_search_cb.peer_bdaddr);
+
+            return;
+            }
+        }
+    }
+
+    /* name discovery and service discovery are done for this device */
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+        /* initialize the data structure - includes p_raw_data and raw_data_size */
+        memset(&(p_msg->disc_result.result), 0, sizeof(tBTA_DM_DISC_RES));
+        p_msg->disc_result.result.disc_res.result = BTA_SUCCESS;
+        p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+        bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name,  sizeof(BD_NAME),
+                      (char*)bta_dm_search_cb.peer_name, (BD_NAME_LEN-1));
+
+        /* make sure the string is terminated */
+        p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sdp_callback
+**
+** Description      Callback from sdp with discovery status
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_sdp_callback (UINT16 sdp_status)
+{
+
+    tBTA_DM_SDP_RESULT * p_msg;
+
+    if ((p_msg = (tBTA_DM_SDP_RESULT *) GKI_getbuf(sizeof(tBTA_DM_SDP_RESULT))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_SDP_RESULT_EVT;
+        p_msg->sdp_result = sdp_status;
+        bta_sys_sendmsg(p_msg);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_results_cb
+**
+** Description      Inquiry results callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_inq_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+
+    tBTA_DM_SEARCH     result;
+    tBTM_INQ_INFO      *p_inq_info;
+    UINT16             service_class;
+
+    bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+    memcpy(result.inq_res.dev_class, p_inq->dev_class, DEV_CLASS_LEN);
+    BTM_COD_SERVICE_CLASS(service_class, p_inq->dev_class);
+    result.inq_res.is_limited = (service_class & BTM_COD_SERVICE_LMTD_DISCOVER)?TRUE:FALSE;
+    result.inq_res.rssi = p_inq->rssi;
+
+#if (BLE_INCLUDED == TRUE)
+    result.inq_res.ble_addr_type    = p_inq->ble_addr_type;
+    result.inq_res.inq_result_type  = p_inq->inq_result_type;
+    result.inq_res.device_type      = p_inq->device_type;
+
+#endif
+
+    /* application will parse EIR to find out remote device name */
+    result.inq_res.p_eir = p_eir;
+
+    if((p_inq_info = BTM_InqDbRead(p_inq->remote_bd_addr)) != NULL)
+    {
+        /* initialize remt_name_not_required to FALSE so that we get the name by default */
+        result.inq_res.remt_name_not_required = FALSE;
+
+    }
+
+    if(bta_dm_search_cb.p_search_cback)
+        bta_dm_search_cb.p_search_cback(BTA_DM_INQ_RES_EVT, &result);
+
+    if(p_inq_info)
+    {
+        /* application indicates if it knows the remote name, inside the callback
+         copy that to the inquiry data base*/
+        if(result.inq_res.remt_name_not_required)
+            p_inq_info->appl_knows_rem_name = TRUE;
+
+    }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_inq_cmpl_cb
+**
+** Description      Inquiry complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_inq_cmpl_cb (void * p_result)
+{
+
+    tBTA_DM_MSG * p_msg;
+
+    APPL_TRACE_DEBUG0("bta_dm_inq_cmpl_cb");
+    if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->inq_cmpl.hdr.event = BTA_DM_INQUIRY_CMPL_EVT;
+        p_msg->inq_cmpl.num = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+        bta_sys_sendmsg(p_msg);
+
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_service_search_remname_cback
+**
+** Description      Remote name call back from BTM during service discovery
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_service_search_remname_cback (BD_ADDR bd_addr, DEV_CLASS dc, BD_NAME bd_name)
+{
+    tBTM_REMOTE_DEV_NAME    rem_name;
+    tBTM_STATUS             btm_status;
+
+    APPL_TRACE_DEBUG1("bta_dm_service_search_remname_cback name=<%s>", bd_name);
+
+    /* if this is what we are looking for */
+    if (!bdcmp( bta_dm_search_cb.peer_bdaddr, bd_addr))
+    {
+        rem_name.length = strlen((char*)bd_name);
+        if (rem_name.length > (BD_NAME_LEN-1))
+        {
+            rem_name.length = (BD_NAME_LEN-1);
+            rem_name.remote_bd_name[(BD_NAME_LEN-1)] = 0;
+        }
+        BCM_STRNCPY_S((char*)rem_name.remote_bd_name,  sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+        rem_name.status = BTM_SUCCESS;
+
+        bta_dm_remname_cback(&rem_name);
+    }
+    else
+    {
+        /* get name of device */
+        btm_status = BTM_ReadRemoteDeviceName (bta_dm_search_cb.peer_bdaddr,
+                                                (tBTM_CMPL_CB *) bta_dm_remname_cback);
+        if ( btm_status == BTM_BUSY )
+        {
+            /* wait for next chance(notification of remote name discovery done) */
+            APPL_TRACE_DEBUG0("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName is busy");
+        }
+        else if ( btm_status != BTM_CMD_STARTED )
+        {
+            /* if failed to start getting remote name then continue */
+            APPL_TRACE_WARNING1("bta_dm_service_search_remname_cback: BTM_ReadRemoteDeviceName returns 0x%02X", btm_status);
+
+            rem_name.length = 0;
+            rem_name.remote_bd_name[0] = 0;
+            rem_name.status = btm_status;
+            bta_dm_remname_cback(&rem_name);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_remname_cback
+**
+** Description      Remote name complete call back from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_remname_cback (tBTM_REMOTE_DEV_NAME *p_remote_name)
+{
+    tBTA_DM_REM_NAME * p_msg;
+
+    APPL_TRACE_DEBUG1("bta_dm_remname_cback name=<%s>", p_remote_name->remote_bd_name);
+
+    /* remote name discovery is done but it could be failed */
+    bta_dm_search_cb.name_discover_done = TRUE;
+    BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
+    bta_dm_search_cb.peer_name[BD_NAME_LEN-1]=0;
+
+    BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
+
+    if ((p_msg = (tBTA_DM_REM_NAME *) GKI_getbuf(sizeof(tBTA_DM_REM_NAME))) != NULL)
+    {
+        bdcpy (p_msg->result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN-1));
+
+        /* make sure the string is null terminated */
+        p_msg->result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+        p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
+        bta_sys_sendmsg(p_msg);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_authorize_cback
+**
+** Description      cback requesting authorization
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authorize_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name,
+                                     UINT8 *service_name, UINT8 service_id, BOOLEAN is_originator)
+{
+    tBTA_DM_SEC sec_event;
+    UINT8       index = 1;
+
+    bdcpy(sec_event.authorize.bd_addr, bd_addr);
+    memcpy(sec_event.authorize.dev_class, dev_class, DEV_CLASS_LEN);
+
+    BCM_STRNCPY_S((char*)sec_event.authorize.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+
+    /* make sure the string is null terminated */
+    sec_event.authorize.bd_name[BD_NAME_LEN-1] = 0;
+
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+    sec_event.authorize.service = service_id;
+#endif
+
+    while(index < BTA_MAX_SERVICE_ID)
+    {
+        /* get the BTA service id corresponding to BTM id */
+        if(bta_service_id_to_btm_srv_id_lkup_tbl[index] == service_id)
+        {
+            sec_event.authorize.service = index;
+            break;
+        }
+        index++;
+    }
+
+
+    /* if supported service callback otherwise not authorized */
+    if(bta_dm_cb.p_sec_cback && (index < BTA_MAX_SERVICE_ID
+#if ( defined(BTA_JV_INCLUDED) && BTA_JV_INCLUDED == TRUE )
+        /* pass through JV service ID */
+        || (service_id >= BTA_FIRST_JV_SERVICE_ID && service_id <= BTA_LAST_JV_SERVICE_ID)
+#endif
+        ))
+    {
+        bta_dm_cb.p_sec_cback(BTA_DM_AUTHORIZE_EVT, &sec_event);
+        return BTM_CMD_STARTED;
+    }
+    else
+    {
+        return BTM_NOT_AUTHORIZED;
+    }
+}
+
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pinname_cback
+**
+** Description      Callback requesting pin_key
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pinname_cback (void *p_data)
+{
+    tBTM_REMOTE_DEV_NAME *p_result = (tBTM_REMOTE_DEV_NAME *)p_data;
+    tBTA_DM_SEC           sec_event;
+    UINT32                bytes_to_copy;
+    tBTA_DM_SEC_EVT       event = bta_dm_cb.pin_evt;
+
+    if (BTA_DM_SP_CFM_REQ_EVT == event)
+    {
+	    /* Retrieved saved device class and bd_addr */
+	    bdcpy(sec_event.cfm_req.bd_addr, bta_dm_cb.pin_bd_addr);
+	    BTA_COPY_DEVICE_CLASS(sec_event.cfm_req.dev_class, bta_dm_cb.pin_dev_class);
+
+	    if (p_result && p_result->status == BTM_SUCCESS)
+	    {
+	        bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+            ? p_result->length : (BD_NAME_LEN-1);
+	        memcpy(sec_event.cfm_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+	        sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+	    }
+	    else    /* No name found */
+	        sec_event.cfm_req.bd_name[0] = 0;
+
+	    sec_event.key_notif.passkey    = bta_dm_cb.num_val; /* get PIN code numeric number */
+
+        /* 1 additional event data fields for this event */
+        sec_event.cfm_req.just_works = bta_dm_cb.just_works;
+    }
+    else
+    {
+	    /* Retrieved saved device class and bd_addr */
+	    bdcpy(sec_event.pin_req.bd_addr, bta_dm_cb.pin_bd_addr);
+	    BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, bta_dm_cb.pin_dev_class);
+
+	    if (p_result && p_result->status == BTM_SUCCESS)
+	    {
+	        bytes_to_copy = (p_result->length < (BD_NAME_LEN-1))
+            ? p_result->length : (BD_NAME_LEN-1);
+	        memcpy(sec_event.pin_req.bd_name, p_result->remote_bd_name, bytes_to_copy);
+	        sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+	    }
+	    else    /* No name found */
+	        sec_event.pin_req.bd_name[0] = 0;
+
+	    event = bta_dm_cb.pin_evt;
+	    sec_event.key_notif.passkey    = bta_dm_cb.num_val; /* get PIN code numeric number */
+    }
+
+    if( bta_dm_cb.p_sec_cback )
+        bta_dm_cb.p_sec_cback(event, &sec_event);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pin_cback
+**
+** Description      Callback requesting pin_key
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_pin_cback (BD_ADDR bd_addr, DEV_CLASS dev_class, BD_NAME bd_name)
+{
+    tBTA_DM_SEC sec_event;
+
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+    if (bd_name[0] == 0)
+    {
+        bta_dm_cb.pin_evt = BTA_DM_PIN_REQ_EVT;
+        bdcpy(bta_dm_cb.pin_bd_addr, bd_addr);
+        BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, dev_class);
+        if ((BTM_ReadRemoteDeviceName(bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+            return BTM_CMD_STARTED;
+
+        APPL_TRACE_WARNING0(" bta_dm_pin_cback() -> Failed to start Remote Name Request  ");
+    }
+
+    bdcpy(sec_event.pin_req.bd_addr, bd_addr);
+    BTA_COPY_DEVICE_CLASS(sec_event.pin_req.dev_class, dev_class);
+    BCM_STRNCPY_S((char*)sec_event.pin_req.bd_name, sizeof(BD_NAME), (char*)bd_name, (BD_NAME_LEN-1));
+    sec_event.pin_req.bd_name[BD_NAME_LEN-1] = 0;
+
+    bta_dm_cb.p_sec_cback(BTA_DM_PIN_REQ_EVT, &sec_event);
+    return BTM_CMD_STARTED;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_link_key_request_cback
+**
+** Description      Callback requesting linkkey
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8  bta_dm_link_key_request_cback (BD_ADDR bd_addr, LINK_KEY key)
+{
+    /* Application passes all link key to
+    BTM during initialization using add_device
+    API. If BTM doesn't have the link key in it's
+    data base, that's because application doesn't
+    it */
+
+    return BTM_NOT_AUTHORIZED;
+}
+
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_new_link_key_cback
+**
+** Description      Callback from BTM to notify new link key
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8  bta_dm_new_link_key_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,
+                                        BD_NAME bd_name, LINK_KEY key, UINT8 key_type)
+{
+    tBTA_DM_SEC sec_event;
+    tBTA_DM_AUTH_CMPL *p_auth_cmpl;
+    UINT8             event;
+
+    memset (&sec_event, 0, sizeof(tBTA_DM_SEC));
+
+    /* Not AMP Key type */
+    if (key_type != HCI_LKEY_TYPE_AMP_WIFI && key_type != HCI_LKEY_TYPE_AMP_UWB)
+    {
+        event = BTA_DM_AUTH_CMPL_EVT;
+        p_auth_cmpl = &sec_event.auth_cmpl;
+
+        bdcpy(p_auth_cmpl->bd_addr, bd_addr);
+
+        memcpy(p_auth_cmpl->bd_name, bd_name, (BD_NAME_LEN-1));
+        p_auth_cmpl->bd_name[BD_NAME_LEN-1] = 0;
+
+        p_auth_cmpl->key_present = TRUE;
+        p_auth_cmpl->key_type = key_type;
+        p_auth_cmpl->success = TRUE;
+
+        memcpy(p_auth_cmpl->key, key, LINK_KEY_LEN);
+        sec_event.auth_cmpl.fail_reason = HCI_SUCCESS;
+
+        if(bta_dm_cb.p_sec_cback)
+        {
+            bta_dm_cb.p_sec_cback(event, &sec_event);
+        }
+    }
+    else
+    {
+        APPL_TRACE_WARNING0(" bta_dm_new_link_key_cback() Received AMP Key??  ");
+    }
+
+    return BTM_CMD_STARTED;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_authentication_complete_cback
+**
+** Description      Authentication complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_authentication_complete_cback(BD_ADDR bd_addr, DEV_CLASS dev_class,BD_NAME bd_name, int result)
+{
+
+    tBTA_DM_SEC sec_event;
+
+    if(result != BTM_SUCCESS)
+    {
+        memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+        bdcpy(sec_event.auth_cmpl.bd_addr, bd_addr);
+
+        memcpy(sec_event.auth_cmpl.bd_name, bd_name, (BD_NAME_LEN-1));
+        sec_event.auth_cmpl.bd_name[BD_NAME_LEN-1] = 0;
+
+/*      taken care of by memset [above]
+        sec_event.auth_cmpl.key_present = FALSE;
+        sec_event.auth_cmpl.success = FALSE;
+*/
+        sec_event.auth_cmpl.fail_reason = (UINT8)result;
+        if(bta_dm_cb.p_sec_cback)
+        {
+            bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+        }
+    }
+
+    return BTM_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sp_cback
+**
+** Description      simple pairing callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_sp_cback (tBTM_SP_EVT event, tBTM_SP_EVT_DATA *p_data)
+{
+    tBTM_STATUS status = BTM_CMD_STARTED;
+    tBTA_DM_SEC sec_event;
+    tBTA_DM_SEC_EVT pin_evt = BTA_DM_SP_KEY_NOTIF_EVT;
+
+    APPL_TRACE_EVENT1("bta_dm_sp_cback: %d", event);
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    /* TODO_SP */
+    switch(event)
+    {
+    case BTM_SP_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+        /* translate auth_req */
+        bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
+            &p_data->io_req.oob_data, &p_data->io_req.auth_req, p_data->io_req.is_orig);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+        status = BTM_SUCCESS;
+#endif
+
+        APPL_TRACE_EVENT2("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
+        break;
+    case BTM_SP_IO_RSP_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+        bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
+                         p_data->io_rsp.oob_data, p_data->io_rsp.auth_req );
+#endif
+        break;
+
+    case BTM_SP_CFM_REQ_EVT:
+        pin_evt = BTA_DM_SP_CFM_REQ_EVT;
+        bta_dm_cb.just_works = sec_event.cfm_req.just_works = p_data->cfm_req.just_works;
+        sec_event.cfm_req.loc_auth_req = p_data->cfm_req.loc_auth_req;
+        sec_event.cfm_req.rmt_auth_req = p_data->cfm_req.rmt_auth_req;
+        sec_event.cfm_req.loc_io_caps = p_data->cfm_req.loc_io_caps;
+        sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;
+        /* continue to next case */
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    /* Passkey entry mode, mobile device with output capability is very
+        unlikely to receive key request, so skip this event */
+    /*case BTM_SP_KEY_REQ_EVT: */
+    case BTM_SP_KEY_NOTIF_EVT:
+#endif
+        bta_dm_cb.num_val = sec_event.key_notif.passkey = p_data->key_notif.passkey;
+        /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+        if (p_data->key_notif.bd_name[0] == 0)
+        {
+            bta_dm_cb.pin_evt = pin_evt;
+            bdcpy(bta_dm_cb.pin_bd_addr, p_data->key_notif.bd_addr);
+            BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->key_notif.dev_class);
+            if ((BTM_ReadRemoteDeviceName(p_data->key_notif.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+                return BTM_CMD_STARTED;
+
+            APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
+        }
+        bdcpy(sec_event.key_notif.bd_addr, p_data->key_notif.bd_addr);
+        BTA_COPY_DEVICE_CLASS(sec_event.key_notif.dev_class, p_data->key_notif.dev_class);
+            BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), (char*)p_data->key_notif.bd_name, (BD_NAME_LEN-1));
+            sec_event.key_notif.bd_name[BD_NAME_LEN-1] = 0;
+
+        bta_dm_cb.p_sec_cback(pin_evt, &sec_event);
+
+        break;
+
+#if BTM_OOB_INCLUDED == TRUE
+    case BTM_SP_LOC_OOB_EVT:
+        bta_dm_co_loc_oob((BOOLEAN)(p_data->loc_oob.status == BTM_SUCCESS),
+            p_data->loc_oob.c, p_data->loc_oob.r);
+        break;
+
+    case BTM_SP_RMT_OOB_EVT:
+        /* If the device name is not known, save bdaddr and devclass and initiate a name request */
+        if (p_data->rmt_oob.bd_name[0] == 0)
+        {
+            bta_dm_cb.pin_evt = BTA_DM_SP_RMT_OOB_EVT;
+            bdcpy(bta_dm_cb.pin_bd_addr, p_data->rmt_oob.bd_addr);
+            BTA_COPY_DEVICE_CLASS(bta_dm_cb.pin_dev_class, p_data->rmt_oob.dev_class);
+            if ((BTM_ReadRemoteDeviceName(p_data->rmt_oob.bd_addr, bta_dm_pinname_cback)) == BTM_CMD_STARTED)
+                return BTM_CMD_STARTED;
+
+            APPL_TRACE_WARNING0(" bta_dm_sp_cback() -> Failed to start Remote Name Request  ");
+        }
+        bdcpy(sec_event.rmt_oob.bd_addr, p_data->rmt_oob.bd_addr);
+        BTA_COPY_DEVICE_CLASS(sec_event.rmt_oob.dev_class, p_data->rmt_oob.dev_class);
+            BCM_STRNCPY_S((char*)sec_event.rmt_oob.bd_name, sizeof(BD_NAME), (char*)p_data->rmt_oob.bd_name, (BD_NAME_LEN-1));
+            sec_event.rmt_oob.bd_name[BD_NAME_LEN-1] = 0;
+
+        bta_dm_cb.p_sec_cback(BTA_DM_SP_RMT_OOB_EVT, &sec_event);
+
+        bta_dm_co_rmt_oob(p_data->rmt_oob.bd_addr);
+        break;
+#endif
+    case BTM_SP_COMPLT_EVT:
+        /* do not report this event - handled by link_key_callback or auth_complete_callback */
+        break;
+
+    case BTM_SP_KEYPRESS_EVT:
+        memcpy(&sec_event.key_press, &p_data->key_press, sizeof(tBTM_SP_KEYPRESS));
+        bta_dm_cb.p_sec_cback(BTA_DM_SP_KEYPRESS_EVT, &sec_event);
+        break;
+
+    case BTM_SP_UPGRADE_EVT:
+        bta_dm_co_lk_upgrade(p_data->upgrade.bd_addr, &p_data->upgrade.upgrade );
+        break;
+
+    default:
+        status = BTM_NOT_AUTHORIZED;
+        break;
+    }
+    APPL_TRACE_EVENT1("dm status: %d", status);
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_local_name_cback
+**
+** Description      Callback from btm after local name is read
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_local_name_cback(UINT8 *p_name)
+{
+    tBTA_DM_SEC sec_event;
+
+    BTM_GetLocalDeviceAddr(sec_event.enable.bd_addr);
+    sec_event.enable.status = BTA_SUCCESS;
+
+    if(bta_dm_cb.p_sec_cback)
+        bta_dm_cb.p_sec_cback(BTA_DM_ENABLE_EVT, &sec_event);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_signal_strength
+**
+** Description      Callback from btm after local bdaddr is read
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_signal_strength(tBTA_DM_MSG *p_data)
+{
+
+    if(p_data->sig_strength.start)
+    {
+        bta_dm_cb.signal_strength_mask = p_data->sig_strength.mask;
+        bta_dm_cb.signal_strength_period = p_data->sig_strength.period;
+        bta_dm_signal_strength_timer_cback(NULL);
+    }
+    else
+    {
+        bta_sys_stop_timer(&bta_dm_cb.signal_strength_timer);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_dm_signal_strength_timer_cback
+**
+** Description      Periodic timer callback to read signal strength
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_signal_strength_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+
+    UINT8 i;
+
+    if(bta_dm_cb.signal_strength_mask & BTA_SIG_STRENGTH_RSSI_MASK)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            BTM_ReadRSSI (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, (tBTM_CMPL_CB *)bta_dm_rssi_cback);
+
+        }
+    }
+    if(bta_dm_cb.signal_strength_mask & BTA_SIG_STRENGTH_LINK_QUALITY_MASK)
+    {
+
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            BTM_ReadLinkQuality (bta_dm_cb.device_list.peer_device[i].peer_bdaddr, (tBTM_CMPL_CB *)bta_dm_link_quality_cback);
+        }
+
+    }
+
+    if(bta_dm_cb.signal_strength_period)
+    {
+        bta_dm_cb.signal_strength_timer.p_cback = (TIMER_CBACK*)&bta_dm_signal_strength_timer_cback;
+        bta_sys_start_timer(&bta_dm_cb.signal_strength_timer, 0, (UINT32)1000*bta_dm_cb.signal_strength_period);
+    }
+}
+
+
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_bl_change_cback
+**
+** Description      Callback from btm when acl connection goes up or down
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_bl_change_cback (tBTM_BL_EVENT_DATA *p_data)
+{
+
+    tBTA_DM_ACL_CHANGE * p_msg;
+
+    if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
+    {
+        p_msg->event = p_data->event;
+        p_msg->is_new = FALSE;
+
+        switch(p_msg->event)
+        {
+        case BTM_BL_CONN_EVT:
+            p_msg->is_new = TRUE;
+            bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+            break;
+        case BTM_BL_DISCN_EVT:
+            bdcpy(p_msg->bd_addr, p_data->discn.p_bda);
+            break;
+        case BTM_BL_UPDATE_EVT:
+            p_msg->busy_level = p_data->update.busy_level;
+            break;
+        case BTM_BL_ROLE_CHG_EVT:
+            p_msg->new_role = p_data->role_chg.new_role;
+            p_msg->hci_status = p_data->role_chg.hci_status;
+            bdcpy(p_msg->bd_addr, p_data->role_chg.p_bda);
+            break;
+            case BTM_BL_COLLISION_EVT:
+                bdcpy(p_msg->bd_addr, p_data->conn.p_bda);
+                break;;
+        }
+
+        p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+        bta_sys_sendmsg(p_msg);
+
+    }
+
+}
+#else
+
+/*******************************************************************************
+**
+** Function         bta_dm_acl_change_cback
+**
+** Description      Callback from btm when acl connection goes up or down
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_acl_change_cback (BD_ADDR p_bda, DEV_CLASS p_dc, BD_NAME p_bdn,
+                                     BD_FEATURES features, BOOLEAN is_new)
+{
+
+    tBTA_DM_ACL_CHANGE * p_msg;
+
+    if ((p_msg = (tBTA_DM_ACL_CHANGE *) GKI_getbuf(sizeof(tBTA_DM_ACL_CHANGE))) != NULL)
+    {
+        bdcpy (p_msg->bd_addr, p_bda);
+        p_msg->is_new = is_new;
+
+        /* This is collision case */
+        if (features != NULL)
+        {
+            if ((features[0] == 0xFF) && !is_new)
+                p_msg->event = BTM_BL_COLLISION_EVT;
+        }
+
+        p_msg->hdr.event = BTA_DM_ACL_CHANGE_EVT;
+        bta_sys_sendmsg(p_msg);
+
+    }
+
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_dm_rs_cback
+**
+** Description      Receives the role switch complete event
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_dm_rs_cback (tBTM_ROLE_SWITCH_CMPL *p1)
+{
+    APPL_TRACE_WARNING1("bta_dm_rs_cback:%d", bta_dm_cb.rs_event);
+    if(bta_dm_cb.rs_event == BTA_DM_API_SEARCH_EVT)
+    {
+        bta_dm_cb.search_msg.rs_res = BTA_DM_RS_OK; /* do not care about the result for now */
+        bta_dm_cb.rs_event = 0;
+        bta_dm_search_start((tBTA_DM_MSG *)&bta_dm_cb.search_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_check_av
+**
+** Description      This function checks if AV is active
+**                  if yes, make sure the AV link is master
+**
+** Returns          BOOLEAN - TRUE, if switch is in progress
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_check_av(UINT16 event)
+{
+    BOOLEAN switching = FALSE;
+    UINT8 i;
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    APPL_TRACE_WARNING1("bta_dm_check_av:%d", bta_dm_cb.cur_av_count);
+    if(bta_dm_cb.cur_av_count)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            p_dev = &bta_dm_cb.device_list.peer_device[i];
+            APPL_TRACE_WARNING3("[%d]: state:%d, info:x%x", i, p_dev->conn_state, p_dev->info);
+            if((p_dev->conn_state == BTA_DM_CONNECTED) && (p_dev->info & BTA_DM_DI_AV_ACTIVE))
+            {
+                /* make master and take away the role switch policy */
+                if(BTM_CMD_STARTED == BTM_SwitchRole (p_dev->peer_bdaddr, HCI_ROLE_MASTER, (tBTM_CMPL_CB *)bta_dm_rs_cback))
+                {
+                    /* the role switch command is actually sent */
+                    bta_dm_cb.rs_event = event;
+                    switching = TRUE;
+                }
+                /* else either already master or can not switch for some reasons */
+                bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+                break;
+            }
+        }
+    }
+    return switching;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_acl_change
+**
+** Description      Process BTA_DM_ACL_CHANGE_EVT
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_acl_change(tBTA_DM_MSG *p_data)
+{
+
+    UINT8 i;
+    UINT8 *p;
+    tBTA_DM_SEC conn;
+    BOOLEAN is_new = p_data->acl_change.is_new;
+    BD_ADDR_PTR     p_bda = p_data->acl_change.bd_addr;
+    BOOLEAN         need_policy_change = FALSE;
+    BOOLEAN         issue_unpair_cb = FALSE;
+
+#if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    switch(p_data->acl_change.event)
+    {
+    case BTM_BL_UPDATE_EVT:     /* busy level update */
+        if( bta_dm_cb.p_sec_cback )
+        {
+            conn.busy_level.level = p_data->acl_change.busy_level;
+            bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
+        }
+        return;
+
+    case BTM_BL_ROLE_CHG_EVT:   /* role change event */
+        p_dev = bta_dm_find_peer_device(p_bda);
+        if(p_dev)
+        {
+            APPL_TRACE_DEBUG3("bta_dm_acl_change role chg info:x%x new_role:%d dev count:%d",
+                p_dev->info, p_data->acl_change.new_role, bta_dm_cb.device_list.count);
+            if(p_dev->info & BTA_DM_DI_AV_ACTIVE)
+            {
+                /* there's AV activity on this link */
+                if(p_data->acl_change.new_role == HCI_ROLE_SLAVE && bta_dm_cb.device_list.count > 1
+                    && p_data->acl_change.hci_status == HCI_SUCCESS)
+                {
+                    /* more than one connections and the AV connection is role switched to slave
+                     * switch it back to master and remove the switch policy */
+                    BTM_SwitchRole(p_bda, BTM_ROLE_MASTER, NULL);
+                    need_policy_change = TRUE;
+                }
+                else if (bta_dm_cfg.avoid_scatter && (p_data->acl_change.new_role == HCI_ROLE_MASTER))
+                {
+                    /* if the link updated to be master include AV activities, remove the switch policy */
+                    need_policy_change = TRUE;
+                }
+
+                if(need_policy_change)
+                {
+                    bta_dm_policy_cback(BTA_SYS_PLCY_CLR, 0, HCI_ENABLE_MASTER_SLAVE_SWITCH, p_dev->peer_bdaddr);
+                }
+            }
+            else
+            {
+                /* there's AV no activity on this link and role switch happened
+                 * check if AV is active
+                 * if so, make sure the AV link is master */
+                bta_dm_check_av(0);
+            }
+            bta_sys_notify_role_chg(p_data->acl_change.bd_addr, p_data->acl_change.new_role, p_data->acl_change.hci_status);
+            bdcpy(conn.role_chg.bd_addr, p_bda);
+            conn.role_chg.new_role = (UINT8) p_data->acl_change.new_role;
+            if( bta_dm_cb.p_sec_cback )
+                bta_dm_cb.p_sec_cback(BTA_DM_ROLE_CHG_EVT, &conn);
+        }
+        return;
+    }
+#endif
+
+    /* Collision report from Stack: Notify profiles */
+    if (p_data->acl_change.event == BTM_BL_COLLISION_EVT)
+    {
+        bta_sys_notify_collision (p_bda);
+        return;
+    }
+
+    if(is_new)
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+                break;
+
+        }
+
+        if(i == bta_dm_cb.device_list.count)
+        {
+            bdcpy(bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].peer_bdaddr, p_bda);
+            bta_dm_cb.device_list.peer_device[bta_dm_cb.device_list.count].link_policy = bta_dm_cb.cur_policy;
+            bta_dm_cb.device_list.count++;
+        }
+
+        bta_dm_cb.device_list.peer_device[i].conn_state = BTA_DM_CONNECTED;
+        bta_dm_cb.device_list.peer_device[i].pref_role = BTA_ANY_ROLE;
+        bdcpy(conn.link_up.bd_addr, p_bda);
+        bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_NONE;
+        if( ((NULL != (p = BTM_ReadLocalFeatures ())) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) &&
+            ((NULL != (p = BTM_ReadRemoteFeatures (p_bda))) && HCI_SNIFF_SUB_RATE_SUPPORTED(p)) )
+        {
+            /* both local and remote devices support SSR */
+            bta_dm_cb.device_list.peer_device[i].info = BTA_DM_DI_USE_SSR;
+        }
+        APPL_TRACE_WARNING1("info:x%x", bta_dm_cb.device_list.peer_device[i].info);
+        if( bta_dm_cb.p_sec_cback )
+            bta_dm_cb.p_sec_cback(BTA_DM_LINK_UP_EVT, &conn);
+
+    }
+    else
+    {
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if(bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, p_bda))
+                continue;
+
+            if( bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_UNPAIRING )
+            {
+                BTM_SecDeleteDevice(bta_dm_cb.device_list.peer_device[i].peer_bdaddr);
+                issue_unpair_cb = TRUE;
+            }
+
+            for(; i<bta_dm_cb.device_list.count ; i++)
+            {
+                memcpy(&bta_dm_cb.device_list.peer_device[i], &bta_dm_cb.device_list.peer_device[i+1], sizeof(bta_dm_cb.device_list.peer_device[i]));
+            }
+            break;
+        }
+        if(bta_dm_cb.device_list.count)
+            bta_dm_cb.device_list.count--;
+
+        if(bta_dm_search_cb.wait_disc && !bdcmp(bta_dm_search_cb.peer_bdaddr, p_bda))
+        {
+            bta_dm_search_cb.wait_disc = FALSE;
+
+            if(bta_dm_search_cb.sdp_results)
+            {
+                APPL_TRACE_EVENT0(" timer stopped  ");
+                bta_sys_stop_timer(&bta_dm_search_cb.search_timer);
+                bta_dm_discover_next_device();
+            }
+
+        }
+
+        if(bta_dm_cb.disabling)
+        {
+            if(!BTM_GetNumAclLinks())
+            {
+                bta_sys_stop_timer(&bta_dm_cb.disable_timer);
+                bta_dm_cb.disable_timer.p_cback = (TIMER_CBACK*)&bta_dm_disable_conn_down_timer_cback;
+                /* start a timer to make sure that the profiles get the disconnect event */
+                bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1000);
+            }
+        }
+
+        bdcpy(conn.link_down.bd_addr, p_bda);
+        conn.link_down.status = (UINT8) btm_get_acl_disc_reason_code();
+        if( bta_dm_cb.p_sec_cback )
+        {
+            bta_dm_cb.p_sec_cback(BTA_DM_LINK_DOWN_EVT, &conn);
+            if( issue_unpair_cb )
+                bta_dm_cb.p_sec_cback(BTA_DM_DEV_UNPAIRED_EVT, &conn);
+        }
+    }
+
+    bta_dm_adjust_roles(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_conn_down_timer_cback
+**
+** Description      Sends disable event to application
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_conn_down_timer_cback (TIMER_LIST_ENT *p_tle)
+{
+    tBTA_SYS_HW_MSG *sys_enable_event;
+
+    /* register our callback to SYS HW manager */
+    bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
+
+    /* send a message to BTA SYS */
+    if ((sys_enable_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        sys_enable_event->hdr.event = BTA_SYS_API_DISABLE_EVT;
+        sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
+        bta_sys_sendmsg(sys_enable_event);
+    }
+
+    bta_dm_cb.disabling = FALSE;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_rssi_cback
+**
+** Description      Callback from btm with rssi values
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_rssi_cback (tBTM_RSSI_RESULTS *p_result)
+{
+    tBTA_DM_SEC sec_event;
+
+    if(p_result->status == BTM_SUCCESS)
+    {
+
+        bdcpy(sec_event.sig_strength.bd_addr, p_result->rem_bda);
+        sec_event.sig_strength.mask = BTA_SIG_STRENGTH_RSSI_MASK;
+        sec_event.sig_strength.rssi_value = p_result->rssi;
+        if( bta_dm_cb.p_sec_cback!= NULL )
+            bta_dm_cb.p_sec_cback(BTA_DM_SIG_STRENGTH_EVT, &sec_event);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_link_quality_cback
+**
+** Description      Callback from btm with link quality value
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_link_quality_cback (tBTM_LINK_QUALITY_RESULTS *p_result)
+{
+
+    tBTA_DM_SEC sec_event;
+
+    if(p_result->status == BTM_SUCCESS)
+    {
+
+        bdcpy(sec_event.sig_strength.bd_addr, p_result->rem_bda);
+        sec_event.sig_strength.mask = BTA_SIG_STRENGTH_LINK_QUALITY_MASK;
+        sec_event.sig_strength.link_quality_value = p_result->link_quality;
+        if( bta_dm_cb.p_sec_cback!= NULL )
+            bta_dm_cb.p_sec_cback(BTA_DM_SIG_STRENGTH_EVT, &sec_event);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_rm_cback
+**
+** Description      Role management callback from sys
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_rm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+    UINT8 j;
+    tBTA_PREF_ROLES role;
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    p_dev = bta_dm_find_peer_device(peer_addr);
+    if( status == BTA_SYS_CONN_OPEN)
+    {
+        if(p_dev)
+        {
+            /* Do not set to connected if we are in the middle of unpairing. When AV stream is
+             * started it fakes out a SYS_CONN_OPEN to potentially trigger a role switch command.
+             * But this should not be done if we are in the middle of unpairing.
+             */
+            if (p_dev->conn_state != BTA_DM_UNPAIRING)
+                p_dev->conn_state = BTA_DM_CONNECTED;
+
+            for(j=1; j<= p_bta_dm_rm_cfg[0].app_id; j++)
+            {
+                if(((p_bta_dm_rm_cfg[j].app_id == app_id) || (p_bta_dm_rm_cfg[j].app_id == BTA_ALL_APP_ID))
+                    && (p_bta_dm_rm_cfg[j].id == id))
+                {
+                    role = p_bta_dm_rm_cfg[j].cfg;
+
+                    if(role > p_dev->pref_role )
+                        p_dev->pref_role = role;
+                    break;
+                }
+            }
+
+        }
+
+    }
+
+    if((BTA_ID_AV == id)||(BTA_ID_AVK ==id))
+    {
+        if( status == BTA_SYS_CONN_BUSY)
+        {
+            if(p_dev)
+                p_dev->info |= BTA_DM_DI_AV_ACTIVE;
+            /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
+            if(BTA_ID_AV == id)
+                bta_dm_cb.cur_av_count = app_id;
+        }
+        else if( status == BTA_SYS_CONN_IDLE)
+        {
+            if(p_dev)
+                p_dev->info &= ~BTA_DM_DI_AV_ACTIVE;
+            /* AV calls bta_sys_conn_open with the A2DP stream count as app_id */
+            if(BTA_ID_AV == id)
+                bta_dm_cb.cur_av_count = app_id;
+        }
+        APPL_TRACE_WARNING2("bta_dm_rm_cback:%d, status:%d", bta_dm_cb.cur_av_count, status);
+    }
+
+
+    bta_dm_adjust_roles(FALSE);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_dev_blacklisted_for_switch
+**
+** Description      Checks if the device is blacklisted for immediate role switch after connection.
+**
+** Returns          TRUE if dev is blacklisted else FALSE
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_dev_blacklisted_for_switch (BD_ADDR remote_bd_addr)
+{
+    UINT16 manufacturer = 0;
+    UINT16  lmp_sub_version = 0;
+    UINT8 lmp_version = 0;
+    UINT8 i = 0;
+
+    if (BTM_ReadRemoteVersion(remote_bd_addr, &lmp_version,
+        &manufacturer, &lmp_sub_version) == BTM_SUCCESS)
+    {
+        /* Check if this device version info matches with is
+           blacklisted versions for role switch  */
+        for (i = 0; i < BTA_DM_MAX_ROLE_SWITCH_BLACKLIST_COUNT; i++)
+        {
+             if ((bta_role_switch_blacklist[i].lmp_version == lmp_version) &&
+                 (bta_role_switch_blacklist[i].manufacturer == manufacturer)&&
+                 ((bta_role_switch_blacklist[i].lmp_sub_version & lmp_sub_version) ==
+                     bta_role_switch_blacklist[i].lmp_sub_version))
+                {
+                    APPL_TRACE_EVENT0("Black list F/W version matches.. Delay Role Switch...");
+                    return TRUE;
+                }
+
+        }
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_delay_role_switch_cback
+**
+** Description      Callback from btm to delay a role switch
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_delay_role_switch_cback(TIMER_LIST_ENT *p_tle)
+{
+    APPL_TRACE_EVENT0("bta_dm_delay_role_switch_cback: initiating Delayed RS");
+    bta_dm_adjust_roles (FALSE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_adjust_roles
+**
+** Description      Adjust roles
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_adjust_roles(BOOLEAN delay_role_switch)
+{
+
+    UINT8 i;
+    BOOLEAN set_master_role = FALSE;
+
+    if(bta_dm_cb.device_list.count)
+    {
+
+        /* the configuration is no scatternet
+         * or AV connection exists and there are more than one ACL link */
+        if( (p_bta_dm_rm_cfg[0].cfg == BTA_DM_NO_SCATTERNET) ||
+            (bta_dm_cb.cur_av_count && bta_dm_cb.device_list.count > 1) )
+        {
+
+            L2CA_SetDesireRole (HCI_ROLE_MASTER);
+            set_master_role = TRUE;
+
+        }
+
+        for(i=0; i<bta_dm_cb.device_list.count; i++)
+        {
+            if(bta_dm_cb.device_list.peer_device[i].conn_state == BTA_DM_CONNECTED)
+            {
+                if(!set_master_role && (bta_dm_cb.device_list.peer_device[i].pref_role != BTA_ANY_ROLE)
+                    && (p_bta_dm_rm_cfg[0].cfg == BTA_DM_PARTIAL_SCATTERNET))
+                {
+                    L2CA_SetDesireRole (HCI_ROLE_MASTER);
+                    set_master_role = TRUE;
+                }
+
+                if((bta_dm_cb.device_list.peer_device[i].pref_role == BTA_MASTER_ROLE_ONLY)
+                    || (bta_dm_cb.device_list.count > 1))
+                {
+
+                /* Initiating immediate role switch with certain remote devices
+                  has caused issues due to role  switch colliding with link encryption setup and
+                  causing encryption (and in turn the link) to fail .  These device . Firmware
+                  versions are stored in a blacklist and role switch with these devices are
+                  delayed to avoid the collision with link encryption setup */
+
+                    if ((delay_role_switch == FALSE) ||
+                       (bta_dm_dev_blacklisted_for_switch(
+                                       bta_dm_cb.device_list.peer_device[i].peer_bdaddr) == FALSE))
+                    {
+                        BTM_SwitchRole (bta_dm_cb.device_list.peer_device[i].peer_bdaddr,
+                                        HCI_ROLE_MASTER, NULL);
+                    }
+                    else
+                    {
+                        bta_dm_cb.switch_delay_timer.p_cback =
+                            (TIMER_CBACK*)&bta_dm_delay_role_switch_cback;
+                        bta_sys_start_timer(&bta_dm_cb.switch_delay_timer, 0, 500);
+                    }
+                }
+
+            }
+        }
+
+
+        if(!set_master_role)
+        {
+
+            L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+
+        }
+
+    }
+    else
+    {
+        L2CA_SetDesireRole (L2CAP_DESIRED_LINK_ROLE);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_get_remname
+**
+** Description      Returns a pointer to the remote name stored in the DM control
+**                  block if it exists, or from the BTM memory.
+**
+** Returns          char * - Pointer to the remote device name
+*******************************************************************************/
+static char *bta_dm_get_remname(void)
+{
+    char *p_name = bta_dm_search_cb.peer_name;
+    char *p_temp;
+
+    /* If the name isn't already stored, try retrieving from BTM */
+    if (*p_name == '\0')
+        if ((p_temp = BTM_SecReadDevName(bta_dm_search_cb.peer_bdaddr)) != NULL)
+            p_name = p_temp;
+
+    return p_name;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_bond_cancel_complete_cback
+**
+** Description      Authentication complete callback from BTM
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_bond_cancel_complete_cback(tBTM_STATUS result)
+{
+
+    tBTA_DM_SEC sec_event;
+
+    if (result == BTM_SUCCESS)
+        sec_event.bond_cancel_cmpl.result = BTA_SUCCESS;
+    else
+        sec_event.bond_cancel_cmpl.result = BTA_FAILURE;
+
+    if(bta_dm_cb.p_sec_cback)
+    {
+        bta_dm_cb.p_sec_cback(BTA_DM_BOND_CANCEL_CMPL_EVT, &sec_event);
+    }
+}
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+    #if ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+/*******************************************************************************
+**
+** Function         bta_dm_update_eir_uuid
+**
+** Description
+**
+**
+*******************************************************************************/
+void bta_dm_update_eir_uuid (tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_UPDATE_EIR_UUID *p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *)p_data;
+    UINT8 xx;
+    UINT8 empty_slot = BTA_EIR_SERVER_NUM_CUSTOM_UUID;
+    UINT8 match_slot = BTA_EIR_SERVER_NUM_CUSTOM_UUID;
+
+    for (xx = 0; xx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; xx++)
+    {
+        if (bta_dm_cb.custom_uuid[xx].len == 0)
+        {
+            if (empty_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+                empty_slot = xx;
+        }
+        else if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+        {
+            if (!memcmp (bta_dm_cb.custom_uuid[xx].uu.uuid128, p_msg->uuid.uu.uuid128, p_msg->uuid.len))
+            {
+                match_slot = xx;;
+            }
+        }
+    }
+
+    if (p_msg->is_add)
+    {
+        if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+        {
+            if (empty_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+            {
+                APPL_TRACE_ERROR0("No space to add UUID for EIR");
+                return;
+            }
+            else
+            {
+                memcpy (&(bta_dm_cb.custom_uuid[empty_slot]), &(p_msg->uuid), sizeof(tBT_UUID));
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("UUID is already added for EIR");
+            return;
+        }
+    }
+    else
+    {
+        if (match_slot == BTA_EIR_SERVER_NUM_CUSTOM_UUID)
+        {
+            APPL_TRACE_ERROR0("UUID is not found for EIR");
+            return;
+        }
+        else
+        {
+            memset (&(bta_dm_cb.custom_uuid[match_slot]), 0, sizeof(tBT_UUID));
+        }
+    }
+
+    bta_dm_set_eir (NULL);
+}
+    #endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_eir_config
+**
+** Description
+**
+**
+*******************************************************************************/
+void bta_dm_set_eir_config (tBTA_DM_MSG *p_data)
+{
+    if (p_data->set_eir_cfg.p_eir_cfg)
+    {
+        /* User defined config */
+        p_bta_dm_eir_cfg = p_data->set_eir_cfg.p_eir_cfg;
+    }
+    else
+    {
+        /* Back to default config */
+        p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;
+    }
+
+    bta_dm_set_eir (NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_eir
+**
+** Description      This function creates EIR tagged data and writes it to controller.
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_set_eir (char *local_name)
+{
+    BT_HDR   *p_buf;
+    UINT8    *p;
+    UINT8    *p_length;
+#if (BTA_EIR_CANNED_UUID_LIST != TRUE)
+    UINT8    *p_type;
+    UINT8    max_num_uuid;
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    UINT8    custom_uuid_idx;
+#endif
+#endif
+#if (BTM_EIR_DEFAULT_FEC_REQUIRED == FALSE)
+    UINT8    free_eir_length = HCI_EXT_INQ_RESPONSE_LEN;
+#else
+    UINT8    free_eir_length = HCI_DM5_PACKET_SIZE;
+#endif
+    UINT8    num_uuid;
+    UINT8    data_type;
+    UINT8    local_name_len;
+
+    /* wait until complete to disable */
+    if (bta_dm_cb.disable_timer.in_use)
+        return;
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )
+    /* wait until App is ready */
+    if (bta_dm_cb.app_ready_timer.in_use)
+        return;
+
+    /* if local name is not provided, get it from controller */
+    if( local_name == NULL )
+    {
+        if( BTM_ReadLocalDeviceName( &local_name ) != BTM_SUCCESS )
+        {
+            APPL_TRACE_ERROR0("Fail to read local device name for EIR");
+        }
+    }
+#endif
+
+    /* Allocate a buffer to hold HCI command */
+    if ((p_buf = (BT_HDR *)GKI_getpoolbuf(BTM_CMD_POOL_ID)) == NULL)
+    {
+        APPL_TRACE_ERROR0("bta_dm_set_eir couldn't allocate buffer");
+        return;
+    }
+    p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET;
+
+    memset(p, 0x00, HCI_EXT_INQ_RESPONSE_LEN );
+
+    APPL_TRACE_DEBUG0("BTA is generating EIR");
+
+    if( local_name )
+        local_name_len = strlen( local_name );
+    else
+        local_name_len = 0;
+
+    data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+    /* if local name is longer than minimum length of shortened name */
+    /* check whether it needs to be shortened or not */
+    if( local_name_len > p_bta_dm_eir_cfg->bta_dm_eir_min_name_len )
+    {
+        /* get number of UUID 16-bit list */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+        num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len/LEN_UUID_16;
+#else
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+        data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p,
+                                                 max_num_uuid, &num_uuid );
+        p = (UINT8 *)p_buf + BTM_HCI_EIR_OFFSET; /* reset p */
+#endif
+
+        /* if UUID doesn't fit remaing space, shorten local name */
+        if ( local_name_len > (free_eir_length - 4 - num_uuid*LEN_UUID_16))
+        {
+            APPL_TRACE_WARNING0("BTA EIR: local name is shortened");
+            local_name_len = p_bta_dm_eir_cfg->bta_dm_eir_min_name_len;
+            data_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
+        }
+        else
+            data_type = BTM_EIR_COMPLETE_LOCAL_NAME_TYPE;
+    }
+
+    UINT8_TO_STREAM(p, local_name_len + 1);
+    UINT8_TO_STREAM(p, data_type);
+    memcpy(p, local_name, local_name_len);
+    p += local_name_len;
+    free_eir_length -= local_name_len + 2;
+
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    /* if UUID list is provided as static data in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len > 0 )
+        &&(p_bta_dm_eir_cfg->bta_dm_eir_uuid16))
+    {
+        if( free_eir_length > LEN_UUID_16 + 2)
+        {
+            free_eir_length -= 2;
+
+            if( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len)
+            {
+                num_uuid = p_bta_dm_eir_cfg->bta_dm_eir_uuid16_len / LEN_UUID_16;
+                data_type = BTM_EIR_COMPLETE_16BITS_UUID_TYPE;
+            }
+            else /* not enough room for all UUIDs */
+            {
+                APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+                num_uuid = free_eir_length / LEN_UUID_16;
+                data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+            }
+            UINT8_TO_STREAM(p, num_uuid * LEN_UUID_16 + 1);
+            UINT8_TO_STREAM(p, data_type);
+            memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_uuid16, num_uuid * LEN_UUID_16 );
+            p += num_uuid * LEN_UUID_16;
+            free_eir_length -= num_uuid * LEN_UUID_16;
+        }
+    }
+#else /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+    /* if UUID list is dynamic */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_16;
+        data_type = BTM_GetEirSupportedServices( bta_dm_cb.eir_uuid, &p, max_num_uuid, &num_uuid );
+
+        if( data_type == BTM_EIR_MORE_16BITS_UUID_TYPE )
+        {
+            APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+        }
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+        else
+        {
+            for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+            {
+                if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_16)
+                {
+                    if ( num_uuid < max_num_uuid )
+                    {
+                        UINT16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid16);
+                        num_uuid++;
+                    }
+                    else
+                    {
+                        data_type = BTM_EIR_MORE_16BITS_UUID_TYPE;
+                        APPL_TRACE_WARNING0("BTA EIR: UUID 16-bit list is truncated");
+                        break;
+                    }
+                }
+            }
+        }
+#endif /* (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_16 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_16 + 2;
+    }
+#endif /* (BTA_EIR_CANNED_UUID_LIST == TRUE) */
+
+#if ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    /* Adding 32-bit UUID list */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+        data_type = BTM_EIR_COMPLETE_32BITS_UUID_TYPE;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_32;
+
+        for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+        {
+            if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_32)
+            {
+                if ( num_uuid < max_num_uuid )
+                {
+                    UINT32_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid32);
+                    num_uuid++;
+                }
+                else
+                {
+                    data_type = BTM_EIR_MORE_32BITS_UUID_TYPE;
+                    APPL_TRACE_WARNING0("BTA EIR: UUID 32-bit list is truncated");
+                    break;
+                }
+            }
+        }
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_32 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_32 + 2;
+    }
+
+    /* Adding 128-bit UUID list */
+    if ( free_eir_length >= 2)
+    {
+        p_length = p++;
+        p_type   = p++;
+        num_uuid = 0;
+        data_type = BTM_EIR_COMPLETE_128BITS_UUID_TYPE;
+
+        max_num_uuid = (free_eir_length - 2)/LEN_UUID_128;
+
+        for (custom_uuid_idx = 0; custom_uuid_idx < BTA_EIR_SERVER_NUM_CUSTOM_UUID; custom_uuid_idx++)
+        {
+            if (bta_dm_cb.custom_uuid[custom_uuid_idx].len == LEN_UUID_128)
+            {
+                if ( num_uuid < max_num_uuid )
+                {
+                    ARRAY16_TO_STREAM(p, bta_dm_cb.custom_uuid[custom_uuid_idx].uu.uuid128);
+                    num_uuid++;
+                }
+                else
+                {
+                    data_type = BTM_EIR_MORE_128BITS_UUID_TYPE;
+                    APPL_TRACE_WARNING0("BTA EIR: UUID 128-bit list is truncated");
+                    break;
+                }
+            }
+        }
+
+        UINT8_TO_STREAM(p_length, num_uuid * LEN_UUID_128 + 1);
+        UINT8_TO_STREAM(p_type, data_type);
+        free_eir_length -= num_uuid * LEN_UUID_128 + 2;
+    }
+#endif /* ( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0) */
+
+    /* if Flags are provided in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_flag_len > 0 )
+     &&( p_bta_dm_eir_cfg->bta_dm_eir_flags )
+     &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2 ))
+    {
+        UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 1);
+        UINT8_TO_STREAM(p, BTM_EIR_FLAGS_TYPE);
+        memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_flags,
+               p_bta_dm_eir_cfg->bta_dm_eir_flag_len);
+        p += p_bta_dm_eir_cfg->bta_dm_eir_flag_len;
+        free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_flag_len + 2;
+    }
+
+    /* if Inquiry Tx Resp Power compiled */
+    if((p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power) &&
+       (free_eir_length >= 3))
+    {
+        UINT8_TO_STREAM(p, 2);      /* Length field */
+        UINT8_TO_STREAM(p, BTM_EIR_TX_POWER_LEVEL_TYPE);
+        UINT8_TO_STREAM(p, *(p_bta_dm_eir_cfg->bta_dm_eir_inq_tx_power));
+        free_eir_length -= 3;
+    }
+
+    /* if Manufacturer Specific are provided in configuration */
+    if(( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len > 0 )
+     &&( p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec )
+     &&( free_eir_length >= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2 ))
+    {
+        p_length = p;
+
+        UINT8_TO_STREAM(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 1);
+        UINT8_TO_STREAM(p, BTM_EIR_MANUFACTURER_SPECIFIC_TYPE);
+        memcpy(p, p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec,
+               p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len);
+        p += p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len;
+        free_eir_length -= p_bta_dm_eir_cfg->bta_dm_eir_manufac_spec_len + 2;
+
+    }
+    else
+    {
+        p_length = NULL;
+    }
+
+    if( free_eir_length )
+        UINT8_TO_STREAM(p, 0); /* terminator of significant part */
+
+    BTM_WriteEIR( p_buf );
+
+}
+#endif
+
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+/*******************************************************************************
+**
+** Function         bta_dm_eir_search_services
+**
+** Description      This function searches services in received EIR
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_eir_search_services( tBTM_INQ_RESULTS  *p_result,
+                                        tBTA_SERVICE_MASK *p_services_to_search,
+                                        tBTA_SERVICE_MASK *p_services_found)
+{
+    tBTA_SERVICE_MASK       service_index = 0;
+    tBTM_EIR_SEARCH_RESULT  result;
+
+    APPL_TRACE_DEBUG6("BTA searching services in EIR of BDA:0x%02X%02X%02X%02X%02X%02X",
+                        p_result->remote_bd_addr[0],p_result->remote_bd_addr[1],
+                        p_result->remote_bd_addr[2],p_result->remote_bd_addr[3],
+                        p_result->remote_bd_addr[4],p_result->remote_bd_addr[5]);
+
+    APPL_TRACE_DEBUG1("    with services_to_search=0x%08X", *p_services_to_search);
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    /* always do GATT based service discovery by SDP instead of from EIR    */
+    /* if GATT based service is also to be put in EIR, need to modify this  */
+    while (service_index < (BTA_MAX_SERVICE_ID - 1))
+#else
+    while(service_index < BTA_MAX_SERVICE_ID)
+#endif
+    {
+        if( *p_services_to_search
+           & (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)))
+        {
+            result = BTM_HasInquiryEirService( p_result,
+                                               bta_service_id_to_uuid_lkup_tbl[service_index] );
+
+            /* Searching for HSP v1.2 only device */
+            if ((result != BTM_EIR_FOUND) &&
+                (bta_service_id_to_uuid_lkup_tbl[service_index] == UUID_SERVCLASS_HEADSET))
+            {
+                result = BTM_HasInquiryEirService (p_result, UUID_SERVCLASS_HEADSET_HS);
+            }
+
+            if( result == BTM_EIR_FOUND )
+            {
+                /* If Plug and Play service record, need to check to see if Broadcom stack */
+                /* However, EIR data doesn't have EXT_BRCM_VERSION so just skip it */
+                if( bta_service_id_to_uuid_lkup_tbl[service_index]
+                    != UUID_SERVCLASS_PNP_INFORMATION )
+                {
+
+                    *p_services_found |=
+                       (tBTA_SERVICE_MASK)(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index));
+                    /* remove the service from services to be searched  */
+                    *p_services_to_search &=
+                       (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+                }
+            }
+            else if( result == BTM_EIR_NOT_FOUND )
+            {
+                /* remove the service from services to be searched  */
+                *p_services_to_search &=
+                       (tBTA_SERVICE_MASK)(~(BTA_SERVICE_ID_TO_SERVICE_MASK(service_index)));
+            }
+        }
+
+        service_index++;
+    }
+
+    APPL_TRACE_ERROR2("BTA EIR search result, services_to_search=0x%08X, services_found=0x%08X",
+                        *p_services_to_search, *p_services_found);
+}
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_eir_update_uuid
+**
+** Description      This function adds or removes service UUID in EIR database.
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding)
+{
+    /* if this UUID is not advertised in EIR */
+    if( !BTM_HasEirService( p_bta_dm_eir_cfg->uuid_mask, uuid16 ))
+        return;
+
+    if( adding )
+    {
+        APPL_TRACE_EVENT1("Adding UUID=0x%04X into EIR", uuid16);
+
+        BTM_AddEirService( bta_dm_cb.eir_uuid, uuid16 );
+    }
+    else
+    {
+        APPL_TRACE_EVENT1("Removing UUID=0x%04X from EIR", uuid16);
+
+        BTM_RemoveEirService( bta_dm_cb.eir_uuid, uuid16 );
+    }
+
+    bta_dm_set_eir (NULL);
+
+    APPL_TRACE_EVENT2("bta_dm_eir_update_uuid UUID bit mask=0x%08X %08X",
+                       bta_dm_cb.eir_uuid[1], bta_dm_cb.eir_uuid[0] );
+}
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_enable_test_mode
+**
+** Description      enable test mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data)
+{
+    BTM_EnableTestMode();
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_test_mode
+**
+** Description      disable test mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data)
+{
+    BTM_DeviceReset(NULL);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_execute_callback
+**
+** Description      Just execute a generic call back in the context of the BTU/BTA tack
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_execute_callback(tBTA_DM_MSG *p_data)
+{
+    /* sanity check */
+    if(p_data->exec_cback.p_exec_cback == NULL)
+    {
+        return;
+    }
+
+    p_data->exec_cback.p_exec_cback(p_data->exec_cback.p_param);
+}
+/*******************************************************************************
+**
+** Function         bta_dm_encrypt_cback
+**
+** Description      link encryption complete callback.
+**
+** Returns         None
+**
+*******************************************************************************/
+void bta_dm_encrypt_cback(BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+{
+    tBTA_STATUS   bta_status = BTA_SUCCESS;
+    tBTA_DM_ENCRYPT_CBACK *p_callback = bta_dm_cb.p_encrypt_cback;
+
+    bta_dm_cb.p_encrypt_cback = NULL;
+    switch (result)
+    {
+        case BTM_SUCCESS:
+            break;
+        case BTM_WRONG_MODE:
+            bta_status = BTA_WRONG_MODE;
+            break;
+        case BTM_NO_RESOURCES:
+            bta_status = BTA_NO_RESOURCES;
+            break;
+        case BTM_BUSY:
+            bta_status = BTA_BUSY;
+            break;
+        default:
+            bta_status = BTA_FAILURE;
+            break;
+    }
+
+    APPL_TRACE_DEBUG2("bta_dm_encrypt_cback status =%d p_callback=0x%x", bta_status, p_callback);
+
+    if (p_callback)
+    {
+        (*p_callback)(bd_addr, bta_status);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_dm_set_encryption
+**
+** Description      This function to encrypt the link
+**
+** Returns          None
+**
+*******************************************************************************/
+void bta_dm_set_encryption (tBTA_DM_MSG *p_data)
+{
+
+    APPL_TRACE_DEBUG0("bta_dm_set_encryption"); //todo
+    if (!p_data->set_encryption.p_callback)
+    {
+        APPL_TRACE_ERROR0("bta_dm_set_encryption callback is not provided");
+        return;
+    }
+
+    if (bta_dm_cb.p_encrypt_cback)
+    {
+        (*p_data->set_encryption.p_callback)(p_data->set_encryption.bd_addr, BTA_BUSY);
+        return;
+    }
+
+
+    bta_dm_cb.p_encrypt_cback = p_data->set_encryption.p_callback;
+    bta_dm_cb.sec_act         = p_data->set_encryption.sec_act;
+    BTM_SetEncryption(p_data->set_encryption.bd_addr, bta_dm_encrypt_cback, &bta_dm_cb.sec_act);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_afh_channels
+**
+** Description      set afh channels
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_set_afh_channels(tBTA_DM_MSG * p_data)
+{
+
+    BTM_SetAfhChannels(p_data->set_afhchannels.first,p_data->set_afhchannels.last);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_set_afh_channel_assesment
+**
+** Description      set afh channel assesment
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+
+void bta_dm_set_afh_channel_assesment (tBTA_DM_MSG * p_data)
+{
+    BTM_SetAfhChannelAssessment(p_data->set_afh_channel_assessment.enable_or_disable);
+}
+
+#if (BLE_INCLUDED == TRUE)
+#if (SMP_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_ble_smp_cback
+**
+** Description      Callback for BLE SMP
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_DATA *p_data)
+{
+    tBTM_STATUS status = BTM_SUCCESS;
+    tBTA_DM_SEC sec_event;
+
+    if (!bta_dm_cb.p_sec_cback)
+        return BTM_NOT_AUTHORIZED;
+
+    memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
+    switch (event)
+    {
+        case BTM_LE_IO_REQ_EVT:
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+
+            bta_dm_co_ble_io_req(bda,
+                                 &p_data->io_req.io_cap,
+                                 &p_data->io_req.oob_data,
+                                 &p_data->io_req.auth_req,
+                                 &p_data->io_req.max_key_size,
+                                 &p_data->io_req.init_keys,
+                                 &p_data->io_req.resp_keys);
+#endif
+#if BTM_OOB_INCLUDED == FALSE
+            status = BTM_SUCCESS;
+#endif
+            APPL_TRACE_EVENT2("io mitm: %d oob_data:%d", p_data->io_req.auth_req, p_data->io_req.oob_data);
+
+            break;
+
+        case BTM_LE_SEC_REQUEST_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_SEC_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_NOTIF_EVT:
+            bdcpy(sec_event.key_notif.bd_addr, bda);
+            BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+            sec_event.key_notif.passkey = p_data->key_notif;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_REQ_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_OOB_REQ_EVT:
+            bdcpy(sec_event.ble_req.bd_addr, bda);
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
+            break;
+
+        case BTM_LE_KEY_EVT:
+            bdcpy(sec_event.ble_key.bd_addr, bda);
+            sec_event.ble_key.key_type = p_data->key.key_type;
+            memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
+            break;
+
+        case BTM_LE_COMPLT_EVT:
+            bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+            if (p_data->complt.reason != 0)
+                sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
+            else
+                sec_event.auth_cmpl.success = TRUE;
+
+            if (bta_dm_cb.p_sec_cback)
+            {
+                //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
+                bta_dm_cb.p_sec_cback(BTA_DM_BLE_AUTH_CMPL_EVT, &sec_event);
+            }
+
+            break;
+
+        default:
+            status = BTM_NOT_AUTHORIZED;
+            break;
+    }
+    return status;
+}
+#endif  /* SMP_INCLUDED == TRUE */
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_id_key_cback
+**
+** Description      Callback for BLE local ID keys
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_ble_id_key_cback (UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
+{
+    UINT8   evt;
+    tBTA_DM_SEC dm_key;
+
+    switch (key_type)
+    {
+        case BTM_BLE_KEY_TYPE_ID:
+        case BTM_BLE_KEY_TYPE_ER:
+            if (bta_dm_cb.p_sec_cback)
+            {
+                memcpy(&dm_key.ble_id_keys, p_key, sizeof(tBTM_BLE_LOCAL_KEYS));
+
+                evt = (key_type == BTM_BLE_KEY_TYPE_ID) ? BTA_DM_BLE_LOCAL_IR_EVT :\
+                      BTA_DM_BLE_LOCAL_ER_EVT;
+                bta_dm_cb.p_sec_cback(evt, &dm_key);
+            }
+            break;
+
+        default:
+            APPL_TRACE_DEBUG1("Unknown key type %d", key_type);
+            break;
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_blekey
+**
+** Description      This function adds an BLE Key to an security database entry.
+**                  This function shall only be called AFTER BTA_DmAddBleDevice has been called.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_blekey (tBTA_DM_MSG *p_data)
+{
+    if (!BTM_SecAddBleKey (p_data->add_ble_key.bd_addr,
+                           (tBTM_LE_KEY_VALUE *)&p_data->add_ble_key.blekey,
+                           p_data->add_ble_key.key_type))
+    {
+        APPL_TRACE_ERROR2 ("BTA_DM: Error adding BLE Key for device %08x%04x",
+                           (p_data->add_ble_key.bd_addr[0]<<24)+(p_data->add_ble_key.bd_addr[1]<<16)+\
+                           (p_data->add_ble_key.bd_addr[2]<<8)+p_data->add_ble_key.bd_addr[3],
+                           (p_data->add_ble_key.bd_addr[4]<<8)+p_data->add_ble_key.bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_ble_device
+**
+** Description      This function adds an BLE device to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_add_ble_device (tBTA_DM_MSG *p_data)
+{
+    if (!BTM_SecAddBleDevice (p_data->add_ble_device.bd_addr, NULL,
+                              p_data->add_ble_device.dev_type  ,
+                              p_data->add_ble_device.addr_type))
+    {
+        APPL_TRACE_ERROR2 ("BTA_DM: Error adding BLE Device for device %08x%04x",
+                           (p_data->add_ble_device.bd_addr[0]<<24)+(p_data->add_ble_device.bd_addr[1]<<16)+ \
+                           (p_data->add_ble_device.bd_addr[2]<<8)+p_data->add_ble_device.bd_addr[3],
+                           (p_data->add_ble_device.bd_addr[4]<<8)+p_data->add_ble_device.bd_addr[5]);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_add_ble_device
+**
+** Description      This function adds an BLE device to an security database entry.
+**                  It is normally called during host startup to restore all required information
+**                  stored in the NVRAM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data)
+{
+    if (p_data->pin_reply.accept)
+    {
+
+        BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_SUCCESS, p_data->ble_passkey_reply.passkey);
+    }
+    else
+    {
+        BTM_BlePasskeyReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED, p_data->ble_passkey_reply.passkey);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_security_grant
+**
+** Description      This function grant SMP security request access.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_security_grant (tBTA_DM_MSG *p_data)
+{
+    BTM_SecurityGrant(p_data->ble_sec_grant.bd_addr, p_data->ble_sec_grant.res);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_bg_conn_type
+**
+** Description      This function set the BLE background connection type
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetBgConnType(p_data->ble_set_bd_conn_type.bg_conn_type,
+                         p_data->ble_set_bd_conn_type.p_select_cback);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_conn_params
+**
+** Description      This function set the preferred connection parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetPrefConnParams(p_data->ble_set_conn_params.peer_bda,
+                             p_data->ble_set_conn_params.conn_int_min,
+                             p_data->ble_set_conn_params.conn_int_max,
+                             p_data->ble_set_conn_params.slave_latency,
+                             p_data->ble_set_conn_params.supervision_tout);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_set_scan_params
+**
+** Description      This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data)
+{
+    BTM_BleSetConnScanParams(p_data->ble_set_scan_params.scan_int,
+                             p_data->ble_set_scan_params.scan_window);
+}
+
+#if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
+
+/*******************************************************************************
+**
+** Function         btm_dm_start_disc_gatt_services
+**
+** Description      This function starts a GATT service search request.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void btm_dm_start_disc_gatt_services (UINT16 conn_id)
+{
+    tBT_UUID    *p_uuid = bta_dm_search_cb.p_srvc_uuid +
+                          bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+    p_uuid = bta_dm_search_cb.p_srvc_uuid +
+             bta_dm_search_cb.num_uuid - bta_dm_search_cb.uuid_to_search;
+
+    /* always search for all services */
+    BTA_GATTC_ServiceSearchRequest(conn_id, p_uuid);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gatt_disc_result
+**
+** Description      This function process the GATT service search result.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_result(tBTA_GATT_ID service_id)
+{
+    tBTA_DM_SEARCH   result;
+
+    /*
+        * This logic will not work for gatt case.  We are checking against the bluetooth profiles here
+        * just copy the GATTID in raw data field and send it across.
+        */
+
+
+    if ( bta_dm_search_cb.ble_raw_used + sizeof(tBTA_GATT_ID) < bta_dm_search_cb.ble_raw_size )
+    {
+        APPL_TRACE_DEBUG3("ADDING BLE SERVICE uuid=0x%x, ble_ptr = 0x%x, ble_raw_used = 0x%x", service_id.uuid.uu.uuid16,bta_dm_search_cb.p_ble_rawdata,bta_dm_search_cb.ble_raw_used);
+
+        memcpy((bta_dm_search_cb.p_ble_rawdata + bta_dm_search_cb.ble_raw_used), &service_id,
+                sizeof(service_id) );
+
+        bta_dm_search_cb.ble_raw_used += sizeof(service_id);
+
+    }
+    else
+    {
+        APPL_TRACE_ERROR3("%s out of room to accomodate more service ids ble_raw_size = %d ble_raw_used = %d", __FUNCTION__,bta_dm_search_cb.ble_raw_size, bta_dm_search_cb.ble_raw_used );
+    }
+
+    APPL_TRACE_ERROR1("bta_dm_gatt_disc_result serivce_id len=%d ", service_id.uuid.len);
+    if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+    {
+
+        /* send result back to app now, one by one */
+        bdcpy (result.disc_ble_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN-1));
+        memcpy(&result.disc_ble_res.service, &service_id.uuid, sizeof(tBT_UUID));
+
+        bta_dm_search_cb.p_search_cback(BTA_DM_DISC_BLE_RES_EVT, &result);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gatt_disc_complete
+**
+** Description      This function process the GATT service search complete.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gatt_disc_complete(UINT16 conn_id, tBTA_GATT_STATUS status)
+{
+    tBTA_DM_MSG *p_msg;
+
+    APPL_TRACE_DEBUG1("bta_dm_gatt_disc_complete conn_id = %d",conn_id);
+
+    if (bta_dm_search_cb.uuid_to_search > 0) bta_dm_search_cb.uuid_to_search --;
+
+    if (status == BTA_GATT_OK && bta_dm_search_cb.uuid_to_search > 0)
+    {
+        btm_dm_start_disc_gatt_services(conn_id);
+    }
+    else
+    {
+        bta_dm_search_cb.uuid_to_search = 0;
+
+        /* no more services to be discovered */
+        if ((p_msg = (tBTA_DM_MSG *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_DISCOVERY_RESULT_EVT;
+            p_msg->disc_result.result.disc_res.result = (status == BTA_GATT_OK) ? BTA_SUCCESS :BTA_FAILURE;
+            p_msg->disc_result.result.disc_res.services = bta_dm_search_cb.services_found;
+            bdcpy (p_msg->disc_result.result.disc_res.bd_addr, bta_dm_search_cb.peer_bdaddr);
+            BCM_STRNCPY_S((char*)p_msg->disc_result.result.disc_res.bd_name, sizeof(BD_NAME),
+                    bta_dm_get_remname(), (BD_NAME_LEN-1));
+
+            /* make sure the string is terminated */
+            p_msg->disc_result.result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+
+            p_msg->disc_result.result.disc_res.device_type = BT_DEVICE_TYPE_BLE;
+            if ( bta_dm_search_cb.ble_raw_used > 0 )
+            {
+                p_msg->disc_result.result.disc_res.p_raw_data = GKI_getbuf(bta_dm_search_cb.ble_raw_used);
+
+                memcpy( p_msg->disc_result.result.disc_res.p_raw_data,
+                            bta_dm_search_cb.p_ble_rawdata,
+                            bta_dm_search_cb.ble_raw_used );
+
+                p_msg->disc_result.result.disc_res.raw_data_size = bta_dm_search_cb.ble_raw_used;
+            }
+            else
+            {
+                p_msg->disc_result.result.disc_res.p_raw_data = NULL;
+                bta_dm_search_cb.p_ble_rawdata = 0;
+            }
+
+            bta_sys_sendmsg(p_msg);
+        }
+        if (conn_id != BTA_GATT_INVALID_CONN_ID)
+        {
+            BTA_GATTC_Close(conn_id);
+        }
+        bta_dm_search_cb.conn_id = BTA_GATT_INVALID_CONN_ID;
+        bta_dm_search_cb.gatt_disc_active = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_dm_start_gatt_discovery
+**
+** Description      This is GATT initiate the service search by open a GATT connection
+**                  first.
+**
+** Parameters:
+**
+*******************************************************************************/
+void btm_dm_start_gatt_discovery (BD_ADDR bd_addr)
+{
+    bta_dm_search_cb.gatt_disc_active = TRUE;
+    BTA_GATTC_Open(bta_dm_search_cb.client_if, bd_addr, TRUE);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_cancel_gatt_discovery
+**
+** Description      This is GATT cancel the GATT service search.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_cancel_gatt_discovery(BD_ADDR bd_addr)
+{
+    if (bta_dm_search_cb.conn_id == BTA_GATT_INVALID_CONN_ID)
+    {
+        BTA_GATTC_CancelOpen(bta_dm_search_cb.client_if, bd_addr, TRUE);
+    }
+
+    bta_dm_gatt_disc_complete(bta_dm_search_cb.conn_id, (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_proc_open_evt
+**
+** Description      process BTA_GATTC_OPEN_EVT in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_proc_open_evt(tBTA_GATTC_OPEN *p_data)
+{
+    UINT8           *p1;
+    UINT8           *p2;
+
+    p1 = bta_dm_search_cb.peer_bdaddr;
+    p2 = p_data->remote_bda;
+
+    APPL_TRACE_DEBUG5("DM Search state= %d search_cb.peer_dbaddr: [%08x%04x] connected_bda= [%08x%04x] ",
+                      bta_dm_search_cb.state,
+                      ((p1[0])<<24)+((p1[1])<<16)+((p1[2])<<8)+(p1[3]),
+                      ((p1[4])<<8)+ p1[5],
+                      ((p2[0])<<24)+((p2[1])<<16)+((p2[2])<<8)+(p2[3]),
+                      ((p2[4])<<8)+ p2[5]);
+
+    APPL_TRACE_DEBUG3("BTA_GATTC_OPEN_EVT conn_id = %d client_if=%d status = %d" ,
+                      p_data->conn_id,
+                      p_data->client_if,
+                      p_data->status);
+
+    bta_dm_search_cb.conn_id = p_data->conn_id;
+
+    if (p_data->status == BTA_GATT_OK)
+    {
+        btm_dm_start_disc_gatt_services(p_data->conn_id);
+    }
+    else
+    {
+        bta_dm_gatt_disc_complete(BTA_GATT_INVALID_CONN_ID, p_data->status);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_gattc_callback
+**
+** Description      This is GATT client callback function used in DM.
+**
+** Parameters:
+**
+*******************************************************************************/
+static void bta_dm_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+    APPL_TRACE_DEBUG1("bta_dm_gattc_callback event = %d", event);
+
+    switch (event)
+    {
+        case BTA_GATTC_REG_EVT:
+            APPL_TRACE_DEBUG1("BTA_GATTC_REG_EVT client_if = %d",  p_data->reg_oper.client_if);
+            if (p_data->reg_oper.status == BTA_GATT_OK)
+                bta_dm_search_cb.client_if = p_data->reg_oper.client_if;
+            else
+                bta_dm_search_cb.client_if = BTA_GATTS_INVALID_IF;
+            break;
+
+        case BTA_GATTC_OPEN_EVT:
+            bta_dm_proc_open_evt(&p_data->open);
+            break;
+
+        case BTA_GATTC_SEARCH_RES_EVT:
+            bta_dm_gatt_disc_result(p_data->srvc_res.service_uuid.id);
+            break;
+
+        case BTA_GATTC_SEARCH_CMPL_EVT:
+            if ( bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE)
+                bta_dm_gatt_disc_complete(p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
+            break;
+
+        case BTA_GATTC_CLOSE_EVT:
+            APPL_TRACE_DEBUG1("BTA_GATTC_CLOSE_EVT reason = %d", p_data->close.reason);
+            /* in case of disconnect before search is completed */
+            if ( (bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE) &&
+                 !memcmp(p_data->close.remote_bda, bta_dm_search_cb.peer_bdaddr, BD_ADDR_LEN))
+            {
+                bta_dm_gatt_disc_complete((UINT16)BTA_GATT_INVALID_CONN_ID,  (tBTA_GATT_STATUS) BTA_GATT_ERROR);
+            }
+            break;
+
+        default:
+            break;
+    }
+}
+
+#endif /* BTA_GATT_INCLUDED */
+
+#endif  /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
new file mode 100644
index 0000000..06e3b93
--- /dev/null
+++ b/bta/dm/bta_dm_api.c
@@ -0,0 +1,1616 @@
+/******************************************************************************
+ *
+ *  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 is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "bta_sys_int.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include <string.h>
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_dm_reg =
+{
+    bta_dm_sm_execute,
+    bta_dm_sm_disable
+};
+
+static const tBTA_SYS_REG bta_dm_search_reg =
+{
+    bta_dm_search_sm_execute,
+    bta_dm_search_sm_disable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_EnableBluetooth
+**
+** Description      Enables bluetooth service.  This function must be
+**                  called before any other functions in the BTA API are called.
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback)
+{
+
+    tBTA_DM_API_ENABLE    *p_msg;
+
+    /* Bluetooth disabling is in progress */
+    if (bta_dm_cb.disabling)
+        return BTA_FAILURE;
+
+    memset(&bta_dm_cb, 0, sizeof(bta_dm_cb));
+
+    GKI_sched_lock();
+    bta_sys_register (BTA_ID_DM, &bta_dm_reg );
+    bta_sys_register (BTA_ID_DM_SEARCH, &bta_dm_search_reg );
+
+    /* if UUID list is not provided as static data */
+    bta_sys_eir_register(bta_dm_eir_update_uuid);
+
+    GKI_sched_unlock();
+
+    if ((p_msg = (tBTA_DM_API_ENABLE *) GKI_getbuf(sizeof(tBTA_DM_API_ENABLE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_ENABLE_EVT;
+        p_msg->p_sec_cback = p_cback;
+        bta_sys_sendmsg(p_msg);
+        return BTA_SUCCESS;
+    }
+    return BTA_FAILURE;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DisableBluetooth
+**
+** Description      Disables bluetooth service.  This function is called when
+**                  the application no longer needs bluetooth service
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DisableBluetooth(void)
+{
+
+    BT_HDR    *p_msg;
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+    else
+    {
+        return BTA_FAILURE;
+    }
+
+    return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_EnableTestMode
+**
+** Description      Enables bluetooth device under test mode
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_EnableTestMode(void)
+{
+    BT_HDR    *p_msg;
+
+    APPL_TRACE_API0("BTA_EnableTestMode");
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_ENABLE_TEST_MODE_EVT;
+        bta_sys_sendmsg(p_msg);
+        return BTA_SUCCESS;
+    }
+    return BTA_FAILURE;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DisableTestMode
+**
+** Description      Disable bluetooth device under test mode
+**
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DisableTestMode(void)
+{
+    BT_HDR    *p_msg;
+
+    APPL_TRACE_API0("BTA_DisableTestMode");
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_DISABLE_TEST_MODE_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmIsDeviceUp
+**
+** Description      Called during startup to check whether the bluetooth module
+**                  is up and ready
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+BOOLEAN BTA_DmIsDeviceUp(void)
+{
+
+    BOOLEAN status;
+
+    GKI_sched_lock();
+    status = BTM_IsDeviceUp();
+    GKI_sched_unlock();
+    return status;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetDeviceName
+**
+** Description      This function sets the Bluetooth name of local device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetDeviceName(char *p_name)
+{
+
+    tBTA_DM_API_SET_NAME    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_NAME *) GKI_getbuf(sizeof(tBTA_DM_API_SET_NAME))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_NAME_EVT;
+        /* truncate the name if needed */
+        BCM_STRNCPY_S(p_msg->name, sizeof(p_msg->name), p_name, BD_NAME_LEN-1);
+        p_msg->name[BD_NAME_LEN-1]=0;
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetVisibility
+**
+** Description      This function sets the Bluetooth connectable,
+**                  discoverable, pairable and conn paired only modes of local device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter )
+{
+
+    tBTA_DM_API_SET_VISIBILITY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_VISIBILITY *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_VISIBILITY_EVT;
+        p_msg->disc_mode = disc_mode;
+        p_msg->conn_mode = conn_mode;
+        p_msg->pair_mode = pairable_mode;
+        p_msg->conn_paired_only = conn_filter;
+
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetScanParam
+**
+** Description      This function sets the parameters for page scan and
+**                  inquiry scan.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetScanParam (UINT16 page_scan_interval, UINT16 page_scan_window,
+                                  UINT16 inquiry_scan_interval, UINT16 inquiry_scan_window)
+{
+    APPL_TRACE_API4 ("BTA_DmSetScanParam: %d, %d, %d, %d",
+            page_scan_interval, page_scan_window,
+            inquiry_scan_interval, inquiry_scan_window);
+
+    bta_dm_cb.page_scan_interval = page_scan_interval;
+    bta_dm_cb.page_scan_window = page_scan_window;
+    bta_dm_cb.inquiry_scan_interval = inquiry_scan_interval;
+    bta_dm_cb.inquiry_scan_window = inquiry_scan_window;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetAfhChannels
+**
+** Description      This function sets the AFH first and
+**                  last disable channel, so channels within
+**                  that range are disabled.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetAfhChannels(UINT8 first, UINT8 last)
+{
+
+    tBTA_DM_API_SET_AFH_CHANNELS_EVT    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_AFH_CHANNELS_EVT *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_AFH_CHANNELS_EVT;
+        p_msg->first = first;
+        p_msg->last = last;
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_SetAfhChannelAssessment
+**
+** Description      This function is called to set the channel assessment mode on or off
+**
+** Returns          status
+**
+*******************************************************************************/
+void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable)
+{
+    tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT *) GKI_getbuf(sizeof(tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT))) != NULL)
+    {
+        p_msg->hdr.event    = BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT;
+        p_msg->enable_or_disable = enable_or_disable;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmVendorSpecificCommand
+**
+** Description      This function sends the vendor specific command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len,
+                                         UINT8 *p_param_buf,
+                                         tBTA_VENDOR_CMPL_CBACK *p_cback)
+{
+
+    tBTA_DM_API_VENDOR_SPECIFIC_COMMAND    *p_msg;
+    UINT16 size;
+
+    /* If p_cback is NULL, Notify application */
+    if (p_cback == NULL)
+    {
+        return (BTA_FAILURE);
+    }
+    else
+    {
+        size = sizeof (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND) + param_len;
+        if ((p_msg = (tBTA_DM_API_VENDOR_SPECIFIC_COMMAND *) GKI_getbuf(size)) != NULL)
+        {
+            p_msg->hdr.event = BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT;
+            p_msg->opcode = opcode;
+            p_msg->param_len = param_len;
+            p_msg->p_param_buf = (UINT8 *)(p_msg + 1);
+            p_msg->p_cback = p_cback;
+
+            memcpy (p_msg->p_param_buf, p_param_buf, param_len);
+
+            bta_sys_sendmsg(p_msg);
+        }
+        return (BTA_SUCCESS);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_DmSearch
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+
+    tBTA_DM_API_SEARCH    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(sizeof(tBTA_DM_API_SEARCH))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_SEARCH));
+
+        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+        memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+        p_msg->services = services;
+        p_msg->p_cback = p_cback;
+        p_msg->rs_res  = BTA_DM_RS_NONE;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchCancel
+**
+** Description      This function  cancels a search initiated by BTA_DmSearch
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearchCancel(void)
+{
+    BT_HDR    *p_msg;
+
+    if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_DM_API_SEARCH_CANCEL_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscover
+**
+** Description      This function does service discovery for services of a
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+    tBTA_DM_API_DISCOVER    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_DISCOVER));
+
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->services = services;
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverUUID
+**
+** Description      This function does service discovery for services of a
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+    tBTA_DM_API_DISCOVER    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(sizeof(tBTA_DM_API_DISCOVER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->services = BTA_USER_SERVICE_MASK; //Not exposed at API level
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+        p_msg->num_uuid = 0;
+        p_msg->p_uuid = NULL;
+#endif
+        memcpy( &p_msg->uuid, uuid, sizeof(tSDP_UUID) );
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         BTA_DmIsMaster
+**
+** Description      This function checks if the local device is the master of
+**                  the link to the given device
+**
+** Returns          TRUE if master.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_DmIsMaster(BD_ADDR bd_addr)
+{
+    BOOLEAN is_master = FALSE;
+    UINT8 link_role;
+
+    BTM_GetRole(bd_addr, &link_role);
+    APPL_TRACE_API1("BTA_DmIsMaster role:x%x", link_role);
+    if(link_role == BTM_ROLE_MASTER)
+    {
+        is_master = TRUE;
+    }
+    return is_master;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBond
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBond(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_BOND    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BOND *) GKI_getbuf(sizeof(tBTA_DM_API_BOND))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BOND_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondCancel
+**
+** Description      This function cancels the bonding procedure with a peer
+**                  device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBondCancel(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_BOND_CANCEL    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BOND_CANCEL *) GKI_getbuf(sizeof(tBTA_DM_API_BOND_CANCEL))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_BOND_CANCEL_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmPinReply
+**
+** Description      This function provides a pincode for a remote device when
+**                  one is requested by DM through BTA_DM_PIN_REQ_EVT
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len, UINT8 *p_pin)
+
+{
+    tBTA_DM_API_PIN_REPLY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PIN_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PIN_REPLY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_PIN_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        if(accept)
+        {
+            p_msg->pin_len = pin_len;
+            memcpy(p_msg->p_pin, p_pin, pin_len);
+        }
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmLinkPolicy
+**
+** Description      This function sets/clears the link policy mask to the given
+**                  bd_addr.
+**                  If clearing the sniff or park mode mask, the link is put
+**                  in active mode.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmLinkPolicy(BD_ADDR bd_addr, tBTA_DM_LP_MASK policy_mask,
+                      BOOLEAN set)
+{
+    tBTA_DM_API_LINK_POLICY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_LINK_POLICY *) GKI_getbuf(sizeof(tBTA_DM_API_LINK_POLICY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_LINK_POLICY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->policy_mask = policy_mask;
+        p_msg->set = set;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmLocalOob
+**
+** Description      This function retrieves the OOB data from local controller.
+**                  The result is reported by bta_dm_co_loc_oob().
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmLocalOob(void)
+{
+    tBTA_DM_API_LOC_OOB    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_LOC_OOB *) GKI_getbuf(sizeof(tBTA_DM_API_LOC_OOB))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_LOC_OOB_EVT;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif /* BTM_OOB_INCLUDED */
+/*******************************************************************************
+**
+** Function         BTA_DmConfirm
+**
+** Description      This function accepts or rejects the numerical value of the
+**                  Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept)
+{
+    tBTA_DM_API_CONFIRM    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_CONFIRM_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmPasskeyCancel
+**
+** Description      This function is called to cancel the simple pairing process
+**                  reported by BTA_DM_SP_KEY_NOTIF_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+void BTA_DmPasskeyCancel(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_PASKY_CANCEL    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PASKY_CANCEL *) \
+        GKI_getbuf(sizeof(tBTA_DM_API_PASKY_CANCEL))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_PASKY_CANCEL_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevice
+**
+** Description      This function adds a device to the security database list of
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class, LINK_KEY link_key,
+                     tBTA_SERVICE_MASK trusted_mask, BOOLEAN is_trusted,
+                     UINT8 key_type, tBTA_IO_CAP io_cap)
+{
+
+    tBTA_DM_API_ADD_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->tm = trusted_mask;
+        p_msg->is_trusted = is_trusted;
+        p_msg->io_cap = io_cap;
+
+        if (link_key)
+        {
+            p_msg->link_key_known = TRUE;
+            p_msg->key_type = key_type;
+            memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+        }
+
+        /* Load device class if specified */
+        if (dev_class)
+        {
+            p_msg->dc_known = TRUE;
+            memcpy (p_msg->dc, dev_class, DEV_CLASS_LEN);
+        }
+
+        memset (p_msg->bd_name, 0, BD_NAME_LEN);
+        memset (p_msg->features, 0, BD_FEATURES_LEN);
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmRemoveDevice
+**
+** Description      This function removes a device fromthe security database list of
+**                  peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr)
+{
+    tBTA_DM_API_REMOVE_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_REMOVE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_REMOVE_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_REMOVE_DEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+    }
+    else
+    {
+        return BTA_FAILURE;
+    }
+
+    return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevWithName
+**
+** Description      This function is newer version of  BTA_DmAddDevice()
+**                  which added bd_name and features as input parameters.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
+                                      BD_NAME bd_name, BD_FEATURES features,
+                                      LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+                                      BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap)
+{
+    tBTA_DM_API_ADD_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_DEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->tm = trusted_mask;
+        p_msg->is_trusted = is_trusted;
+        p_msg->io_cap = io_cap;
+
+        if (link_key)
+        {
+            p_msg->link_key_known = TRUE;
+            p_msg->key_type = key_type;
+            memcpy(p_msg->link_key, link_key, LINK_KEY_LEN);
+        }
+
+        /* Load device class if specified */
+        if (dev_class)
+        {
+            p_msg->dc_known = TRUE;
+            memcpy (p_msg->dc, dev_class, DEV_CLASS_LEN);
+        }
+
+        if (bd_name)
+            memcpy(p_msg->bd_name, bd_name, BD_NAME_LEN);
+
+        if (features)
+            memcpy(p_msg->features, features, BD_FEATURES_LEN);
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAuthorizeReply
+**
+** Description      This function provides an authorization reply when authorization
+**                  is requested by BTA through BTA_DM_AUTHORIZE_EVT
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+void BTA_DmAuthorizeReply(BD_ADDR bd_addr, tBTA_SERVICE_ID service, tBTA_AUTH_RESP response)
+{
+
+    tBTA_DM_API_AUTH_REPLY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_AUTH_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_AUTH_REPLY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_AUTH_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->service = service;
+        p_msg->response = response;
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSignalStrength
+**
+** Description      This function initiates RSSI and channnel quality
+**                  measurments. BTA_DM_SIG_STRENGTH_EVT is sent to
+**                  application with the values of RSSI and channel
+**                  quality
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSignalStrength(tBTA_SIG_STRENGTH_MASK mask, UINT16 period, BOOLEAN start)
+{
+
+    tBTA_API_DM_SIG_STRENGTH    *p_msg;
+
+    if ((p_msg = (tBTA_API_DM_SIG_STRENGTH *) GKI_getbuf(sizeof(tBTA_API_DM_SIG_STRENGTH))) != NULL)
+    {
+        p_msg->hdr.event = BTA_API_DM_SIG_STRENGTH_EVT;
+        p_msg->mask = mask;
+        p_msg->period = period;
+        p_msg->start = start;
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmWriteInqTxPower
+**
+** Description      This command is used to write the inquiry transmit power level
+**                  used to transmit the inquiry (ID) data packets.
+**
+** Parameters       tx_power - tx inquiry power to use, valid value is -70 ~ 20
+
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmWriteInqTxPower(INT8 tx_power)
+{
+
+    tBTA_API_DM_TX_INQPWR    *p_msg;
+
+    if ((p_msg = (tBTA_API_DM_TX_INQPWR *) GKI_getbuf(sizeof(tBTA_API_DM_TX_INQPWR))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_TX_INQPWR_EVT;
+        p_msg->tx_power = tx_power;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmEirAddUUID
+**
+** Description      This function is called to add UUID into EIR.
+**
+** Parameters       tBT_UUID - UUID
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DmEirAddUUID (tBT_UUID *p_uuid)
+{
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    tBTA_DM_API_UPDATE_EIR_UUID    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_EIR_UUID))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_UPDATE_EIR_UUID_EVT;
+        p_msg->is_add    = TRUE;
+        memcpy (&(p_msg->uuid), p_uuid, sizeof(tBT_UUID));
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmEirRemoveUUID
+**
+** Description      This function is called to remove UUID from EIR.
+**
+** Parameters       tBT_UUID - UUID
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DmEirRemoveUUID (tBT_UUID *p_uuid)
+{
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    tBTA_DM_API_UPDATE_EIR_UUID    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_UPDATE_EIR_UUID *) GKI_getbuf(sizeof(tBTA_DM_API_UPDATE_EIR_UUID))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_UPDATE_EIR_UUID_EVT;
+        p_msg->is_add    = FALSE;
+        memcpy (&(p_msg->uuid), p_uuid, sizeof(tBT_UUID));
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEIRConfig
+**
+** Description      This function is called to override the BTA default EIR parameters.
+**                  This funciton is only valid in a system where BTU & App task
+**                  are in the same memory space.
+**
+** Parameters       Pointer to User defined EIR config
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_DmSetEIRConfig (tBTA_DM_EIR_CONF *p_eir_cfg)
+{
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+    tBTA_DM_API_SET_EIR_CONFIG  *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_SET_EIR_CONFIG *) GKI_getbuf(sizeof(tBTA_DM_API_SET_EIR_CONFIG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_SET_EIR_CONFIG_EVT;
+        p_msg->p_eir_cfg = p_eir_cfg;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_CheckEirData
+**
+** Description      This function is called to get EIR data from significant part.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  type   - finding EIR data type
+**                  p_length - return the length of EIR data
+**
+** Returns          pointer of EIR data
+**
+*******************************************************************************/
+UINT8 *BTA_CheckEirData( UINT8 *p_eir, UINT8 type, UINT8 *p_length )
+{
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+    return BTM_CheckEirData( p_eir, type, p_length );
+#else
+    return NULL;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GetEirService
+**
+** Description      This function is called to get BTA service mask from EIR.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  p_services - return the BTA service mask
+**
+** Returns          None
+**
+*******************************************************************************/
+extern const UINT16 bta_service_id_to_uuid_lkup_tbl [];
+void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services )
+{
+#if ( BTM_EIR_CLIENT_INCLUDED == TRUE )
+    UINT8 xx, yy;
+    UINT8 num_uuid, max_num_uuid = 32;
+    UINT8 uuid_list[32*LEN_UUID_16];
+    UINT16 *p_uuid16 = (UINT16 *)uuid_list;
+    tBTA_SERVICE_MASK mask;
+
+    BTM_GetEirUuidList( p_eir, LEN_UUID_16, &num_uuid, uuid_list, max_num_uuid);
+    for( xx = 0; xx < num_uuid; xx++ )
+    {
+        mask = 1;
+        for( yy = 0; yy < BTA_MAX_SERVICE_ID; yy++ )
+        {
+            if( *(p_uuid16 + xx) == bta_service_id_to_uuid_lkup_tbl[yy] )
+            {
+                *p_services |= mask;
+                break;
+            }
+            mask <<= 1;
+        }
+
+        /* for HSP v1.2 only device */
+        if (*(p_uuid16 + xx) == UUID_SERVCLASS_HEADSET_HS)
+            *p_services |= BTA_HSP_SERVICE_MASK;
+
+       if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SOURCE)
+            *p_services |= BTA_HL_SERVICE_MASK;
+
+        if (*(p_uuid16 + xx) == UUID_SERVCLASS_HDP_SINK)
+            *p_services |= BTA_HL_SERVICE_MASK;
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmUseSsr
+**
+** Description      This function is called to check if the connected peer device
+**                  supports SSR or not.
+**
+** Returns          TRUE, if SSR is supported
+**
+*******************************************************************************/
+BOOLEAN BTA_DmUseSsr( BD_ADDR bd_addr )
+{
+    BOOLEAN use_ssr = FALSE;
+    tBTA_DM_PEER_DEVICE * p_dev = bta_dm_find_peer_device(bd_addr);
+    if(p_dev && (p_dev->info & BTA_DM_DI_USE_SSR) )
+        use_ssr = TRUE;
+    return use_ssr;
+}
+
+/*******************************************************************************
+**                   Device Identification (DI) Server Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_DmSetLocalDiRecord
+**
+** Description      This function adds a DI record to the local SDP database.
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+                              UINT32 *p_handle )
+{
+    tBTA_STATUS  status = BTA_FAILURE;
+
+    if(bta_dm_di_cb.di_num < BTA_DI_NUM_MAX)
+    {
+        if(SDP_SetLocalDiRecord((tSDP_DI_RECORD *)p_device_info, p_handle) == SDP_SUCCESS)
+        {
+            if(!p_device_info->primary_record)
+            {
+                bta_dm_di_cb.di_handle[bta_dm_di_cb.di_num] = *p_handle;
+                bta_dm_di_cb.di_num ++;
+            }
+
+            bta_sys_add_uuid(UUID_SERVCLASS_PNP_INFORMATION);
+            status =  BTA_SUCCESS;
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetLocalDiRecord
+**
+** Description      Get a specified DI record to the local SDP database. If no
+**                  record handle is provided, the primary DI record will be
+**                  returned.
+**
+**                  Fills in the device information of the record
+**                  p_handle - if p_handle == 0, the primary record is returned
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetLocalDiRecord( tBTA_DI_GET_RECORD *p_device_info,
+                              UINT32 *p_handle )
+{
+    UINT16  status;
+
+    status = SDP_GetLocalDiRecord(p_device_info, p_handle);
+
+    if (status == SDP_SUCCESS)
+        return BTA_SUCCESS;
+    else
+        return BTA_FAILURE;
+
+}
+
+/*******************************************************************************
+**                   Device Identification (DI) Client Functions
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_DmDiDiscover
+**
+** Description      This function queries a remote device for DI information.
+**
+**
+** Returns          None.
+**
+*******************************************************************************/
+void BTA_DmDiDiscover( BD_ADDR remote_device, tBTA_DISCOVERY_DB *p_db,
+                       UINT32 len, tBTA_DM_SEARCH_CBACK *p_cback )
+{
+    tBTA_DM_API_DI_DISC    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_DI_DISC *) GKI_getbuf(sizeof(tBTA_DM_API_DI_DISC))) != NULL)
+    {
+        bdcpy(p_msg->bd_addr, remote_device);
+        p_msg->hdr.event    = BTA_DM_API_DI_DISCOVER_EVT;
+        p_msg->p_sdp_db     = p_db;
+        p_msg->len          = len;
+        p_msg->p_cback      = p_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetDiRecord
+**
+** Description      This function retrieves a remote device's DI record from
+**                  the specified database.
+**
+** Returns          BTA_SUCCESS if Get DI record is succeed.
+**                  BTA_FAILURE if Get DI record failed.
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetDiRecord( UINT8 get_record_index, tBTA_DI_GET_RECORD *p_device_info,
+                        tBTA_DISCOVERY_DB *p_db )
+{
+    if (SDP_GetDiRecord(get_record_index, p_device_info, p_db) != SDP_SUCCESS)
+        return BTA_FAILURE;
+    else
+        return BTA_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_SysFeatures
+**
+** Description      This function is called to set system features.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_SysFeatures (UINT16 sys_features)
+{
+    bta_sys_cb.sys_features = sys_features;
+
+    APPL_TRACE_API1("BTA_SysFeatures: sys_features = %d", sys_features);
+}
+
+/*******************************************************************************
+**
+** Function         bta_dmexecutecallback
+**
+** Description      This function will request BTA to execute a call back in the context of BTU task
+**                  This API was named in lower case because it is only intended
+**                  for the internal customers(like BTIF).
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param)
+{
+    tBTA_DM_API_EXECUTE_CBACK *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_EXECUTE_CBACK *) GKI_getbuf(sizeof(tBTA_DM_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_API_EXECUTE_CBACK_EVT;
+        p_msg->p_param= p_param;
+        p_msg->p_exec_cback= p_callback;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleKey
+**
+** Description      Add/modify LE device information.  This function will be
+**                  normally called during host startup to restore all required
+**                  information stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  p_le_key         - LE key values.
+**                  key_type         - LE SMP key type.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key, tBTA_LE_KEY_TYPE key_type)
+{
+#if BLE_INCLUDED == TRUE
+
+    tBTA_DM_API_ADD_BLEKEY *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_BLEKEY *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLEKEY))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLEKEY));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_BLEKEY_EVT;
+        p_msg->key_type = key_type;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        memcpy(&p_msg->blekey, p_le_key, sizeof(tBTA_LE_KEY_VALUE));
+
+        bta_sys_sendmsg(p_msg);
+    }
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleDevice
+**
+** Description      Add a BLE device.  This function will be normally called
+**                  during host startup to restore all required information
+**                  for a LE device stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  dev_type         - Remote device's device type.
+**                  addr_type        - LE device address type.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type, tBT_DEVICE_TYPE dev_type)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_ADD_BLE_DEVICE *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_ADD_BLE_DEVICE *) GKI_getbuf(sizeof(tBTA_DM_API_ADD_BLE_DEVICE))) != NULL)
+    {
+        memset (p_msg, 0, sizeof(tBTA_DM_API_ADD_BLE_DEVICE));
+
+        p_msg->hdr.event = BTA_DM_API_ADD_BLEDEVICE_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->addr_type = addr_type;
+        p_msg->dev_type = dev_type;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBlePasskeyReply
+**
+** Description      Send BLE SMP passkey reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - passkey entry sucessful or declined.
+**                  passkey          - passkey value, must be a 6 digit number,
+**                                     can be lead by 0.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_PASSKEY_REPLY    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_PASSKEY_REPLY *) GKI_getbuf(sizeof(tBTA_DM_API_PASSKEY_REPLY))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_PASSKEY_REPLY));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_PASSKEY_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+
+        if(accept)
+        {
+            p_msg->passkey = passkey;
+        }
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmBleSecurityGrant
+**
+** Description      Grant security request access.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  res              - security grant status.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_SEC_GRANT    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SEC_GRANT *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SEC_GRANT))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SEC_GRANT));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_SEC_GRANT_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->res = res;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmSetBlePrefConnParams
+**
+** Description      This function is called to set the preferred connection
+**                  parameters when default connection parameter is not desired.
+**
+** Parameters:      bd_addr          - BD address of the peripheral
+**                  scan_interval    - scan interval
+**                  scan_window      - scan window
+**                  min_conn_int     - minimum preferred connection interval
+**                  max_conn_int     - maximum preferred connection interval
+**                  slave_latency    - preferred slave latency
+**                  supervision_tout - preferred supervision timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+                               UINT16 min_conn_int, UINT16 max_conn_int,
+                               UINT16 slave_latency, UINT16 supervision_tout )
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_CONN_PARAMS    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_CONN_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_CONN_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_CONN_PARAMS));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_CONN_PARAM_EVT;
+
+        memcpy(p_msg->peer_bda, bd_addr, BD_ADDR_LEN);
+
+        p_msg->conn_int_max     = max_conn_int;
+        p_msg->conn_int_min     = min_conn_int;
+        p_msg->slave_latency    = slave_latency;
+        p_msg->supervision_tout = supervision_tout;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleConnScanParams
+**
+** Description      This function is called to set scan parameters used in
+**                  BLE connection request
+**
+** Parameters:      scan_interval    - scan interval
+**                  scan_window      - scan window
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetBleConnScanParams(UINT16 scan_interval, UINT16 scan_window )
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_SCAN_PARAMS    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SCAN_PARAMS *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SCAN_PARAMS))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SCAN_PARAMS));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_SCAN_PARAM_EVT;
+
+        p_msg->scan_int         = scan_interval;
+        p_msg->scan_window      = scan_window;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetBgConnType
+**
+** Description      This function is called to set BLE connectable mode for a
+**                  peripheral device.
+**
+** Parameters       bg_conn_type: it can be auto connection, or selective connection.
+**                  p_select_cback: callback function when selective connection procedure
+**                              is being used.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback)
+{
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_BLE_SET_BG_CONN_TYPE    *p_msg;
+
+    if ((p_msg = (tBTA_DM_API_BLE_SET_BG_CONN_TYPE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_SET_BG_CONN_TYPE));
+
+        p_msg->hdr.event        = BTA_DM_API_BLE_SET_BG_CONN_TYPE;
+        p_msg->bg_conn_type     = bg_conn_type;
+        p_msg->p_select_cback   = p_select_cback;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverExt
+**
+** Description      This function does service discovery for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; other wise a list of
+**                  UUID of interested services should be provided through
+**                  p_services->p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBTA_DM_API_DISCOVER    *p_msg;
+    UINT16  len = p_services ? (sizeof(tBTA_DM_API_DISCOVER) + sizeof(tBT_UUID) * p_services->num_uuid) :
+                    sizeof(tBTA_DM_API_DISCOVER);
+
+    if ((p_msg = (tBTA_DM_API_DISCOVER *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, len);
+
+        p_msg->hdr.event = BTA_DM_API_DISCOVER_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->p_cback = p_cback;
+        p_msg->sdp_search = sdp_search;
+
+        if (p_services != NULL)
+        {
+            p_msg->services = p_services->srvc_mask;
+            p_msg->num_uuid = p_services->num_uuid;
+
+            if (p_services->num_uuid != 0)
+            {
+                p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+                memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+            }
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchExt
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+** Parameters       p_dm_inq: inquiry conditions
+**                  p_services: if service is not empty, service discovery will be done.
+**                            for all GATT based service condition, put num_uuid, and
+**                            p_uuid is the pointer to the list of UUID values.
+**                  p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services, tBTA_DM_SEARCH_CBACK *p_cback)
+{
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    tBTA_DM_API_SEARCH    *p_msg;
+    UINT16  len = p_services ? (sizeof(tBTA_DM_API_SEARCH) + sizeof(tBT_UUID) * p_services->num_uuid) :
+                    sizeof(tBTA_DM_API_SEARCH);
+
+    if ((p_msg = (tBTA_DM_API_SEARCH *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_msg, 0, len);
+
+        p_msg->hdr.event = BTA_DM_API_SEARCH_EVT;
+        memcpy(&p_msg->inq_params, p_dm_inq, sizeof(tBTA_DM_INQ));
+        p_msg->p_cback = p_cback;
+        p_msg->rs_res  = BTA_DM_RS_NONE;
+
+
+        if (p_services != NULL)
+        {
+            p_msg->services = p_services->srvc_mask;
+            p_msg->num_uuid = p_services->num_uuid;
+
+            if (p_services->num_uuid != 0)
+            {
+                p_msg->p_uuid = (tBT_UUID *)(p_msg + 1);
+                memcpy(p_msg->p_uuid, p_services->p_uuid, sizeof(tBT_UUID) * p_services->num_uuid);
+            }
+            else
+                p_msg->p_uuid = NULL;
+        }
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEncryption
+**
+** Description      This function is called to ensure that connection is
+**                  encrypted.  Should be called only on an open connection.
+**                  Typically only needed for connections that first want to
+**                  bring up unencrypted links, then later encrypt them.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  p_callback    - Pointer to callback function to indicat the
+**                                  link encryption status
+**                  sec_act       - This is the security action to indicate
+**                                  what knid of BLE security level is required for
+**                                  the BLE link if the BLE is supported
+**                                  Note: This parameter is ignored for the BR/EDR link
+**                                        or the BLE is not supported
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
+                            tBTA_DM_BLE_SEC_ACT sec_act)
+{
+    tBTA_DM_API_SET_ENCRYPTION   *p_msg;
+
+    APPL_TRACE_API0("BTA_DmSetEncryption"); //todo
+    if ((p_msg = (tBTA_DM_API_SET_ENCRYPTION *) GKI_getbuf(sizeof(tBTA_DM_API_SET_ENCRYPTION))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_SET_ENCRYPTION));
+
+        p_msg->hdr.event = BTA_DM_API_SET_ENCRYPTION_EVT;
+
+        memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+        p_msg->p_callback      = p_callback;
+        p_msg->sec_act         = sec_act;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
new file mode 100644
index 0000000..5e26909
--- /dev/null
+++ b/bta/dm/bta_dm_cfg.c
@@ -0,0 +1,424 @@
+/******************************************************************************
+ *
+ *  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 compile-time configurable constants for the device
+ *  manager.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+
+#ifndef BTA_DM_LINK_POLICY_SETTINGS
+#define BTA_DM_LINK_POLICY_SETTINGS    (HCI_ENABLE_MASTER_SLAVE_SWITCH | HCI_ENABLE_HOLD_MODE | HCI_ENABLE_SNIFF_MODE | HCI_ENABLE_PARK_MODE)
+#endif
+
+/* page timeout in 625uS */
+#ifndef BTA_DM_PAGE_TIMEOUT
+#define BTA_DM_PAGE_TIMEOUT    8192
+#endif
+
+/* link supervision timeout in 625uS (5 secs) */
+#ifndef BTA_DM_LINK_TIMEOUT
+#define BTA_DM_LINK_TIMEOUT    8000
+#endif
+
+/* For Insight, PM cfg lookup tables are runtime configurable (to allow tweaking of params for power consumption measurements) */
+#ifndef BTE_SIM_APP
+#define tBTA_DM_PM_TYPE_QUALIFIER   const
+#else
+#define tBTA_DM_PM_TYPE_QUALIFIER
+#endif
+
+
+const tBTA_DM_CFG bta_dm_cfg =
+{
+    /* mobile phone COD */
+    BTA_DM_COD,
+    /* link policy settings */
+    BTA_DM_LINK_POLICY_SETTINGS,
+    /* page timeout in 625uS */
+    BTA_DM_PAGE_TIMEOUT,
+    /* link supervision timeout in 625uS*/
+    BTA_DM_LINK_TIMEOUT,
+    /* TRUE to avoid scatternet when av is streaming (be the master) */
+    TRUE
+};
+
+#ifndef BTA_DM_SCATTERNET
+/* By default, allow partial scatternet */
+#define BTA_DM_SCATTERNET BTA_DM_PARTIAL_SCATTERNET
+#endif
+
+#ifndef BTA_HH_ROLE
+/* By default, do not specify HH role (backward compatibility) */
+#define BTA_HH_ROLE BTA_ANY_ROLE
+#endif
+
+#ifndef BTA_AV_ROLE
+/* By default, AV role (backward BTA_MASTER_ROLE_PREF) */
+#define BTA_AV_ROLE BTA_MASTER_ROLE_PREF
+#endif
+
+#define BTA_DM_NUM_RM_ENTRY    4
+
+/* appids for PAN used by insight sample application
+   these have to be same as defined in btui_int.h */
+#define BTUI_PAN_ID_PANU         0
+#define BTUI_PAN_ID_NAP          1
+#define BTUI_PAN_ID_GN           2
+
+/* First element is always for SYS:
+   app_id = # of entries table, cfg is
+   device scatternet support */
+const tBTA_DM_RM bta_dm_rm_cfg[] =
+{
+    {BTA_ID_SYS, BTA_DM_NUM_RM_ENTRY, BTA_DM_SCATTERNET},
+    {BTA_ID_PAN, BTUI_PAN_ID_NAP, BTA_MASTER_ROLE_ONLY},
+    {BTA_ID_PAN, BTUI_PAN_ID_GN, BTA_MASTER_ROLE_ONLY},
+    {BTA_ID_HH,  BTA_ALL_APP_ID, BTA_HH_ROLE},
+    {BTA_ID_AV,  BTA_ALL_APP_ID, BTA_AV_ROLE}
+};
+
+
+tBTA_DM_CFG *p_bta_dm_cfg = (tBTA_DM_CFG *)&bta_dm_cfg;
+
+tBTA_DM_RM *p_bta_dm_rm_cfg = (tBTA_DM_RM *)&bta_dm_rm_cfg;
+
+
+#define BTA_DM_NUM_PM_ENTRY         (15+BTA_DM_NUM_JV_ID)  /* number of entries in bta_dm_pm_cfg except the first */
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG bta_dm_pm_cfg[] =
+{
+  {BTA_ID_SYS, BTA_DM_NUM_PM_ENTRY, 0},
+  {BTA_ID_AG,  BTA_ALL_APP_ID,      0},  /* ag uses first spec table for app id 0 */
+  {BTA_ID_CT,  1,                   1},  /* ct (BTA_ID_CT,APP ID=1) spec table */
+  {BTA_ID_CG,  BTA_ALL_APP_ID,      1},  /* cg resue ct spec table */
+  {BTA_ID_DG,  BTA_ALL_APP_ID,      2},  /* dg spec table */
+  {BTA_ID_AV,  BTA_ALL_APP_ID,      4},  /* av spec table */
+  {BTA_ID_FTC, BTA_ALL_APP_ID,      6},  /* ftc spec table */
+  {BTA_ID_FTS, BTA_ALL_APP_ID,      7},  /* fts spec table */
+  {BTA_ID_HD,  BTA_ALL_APP_ID,      3},  /* hd spec table */
+  {BTA_ID_HH,  BTA_ALL_APP_ID,      5},  /* hh spec table */
+  {BTA_ID_PBC, BTA_ALL_APP_ID,      2},  /* reuse dg spec table */
+  {BTA_ID_PBS, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_OPC, BTA_ALL_APP_ID,      6},  /* reuse ftc spec table */
+  {BTA_ID_OPS, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_MSE, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_JV1, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_JV2, BTA_ALL_APP_ID,      7},  /* reuse fts spec table */
+  {BTA_ID_HL,  BTA_ALL_APP_ID,      8}   /* reuse fts spec table */
+};
+
+
+#ifdef BTE_SIM_APP      /* For Insight builds only, see the detail below */
+#define BTA_DM_NUM_PM_SPEC      (9 + 2)  /* additional two */
+#else
+#define BTA_DM_NUM_PM_SPEC      9  /* additional JV*/
+#endif
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_SPEC bta_dm_pm_spec[BTA_DM_NUM_PM_SPEC] =
+{
+  /* AG */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn open sniff  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
+      {{BTA_DM_PM_SNIFF3, 5000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+      {{BTA_DM_PM_RETRY,  5000},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ },
+
+  /* CT */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                           /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_PARK,   5000},  {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  park */
+      {{BTA_DM_PM_NO_PREF,   0},  {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_SNIFF,  5000},  {BTA_DM_PM_NO_ACTION, 0}},    /* sco open sniff */
+      {{BTA_DM_PM_PARK,   5000},  {BTA_DM_PM_NO_ACTION, 0}},    /* sco close  park */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_NO_ACTION, 0},  {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_RETRY,  5000},  {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* DG */
+ {
+  (BTA_DM_PM_ACTIVE),                                             /* no power saving mode allowed */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* HD */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                            /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR3),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF4, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF2, 5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF4,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* AV */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* HH */
+ {
+  (BTA_DM_PM_SNIFF | BTA_DM_PM_PARK),                            /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR1),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF2, 7000},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  sniff */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close, used for HH suspend   */
+      {{BTA_DM_PM_SNIFF2, 7000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF2, 7000},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* FTC, OPC */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+  /* FTS, OPS */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn open  active */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},    /* conn close  */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco open  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},    /* sco close   */
+      {{BTA_DM_PM_SNIFF,  7000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
+  }
+ },
+
+   /* HL */
+ {
+  (BTA_DM_PM_SNIFF),                                             /* allow sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+  (BTA_DM_PM_SSR2),                                              /* the SSR entry */
+#endif
+  {
+      {{BTA_DM_PM_SNIFF,  5000},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn open sniff  */
+      {{BTA_DM_PM_NO_PREF,   0},   {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app open */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* app close */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco open, active */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* sco close sniff  */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}},   /* idle */
+      {{BTA_DM_PM_ACTIVE,    0},   {BTA_DM_PM_NO_ACTION, 0}},   /* busy */
+      {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}    /* mode change retry */
+  }
+ }
+
+#ifdef BTE_SIM_APP      /* For Insight builds only */
+ /* Entries at the end of the pm_spec table are user-defined (runtime configurable),
+    for power consumption experiments.
+    Insight finds the first user-defined entry by looking for the first BTA_DM_PM_NO_PREF.
+    The number of user_defined specs is defined by BTA_SWRAP_UD_PM_SPEC_COUNT */
+ ,
+ {BTA_DM_PM_NO_PREF},               /* pm_spec USER_DEFINED_0 */
+ {BTA_DM_PM_NO_PREF}                /* pm_spec USER_DEFINED_1 */
+#endif  /* BTE_SIM_APP */
+};
+
+tBTA_DM_PM_TYPE_QUALIFIER tBTM_PM_PWR_MD bta_dm_pm_md[] =
+{
+/* more sniff parameter entries can be added for BTA_DM_PM_SNIFF3 - BTA_DM_PM_SNIFF7, if needed
+When entries are added or removed, BTA_DM_PM_PARK_IDX needs to be updated to reflect the actual index
+BTA_DM_PM_PARK_IDX is defined in bta_api.h and can be override by the bdroid_buildcfg.h settings.
+The SNIFF table entries must be in the order from highest latency (biggest interval) to lowest latency.
+If there's a conflict among the connected services, the setting with lowest latency wins.
+*/
+/* sniff modes: max interval, min interval, attempt, timeout */
+  {800, 400, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF - A2DP */
+  {400, 200, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF1 */
+  {180, 150, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF2- HD idle */
+  {150,  50, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF3- SCO open */
+  { 54,  30, 4, 1, BTM_PM_MD_SNIFF}, /*for BTA_DM_PM_SNIFF4- HD active*/
+  {800, 400, 0, 0, BTM_PM_MD_PARK}
+
+#ifdef BTE_SIM_APP      /* For Insight builds only */
+  /* Entries at the end of the bta_dm_pm_md table are user-defined (runtime configurable),
+     for power consumption experiments.
+     Insight finds the first user-defined entry by looking for the first 'max=0'.
+     The number of user_defined specs is defined by BTA_SWRAP_UD_PM_DM_COUNT */
+  ,
+  {0},           /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_0 */
+  {0},           /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_0 */
+
+  {0},           /* CONN_OPEN/SCO_CLOSE power mode settings for pm_spec USER_DEFINED_1 */
+  {0}            /* SCO_OPEN power mode settings for pm_spec USER_DEFINED_1 */
+#endif  /* BTE_SIM_APP */
+};
+
+/* 0=max_lat -> no SSR */
+/* the smaller of the SSR max latency wins.
+ * the entries in this table must be from highest latency (biggest interval) to lowest latency */
+#if (BTM_SSR_INCLUDED == TRUE)
+tBTA_DM_SSR_SPEC bta_dm_ssr_spec[] =
+{
+    /*max_lat, min_rmt_to, min_loc_to*/
+    {0,      0, 0},     /* BTA_DM_PM_SSR0 - do not use SSR */
+    {1600,   2, 2},     /* BTA_DM_PM_SSR1 - HH */
+    {1200,   2, 2},     /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
+    {360,  160, 2}      /* BTA_DM_PM_SSR3 - HD */
+};
+
+tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec = (tBTA_DM_SSR_SPEC *)&bta_dm_ssr_spec;
+#endif
+
+tBTA_DM_PM_CFG *p_bta_dm_pm_cfg = (tBTA_DM_PM_CFG *)&bta_dm_pm_cfg;
+tBTA_DM_PM_SPEC *p_bta_dm_pm_spec = (tBTA_DM_PM_SPEC *)&bta_dm_pm_spec;
+tBTM_PM_PWR_MD *p_bta_dm_pm_md = (tBTM_PM_PWR_MD *)&bta_dm_pm_md;
+
+/* The performance impact of EIR packet size
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is TRUE,
+** 1 to 17 bytes,    DM1 is used and most robust.
+** 18 to 121 bytes,  DM3 is used but impacts inquiry scan time with large number
+**                    of devices.(almost double with 150 users)
+** 122 to 224 bytes, DM5 is used but cause quite big performance loss even with
+**                    small number of users. so it is not recommended.
+** 225 to 240 bytes, DH5 is used without FEC but it not recommended.
+**                    (same reason of DM5)
+**
+** When BTM_EIR_DEFAULT_FEC_REQUIRED is FALSE,
+** 1 to 27 bytes,    DH1 is used but only robust at short range.
+** 28 to 183 bytes,  DH3 is used but only robust at short range and impacts inquiry
+**                    scan time with large number of devices.
+** 184 to 240 bytes, DH5 is used but it not recommended.
+*/
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+                                            /* for example */
+const UINT8 bta_dm_eir_uuid16_list[] = {    0x08, 0x11, /* Headset */
+                                            0x1E, 0x11, /* Handsfree */
+                                            0x0E, 0x11, /* AV Remote Control */
+                                            0x0B, 0x11, /* Audio Sink */
+};
+#endif
+
+/* Extended Inquiry Response */
+const tBTA_DM_EIR_CONF bta_dm_eir_cfg =
+{
+    50,    /* minimum length of local name when it is shortened */
+           /* if length of local name is longer than this and EIR has not enough */
+           /* room for all UUID list then local name is shortened to this length */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    8,
+    (UINT8 *)bta_dm_eir_uuid16_list,
+#else
+    {   /* mask of UUID list in EIR */
+        0xFFFFFFFF, /* LSB is the first UUID of the first 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+        0xFFFFFFFF  /* LSB is the first UUID of the next 32 UUIDs in BTM_EIR_UUID_LKUP_TBL */
+        /* BTM_EIR_UUID_LKUP_TBL can be overrided */
+    },
+#endif
+    NULL,   /* Inquiry TX power         */
+    0,      /* length of flags in bytes */
+    NULL,   /* flags for EIR */
+    0,      /* length of manufacturer specific in bytes */
+    NULL,   /* manufacturer specific */
+};
+tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg = (tBTA_DM_EIR_CONF*)&bta_dm_eir_cfg;
+#endif
diff --git a/bta/dm/bta_dm_ci.c b/bta/dm/bta_dm_ci.c
new file mode 100644
index 0000000..5e2e312
--- /dev/null
+++ b/bta/dm/bta_dm_ci.c
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ *  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 is the API implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include <string.h>
+#include "bta_dm_ci.h"
+
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_io_req(), if *p_oob_data to BTA_OOB_UNKNOWN
+**                  by bta_dm_co_io_req().
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap, tBTA_OOB_DATA oob_data,
+                                     tBTA_AUTH_REQ auth_req)
+
+{
+    tBTA_DM_CI_IO_REQ    *p_msg;
+
+    if ((p_msg = (tBTA_DM_CI_IO_REQ *) GKI_getbuf(sizeof(tBTA_DM_CI_IO_REQ))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_CI_IO_REQ_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->io_cap   = io_cap;
+        p_msg->oob_data = oob_data;
+        p_msg->auth_req = auth_req;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_rmt_oob() to provide the OOB data associated
+**                  with the remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
+{
+    tBTA_DM_CI_RMT_OOB    *p_msg;
+
+    if ((p_msg = (tBTA_DM_CI_RMT_OOB *) GKI_getbuf(sizeof(tBTA_DM_CI_RMT_OOB))) != NULL)
+    {
+        p_msg->hdr.event = BTA_DM_CI_RMT_OOB_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept    = accept;
+        memcpy(p_msg->c, c, BT_OCTET16_LEN);
+        memcpy(p_msg->r, r, BT_OCTET16_LEN);
+        bta_sys_sendmsg(p_msg);
+    }
+}
+#endif /* BTM_OOB_INCLUDED */
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_sco_ci_data_ready
+**
+** Description      This function sends an event to indicating that the phone
+**                  has SCO data ready.
+**
+** Parameters       event: is obtained from bta_dm_sco_co_open() function, which
+**                          is the BTA event we want to send back to BTA module
+**                          when there is encoded data ready.
+**                  sco_handle: is the BTA sco handle which indicate a specific
+**                           SCO connection.
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = event;
+        p_buf->layer_specific = sco_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+#endif
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
new file mode 100644
index 0000000..35b369d
--- /dev/null
+++ b/bta/dm/bta_dm_int.h
@@ -0,0 +1,989 @@
+/******************************************************************************
+ *
+ *  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 is the private interface file for the BTA device manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_INT_H
+#define BTA_DM_INT_H
+
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    #include "bta_gatt_api.h"
+#endif
+
+
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+
+#define BTA_COPY_DEVICE_CLASS(coddst, codsrc)   {((UINT8 *)(coddst))[0] = ((UINT8 *)(codsrc))[0]; \
+                                                 ((UINT8 *)(coddst))[1] = ((UINT8 *)(codsrc))[1];  \
+                                                 ((UINT8 *)(coddst))[2] = ((UINT8 *)(codsrc))[2];}
+
+
+#define BTA_DM_MSG_LEN 50
+
+#define BTA_SERVICE_ID_TO_SERVICE_MASK(id)       (1 << (id))
+
+/* DM events */
+enum
+{
+    /* device manager local device API events */
+    BTA_DM_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_DM),
+    BTA_DM_API_DISABLE_EVT,
+    BTA_DM_API_SET_NAME_EVT,
+    BTA_DM_API_SET_VISIBILITY_EVT,
+    BTA_DM_API_SET_AFH_CHANNELS_EVT,
+    BTA_API_DM_SIG_STRENGTH_EVT,
+    BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT,
+    BTA_DM_API_TX_INQPWR_EVT,
+    BTA_DM_ACL_CHANGE_EVT,
+    BTA_DM_API_ADD_DEVICE_EVT,
+
+    /* security API events */
+    BTA_DM_API_BOND_EVT,
+    BTA_DM_API_BOND_CANCEL_EVT,
+    BTA_DM_API_PIN_REPLY_EVT,
+    BTA_DM_API_LINK_POLICY_EVT,
+    BTA_DM_API_AUTH_REPLY_EVT,
+
+    /* power manger events */
+    BTA_DM_PM_BTM_STATUS_EVT,
+    BTA_DM_PM_TIMER_EVT,
+
+    /* simple pairing events */
+    BTA_DM_API_CONFIRM_EVT,
+
+    BTA_DM_API_SET_ENCRYPTION_EVT,
+
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    BTA_DM_API_PASKY_CANCEL_EVT,
+#endif
+#if (BTM_OOB_INCLUDED == TRUE)
+    BTA_DM_API_LOC_OOB_EVT,
+    BTA_DM_CI_IO_REQ_EVT,
+    BTA_DM_CI_RMT_OOB_EVT,
+#endif /* BTM_OOB_INCLUDED */
+
+    BTA_DM_API_REMOVE_DEVICE_EVT,
+
+#if BLE_INCLUDED == TRUE
+    BTA_DM_API_ADD_BLEKEY_EVT,
+    BTA_DM_API_ADD_BLEDEVICE_EVT,
+    BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
+    BTA_DM_API_BLE_SEC_GRANT_EVT,
+    BTA_DM_API_BLE_SET_BG_CONN_TYPE,
+    BTA_DM_API_BLE_CONN_PARAM_EVT,
+    BTA_DM_API_BLE_SCAN_PARAM_EVT,
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    BTA_DM_API_UPDATE_EIR_UUID_EVT,
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+    BTA_DM_API_SET_EIR_CONFIG_EVT,
+#endif
+
+    BTA_DM_API_ENABLE_TEST_MODE_EVT,
+    BTA_DM_API_DISABLE_TEST_MODE_EVT,
+    BTA_DM_API_EXECUTE_CBACK_EVT,
+    BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT,
+    BTA_DM_MAX_EVT
+};
+
+
+/* DM search events */
+enum
+{
+    /* DM search API events */
+    BTA_DM_API_SEARCH_EVT = BTA_SYS_EVT_START(BTA_ID_DM_SEARCH),
+    BTA_DM_API_SEARCH_CANCEL_EVT,
+    BTA_DM_API_DISCOVER_EVT,
+    BTA_DM_INQUIRY_CMPL_EVT,
+    BTA_DM_REMT_NAME_EVT,
+    BTA_DM_SDP_RESULT_EVT,
+    BTA_DM_SEARCH_CMPL_EVT,
+    BTA_DM_DISCOVERY_RESULT_EVT,
+    BTA_DM_API_DI_DISCOVER_EVT
+
+};
+
+/* data type for BTA_DM_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_DM_SEC_CBACK *p_sec_cback;
+} tBTA_DM_API_ENABLE;
+
+/* data type for BTA_DM_API_SET_NAME_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    char    name[BD_NAME_LEN];
+} tBTA_DM_API_SET_NAME;
+
+/* data type for BTA_DM_API_SET_VISIBILITY_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_DM_DISC    disc_mode;
+    tBTA_DM_CONN    conn_mode;
+    UINT8           pair_mode;
+    UINT8           conn_paired_only;
+} tBTA_DM_API_SET_VISIBILITY;
+
+/* data type for BTA_DM_API_SET_AFH_CHANNELS_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8           first;
+    UINT8           last;
+} tBTA_DM_API_SET_AFH_CHANNELS_EVT;
+
+/* data type for BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              opcode;
+    UINT8               param_len;
+    UINT8               *p_param_buf;
+    tBTA_VENDOR_CMPL_CBACK *p_cback;
+
+} tBTA_DM_API_VENDOR_SPECIFIC_COMMAND;
+
+enum
+{
+    BTA_DM_RS_NONE,     /* straight API call */
+    BTA_DM_RS_OK,       /* the role switch result - successful */
+    BTA_DM_RS_FAIL      /* the role switch result - failed */
+};
+typedef UINT8 tBTA_DM_RS_RES;
+
+/* data type for BTA_DM_API_SEARCH_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_INQ inq_params;
+    tBTA_SERVICE_MASK services;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+    tBTA_DM_RS_RES  rs_res;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT8           num_uuid;
+    tBT_UUID        *p_uuid;
+#endif
+} tBTA_DM_API_SEARCH;
+
+/* data type for BTA_DM_API_DISCOVER_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    tBTA_SERVICE_MASK services;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+    BOOLEAN         sdp_search;
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+    UINT8           num_uuid;
+    tBT_UUID        *p_uuid;
+#endif
+    tSDP_UUID    uuid;
+} tBTA_DM_API_DISCOVER;
+
+/* data type for BTA_DM_API_DI_DISC_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    tBTA_DISCOVERY_DB   *p_sdp_db;
+    UINT32              len;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_DI_DISC;
+
+/* data type for BTA_DM_API_BOND_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+} tBTA_DM_API_BOND;
+
+/* data type for BTA_DM_API_BOND_CANCEL_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+} tBTA_DM_API_BOND_CANCEL;
+
+/* data type for BTA_DM_API_PIN_REPLY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    BOOLEAN accept;
+    UINT8 pin_len;
+    UINT8 p_pin[PIN_CODE_LEN];
+} tBTA_DM_API_PIN_REPLY;
+
+/* data type for BTA_DM_API_LINK_POLICY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    UINT16      policy_mask;
+    BOOLEAN     set;
+} tBTA_DM_API_LINK_POLICY;
+
+/* data type for BTA_DM_API_AUTH_REPLY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    tBTA_SERVICE_ID service;
+    tBTA_AUTH_RESP response;
+} tBTA_DM_API_AUTH_REPLY;
+
+/* data type for BTA_DM_API_LOC_OOB_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+} tBTA_DM_API_LOC_OOB;
+
+/* data type for BTA_DM_API_CONFIRM_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BOOLEAN     accept;
+} tBTA_DM_API_CONFIRM;
+
+/* data type for BTA_DM_API_PASKY_CANCEL_EVT*/
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+} tBTA_DM_API_PASKY_CANCEL;
+
+/* data type for BTA_DM_CI_IO_REQ_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTA_IO_CAP     io_cap;
+    tBTA_OOB_DATA   oob_data;
+    tBTA_AUTH_REQ   auth_req;
+} tBTA_DM_CI_IO_REQ;
+
+/* data type for BTA_DM_CI_RMT_OOB_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BT_OCTET16  c;
+    BT_OCTET16  r;
+    BOOLEAN     accept;
+} tBTA_DM_CI_RMT_OOB;
+
+/* data type for BTA_DM_REMT_NAME_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_SEARCH  result;
+} tBTA_DM_REM_NAME;
+
+/* data type for tBTA_DM_DISC_RESULT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_DM_SEARCH  result;
+} tBTA_DM_DISC_RESULT;
+
+
+/* data type for BTA_DM_INQUIRY_CMPL_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT8       num;
+} tBTA_DM_INQUIRY_CMPL;
+
+/* data type for BTA_DM_SDP_RESULT_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT16 sdp_result;
+} tBTA_DM_SDP_RESULT;
+
+/* data type for BTA_API_DM_SIG_STRENGTH_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    tBTA_SIG_STRENGTH_MASK mask;
+    UINT16 period;
+    BOOLEAN start;
+} tBTA_API_DM_SIG_STRENGTH;
+
+/* data type for tBTA_API_DM_TX_INQPWR */
+typedef struct
+{
+    BT_HDR      hdr;
+    INT8        tx_power;
+}tBTA_API_DM_TX_INQPWR;
+
+/* data type for BTA_DM_ACL_CHANGE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTM_BL_EVENT   event;
+    UINT8           busy_level;
+    BOOLEAN         is_new;
+    UINT8           new_role;
+    BD_ADDR         bd_addr;
+    UINT8           hci_status;
+} tBTA_DM_ACL_CHANGE;
+
+/* data type for BTA_DM_PM_BTM_STATUS_EVT */
+typedef struct
+{
+
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    tBTM_PM_STATUS  status;
+    UINT16          value;
+    UINT8           hci_status;
+
+} tBTA_DM_PM_BTM_STATUS;
+
+/* data type for BTA_DM_PM_TIMER_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+
+} tBTA_DM_PM_TIMER;
+
+
+/* data type for BTA_DM_API_ADD_DEVICE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+    DEV_CLASS           dc;
+    LINK_KEY            link_key;
+    tBTA_SERVICE_MASK   tm;
+    BOOLEAN             is_trusted;
+    UINT8               key_type;
+    tBTA_IO_CAP         io_cap;
+    BOOLEAN             link_key_known;
+    BOOLEAN             dc_known;
+    BD_NAME             bd_name;
+    BD_FEATURES         features;
+} tBTA_DM_API_ADD_DEVICE;
+
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bd_addr;
+} tBTA_DM_API_REMOVE_DEVICE;
+
+/* data type for BTA_DM_API_EXECUTE_CBACK_EVT */
+typedef struct
+{
+    BT_HDR               hdr;
+    void *               p_param;
+    tBTA_DM_EXEC_CBACK  *p_exec_cback;
+} tBTA_DM_API_EXECUTE_CBACK;
+
+/* data type for tBTA_DM_API_SET_ENCRYPTION */
+typedef struct
+{
+    BT_HDR                    hdr;
+    tBTA_DM_ENCRYPT_CBACK     *p_callback;
+    tBTA_DM_BLE_SEC_ACT       sec_act;
+    BD_ADDR                   bd_addr;
+} tBTA_DM_API_SET_ENCRYPTION;
+
+#if BLE_INCLUDED == TRUE
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBTA_LE_KEY_VALUE       blekey;
+    tBTA_LE_KEY_TYPE        key_type;
+
+}tBTA_DM_API_ADD_BLEKEY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBT_DEVICE_TYPE         dev_type ;
+    tBLE_ADDR_TYPE          addr_type;
+
+}tBTA_DM_API_ADD_BLE_DEVICE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    BOOLEAN                 accept;
+    UINT32                  passkey;
+}tBTA_DM_API_PASSKEY_REPLY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 bd_addr;
+    tBTA_DM_BLE_SEC_GRANT   res;
+}tBTA_DM_API_BLE_SEC_GRANT;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_DM_BLE_CONN_TYPE   bg_conn_type;
+    tBTA_DM_BLE_SEL_CBACK   *p_select_cback;
+}tBTA_DM_API_BLE_SET_BG_CONN_TYPE;
+
+/* set prefered BLE connection parameters for a device */
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 peer_bda;
+    UINT16                  conn_int_min;
+    UINT16                  conn_int_max;
+    UINT16                  supervision_tout;
+    UINT16                  slave_latency;
+
+}tBTA_DM_API_BLE_CONN_PARAMS;
+
+/* set scan parameter for BLE connections */
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  scan_int;
+    UINT16                  scan_window;
+}tBTA_DM_API_BLE_SCAN_PARAMS;
+
+#endif
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 enable_or_disable;
+}tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT;
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+/* data type for BTA_DM_API_UPDATE_EIR_UUID_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    BOOLEAN         is_add;
+    tBT_UUID        uuid;
+}tBTA_DM_API_UPDATE_EIR_UUID;
+#endif
+
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+/* data type for BTA_DM_API_SET_EIR_CONFIG_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_DM_EIR_CONF    *p_eir_cfg;
+}tBTA_DM_API_SET_EIR_CONFIG;
+#endif
+
+/* union of all data types */
+typedef union
+{
+    /* GKI event buffer header */
+    BT_HDR              hdr;
+    tBTA_DM_API_ENABLE  enable;
+
+    tBTA_DM_API_SET_NAME set_name;
+
+    tBTA_DM_API_SET_VISIBILITY set_visibility;
+
+    tBTA_DM_API_SET_AFH_CHANNELS_EVT set_afhchannels;
+
+    tBTA_DM_API_VENDOR_SPECIFIC_COMMAND vendor_command;
+
+    tBTA_DM_API_ADD_DEVICE  add_dev;
+
+    tBTA_DM_API_REMOVE_DEVICE remove_dev;
+
+    tBTA_DM_API_SEARCH search;
+
+    tBTA_DM_API_DISCOVER discover;
+
+    tBTA_DM_API_BOND bond;
+
+    tBTA_DM_API_BOND_CANCEL bond_cancel;
+
+    tBTA_DM_API_PIN_REPLY pin_reply;
+    tBTA_DM_API_LINK_POLICY link_policy;
+
+    tBTA_DM_API_LOC_OOB     loc_oob;
+    tBTA_DM_API_CONFIRM     confirm;
+    tBTA_DM_API_PASKY_CANCEL passkey_cancel;
+    tBTA_DM_CI_IO_REQ       ci_io_req;
+    tBTA_DM_CI_RMT_OOB      ci_rmt_oob;
+
+    tBTA_DM_API_AUTH_REPLY auth_reply;
+
+    tBTA_DM_REM_NAME rem_name;
+
+    tBTA_DM_DISC_RESULT disc_result;
+
+    tBTA_DM_INQUIRY_CMPL inq_cmpl;
+
+    tBTA_DM_SDP_RESULT sdp_event;
+
+    tBTA_API_DM_SIG_STRENGTH sig_strength;
+
+    tBTA_API_DM_TX_INQPWR   tx_inq_pwr;
+
+    tBTA_DM_ACL_CHANGE  acl_change;
+
+    tBTA_DM_PM_BTM_STATUS pm_status;
+
+    tBTA_DM_PM_TIMER pm_timer;
+
+    tBTA_DM_API_DI_DISC     di_disc;
+
+    tBTA_DM_API_EXECUTE_CBACK exec_cback;
+
+    tBTA_DM_API_SET_ENCRYPTION     set_encryption;
+
+#if BLE_INCLUDED == TRUE
+    tBTA_DM_API_ADD_BLEKEY              add_ble_key;
+    tBTA_DM_API_ADD_BLE_DEVICE          add_ble_device;
+    tBTA_DM_API_PASSKEY_REPLY           ble_passkey_reply;
+    tBTA_DM_API_BLE_SEC_GRANT           ble_sec_grant;
+    tBTA_DM_API_BLE_SET_BG_CONN_TYPE    ble_set_bd_conn_type;
+    tBTA_DM_API_BLE_CONN_PARAMS         ble_set_conn_params;
+    tBTA_DM_API_BLE_SCAN_PARAMS         ble_set_scan_params;
+#endif
+
+    tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    tBTA_DM_API_UPDATE_EIR_UUID     update_eir_uuid;
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+    tBTA_DM_API_SET_EIR_CONFIG          set_eir_cfg;
+#endif
+
+} tBTA_DM_MSG;
+
+
+#define BTA_DM_NUM_PEER_DEVICE 7
+
+#define BTA_DM_NOT_CONNECTED  0
+#define BTA_DM_CONNECTED      1
+#define BTA_DM_UNPAIRING      2
+typedef UINT8 tBTA_DM_CONN_STATE;
+
+
+#define BTA_DM_DI_NONE          0x00       /* nothing special */
+#define BTA_DM_DI_USE_SSR       0x10       /* set this bit if ssr is supported for this link */
+#define BTA_DM_DI_AV_ACTIVE     0x20       /* set this bit if AV is active for this link */
+#define BTA_DM_DI_SET_SNIFF     0x01       /* set this bit if call BTM_SetPowerMode(sniff) */
+#define BTA_DM_DI_INT_SNIFF     0x02       /* set this bit if call BTM_SetPowerMode(sniff) & enter sniff mode */
+#define BTA_DM_DI_ACP_SNIFF     0x04       /* set this bit if peer init sniff */
+typedef UINT8 tBTA_DM_DEV_INFO;
+
+typedef struct
+{
+    BD_ADDR                     peer_bdaddr;
+    UINT16                      link_policy;
+    tBTA_DM_CONN_STATE          conn_state;
+    tBTA_PREF_ROLES             pref_role;
+    BOOLEAN                     in_use;
+    tBTA_DM_DEV_INFO            info;
+#if (BTM_SSR_INCLUDED == TRUE)
+    tBTM_PM_STATUS              prev_low;   /* previous low power mode used */
+#endif
+    tBTA_DM_PM_ACTTION          pm_mode_attempted;
+    tBTA_DM_PM_ACTTION          pm_mode_failed;
+
+} tBTA_DM_PEER_DEVICE;
+
+
+
+/* structure to store list of
+  active connections */
+typedef struct
+{
+    tBTA_DM_PEER_DEVICE    peer_device[BTA_DM_NUM_PEER_DEVICE];
+    UINT8                  count;
+
+} tBTA_DM_ACTIVE_LINK;
+
+
+typedef struct
+{
+    BD_ADDR                 peer_bdaddr;
+    tBTA_SYS_ID             id;
+    UINT8                   app_id;
+    tBTA_SYS_CONN_STATUS    state;
+
+
+} tBTA_DM_SRVCS;
+
+#define BTA_DM_NUM_CONN_SRVS   5
+
+typedef struct
+{
+
+    UINT8 count;
+    tBTA_DM_SRVCS  conn_srvc[BTA_DM_NUM_CONN_SRVS];
+
+}  tBTA_DM_CONNECTED_SRVCS;
+
+typedef struct
+{
+    TIMER_LIST_ENT          timer;
+    BD_ADDR                 peer_bdaddr;
+    BOOLEAN                 in_use;
+
+} tBTA_PM_TIMER;
+
+extern tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+#define BTA_DM_NUM_PM_TIMER 3
+
+/* DM control block */
+typedef struct
+{
+    BOOLEAN                     is_bta_dm_active;
+    tBTA_DM_ACTIVE_LINK         device_list;
+    tBTA_DM_SEC_CBACK           *p_sec_cback;
+    TIMER_LIST_ENT              signal_strength_timer;
+    tBTA_SIG_STRENGTH_MASK      signal_strength_mask;
+    UINT16                      state;
+    UINT16                      signal_strength_period;
+    BOOLEAN                     disabling;
+    TIMER_LIST_ENT              disable_timer;
+    UINT32                      wbt_sdp_handle;          /* WIDCOMM Extensions SDP record handle */
+    UINT8                       wbt_scn;                 /* WIDCOMM Extensions SCN */
+    UINT8                       num_master_only;
+    UINT8                       pm_id;
+    tBTA_PM_TIMER               pm_timer[BTA_DM_NUM_PM_TIMER];
+    UINT32                      role_policy_mask;   /* the bits set indicates the modules that wants to remove role switch from the default link policy */
+    UINT16                      cur_policy;         /* current default link policy */
+    UINT16                      rs_event;           /* the event waiting for role switch */
+    UINT8                       cur_av_count;       /* current AV connecions */
+    BOOLEAN                     disable_pair_mode;          /* disable pair mode or not */
+    BOOLEAN                     conn_paired_only;   /* allow connectable to paired device only or not */
+    tBTA_DM_API_SEARCH          search_msg;
+    UINT16                      page_scan_interval;
+    UINT16                      page_scan_window;
+    UINT16                      inquiry_scan_interval;
+    UINT16                      inquiry_scan_window;
+
+    /* Storage for pin code request parameters */
+    BD_ADDR                     pin_bd_addr;
+    DEV_CLASS                   pin_dev_class;
+    tBTA_DM_SEC_EVT             pin_evt;
+    UINT32          num_val;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+    BOOLEAN         just_works;     /* TRUE, if "Just Works" association model */
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )
+    /* store UUID list for EIR */
+    TIMER_LIST_ENT              app_ready_timer;
+    UINT32                      eir_uuid[BTM_EIR_SERVICE_ARRAY_SIZE];
+#if (BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    tBT_UUID                    custom_uuid[BTA_EIR_SERVER_NUM_CUSTOM_UUID];
+#endif
+
+#endif
+
+    tBTA_DM_ENCRYPT_CBACK      *p_encrypt_cback;
+    tBTA_DM_BLE_SEC_ACT         sec_act;
+    TIMER_LIST_ENT              switch_delay_timer;
+
+} tBTA_DM_CB;
+
+#ifndef BTA_DM_SDP_DB_SIZE
+#define BTA_DM_SDP_DB_SIZE 250
+#endif
+
+/* DM search control block */
+typedef struct
+{
+
+    tBTA_DM_SEARCH_CBACK * p_search_cback;
+    tBTM_INQ_INFO        * p_btm_inq_info;
+    tBTA_SERVICE_MASK      services;
+    tBTA_SERVICE_MASK      services_to_search;
+    tBTA_SERVICE_MASK      services_found;
+    tSDP_DISCOVERY_DB    * p_sdp_db;
+    UINT16                 state;
+    BD_ADDR                peer_bdaddr;
+    BOOLEAN                name_discover_done;
+    char                   peer_name[BD_NAME_LEN];
+    TIMER_LIST_ENT         search_timer;
+    UINT8                  service_index;
+    tBTA_DM_MSG          * p_search_queue;   /* search or discover commands during search cancel stored here */
+    BOOLEAN                wait_disc;
+    BOOLEAN                sdp_results;
+    tSDP_UUID              uuid;
+    UINT8                  peer_scn;
+    BOOLEAN                sdp_search;
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    tBTA_GATTC_IF          client_if;
+    UINT8                  num_uuid;
+    tBT_UUID               *p_srvc_uuid;
+    UINT8                  uuid_to_search;
+    BOOLEAN                gatt_disc_active;
+    UINT16                 conn_id;
+    UINT8 *                 p_ble_rawdata;
+    UINT32                 ble_raw_size;
+    UINT32                 ble_raw_used;
+#endif
+#endif
+
+
+} tBTA_DM_SEARCH_CB;
+
+/* DI control block */
+typedef struct
+{
+    tSDP_DISCOVERY_DB    * p_di_db;     /* pointer to the DI discovery database */
+    UINT8               di_num;         /* total local DI record number */
+    UINT32              di_handle[BTA_DI_NUM_MAX];  /* local DI record handle, the first one is primary record */
+}tBTA_DM_DI_CB;
+
+/* DM search state */
+enum
+{
+
+    BTA_DM_SEARCH_IDLE,
+    BTA_DM_SEARCH_ACTIVE,
+    BTA_DM_SEARCH_CANCELLING,
+    BTA_DM_DISCOVER_ACTIVE
+
+};
+
+
+
+typedef struct
+{
+    DEV_CLASS      dev_class;          /* local device class */
+    UINT16         policy_settings;    /* link policy setting hold, sniff, park, MS switch */
+    UINT16         page_timeout;       /* timeout for page in slots */
+    UINT16         link_timeout;       /* link supervision timeout in slots */
+    BOOLEAN        avoid_scatter;      /* TRUE to avoid scatternet when av is streaming (be the master) */
+
+} tBTA_DM_CFG;
+
+extern const UINT32 bta_service_id_to_btm_srv_id_lkup_tbl[];
+
+extern const tBTA_DM_CFG bta_dm_cfg;
+
+
+
+#define BTA_ALL_APP_ID 0xff
+
+typedef struct
+{
+    UINT8   id;
+    UINT8   app_id;
+    UINT8   cfg;
+
+} tBTA_DM_RM ;
+
+extern tBTA_DM_CFG *p_bta_dm_cfg;
+extern tBTA_DM_RM *p_bta_dm_rm_cfg;
+
+typedef struct
+{
+
+  UINT8  id;
+  UINT8  app_id;
+  UINT8  spec_idx;  /* index of spec table to use */
+
+} tBTA_DM_PM_CFG;
+
+
+typedef struct
+{
+
+  tBTA_DM_PM_ACTTION  power_mode;
+  UINT16              timeout;
+
+} tBTA_DM_PM_ACTN;
+
+typedef struct
+{
+
+  UINT8  allow_mask;         /* mask of sniff/hold/park modes to allow */
+#if (BTM_SSR_INCLUDED == TRUE)
+  UINT8  ssr;                /* set SSR on conn open/unpark */
+#endif
+  tBTA_DM_PM_ACTN actn_tbl [BTA_DM_PM_NUM_EVTS][2];
+
+} tBTA_DM_PM_SPEC;
+
+typedef struct
+{
+    UINT16      max_lat;
+    UINT16      min_rmt_to;
+    UINT16      min_loc_to;
+} tBTA_DM_SSR_SPEC;
+
+typedef struct
+{
+   UINT16 manufacturer;
+   UINT16 lmp_sub_version;
+   UINT8 lmp_version;
+}tBTA_DM_LMP_VER_INFO;
+
+extern tBTA_DM_PM_CFG *p_bta_dm_pm_cfg;
+extern tBTA_DM_PM_SPEC *p_bta_dm_pm_spec;
+extern tBTM_PM_PWR_MD *p_bta_dm_pm_md;
+#if (BTM_SSR_INCLUDED == TRUE)
+extern tBTA_DM_SSR_SPEC *p_bta_dm_ssr_spec;
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+/* update dynamic BRCM Aware EIR data */
+extern const tBTA_DM_EIR_CONF bta_dm_eir_cfg;
+extern tBTA_DM_EIR_CONF *p_bta_dm_eir_cfg;
+#endif
+
+/* DM control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_CB  bta_dm_cb;
+#else
+extern tBTA_DM_CB *bta_dm_cb_ptr;
+#define bta_dm_cb (*bta_dm_cb_ptr)
+#endif
+
+/* DM search control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_SEARCH_CB  bta_dm_search_cb;
+#else
+extern tBTA_DM_SEARCH_CB *bta_dm_search_cb_ptr;
+#define bta_dm_search_cb (*bta_dm_search_cb_ptr)
+#endif
+
+/* DI control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_DM_DI_CB  bta_dm_di_cb;
+#else
+extern tBTA_DM_DI_CB *bta_dm_di_cb_ptr;
+#define bta_dm_di_cb (*bta_dm_di_cb_ptr)
+#endif
+
+extern BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_sm_disable( void );
+extern BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg);
+extern void bta_dm_search_sm_disable( void );
+
+
+extern void bta_dm_enable (tBTA_DM_MSG *p_data);
+extern void bta_dm_disable (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_dev_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_visibility (tBTA_DM_MSG *p_data);
+extern void bta_dm_set_afhchannels (tBTA_DM_MSG *p_data);
+extern void bta_dm_vendor_spec_command(tBTA_DM_MSG *p_data);
+extern void bta_dm_bond (tBTA_DM_MSG *p_data);
+extern void bta_dm_bond_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_pin_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_link_policy (tBTA_DM_MSG *p_data);
+extern void bta_dm_auth_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_signal_strength(tBTA_DM_MSG *p_data);
+extern void bta_dm_tx_inqpower(tBTA_DM_MSG *p_data);
+extern void bta_dm_acl_change(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_remove_device (tBTA_DM_MSG *p_data);
+
+
+extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
+extern void bta_dm_pm_timer(tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data);
+
+#if BLE_INCLUDED == TRUE
+extern void bta_dm_add_blekey (tBTA_DM_MSG *p_data);
+extern void bta_dm_add_ble_device (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_set_scan_params (tBTA_DM_MSG *p_data);
+#endif
+extern void bta_dm_set_encryption(tBTA_DM_MSG *p_data);
+extern void bta_dm_confirm(tBTA_DM_MSG *p_data);
+extern void bta_dm_passkey_cancel(tBTA_DM_MSG *p_data);
+#if (BTM_OOB_INCLUDED == TRUE)
+extern void bta_dm_loc_oob(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_io_req_act(tBTA_DM_MSG *p_data);
+extern void bta_dm_ci_rmt_oob_act(tBTA_DM_MSG *p_data);
+#endif /* BTM_OOB_INCLUDED */
+
+extern void bta_dm_init_pm(void);
+extern void bta_dm_disable_pm(void);
+
+extern void bta_dm_search_start (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel (tBTA_DM_MSG *p_data);
+extern void bta_dm_discover (tBTA_DM_MSG *p_data);
+extern void bta_dm_di_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_inq_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_rmt_name (tBTA_DM_MSG *p_data);
+extern void bta_dm_sdp_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_free_sdp_db (tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_result (tBTA_DM_MSG *p_data);
+extern void bta_dm_discovery_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_search (tBTA_DM_MSG *p_data);
+extern void bta_dm_queue_disc (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_clear_queue (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_cmpl (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_notify (tBTA_DM_MSG *p_data);
+extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data);
+extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
+extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
+
+extern void bta_dm_pm_active(BD_ADDR peer_addr);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )
+void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
+#else
+#define bta_dm_eir_update_uuid(x, y)
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+extern void bta_dm_update_eir_uuid (tBTA_DM_MSG *p_data);
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+extern void bta_dm_set_eir_config (tBTA_DM_MSG *p_data);
+#endif
+extern void bta_dm_enable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_disable_test_mode(tBTA_DM_MSG *p_data);
+extern void bta_dm_execute_callback(tBTA_DM_MSG *p_data);
+
+extern void bta_dm_set_afh_channel_assesment(tBTA_DM_MSG *p_data);
+
+#endif /* BTA_DM_INT_H */
+
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
new file mode 100644
index 0000000..a2fec04
--- /dev/null
+++ b/bta/dm/bta_dm_main.c
@@ -0,0 +1,345 @@
+/******************************************************************************
+ *
+ *  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 is the main implementation file for the BTA device manager.
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_dm_int.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_DM_CB  bta_dm_cb;
+tBTA_DM_SEARCH_CB bta_dm_search_cb;
+tBTA_DM_DI_CB       bta_dm_di_cb;
+#endif
+
+
+#define BTA_DM_NUM_ACTIONS  (BTA_DM_MAX_EVT & 0x00ff)
+
+/* type for action functions */
+typedef void (*tBTA_DM_ACTION)(tBTA_DM_MSG *p_data);
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_action[] =
+{
+
+    /* device manager local device API events */
+    bta_dm_enable,            /* 0  BTA_DM_API_ENABLE_EVT */
+    bta_dm_disable,           /* 1  BTA_DM_API_DISABLE_EVT */
+    bta_dm_set_dev_name,      /* 2  BTA_DM_API_SET_NAME_EVT */
+    bta_dm_set_visibility,    /* 3  BTA_DM_API_SET_VISIBILITY_EVT */
+    bta_dm_set_afhchannels,   /* 4  BTA_DM_API_SET_AFH_CHANNELS_EVT */
+    bta_dm_signal_strength,   /* 5  BTA_API_DM_SIG_STRENGTH_EVT */
+    bta_dm_vendor_spec_command,/* 6  BTA_DM_API_VENDOR_SPECIFIC_COMMAND_EVT */
+    bta_dm_tx_inqpower,       /* 7  BTA_DM_API_SIG_STRENGTH_EVT */
+    bta_dm_acl_change,        /* 8  BTA_DM_ACL_CHANGE_EVT */
+    bta_dm_add_device,        /* 9  BTA_DM_API_ADD_DEVICE_EVT */
+
+    /* security API events */
+    bta_dm_bond,              /* 10  BTA_DM_API_BOND_EVT */
+    bta_dm_bond_cancel,       /* 11  BTA_DM_API_BOND_CANCEL_EVT */
+    bta_dm_pin_reply,         /* 12 BTA_DM_API_PIN_REPLY_EVT */
+    bta_dm_link_policy,       /* 13 BTA_DM_API_LINK_POLICY_EVT */
+    bta_dm_auth_reply,        /* 14 BTA_DM_API_AUTH_REPLY_EVT */
+
+    /* power manger events */
+    bta_dm_pm_btm_status,     /* 15 BTA_DM_PM_BTM_STATUS_EVT */
+    bta_dm_pm_timer,          /* 16 BTA_DM_PM_TIMER_EVT*/
+
+    /* simple pairing events */
+    bta_dm_confirm,           /* 17 BTA_DM_API_CONFIRM_EVT */
+
+    bta_dm_set_encryption,    /* BTA_DM_API_SET_ENCRYPTION_EVT */
+
+#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
+    bta_dm_passkey_cancel,    /* 19 BTA_DM_API_PASKY_CANCEL_EVT */
+#endif
+#if (BTM_OOB_INCLUDED == TRUE)
+    bta_dm_loc_oob,           /* 20 BTA_DM_API_LOC_OOB_EVT */
+    bta_dm_ci_io_req_act,     /* 21 BTA_DM_CI_IO_REQ_EVT */
+    bta_dm_ci_rmt_oob_act,    /* 22 BTA_DM_CI_RMT_OOB_EVT */
+#endif /* BTM_OOB_INCLUDED */
+
+    bta_dm_remove_device,      /*  BTA_DM_API_REMOVE_DEVICE_EVT */
+
+#if BLE_INCLUDED == TRUE
+    bta_dm_add_blekey,          /*  BTA_DM_API_ADD_BLEKEY_EVT           */
+    bta_dm_add_ble_device,      /*  BTA_DM_API_ADD_BLEDEVICE_EVT        */
+    bta_dm_ble_passkey_reply,   /*  BTA_DM_API_BLE_PASSKEY_REPLY_EVT    */
+    bta_dm_security_grant,
+    bta_dm_ble_set_bg_conn_type,
+    bta_dm_ble_set_conn_params,      /* BTA_DM_API_BLE_CONN_PARAM_EVT */
+    bta_dm_ble_set_scan_params,      /* BTA_DM_API_BLE_SCAN_PARAM_EVT */
+#endif
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
+    bta_dm_update_eir_uuid,     /*  BTA_DM_API_UPDATE_EIR_UUID_EVT      */
+#endif
+#if (BTM_EIR_SERVER_INCLUDED == TRUE)
+    bta_dm_set_eir_config,      /*  BTA_DM_API_SET_EIR_CONFIG_EVT       */
+#endif
+
+    bta_dm_enable_test_mode,    /*  BTA_DM_API_ENABLE_TEST_MODE_EVT     */
+    bta_dm_disable_test_mode,   /*  BTA_DM_API_DISABLE_TEST_MODE_EVT    */
+    bta_dm_execute_callback,     /*  BTA_DM_API_EXECUTE_CBACK_EVT        */
+    bta_dm_set_afh_channel_assesment      /* BTA_DM_API_SET_AFH_CHANNEL_ASSESMENT_EVT */
+};
+
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_DM_API_SEARCH,                  /* 0 bta_dm_search_start */
+    BTA_DM_API_SEARCH_CANCEL,           /* 1 bta_dm_search_cancel */
+    BTA_DM_API_DISCOVER,                /* 2 bta_dm_discover */
+    BTA_DM_INQUIRY_CMPL,                /* 3 bta_dm_inq_cmpl */
+    BTA_DM_REMT_NAME,                   /* 4 bta_dm_rmt_name */
+    BTA_DM_SDP_RESULT,                  /* 5 bta_dm_sdp_result */
+    BTA_DM_SEARCH_CMPL,                 /* 6 bta_dm_search_cmpl*/
+    BTA_DM_FREE_SDP_DB,                 /* 7 bta_dm_free_sdp_db */
+    BTA_DM_DISC_RESULT,                 /* 8 bta_dm_disc_result */
+    BTA_DM_SEARCH_RESULT,               /* 9 bta_dm_search_result */
+    BTA_DM_QUEUE_SEARCH,                /* 10 bta_dm_queue_search */
+    BTA_DM_QUEUE_DISC,                  /* 11 bta_dm_queue_disc */
+    BTA_DM_SEARCH_CLEAR_QUEUE,          /* 12 bta_dm_search_clear_queue */
+    BTA_DM_SEARCH_CANCEL_CMPL,          /* 13 bta_dm_search_cancel_cmpl */
+    BTA_DM_SEARCH_CANCEL_NOTIFY,        /* 14 bta_dm_search_cancel_notify */
+    BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL,  /* 15 bta_dm_search_cancel_transac_cmpl */
+    BTA_DM_DISC_RMT_NAME,               /* 16 bta_dm_disc_rmt_name */
+    BTA_DM_API_DI_DISCOVER,             /* 17 bta_dm_di_disc */
+    BTA_DM_SEARCH_NUM_ACTIONS           /* 18 */
+};
+
+
+/* action function list */
+const tBTA_DM_ACTION bta_dm_search_action[] =
+{
+
+  bta_dm_search_start,              /* 0 BTA_DM_API_SEARCH */
+  bta_dm_search_cancel,             /* 1 BTA_DM_API_SEARCH_CANCEL */
+  bta_dm_discover,                  /* 2 BTA_DM_API_DISCOVER */
+  bta_dm_inq_cmpl,                  /* 3 BTA_DM_INQUIRY_CMPL */
+  bta_dm_rmt_name,                  /* 4 BTA_DM_REMT_NAME */
+  bta_dm_sdp_result,                /* 5 BTA_DM_SDP_RESULT */
+  bta_dm_search_cmpl,               /* 6 BTA_DM_SEARCH_CMPL */
+  bta_dm_free_sdp_db,               /* 7 BTA_DM_FREE_SDP_DB */
+  bta_dm_disc_result,               /* 8 BTA_DM_DISC_RESULT */
+  bta_dm_search_result,             /* 9 BTA_DM_SEARCH_RESULT */
+  bta_dm_queue_search,              /* 10 BTA_DM_QUEUE_SEARCH */
+  bta_dm_queue_disc,                /* 11 BTA_DM_QUEUE_DISC */
+  bta_dm_search_clear_queue,        /* 12 BTA_DM_SEARCH_CLEAR_QUEUE */
+  bta_dm_search_cancel_cmpl,        /* 13 BTA_DM_SEARCH_CANCEL_CMPL */
+  bta_dm_search_cancel_notify,      /* 14 BTA_DM_SEARCH_CANCEL_NOTIFY */
+  bta_dm_search_cancel_transac_cmpl, /* 15 BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL */
+  bta_dm_disc_rmt_name,             /* 16 BTA_DM_DISC_RMT_NAME */
+  bta_dm_di_disc                    /* 17 BTA_DM_API_DI_DISCOVER */
+};
+
+#define BTA_DM_SEARCH_IGNORE       BTA_DM_SEARCH_NUM_ACTIONS
+/* state table information */
+#define BTA_DM_SEARCH_ACTIONS              2       /* number of actions */
+#define BTA_DM_SEARCH_NEXT_STATE           2       /* position of next state */
+#define BTA_DM_SEARCH_NUM_COLS             3       /* number of columns in state tables */
+
+
+
+/* state table for listen state */
+const UINT8 bta_dm_search_idle_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_API_SEARCH,                BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CANCEL_NOTIFY,      BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* API_SEARCH_DISC */       {BTA_DM_API_DISCOVER,              BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */         {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */        {BTA_DM_FREE_SDP_DB,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_API_DI_DISCOVER,           BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+
+};
+const UINT8 bta_dm_search_search_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_API_SEARCH_CANCEL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_INQUIRY_CMPL,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* REMT_NAME_EVT */         {BTA_DM_REMT_NAME,                 BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* SDP_RESULT_EVT */        {BTA_DM_SDP_RESULT,                BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CMPL,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_RESULT,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_ACTIVE}
+
+
+};
+
+const UINT8 bta_dm_search_search_cancelling_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_QUEUE_SEARCH,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CLEAR_QUEUE,         BTA_DM_SEARCH_CANCEL_NOTIFY,   BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_QUEUE_DISC,                 BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_CANCEL_CMPL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* REMT_NAME_EVT */         {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* SDP_RESULT_EVT */        {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CANCEL_CMPL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_CANCEL_CMPL,         BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
+
+
+};
+
+const UINT8 bta_dm_search_disc_active_st_table[][BTA_DM_SEARCH_NUM_COLS] =
+{
+
+/* Event                        Action 1                            Action 2                    Next State */
+/* API_SEARCH */            {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* API_SEARCH_CANCEL */     {BTA_DM_SEARCH_CANCEL_NOTIFY,      BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING},
+/* API_SEARCH_DISC */       {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* INQUIRY_CMPL */          {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* REMT_NAME_EVT */         {BTA_DM_DISC_RMT_NAME,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* SDP_RESULT_EVT */        {BTA_DM_SDP_RESULT,                BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CMPL,               BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_DISC_RESULT,               BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE},
+/* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,             BTA_DM_SEARCH_IGNORE,          BTA_DM_DISCOVER_ACTIVE}
+
+};
+
+typedef const UINT8 (*tBTA_DM_ST_TBL)[BTA_DM_SEARCH_NUM_COLS];
+
+/* state table */
+const tBTA_DM_ST_TBL bta_dm_search_st_tbl[] = {
+    bta_dm_search_idle_st_table,
+    bta_dm_search_search_active_st_table,
+    bta_dm_search_search_cancelling_st_table,
+    bta_dm_search_disc_active_st_table
+};
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_disable
+**
+** Description     unregister BTA DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_sm_disable( )
+{
+    bta_sys_deregister( BTA_ID_DM );
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_sm_execute(BT_HDR *p_msg)
+{
+    UINT16  event = p_msg->event & 0x00ff;
+
+    APPL_TRACE_EVENT1("bta_dm_sm_execute event:0x%x", event);
+
+    /* execute action functions */
+    if(event < BTA_DM_NUM_ACTIONS)
+    {
+        (*bta_dm_action[event])( (tBTA_DM_MSG*) p_msg);
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_search_disable
+**
+** Description     unregister BTA SEARCH DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_search_sm_disable( )
+{
+    bta_sys_deregister( BTA_ID_DM_SEARCH );
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_search_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_dm_search_sm_execute(BT_HDR *p_msg)
+{
+    tBTA_DM_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+    APPL_TRACE_EVENT2("bta_dm_search_sm_execute state:%d, event:0x%x",
+        bta_dm_search_cb.state, p_msg->event);
+
+    /* look up the state table for the current state */
+    state_table = bta_dm_search_st_tbl[bta_dm_search_cb.state];
+
+    bta_dm_search_cb.state = state_table[p_msg->event & 0x00ff][BTA_DM_SEARCH_NEXT_STATE];
+
+
+    /* execute action functions */
+    for (i = 0; i < BTA_DM_SEARCH_ACTIONS; i++)
+    {
+        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_DM_SEARCH_IGNORE)
+        {
+            (*bta_dm_search_action[action])( (tBTA_DM_MSG*) p_msg);
+        }
+        else
+        {
+            break;
+        }
+    }
+    return TRUE;
+}
+
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
new file mode 100644
index 0000000..8a993de
--- /dev/null
+++ b/bta/dm/bta_dm_pm.c
@@ -0,0 +1,994 @@
+/******************************************************************************
+ *
+ *  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 the action functions for device manager state
+ *  machine.
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_dm_int.h"
+#include "btm_api.h"
+
+#include <string.h>
+
+
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, BOOLEAN timed_out );
+static void bta_dm_pm_timer_cback(void *p_tle);
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status);
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr);
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index);
+static BOOLEAN bta_dm_pm_is_sco_active ();
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive);
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable);
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_dm_pm_ssr(BD_ADDR peer_addr);
+static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id, UINT16 max_lat, UINT16 min_rmt_to);
+#endif
+
+tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_init_pm
+**
+** Description      Initialises the BT low power manager
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_init_pm(void)
+{
+
+    memset(&bta_dm_conn_srvcs, 0x00, sizeof(bta_dm_conn_srvcs));
+
+    /* if there are no power manger entries, so not register */
+    if(p_bta_dm_pm_cfg[0].app_id != 0)
+    {
+        bta_sys_pm_register((tBTA_SYS_CONN_CBACK*)bta_dm_pm_cback);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+        bta_sys_ssr_cfg_register((tBTA_SYS_SSR_CFG_CBACK*)bta_dm_ssr_cfg_cback);
+#endif
+        BTM_PmRegister((BTM_PM_REG_SET | BTM_PM_REG_NOTIF), &bta_dm_cb.pm_id,
+                       bta_dm_pm_btm_cback);
+    }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_disable_pm
+**
+** Description      Disable PM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_disable_pm(void)
+{
+    UINT8 i;
+
+    bta_sys_pm_register(NULL);
+    BTM_PmRegister( BTM_PM_DEREG, &bta_dm_cb.pm_id, NULL);
+
+    /* Need to stop all active timers. */
+    for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+    {
+        if(bta_dm_cb.pm_timer[i].in_use)
+        {
+            APPL_TRACE_DEBUG1("stop dm_pm_timer:%d", i);
+            bta_sys_stop_timer(&bta_dm_cb.pm_timer[i].timer);
+            bta_dm_cb.pm_timer[i].in_use = FALSE;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_stop_timer
+**
+** Description      stop a PM timer
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_stop_timer(BD_ADDR peer_addr)
+{
+    UINT8 i;
+
+    for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+    {
+
+        if(bta_dm_cb.pm_timer[i].in_use && !bdcmp(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr))
+        {
+            APPL_TRACE_DEBUG1("stop dm_pm_timer:%d", i);
+            bta_sys_stop_timer(&bta_dm_cb.pm_timer[i].timer);
+            bta_dm_cb.pm_timer[i].in_use = FALSE;
+            break;
+        }
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_cback
+**
+** Description      Conn change callback from sys for low power management
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+    UINT8 i,j;
+    UINT16 policy_setting;
+    tBTM_STATUS btm_status;
+    tBTM_VERSION_INFO vers;
+#if (BTM_SSR_INCLUDED == TRUE)
+    int               index = BTA_DM_PM_SSR0;
+#endif
+    tBTA_DM_PEER_DEVICE *p_dev;
+
+    APPL_TRACE_DEBUG3("bta_dm_pm_cback: st(%d), id(%d), app(%d)", status, id, app_id);
+
+    btm_status = BTM_ReadLocalVersion (&vers);
+    p_dev = bta_dm_find_peer_device(peer_addr);
+
+	/* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/
+    if ((btm_status == BTM_SUCCESS) &&
+        (vers.manufacturer == LMP_COMPID_BROADCOM) &&
+        (vers.hci_version < HCI_PROTO_VERSION_2_0) &&
+        ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) )
+        {
+        bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+    }
+
+    /* find if there is an power mode entry for the service */
+    for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
+    {
+
+        if((p_bta_dm_pm_cfg[i].id == id)
+            && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
+            break;
+
+    }
+
+    /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/
+    if(i> p_bta_dm_pm_cfg[0].app_id)
+        return;
+
+    bta_dm_pm_stop_timer(peer_addr);
+    /*p_dev = bta_dm_find_peer_device(peer_addr);*/
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    /* set SSR parameters on SYS CONN OPEN */
+    if((BTA_SYS_CONN_OPEN == status) && p_dev && (p_dev->info & BTA_DM_DI_USE_SSR))
+    {
+        index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+    }
+#endif
+
+    /* if no action for the event */
+    if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_ACTION)
+    {
+#if (BTM_SSR_INCLUDED == TRUE)
+        if(BTA_DM_PM_SSR0 == index) /* and do not need to set SSR, return. */
+#endif
+        return;
+    }
+
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if((bta_dm_conn_srvcs.conn_srvc[j].id == id)
+            && (bta_dm_conn_srvcs.conn_srvc[j].app_id == app_id )
+            && !bdcmp(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr))
+            break;
+
+    }
+
+        /* if subsystem has no more preference on the power mode remove
+       the cb */
+    if(p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].actn_tbl[status][0].power_mode == BTA_DM_PM_NO_PREF)
+    {
+
+        if(j != bta_dm_conn_srvcs.count)
+        {
+            bta_dm_conn_srvcs.count--;
+
+            for(; j<bta_dm_conn_srvcs.count ; j++)
+            {
+
+                memcpy(&bta_dm_conn_srvcs.conn_srvc[j], &bta_dm_conn_srvcs.conn_srvc[j+1], sizeof(bta_dm_conn_srvcs.conn_srvc[j]));
+
+            }
+        }
+        else
+        {
+            APPL_TRACE_WARNING0("bta_dm_act no entry for connected service cbs");
+            return;
+        }
+    }
+    else if(j == bta_dm_conn_srvcs.count )
+    {
+        /* check if we have more connected service that cbs */
+        if(bta_dm_conn_srvcs.count == BTA_DM_NUM_CONN_SRVS)
+        {
+            APPL_TRACE_WARNING0("bta_dm_act no more connected service cbs");
+            return;
+        }
+
+        /* fill in a new cb */
+        bta_dm_conn_srvcs.conn_srvc[j].id = id;
+        bta_dm_conn_srvcs.conn_srvc[j].app_id = app_id;
+        bdcpy(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, peer_addr);
+
+        APPL_TRACE_WARNING2("new conn_srvc id:%d, app_id:%d", id, app_id);
+
+        bta_dm_conn_srvcs.count++;
+        bta_dm_conn_srvcs.conn_srvc[j].state = status;
+    }
+    else
+    {
+        /* no service is added or removed. only updating status. */
+        bta_dm_conn_srvcs.conn_srvc[j].state = status;
+    }
+
+    if(p_dev)
+    {
+        p_dev->pm_mode_attempted = 0;
+        p_dev->pm_mode_failed = 0;
+    }
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    if(p_bta_dm_ssr_spec[index].max_lat)
+    {
+        bta_dm_pm_ssr(peer_addr);
+    }
+#endif
+
+    bta_dm_pm_set_mode(peer_addr, FALSE);
+
+    /* perform the HID link workaround if needed
+    ** 1. If SCO up/down event is received OR
+    ** 2. If HID connection open is received and SCO is already active.
+    **     This will handle the case where HID connects when SCO already active
+    */
+    if ( (btm_status == BTM_SUCCESS) &&
+         ( ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) ||
+           ((status == BTA_SYS_CONN_OPEN) && (id == BTA_ID_HH) && bta_dm_pm_is_sco_active()) ) )
+    {
+        BOOLEAN bScoActive;
+        if (status == BTA_SYS_CONN_OPEN)
+            bScoActive = TRUE;
+        else
+            bScoActive = (status == BTA_SYS_SCO_OPEN);
+
+        bta_dm_pm_hid_check(bScoActive);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_set_mode
+**
+** Description      Set the power mode for the device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_set_mode(BD_ADDR peer_addr, BOOLEAN timed_out )
+{
+
+    tBTA_DM_PM_ACTTION  pm_action = BTA_DM_PM_NO_ACTION;
+    UINT16              timeout = 0;
+    UINT8               i,j;
+    tBTA_DM_PM_ACTTION  failed_pm = 0;
+    tBTA_DM_PEER_DEVICE *p_peer_device = NULL;
+    tBTA_DM_PM_ACTTION   allowed_modes = 0;
+    tBTA_DM_PM_ACTTION   pref_modes = 0;
+    tBTA_DM_PM_CFG      *p_pm_cfg;
+    tBTA_DM_PM_SPEC     *p_pm_spec;
+    tBTA_DM_PM_ACTN     *p_act0, *p_act1;
+    tBTA_DM_SRVCS       *p_srvcs;
+
+
+    if(!bta_dm_cb.device_list.count)
+        return;
+
+    /* see if any attempt to put device in low power mode failed */
+    p_peer_device = bta_dm_find_peer_device(peer_addr);
+    /* if no peer device found return */
+    if (p_peer_device == NULL)
+        return;
+
+    failed_pm = p_peer_device->pm_mode_failed;
+
+    for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+    {
+
+        p_srvcs = &bta_dm_conn_srvcs.conn_srvc[i];
+        if(!bdcmp(p_srvcs->peer_bdaddr, peer_addr))
+        {
+
+            /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+            for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+            {
+                if((p_bta_dm_pm_cfg[j].id == p_srvcs->id)
+                    && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID ) ||
+                    (p_bta_dm_pm_cfg[j].app_id == p_srvcs->app_id)))
+                    break;
+            }
+
+            p_pm_cfg = &p_bta_dm_pm_cfg[j];
+            p_pm_spec = &p_bta_dm_pm_spec[p_pm_cfg->spec_idx];
+            p_act0 = &p_pm_spec->actn_tbl[p_srvcs->state][0];
+            p_act1 = &p_pm_spec->actn_tbl[p_srvcs->state][1];
+
+            APPL_TRACE_DEBUG3("bta_dm_pm_set_mode: srvcsid: %d, state: %d, j: %d", p_srvcs->id, p_srvcs->state, j);
+            allowed_modes |= p_pm_spec->allow_mask;
+
+            /* PM actions are in the order of strictness */
+
+            /* first check if the first preference is ok */
+            if(!(failed_pm & p_act0->power_mode))
+            {
+                pref_modes |= p_act0->power_mode;
+
+                if(p_act0->power_mode > pm_action)
+                {
+                    pm_action = p_act0->power_mode;
+                    timeout =  p_act0->timeout;
+
+                }
+            }
+            /* if first preference has already failed, try second preference */
+            else if(!(failed_pm & p_act1->power_mode))
+            {
+                pref_modes |= p_act1->power_mode;
+
+                if(p_act1->power_mode > pm_action)
+                {
+                    pm_action = p_act1->power_mode;
+                    timeout =  p_act1->timeout;
+
+                }
+            }
+        }
+    }
+
+    if(pm_action & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+    {
+
+        /* some service don't like the mode */
+        if(!(allowed_modes & pm_action))
+        {
+
+            /* select the other mode if its allowed and preferred, otherwise 0 which is BTA_DM_PM_NO_ACTION */
+            pm_action =  (allowed_modes & (BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & pref_modes);
+
+            /* no timeout needed if no action is required */
+            if(pm_action == BTA_DM_PM_NO_ACTION)
+            {
+                timeout = 0;
+            }
+
+        }
+
+
+    }
+
+    if(!timed_out && timeout)
+    {
+
+        for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+        {
+
+            if(!bta_dm_cb.pm_timer[i].in_use)
+            {
+                bta_dm_cb.pm_timer[i].in_use = TRUE;
+                bdcpy(bta_dm_cb.pm_timer[i].peer_bdaddr, peer_addr);
+                bta_dm_cb.pm_timer[i].timer.p_cback = bta_dm_pm_timer_cback;
+                bta_sys_start_timer(&bta_dm_cb.pm_timer[i].timer, 0, timeout);
+                APPL_TRACE_DEBUG2("start dm_pm_timer:%d, %d", i, timeout);
+                return;
+
+            }
+
+        }
+
+        /* no more timers */
+        if(i==BTA_DM_NUM_PM_TIMER)
+        {
+            APPL_TRACE_WARNING0("bta_dm_act dm_pm_timer no more");
+            return;
+        }
+    }
+
+    if(pm_action == BTA_DM_PM_NO_ACTION)
+    {
+
+
+    }
+    else if(pm_action == BTA_DM_PM_PARK)
+    {
+        p_peer_device->pm_mode_attempted = BTA_DM_PM_PARK;
+        bta_dm_pm_park(peer_addr);
+
+    }
+    else if(pm_action & BTA_DM_PM_SNIFF)
+    {
+        /* dont initiate SNIFF, if link_policy has it disabled */
+        if (p_peer_device->link_policy & HCI_ENABLE_SNIFF_MODE)
+        {
+	        p_peer_device->pm_mode_attempted = BTA_DM_PM_SNIFF;
+    	    bta_dm_pm_sniff(p_peer_device, (UINT8)(pm_action & 0x0F) );
+        }
+        else
+        {
+            APPL_TRACE_DEBUG0("bta_dm_pm_set_mode: Link policy disallows SNIFF, ignore request");
+        }
+    }
+    else if(pm_action == BTA_DM_PM_ACTIVE)
+    {
+
+        bta_dm_pm_active(peer_addr);
+
+    }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_pm_park
+**
+** Description      Switch to park mode.
+**
+**
+** Returns          TRUE if park attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_park(BD_ADDR peer_addr)
+{
+
+    tBTM_PM_MODE    mode = BTM_PM_STS_ACTIVE;
+
+    /* if not in park mode, switch to park */
+    BTM_ReadPowerMode(peer_addr, &mode);
+
+    if(mode != BTM_PM_MD_PARK)
+    {
+        BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &p_bta_dm_pm_md[BTA_DM_PM_PARK_IDX]);
+    }
+    return TRUE;
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_ag_pm_sniff
+**
+** Description      Switch to sniff mode.
+**
+**
+** Returns          TRUE if sniff attempted, FALSE otherwise.
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_sniff(tBTA_DM_PEER_DEVICE *p_peer_dev, UINT8 index)
+{
+    tBTM_PM_MODE    mode = BTM_PM_STS_ACTIVE;
+    tBTM_PM_PWR_MD  pwr_md;
+    tBTM_STATUS     status;
+
+    BTM_ReadPowerMode(p_peer_dev->peer_bdaddr, &mode);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+    APPL_TRACE_DEBUG3("bta_dm_pm_sniff cur:%d, idx:%d, info:x%x", mode, index, p_peer_dev->info);
+    if (mode != BTM_PM_MD_SNIFF ||
+        (HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadLocalFeatures ()) &&
+         HCI_SNIFF_SUB_RATE_SUPPORTED(BTM_ReadRemoteFeatures (p_peer_dev->peer_bdaddr)) &&
+         !(p_peer_dev->info & BTA_DM_DI_USE_SSR)))
+#else
+    APPL_TRACE_DEBUG2("bta_dm_pm_sniff cur:%d, idx:%d", mode, index);
+    if(mode != BTM_PM_MD_SNIFF)
+#endif
+    {
+        /* if the current mode is not sniff, issue the sniff command.
+         * If sniff, but SSR is not used in this link, still issue the command */
+        memcpy(&pwr_md, &p_bta_dm_pm_md[index], sizeof (tBTM_PM_PWR_MD));
+        if (p_peer_dev->info & BTA_DM_DI_INT_SNIFF)
+        {
+            pwr_md.mode |= BTM_PM_MD_FORCE;
+        }
+        status = BTM_SetPowerMode (bta_dm_cb.pm_id, p_peer_dev->peer_bdaddr, &pwr_md);
+        if (status == BTM_CMD_STORED|| status == BTM_CMD_STARTED)
+        {
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
+            p_peer_dev->info |= BTA_DM_DI_SET_SNIFF;
+        }
+        else if (status == BTM_SUCCESS)
+        {
+            APPL_TRACE_DEBUG0("bta_dm_pm_sniff BTM_SetPowerMode() returns BTM_SUCCESS");
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+        }
+        else /* error */
+        {
+            APPL_TRACE_ERROR1("bta_dm_pm_sniff BTM_SetPowerMode() returns ERROR status=%d", status);
+            p_peer_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+        }
+    }
+    /* else already in sniff and is using SSR, do nothing */
+
+    return TRUE;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_ssr
+**
+** Description      checks and sends SSR parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+static void bta_dm_pm_ssr(BD_ADDR peer_addr)
+{
+    tBTA_DM_SSR_SPEC *p_spec, *p_spec_cur;
+    UINT8   i,j;
+    int     ssr = BTA_DM_PM_SSR0;
+
+    /* go through the connected services */
+    for(i=0; i<bta_dm_conn_srvcs.count ; i++)
+    {
+        if(!bdcmp(bta_dm_conn_srvcs.conn_srvc[i].peer_bdaddr, peer_addr))
+        {
+            /* p_bta_dm_pm_cfg[0].app_id is the number of entries */
+            for(j=1; j<=p_bta_dm_pm_cfg[0].app_id; j++)
+            {
+                /* find the associated p_bta_dm_pm_cfg */
+                if((p_bta_dm_pm_cfg[j].id == bta_dm_conn_srvcs.conn_srvc[i].id)
+                    && ((p_bta_dm_pm_cfg[j].app_id == BTA_ALL_APP_ID )
+                    || (p_bta_dm_pm_cfg[j].app_id == bta_dm_conn_srvcs.conn_srvc[i].app_id)))
+                {
+                    APPL_TRACE_WARNING2("bta_dm_pm_ssr conn_srvc id:%d, app_id:%d",
+                        bta_dm_conn_srvcs.conn_srvc[i].id, bta_dm_conn_srvcs.conn_srvc[i].app_id);
+                    break;
+                }
+            }
+
+            /* find the ssr index with the smallest max latency. */
+            p_spec_cur = &p_bta_dm_ssr_spec[p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr];
+            p_spec = &p_bta_dm_ssr_spec[ssr];
+
+            if (p_spec_cur->max_lat < p_spec->max_lat ||
+                (ssr == BTA_DM_PM_SSR0 && p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr != BTA_DM_PM_SSR0))
+            {
+                ssr = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr;
+            }
+
+        }
+    }
+
+    p_spec = &p_bta_dm_ssr_spec[ssr];
+    APPL_TRACE_WARNING2("bta_dm_pm_ssr:%d, lat:%d", ssr, p_spec->max_lat);
+    if(p_spec->max_lat)
+    {
+        /* set the SSR parameters. */
+        BTM_SetSsrParams (peer_addr, p_spec->max_lat,
+            p_spec->min_rmt_to, p_spec->min_loc_to);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_dm_ssr_cfg_cback
+**
+** Description      Conn change callback from sys for low power management
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_ssr_cfg_cback(UINT8 id, UINT8 app_id,
+                                 UINT16 max_lat, UINT16 min_rmt_to)
+{
+    tBTA_DM_SSR_SPEC *p_spec;
+    UINT8   i, index;
+    /* find if there is an power mode entry for the service */
+    for(i=1; i<=p_bta_dm_pm_cfg[0].app_id; i++)
+    {
+
+        if((p_bta_dm_pm_cfg[i].id == id)
+            && ((p_bta_dm_pm_cfg[i].app_id == BTA_ALL_APP_ID ) || (p_bta_dm_pm_cfg[i].app_id == app_id )))
+            break;
+
+    }
+    /* if no entries are there for the app_id and subystem in p_bta_dm_pm_spec*/
+    if(i> p_bta_dm_pm_cfg[0].app_id)
+        return;
+
+    index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+
+    APPL_TRACE_DEBUG2("SSR parameter changed to: max_latency: %d min_tout: %d", max_lat, min_rmt_to);
+
+    p_spec = &p_bta_dm_ssr_spec[index];
+    p_spec->max_lat = max_lat;
+    p_spec->min_rmt_to = min_rmt_to;
+}
+
+
+#endif
+/*******************************************************************************
+**
+** Function         bta_dm_pm_active
+**
+** Description      Brings connection to active mode
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_active(BD_ADDR peer_addr)
+{
+    tBTM_PM_PWR_MD  pm;
+
+    memset( (void*)&pm, 0, sizeof(pm));
+
+    /* switch to active mode */
+    pm.mode = BTM_PM_MD_ACTIVE;
+    BTM_SetPowerMode (bta_dm_cb.pm_id, peer_addr, &pm);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_btm_cback
+**
+** Description      BTM power manager callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_btm_cback(BD_ADDR bd_addr, tBTM_PM_STATUS status, UINT16 value, UINT8 hci_status)
+{
+   tBTA_DM_PM_BTM_STATUS  *p_buf;
+
+   if ((p_buf = (tBTA_DM_PM_BTM_STATUS *) GKI_getbuf(sizeof(tBTA_DM_PM_BTM_STATUS))) != NULL)
+    {
+        p_buf->hdr.event = BTA_DM_PM_BTM_STATUS_EVT;
+        p_buf->status = status;
+        p_buf->value = value;
+        p_buf->hci_status = hci_status;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_timer_cback
+**
+** Description      Power management timer callback.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_pm_timer_cback(void *p_tle)
+{
+    tBTA_DM_PM_TIMER  *p_buf;
+    UINT8 i;
+
+    APPL_TRACE_WARNING0("dm_pm_timer expires");
+
+    for(i=0; i<BTA_DM_NUM_PM_TIMER; i++)
+    {
+
+        if(bta_dm_cb.pm_timer[i].in_use)
+        {
+
+            if(&bta_dm_cb.pm_timer[i].timer == (TIMER_LIST_ENT*) p_tle)
+            {
+                APPL_TRACE_WARNING1("dm_pm_timer expires %d", i);
+                bta_dm_cb.pm_timer[i].in_use = FALSE;
+                break;
+            }
+
+        }
+
+    }
+
+
+    /* no more timers */
+    if(i==BTA_DM_NUM_PM_TIMER)
+    {
+        return;
+    }
+
+    if ((p_buf = (tBTA_DM_PM_TIMER *) GKI_getbuf(sizeof(tBTA_DM_PM_TIMER))) != NULL)
+    {
+        p_buf->hdr.event = BTA_DM_PM_TIMER_EVT;
+        bdcpy(p_buf->bd_addr, bta_dm_cb.pm_timer[i].peer_bdaddr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_btm_status
+**
+** Description      Process pm status event from btm
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data)
+{
+
+    tBTA_DM_PEER_DEVICE *p_dev;
+    tBTA_DM_DEV_INFO    info;
+
+    APPL_TRACE_DEBUG1("bta_dm_pm_btm_status:%d", p_data->pm_status.status);
+    p_dev = bta_dm_find_peer_device(p_data->pm_status.bd_addr);
+    if(NULL == p_dev)
+        return;
+
+    info = p_dev->info;
+    /* check new mode */
+    switch (p_data->pm_status.status)
+    {
+        case BTM_PM_STS_ACTIVE:
+            /* if our sniff or park attempt failed
+            we should not try it again*/
+            if (p_data->pm_status.hci_status != 0)
+            {
+                APPL_TRACE_ERROR1("bta_dm_pm_btm_status  hci_status=%d", p_data->pm_status.hci_status);
+                p_dev->info &= ~(BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF|BTA_DM_DI_SET_SNIFF);
+
+                if(p_dev->pm_mode_attempted &(BTA_DM_PM_PARK | BTA_DM_PM_SNIFF))
+                {
+                    p_dev->pm_mode_failed
+                        |= ((BTA_DM_PM_PARK | BTA_DM_PM_SNIFF) & p_dev->pm_mode_attempted);
+                    bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+                    bta_dm_pm_set_mode(p_data->pm_status.bd_addr, FALSE);
+                }
+            }
+            else
+            {
+#if (BTM_SSR_INCLUDED == TRUE)
+                if(p_dev->prev_low)
+                {
+                    /* need to send the SSR paramaters to controller again */
+                    bta_dm_pm_ssr(p_dev->peer_bdaddr);
+                }
+                p_dev->prev_low = BTM_PM_STS_ACTIVE;
+#endif
+                bta_dm_pm_stop_timer(p_data->pm_status.bd_addr);
+                bta_dm_pm_set_mode(p_data->pm_status.bd_addr, FALSE);
+            }
+            break;
+
+#if (BTM_SSR_INCLUDED == TRUE)
+        case BTM_PM_STS_PARK:
+        case BTM_PM_STS_HOLD:
+            /* save the previous low power mode - for SSR.
+             * SSR parameters are sent to controller on "conn open".
+             * the numbers stay good until park/hold/detach */
+            if(p_dev->info & BTA_DM_DI_USE_SSR)
+                p_dev->prev_low = p_data->pm_status.status;
+            break;
+
+        case BTM_PM_STS_SSR:
+            if(p_data->pm_status.value)
+                p_dev->info |= BTA_DM_DI_USE_SSR;
+            else
+                p_dev->info &= ~BTA_DM_DI_USE_SSR;
+            break;
+#endif
+        case BTM_PM_STS_SNIFF:
+            p_dev->info &= ~(BTA_DM_DI_SET_SNIFF|BTA_DM_DI_INT_SNIFF|BTA_DM_DI_ACP_SNIFF);
+            if (info & BTA_DM_DI_SET_SNIFF)
+                p_dev->info |= BTA_DM_DI_INT_SNIFF;
+            else
+                p_dev->info |= BTA_DM_DI_ACP_SNIFF;
+            break;
+
+        case BTM_PM_STS_ERROR:
+            p_dev->info &= ~BTA_DM_DI_SET_SNIFF;
+            break;
+
+        default:
+            break;
+    }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_timer
+**
+** Description      Process pm timer event from btm
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_dm_pm_timer(tBTA_DM_MSG *p_data)
+{
+
+    APPL_TRACE_WARNING0("proc dm_pm_timer expires");
+    bta_dm_pm_set_mode(p_data->pm_status.bd_addr, TRUE);
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_find_peer_device
+**
+** Description      Given an address, find the associated control block.
+**
+** Returns          tBTA_DM_PEER_DEVICE
+**
+*******************************************************************************/
+tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr)
+{
+    tBTA_DM_PEER_DEVICE *p_dev = NULL;
+    int i;
+
+    for(i=0; i<bta_dm_cb.device_list.count; i++)
+    {
+        if(!bdcmp( bta_dm_cb.device_list.peer_device[i].peer_bdaddr, peer_addr))
+        {
+            p_dev = &bta_dm_cb.device_list.peer_device[i];
+            break;
+        }
+
+    }
+    return p_dev;
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_is_sco_active
+**
+** Description      Loop through connected services for HFP+State=SCO
+**
+** Returns          BOOLEAN. TRUE if SCO active, else FALSE
+**
+*******************************************************************************/
+static BOOLEAN bta_dm_pm_is_sco_active ()
+{
+    int j;
+    BOOLEAN bScoActive = FALSE;
+
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if ( (bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_AG )  && (bta_dm_conn_srvcs.conn_srvc[j].state == BTA_SYS_SCO_OPEN) )
+        {
+            bScoActive = TRUE;
+            break;
+        }
+    }
+
+    APPL_TRACE_DEBUG1("bta_dm_is_sco_active: SCO active: %d", bScoActive);
+    return bScoActive;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_hid_check
+**
+** Description      Disables/Enables sniff in link policy based on SCO Up/Down
+**
+** Returns          None
+**
+*******************************************************************************/
+
+static void bta_dm_pm_hid_check(BOOLEAN bScoActive)
+{
+    int j;
+
+    /* if HID is active, disable the link policy */
+    for(j=0; j<bta_dm_conn_srvcs.count ; j++)
+    {
+        /* check if an entry already present */
+        if(bta_dm_conn_srvcs.conn_srvc[j].id == BTA_ID_HH )
+        {
+            APPL_TRACE_DEBUG2 ("SCO status change(Active: %d), modify HID link policy. state: %d",
+                bScoActive, bta_dm_conn_srvcs.conn_srvc[j].state);
+            bta_dm_pm_set_sniff_policy( bta_dm_find_peer_device(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr), bScoActive);
+
+            /* if we had disabled link policy, seems like the hid device stop retrying SNIFF after a few tries. force sniff if needed */
+            if (!bScoActive)
+                bta_dm_pm_set_mode(bta_dm_conn_srvcs.conn_srvc[j].peer_bdaddr, FALSE);
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_pm_set_sniff_policy
+**
+** Description      Disables/Enables sniff in link policy for the give device
+**
+** Returns          None
+**
+*******************************************************************************/
+static void bta_dm_pm_set_sniff_policy(tBTA_DM_PEER_DEVICE *p_dev, BOOLEAN bDisable)
+{
+    UINT16 policy_setting;
+
+    if (!p_dev)
+        return;
+
+    if (bDisable)
+    {
+        policy_setting = bta_dm_cb.cur_policy &
+            (HCI_ENABLE_MASTER_SLAVE_SWITCH |
+             HCI_ENABLE_HOLD_MODE  |
+             HCI_ENABLE_PARK_MODE);
+
+    }
+    else
+    {
+        /*  allow sniff after sco is closed */
+         policy_setting= bta_dm_cb.cur_policy;
+    }
+
+    /* if disabling SNIFF, make sure link is Active */
+    if (bDisable)
+        bta_dm_pm_active(p_dev->peer_bdaddr);
+
+    /* update device record and set link policy */
+    p_dev->link_policy = policy_setting;
+    BTM_SetLinkPolicy(p_dev->peer_bdaddr, &policy_setting);
+
+}
diff --git a/bta/dm/bta_dm_sco.c b/bta/dm/bta_dm_sco.c
new file mode 100644
index 0000000..803242b
--- /dev/null
+++ b/bta/dm/bta_dm_sco.c
@@ -0,0 +1,695 @@
+/******************************************************************************
+ *
+ *  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 the down sampling utility to convert PCM samples in
+ *  16k/32k/48k/44.1k/22050/11025 sampling rate into 8K/16bits samples
+ *  required for SCO channel format. One API function isprovided and only
+ *  possible to be used when transmitting SCO data is sent via HCI
+ *  interface.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+
+#ifndef BTA_DM_SCO_DEBUG
+#define BTA_DM_SCO_DEBUG    FALSE
+#endif
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+#define BTA_DM_PCM_OVERLAP_SIZE			     48
+
+#define BTA_DM_PCM_SMPL_RATE_44100     44100
+#define BTA_DM_PCM_SMPL_RATE_22050     22050
+#define BTA_DM_PCM_SMPL_RATE_11025     11025
+
+/*****************************************************************************
+**  Data types for PCM Resampling utility
+*****************************************************************************/
+
+typedef INT32   (*PCONVERT_TO_BT_FILTERED)  (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                             UINT32 dwSrcSps,INT32 *pLastCurPos, UINT8 *pOverlapArea);
+typedef INT32   (*PCONVERT_TO_BT_NOFILTER)  (void *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                             UINT32 dwSrcSps);
+typedef struct
+{
+    UINT8               overlap_area[BTA_DM_PCM_OVERLAP_SIZE * 4];
+    UINT32              cur_pos;    /* current position */
+    UINT32              src_sps;    /* samples per second (source audio data) */
+    PCONVERT_TO_BT_FILTERED     filter;    /* the action function to do the
+                                    conversion 44100, 22050, 11025*/
+    PCONVERT_TO_BT_NOFILTER     nofilter;    /* the action function to do
+                                        the conversion 48000, 32000, 16000*/
+    UINT32              bits;       /* number of bits per pcm sample */
+    UINT32              n_channels; /* number of channels (i.e. mono(1), stereo(2)...) */
+    UINT32              sample_size;
+    UINT32              can_be_filtered;
+    UINT32	            divisor;
+} tBTA_DM_PCM_RESAMPLE_CB;
+
+tBTA_DM_PCM_RESAMPLE_CB bta_dm_pcm_cb;
+
+/*****************************************************************************
+**  Macro Definition
+*****************************************************************************/
+
+
+#define CHECK_SATURATION16(x)                                           \
+            if (x > 32767)                                              \
+                x = 32767;                                              \
+            else if (x < -32768)                                        \
+                x = -32768;
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_44100_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1, out2, out3, out4, out5;                         \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 1587)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 1522)                \
+                 + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1337)                \
+                 + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 1058);               \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 725)                 \
+                 + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 384)                 \
+                 + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 79);                 \
+                                                                            \
+            out2 = out2 / 30000;                                            \
+                                                                            \
+            out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 156)                 \
+                 + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 298)                 \
+                 + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 345);                \
+                                                                            \
+            out3 = out3 / 30000;                                            \
+                                                                            \
+            out4 = ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 306)               \
+                 + ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 207)               \
+                 + ((SRC_SAMPLE(12) + SRC_SAMPLE(-12)) * 78);               \
+                                                                            \
+            out4 = out4 / 30000;                                            \
+                                                                            \
+            out5 = out1 + out2 - out3 - out4;                               \
+                                                                            \
+            CHECK_SATURATION16(out5);                                       \
+            *psBtOut++ = (INT16)out5;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_22050_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1, out2, out3, out4, out5;                         \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 2993)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2568)                \
+                 + ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1509)                \
+                 + ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 331);                \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            out2 = ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 454)                 \
+                 + ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 620)                 \
+                 + ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 305);                \
+                                                                            \
+            out2 = out2 / 30000;                                            \
+                                                                            \
+            out3 = ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 127)                 \
+                 + ((SRC_SAMPLE(8) + SRC_SAMPLE(-8)) * 350)                 \
+                 + ((SRC_SAMPLE(9) + SRC_SAMPLE(-9)) * 265)                 \
+                 + ((SRC_SAMPLE(10) + SRC_SAMPLE(-10)) * 6);                \
+                                                                            \
+            out3 = out3 / 30000;                                            \
+                                                                            \
+            out4 = ((SRC_SAMPLE(11) + SRC_SAMPLE(-11)) * 201);              \
+                                                                            \
+            out4 = out4 / 30000;                                            \
+                                                                            \
+            out5 = out1 - out2 + out3 - out4;                               \
+                                                                            \
+            CHECK_SATURATION16(out5);                                       \
+            *psBtOut++ = (INT16)out5;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#define CONVERT_11025_TO_BLUETOOTH(pStart, pEnd)                            \
+    {                                                                       \
+        INT32         out1;                                                   \
+        SRC_TYPE    *pS = (SRC_TYPE *)pStart;                               \
+        SRC_TYPE    *pSEnd = (SRC_TYPE *)pEnd;                              \
+                                                                            \
+        while (pS < pSEnd)                                                  \
+        {                                                                   \
+            CurrentPos -= 8000;                                             \
+                                                                            \
+            if (CurrentPos >= 0)                                            \
+            {                                                               \
+                pS += SRC_CHANNELS;                                         \
+                continue;                                                   \
+            }                                                               \
+            CurrentPos += dwSrcSps;                                         \
+                                                                            \
+            out1 = (SRC_SAMPLE(0) * 6349)                                   \
+                 + ((SRC_SAMPLE(1) + SRC_SAMPLE(-1)) * 2874)                \
+                 - ((SRC_SAMPLE(2) + SRC_SAMPLE(-2)) * 1148)                \
+                 - ((SRC_SAMPLE(3) + SRC_SAMPLE(-3)) * 287)                 \
+                 + ((SRC_SAMPLE(4) + SRC_SAMPLE(-4)) * 675)                 \
+                 - ((SRC_SAMPLE(5) + SRC_SAMPLE(-5)) * 258)                 \
+                 - ((SRC_SAMPLE(6) + SRC_SAMPLE(-6)) * 206)                 \
+                 + ((SRC_SAMPLE(7) + SRC_SAMPLE(-7)) * 266);                \
+                                                                            \
+            out1 = out1 / 30000;                                            \
+                                                                            \
+            CHECK_SATURATION16(out1);                                       \
+            *psBtOut++ = (INT16)out1;                                       \
+                                                                            \
+            pS += SRC_CHANNELS;                                             \
+        }                                                                   \
+    }
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        UINT8
+#define SRC_CHANNELS    1
+#define SRC_SAMPLE(x)   ((pS[x]  - 0x80) << 8)
+
+/*****************************************************************************
+**  Local Function
+*****************************************************************************/
+INT32 Convert_8M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                    UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG1("Convert_8M_ToBT_Filtered,  CurrentPos %d\n", CurrentPos);
+#endif
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    UINT8            *pbSrc = (UINT8 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            pbSrc++;
+        else
+        {
+            sWorker = *pbSrc++;
+            sWorker -= 0x80;
+            sWorker <<= 8;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        INT16
+#define SRC_CHANNELS    1
+#define SRC_SAMPLE(x)   pS[x]
+
+INT32 Convert_16M_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                 UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16M_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    INT16           *psSrc = (INT16 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            psSrc++;
+        else
+        {
+            *psDst++ = *psSrc++;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        UINT8
+#define SRC_CHANNELS    2
+#define SRC_SAMPLE(x) ((((pS[x * 2]  - 0x80) << 8) + ((pS[(x * 2) + 1]  - 0x80) << 8)) >> 1)
+
+INT32 Convert_8S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG5("Convert_8S_ToBT_Filtered CurrentPos %d, SRC_TYPE %d, SRC_CHANNELS %d, \
+        dwSrcSamples %d,  dwSrcSps %d",  	CurrentPos, sizeof (SRC_TYPE), SRC_CHANNELS, \
+        dwSrcSamples, dwSrcSps);
+#endif
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_8S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    UINT8            *pbSrc = (UINT8 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker, sWorker2;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            pbSrc += 2;
+        else
+        {
+            sWorker = *(unsigned char *)pbSrc;
+            sWorker -= 0x80;
+            sWorker <<= 8;
+            pbSrc++;
+
+            sWorker2 = *(unsigned char *)pbSrc;
+            sWorker2 -= 0x80;
+            sWorker2 <<= 8;
+            pbSrc++;
+
+            sWorker += sWorker2;
+            sWorker >>= 1;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+//
+#undef  SRC_CHANNELS
+#undef  SRC_SAMPLE
+#undef  SRC_TYPE
+
+#define SRC_TYPE        INT16
+#define SRC_CHANNELS    2
+#define SRC_SAMPLE(x) ((pS[x * 2] + pS[(x * 2) + 1]) >> 1)
+
+INT32 Convert_16S_ToBT_Filtered (UINT8 *pSrc, void *pDst, UINT32 dwSrcSamples,
+                                 UINT32 dwSrcSps, INT32 *pLastCurPos, UINT8 *pOverlapArea)
+{
+    INT32             CurrentPos = *pLastCurPos;
+    SRC_TYPE        *pIn, *pInEnd;
+    SRC_TYPE        *pOv, *pOvEnd;
+    INT16           *psBtOut = (INT16 *)pDst;
+
+    memcpy (pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 2), pSrc, BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    pOv    = (SRC_TYPE *)(pOverlapArea + BTA_DM_PCM_OVERLAP_SIZE);
+	pOvEnd = (SRC_TYPE *)(pOverlapArea + (BTA_DM_PCM_OVERLAP_SIZE * 3));
+
+    pIn     = (SRC_TYPE *)(pSrc + BTA_DM_PCM_OVERLAP_SIZE);
+	pInEnd  = (SRC_TYPE *)(pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - BTA_DM_PCM_OVERLAP_SIZE);
+
+    if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_44100)
+    {
+        CONVERT_44100_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_44100_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_22050)
+    {
+        CONVERT_22050_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_22050_TO_BLUETOOTH(pIn, pInEnd);
+    }
+    else if (dwSrcSps == BTA_DM_PCM_SMPL_RATE_11025)
+    {
+        CONVERT_11025_TO_BLUETOOTH(pOv, pOvEnd);
+        CONVERT_11025_TO_BLUETOOTH(pIn, pInEnd);
+    }
+
+    memcpy (pOverlapArea, pSrc + (dwSrcSamples * SRC_CHANNELS * sizeof (SRC_TYPE)) - \
+        (BTA_DM_PCM_OVERLAP_SIZE * 2), BTA_DM_PCM_OVERLAP_SIZE * 2);
+
+    *pLastCurPos = CurrentPos;
+
+    return (psBtOut - (INT16 *)pDst);
+}
+
+INT32 Convert_16S_ToBT_NoFilter (void *pSrc, void *pDst, UINT32 dwSrcSamples, UINT32 dwSrcSps)
+{
+    INT32             CurrentPos;
+    INT16           *psSrc = (INT16 *)pSrc;
+    INT16           *psDst = (INT16 *)pDst;
+    INT16           sWorker;
+
+    //      start at dwSpsSrc / 2, decrement by 8000
+    //
+    CurrentPos = (dwSrcSps >> 1);
+
+    while (dwSrcSamples--)
+    {
+        CurrentPos -= 8000;
+
+        if (CurrentPos >= 0)
+            psSrc += 2;
+        else
+        {
+            /* CR 82894, to avoid overflow, divide before add */
+            sWorker  = ((*psSrc) >> 1 );
+            psSrc++;
+            sWorker += ((*psSrc) >> 1 );
+            psSrc++;
+
+            *psDst++ = sWorker;
+
+            CurrentPos += dwSrcSps;
+        }
+    }
+
+    return (psDst - (INT16 *)pDst);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmPcmInitSamples
+**
+** Description      initialize the down sample converter.
+**
+**                  src_sps: original samples per second (source audio data)
+**                            (ex. 44100, 48000)
+**                  bits: number of bits per pcm sample (16)
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels)
+{
+    tBTA_DM_PCM_RESAMPLE_CB *p_cb = &bta_dm_pcm_cb;
+
+    p_cb->cur_pos       = src_sps / 2;
+    p_cb->src_sps       = src_sps;
+    p_cb->bits          = bits;
+    p_cb->n_channels    = n_channels;
+    p_cb->sample_size   = 2;
+    p_cb->divisor	    = 2;
+
+    memset(p_cb->overlap_area, 0, sizeof(p_cb->overlap_area) );
+
+    if ((src_sps == BTA_DM_PCM_SMPL_RATE_44100) ||
+        (src_sps == BTA_DM_PCM_SMPL_RATE_22050) ||
+        (src_sps == BTA_DM_PCM_SMPL_RATE_11025))
+         p_cb->can_be_filtered = 1;
+    else
+         p_cb->can_be_filtered = 0;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG2("bta_dm_pcm_init_samples: n_channels = %d bits = %d", n_channels, bits);
+#endif
+    if(n_channels == 1)
+    {
+        /* mono */
+        if(bits == 8)
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8M_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8M_ToBT_NoFilter;
+	        p_cb->divisor	 = 1;
+        }
+        else
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16M_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16M_ToBT_NoFilter;
+        }
+    }
+    else
+    {
+        /* stereo */
+        if(bits == 8)
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_8S_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_8S_ToBT_NoFilter;
+        }
+        else
+        {
+            p_cb->filter = (PCONVERT_TO_BT_FILTERED) Convert_16S_ToBT_Filtered;
+            p_cb->nofilter = (PCONVERT_TO_BT_NOFILTER) Convert_16S_ToBT_NoFilter;
+	        p_cb->divisor	 = 4;
+        }
+    }
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG2("bta_pcm_init_dwn_sample: cur_pos %d, src_sps %d", \
+		p_cb->cur_pos, p_cb->src_sps);
+    APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: bits %d, n_channels %d, sample_size %d, ", \
+		p_cb->bits, p_cb->n_channels, p_cb->sample_size);
+    APPL_TRACE_DEBUG3("bta_pcm_init_dwn_sample: can_be_filtered %d, n_channels: %d, \
+        divisor %d", p_cb->can_be_filtered, p_cb->n_channels, p_cb->divisor);
+#endif
+
+}
+
+/**************************************************************************************
+** Function         BTA_DmPcmResample
+**
+** Description      Down sampling utility to convert higher sampling rate into 8K/16bits
+**                  PCM samples.
+**
+** Parameters       p_src: pointer to the buffer where the original sampling PCM
+**                              are stored.
+**                  in_bytes:  Length of the input PCM sample buffer in byte.
+**                  p_dst:      pointer to the buffer which is to be used to store
+**                              the converted PCM samples.
+**
+**
+** Returns          INT32: number of samples converted.
+**
+**************************************************************************************/
+INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst)
+{
+    UINT32 out_sample;
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG1("bta_pcm_resample : insamples  %d",  (in_bytes  / bta_dm_pcm_cb.divisor));
+#endif
+    if(bta_dm_pcm_cb.can_be_filtered)
+    {
+        out_sample = (*bta_dm_pcm_cb.filter) (p_src, p_dst, (in_bytes  / bta_dm_pcm_cb.divisor),
+            bta_dm_pcm_cb.src_sps, (INT32 *) &bta_dm_pcm_cb.cur_pos, bta_dm_pcm_cb.overlap_area);
+    }
+    else
+    {
+        out_sample = (*bta_dm_pcm_cb.nofilter) (p_src, p_dst,
+            (in_bytes / bta_dm_pcm_cb.divisor), bta_dm_pcm_cb.src_sps);
+    }
+
+#if BTA_DM_SCO_DEBUG
+    APPL_TRACE_DEBUG1("bta_pcm_resample : outsamples  %d",  out_sample);
+#endif
+
+    return (out_sample * bta_dm_pcm_cb.sample_size);
+}
+#endif
diff --git a/bta/fs/bta_fs_cfg.c b/bta/fs/bta_fs_cfg.c
new file mode 100644
index 0000000..0bfffcd
--- /dev/null
+++ b/bta/fs/bta_fs_cfg.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ *  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 compile-time configurable constants for the BTA File
+ *  System.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_fs_api.h"
+
+/* Character used as path separator */
+#ifndef BTA_FS_PATH_SEPARATOR
+#define BTA_FS_PATH_SEPARATOR   ((char) 0x2f)   /* 0x2f ('/'), or 0x5c ('\') */
+#endif
+
+/* Maximum path length supported by MMI */
+#ifndef BTA_FS_PATH_LEN
+#define BTA_FS_PATH_LEN         294
+#endif
+
+#ifndef BTA_FS_FILE_LEN
+#define BTA_FS_FILE_LEN         256
+#endif
+
+const tBTA_FS_CFG bta_fs_cfg =
+{
+    BTA_FS_FILE_LEN,
+    BTA_FS_PATH_LEN,
+    BTA_FS_PATH_SEPARATOR
+};
+
+tBTA_FS_CFG *p_bta_fs_cfg = (tBTA_FS_CFG *)&bta_fs_cfg;
+
diff --git a/bta/fs/bta_fs_ci.c b/bta/fs/bta_fs_ci.c
new file mode 100644
index 0000000..589a591
--- /dev/null
+++ b/bta/fs/bta_fs_ci.c
@@ -0,0 +1,280 @@
+/******************************************************************************
+ *
+ *  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 is the implementation file for the file system call-in functions.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_fs_ci.h"
+#include "gki.h"
+#include "bd.h"
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_write
+**
+** Description      This function sends an event to IO indicating the phone
+**                  has written the number of bytes specified in the call-out
+**                  function, bta_fs_co_write(), and is ready for more data.
+**                  This function is used to control the TX data flow.
+**                  Note: The data buffer is released by the stack after
+**                        calling this function.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK or BTA_FS_CO_FAIL
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_write(int fd, tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+    tBTA_FS_CI_WRITE_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_FS_CI_WRITE_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_WRITE_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->fd = fd;
+        p_evt->status = status;
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_read
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  read in the requested amount of data specified in the
+**                  bta_fs_co_read() call-out function.  It should only be called
+**                  when the requested number of bytes has been read in, or after
+**                  the end of the file has been detected.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_FS_CO_OK if full buffer of data,
+**                           BTA_FS_CO_EOF if the end of file has been reached,
+**                           BTA_FS_CO_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_read(int fd, UINT16 num_bytes_read, tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+    tBTA_FS_CI_READ_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_FS_CI_READ_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_READ_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->fd        = fd;
+        p_evt->status    = status;
+        p_evt->num_read  = num_bytes_read;
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_open
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  finished opening a file for reading or writing.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK if file was opened in mode specified
+**                                          in the call-out function.
+**                           BTA_FS_CO_EACCES if the file exists, but contains
+**                                          the wrong access permissions.
+**                           BTA_FS_CO_FAIL if any other error has occurred.
+**                  file_size - The total size of the file
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_open(int fd, tBTA_FS_CO_STATUS status, UINT32 file_size, UINT16 evt)
+{
+    tBTA_FS_CI_OPEN_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_FS_CI_OPEN_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_OPEN_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->fd        = fd;
+        p_evt->status    = status;
+        p_evt->file_size = file_size;
+        p_evt->p_file    = NULL;
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_direntry
+**
+** Description      This function is called in response to the
+**                  bta_fs_co_getdirentry call-out function.
+**
+** Parameters       status - BTA_FS_CO_OK if p_entry points to a valid entry.
+**                           BTA_FS_CO_EODIR if no more entries (p_entry is ignored).
+**                           BTA_FS_CO_FAIL if any errors have occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_direntry(tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+    tBTA_FS_CI_GETDIR_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_FS_CI_GETDIR_EVT *)GKI_getbuf(sizeof(tBTA_FS_CI_GETDIR_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_resume
+**
+** Description      This function is called in response to the
+**                  bta_fs_co_resume call-out function.
+**
+** Parameters       p_sess_info - the stored session ID and related information.
+**                  timeout - the timeout for this suspended session.
+**                  ssn     - the stored session sequence number.
+**                  info    - the stored BTA specific information (like last active operation).
+**                  status  - BTA_FS_CO_OK if p_entry points to a valid entry.
+**                            BTA_FS_CO_FAIL if any errors have occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_resume (BD_ADDR_PTR p_addr, UINT8 *p_sess_info,
+                       UINT32 timeout, UINT32 offset, UINT8 ssn, UINT8 info,
+                       tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+    tBTA_FS_CI_RESUME_EVT  *p_evt;
+    UINT16  size = sizeof(tBTA_FS_CI_RESUME_EVT) + sizeof(BD_ADDR);
+
+    if ((p_evt = (tBTA_FS_CI_RESUME_EVT *)GKI_getbuf(size)) != NULL)
+    {
+        p_evt->p_addr       = NULL;
+        if (p_addr != NULL)
+        {
+            p_evt->p_addr   = (BD_ADDR_PTR)(p_evt + 1);
+            bdcpy(p_evt->p_addr, p_addr);
+        }
+        p_evt->hdr.event    = evt;
+        p_evt->p_sess_info  = p_sess_info;
+        p_evt->timeout      = timeout;
+        p_evt->offset       = offset;
+        p_evt->ssn          = ssn;
+        p_evt->info         = info;
+        p_evt->status       = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_action
+**
+** Description      This function is called in response to one of the action
+**                  call-out functions: bta_fs_co_copy, bta_fs_co_rename or
+**                  bta_fs_co_set_perms.
+**
+** Parameters       status  - BTA_FS_CO_OK if the action is succession.
+**                            BTA_FS_CO_FAIL if any errors have occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_action(tBTA_FS_CO_STATUS status, UINT16 evt)
+{
+    tBTA_FS_CI_ACTION_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_FS_CI_ACTION_EVT *) GKI_getbuf(sizeof(tBTA_FS_CI_ACTION_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->status    = status;
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_resume_op
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  finished opening a file for reading or writing on resume.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK if file was opened in mode specified
+**                                          in the call-out function.
+**                           BTA_FS_CO_EACCES if the file exists, but contains
+**                                          the wrong access permissions.
+**                           BTA_FS_CO_FAIL if any other error has occurred.
+**                  p_file - The file name associated with fd
+**                  file_size - The total size of the file
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_fs_ci_resume_op(int fd, tBTA_FS_CO_STATUS status, const char *p_file,
+                         UINT32 file_size, UINT16 evt)
+{
+    tBTA_FS_CI_OPEN_EVT  *p_evt;
+    UINT16  file_len = strlen(p_file) + 1;
+    UINT16  size = sizeof(tBTA_FS_CI_OPEN_EVT) + file_len;
+    char *p;
+
+    if ((p_evt = (tBTA_FS_CI_OPEN_EVT *) GKI_getbuf(size)) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->fd        = fd;
+        p_evt->status    = status;
+        p_evt->file_size = file_size;
+        p   = (char *)(p_evt + 1);
+        BCM_STRNCPY_S (p, file_len, p_file, file_len-1);
+        p[file_len] = '\0';
+        p_evt->p_file    = (const char *)p;
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
new file mode 100644
index 0000000..5cacf03
--- /dev/null
+++ b/bta/gatt/bta_gattc_act.c
@@ -0,0 +1,1802 @@
+/******************************************************************************
+ *
+ *  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 the GATT client action functions for the state
+ *  machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+
+#include "utl.h"
+#include "gki.h"
+#include "bd.h"
+#include "bta_sys.h"
+
+#include "bta_gattc_int.h"
+#include "l2c_api.h"
+
+
+#include <string.h>
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+                                 BOOLEAN connected, tGATT_DISCONN_REASON reason);
+
+static void  bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+                                  tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK bta_gattc_cl_cback =
+{
+    bta_gattc_conn_cback,
+    bta_gattc_cmpl_cback,
+    bta_gattc_disc_res_cback,
+    bta_gattc_disc_cmpl_cback,
+    NULL
+};
+
+/* opcode(tGATTC_OPTYPE) order has to be comply with internal event order */
+static UINT16 bta_gattc_opcode_to_int_evt[] =
+{
+    BTA_GATTC_API_READ_EVT,
+    BTA_GATTC_API_WRITE_EVT,
+    BTA_GATTC_API_EXEC_EVT
+};
+
+#if (BT_TRACE_VERBOSE == TRUE)
+static const char *bta_gattc_op_code_name[] =
+{
+    "Unknown",
+    "Discovery",
+    "Read",
+    "Write",
+    "Exec",
+    "Config",
+    "Notification",
+    "Indication"
+};
+#endif
+/*****************************************************************************
+**  Action Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_gattc_register
+**
+** Description      Register a GATT client application with BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC               cb_data;
+    UINT8                    i;
+    tBT_UUID                 *p_app_uuid = &p_data->api_reg.app_uuid;
+    tBTA_GATTC_INT_START_IF  *p_buf;
+
+
+    /* todo need to check duplicate uuid */
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+    {
+        if (!p_cb->cl_rcb[i].in_use)
+        {
+            if ((p_app_uuid == NULL) || (p_cb->cl_rcb[i].client_if = GATT_Register(p_app_uuid, &bta_gattc_cl_cback)) == 0)
+            {
+                APPL_TRACE_ERROR0("Register with GATT stack failed.");
+                cb_data.reg_oper.status = BTA_GATT_ERROR;
+            }
+            else
+
+            {
+                p_cb->cl_rcb[i].in_use = TRUE;
+                p_cb->cl_rcb[i].p_cback = p_data->api_reg.p_cback;
+                memcpy(&p_cb->cl_rcb[i].app_uuid, p_app_uuid, sizeof(tBT_UUID));
+
+                /* BTA use the same client interface as BTE GATT statck */
+                cb_data.reg_oper.client_if = p_cb->cl_rcb[i].client_if;
+// btla-specific ++
+                memcpy(&(cb_data.reg_oper.app_uuid),p_app_uuid,sizeof(tBT_UUID));
+// btla-specific --
+
+                cb_data.reg_oper.status = BTA_GATT_OK;
+
+                if ((p_buf = (tBTA_GATTC_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTC_INT_START_IF))) != NULL)
+                {
+                    p_buf->hdr.event    = BTA_GATTC_INT_START_IF_EVT;
+                    p_buf->client_if    = p_cb->cl_rcb[i].client_if;
+
+                    bta_sys_sendmsg(p_buf);
+                }
+                else
+                {
+                    cb_data.reg_oper.status = BTA_GATT_NO_RESOURCES;
+                    memset( &p_cb->cl_rcb[i], 0 , sizeof(tBTA_GATTC_RCB));
+                }
+                break;
+            }
+        }
+    }
+    /* callback with register event */
+    if (p_data->api_reg.p_cback)
+    {
+        (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_start_if
+**
+** Description      start an application interface.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_msg)
+{
+    if (bta_gattc_cl_get_regcb(p_msg->int_start_if.client_if) !=NULL )
+    {
+        GATT_StartIf(p_msg->int_start_if.client_if);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister_cmpl
+**
+** Description      De-Register a GATT client application with BTA completed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_int_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if)
+{
+    tBTA_GATTC_CBACK    *p_cback = p_clreg->p_cback;
+    tBTA_GATTC          cb_data;
+
+
+    APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if );
+
+    GATT_Deregister(p_clreg->client_if);
+    memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+
+    cb_data.reg_oper.client_if = client_if;
+    cb_data.reg_oper.status    = BTA_GATT_OK;
+
+    if (p_cback)
+        /* callback with de-register event */
+        (*p_cback)(BTA_GATTC_DEREG_EVT,  (tBTA_GATTC *)&cb_data);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister_cmpl
+**
+** Description      De-Register a GATT client application with BTA completed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_deregister_cmpl(tBTA_GATTC_RCB *p_clreg, tBTA_GATTC_IF client_if)
+{
+    tBTA_GATTC_INT_DEREG  *p_buf;
+
+    APPL_TRACE_DEBUG1("bta_gattc_deregister_cmpl client_if=%d", client_if );
+
+    if ((p_buf = (tBTA_GATTC_INT_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_INT_DEREG))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_INT_DEREG_EVT;
+        p_buf->client_if = client_if;
+        bta_sys_sendmsg(p_buf);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_gattc_deregister_cmpl unable to allocate buffer to complete dereg=%d", client_if);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister
+**
+** Description      De-Register a GATT client application with BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+
+    tBTA_GATTC_IF       client_if = p_data->int_dereg.client_if;
+    tBTA_GATTC_CBACK    *p_cback;
+    tBTA_GATTC          cb_data;
+    tBTA_GATTC_RCB      *p_clreg;
+
+
+    APPL_TRACE_DEBUG1("bta_gattc_int_deregister_cmpl client_if=%d", client_if );
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+    {
+        p_cback = p_clreg->p_cback;
+        GATT_Deregister(client_if);
+        memset(p_clreg, 0, sizeof(tBTA_GATTC_RCB));
+        cb_data.reg_oper.client_if = client_if;
+        cb_data.reg_oper.status    = BTA_GATT_OK;
+
+        if (p_cback)
+            /* callback with de-register event */
+            (*p_cback)(BTA_GATTC_DEREG_EVT,  (tBTA_GATTC *)&cb_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_gattc_int_deregister Deregister Failed, unknown client_if: %d", p_data->int_dereg.client_if);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_deregister
+**
+** Description      De-Register a GATT client application with BTA.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    UINT8               i;
+    BT_HDR              buf;
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(p_data->api_dereg.client_if)) != NULL)
+    {
+        if (p_clreg->num_clcb > 0)
+        {
+            /* close all CLCB related to this app */
+            for (i= 0; i < BTA_GATTC_CLCB_MAX; i ++)
+            {
+                if (p_cb->clcb[i].in_use && (p_cb->clcb[i].p_rcb == p_clreg))
+                {
+                    p_clreg->dereg_pending = TRUE;
+
+                    buf.event = BTA_GATTC_API_CLOSE_EVT;
+                    buf.layer_specific = p_cb->clcb[i].bta_conn_id;
+                    bta_gattc_close(&p_cb->clcb[i], (tBTA_GATTC_DATA *)&buf)  ;
+                }
+            }
+        }
+        else
+            bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_gattc_deregister Deregister Failed, unknown client_if: %d", p_data->api_dereg.client_if);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_api_open
+**
+** Description      process connect API request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    UINT16 event = ((BT_HDR *)p_msg)->event;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+    tBTA_GATTC_RCB *p_clreg = bta_gattc_cl_get_regcb(p_msg->api_conn.client_if);
+
+    if (p_clreg != NULL)
+    {
+        if (p_msg->api_conn.is_direct)
+        {
+            if ((p_clcb = bta_gattc_find_alloc_clcb(p_msg->api_conn.client_if,
+                                                    p_msg->api_conn.remote_bda)) != NULL)
+            {
+                bta_gattc_sm_execute(p_clcb, event, p_msg);
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("No resources to open a new connection.");
+
+                bta_gattc_send_open_cback(p_clreg,
+                                          BTA_GATT_NO_RESOURCES,
+                                          p_msg->api_conn.remote_bda,
+                                          BTA_GATT_INVALID_CONN_ID);
+            }
+        }
+        else
+        {
+            bta_gattc_init_bk_conn(&p_msg->api_conn, p_clreg);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_gattc_process_api_open Failed, unknown client_if: %d",
+                        p_msg->api_conn.client_if);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_api_open_cancel
+**
+** Description      process connect API request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    UINT16 event = ((BT_HDR *)p_msg)->event;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+    tBTA_GATTC_RCB *p_clreg;
+    tBTA_GATT_STATUS status = BTA_GATT_ERROR;
+
+    if (p_msg->api_cancel_conn.is_direct)
+    {
+        if ((p_clcb = bta_gattc_find_clcb_by_cif(p_msg->api_cancel_conn.client_if,
+                                                 p_msg->api_cancel_conn.remote_bda)) != NULL)
+        {
+            bta_gattc_sm_execute(p_clcb, event, p_msg);
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("No such connection need to be cancelled");
+
+            p_clreg = bta_gattc_cl_get_regcb(p_msg->api_cancel_conn.client_if);
+
+            if (p_clreg && p_clreg->p_cback)
+            {
+                (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+            }
+        }
+    }
+    else
+    {
+        bta_gattc_cancel_bk_conn(&p_msg->api_cancel_conn);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_open_error
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+
+    if ( p_clcb->p_rcb->p_cback )
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_open_error
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_ERROR0("Connection already opened. wrong state");
+
+    bta_gattc_send_open_cback(p_clcb->p_rcb,
+                              BTA_GATT_ALREADY_OPEN,
+                              p_clcb->bda,
+                              p_clcb->bta_conn_id);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_open_fail
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    bta_gattc_open_error(p_clcb, p_data);
+    /* open failure, remove clcb */
+    bta_gattc_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_open
+**
+** Description      Process API connection function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_DATA gattc_data;
+
+    /* open/hold a connection */
+    if (!GATT_Connect(p_clcb->p_rcb->client_if, p_data->api_conn.remote_bda, TRUE))
+    {
+        APPL_TRACE_ERROR0("Connection open failure");
+
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_OPEN_FAIL_EVT, p_data);
+    }
+    else
+    {
+        /* a connected remote device */
+        if (GATT_GetConnIdIfConnected(p_clcb->p_rcb->client_if,
+                                      p_data->api_conn.remote_bda,
+                                      &p_clcb->bta_conn_id))
+        {
+            gattc_data.hdr.layer_specific = p_clcb->bta_conn_id;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+        }
+        /* else wait for the callback event */
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_init_bk_conn
+**
+** Description      Process API Open for a background connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg)
+{
+    tBTA_GATT_STATUS         status = BTA_GATT_NO_RESOURCES;
+    UINT16                   conn_id;
+    tBTA_GATTC_CLCB         *p_clcb;
+    tBTA_GATTC_DATA         gattc_data;
+
+    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE))
+    {
+        /* alwaya call open to hold a connection */
+        if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE))
+        {
+            status = BTA_GATT_ERROR;
+            APPL_TRACE_ERROR0("bta_gattc_init_bk_conn failed");
+        }
+        else
+        {
+            status = BTA_GATT_OK;
+
+            /* if is a connected remote device */
+            if (GATT_GetConnIdIfConnected(p_data->client_if,
+                                          p_data->remote_bda,
+                                          &conn_id))
+            {
+                if ((p_clcb = bta_gattc_clcb_alloc(p_data->client_if, p_data->remote_bda)) != NULL)
+                {
+                    gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+                    /* open connection */
+                    bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CONN_EVT, &gattc_data);
+                    status = BTA_GATT_OK;
+                }
+            }
+        }
+    }
+
+    /* open failure, report OPEN_EVT */
+    if (status != BTA_GATT_OK)
+    {
+        bta_gattc_send_open_cback(p_clreg, status, p_data->remote_bda, BTA_GATT_INVALID_CONN_ID);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_bk_conn
+**
+** Description      Process API Cancel Open for a background connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+
+    /* remove the device from the bg connection mask */
+    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE))
+    {
+        if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE))
+        {
+            status = BTA_GATT_OK;
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("bta_gattc_cancel_bk_conn failed");
+        }
+    }
+    p_clreg = bta_gattc_cl_get_regcb(p_data->client_if);
+
+    if (p_clreg && p_clreg->p_cback)
+    {
+        (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_int_cancel_open_ok
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS status = BTA_GATT_OK;
+
+    if ( p_clcb->p_rcb->p_cback )
+    {
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+    }
+
+    bta_gattc_clcb_dealloc(p_clcb);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cancel_open
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+
+    if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE))
+    {
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_CANCEL_OPEN_OK_EVT, p_data);
+    }
+    else
+    {
+        if ( p_clcb->p_rcb->p_cback )
+        {
+            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_conn
+**
+** Description      receive connection callback from stack
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_IF   gatt_if;
+    APPL_TRACE_DEBUG1("bta_gattc_conn server cache state=%d",p_clcb->p_srcb->state);
+
+    if (p_data != NULL)
+    {
+        APPL_TRACE_DEBUG1("bta_gattc_conn conn_id=%d",p_data->hdr.layer_specific);
+
+        p_clcb->p_srcb->connected = TRUE;
+        p_clcb->bta_conn_id  = p_data->hdr.layer_specific;
+        GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda);
+
+        /* start database cache if needed */
+        if (p_clcb->p_srcb->p_srvc_cache == NULL)
+        {
+            if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+            {
+                p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_START_CACHE_EVT, p_data);
+            }
+            else /* cache is building */
+                p_clcb->state = BTA_GATTC_DISCOVER_ST;
+        }
+
+        else
+        {
+            /* a pending service handle change indication */
+            if (p_clcb->p_srcb->srvc_hdl_chg)
+            {
+                p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+                /* start discovery */
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+            }
+        }
+
+        if (p_clcb->p_rcb)
+        {
+            bta_gattc_send_open_cback(p_clcb->p_rcb,
+                                      BTA_GATT_OK,
+                                      p_clcb->bda,
+                                      p_clcb->bta_conn_id);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_close_fail
+**
+** Description      close a  connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC           cb_data;
+
+    if ( p_clcb->p_rcb->p_cback )
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+        cb_data.close.client_if = p_clcb->p_rcb->client_if;
+        cb_data.close.conn_id   = p_data->hdr.layer_specific;
+        bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+        cb_data.close.status    = BTA_GATT_ERROR;
+        cb_data.close.reason    = BTA_GATT_CONN_NONE;
+
+
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CLOSE_EVT, &cb_data);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_api_close
+**
+** Description      close a GATTC connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_CBACK    *p_cback = p_clcb->p_rcb->p_cback;
+    tBTA_GATTC_RCB      *p_clreg = p_clcb->p_rcb;
+    tBTA_GATTC           cb_data;
+
+    APPL_TRACE_DEBUG1("bta_gattc_close conn_id=%d",p_clcb->bta_conn_id);
+
+    if (p_data->hdr.event == BTA_GATTC_API_CLOSE_EVT)
+        p_clcb->status = GATT_Disconnect(p_clcb->bta_conn_id);
+
+    cb_data.close.client_if = p_clcb->p_rcb->client_if;
+    cb_data.close.conn_id   = p_clcb->bta_conn_id;
+    cb_data.close.status    = p_clcb->status;
+    cb_data.close.reason    = p_clcb->reason;
+    bdcpy(cb_data.close.remote_bda, p_clcb->bda);
+
+    if (p_clcb->status == BTA_GATT_OK)
+    {
+        /* if the srcb is no longer needed, reset the state */
+        if ( -- p_clcb->p_srcb->num_clcb == 0)
+        {
+            APPL_TRACE_DEBUG0("Update srcb connection status");
+            p_clcb->p_srcb->connected = FALSE;
+            p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+        }
+
+        bta_gattc_clcb_dealloc(p_clcb);
+    }
+
+    ( * p_cback)(BTA_GATTC_CLOSE_EVT,   (tBTA_GATTC *)&cb_data);
+
+    if (-- p_clreg->num_clcb == 0 && p_clreg->dereg_pending)
+    {
+        bta_gattc_deregister_cmpl(p_clreg, p_clreg->client_if);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_reset_discover_st
+**
+** Description      when a SRCB finished discovery, tell all related clcb.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb)
+{
+    tBTA_GATTC_CB   *p_cb = &bta_gattc_cb;
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+    {
+        if (p_cb->clcb[i].p_srcb == p_srcb)
+        {
+            bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_set_discover_st
+**
+** Description      when a SRCB start discovery, tell all related clcb and set
+**                  the state.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_set_discover_st(tBTA_GATTC_SERV *p_srcb)
+{
+    tBTA_GATTC_CB   *p_cb = &bta_gattc_cb;
+    UINT8   i;
+
+#if BLE_INCLUDED == TRUE
+    L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, FALSE);
+#endif
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++)
+    {
+        if (p_cb->clcb[i].p_srcb == p_srcb)
+        {
+            p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST;
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_discover
+**
+** Description      Start a discovery on server.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    /* pending operation, wait until it finishes */
+
+    APPL_TRACE_DEBUG1("bta_gattc_start_discover conn_id=%d",p_clcb->bta_conn_id);
+    if (p_clcb->p_q_cmd != NULL && p_clcb->auto_update == BTA_GATTC_NO_SCHEDULE &&
+        p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+    {
+        p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+        p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
+    }
+    else /* no pending operation, start discovery right away */
+    {
+        p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
+
+        if (p_clcb->p_srcb != NULL)
+        {
+            /* clear the service change mask */
+            p_clcb->p_srcb->srvc_hdl_chg = FALSE;
+            p_clcb->p_srcb->update_count = 0;
+
+            /* set all srcb related clcb into discovery ST */
+            bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+            if ( bta_gattc_init_cache(p_clcb->p_srcb) ||
+                 bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL) != BTA_GATT_OK)
+            {
+                APPL_TRACE_ERROR0("discovery on server failed");
+                bta_gattc_reset_discover_st(p_clcb->p_srcb);
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("unknown device, can not start discovery");
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_disc_cmpl
+**
+** Description      discovery on server is finished
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_DATA *p_q_cmd = p_clcb->p_q_cmd;
+    APPL_TRACE_DEBUG1("bta_gattc_disc_cmpl conn_id=%d",p_clcb->bta_conn_id);
+
+#if BLE_INCLUDED == TRUE
+    L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, TRUE);
+#endif
+    p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
+
+    /* release pending attribute list buffer */
+    utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
+
+    /* get any queued command to proceed */
+    if (p_q_cmd != NULL)
+    {
+        p_clcb->p_q_cmd = NULL;
+
+        bta_gattc_sm_execute(p_clcb, p_q_cmd->hdr.event, p_q_cmd);
+
+        utl_freebuf((void **)&p_q_cmd);
+
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read
+**
+** Description      Read an attribute
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16 handle = 0;
+    tGATT_READ_PARAM    read_param;
+    tBTA_GATTC_OP_CMPL  op_cmpl;
+
+    memset (&read_param, 0 ,sizeof(tGATT_READ_PARAM));
+    memset (&op_cmpl, 0 ,sizeof(tBTA_GATTC_OP_CMPL));
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                          &p_data->api_read.srvc_id,
+                                          &p_data->api_read.char_id,
+                                          p_data->api_read.descr_type)) == 0)
+        {
+            op_cmpl.status = BTA_GATT_ERROR;
+        }
+        else
+        {
+            read_param.by_handle.handle = handle;
+            read_param.by_handle.auth_req = p_data->api_read.auth_req;
+
+            op_cmpl.status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_BY_HANDLE, &read_param);
+        }
+
+        /* read fail */
+        if (op_cmpl.status != BTA_GATT_OK)
+        {
+            op_cmpl.op_code = GATTC_OPTYPE_READ;
+            op_cmpl.p_cmpl = NULL;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read_multi
+**
+** Description      read multiple
+**
+** Returns          None.
+*********************************************************************************/
+void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16              i, handle;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    tGATT_READ_PARAM    read_param;
+    tBTA_GATTC_OP_CMPL  op_cmpl;
+    tBTA_GATTC_ATTR_ID  *p_id;
+    tBT_UUID            dummy_uuid;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        memset(&dummy_uuid, 0, sizeof(tBT_UUID));
+        memset(&read_param, 0, sizeof(tGATT_READ_PARAM));
+
+        p_id = p_data->api_read_multi.p_id_list;
+
+        for (i = 0; i < p_data->api_read_multi.num_attr && p_id; i ++, p_id ++)
+        {
+            handle = 0;
+
+            if (p_id->id_type == BTA_GATT_TYPE_CHAR)
+            {
+                handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                     &p_id->id_value.char_id.srvc_id,
+                                     &p_id->id_value.char_id.char_id,
+                                     dummy_uuid);
+            }
+            else if (p_id->id_type == BTA_GATT_TYPE_CHAR_DESCR)
+            {
+                handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                     &p_id->id_value.char_descr_id.char_id.srvc_id,
+                                     &p_id->id_value.char_descr_id.char_id.char_id,
+                                     p_id->id_value.char_descr_id.descr_type);
+            }
+            else
+            {
+                APPL_TRACE_ERROR1("invalud ID type: %d", p_id->id_type);
+            }
+
+            if (handle == 0)
+            {
+                status = BTA_GATT_ERROR;
+                break;
+            }
+        }
+        if (status == BTA_GATT_OK)
+        {
+            read_param.read_multiple.num_handles = p_data->api_read_multi.num_attr;
+            read_param.read_multiple.auth_req = p_data->api_read_multi.auth_req;
+
+            status = GATTC_Read(p_clcb->bta_conn_id, GATT_READ_MULTIPLE, &read_param);
+        }
+
+        /* read fail */
+        if (status != BTA_GATT_OK)
+        {
+            memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+            op_cmpl.status  = status;
+            op_cmpl.op_code = GATTC_OPTYPE_READ;
+            op_cmpl.p_cmpl  = NULL;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_write
+**
+** Description      Write an attribute
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16              handle = 0;
+    tGATT_VALUE         attr = {0};
+    tBTA_GATTC_OP_CMPL  op_cmpl;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                          &p_data->api_write.srvc_id,
+                                          &p_data->api_write.char_id,
+                                          p_data->api_write.descr_type)) == 0)
+        {
+            status = BTA_GATT_ERROR;
+        }
+        else
+        {
+            attr.handle= handle;
+            attr.offset = p_data->api_write.offset;
+            attr.len    = p_data->api_write.len;
+            attr.auth_req = p_data->api_write.auth_req;
+
+            if (p_data->api_write.p_value)
+                memcpy(attr.value, p_data->api_write.p_value, p_data->api_write.len);
+
+            status = GATTC_Write(p_clcb->bta_conn_id, p_data->api_write.write_type, &attr);
+        }
+
+        /* write fail */
+        if (status != BTA_GATT_OK)
+        {
+            memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+            op_cmpl.status  = status;
+            op_cmpl.op_code = GATTC_OPTYPE_WRITE;
+            op_cmpl.p_cmpl  = NULL;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_execute
+**
+** Description      send execute write
+**
+** Returns          None.
+*********************************************************************************/
+void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_OP_CMPL  op_cmpl;
+    tBTA_GATT_STATUS    status;
+
+    if (bta_gattc_enqueue(p_clcb, p_data))
+    {
+        status = GATTC_ExecuteWrite(p_clcb->bta_conn_id, p_data->api_exec.is_execute);
+
+        if (status != BTA_GATT_OK)
+        {
+            memset(&op_cmpl, 0, sizeof(tBTA_GATTC_OP_CMPL));
+
+            op_cmpl.status  = status;
+            op_cmpl.op_code = GATTC_OPTYPE_EXE_WRITE;
+            op_cmpl.p_cmpl  = NULL;
+
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_OP_CMPL_EVT, (tBTA_GATTC_DATA *)&op_cmpl);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_confirm
+**
+** Description      send handle value confirmation
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT16 handle;
+    tBT_UUID    null_uuid = {0};
+
+    if ((handle = bta_gattc_id2handle(p_clcb->p_srcb,
+                                      &p_data->api_confirm.srvc_id,
+                                      &p_data->api_confirm.char_id,
+                                      null_uuid)) == 0)
+    {
+        APPL_TRACE_ERROR0("Can not map service/char ID into valid handle");
+    }
+    else
+    {
+        if (GATTC_SendHandleValueConfirm(p_data->api_confirm.hdr.layer_specific, handle)
+            != GATT_SUCCESS)
+        {
+            APPL_TRACE_ERROR1("bta_gattc_confirm to handle [0x%04x] failed", handle);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_read_cmpl
+**
+** Description      read complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_read_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    UINT8               event;
+    tBTA_GATTC          cb_data;
+    tBTA_GATT_READ_VAL  read_value;
+
+    memset(&cb_data, 0, sizeof(tBTA_GATTC));
+    memset(&read_value, 0, sizeof(tBTA_GATT_READ_VAL));
+
+    cb_data.read.status     = p_data->status;
+
+    if (p_data->p_cmpl != NULL && p_data->status == BTA_GATT_OK)
+    {
+        if (bta_gattc_handle2id(p_clcb->p_srcb,
+                                p_data->p_cmpl->att_value.handle,
+                                &cb_data.read.srvc_id,
+                                &cb_data.read.char_id,
+                                &cb_data.read.descr_type) == FALSE)
+        {
+            cb_data.read.status = BTA_GATT_INTERNAL_ERROR;
+            APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", p_data->p_cmpl->att_value.handle);
+        }
+        else
+        {
+            cb_data.read.status = bta_gattc_pack_read_cb_data(p_clcb->p_srcb,
+                                                              cb_data.read.descr_type,
+                                                              &p_data->p_cmpl->att_value,
+                                                              &read_value);
+            cb_data.read.p_value = &read_value;
+        }
+    }
+    else
+    {
+        cb_data.read.srvc_id = p_clcb->p_q_cmd->api_read.srvc_id;
+        cb_data.read.char_id = p_clcb->p_q_cmd->api_read.char_id;
+        cb_data.read.descr_type = p_clcb->p_q_cmd->api_read.descr_type;
+    }
+
+    event = (p_clcb->p_q_cmd->api_read.descr_type.len == 0) ? BTA_GATTC_READ_CHAR_EVT: BTA_GATTC_READ_DESCR_EVT;
+    cb_data.read.conn_id = p_clcb->bta_conn_id;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    /* read complete, callback */
+    ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_write_cmpl
+**
+** Description      read complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_write_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC      cb_data = {0};
+    UINT8          event;
+
+    cb_data.write.status     = p_data->status;
+
+    if (p_data->p_cmpl != NULL)
+    {
+        bta_gattc_handle2id(p_clcb->p_srcb, p_data->p_cmpl->handle,
+                            &cb_data.write.srvc_id, &cb_data.write.char_id,
+                            &cb_data.write.descr_type);
+    }
+    else
+    {
+        cb_data.write.srvc_id = p_clcb->p_q_cmd->api_write.srvc_id;
+        cb_data.write.char_id = p_clcb->p_q_cmd->api_write.char_id;
+        cb_data.write.descr_type = p_clcb->p_q_cmd->api_write.descr_type;
+    }
+
+    if (p_clcb->p_q_cmd->api_write.hdr.event == BTA_GATTC_API_WRITE_EVT &&
+        p_clcb->p_q_cmd->api_write.write_type == BTA_GATTC_WRITE_PREPARE)
+
+        event = BTA_GATTC_PREP_WRITE_EVT;
+
+    else if (p_clcb->p_q_cmd->api_write.descr_type.len == 0)
+
+        event = BTA_GATTC_WRITE_CHAR_EVT;
+
+    else
+        event = BTA_GATTC_WRITE_DESCR_EVT;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+    cb_data.write.conn_id = p_clcb->bta_conn_id;
+    /* write complete, callback */
+    ( *p_clcb->p_rcb->p_cback)(event, (tBTA_GATTC *)&cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_exec_cmpl
+**
+** Description      execute write complete
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_exec_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_OP_CMPL *p_data)
+{
+    tBTA_GATTC          cb_data;
+
+    utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+    p_clcb->status      = BTA_GATT_OK;
+
+    /* execute complete, callback */
+    cb_data.exec_cmpl.conn_id = p_clcb->bta_conn_id;
+    cb_data.exec_cmpl.status = p_data->status;
+
+    ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT,  &cb_data);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_op_cmpl
+**
+** Description      operation completed.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    UINT8           op = (UINT8)p_data->op_cmpl.op_code;
+    UINT8           mapped_op = 0;
+
+    APPL_TRACE_DEBUG1("bta_gattc_op_cmpl op = %d", op);
+
+    if (op == GATTC_OPTYPE_INDICATION || op == GATTC_OPTYPE_NOTIFICATION)
+    {
+        APPL_TRACE_ERROR0("unexpected operation, ignored");
+    }
+    else if (op >= GATTC_OPTYPE_READ)
+    {
+        if (p_clcb->p_q_cmd == NULL)
+        {
+            APPL_TRACE_ERROR0("No pending command");
+            return;
+        }
+        if (p_clcb->p_q_cmd->hdr.event != bta_gattc_opcode_to_int_evt[op - GATTC_OPTYPE_READ])
+        {
+            mapped_op = p_clcb->p_q_cmd->hdr.event - BTA_GATTC_API_READ_EVT + GATTC_OPTYPE_READ;
+            if ( mapped_op > GATTC_OPTYPE_INDICATION)   mapped_op = 0;
+
+#if (BT_TRACE_VERBOSE == TRUE)
+            APPL_TRACE_ERROR3("expect op:(%s :0x%04x), receive unexpected operation (%s).",
+                                bta_gattc_op_code_name[mapped_op] , p_clcb->p_q_cmd->hdr.event,
+                                bta_gattc_op_code_name[op]);
+#else
+            APPL_TRACE_ERROR3("expect op:(%u :0x%04x), receive unexpected operation (%u).",
+                                mapped_op , p_clcb->p_q_cmd->hdr.event, op);
+#endif
+            return;
+        }
+
+        /* service handle change void the response, discard it */
+        if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+        {
+            p_clcb->auto_update = BTA_GATTC_REQ_WAITING;
+            bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+        }
+        else if (op == GATTC_OPTYPE_READ)
+            bta_gattc_read_cmpl(p_clcb, &p_data->op_cmpl);
+
+        else if (op == GATTC_OPTYPE_WRITE)
+            bta_gattc_write_cmpl(p_clcb, &p_data->op_cmpl);
+
+        else if (op == GATTC_OPTYPE_EXE_WRITE)
+            bta_gattc_exec_cmpl(p_clcb, &p_data->op_cmpl);
+        /*
+        else if (op == GATTC_OPTYPE_CONFIG) // API to be added
+        {
+        }
+       */
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_op_cmpl
+**
+** Description      operation completed.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    /* receive op complete when discovery is started, ignore the response,
+        and wait for discovery finish and resent */
+    APPL_TRACE_DEBUG1("bta_gattc_ignore_op_cmpl op = %d", p_data->hdr.layer_specific);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_search
+**
+** Description      start a search in the local server cache
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATT_STATUS    status = GATT_INTERNAL_ERROR;
+    tBTA_GATTC cb_data;
+    APPL_TRACE_DEBUG1("bta_gattc_search conn_id=%d",p_clcb->bta_conn_id);
+    if (p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+    {
+        status = BTA_GATT_OK;
+        /* search the local cache of a server device */
+        bta_gattc_search_service(p_clcb, p_data->api_search.srvc_uuid);
+    }
+    cb_data.search_cmpl.status  = status;
+    cb_data.search_cmpl.conn_id = p_clcb->bta_conn_id;
+
+    /* end of search or no server cache available */
+    ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_CMPL_EVT,  &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_q_cmd
+**
+** Description      enqueue a command into control block, usually because discovery
+**                  operation is busy.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    bta_gattc_enqueue(p_clcb, p_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_open
+**
+** Description      open a NV cache for loading
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    bta_gattc_set_discover_st(p_clcb->p_srcb);
+
+    APPL_TRACE_DEBUG1("bta_gattc_cache_open conn_id=%d",p_clcb->bta_conn_id);
+    bta_gattc_co_cache_open(p_clcb->p_srcb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+                            p_clcb->bta_conn_id, FALSE);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_load
+**
+** Description      start cache loading by sending callout open cache
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_DEBUG2("bta_gattc_ci_open conn_id=%d server state=%d" ,
+                      p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_LOAD)
+    {
+        if (p_data->ci_open.status == BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
+                                    p_clcb->p_srcb->attr_index,
+                                    p_clcb->bta_conn_id);
+        }
+        else
+        {
+            /* cache open failure, start discovery */
+            bta_gattc_start_discover(p_clcb, NULL);
+        }
+    }
+    if (p_clcb->p_srcb->state == BTA_GATTC_SERV_SAVE)
+    {
+        if (p_data->ci_open.status == BTA_GATT_OK)
+        {
+            if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+            {
+                p_data->ci_open.status = BTA_GATT_ERROR;
+            }
+        }
+        if (p_data->ci_open.status != BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, p_clcb->bta_conn_id);
+            bta_gattc_reset_discover_st(p_clcb->p_srcb);
+
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_load
+**
+** Description      cache loading received.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+
+    APPL_TRACE_DEBUG2("bta_gattc_ci_load conn_id=%d load status=%d" ,
+                      p_clcb->bta_conn_id, p_data->ci_load.status );
+    bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+
+    if ((p_data->ci_load.status == BTA_GATT_OK ||
+         p_data->ci_load.status == BTA_GATT_MORE) &&
+        p_data->ci_load.num_attr > 0)
+    {
+        bta_gattc_rebuild_cache(p_clcb->p_srcb, p_data->ci_load.num_attr, p_data->ci_load.attr, p_clcb->p_srcb->attr_index);
+
+        if (p_data->ci_load.status == BTA_GATT_OK)
+        {
+            p_clcb->p_srcb->attr_index = 0;
+            bta_gattc_reset_discover_st(p_clcb->p_srcb);
+
+        }
+        else /* load more */
+        {
+            p_clcb->p_srcb->attr_index += p_data->ci_load.num_attr;
+
+            bta_gattc_co_cache_load(p_clcb->p_srcb->server_bda,
+                                    BTA_GATTC_CI_CACHE_LOAD_EVT,
+                                    p_clcb->p_srcb->attr_index,
+                                    p_clcb->bta_conn_id);
+        }
+    }
+    else
+    {
+        p_clcb->p_srcb->attr_index = 0;
+        /* cache open failure, start discovery */
+        bta_gattc_start_discover(p_clcb, NULL);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_load
+**
+** Description      cache loading received.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_DEBUG1("bta_gattc_ci_save conn_id=%d  " ,
+                      p_clcb->bta_conn_id   );
+
+    if (!bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id))
+    {
+        p_clcb->p_srcb->attr_index = 0;
+        bta_gattc_co_cache_close(p_clcb->p_srcb->server_bda, 0);
+        bta_gattc_reset_discover_st(p_clcb->p_srcb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_fail
+**
+** Description      report API call failure back to apps
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    if (p_clcb->status == BTA_GATT_OK)
+    {
+        APPL_TRACE_ERROR1("operation not supported at current state [%d]", p_clcb->state);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_cback
+**                  bta_gattc_cmpl_cback
+**
+** Description      callback functions to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_gattc_conn_cback(tGATT_IF gattc_if, BD_ADDR bda, UINT16 conn_id,
+                                 BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+    BT_HDR          *p_buf;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+    APPL_TRACE_DEBUG4("bta_gattc_conn_cback: cif = %d connected = %d conn_id = %d reaosn = 0x%04x",
+                      gattc_if, connected, conn_id, reason);
+
+    if (connected)
+    {
+        /* outgoing connection : locate a logic channel */
+        if ((p_clcb = bta_gattc_find_clcb_by_cif(gattc_if, bda)) == NULL)
+        {
+
+#if BLE_INCLUDED == TRUE
+            /* for a background connection */
+            if (L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER &&
+                bta_gattc_check_bg_conn(gattc_if, bda))
+            {
+                /* allocate a new channel */
+                p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+            }
+#endif
+        }
+        if (p_clcb != NULL)
+        {
+            p_clcb->bta_conn_id = conn_id;
+
+            if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+            {
+                p_buf->event = BTA_GATTC_INT_CONN_EVT;
+                p_buf->layer_specific = conn_id;
+
+                bta_sys_sendmsg(p_buf);
+            }
+        }
+    }
+    else
+    {
+        /* connection attempt timeout, send connection callback event */
+        if (reason == GATT_CONN_CANCEL )
+        {
+            p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+            p_clcb->bta_conn_id = conn_id;
+        }
+        if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
+        {
+            if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+            {
+                p_buf->event = BTA_GATTC_INT_DISCONN_EVT;
+                p_buf->layer_specific = conn_id;
+                p_clcb->reason        = reason;
+
+                bta_sys_sendmsg(p_buf);
+            }
+        }
+        else
+        {
+            APPL_TRACE_DEBUG1(" connection ID: [%d] not used by BTA", conn_id);
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_srvc_chg_ind
+**
+** Description      process service change indication.
+**
+** Returns          None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_process_srvc_chg_ind(UINT16 conn_id,
+                                       tBTA_GATTC_RCB      *p_clrcb,
+                                       tBTA_GATTC_SERV     *p_srcb,
+                                       tBTA_GATTC_CLCB      *p_clcb,
+                                       tBTA_GATTC_NOTIFY    *p_notify,
+                                       UINT16 handle)
+{
+    tBT_UUID        gattp_uuid, srvc_chg_uuid;
+    BOOLEAN         processed = FALSE;
+    UINT8           i;
+
+    gattp_uuid.len = 2;
+    gattp_uuid.uu.uuid16 = UUID_SERVCLASS_GATT_SERVER;
+
+    srvc_chg_uuid.len = 2;
+    srvc_chg_uuid.uu.uuid16 = GATT_UUID_GATT_SRV_CHGD;
+
+    if (bta_gattc_uuid_compare(p_notify->char_id.srvc_id.id.uuid, gattp_uuid, TRUE) &&
+        bta_gattc_uuid_compare(p_notify->char_id.char_id.uuid, srvc_chg_uuid, TRUE))
+    {
+        processed = TRUE;
+        /* mark service handle change pending */
+        p_srcb->srvc_hdl_chg = TRUE;
+        /* clear up all notification/indication registration */
+        bta_gattc_clear_notif_registration(conn_id);
+        /* service change indication all received, do discovery update */
+        if ( ++ p_srcb->update_count == bta_gattc_num_reg_app())
+        {
+            /* not an opened connection; or connection busy */
+            /* search for first available clcb and start discovery */
+            if (p_clcb == NULL || (p_clcb && p_clcb->p_q_cmd != NULL))
+            {
+                for (i = 0 ; i < BTA_GATTC_CLCB_MAX; i ++)
+                {
+                    if (bta_gattc_cb.clcb[i].in_use &&
+                        bta_gattc_cb.clcb[i].p_srcb == p_srcb &&
+                        bta_gattc_cb.clcb[i].p_q_cmd == NULL)
+                    {
+                        p_clcb = &bta_gattc_cb.clcb[i];
+                        break;
+                    }
+                }
+            }
+            /* send confirmation here if this is an indication, it should always be */
+            GATTC_SendHandleValueConfirm(conn_id, handle);
+
+            /* if connection available, refresh cache by doing discovery now */
+            if (p_clcb != NULL)
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+        }
+        /* notify applicationf or service change */
+        if (p_clrcb->p_cback != NULL)
+        {
+            APPL_TRACE_ERROR0("bta_gattc_process_srvc_chg_ind 2");
+           (* p_clrcb->p_cback)(BTA_GATTC_SRVC_CHG_EVT, (tBTA_GATTC *)p_srcb->server_bda);
+        }
+
+    }
+
+    return processed;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_proc_other_indication
+**
+** Description      process all non-service change indication/notification.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_proc_other_indication(tBTA_GATTC_CLCB *p_clcb, UINT8 op,
+                                     tGATT_CL_COMPLETE *p_data,
+                                     tBTA_GATTC_NOTIFY *p_notify)
+{
+    APPL_TRACE_DEBUG2("bta_gattc_proc_other_indication check \
+                       p_data->att_value.handle=%d p_data->handle=%d",
+                       p_data->att_value.handle, p_data->handle);
+    APPL_TRACE_DEBUG1("is_notify", p_notify->is_notify);
+
+    p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? FALSE : TRUE;
+    p_notify->len = p_data->att_value.len;
+    bdcpy(p_notify->bda, p_clcb->bda);
+    memcpy(p_notify->value, p_data->att_value.value, p_data->att_value.len);
+    p_notify->conn_id = p_clcb->bta_conn_id;
+
+    if (p_clcb->p_rcb->p_cback)
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_NOTIF_EVT,  (tBTA_GATTC *)p_notify);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_process_indicate
+**
+** Description      process indication/notification.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_process_indicate(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_CL_COMPLETE *p_data)
+{
+    UINT16              handle = p_data->att_value.handle;
+    tBTA_GATTC_CLCB     *p_clcb ;
+    tBTA_GATTC_RCB      *p_clrcb = NULL;
+    tBTA_GATTC_SERV     *p_srcb = NULL;
+    tBTA_GATTC_NOTIFY   notify;
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_IF       gatt_if;
+
+    if (!GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+    {
+        APPL_TRACE_ERROR0("indication/notif for unknown app");
+        return;
+    }
+
+    if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) == NULL)
+    {
+        APPL_TRACE_ERROR0("indication/notif for unregistered app");
+        return;
+    }
+
+    if ((p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+    {
+        APPL_TRACE_ERROR0("indication/notif for unknown device, ignore");
+        return;
+    }
+
+    p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (bta_gattc_handle2id(p_srcb, handle,
+                            &notify.char_id.srvc_id,
+                            &notify.char_id.char_id,
+                            &notify.descr_type))
+    {
+        /* if non-service change indication/notification, forward to application */
+        if (!bta_gattc_process_srvc_chg_ind(conn_id, p_clrcb, p_srcb, p_clcb, &notify, handle))
+        {
+            /* if app registered for the notification */
+            if (bta_gattc_check_notif_registry(p_clrcb, p_srcb, &notify))
+            {
+                /* connection not open yet */
+                if (p_clcb == NULL)
+                {
+                    if ((p_clcb = bta_gattc_clcb_alloc(gatt_if, remote_bda)) != NULL)
+                    {
+                        p_clcb->bta_conn_id = conn_id;
+
+                        /* send connection event */
+                        bta_gattc_send_open_cback(p_clrcb,
+                                                  BTA_GATT_OK,
+                                                  remote_bda,
+                                                  conn_id);
+                    }
+                    else
+                    {
+                        APPL_TRACE_ERROR0("No resources");
+                    }
+                }
+
+                if (p_clcb != NULL)
+                    bta_gattc_proc_other_indication(p_clcb, op, p_data, &notify);
+            }
+            /* no one intersted and need ack? */
+            else if (op == GATTC_OPTYPE_INDICATION)
+            {
+                APPL_TRACE_DEBUG0("no one interested, ack now");
+                GATTC_SendHandleValueConfirm(conn_id, handle);
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cmpl_cback
+**
+** Description      client operation complete callback register with BTE GATT.
+**
+** Returns          None.
+**
+*******************************************************************************/
+static void  bta_gattc_cmpl_cback(UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status,
+                                  tGATT_CL_COMPLETE *p_data)
+{
+    tBTA_GATTC_CLCB     *p_clcb ;
+    tBTA_GATTC_OP_CMPL  *p_buf;
+    UINT16              len = sizeof(tBTA_GATTC_OP_CMPL) + sizeof(tGATT_CL_COMPLETE);
+
+    APPL_TRACE_DEBUG3("bta_gattc_cmpl_cback: conn_id = %d op = %d status = %d",
+                      conn_id, op, status);
+
+    /* notification and indication processed right away */
+    if (op == GATTC_OPTYPE_NOTIFICATION || op == GATTC_OPTYPE_INDICATION)
+    {
+        bta_gattc_process_indicate(conn_id, op, p_data);
+        return;
+    }
+    /* for all other operation, not expected if w/o connection */
+    else if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) == NULL)
+    {
+        APPL_TRACE_ERROR1("bta_gattc_cmpl_cback unknown conn_id =  %d, ignore data", conn_id);
+        return;
+    }
+
+
+    if ((p_buf = (tBTA_GATTC_OP_CMPL *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+        p_buf->hdr.event = BTA_GATTC_OP_CMPL_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->status = status;
+        p_buf->op_code = op;
+
+        if (p_data != NULL)
+        {
+            p_buf->p_cmpl = (tGATT_CL_COMPLETE *)(p_buf + 1);
+            memcpy(p_buf->p_cmpl, p_data, sizeof(tGATT_CL_COMPLETE));
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+
+    return;
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
new file mode 100644
index 0000000..1cace7d
--- /dev/null
+++ b/bta/gatt/bta_gattc_api.c
@@ -0,0 +1,934 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the implementation of the API for GATT module of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gatt_reg =
+{
+    bta_gattc_hdl_event,
+    NULL        /* need a disable functino to be called when BT is disabled */
+};
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTC module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_client_cb - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb)
+{
+    tBTA_GATTC_API_REG  *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_GATTC, &bta_gatt_reg);
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_GATTC_API_REG *) GKI_getbuf(sizeof(tBTA_GATTC_API_REG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTC_API_REG_EVT;
+        if (p_app_uuid != NULL)
+            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+        p_buf->p_cback      = p_client_cb;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppDeregister
+**
+** Description      This function is called to deregister an application
+**                  from BTA GATTC module.
+**
+** Parameters       client_if - client interface identifier.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_AppDeregister(tBTA_GATTC_IF client_if)
+{
+    tBTA_GATTC_API_DEREG  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTC_API_DEREG))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_DEREG_EVT;
+        p_buf->client_if = client_if;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Open
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTC_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_OPEN_EVT;
+
+        p_buf->client_if = client_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTC_API_CANCEL_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTC_API_CANCEL_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTC_API_CANCEL_OPEN_EVT;
+
+        p_buf->client_if = client_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Close
+**
+** Description      Close a connection to a GATT server.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Close(UINT16 conn_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTC_API_CLOSE_EVT;
+
+        p_buf->layer_specific = conn_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ServiceSearchRequest
+**
+** Description      This function is called to request a GATT service discovery
+**                    on a GATT server. This function report service search result
+**                  by a callback event, and followed by a service search complete
+**                  event.
+**
+** Parameters       conn_id: connection ID.
+**                  p_srvc_uuid: a UUID of the service application is interested in.
+**                              If Null, discover for all services.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ServiceSearchRequest (UINT16 conn_id, tBT_UUID *p_srvc_uuid)
+{
+    tBTA_GATTC_API_SEARCH  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTC_API_SEARCH) + sizeof(tBT_UUID);
+
+    if ((p_buf = (tBTA_GATTC_API_SEARCH *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_SEARCH_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        if (p_srvc_uuid)
+        {
+            memcpy(&p_buf->srvc_uuid, p_srvc_uuid, sizeof(tBT_UUID));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstChar
+**
+** Description      This function is called to find the first charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                          tBT_UUID *p_char_uuid_cond,
+                                          tBTA_GATTC_CHAR_ID *p_char_result,
+                                          tBTA_GATT_CHAR_PROP *p_property)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_srvc_id || !p_char_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR, p_srvc_id, NULL,
+                                        p_char_uuid_cond, &p_char_result->char_id, p_property))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_char_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextChar
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_char_id: start the characteristic search from the next record
+**                           after the one identified by char_id.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
+                                         tBTA_GATTC_CHAR_ID *p_start_char_id,
+                                         tBT_UUID           *p_char_uuid_cond,
+                                         tBTA_GATTC_CHAR_ID *p_char_result,
+                                         tBTA_GATT_CHAR_PROP    *p_property)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_char_id || !p_char_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR,
+                                        &p_start_char_id->srvc_id,
+                                        &p_start_char_id->char_id,
+                                        p_char_uuid_cond,
+                                        &p_char_result->char_id,
+                                        p_property))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_char_result->srvc_id, &p_start_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstCharDescr
+**
+** Description      This function is called to find the first charatceristic descriptor of the
+**                  charatceristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
+**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+**                               characteristic.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                                tBT_UUID *p_descr_uuid_cond,
+                                                tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_char_id || !p_descr_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                        &p_char_id->srvc_id,
+                                        &p_char_id->char_id,
+                                        p_descr_uuid_cond,
+                                        &p_descr_result->char_id.char_id,
+                                        NULL))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+        memcpy(&p_descr_result->char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
+    }
+
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextCharDescr
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_descr_id: start the characteristic search from the next record
+**                           after the one identified by p_start_descr_id.
+**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+**                               the first available characteristic descriptor.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+                                             tBT_UUID           *p_descr_uuid_cond,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_descr_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_descr_id || !p_descr_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    memset(p_descr_result, 0, sizeof(tBTA_GATTC_CHAR_DESCR_ID));
+
+    if ((status = bta_gattc_query_cache(conn_id, BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+                                        &p_start_descr_id->char_id.srvc_id,
+                                        &p_start_descr_id->char_id.char_id,
+                                        p_descr_uuid_cond,
+                                        &p_descr_result->char_id.char_id,
+                                        (void *)&p_start_descr_id->descr_type))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_descr_result->descr_type, &p_descr_result->char_id.char_id.uuid, sizeof(tBT_UUID));
+        memcpy(&p_descr_result->char_id, p_start_descr_id, sizeof(tBTA_GATTC_CHAR_ID));
+    }
+
+    return status;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstIncludedService
+**
+** Description      This function is called to find the first included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                                    tBT_UUID *p_uuid_cond, tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_srvc_id || !p_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                        p_srvc_id,
+                                        NULL,
+                                        p_uuid_cond,
+                                        &p_result->incl_svc_id.id,
+                                        (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_result->srvc_id, p_srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextIncludedService
+**
+** Description      This function is called to find the next included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_id: start the search from the next record
+**                                  after the one identified by p_start_id.
+**                  p_uuid_cond: Included service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+                                                   tBTA_GATTC_INCL_SVC_ID *p_start_id,
+                                                   tBT_UUID               *p_uuid_cond,
+                                                   tBTA_GATTC_INCL_SVC_ID *p_result)
+{
+    tBTA_GATT_STATUS    status;
+
+    if (!p_start_id || !p_result)
+        return BTA_GATT_ILLEGAL_PARAMETER;
+
+    if ((status = bta_gattc_query_cache(conn_id,
+                                        BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+                                        &p_start_id->srvc_id,
+                                        &p_start_id->incl_svc_id.id,
+                                        p_uuid_cond,
+                                        &p_result->incl_svc_id.id,
+                                        (tBTA_GATT_CHAR_PROP *)&p_result->incl_svc_id.is_primary))
+        == BTA_GATT_OK)
+    {
+        memcpy(&p_result->srvc_id, &p_start_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharacteristic
+**
+** Description      This function is called to read a service's characteristics of
+**                    the given characteritisc ID.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_char_id - characteritic ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharacteristic(UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                  tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharDescr
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+                              tBTA_GATTC_CHAR_DESCR_ID  *p_descr_id,
+                              tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_READ *) GKI_getbuf(sizeof(tBTA_GATTC_API_READ))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_READ));
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+        memcpy(&p_buf->descr_type, &p_descr_id->descr_type, sizeof(tBT_UUID));
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadMultiple
+**
+** Description      This function is called to read multiple characteristic or
+**                  characteristic descriptors.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_read_multi - pointer to the read multiple parameter.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+                            tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_READ_MULTI  *p_buf;
+    tBTA_GATTC_ATTR_ID          *p_value;
+    UINT16      len = (UINT16)(sizeof(tBTA_GATTC_API_READ_MULTI) +
+                               p_read_multi->num_attr * sizeof(tBTA_GATTC_ATTR_ID));
+    UINT8       i;
+
+    if ((p_buf = (tBTA_GATTC_API_READ_MULTI *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_READ_MULTI_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        p_buf->num_attr = p_read_multi->num_attr;
+
+        if (p_buf->num_attr > 0)
+        {
+            p_buf->p_id_list = p_value = (tBTA_GATTC_ATTR_ID *)(p_buf + 1);
+
+            for (i = 0; i < p_buf->num_attr; i ++, p_value ++)
+            {
+                memcpy(p_value, &p_read_multi->id_list[i], sizeof(tBTA_GATTC_ATTR_ID));
+            }
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharValue
+**
+** Description      This function is called to write characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to write.
+**                    write_type - type of write.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharValue ( UINT16 conn_id,
+                                tBTA_GATTC_CHAR_ID *p_char_id,
+                                tBTA_GATTC_WRITE_TYPE  write_type,
+                                UINT16 len,
+                                UINT8 *p_value,
+                                tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        p_buf->write_type = write_type;
+        p_buf->len = len;
+
+        if (p_value && len > 0)
+        {
+            p_buf->p_value = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->p_value, p_value, len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharDescr
+**
+** Description      This function is called to write characteristic descriptor value.
+**
+** Parameters       conn_id - connection ID
+**                    p_char_descr_id - characteristic descriptor ID to write.
+**                  write_type - write type.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+                               tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                               tBTA_GATTC_WRITE_TYPE  write_type,
+                               tBTA_GATT_UNFMT      *p_data,
+                               tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + p_data->len;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_descr_id->char_id.srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_descr_id->char_id.char_id, sizeof(tBTA_GATT_ID));
+        memcpy(&p_buf->descr_type, &p_char_descr_id->descr_type, sizeof(tBT_UUID));
+        p_buf->write_type = write_type;
+
+        if (p_data && p_data->len != 0)
+        {
+            p_buf->p_value  = (UINT8 *)(p_buf + 1);
+            p_buf->len      = p_data->len;
+            /* pack the descr data */
+            memcpy(p_buf->p_value, p_data->p_value, p_data->len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_PrepareWrite
+**
+** Description      This function is called to prepare write a characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - GATT characteritic ID of the service.
+**                  offset - offset of the write value.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_PrepareWrite  (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                              UINT16 offset, UINT16 len, UINT8 *p_value,
+                              tBTA_GATT_AUTH_REQ auth_req)
+{
+    tBTA_GATTC_API_WRITE  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf((UINT16)(sizeof(tBTA_GATTC_API_WRITE) + len))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_WRITE) + len);
+
+        p_buf->hdr.event = BTA_GATTC_API_WRITE_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->auth_req = auth_req;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        p_buf->write_type = BTA_GATTC_WRITE_PREPARE;
+        p_buf->offset   = offset;
+        p_buf->len = len;
+
+        if (p_value && len > 0)
+        {
+            p_buf->p_value = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->p_value, p_value, len);
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ExecuteWrite
+**
+** Description      This function is called to execute write a prepare write sequence.
+**
+** Parameters       conn_id - connection ID.
+**                    is_execute - execute or cancel.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute)
+{
+    tBTA_GATTC_API_EXEC  *p_buf;
+
+    if ((p_buf = (tBTA_GATTC_API_EXEC *) GKI_getbuf((UINT16)sizeof(tBTA_GATTC_API_EXEC))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_EXEC));
+
+        p_buf->hdr.event = BTA_GATTC_API_EXEC_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        p_buf->is_execute = is_execute;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTC_SendIndConfirm
+**
+** Description      This function is called to send handle value confirmation.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to confirm.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_API_CONFIRM  *p_buf;
+
+    APPL_TRACE_API3("BTA_GATTC_SendIndConfirm conn_id=%d service uuid1=0x%x char uuid=0x%x",
+                    conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16); //toto
+
+    if ((p_buf = (tBTA_GATTC_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTC_API_CONFIRM));
+
+        p_buf->hdr.event = BTA_GATTC_API_CONFIRM_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+
+        memcpy(&p_buf->srvc_id, &p_char_id->srvc_id, sizeof(tBTA_GATT_SRVC_ID));
+        memcpy(&p_buf->char_id, &p_char_id->char_id, sizeof(tBTA_GATT_ID));
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_RegisterForNotifications
+**
+** Description      This function is called to register for notification of a service.
+**
+** Parameters       client_if - client interface.
+**                  bda - target GATT server.
+**                  p_char_id - pointer to GATT characteristic ID.
+**
+** Returns          OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF client_if,
+                                                     BD_ADDR bda,
+                                                     tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
+    UINT8               i;
+
+    if (!p_char_id)
+    {
+        APPL_TRACE_ERROR0("deregistration failed, unknow char id");
+        return status;
+    }
+
+    /* lock other GKI task */
+    GKI_sched_lock();
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+    {
+        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+        {
+            if (!p_clreg->notif_reg[i].in_use)
+            {
+                memset(&p_clreg->notif_reg, 0, sizeof(tBTA_GATTC_NOTIF_REG));
+
+                p_clreg->notif_reg[i].in_use = TRUE;
+                memcpy(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN);
+                memcpy(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID));
+
+                status = BTA_GATT_OK;
+                break;
+            }
+        }
+        if (i == BTA_GATTC_NOTIF_REG_MAX)
+        {
+            status = BTA_GATT_NO_RESOURCES;
+            APPL_TRACE_ERROR0("Max Notification Reached, registration failed.");
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Client_if: %d Not Registered", client_if);
+    }
+
+    GKI_sched_unlock();
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_DeregisterForNotifications
+**
+** Description      This function is called to de-register for notification of a service.
+**
+** Parameters       client_if - client interface.
+**                  bda - target GATT server.
+**                  p_char_id - pointer to GATT characteristic ID.
+**
+** Returns          OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF client_if,
+                                                       BD_ADDR bda,
+                                                       tBTA_GATTC_CHAR_ID *p_char_id)
+{
+    tBTA_GATTC_RCB      *p_clreg;
+    tBTA_GATT_STATUS    status = BTA_GATT_ILLEGAL_PARAMETER;
+    UINT8               i;
+
+    if (!p_char_id)
+    {
+        APPL_TRACE_ERROR0("deregistration failed, unknow char id");
+        return status;
+    }
+
+    /* lock other GKI task */
+    GKI_sched_lock();
+
+    if ((p_clreg = bta_gattc_cl_get_regcb(client_if)) != NULL)
+    {
+        for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+        {
+            if (p_clreg->notif_reg[i].in_use &&
+                !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+                !memcmp(&p_clreg->notif_reg[i].char_id, p_char_id, sizeof(tBTA_GATTC_CHAR_ID)))
+            {
+                APPL_TRACE_DEBUG0("Deregistered.");
+
+                memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+                status = BTA_GATT_OK;
+                break;
+            }
+        }
+        if (i == BTA_GATTC_NOTIF_REG_MAX)
+        {
+            status = BTA_GATT_ERROR;
+
+            APPL_TRACE_ERROR0("registration not found");
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Client_if: %d Not Registered", client_if);
+    }
+
+    GKI_sched_unlock();
+
+    return status;
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
new file mode 100644
index 0000000..3774df4
--- /dev/null
+++ b/bta/gatt/bta_gattc_cache.c
@@ -0,0 +1,1597 @@
+/******************************************************************************
+ *
+ *  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 the GATT client discovery procedures and cache
+ *  related functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "sdp_api.h"
+#include "sdpdefs.h"
+#include "bta_gattc_int.h"
+#include "btm_api.h"
+
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb);
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb);
+
+#define BTA_GATT_SDP_DB_SIZE 750
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+static char *bta_gattc_attr_type[] =
+{
+    "I", /* Included Service */
+    "C", /* Characteristic */
+    "D" /* Characteristic Descriptor */
+};
+/* utility functions */
+
+/*******************************************************************************
+**
+** Function         bta_gattc_display_cache_server
+**
+** Description      debug function to display the server cache.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gattc_display_cache_server(tBTA_GATTC_CACHE *p_cache)
+{
+    UINT8 i = 0, j;
+    tBTA_GATTC_CACHE    *p_cur_srvc = p_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+
+    APPL_TRACE_ERROR0("<================Start Server Cache =============>");
+
+    while (p_cur_srvc)
+    {
+        APPL_TRACE_ERROR6("Service[%d]: handle[%d ~ %d] %s[0x%04x] inst[%d]",
+                          i, p_cur_srvc->s_handle, p_cur_srvc->e_handle,
+                          ((p_cur_srvc->service_uuid.id.uuid.len == 2) ? "uuid16" : "uuid128"),
+                          p_cur_srvc->service_uuid.id.uuid.uu.uuid16,
+                          p_cur_srvc->service_uuid.id.inst_id);
+        i ++;
+
+        p_attr = p_cur_srvc->p_attr;
+
+        for (j = 0; p_attr; j ++ )
+        {
+            APPL_TRACE_ERROR6("\t Attr[0x%04x] handle[%d] uuid[0x%04x] inst[%d] type[%s] prop[0x%1x]",
+                              j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id,
+                              bta_gattc_attr_type[p_attr->attr_type], p_attr->property);
+
+            p_attr = p_attr->p_next;
+        }
+        p_cur_srvc = p_cur_srvc->p_next;
+    }
+
+    APPL_TRACE_ERROR0("<================End Server Cache =============>");
+    APPL_TRACE_ERROR0(" ");
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_display_explore_record
+**
+** Description      debug function to display the exploration list
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gattc_display_explore_record(tBTA_GATTC_ATTR_REC *p_rec, UINT8 num_rec)
+{
+    UINT8 i;
+    tBTA_GATTC_ATTR_REC *pp = p_rec;
+
+    APPL_TRACE_ERROR0("<================Start Explore Queue =============>");
+    for (i = 0; i < num_rec; i ++, pp ++)
+    {
+        APPL_TRACE_ERROR5("\t rec[%d] uuid[0x%04x] s_handle[%d] e_handle[%d] is_primary[%d]",
+                          i + 1, pp->uuid.uu.uuid16, pp->s_handle, pp->e_handle, pp->is_primary);
+    }
+    APPL_TRACE_ERROR0("<================ End Explore Queue =============>");
+    APPL_TRACE_ERROR0(" ");
+
+}
+#endif  /* BTA_GATT_DEBUG == TRUE */
+
+
+/*******************************************************************************
+**
+** Function         bta_gattc_alloc_cache_buf
+**
+** Description      Allocate a GKI buffer for database cache.
+**
+** Returns          status
+**
+*******************************************************************************/
+BT_HDR *bta_gattc_alloc_cache_buf(tBTA_GATTC_SERV *p_srvc_cb)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getpoolbuf(GATT_DB_POOL_ID)) == NULL)
+    {
+        APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed.");
+        utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+        p_srvc_cb->free_byte = 0;
+    }
+    else
+    {
+        memset(p_buf, 0, GKI_get_buf_size(p_buf));
+        p_srvc_cb->p_free = (UINT8 *) p_buf;
+        p_srvc_cb->free_byte = GKI_get_buf_size(p_buf);
+
+        /* link into buffer queue */
+        GKI_enqueue(&p_srvc_cb->cache_buffer, p_buf);
+    }
+#if BTA_GATT_DEBUG== TRUE
+    APPL_TRACE_DEBUG1("allocating new buffer: free byte = %d", p_srvc_cb->free_byte);
+#endif
+    return p_buf;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_init_cache
+**
+** Description      Initialize the database cache and discovery related resources.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    while (p_srvc_cb->cache_buffer.p_first)
+        GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+    utl_freebuf((void **)&p_srvc_cb->p_srvc_list);
+
+    if ((p_srvc_cb->p_srvc_list = (tBTA_GATTC_ATTR_REC*)GKI_getbuf(BTA_GATTC_ATTR_LIST_SIZE)) == NULL)
+    {
+        APPL_TRACE_DEBUG0("No resources: GKI buffer allocation failed.");
+        status = GATT_NO_RESOURCES;
+    }
+    else
+    {
+        p_srvc_cb->total_srvc = 0;
+        p_srvc_cb->cur_srvc_idx =
+        p_srvc_cb->cur_char_idx =
+        p_srvc_cb->next_avail_idx = 0;
+
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+        {
+            status = GATT_NO_RESOURCES;
+        }
+        else
+        {
+            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_srvc_inst_id
+**
+** Description      get service instance number
+**
+** Returns          instance ID of the service.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_srvc_inst_id(tBTA_GATTC_SERV *p_srvc_cb, tBT_UUID uuid)
+{
+    UINT8 i = 0, inst = 0;
+    tBTA_GATTC_ATTR_REC   *p_srvc_rec;
+
+    for (i = 0; i < p_srvc_cb->total_srvc; i ++)
+    /*
+    for (; i < p_srvc_cb->cur_srvc_idx; i ++)*/
+    {
+        p_srvc_rec = p_srvc_cb->p_srvc_list + i;
+
+        if (bta_gattc_uuid_compare(p_srvc_rec->uuid, uuid, TRUE))
+            inst ++;
+    }
+    return inst ;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_get_char_inst_id
+**
+** Description      get characteristic instance number
+**
+** Returns          characteristic instance ID.
+**
+*******************************************************************************/
+static UINT8 bta_gattc_get_char_inst_id(tBTA_GATTC_CACHE *p_service_cache, tBT_UUID uuid)
+{
+    UINT8 inst = 0;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBT_UUID    attr_uuid;
+
+    p_attr = p_service_cache->p_attr;
+
+    while (p_attr)
+    {
+        bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+        if (bta_gattc_uuid_compare(attr_uuid, uuid, TRUE))
+            inst ++;
+
+        p_attr = p_attr->p_next;
+    }
+    return inst ;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_add_srvc_to_cache
+**
+** Description      Add a service into database cache.
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+                                                    UINT16 s_handle, UINT16 e_handle,
+                                                    tBT_UUID *p_uuid,
+                                                    BOOLEAN is_primary, UINT8 srvc_inst)
+{
+    tBTA_GATTC_CACHE    *p_new_srvc = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("Add a service into Service");
+    APPL_TRACE_DEBUG2("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, sizeof(tBTA_GATTC_CACHE))
+#endif
+
+    if (p_srvc_cb->free_byte < sizeof(tBTA_GATTC_CACHE))
+    {
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+            return GATT_NO_RESOURCES;
+    }
+
+    p_new_srvc = (tBTA_GATTC_CACHE *)p_srvc_cb->p_free;
+    /* update service information */
+    p_new_srvc->s_handle = s_handle;
+    p_new_srvc->e_handle = e_handle;
+    p_new_srvc->service_uuid.is_primary = is_primary;
+    memcpy(&p_new_srvc->service_uuid.id.uuid, p_uuid, sizeof(tBT_UUID));
+    p_new_srvc->service_uuid.id.inst_id = srvc_inst;
+    p_new_srvc->p_next  = NULL;
+
+    if (p_srvc_cb->p_cur_srvc != NULL)
+        p_srvc_cb->p_cur_srvc->p_next = p_new_srvc;
+    p_srvc_cb->p_cur_srvc = p_new_srvc;
+
+    /* first service */
+    if (p_srvc_cb->p_srvc_cache == NULL)
+        p_srvc_cb->p_srvc_cache = p_new_srvc;
+
+    /* update buffer managament info */
+    p_srvc_cb->p_free += sizeof(tBTA_GATTC_CACHE);
+    p_srvc_cb->free_byte -= sizeof(tBTA_GATTC_CACHE);
+
+
+#if 0
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_attr_to_cache
+**
+** Description      Add an attribute into database cache buffer.
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_attr_to_cache(tBTA_GATTC_SERV *p_srvc_cb,
+                                                    UINT16 handle,
+                                                    tBT_UUID *p_uuid,
+                                                    UINT8 property,
+                                                    tBTA_GATTC_ATTR_TYPE type)
+{
+    tBTA_GATTC_CACHE_ATTR *p_attr;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+    UINT16  len = sizeof(tBTA_GATTC_CACHE_ATTR) + p_uuid->len;
+    UINT8   *pp;
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("bta_gattc_add_attr_to_cache: Add a [%s] into Service", bta_gattc_attr_type[type]);
+    APPL_TRACE_DEBUG4("handle=%d uuid16=0x%x property=0x%x type=%d", handle, p_uuid->uu.uuid16, property, type);
+    APPL_TRACE_DEBUG2("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, len);
+#endif
+
+    if (p_srvc_cb->free_byte < len)
+    {
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+            return GATT_NO_RESOURCES;
+    }
+
+    p_attr = (tBTA_GATTC_CACHE_ATTR *)p_srvc_cb->p_free;
+
+    p_attr->attr_handle = handle;
+    p_attr->attr_type   = type;
+    p_attr->property    = property;
+    p_attr->uuid_len    = p_uuid->len;
+    p_attr->p_uuid      = (tBTA_GATTC_UUID *)(p_attr + 1);
+    p_attr->p_next      = NULL;
+
+    pp = (UINT8 *)p_attr->p_uuid;
+
+    if (p_uuid->len == LEN_UUID_16)
+    {
+        UINT16_TO_STREAM(pp, p_uuid->uu.uuid16);
+    }
+    else if (p_uuid->len == LEN_UUID_128)
+    {
+        memcpy(pp, p_uuid->uu.uuid128, LEN_UUID_128);
+    }
+
+    if (type == BTA_GATTC_ATTR_TYPE_CHAR)
+        p_attr->inst_id = bta_gattc_get_char_inst_id(p_srvc_cb->p_cur_srvc, *p_uuid);
+    /* else: char descriptor, no instance ID needed */
+    else /* TODO: --->> temp treat included service same as char descriptor */
+        p_attr->inst_id = 0;
+
+    /* update service information */
+    p_srvc_cb->p_free += len;
+    p_srvc_cb->free_byte -= len;
+
+    /* first attribute within the service, update the attribute pointer */
+    if (p_srvc_cb->p_cur_srvc->p_attr == NULL)
+    {
+        p_srvc_cb->p_cur_srvc->p_attr = p_attr;
+    }
+    if (p_srvc_cb->p_cur_srvc->p_last_attr != NULL)
+        p_srvc_cb->p_cur_srvc->p_last_attr->p_next = p_attr;
+
+    p_srvc_cb->p_cur_srvc->p_last_attr = p_attr;
+
+#if 0
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_get_disc_range
+**
+** Description      get discovery stating and ending handle range.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_get_disc_range(tBTA_GATTC_SERV *p_srvc_cb, UINT16 *p_s_hdl, UINT16 *p_e_hdl, BOOLEAN is_srvc)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+    if (is_srvc)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+        *p_s_hdl = p_rec->s_handle;
+    }
+    else
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+        *p_s_hdl = p_rec->s_handle + 1;
+    }
+
+    *p_e_hdl = p_rec->e_handle;
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    APPL_TRACE_DEBUG2("discover range [%d ~ %d]",p_rec->s_handle, p_rec->e_handle);
+#endif
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_discover_pri_service
+**
+** Description      Start primary service discovery
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+{
+#if (BLE_INCLUDED == TRUE && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+    tBT_DEVICE_TYPE dev_type;
+    tBLE_ADDR_TYPE  addr_type;
+
+    BTM_ReadDevInfo(p_server_cb->server_bda, &dev_type, &addr_type);
+    if (dev_type == BT_DEVICE_TYPE_BLE)
+        return bta_gattc_discover_procedure(conn_id, p_server_cb, disc_type);
+    else
+        return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
+#endif
+    return BTA_GATT_ERROR;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_discover_procedure
+**
+** Description      Start a particular type of discovery procedure on server.
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type)
+{
+    tGATT_DISC_PARAM param;
+    BOOLEAN is_service = TRUE;
+
+    memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+    if (disc_type == GATT_DISC_SRVC_ALL || disc_type == GATT_DISC_SRVC_BY_UUID)
+    {
+        param.s_handle = 1;
+        param.e_handle = 0xFFFF;
+    }
+    else
+    {
+        if (disc_type == GATT_DISC_CHAR_DSCPT)
+            is_service = FALSE;
+
+        bta_gattc_get_disc_range(p_server_cb, &param.s_handle, &param.e_handle, is_service);
+
+        if (param.s_handle > param.e_handle)
+        {
+            APPL_TRACE_ERROR2("discover range invalid: [0x%04x ~ 0x%04x]", param.s_handle, param.e_handle);
+
+            return GATT_ERROR;
+        }
+    }
+    return GATTC_Discover (conn_id, disc_type, &param);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_include_srvc
+**
+** Description      Start discovery for included service
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_include_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    APPL_TRACE_DEBUG0("starting discovery included service");
+
+    return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_INC_SRVC);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_char
+**
+** Description      Start discovery for characteristic
+**
+** Returns          status of the operation.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_start_disc_char(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    p_srvc_cb->total_char = 0;
+
+    APPL_TRACE_DEBUG0("starting discover characteristics");
+
+    return bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_start_disc_char_dscp
+**
+** Description      Start discovery for characteristic descriptor
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gattc_start_disc_char_dscp(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    APPL_TRACE_DEBUG0("starting discover characteristics descriptor");
+
+    if (bta_gattc_discover_procedure(conn_id, p_srvc_cb, GATT_DISC_CHAR_DSCPT) != 0)
+        bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_explore_srvc
+**
+** Description      process the service discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_explore_srvc(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    APPL_TRACE_DEBUG1("Start service discovery: srvc_idx = %d", p_srvc_cb->cur_srvc_idx);
+
+    p_srvc_cb->cur_char_idx = p_srvc_cb->next_avail_idx = p_srvc_cb->total_srvc;
+
+    if (p_clcb == NULL)
+    {
+        APPL_TRACE_ERROR0("unknown connection ID");
+        return;
+    }
+    /* start expore a service if there is service not been explored */
+    if (p_srvc_cb->cur_srvc_idx < p_srvc_cb->total_srvc)
+    {
+        /* add the first service into cache */
+        if (bta_gattc_add_srvc_to_cache (p_srvc_cb,
+                                         p_rec->s_handle,
+                                         p_rec->e_handle,
+                                         &p_rec->uuid,
+                                         p_rec->is_primary,
+                                         p_rec->srvc_inst_id) == 0)
+        {
+            /* start discovering included services */
+            bta_gattc_start_disc_include_srvc(conn_id, p_srvc_cb);
+            return;
+        }
+    }
+    /* no service found at all, the end of server discovery*/
+    APPL_TRACE_ERROR0("No More Service found");
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+    bta_gattc_display_cache_server(p_srvc_cb->p_srvc_cache);
+#endif
+    /* save cache to NV */
+    p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
+    bta_gattc_co_cache_open(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_OPEN_EVT,
+                            conn_id, TRUE);
+    //bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_incl_srvc_disc_cmpl
+**
+** Description      process the relationship discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_incl_srvc_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    p_srvc_cb->cur_char_idx = p_srvc_cb->total_srvc;
+
+    /* start discoverying characteristic */
+    bta_gattc_start_disc_char(conn_id, p_srvc_cb);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_char_disc_cmpl
+**
+** Description      process the characteristic discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_char_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->cur_char_idx;
+
+    APPL_TRACE_DEBUG1("Total %d Char found ", p_srvc_cb->total_char);
+
+    /* if there are characteristic needs to be explored */
+    if (p_srvc_cb->total_char > 0)
+    {
+        /* add the first characteristic into cache */
+        bta_gattc_add_attr_to_cache (p_srvc_cb,
+                                     p_rec->s_handle,
+                                     &p_rec->uuid,
+                                     p_rec->property,
+                                     BTA_GATTC_ATTR_TYPE_CHAR);
+
+        /* start discoverying characteristic descriptor , if failed, disc for next char*/
+        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+    }
+    else /* otherwise start with next service */
+    {
+        p_srvc_cb->cur_srvc_idx ++;
+
+        bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_char_dscpt_disc_cmpl
+**
+** Description      process the char descriptor discovery complete event
+**
+** Returns          status
+**
+*******************************************************************************/
+static void bta_gattc_char_dscpt_disc_cmpl(UINT16 conn_id, tBTA_GATTC_SERV *p_srvc_cb)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+
+    if (-- p_srvc_cb->total_char > 0)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + (++ p_srvc_cb->cur_char_idx);
+        /* add the next characteristic into cache */
+        bta_gattc_add_attr_to_cache (p_srvc_cb,
+                                     p_rec->s_handle,
+                                     &p_rec->uuid,
+                                     p_rec->property,
+                                     BTA_GATTC_ATTR_TYPE_CHAR);
+
+        /* start discoverying next characteristic for char descriptor */
+        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
+    }
+    else
+    /* all characteristic has been explored, start with next service if any */
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_ERROR0("all char has been explored");
+#endif
+        p_srvc_cb->cur_srvc_idx ++;
+        bta_gattc_explore_srvc (conn_id, p_srvc_cb);
+    }
+
+}
+static BOOLEAN bta_gattc_srvc_in_list(tBTA_GATTC_SERV *p_srvc_cb, UINT16 s_handle,
+                                      UINT16 e_handle, tBT_UUID uuid)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    UINT8   i;
+    BOOLEAN exist_srvc = FALSE;
+
+    if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle))
+    {
+        APPL_TRACE_ERROR2("invalid included service handle: [0x%04x ~ 0x%04x]", s_handle, e_handle);
+        exist_srvc = TRUE;
+    }
+    else
+    {
+        for (i = 0; i < p_srvc_cb->next_avail_idx; i ++)
+        {
+            p_rec = p_srvc_cb->p_srvc_list + i;
+
+            /* a new service should not have any overlap with other service handle range */
+            if (p_rec->s_handle == s_handle || p_rec->e_handle == e_handle)
+            {
+                exist_srvc = TRUE;
+                break;
+            }
+        }
+    }
+    return exist_srvc;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_srvc_to_list
+**
+** Description      Add a service into explore pending list
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_srvc_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+                                                   UINT16 s_handle, UINT16 e_handle,
+                                                   tBT_UUID uuid, BOOLEAN is_primary)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+    {
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+        p_srvc_cb->total_srvc ++;
+
+        APPL_TRACE_DEBUG2("bta_gattc_add_srvc_to_list handle = %d, service type = 0x%04x",
+            s_handle, uuid.uu.uuid16);
+
+        p_rec->s_handle     = s_handle;
+        p_rec->e_handle     = e_handle;
+        p_rec->is_primary   = is_primary;
+        p_rec->srvc_inst_id = bta_gattc_get_srvc_inst_id(p_srvc_cb, uuid);
+        memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+        p_srvc_cb->next_avail_idx ++;
+
+    }
+    else
+    {   /* allocate bigger buffer ?? */
+        status = GATT_DB_FULL;
+
+        APPL_TRACE_ERROR0("char not added, no resources");
+    }
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_add_char_to_list
+**
+** Description      Add a characteristic into explore pending list
+**
+** Returns          status
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_add_char_to_list(tBTA_GATTC_SERV *p_srvc_cb,
+                                                   UINT16 decl_handle, UINT16 value_handle,
+                                                   tBT_UUID uuid, UINT8 property)
+{
+    tBTA_GATTC_ATTR_REC *p_rec = NULL;
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    if (p_srvc_cb->p_srvc_list == NULL)
+    {
+        APPL_TRACE_ERROR0("No service available, unexpected char discovery result");
+        status = BTA_GATT_INTERNAL_ERROR;
+    }
+    else if (p_srvc_cb->next_avail_idx < BTA_GATTC_MAX_CACHE_CHAR)
+    {
+
+        p_rec = p_srvc_cb->p_srvc_list + p_srvc_cb->next_avail_idx;
+
+        p_srvc_cb->total_char ++;
+
+        p_rec->s_handle = value_handle;
+        p_rec->property = property;
+        p_rec->e_handle = (p_srvc_cb->p_srvc_list + p_srvc_cb->cur_srvc_idx)->e_handle;
+        memcpy(&p_rec->uuid, &uuid, sizeof(tBT_UUID));
+
+        /* update the endind handle of pervious characteristic if available */
+        if (p_srvc_cb->total_char > 1)
+        {
+            p_rec -= 1;
+            p_rec->e_handle = decl_handle - 1;
+        }
+        p_srvc_cb->next_avail_idx ++;
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("char not added, no resources");
+        /* allocate bigger buffer ?? */
+        status = BTA_GATT_DB_FULL;
+    }
+    return status;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_sdp_callback
+**
+** Description      Process the discovery result from sdp
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_sdp_callback (UINT16 sdp_status)
+{
+    tSDP_DISC_REC       *p_sdp_rec = NULL;
+    tBT_UUID            service_uuid;
+    tSDP_PROTOCOL_ELEM  pe;
+    UINT16              start_handle = 0, end_handle = 0;
+    tBTA_GATTC_SERV     *p_srvc_cb = bta_gattc_find_scb_by_cid(bta_gattc_cb.sdp_conn_id);
+
+    if(((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) && p_srvc_cb != NULL)
+    {
+        do
+        {
+            /* find a service record, report it */
+            p_sdp_rec = SDP_FindServiceInDb(bta_gattc_cb.p_sdp_db,
+                                            0, p_sdp_rec);
+            if (p_sdp_rec)
+            {
+                if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid))
+                {
+
+                    if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
+                    {
+                        start_handle    = (UINT16) pe.params[0];
+                        end_handle      = (UINT16) pe.params[1];
+
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                        APPL_TRACE_EVENT3("Found ATT service [0x%04x] handle[0x%04x ~ 0x%04x]",
+                                        service_uuid.uu.uuid16, start_handle, end_handle);
+#endif
+
+                        if (GATT_HANDLE_IS_VALID(start_handle) && GATT_HANDLE_IS_VALID(end_handle) &&
+                            p_srvc_cb != NULL)
+                        {
+                            /* discover services result, add services into a service list */
+                            bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                                       start_handle,
+                                                       end_handle,
+                                                       service_uuid,
+                                                       TRUE);
+                        }
+                        else
+                        {
+                            APPL_TRACE_ERROR2("invalid start_handle = %d end_handle = %d", start_handle, end_handle);
+                        }
+                }
+
+
+                }
+            }
+        } while (p_sdp_rec);
+    }
+
+    if ( p_srvc_cb != NULL)
+        /* start discover primary service */
+        bta_gattc_explore_srvc(bta_gattc_cb.sdp_conn_id, p_srvc_cb);
+    else
+    {
+        APPL_TRACE_ERROR0("GATT service discovery is done on unknown connection");
+    }
+
+    GKI_freebuf(bta_gattc_cb.p_sdp_db);
+    bta_gattc_cb.p_sdp_db  = NULL;
+    bta_gattc_cb.sdp_conn_id = 0;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_sdp_service_disc
+**
+** Description      Start DSP Service Discovert
+**
+** Returns          void
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_sdp_service_disc(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb)
+{
+    tSDP_UUID       uuid;
+    UINT16          num_attrs = 2;
+    UINT16          attr_list[2];
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+
+    memset (&uuid, 0, sizeof(tSDP_UUID));
+
+    uuid.len = LEN_UUID_16;
+    uuid.uu.uuid16 = UUID_PROTOCOL_ATT;
+
+     if((bta_gattc_cb.p_sdp_db = (tSDP_DISCOVERY_DB *)GKI_getbuf(BTA_GATT_SDP_DB_SIZE)) != NULL)
+    {
+        attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+        attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+
+        SDP_InitDiscoveryDb (bta_gattc_cb.p_sdp_db, BTA_GATT_SDP_DB_SIZE, 1, &uuid, num_attrs, attr_list);
+
+        if(!SDP_ServiceSearchAttributeRequest (p_server_cb->server_bda, bta_gattc_cb.p_sdp_db, &bta_gattc_sdp_callback))
+        {
+            GKI_freebuf(bta_gattc_cb.p_sdp_db);
+            bta_gattc_cb.p_sdp_db = NULL;
+        }
+        else
+        {
+            bta_gattc_cb.sdp_conn_id = conn_id;
+            status = BTA_GATT_OK;
+        }
+     }
+     return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_disc_res_cback
+**                  bta_gattc_disc_cmpl_cback
+**
+** Description      callback functions to GATT client stack.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data)
+{
+    tBTA_GATTC_SERV * p_srvc_cb = NULL;
+    BOOLEAN          pri_srvc;
+
+    p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+    if (p_srvc_cb != NULL)
+    {
+        switch (disc_type)
+        {
+            case GATT_DISC_SRVC_ALL:
+                /* discover services result, add services into a service list */
+                bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.group_value.e_handle,
+                                           p_data->value.group_value.service_type,
+                                           TRUE);
+
+                break;
+            case GATT_DISC_SRVC_BY_UUID:
+                bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.handle,
+                                           p_data->type,
+                                           TRUE);
+                break;
+
+            case GATT_DISC_INC_SRVC:
+                /* add included service into service list if it's secondary or it never showed up
+                   in the primary service search */
+                pri_srvc = bta_gattc_srvc_in_list(p_srvc_cb,
+                                                  p_data->value.incl_service.s_handle,
+                                                  p_data->value.incl_service.e_handle,
+                                                  p_data->value.incl_service.service_type);
+
+                if (!pri_srvc)
+                    bta_gattc_add_srvc_to_list(p_srvc_cb,
+                                               p_data->value.incl_service.s_handle,
+                                               p_data->value.incl_service.e_handle,
+                                               p_data->value.incl_service.service_type,
+                                               FALSE);
+                /* add into database */
+                bta_gattc_add_attr_to_cache(p_srvc_cb,
+                                            p_data->handle,
+                                            &p_data->value.incl_service.service_type,
+                                            pri_srvc,
+                                            BTA_GATTC_ATTR_TYPE_INCL_SRVC);
+                break;
+
+            case GATT_DISC_CHAR:
+                /* add char value into database */
+                bta_gattc_add_char_to_list(p_srvc_cb,
+                                           p_data->handle,
+                                           p_data->value.dclr_value.val_handle,
+                                           p_data->value.dclr_value.char_uuid,
+                                           p_data->value.dclr_value.char_prop);
+                break;
+
+            case GATT_DISC_CHAR_DSCPT:
+                bta_gattc_add_attr_to_cache(p_srvc_cb, p_data->handle, &p_data->type, 0, BTA_GATTC_ATTR_TYPE_CHAR_DESCR);
+                break;
+        }
+    }
+}
+void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
+{
+    tBTA_GATTC_SERV * p_srvc_cb;
+
+    p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
+
+    if (p_srvc_cb != NULL)
+    {
+        switch (disc_type)
+        {
+            case GATT_DISC_SRVC_ALL:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+                bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+                break;
+
+            case GATT_DISC_INC_SRVC:
+                bta_gattc_incl_srvc_disc_cmpl(conn_id, p_srvc_cb);
+
+                break;
+
+            case GATT_DISC_CHAR:
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                bta_gattc_display_explore_record(p_srvc_cb->p_srvc_list, p_srvc_cb->next_avail_idx);
+#endif
+                bta_gattc_char_disc_cmpl(conn_id, p_srvc_cb);
+                break;
+
+            case GATT_DISC_CHAR_DSCPT:
+                bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+                break;
+        }
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_id2handle
+**
+** Description      map GATT ID to handle in a given cache.
+**
+** Returns          the handle mapped. 0 if not found.
+**
+*******************************************************************************/
+UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id,
+                           tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    UINT8       j;
+    UINT16      handle = 0;
+    tBT_UUID    attr_uuid;
+    BOOLEAN     char_map = FALSE, done = FALSE;
+
+    while (p_cache && !done)
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
+                          p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+                          p_cache->service_uuid.id.inst_id);
+#endif
+        p_attr = p_cache->p_attr;
+
+        if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, TRUE) &&
+            p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
+            p_cache->service_uuid.is_primary == p_service_id->is_primary)
+        {
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+#endif
+                bta_gattc_pack_attr_uuid(p_attr, &attr_uuid);
+
+                if (bta_gattc_uuid_compare(p_char_id->uuid, attr_uuid, TRUE) &&
+                    p_char_id->inst_id == p_attr->inst_id)
+                {
+                    if (descr_uuid.len == 0)
+                    {
+                        handle = p_attr->attr_handle;
+                        done = TRUE;
+                        break;
+                    }
+                    else
+                    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                        APPL_TRACE_DEBUG0("found matching characteristic for the descriptor");
+#endif
+                        char_map = TRUE;
+                    }
+                }
+                else if (char_map == TRUE)
+                {
+                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+
+                        if (bta_gattc_uuid_compare(descr_uuid, attr_uuid, TRUE))
+                        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                            APPL_TRACE_DEBUG0("found descripotor!!");
+#endif
+                            handle = p_attr->attr_handle;
+                            done = TRUE;
+                            break;
+                        }
+                        else
+                        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                            APPL_TRACE_DEBUG0("descriptor UUID not matching");
+#endif
+                        }
+                    }
+                    else /* another char */
+                    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                        APPL_TRACE_DEBUG0("no matching descriptor found!! start of next characteristic");
+#endif
+                        char_map = FALSE;
+                        done = TRUE;
+                        break;
+                    }
+                }
+                p_attr = p_attr->p_next;
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+
+    return handle;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_handle2id
+**
+** Description      map a handle to GATT ID in a given cache.
+**
+** Returns          FALSE if map can not be found.
+**
+*******************************************************************************/
+
+BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *p_service_id,
+                            tBTA_GATT_ID *p_char_id, tBT_UUID *p_descr_type)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC_CACHE_ATTR   *p_attr, *p_char = NULL;
+    UINT8       j;
+
+    memset(p_service_id, 0, sizeof(tBTA_GATT_SRVC_ID));
+    memset(p_char_id, 0, sizeof(tBTA_GATT_ID));
+    memset(p_descr_type, 0, sizeof(tBT_UUID));
+
+    while (p_cache)
+    {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+        APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
+                          p_cache->s_handle, p_cache->service_uuid.id.uuid.uu.uuid16,
+                          p_cache->service_uuid.id.inst_id);
+#endif
+        /* a service found */
+        if (p_cache->s_handle == handle)
+        {
+            memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+            return TRUE;
+        }
+        else /* start looking for attributes within the service */
+        {
+            p_attr = p_cache->p_attr;
+
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG5("\t Attr[0x%04x] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle, p_attr->p_uuid->uuid16, p_attr->inst_id, p_attr->attr_type);
+#endif
+                if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)
+                    p_char = p_attr;
+
+                if (handle == p_attr->attr_handle)
+                {
+                    memcpy(p_service_id, &p_cache->service_uuid, sizeof(tBTA_GATT_SRVC_ID));
+
+                    if (p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+                        bta_gattc_pack_attr_uuid(p_attr, p_descr_type);
+
+                        if (p_char != NULL)
+                        {
+                            bta_gattc_pack_attr_uuid(p_char, &p_char_id->uuid);
+                            p_char_id->inst_id = p_char->inst_id;
+                        }
+                        else
+                        {
+                            APPL_TRACE_ERROR0("descriptor does not belong to any chracteristic, error");
+                        }
+                    }
+                    else
+                    /* is a characterisitc value or included service */
+                    {
+                        bta_gattc_pack_attr_uuid(p_attr, &p_char_id->uuid);
+                        p_char_id->inst_id =p_attr->inst_id;
+                    }
+                    return TRUE;
+                }
+                p_attr = p_attr->p_next;
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_search_service
+**
+** Description      search local cache for matching service record.
+**
+** Returns          FALSE if map can not be found.
+**
+*******************************************************************************/
+void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid)
+{
+    tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATTC          cb_data;
+
+    while (p_cache)
+    {
+        if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE))
+        {
+//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+            APPL_TRACE_DEBUG3("found service [0x%04x], inst[%d] handle [%d]",
+                              p_cache->service_uuid.id.uuid.uu.uuid16,
+                              p_cache->service_uuid.id.inst_id,
+                              p_cache->s_handle);
+//#endif
+            if (p_clcb->p_rcb->p_cback)
+            {
+                memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+                cb_data.srvc_res.conn_id = p_clcb->bta_conn_id;
+                memcpy(&cb_data.srvc_res.service_uuid, &p_cache->service_uuid ,sizeof(tBTA_GATT_SRVC_ID));
+
+                (* p_clcb->p_rcb->p_cback)(BTA_GATTC_SEARCH_RES_EVT, &cb_data);
+                //todo  (tBTA_GATTC *)&p_cache->service_uuid);
+            }
+        }
+        p_cache = p_cache->p_next;
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_record
+**
+** Description      search local cache for matching attribute record.
+**
+** Parameter        p_result: output parameter to store the characteristic/
+**                            included service GATT ID.
+**
+** Returns          GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+static tBTA_GATT_STATUS bta_gattc_find_record(tBTA_GATTC_SERV *p_srcb,
+                                              tBTA_GATTC_ATTR_TYPE attr_type,
+                                              tBTA_GATT_SRVC_ID *p_service_id,
+                                              tBTA_GATT_ID  *p_start_rec,
+                                              tBT_UUID      * p_uuid_cond,
+                                              tBTA_GATT_ID  *p_result,
+                                              void *p_param)
+{
+    tBTA_GATTC_CACHE    *p_cache = p_srcb->p_srvc_cache;
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+    tBT_UUID            uuid_cond = {0}, start_descr = {0};
+    UINT8               i, j;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    BOOLEAN             char_found = FALSE, descr_found = FALSE;
+
+    if (p_uuid_cond)
+        memcpy(&uuid_cond, p_uuid_cond, sizeof(tBT_UUID));
+
+    for (i = 0;  p_cache <= p_srcb->p_cur_srvc && p_cache && status != BTA_GATT_OK; i ++)
+    {
+        if (bta_gattc_uuid_compare(p_service_id->id.uuid, p_cache->service_uuid.id.uuid, FALSE) &&
+            p_service_id->id.inst_id == p_cache->service_uuid.id.inst_id &&
+            p_service_id->is_primary == p_cache->service_uuid.is_primary)
+        {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+            APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]",
+                              p_cache->service_uuid.id.uuid.uu.uuid16,
+                              p_cache->service_uuid.id.inst_id);
+#endif
+            p_attr = p_cache->p_attr;
+
+            for (j = 0; p_attr; j ++)
+            {
+#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+                APPL_TRACE_DEBUG5("\t Attr[%d] handle[0x%04x] uuid[0x%04x] inst[%d] type[%d]",
+                                  j + 1, p_attr->attr_handle,
+                                  p_attr->p_uuid->uuid16,
+                                  p_attr->inst_id,
+                                  p_attr->attr_type);
+#endif
+                bta_gattc_pack_attr_uuid(p_attr, &p_result->uuid);
+
+                if (p_start_rec != NULL && char_found == FALSE)
+                {
+                    /* find the starting record first */
+                    if (bta_gattc_uuid_compare(p_start_rec->uuid, p_result->uuid, FALSE) &&
+                        p_start_rec->inst_id  == p_attr->inst_id &&
+                        (attr_type == p_attr->attr_type ||
+                        /* find descriptor would look for characteristic first */
+                         (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR && p_attr->attr_type == BTA_GATTC_ATTR_TYPE_CHAR)))
+                    {
+                        char_found = TRUE;
+                    }
+                }
+                else
+                {
+                    /* if looking for descriptor, here is the where the descrptor to be found */
+                    if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                    {
+                        /* starting descriptor UUID */
+                        if (p_param != NULL)
+                            memcpy(&start_descr, p_param, sizeof(tBT_UUID));
+                        /* next characeteristic already, return error */
+                        if (p_attr->attr_type != BTA_GATTC_ATTR_TYPE_CHAR_DESCR)
+                        {
+                            break;
+                        }
+                        else
+                        {
+                            if (start_descr.len != 0 && !descr_found)
+                            {
+                                if (bta_gattc_uuid_compare(start_descr, p_result->uuid, FALSE))
+                                {
+                                    descr_found = TRUE;
+                                }
+                            }
+                            else
+                            {
+                                /* with matching descriptor */
+                                if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE))
+                                {
+                                    status = BTA_GATT_OK;
+                                    break;
+                                }
+                            }
+                        }
+                    }
+                    else
+                    {
+                        if (bta_gattc_uuid_compare(uuid_cond, p_result->uuid, FALSE) &&
+                            attr_type == p_attr->attr_type)
+                        {
+
+                            APPL_TRACE_DEBUG0("found char handle mapping characteristic");
+                            p_result->inst_id = p_attr->inst_id;
+
+                            if (p_param != NULL)
+                            {
+                                if (attr_type == BTA_GATTC_ATTR_TYPE_CHAR ||
+                                    attr_type == BTA_GATTC_ATTR_TYPE_INCL_SRVC)
+                                {
+                                    *(tBTA_GATT_CHAR_PROP *)p_param = p_attr->property;
+                                }
+                            }
+
+                            status = BTA_GATT_OK;
+                            break;
+                        }
+                    }
+                }
+                p_attr = p_attr->p_next;
+            }
+            if (status)
+            {
+                APPL_TRACE_ERROR0("In the given service, can not find matching record");
+            }
+            break;
+        }
+
+        p_cache = p_cache->p_next;
+    }
+    return status;
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_query_cache
+**
+** Description      search local cache for matching attribute record.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  *p_start_rec: start the search from the next record
+**                                  after the one identified by *p_start_rec.
+**                  p_uuid_cond: UUID, if NULL find the first available
+**                               characteristic/included service.
+**                  p_output:   output parameter which will store the GATT ID
+**                              of the characteristic /included service found.
+**
+** Returns          BTA_GATT_ERROR is no recording found. BTA_GATT_OK if record found.
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id,
+                                       tBTA_GATTC_ATTR_TYPE query_type,
+                                       tBTA_GATT_SRVC_ID *p_srvc_id,
+                                       tBTA_GATT_ID *p_start_rec,
+                                       tBT_UUID *p_uuid_cond,
+                                       tBTA_GATT_ID *p_output,
+                                       void *p_param)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+    tBTA_GATT_STATUS status = BTA_GATT_ILLEGAL_PARAMETER;
+
+    /* lock other GKI task */
+    GKI_sched_lock();
+
+    APPL_TRACE_DEBUG0("bta_gattc_query_cache");
+
+    if (p_clcb != NULL )
+    {
+        if (p_clcb->state == BTA_GATTC_CONN_ST)
+        {
+            if (p_clcb->p_srcb &&
+                !p_clcb->p_srcb->p_srvc_list && /* no active discovery */
+                p_clcb->p_srcb->p_srvc_cache)
+            {
+                status = bta_gattc_find_record(p_clcb->p_srcb,
+                                               query_type,
+                                               p_srvc_id,
+                                               p_start_rec,
+                                               p_uuid_cond,
+                                               p_output,
+                                               p_param);
+            }
+            else
+            {
+                status = BTA_GATT_ERROR;
+                APPL_TRACE_ERROR0("No server cache available");
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR1("server cache not available, CLCB state = %d", p_clcb->state);
+
+            status = (p_clcb->state == BTA_GATTC_DISCOVER_ST) ? BTA_GATT_BUSY : BTA_GATT_ERROR;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Unknown conn ID: %d", conn_id);
+    }
+    GKI_sched_unlock();
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_rebuild_cache
+**
+** Description      rebuild server cache from NV cache.
+**
+** Parameters
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srvc_cb, UINT16 num_attr,
+                             tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index)
+{
+    /* first attribute loading, initialize buffer */
+    APPL_TRACE_ERROR0("bta_gattc_rebuild_cache");
+    if (attr_index == 0)
+    {
+        while (p_srvc_cb->cache_buffer.p_first)
+            GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+        if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
+        {
+            APPL_TRACE_ERROR0("allocate cache buffer failed, no resources");
+        }
+        else
+        {
+            p_srvc_cb->p_cur_srvc = p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+
+    while (num_attr > 0 && p_attr != NULL)
+    {
+        switch (p_attr->attr_type)
+        {
+            case BTA_GATTC_ATTR_TYPE_SRVC:
+                bta_gattc_add_srvc_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            p_attr->e_handle,
+                                            &p_attr->uuid,
+                                            p_attr->is_primary,
+                                            p_attr->id);
+                break;
+
+            case BTA_GATTC_ATTR_TYPE_CHAR:
+            case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
+            case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
+                bta_gattc_add_attr_to_cache(p_srvc_cb,
+                                            p_attr->s_handle,
+                                            &p_attr->uuid,
+                                            p_attr->prop,
+                                            p_attr->attr_type);
+                break;
+        }
+        p_attr ++;
+        num_attr --;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_fill_nv_attr
+**
+** Description      fill a NV attribute entry value
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR *p_attr, UINT8 type, UINT16 s_handle,
+                            UINT16 e_handle, UINT8 id, tBT_UUID uuid, UINT8 prop, BOOLEAN is_primary)
+{
+    p_attr->s_handle    = s_handle;
+    p_attr->e_handle    = e_handle;
+    p_attr->attr_type   = type;
+    p_attr->is_primary  = is_primary;
+    p_attr->id          = id;
+    p_attr->prop        = prop;
+
+    memcpy(&p_attr->uuid, &uuid, sizeof(tBT_UUID));
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_cache_save
+**
+** Description      save the server cache into NV
+**
+** Returns          None.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id)
+{
+    tBTA_GATTC_CACHE        *p_cur_srvc = p_srvc_cb->p_srvc_cache;
+    UINT8                   i = 0;
+    UINT16                  offset = 0;
+    tBTA_GATTC_NV_ATTR      nv_attr[BTA_GATTC_NV_LOAD_MAX];
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBT_UUID                uuid;
+
+    while (p_cur_srvc && i < BTA_GATTC_NV_LOAD_MAX)
+    {
+        if (offset ++ >= p_srvc_cb->attr_index)
+        {
+            bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                   BTA_GATTC_ATTR_TYPE_SRVC,
+                                   p_cur_srvc->s_handle,
+                                   p_cur_srvc->e_handle,
+                                   p_cur_srvc->service_uuid.id.inst_id,
+                                   p_cur_srvc->service_uuid.id.uuid,
+                                   0,
+                                   p_cur_srvc->service_uuid.is_primary);
+        }
+
+        p_attr = p_cur_srvc->p_attr;
+
+        for (; p_attr && i < BTA_GATTC_NV_LOAD_MAX ; offset ++, p_attr = p_attr->p_next)
+        {
+            if (offset >= p_srvc_cb->attr_index)
+            {
+                if ((uuid.len = p_attr->uuid_len) == LEN_UUID_16)
+                {
+                    uuid.uu.uuid16 = p_attr->p_uuid->uuid16;
+                }
+                else
+                {
+                    memcpy(uuid.uu.uuid128, p_attr->p_uuid->uuid128, LEN_UUID_128);
+                }
+
+                bta_gattc_fill_nv_attr(&nv_attr[i++],
+                                       p_attr->attr_type,
+                                       p_attr->attr_handle,
+                                       0,
+                                       p_attr->inst_id,
+                                       uuid,
+                                       p_attr->property,
+                                       FALSE);
+            }
+        }
+        p_cur_srvc = p_cur_srvc->p_next;
+    }
+
+    if (i > 0)
+    {
+        bta_gattc_co_cache_save(p_srvc_cb->server_bda, BTA_GATTC_CI_CACHE_SAVE_EVT, i,
+                                nv_attr, p_srvc_cb->attr_index, conn_id);
+
+        p_srvc_cb->attr_index += i;
+
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+#endif /* BTA_GATT_INCLUDED */
+
diff --git a/bta/gatt/bta_gattc_ci.c b/bta/gatt/bta_gattc_ci.c
new file mode 100644
index 0000000..212126f
--- /dev/null
+++ b/bta/gatt/bta_gattc_ci.c
@@ -0,0 +1,137 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the implementation file for the GATT call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_gattc_ci.h"
+#include "gki.h"
+#include "bd.h"
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_open
+**
+** Description      This function sends an event to indicate server cache open
+**                  completed.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_load
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  load the servere cache and ready to send it to the stack.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+                             tBTA_GATTC_NV_ATTR *p_attr, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_LOAD  *p_evt;
+
+    if ((p_evt = (tBTA_GATTC_CI_LOAD *) GKI_getbuf(sizeof(tBTA_GATTC_CI_LOAD))) != NULL)
+    {
+        memset(p_evt, 0, sizeof(tBTA_GATTC_CI_LOAD));
+
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status    = status;
+        p_evt->num_attr  = (num_attr > BTA_GATTC_NV_LOAD_MAX) ? BTA_GATTC_NV_LOAD_MAX : num_attr;
+
+        if (p_evt->num_attr > 0 && p_attr != NULL)
+        {
+            memcpy(p_evt->attr, p_attr, p_evt->num_attr * sizeof(tBTA_GATTC_NV_ATTR));
+        }
+
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_save
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  save the servere cache.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  evt - callin event code.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_ERROR if an error has occurred.
+*8                  conn_id - for this NV operation for.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt, tBTA_GATT_STATUS status,
+                             UINT16 conn_id)
+{
+    tBTA_GATTC_CI_EVT  *p_evt;
+
+    if ((p_evt = (tBTA_GATTC_CI_EVT *) GKI_getbuf(sizeof(tBTA_GATTC_CI_EVT))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->hdr.layer_specific = conn_id;
+
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
new file mode 100644
index 0000000..407e5d8
--- /dev/null
+++ b/bta/gatt/bta_gattc_int.h
@@ -0,0 +1,464 @@
+/******************************************************************************
+ *
+ *  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 is the private file for the file transfer client (FTC).
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_INT_H
+#define BTA_GATTC_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gattc_ci.h"
+#include "bta_gattc_co.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+enum
+{
+    BTA_GATTC_API_OPEN_EVT   = BTA_SYS_EVT_START(BTA_ID_GATTC),
+    BTA_GATTC_INT_OPEN_FAIL_EVT,
+    BTA_GATTC_API_CANCEL_OPEN_EVT,
+    BTA_GATTC_INT_CANCEL_OPEN_OK_EVT,
+
+    BTA_GATTC_API_READ_EVT,
+    BTA_GATTC_API_WRITE_EVT,
+    BTA_GATTC_API_EXEC_EVT,
+
+    BTA_GATTC_API_CLOSE_EVT,
+
+    BTA_GATTC_API_SEARCH_EVT,
+    BTA_GATTC_API_CONFIRM_EVT,
+    BTA_GATTC_API_READ_MULTI_EVT,
+
+    BTA_GATTC_INT_CONN_EVT,
+    BTA_GATTC_INT_DISCOVER_EVT,
+    BTA_GATTC_DISCOVER_CMPL_EVT,
+    BTA_GATTC_OP_CMPL_EVT,
+    BTA_GATTC_INT_DISCONN_EVT,
+
+    /* for cache loading/saving */
+    BTA_GATTC_START_CACHE_EVT,
+    BTA_GATTC_CI_CACHE_OPEN_EVT,
+    BTA_GATTC_CI_CACHE_LOAD_EVT,
+    BTA_GATTC_CI_CACHE_SAVE_EVT,
+
+    BTA_GATTC_INT_START_IF_EVT,
+    BTA_GATTC_API_REG_EVT,
+    BTA_GATTC_API_DEREG_EVT,
+    BTA_GATTC_INT_DEREG_EVT
+
+};
+typedef UINT16 tBTA_GATTC_INT_EVT;
+
+/* max client application GATTC can support */
+#ifndef     BTA_GATTC_CL_MAX
+#define     BTA_GATTC_CL_MAX    4
+#endif
+
+/* max known devices GATTC can support */
+#ifndef     BTA_GATTC_KNOWN_SR_MAX
+#define     BTA_GATTC_KNOWN_SR_MAX    4
+#endif
+
+#ifndef BTA_GATTC_CLCB_MAX
+    #define BTA_GATTC_CLCB_MAX      GATT_CL_MAX_LCB
+#endif
+
+#define BTA_GATTC_WRITE_PREPARE          GATT_WRITE_PREPARE
+
+/* internal strucutre for GATTC register API  */
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                app_uuid;
+    tBTA_GATTC_CBACK        *p_cback;
+}tBTA_GATTC_API_REG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTC_IF           client_if;
+}tBTA_GATTC_INT_START_IF;
+
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_API_DEREG;
+typedef tBTA_GATTC_INT_START_IF tBTA_GATTC_INT_DEREG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_IF           client_if;
+    BOOLEAN                 is_direct;
+} tBTA_GATTC_API_OPEN;
+
+typedef tBTA_GATTC_API_OPEN tBTA_GATTC_API_CANCEL_OPEN;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+    tBT_UUID                descr_type;
+} tBTA_GATTC_API_READ;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+    tBT_UUID                descr_type;
+    tBTA_GATTC_WRITE_TYPE   write_type;
+    UINT16                  offset;
+    UINT16                  len;
+    UINT8                   *p_value;
+}tBTA_GATTC_API_WRITE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 is_execute;
+}tBTA_GATTC_API_EXEC;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+} tBTA_GATTC_API_CONFIRM;
+
+typedef tGATT_CL_COMPLETE tBTA_GATTC_CMPL;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   op_code;
+    tGATT_STATUS            status;
+    tBTA_GATTC_CMPL         *p_cmpl;
+}tBTA_GATTC_OP_CMPL;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBT_UUID            srvc_uuid;
+}tBTA_GATTC_API_SEARCH;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_AUTH_REQ      auth_req;
+    UINT8                   num_attr;
+    tBTA_GATTC_ATTR_ID      *p_id_list;
+}tBTA_GATTC_API_READ_MULTI;
+
+typedef union
+{
+    BT_HDR                      hdr;
+    tBTA_GATTC_API_REG          api_reg;
+    tBTA_GATTC_API_DEREG        api_dereg;
+    tBTA_GATTC_API_OPEN         api_conn;
+    tBTA_GATTC_API_CANCEL_OPEN  api_cancel_conn;
+    tBTA_GATTC_API_READ         api_read;
+    tBTA_GATTC_API_SEARCH       api_search;
+    tBTA_GATTC_API_WRITE        api_write;
+    tBTA_GATTC_API_CONFIRM      api_confirm;
+    tBTA_GATTC_API_EXEC         api_exec;
+    tBTA_GATTC_API_READ_MULTI   api_read_multi;
+    tBTA_GATTC_OP_CMPL          op_cmpl;
+    tBTA_GATTC_CI_EVT           ci_open;
+    tBTA_GATTC_CI_EVT           ci_save;
+    tBTA_GATTC_CI_LOAD          ci_load;
+
+    tBTA_GATTC_INT_START_IF     int_start_if;
+    tBTA_GATTC_INT_DEREG        int_dereg;
+
+} tBTA_GATTC_DATA;
+
+
+/* GATT server cache on the client */
+typedef union
+{
+    UINT8               uuid128[LEN_UUID_128];
+    UINT16              uuid16;
+}tBTA_GATTC_UUID;
+
+typedef struct gattc_attr_cache
+{
+    tBTA_GATTC_UUID         *p_uuid;
+    struct                  gattc_attr_cache *p_next;
+    UINT16                  uuid_len;
+    UINT16                  attr_handle;
+    UINT8                   inst_id;
+    tBTA_GATT_CHAR_PROP     property; /* if characteristic, it is char property;
+                                         if included service, flag primary,
+                                         if descriptor, not used */
+    tBTA_GATTC_ATTR_TYPE    attr_type;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE_ATTR;
+// btla-specific --
+
+typedef struct gattc_svc_cache
+{
+    tBTA_GATT_SRVC_ID       service_uuid;
+    tBTA_GATTC_CACHE_ATTR   *p_attr;
+    tBTA_GATTC_CACHE_ATTR   *p_last_attr;
+    UINT16                  s_handle;
+    UINT16                  e_handle;
+    struct                  gattc_svc_cache *p_next;
+// btla-specific ++
+} __attribute__((packed)) tBTA_GATTC_CACHE;
+// btla-specific --
+
+typedef struct
+{
+    tBT_UUID            uuid;
+    UINT16              s_handle;
+    UINT16              e_handle;
+    BOOLEAN             is_primary;
+    UINT8               srvc_inst_id;
+    tBTA_GATT_CHAR_PROP property;
+}tBTA_GATTC_ATTR_REC;
+
+
+#define BTA_GATTC_MAX_CACHE_CHAR    40
+#define BTA_GATTC_ATTR_LIST_SIZE    (BTA_GATTC_MAX_CACHE_CHAR * sizeof(tBTA_GATTC_ATTR_REC))
+
+#ifndef BTA_GATTC_CACHE_SRVR_SIZE
+    #define BTA_GATTC_CACHE_SRVR_SIZE   600
+#endif
+
+enum
+{
+    BTA_GATTC_IDLE_ST = 0,      /* Idle  */
+    BTA_GATTC_W4_CONN_ST,       /* Wait for connection -  (optional) */
+    BTA_GATTC_CONN_ST,          /* connected state */
+    BTA_GATTC_DISCOVER_ST       /* discover is in progress */
+};
+typedef UINT8 tBTA_GATTC_STATE;
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    BD_ADDR             server_bda;
+    BOOLEAN             connected;
+
+#define BTA_GATTC_SERV_IDLE     0
+#define BTA_GATTC_SERV_LOAD     1
+#define BTA_GATTC_SERV_SAVE     2
+
+    UINT8               state;
+
+    tBTA_GATTC_CACHE    *p_srvc_cache;
+    tBTA_GATTC_CACHE    *p_cur_srvc;
+    BUFFER_Q            cache_buffer;   /* buffer queue used for storing the cache data */
+    UINT8               *p_free;        /* starting point to next available byte */
+    UINT16              free_byte;      /* number of available bytes in server cache buffer */
+    UINT8               update_count;   /* indication received */
+    UINT8               num_clcb;       /* number of associated CLCB */
+
+
+    tBTA_GATTC_ATTR_REC *p_srvc_list;
+    UINT8               cur_srvc_idx;
+    UINT8               cur_char_idx;
+    UINT8               next_avail_idx;
+    UINT8               total_srvc;
+    UINT8               total_char;
+
+    UINT8               srvc_hdl_chg;   /* service handle change indication pending */
+    UINT16              attr_index;     /* cahce NV saving/loading attribute index */
+
+} tBTA_GATTC_SERV;
+
+#ifndef BTA_GATTC_NOTIF_REG_MAX
+#define BTA_GATTC_NOTIF_REG_MAX     4
+#endif
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_CHAR_ID  char_id;
+}tBTA_GATTC_NOTIF_REG;
+
+typedef struct
+{
+    tBTA_GATTC_CBACK        *p_cback;
+    BOOLEAN                 in_use;
+    tBTA_GATTC_IF           client_if;      /* client interface with BTE stack for this application */
+    UINT8                   num_clcb;       /* number of associated CLCB */
+    BOOLEAN                 dereg_pending;
+    tBT_UUID                app_uuid;
+    tBTA_GATTC_NOTIF_REG    notif_reg[BTA_GATTC_NOTIF_REG_MAX];
+}tBTA_GATTC_RCB;
+
+/* client channel is a mapping between a BTA client(cl_id) and a remote BD address */
+typedef struct
+{
+    UINT16              bta_conn_id;    /* client channel ID, unique for clcb */
+    BD_ADDR             bda;
+    tBTA_GATTC_RCB      *p_rcb;         /* pointer to the registration CB */
+    tBTA_GATTC_SERV     *p_srcb;    /* server cache CB */
+    tBTA_GATTC_DATA     *p_q_cmd;   /* command in queue waiting for execution */
+
+#define BTA_GATTC_NO_SCHEDULE       0
+#define BTA_GATTC_DISC_WAITING      0x01
+#define BTA_GATTC_REQ_WAITING       0x10
+
+    UINT8               auto_update; /* auto update is waiting */
+    BOOLEAN             in_use;
+    tBTA_GATTC_STATE    state;
+    tBTA_GATT_STATUS    status;
+    UINT16              reason;
+} tBTA_GATTC_CLCB;
+
+/* back ground connection tracking information */
+#if GATT_MAX_APPS <= 8
+typedef UINT8 tBTA_GATTC_CIF_MASK ;
+#elif GATT_MAX_APPS <= 16
+typedef UINT16 tBTA_GATTC_CIF_MASK;
+#elif GATT_MAX_APPS <= 32
+typedef UINT32 tBTA_GATTC_CIF_MASK;
+#endif
+
+typedef struct
+{
+    BOOLEAN                 in_use;
+    BD_ADDR                 remote_bda;
+    tBTA_GATTC_CIF_MASK     cif_mask;
+
+}tBTA_GATTC_BG_TCK;
+
+typedef struct
+{
+    tBTA_GATTC_BG_TCK   bg_track[BTA_GATTC_KNOWN_SR_MAX];
+    tBTA_GATTC_RCB      cl_rcb[BTA_GATTC_CL_MAX];
+
+    tBTA_GATTC_CLCB     clcb[BTA_GATTC_CLCB_MAX];
+    tBTA_GATTC_SERV     known_server[BTA_GATTC_KNOWN_SR_MAX];
+
+    tSDP_DISCOVERY_DB   *p_sdp_db;
+    UINT16              sdp_conn_id;
+}tBTA_GATTC_CB;
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTC_CB  bta_gattc_cb;
+#else
+extern tBTA_GATTC_CB *bta_gattc_cb_ptr;
+#define bta_gattc_cb (*bta_gattc_cb_ptr)
+#endif
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg);
+extern void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data);
+
+/* function processed outside SM */
+extern void bta_gattc_register(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_start_if(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_process_api_open (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_process_api_open_cancel (tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
+extern void bta_gattc_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_int_deregister(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA *p_data);
+
+/* function within state machine */
+extern void bta_gattc_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_conn(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_close_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern void bta_gattc_start_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_disc_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_write(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_q_cmd(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_search(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_fail(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_confirm(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_execute(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_read_multi(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_load(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ci_save(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_cache_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_ignore_op_cmpl(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+extern void bta_gattc_init_bk_conn(tBTA_GATTC_API_OPEN *p_data, tBTA_GATTC_RCB *p_clreg);
+extern void bta_gattc_cancel_bk_conn(tBTA_GATTC_API_CANCEL_OPEN *p_data);
+extern void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+                                       BD_ADDR remote_bda, UINT16 conn_id);
+
+/* utility functions */
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda); //todo
+extern tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id);
+extern tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb);
+extern tBTA_GATTC_CLCB * bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda);
+extern tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if);
+extern tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda);
+extern tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id);
+extern BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+extern UINT16 bta_gattc_id2handle(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_SRVC_ID *p_service_id, tBTA_GATT_ID *p_char_id, tBT_UUID descr_uuid);
+extern BOOLEAN bta_gattc_handle2id(tBTA_GATTC_SERV *p_srcb, UINT16 handle, tBTA_GATT_SRVC_ID *service_id, tBTA_GATT_ID *char_id, tBT_UUID *p_type);
+extern BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise);
+extern void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid);
+extern BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb, tBTA_GATTC_NOTIFY  *p_notify);
+extern tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid, tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value);
+extern BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, BOOLEAN add);
+extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda);
+extern UINT8 bta_gattc_num_reg_app(void);
+extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+
+/* discovery functions */
+extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
+extern void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status);
+extern tBTA_GATT_STATUS bta_gattc_discover_procedure(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern tBTA_GATT_STATUS bta_gattc_discover_pri_service(UINT16 conn_id, tBTA_GATTC_SERV *p_server_cb, UINT8 disc_type);
+extern void bta_gattc_search_service(tBTA_GATTC_CLCB *p_clcb, tBT_UUID uuid);
+extern tBTA_GATT_STATUS bta_gattc_query_cache(UINT16 conn_id, UINT8 query_type, tBTA_GATT_SRVC_ID *p_srvc_id,
+                                              tBTA_GATT_ID *p_start_rec,tBT_UUID *p_uuid_cond,
+                                              tBTA_GATT_ID *p_output, void *p_property);
+extern tBTA_GATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV *p_srvc_cb);
+extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV *p_srcv, UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr, UINT16 attr_index);
+extern BOOLEAN bta_gattc_cache_save(tBTA_GATTC_SERV *p_srvc_cb, UINT16 conn_id);
+
+#endif /* BTA_GATTC_INT_H */
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
new file mode 100644
index 0000000..a1fb536
--- /dev/null
+++ b/bta/gatt/bta_gattc_main.c
@@ -0,0 +1,486 @@
+/******************************************************************************
+ *
+ *  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 the GATT client main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gattc_int.h"
+#include "gki.h"
+
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_GATTC_OPEN,
+    BTA_GATTC_OPEN_FAIL,
+    //BTA_GATTC_OPEN_FAIL_IN_CONN,        //<--- need to remove this?
+    BTA_GATTC_OPEN_ERROR,
+    BTA_GATTC_CANCEL_OPEN,
+    BTA_GATTC_CANCEL_OPEN_OK,
+    BTA_GATTC_CANCEL_OPEN_ERROR,
+    BTA_GATTC_CONN,
+    BTA_GATTC_START_DISCOVER,
+    BTA_GATTC_DISC_CMPL,
+
+    BTA_GATTC_Q_CMD,
+    BTA_GATTC_CLOSE,
+    BTA_GATTC_CLOSE_FAIL,
+    BTA_GATTC_READ,
+    BTA_GATTC_WRITE,
+
+    BTA_GATTC_OP_CMPL,
+    BTA_GATTC_SEARCH,
+    BTA_GATTC_FAIL,
+    BTA_GATTC_CONFIRM,
+    BTA_GATTC_EXEC,
+    BTA_GATTC_READ_MULTI,
+    BTA_GATTC_CI_OPEN,
+    BTA_GATTC_CI_LOAD,
+    BTA_GATTC_CI_SAVE,
+    BTA_GATTC_CACHE_OPEN,
+    BTA_GATTC_IGNORE_OP_CMPL,
+
+    BTA_GATTC_IGNORE
+};
+/* type for action functions */
+typedef void (*tBTA_GATTC_ACTION)(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data);
+
+/* action function list */
+const tBTA_GATTC_ACTION bta_gattc_action[] =
+{
+    bta_gattc_open,
+    bta_gattc_open_fail,
+    //bta_gattc_open_fail_in_conn,            //<--- need to remove this?
+    bta_gattc_open_error,
+    bta_gattc_cancel_open,
+    bta_gattc_cancel_open_ok,
+    bta_gattc_cancel_open_error,
+    bta_gattc_conn,
+    bta_gattc_start_discover,
+    bta_gattc_disc_cmpl,
+
+    bta_gattc_q_cmd,
+    bta_gattc_close,
+    bta_gattc_close_fail,
+    bta_gattc_read,
+    bta_gattc_write,
+
+    bta_gattc_op_cmpl,
+    bta_gattc_search,
+    bta_gattc_fail,
+    bta_gattc_confirm,
+    bta_gattc_execute,
+    bta_gattc_read_multi,
+    bta_gattc_ci_open,
+    bta_gattc_ci_load,
+    bta_gattc_ci_save,
+    bta_gattc_cache_open,
+    bta_gattc_ignore_op_cmpl
+};
+
+
+/* state table information */
+#define BTA_GATTC_ACTIONS           1       /* number of actions */
+#define BTA_GATTC_NEXT_STATE          1       /* position of next state */
+#define BTA_GATTC_NUM_COLS            2       /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_gattc_st_idle[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                  Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,              BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE_FAIL,        BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_FAIL,              BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,              BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_INT_DISCONN_EVT       */    {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,            BTA_GATTC_IDLE_ST}
+};
+
+/* state table for wait for open state */
+static const UINT8 bta_gattc_st_w4_conn[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                             Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN,              BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_OPEN_FAIL,         BTA_GATTC_IDLE_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN,       BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_CANCEL_OPEN_OK,    BTA_GATTC_IDLE_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE_FAIL,         BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_FAIL,               BTA_GATTC_W4_CONN_ST},
+
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_CONN,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT       */  {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_INT_DISCONN_EVT      */     {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_W4_CONN_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_gattc_st_connected[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                            Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN_ERROR,         BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN_ERROR, BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_IGNORE,            BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_READ,               BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_WRITE,              BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_EXEC,               BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST}, //BTA_GATTC_CLOSING_ST
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_SEARCH,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_CONFIRM,            BTA_GATTC_CONN_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_READ_MULTI,         BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_START_DISCOVER,     BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT       */  {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_OP_CMPL,            BTA_GATTC_CONN_ST},
+
+/* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving   */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_CACHE_OPEN,         BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_CONN_ST}
+};
+
+/* state table for discover state */
+static const UINT8 bta_gattc_st_discover[][BTA_GATTC_NUM_COLS] =
+{
+/* Event                            Action 1                            Next state */
+/* BTA_GATTC_API_OPEN_EVT           */   {BTA_GATTC_OPEN_ERROR,         BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_OPEN_FAIL_EVT      */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CANCEL_OPEN_EVT    */   {BTA_GATTC_CANCEL_OPEN_ERROR,  BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CANCEL_OPEN_OK_EVT */   {BTA_GATTC_FAIL,               BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_READ_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_WRITE_EVT          */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_EXEC_EVT           */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+
+/* BTA_GATTC_API_CLOSE_EVT          */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST    },    //BTA_GATTC_CLOSING_ST
+
+/* BTA_GATTC_API_SEARCH_EVT         */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_CONFIRM_EVT        */   {BTA_GATTC_CONFIRM,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_API_READ_MULTI_EVT     */   {BTA_GATTC_Q_CMD,              BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_CONN_EVT           */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCOVER_EVT       */   {BTA_GATTC_START_DISCOVER,     BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_DISCOVER_CMPL_EVT      */   {BTA_GATTC_DISC_CMPL,          BTA_GATTC_CONN_ST},
+/* BTA_GATTC_OP_CMPL_EVT            */   {BTA_GATTC_IGNORE_OP_CMPL,     BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_INT_DISCONN_EVT        */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_ST},
+
+/* ===> for cache loading, saving       */
+/* BTA_GATTC_START_CACHE_EVT        */   {BTA_GATTC_IGNORE,             BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_OPEN_EVT      */   {BTA_GATTC_CI_OPEN,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_LOAD_EVT      */   {BTA_GATTC_CI_LOAD,            BTA_GATTC_DISCOVER_ST},
+/* BTA_GATTC_CI_CACHE_SAVE_EVT      */   {BTA_GATTC_CI_SAVE,            BTA_GATTC_DISCOVER_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_GATTC_ST_TBL)[BTA_GATTC_NUM_COLS];
+
+/* state table */
+const tBTA_GATTC_ST_TBL bta_gattc_st_tbl[] =
+{
+    bta_gattc_st_idle,
+    bta_gattc_st_w4_conn,
+    bta_gattc_st_connected,
+    bta_gattc_st_discover
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTC_CB  bta_gattc_cb;
+#endif
+
+#if BTA_GATT_DEBUG == TRUE
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code);
+static char *gattc_state_code(tBTA_GATTC_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gattc_sm_execute
+**
+** Description      State machine event handling function for GATTC
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_sm_execute(tBTA_GATTC_CLCB *p_clcb, UINT16 event, tBTA_GATTC_DATA *p_data)
+{
+    tBTA_GATTC_ST_TBL     state_table;
+    UINT8               action;
+    int                 i;
+#if BTA_GATT_DEBUG == TRUE
+    tBTA_GATTC_STATE in_state = p_clcb->state;
+    UINT16         in_event = event;
+    APPL_TRACE_DEBUG4("bta_gattc_sm_execute: State 0x%02x [%s], Event 0x%x[%s]", in_state,
+                      gattc_state_code(in_state),
+                      in_event,
+                      gattc_evt_code(in_event));
+#endif
+
+
+    /* look up the state table for the current state */
+    state_table = bta_gattc_st_tbl[p_clcb->state];
+
+    event &= 0x00FF;
+
+    /* set next state */
+    p_clcb->state = state_table[event][BTA_GATTC_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_GATTC_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_GATTC_IGNORE)
+        {
+            (*bta_gattc_action[action])(p_clcb, p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+
+#if BTA_GATT_DEBUG == TRUE
+    if (in_state != p_clcb->state)
+    {
+        APPL_TRACE_DEBUG3("GATTC State Change: [%s] -> [%s] after Event [%s]",
+                          gattc_state_code(in_state),
+                          gattc_state_code(p_clcb->state),
+                          gattc_evt_code(in_event));
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_hdl_event
+**
+** Description      GATT client main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_GATTC_CB *p_cb = &bta_gattc_cb;
+    tBTA_GATTC_CLCB *p_clcb = NULL;
+
+#if BTA_GATT_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_gattc_hdl_event: Event [%s]", gattc_evt_code(p_msg->event));
+#endif
+    switch (p_msg->event)
+    {
+        case BTA_GATTC_API_REG_EVT:
+            bta_gattc_register(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_INT_START_IF_EVT:
+            bta_gattc_start_if(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_DEREG_EVT:
+            bta_gattc_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_INT_DEREG_EVT:
+            bta_gattc_int_deregister(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_OPEN_EVT:
+            bta_gattc_process_api_open(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        case BTA_GATTC_API_CANCEL_OPEN_EVT:
+            bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
+        default:
+            if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific))
+                != NULL)
+            {
+                bta_gattc_sm_execute(p_clcb, p_msg->event, (tBTA_GATTC_DATA *) p_msg);
+            }
+            else
+            {
+                APPL_TRACE_ERROR1("Unknown conn ID: %d", p_msg->layer_specific);
+            }
+
+            break;
+    }
+
+
+    return(TRUE);
+}
+
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if BTA_GATT_DEBUG == TRUE
+
+/*******************************************************************************
+**
+** Function         gattc_evt_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *gattc_evt_code(tBTA_GATTC_INT_EVT evt_code)
+{
+    switch (evt_code)
+    {
+        case BTA_GATTC_API_OPEN_EVT:
+            return "BTA_GATTC_API_OPEN_EVT";
+        case BTA_GATTC_INT_OPEN_FAIL_EVT:
+            return "BTA_GATTC_INT_OPEN_FAIL_EVT";
+        case BTA_GATTC_API_CANCEL_OPEN_EVT:
+            return "BTA_GATTC_API_CANCEL_OPEN_EVT";
+        case BTA_GATTC_INT_CANCEL_OPEN_OK_EVT:
+            return "BTA_GATTC_INT_CANCEL_OPEN_OK_EVT";
+        case BTA_GATTC_API_READ_EVT:
+            return "BTA_GATTC_API_READ_EVT";
+        case BTA_GATTC_API_WRITE_EVT:
+            return "BTA_GATTC_API_WRITE_EVT";
+        case BTA_GATTC_API_EXEC_EVT:
+            return "BTA_GATTC_API_EXEC_EVT";
+        case BTA_GATTC_API_CLOSE_EVT:
+            return "BTA_GATTC_API_CLOSE_EVT";
+        case BTA_GATTC_API_SEARCH_EVT:
+            return "BTA_GATTC_API_SEARCH_EVT";
+        case BTA_GATTC_API_CONFIRM_EVT:
+            return "BTA_GATTC_API_CONFIRM_EVT";
+        case BTA_GATTC_API_READ_MULTI_EVT:
+            return "BTA_GATTC_API_READ_MULTI_EVT";
+        case BTA_GATTC_INT_CONN_EVT:
+            return "BTA_GATTC_INT_CONN_EVT";
+        case BTA_GATTC_INT_DISCOVER_EVT:
+            return "BTA_GATTC_INT_DISCOVER_EVT";
+        case BTA_GATTC_DISCOVER_CMPL_EVT:
+            return "BTA_GATTC_DISCOVER_CMPL_EVT";
+        case BTA_GATTC_OP_CMPL_EVT:
+            return "BTA_GATTC_OP_CMPL_EVT";
+        case BTA_GATTC_INT_DISCONN_EVT:
+            return "BTA_GATTC_INT_DISCONN_EVT";
+        case BTA_GATTC_START_CACHE_EVT:
+            return "BTA_GATTC_START_CACHE_EVT";
+        case BTA_GATTC_CI_CACHE_OPEN_EVT:
+            return "BTA_GATTC_CI_CACHE_OPEN_EVT";
+        case BTA_GATTC_CI_CACHE_LOAD_EVT:
+            return "BTA_GATTC_CI_CACHE_LOAD_EVT";
+        case BTA_GATTC_CI_CACHE_SAVE_EVT:
+            return "BTA_GATTC_CI_CACHE_SAVE_EVT";
+        case BTA_GATTC_INT_START_IF_EVT:
+            return "BTA_GATTC_INT_START_IF_EVT";
+        case BTA_GATTC_API_REG_EVT:
+            return "BTA_GATTC_API_REG_EVT";
+        case BTA_GATTC_API_DEREG_EVT:
+            return "BTA_GATTC_API_DEREG_EVT";
+
+        default:
+            return "unknown GATTC event code";
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gattc_state_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *gattc_state_code(tBTA_GATTC_STATE state_code)
+{
+    switch (state_code)
+    {
+        case BTA_GATTC_IDLE_ST:
+            return "GATTC_IDLE_ST";
+        case BTA_GATTC_W4_CONN_ST:
+            return "GATTC_W4_CONN_ST";
+        case BTA_GATTC_CONN_ST:
+            return "GATTC_CONN_ST";
+        case BTA_GATTC_DISCOVER_ST:
+            return "GATTC_DISCOVER_ST";
+        default:
+            return "unknown GATTC state code";
+    }
+}
+
+#endif  /* Debug Functions */
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
new file mode 100644
index 0000000..a36e26c
--- /dev/null
+++ b/bta/gatt/bta_gattc_utils.c
@@ -0,0 +1,664 @@
+/******************************************************************************
+ *
+ *  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 the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gattc_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*******************************************************************************
+**
+** Function         bta_gatt_convert_uuid16_to_uuid128
+**
+** Description      Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
+
+    memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+    UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_uuid_compare
+**
+** Description      Compare two UUID to see if they are the same.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_uuid_compare (tBT_UUID src, tBT_UUID tar, BOOLEAN is_precise)
+{
+    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
+    UINT8  *ps, *pt;
+
+    /* any of the UUID is unspecified */
+    if (src.len == 0 || tar.len == 0)
+    {
+        if (is_precise)
+            return FALSE;
+        else
+            return TRUE;
+    }
+
+    /* If both are 16-bit, we can do a simple compare */
+    if (src.len == 2 && tar.len == 2)
+    {
+        return src.uu.uuid16 == tar.uu.uuid16;
+    }
+
+    /* One or both of the UUIDs is 128-bit */
+    if (src.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+        ps = su;
+    }
+    else
+        ps = src.uu.uuid128;
+
+    if (tar.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+        pt = tu;
+    }
+    else
+        pt = tar.uu.uuid128;
+
+    return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_cl_get_regcb
+**
+** Description      get registration control block by client interface.
+**
+** Returns          pointer to the regcb
+**
+*******************************************************************************/
+tBTA_GATTC_RCB * bta_gattc_cl_get_regcb(UINT8 client_if)
+{
+    UINT8   i = 0;
+    tBTA_GATTC_RCB  *p_clrcb = &bta_gattc_cb.cl_rcb[0];
+
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++, p_clrcb ++)
+    {
+        if (p_clrcb->in_use &&
+            p_clrcb->client_if == client_if)
+            return p_clrcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_num_reg_app
+**
+** Description      find the number of registered application.
+**
+** Returns          pointer to the regcb
+**
+*******************************************************************************/
+UINT8 bta_gattc_num_reg_app(void)
+{
+    UINT8   i = 0, j = 0;
+
+    for (i = 0; i < BTA_GATTC_CL_MAX; i ++)
+    {
+        if (bta_gattc_cb.cl_rcb[i].in_use)
+            j ++;
+    }
+    return j;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_clcb_by_cif
+**
+** Description      get clcb by client interface and remote bd adddress
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_cif (UINT8 client_if, BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+    UINT8   i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+    {
+        if (p_clcb->in_use &&
+            p_clcb->p_rcb->client_if == client_if &&
+            p_clcb->p_srcb &&
+            bdcmp(p_clcb->p_srcb->server_bda, remote_bda) == 0)
+            return p_clcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_clcb_by_conn_id
+**
+** Description      get clcb by connection ID
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_find_clcb_by_conn_id (UINT16 conn_id)
+{
+    tBTA_GATTC_CLCB *p_clcb = &bta_gattc_cb.clcb[0];
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+    {
+        if (p_clcb->in_use &&
+            p_clcb->bta_conn_id == conn_id)
+            return p_clcb;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_clcb_alloc
+**
+** Description      allocate CLCB
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB * bta_gattc_clcb_alloc(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+{
+    UINT8               i_clcb = 0;
+    tBTA_GATTC_CLCB     *p_clcb = NULL;
+
+    for (i_clcb = 0; i_clcb < BTA_GATTC_CLCB_MAX; i_clcb++)
+    {
+        if (!bta_gattc_cb.clcb[i_clcb].in_use)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG1("bta_gattc_clcb_alloc: found clcb[%d] available",i_clcb);
+#endif
+            p_clcb                  = &bta_gattc_cb.clcb[i_clcb];
+            p_clcb->in_use          = TRUE;
+            bdcpy(p_clcb->bda, remote_bda);
+
+            p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
+
+            if ((p_clcb->p_srcb = bta_gattc_find_srcb(remote_bda)) == NULL)
+                p_clcb->p_srcb      = bta_gattc_srcb_alloc(remote_bda);
+
+            if (p_clcb->p_rcb != NULL && p_clcb->p_srcb != NULL)
+            {
+                p_clcb->p_srcb->num_clcb ++;
+                p_clcb->p_rcb->num_clcb ++;
+            }
+            else
+            {
+                /* release this clcb if clcb or srcb allocation failed */
+                p_clcb->in_use = FALSE;
+                p_clcb = NULL;
+            }
+            break;
+        }
+    }
+    return p_clcb;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_alloc_clcb
+**
+** Description      find or allocate CLCB if not found.
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CLCB *bta_gattc_find_alloc_clcb(tBTA_GATTC_IF client_if, BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CLCB *p_clcb ;
+
+    if ((p_clcb = bta_gattc_find_clcb_by_cif(client_if, remote_bda)) == NULL)
+    {
+        p_clcb = bta_gattc_clcb_alloc(client_if, remote_bda);
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_clcb_dealloc
+**
+** Description      Deallocte a clcb
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
+{
+
+    if (p_clcb)
+    {
+        if (p_clcb->p_srcb->num_clcb)
+            p_clcb->p_srcb->num_clcb --;
+
+        if (p_clcb->p_rcb->num_clcb)
+            p_clcb->p_rcb->num_clcb --;
+
+        utl_freebuf((void **)&p_clcb->p_q_cmd);
+
+        APPL_TRACE_ERROR2("bta_gattc_clcb_dealloc in_use=%d conn_id=%d",p_clcb->in_use, p_clcb->bta_conn_id);
+        memset(p_clcb, 0, sizeof(tBTA_GATTC_CLCB));
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("bta_gattc_clcb_dealloc p_clcb=NULL");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_srcb
+**
+** Description      find server cache by remote bd address
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srcb(BD_ADDR bda)
+{
+    tBTA_GATTC_SERV *p_srcb = &bta_gattc_cb.known_server[0];
+    UINT8   i;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_srcb ++)
+    {
+        if (p_srcb->in_use && bdcmp(p_srcb->server_bda, bda) == 0)
+            return p_srcb;
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_find_scb_by_cid
+**
+** Description      find server control block by connection ID
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_scb_by_cid (UINT16 conn_id)
+{
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+
+    if (p_clcb)
+        return p_clcb->p_srcb;
+    else
+        return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_srcb_alloc
+**
+** Description      allocate server cache control block
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_srcb_alloc(BD_ADDR bda)
+{
+    tBTA_GATTC_SERV *p_tcb = &bta_gattc_cb.known_server[0],
+                             *p_recycle = NULL;
+    BOOLEAN         found = FALSE;
+    UINT8           i;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_tcb ++)
+    {
+        if (!p_tcb->in_use)
+        {
+            found = TRUE;
+            break;
+        }
+        else if (!p_tcb->connected)
+        {
+            p_recycle = p_tcb;
+        }
+    }
+
+    /* if not found, try to recycle one known device */
+    if (!found && !p_recycle)
+        p_tcb = NULL;
+    else if (p_recycle)
+        p_tcb = p_recycle;
+
+    if (p_tcb != NULL)
+    {
+        while (p_tcb->cache_buffer.p_first)
+            GKI_freebuf (GKI_dequeue (&p_tcb->cache_buffer));
+
+        utl_freebuf((void **)&p_tcb->p_srvc_list);
+        memset(p_tcb, 0 , sizeof(tBTA_GATTC_SERV));
+
+        p_tcb->in_use = TRUE;
+        bdcpy(p_tcb->server_bda, bda);
+    }
+    return p_tcb;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_enqueue
+**
+** Description      enqueue a client request in clcb.
+**
+** Returns          success or failure.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_enqueue(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    BOOLEAN in_q = FALSE;
+
+    if (p_clcb->p_q_cmd == NULL)
+    {
+        p_clcb->p_q_cmd = (tBTA_GATTC_DATA *)GKI_getbuf(sizeof(tBTA_GATTC_DATA));
+
+        if (p_data)
+            memcpy(p_clcb->p_q_cmd, p_data, sizeof(tBTA_GATTC_DATA));
+
+        in_q = TRUE;
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("already has a pending command!!");
+        /* skip the callback now. ----- need to send callback ? */
+    }
+    return in_q;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_pack_attr_uuid
+**
+** Description      pack UUID into a stream.
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_pack_attr_uuid(tBTA_GATTC_CACHE_ATTR   *p_attr, tBT_UUID *p_uuid)
+{
+    UINT8 *pp = (UINT8 *)p_attr->p_uuid;
+
+    memset(p_uuid, 0, sizeof(tBT_UUID));
+
+    p_uuid->len = p_attr->uuid_len;
+
+    if (p_attr->uuid_len == LEN_UUID_16)
+    {
+        STREAM_TO_UINT16(p_uuid->uu.uuid16, pp);
+    }
+    else
+    {
+        memcpy(p_uuid->uu.uuid128, pp, LEN_UUID_128);
+    }
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_check_notif_registry
+**
+** Description      check if the service notificaition has been registered.
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_notif_registry(tBTA_GATTC_RCB  *p_clreg, tBTA_GATTC_SERV *p_srcb,
+                                       tBTA_GATTC_NOTIFY  *p_notify)
+{
+    UINT8           i;
+
+    for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+    {
+        if (p_clreg->notif_reg[i].in_use &&
+            bdcmp(p_clreg->notif_reg[i].remote_bda, p_srcb->server_bda) == 0 &&
+            (bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.srvc_id.id.uuid, p_notify->char_id.srvc_id.id.uuid, FALSE) &&
+              p_clreg->notif_reg[i].char_id.srvc_id.id.inst_id == p_notify->char_id.srvc_id.id.inst_id &&
+              p_clreg->notif_reg[i].char_id.srvc_id.is_primary == p_notify->char_id.srvc_id.is_primary  &&
+              bta_gattc_uuid_compare(p_clreg->notif_reg[i].char_id.char_id.uuid, p_notify->char_id.char_id.uuid, FALSE) &&
+              p_clreg->notif_reg[i].char_id.char_id.inst_id == p_notify->char_id.char_id.inst_id)
+           )
+        {
+            APPL_TRACE_DEBUG0("Notification registered!");
+            return TRUE;
+        }
+    }
+    return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_clear_notif_registration
+**
+** Description      clear up the notification registration information by BD_ADDR.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_clear_notif_registration(UINT16 conn_id)
+{
+    BD_ADDR             remote_bda;
+    tBTA_GATTC_IF       gatt_if;
+    tBTA_GATTC_RCB      *p_clrcb ;
+    UINT8       i;
+
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, remote_bda))
+    {
+        if ((p_clrcb = bta_gattc_cl_get_regcb(gatt_if)) != NULL)
+        {
+            for (i = 0 ; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+            {
+                if (p_clrcb->notif_reg[i].in_use && !bdcmp(p_clrcb->notif_reg[i].remote_bda, remote_bda))
+                    memset(&p_clrcb->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
+            }
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("can not clear indication/notif registration for unknown app");
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_pack_cb_data
+**
+** Description      pack the data from read response into callback data structure.
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_GATT_STATUS bta_gattc_pack_read_cb_data(tBTA_GATTC_SERV *p_srcb, tBT_UUID descr_uuid,
+                                             tGATT_VALUE *p_attr, tBTA_GATT_READ_VAL *p_value)
+{
+    UINT8                   i = 0, *pp = p_attr->value;
+    tBT_UUID                uuid = {LEN_UUID_16, {GATT_UUID_CHAR_AGG_FORMAT}};
+    UINT16                  handle;
+    tBTA_GATT_STATUS        status = BTA_GATT_OK;
+
+    /* GATT_UUID_CHAR_AGG_FORMAT */
+    if (bta_gattc_uuid_compare (uuid, descr_uuid, TRUE))
+    {
+        while (p_attr->len >= 2 && i < BTA_GATTC_MULTI_MAX)
+        {
+            STREAM_TO_UINT16(handle, pp);
+
+            if (bta_gattc_handle2id(p_srcb,
+                                    handle,
+                                    &p_value->aggre_value.pre_format[i].char_id.srvc_id,
+                                    &p_value->aggre_value.pre_format[i].char_id.char_id,
+                                    &p_value->aggre_value.pre_format[i].descr_type) == FALSE)
+            {
+                status = BTA_GATT_INTERNAL_ERROR;
+                APPL_TRACE_ERROR1("can not map to GATT ID. handle = 0x%04x", handle);
+                break;
+            }
+            i ++;
+            p_attr->len -= 2;
+        }
+        p_value->aggre_value.num_pres_fmt = i;
+    }
+    else
+    {
+        /* all others, take as raw format */
+        p_value->unformat.len = p_attr->len;
+        p_value->unformat.p_value = p_attr->value;
+    }
+    return status;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_mark_bg_conn
+**
+** Description      mark background connection status when a bg connection is initiated
+**                  or terminated.
+**
+** Returns          TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, BOOLEAN add)
+{
+    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
+    UINT8   i = 0;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+    {
+        if (p_bg_tck->in_use &&
+            bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+        {
+            if (add)
+                /* mask on the cif bit */
+                p_bg_tck->cif_mask |= (1 <<(client_if - 1));
+            else
+                p_bg_tck->cif_mask &= (~(1 <<(client_if - 1)));
+
+            return TRUE;
+        }
+    }
+    if (!add)
+    {
+        APPL_TRACE_ERROR0("Do not find the bg connection mask for the remote device");
+        return FALSE;
+    }
+    else /* adding a new device mask */
+    {
+        for (i = 0, p_bg_tck = &bta_gattc_cb.bg_track[0];
+             i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+        {
+            if (!p_bg_tck->in_use)
+            {
+                p_bg_tck->in_use = TRUE;
+                bdcpy(p_bg_tck->remote_bda, remote_bda);
+                p_bg_tck->cif_mask = (1 <<(client_if - 1));
+                return TRUE;
+            }
+        }
+        APPL_TRACE_ERROR0("no available space to mark the bg connection status");
+        return FALSE;
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_check_bg_conn
+**
+** Description      check if this is a background connection background connection.
+**
+** Returns          TRUE if success; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda)
+{
+    tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
+    UINT8       i = 0;
+    BOOLEAN     is_bg_conn = FALSE;
+
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX; i ++, p_bg_tck ++)
+    {
+        if (p_bg_tck->in_use &&
+            bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+        {
+            if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0)
+                is_bg_conn = TRUE;
+            break;
+        }
+    }
+    return is_bg_conn;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_send_open_cback
+**
+** Description      send open callback
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_send_open_cback( tBTA_GATTC_RCB *p_clreg, tBTA_GATT_STATUS status,
+                                BD_ADDR remote_bda, UINT16 conn_id)
+{
+    tBTA_GATTC      cb_data;
+
+    if (p_clreg->p_cback)
+    {
+        memset(&cb_data, 0, sizeof(tBTA_GATTC));
+
+        cb_data.open.status = status;
+        cb_data.open.client_if = p_clreg->client_if;
+        cb_data.open.conn_id = conn_id;
+        bdcpy(cb_data.open.remote_bda, remote_bda);
+
+        (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
+    }
+}
+
+
+
+
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
new file mode 100644
index 0000000..1b47598
--- /dev/null
+++ b/bta/gatt/bta_gatts_act.c
@@ -0,0 +1,798 @@
+/******************************************************************************
+ *
+ *  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 the GATT Server action functions for the state
+ *  machine.
+ *
+ ******************************************************************************/
+
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+#include "bta_gatts_co.h"
+
+#include <string.h>
+
+static void bta_gatts_nv_save_cback(BOOLEAN is_saved, tGATTS_HNDL_RANGE *p_hndl_range);
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp);
+
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+                                          UINT32 trans_id,
+                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data);
+static tGATT_CBACK bta_gatts_cback =
+{
+    bta_gatts_conn_cback,
+    NULL,
+    NULL,
+    NULL,
+    bta_gatts_send_request_cback
+};
+
+tGATT_APPL_INFO bta_gatts_nv_cback =
+{
+    bta_gatts_nv_save_cback,
+    bta_gatts_nv_srv_chg_cback
+};
+
+/*******************************************************************************
+**
+** Function         bta_gatts_nv_save_cback
+**
+** Description      NV save callback function.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_nv_save_cback(BOOLEAN is_add, tGATTS_HNDL_RANGE *p_hndl_range)
+{
+    bta_gatts_co_update_handle_range(is_add, (tBTA_GATTS_HNDL_RANGE *)p_hndl_range);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_nv_srv_chg_cback
+**
+** Description      NV save callback function.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+** Returns          none.
+**
+*******************************************************************************/
+static BOOLEAN bta_gatts_nv_srv_chg_cback(tGATTS_SRV_CHG_CMD cmd, tGATTS_SRV_CHG_REQ *p_req, tGATTS_SRV_CHG_RSP *p_rsp)
+{
+    return bta_gatts_co_srv_chg((tBTA_GATTS_SRV_CHG_CMD) cmd,
+                                (tBTA_GATTS_SRV_CHG_REQ *) p_req,
+                                (tBTA_GATTS_SRV_CHG_RSP *) p_rsp);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_enable
+**
+** Description      enable BTA GATTS module.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_enable(tBTA_GATTS_CB *p_cb)
+{
+    UINT8 index=0;
+    tBTA_GATTS_HNDL_RANGE handle_range;
+
+    p_cb->enabled = TRUE;
+
+    APPL_TRACE_DEBUG0("bta_gatts_enable");
+    while ( bta_gatts_co_load_handle_range(index, &handle_range))
+    {
+        GATTS_AddHandleRange((tGATTS_HNDL_RANGE *)&handle_range);
+        memset(&handle_range, 0, sizeof(tGATTS_HNDL_RANGE));
+        index++;
+    }
+
+    APPL_TRACE_DEBUG1("bta_gatts_enable: num of handle range added=%d", index);
+
+    if (!GATTS_NVRegister(&bta_gatts_nv_cback))
+    {
+        APPL_TRACE_ERROR0("BTA GATTS NV register failed.");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_register
+**
+** Description      register an application.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    tBTA_GATTS_INT_START_IF  *p_buf;
+    tBTA_GATTS               cb_data;
+    tBTA_GATT_STATUS         status = BTA_GATT_OK;
+    UINT8                    i, first_unuse = 0xff;
+
+    if (!p_cb->enabled)
+        bta_gatts_enable(p_cb);
+
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use)
+        {
+            if (bta_gatts_uuid_compare(p_cb->rcb[i].app_uuid, p_msg->api_reg.app_uuid))
+            {
+                APPL_TRACE_ERROR0("application already registered.");
+                status = BTA_GATT_DUP_REG;
+                break;
+            }
+        }
+    }
+
+    if (status == BTA_GATT_OK)
+    {
+        for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+        {
+            if (first_unuse == 0xff && !p_cb->rcb[i].in_use)
+            {
+                first_unuse = i;
+                break;
+            }
+        }
+
+        cb_data.reg_oper.server_if = BTA_GATTS_INVALID_IF;
+// btla-specific ++
+        memcpy(&cb_data.reg_oper.uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+// btla-specific --
+        if (first_unuse != 0xff)
+        {
+            APPL_TRACE_ERROR1("register application first_unuse rcb_idx = %d", first_unuse);
+
+            p_cb->rcb[first_unuse].in_use = TRUE;
+            p_cb->rcb[first_unuse].p_cback = p_msg->api_reg.p_cback;
+            memcpy(&p_cb->rcb[first_unuse].app_uuid, &p_msg->api_reg.app_uuid, sizeof(tBT_UUID));
+            cb_data.reg_oper.server_if      =
+            p_cb->rcb[first_unuse].gatt_if  = GATT_Register(&p_msg->api_reg.app_uuid, &bta_gatts_cback);
+            if ( !p_cb->rcb[first_unuse].gatt_if)
+            {
+                status = BTA_GATT_NO_RESOURCES;
+            }
+            else
+            {
+                if ((p_buf = (tBTA_GATTS_INT_START_IF *) GKI_getbuf(sizeof(tBTA_GATTS_INT_START_IF))) != NULL)
+                {
+                    p_buf->hdr.event    = BTA_GATTS_INT_START_IF_EVT;
+                    p_buf->server_if    = p_cb->rcb[first_unuse].gatt_if;
+
+                    bta_sys_sendmsg(p_buf);
+                }
+                else
+                {
+                    status = BTA_GATT_NO_RESOURCES;
+                    memset( &p_cb->rcb[first_unuse], 0 , sizeof(tBTA_GATTS_RCB));
+                }
+            }
+        }
+        else
+        {
+            status = BTA_GATT_NO_RESOURCES;
+        }
+
+    }
+    cb_data.reg_oper.status = status;
+    if (p_msg->api_reg.p_cback)
+        (*p_msg->api_reg.p_cback)(BTA_GATTS_REG_EVT, &cb_data);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_start_if
+**
+** Description      start an application interface.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    if (bta_gatts_find_app_rcb_by_app_if(p_msg->int_start_if.server_if))
+    {
+        GATT_StartIf(p_msg->int_start_if.server_if);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.server_if );
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_deregister
+**
+** Description      deregister an application.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_ERROR;
+    tBTA_GATTS_CBACK    *p_cback = NULL;
+    UINT8               i;
+    tBTA_GATTS          cb_data;
+
+    cb_data.reg_oper.server_if = p_msg->api_dereg.server_if;
+    cb_data.reg_oper.status = status;
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == p_msg->api_dereg.server_if)
+        {
+            p_cback = p_cb->rcb[i].p_cback;
+            status = BTA_GATT_OK;
+
+            /* deregister the app */
+            GATT_Deregister(p_cb->rcb[i].gatt_if);
+
+            /* reset cb */
+            memset(&p_cb->rcb[i], 0, sizeof(tBTA_GATTS_RCB));
+            cb_data.reg_oper.status = status;
+            break;
+        }
+    }
+
+    if (p_cback)
+    {
+        (*p_cback)(BTA_GATTS_DEREG_EVT, &cb_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("application not registered.");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_create_srvc
+**
+** Description      action function to create a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    UINT8               rcb_idx;
+    tBTA_GATTS          cb_data;
+    UINT8               srvc_idx;
+    UINT16              service_id = 0;
+    //tBTA_GATTS_HNDL_RANGE   handle_range;
+
+    cb_data.create.status = BTA_GATT_ERROR;
+
+    rcb_idx = bta_gatts_find_app_rcb_idx_by_app_if(p_cb, p_msg->api_create_svc.server_if);
+
+    APPL_TRACE_ERROR1("create service rcb_idx = %d", rcb_idx);
+
+    if (rcb_idx != BTA_GATTS_INVALID_APP)
+    {
+        if ((srvc_idx = bta_gatts_alloc_srvc_cb(p_cb, rcb_idx)) != BTA_GATTS_INVALID_APP)
+        {
+            /* create the service now */
+            service_id = GATTS_CreateService (p_cb->rcb[rcb_idx].gatt_if,
+                                              &p_msg->api_create_svc.service_uuid,
+                                              p_msg->api_create_svc.inst,
+                                              p_msg->api_create_svc.num_handle,
+                                              p_msg->api_create_svc.is_pri);
+
+            if (service_id != 0)
+            {
+                memcpy(&p_cb->srvc_cb[srvc_idx].service_uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+                p_cb->srvc_cb[srvc_idx].service_id   = service_id;
+                p_cb->srvc_cb[srvc_idx].inst_num     = p_msg->api_create_svc.inst;
+                p_cb->srvc_cb[srvc_idx].idx          = srvc_idx;
+
+                cb_data.create.status      = BTA_GATT_OK;
+                cb_data.create.service_id  = service_id;
+// btla-specific ++
+                cb_data.create.is_primary  = p_msg->api_create_svc.is_pri;
+// btla-specific --
+                cb_data.create.server_if   = p_cb->rcb[rcb_idx].gatt_if;
+            }
+            else
+            {
+                cb_data.status  = BTA_GATT_ERROR;
+                memset(&p_cb->srvc_cb[srvc_idx], 0, sizeof(tBTA_GATTS_SRVC_CB));
+                APPL_TRACE_ERROR0("service creation failed.");
+            }
+// btla-specific ++
+            memcpy(&cb_data.create.uuid, &p_msg->api_create_svc.service_uuid, sizeof(tBT_UUID));
+            cb_data.create.svc_instance= p_msg->api_create_svc.inst;
+// btla-specific --
+        }
+        if (p_cb->rcb[rcb_idx].p_cback)
+            (* p_cb->rcb[rcb_idx].p_cback)(BTA_GATTS_CREATE_EVT, &cb_data);
+    }
+    else /* application not registered */
+    {
+        APPL_TRACE_ERROR0("Application not registered");
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_include_srvc
+**
+** Description      action function to add an included service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb,tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddIncludeService(p_msg->api_add_incl_srvc.hdr.layer_specific,
+                                      p_msg->api_add_incl_srvc.included_service_id);
+
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_INCL_SRVC_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_char
+**
+** Description      action function to add characteristic.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddCharacteristic(p_msg->api_add_char.hdr.layer_specific,
+                                      &p_msg->api_add_char.char_uuid,
+                                      p_msg->api_add_char.perm,
+                                      p_msg->api_add_char.property);
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char.char_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_EVT, &cb_data);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_add_char_descr
+**
+** Description      action function to add characteristic descriptor.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB  *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    UINT16          attr_id = 0;
+    tBTA_GATTS      cb_data;
+
+    attr_id = GATTS_AddCharDescriptor(p_msg->api_add_char_descr.hdr.layer_specific,
+                                       p_msg->api_add_char_descr.perm,
+                                       &p_msg->api_add_char_descr.descr_uuid);
+
+    cb_data.add_result.server_if = p_rcb->gatt_if;
+    cb_data.add_result.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+    cb_data.add_result.attr_id = attr_id;
+// btla-specific ++
+    memcpy(&cb_data.add_result.char_uuid, &p_msg->api_add_char_descr.descr_uuid, sizeof(tBT_UUID));
+// btla-specific --
+
+    if (attr_id)
+    {
+        cb_data.add_result.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.add_result.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_ADD_CHAR_DESCR_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_delete_service
+**
+** Description      action function to delete a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+    if (GATTS_DeleteService(p_rcb->gatt_if,
+                            &p_srvc_cb->service_uuid,
+                            p_srvc_cb->inst_num))
+    {
+        cb_data.srvc_oper.status = BTA_GATT_OK;
+        memset(p_srvc_cb, 0, sizeof(tBTA_GATTS_SRVC_CB));
+    }
+    else
+    {
+        cb_data.srvc_oper.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_DELELTE_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_start_service
+**
+** Description      action function to start a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_msg->api_add_incl_srvc.hdr.layer_specific;
+
+    if (GATTS_StartService(p_rcb->gatt_if,
+                           p_srvc_cb->service_id,
+                           p_msg->api_start.transport) ==  GATT_SUCCESS)
+    {
+        APPL_TRACE_DEBUG1("bta_gatts_start_service service_id= %d", p_srvc_cb->service_id);
+        cb_data.srvc_oper.status = BTA_GATT_OK;
+    }
+    else
+    {
+        cb_data.srvc_oper.status = BTA_GATT_ERROR;
+    }
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_START_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_stop_service
+**
+** Description      action function to stop a service.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB *p_rcb = &bta_gatts_cb.rcb[p_srvc_cb->rcb_idx];
+    tBTA_GATTS      cb_data;
+
+    GATTS_StopService(p_srvc_cb->service_id);
+    cb_data.srvc_oper.server_if = p_rcb->gatt_if;
+    cb_data.srvc_oper.service_id = p_srvc_cb->service_id;
+    cb_data.srvc_oper.status = BTA_GATT_OK;
+    APPL_TRACE_ERROR1("bta_gatts_stop_service service_id= %d", p_srvc_cb->service_id);
+
+    if (p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_STOP_EVT, &cb_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_send_rsp
+**
+** Description      GATTS send response.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_send_rsp (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+
+    if (GATTS_SendRsp (p_msg->api_rsp.hdr.layer_specific,
+                        p_msg->api_rsp.trans_id,
+                        p_msg->api_rsp.status,
+                        (tGATTS_RSP *)p_msg->api_rsp.p_rsp) != GATT_SUCCESS)
+    {
+        APPL_TRACE_ERROR0("Sending response failed");
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_send_rsp
+**
+** Description      GATTS send response.
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_SRVC_CB  *p_srvc_cb;
+    tBTA_GATT_STATUS    status;
+
+
+    p_srvc_cb = bta_gatts_find_srvc_cb_by_attr_id (p_cb, p_msg->api_indicate.attr_id);
+
+    if (p_srvc_cb )
+    {
+        if (p_msg->api_indicate.need_confirm)
+
+            status = GATTS_HandleValueIndication (p_msg->api_indicate.hdr.layer_specific,
+                                                  p_msg->api_indicate.attr_id,
+                                                  p_msg->api_indicate.len,
+                                                  p_msg->api_indicate.value);
+        else
+            status = GATTS_HandleValueNotification (p_msg->api_indicate.hdr.layer_specific,
+                                                    p_msg->api_indicate.attr_id,
+                                                    p_msg->api_indicate.len,
+                                                    p_msg->api_indicate.value);
+
+        if (status != GATT_SUCCESS &&
+            p_msg->api_indicate.need_confirm &&
+            p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)
+        {
+            (*p_cb->rcb[p_srvc_cb->rcb_idx].p_cback)(BTA_GATTS_CONF_EVT, (tBTA_GATTS *)&status);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Not an registered servce attribute ID: 0x%04x", p_msg->api_indicate.attr_id);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_open
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB      *p_rcb=NULL;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+
+
+    if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_open.server_if)) != NULL)
+    {
+        if (GATT_Connect(p_rcb->gatt_if, p_msg->api_open.remote_bda, p_msg->api_open.is_direct))
+        {
+            status = BTA_GATT_OK;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Inavlide server_if=%d", p_msg->api_open.server_if);
+    }
+
+    if (p_rcb && p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_OPEN_EVT,  (tBTA_GATTS *)&status);
+
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_cancel_open
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB      *p_rcb;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+
+    if ((p_rcb = bta_gatts_find_app_rcb_by_app_if(p_msg->api_cancel_open.server_if)) != NULL)
+    {
+        if (!GATT_CancelConnect(p_rcb->gatt_if, p_msg->api_cancel_open.remote_bda, p_msg->api_cancel_open.is_direct))
+        {
+            APPL_TRACE_ERROR0("bta_gatts_cancel_open failed for open request");
+        }
+        else
+        {
+            status= BTA_GATT_OK;
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Inavlide server_if=%d", p_msg->api_cancel_open.server_if);
+    }
+
+    if (p_rcb && p_rcb->p_cback)
+        (*p_rcb->p_cback)(BTA_GATTS_CANCEL_OPEN_EVT,  (tBTA_GATTS *)&status);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_close
+**
+** Description
+**
+** Returns          none.
+**
+*******************************************************************************/
+void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg)
+{
+    tBTA_GATTS_RCB     *p_rcb;
+    tBTA_GATT_STATUS    status= BTA_GATT_ERROR;
+    tGATT_IF            gatt_if;
+    BD_ADDR             remote_bda;
+
+    if (GATT_GetConnectionInfor(p_msg->hdr.layer_specific, &gatt_if, remote_bda))
+    {
+        if (GATT_Disconnect(p_msg->hdr.layer_specific) != GATT_SUCCESS)
+        {
+            APPL_TRACE_ERROR1("bta_gatts_close fail conn_id=%d", p_msg->hdr.layer_specific);
+        }
+        else
+        {
+            status= BTA_GATT_OK;
+        }
+
+        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+        if (p_rcb && p_rcb->p_cback)
+            (*p_rcb->p_cback)(BTA_GATTS_CLOSE_EVT,  (tBTA_GATTS *)&status);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Unknown connection ID: %d", p_msg->hdr.layer_specific);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_gatts_request_cback
+**
+** Description      GATTS attribute request callback.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_send_request_cback (UINT16 conn_id,
+                                          UINT32 trans_id,
+                                          tGATTS_REQ_TYPE req_type, tGATTS_DATA *p_data)
+{
+    tBTA_GATTS          cb_data;
+    tBTA_GATTS_RCB     *p_rcb;
+    tGATT_IF            gatt_if;
+
+    memset(&cb_data, 0 , sizeof(tBTA_GATTS));
+
+    if (GATT_GetConnectionInfor(conn_id, &gatt_if, cb_data.req_data.remote_bda))
+    {
+        p_rcb = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+        APPL_TRACE_DEBUG3 ("bta_gatts_send_request_cback conn_id=%d trans_id=%d req_type=%d", conn_id, trans_id, req_type);
+
+        if (p_rcb && p_rcb->p_cback)
+        {
+            cb_data.req_data.conn_id    = conn_id;
+            cb_data.req_data.trans_id   = trans_id;
+            cb_data.req_data.p_data     = (tBTA_GATTS_REQ_DATA *)p_data;
+
+            (*p_rcb->p_cback)(req_type,  &cb_data);
+        }
+        else
+        {
+            APPL_TRACE_ERROR1("connection request on gatt_if[%d] is not interested", gatt_if);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("request received on unknown connectino ID: %d", conn_id);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_conn_cback
+**
+** Description      connection callback.
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void bta_gatts_conn_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+                                  BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+    tBTA_GATTS      cb_data;
+    UINT8           evt = connected ? BTA_GATTS_CONNECT_EVT: BTA_GATTS_DISCONNECT_EVT;
+    tBTA_GATTS_RCB  *p_reg;
+
+    APPL_TRACE_DEBUG4 ("bta_gatts_conn_cback gatt_if=%d conn_id=%d connected=%d reason = 0x%04d",
+                        gatt_if, conn_id, connected, reason);
+    APPL_TRACE_DEBUG6("bta_gatts_conn_cback  bda :%02x-%02x-%02x-%02x-%02x-%02x ",
+                      bda[0],  bda[1], bda[2],  bda[3], bda[4],  bda[5]);
+
+    p_reg = bta_gatts_find_app_rcb_by_app_if(gatt_if);
+
+    if (p_reg && p_reg->p_cback)
+    {
+        cb_data.conn.conn_id = conn_id;
+        cb_data.conn.server_if = gatt_if;
+        cb_data.conn.reason = reason;
+        memcpy(cb_data.conn.remote_bda, bda, BD_ADDR_LEN);
+        (*p_reg->p_cback)(evt, &cb_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("bta_gatts_conn_cback server_if=%d not found",gatt_if);
+    }
+}
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_api.c b/bta/gatt/bta_gatts_api.c
new file mode 100644
index 0000000..65df0a6
--- /dev/null
+++ b/bta/gatt/bta_gatts_api.c
@@ -0,0 +1,512 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the implementation of the API for GATT server of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "bta_gatts_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_gatts_reg =
+{
+    bta_gatts_hdl_event,
+    NULL        /* need a disable functino to be called when BT is disabled */
+};
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTS module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_cback - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback)
+{
+    tBTA_GATTS_API_REG  *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    if (!bta_gatts_cb.enabled)
+    {
+        bta_sys_register(BTA_ID_GATTS, &bta_gatts_reg);
+    }
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_GATTS_API_REG *) GKI_getbuf(sizeof(tBTA_GATTS_API_REG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTS_API_REG_EVT;
+
+        if (p_app_uuid != NULL)
+            memcpy(&p_buf->app_uuid, p_app_uuid, sizeof(tBT_UUID));
+        p_buf->p_cback      = p_cback;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppDeregister
+**
+** Description      De-register with GATT Server.
+**
+** Parameters       app_id: applicatino ID.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if)
+{
+    tBTA_GATTS_API_DEREG  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_DEREG *) GKI_getbuf(sizeof(tBTA_GATTS_API_DEREG))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_GATTS_API_DEREG_EVT;
+        p_buf->server_if    = server_if;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CreateService
+**
+** Description      Create a service. When service creation is done, a callback
+**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+**                  and service ID to the profile. The service ID obtained in
+**                  the callback function needs to be used when adding included
+**                  service and characteristics/descriptors into the service.
+**
+** Parameters       app_id: Profile ID this service is belonged to.
+**                  p_service_uuid: service UUID.
+**                  inst: instance ID number of this service.
+**                  num_handle: numble of handle requessted for this service.
+**                  is_primary: is this service a primary one or not.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid, UINT8 inst,
+                             UINT16 num_handle, BOOLEAN is_primary)
+{
+    tBTA_GATTS_API_CREATE_SRVC  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_CREATE_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_CREATE_SRVC))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_CREATE_SRVC_EVT;
+
+        p_buf->server_if = server_if;
+        p_buf->inst = inst;
+        memcpy(&p_buf->service_uuid, p_service_uuid, sizeof(tBT_UUID));
+        p_buf->num_handle = num_handle;
+        p_buf->is_pri = is_primary;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddIncludeService
+**
+** Description      This function is called to add an included service. After included
+**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+**                  is reported the included service ID.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  included_service_id: the service ID to be included.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id)
+{
+    tBTA_GATTS_API_ADD_INCL_SRVC  *p_buf;
+
+    if ((p_buf =
+         (tBTA_GATTS_API_ADD_INCL_SRVC *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_INCL_SRVC)))
+        != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_ADD_INCL_SRVC_EVT;
+
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->included_service_id = included_service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharacteristic
+**
+** Description      This function is called to add a characteristic into a service.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  p_char_uuid : Characteristic UUID.
+**                  perm      : Characteristic value declaration attribute permission.
+**                  property  : Characteristic Properties
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharacteristic (UINT16 service_id,  tBT_UUID  *p_char_uuid,
+                                  tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property)
+{
+    tBTA_GATTS_API_ADD_CHAR  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_ADD_CHAR *) GKI_getbuf(sizeof(tBTA_GATTS_API_ADD_CHAR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_GATTS_API_ADD_CHAR));
+
+        p_buf->hdr.event = BTA_GATTS_API_ADD_CHAR_EVT;
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->perm = perm;
+        p_buf->property = property;
+
+        if (p_char_uuid)
+        {
+            memcpy(&p_buf->char_uuid, p_char_uuid, sizeof(tBT_UUID));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharDescriptor
+**
+** Description      This function is called to add characteristic descriptor. When
+**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+**                  to report the status and an ID number for this descriptor.
+**
+** Parameters       service_id: service ID to which this charatceristic descriptor is to
+**                              be added.
+**                  perm: descriptor access permission.
+**                  p_descr_uuid: descriptor UUID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+                                  tBTA_GATT_PERM perm,
+                                  tBT_UUID  * p_descr_uuid)
+{
+    tBTA_GATTS_API_ADD_DESCR  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_ADD_DESCR);
+
+
+    if ((p_buf = (tBTA_GATTS_API_ADD_DESCR *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTS_API_ADD_DESCR_EVT;
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->perm = perm;
+
+        if (p_descr_uuid)
+        {
+            memcpy(&p_buf->descr_uuid, p_descr_uuid, sizeof(tBT_UUID));
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_DeleteService
+**
+** Description      This function is called to delete a service. When this is done,
+**                  a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters       service_id: service_id to be deleted.
+**
+** Returns          returns none.
+**
+*******************************************************************************/
+void  BTA_GATTS_DeleteService(UINT16 service_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_DEL_SRVC_EVT;
+
+        p_buf->layer_specific = service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StartService
+**
+** Description      This function is called to start a service.
+**
+** Parameters       service_id: the service ID to be started.
+**                  sup_transport: supported trasnport.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void  BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport)
+{
+    tBTA_GATTS_API_START  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_START *) GKI_getbuf(sizeof(tBTA_GATTS_API_START))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_START_SRVC_EVT;
+
+        p_buf->hdr.layer_specific = service_id;
+        p_buf->transport = sup_transport;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StopService
+**
+** Description      This function is called to stop a service.
+**
+** Parameters       service_id - service to be topped.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_StopService(UINT16 service_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_STOP_SRVC_EVT;
+
+        p_buf->layer_specific = service_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_HandleValueIndication
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       bda - remote device bd address to indicate.
+**					attr_id - attribute ID to indicate.
+**                  data_len - indicate data length.
+**                  p_data: data to indicate.
+**                  need_confirm - if this indication expects a confirmation or not.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id, UINT16 data_len,
+                                      UINT8 *p_data, BOOLEAN need_confirm)
+{
+    tBTA_GATTS_API_INDICATION  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_INDICATION);
+
+    if ((p_buf = (tBTA_GATTS_API_INDICATION *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event = BTA_GATTS_API_INDICATION_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->attr_id = attr_id;
+        p_buf->need_confirm = need_confirm;
+
+        if (data_len > 0 && p_data != NULL)
+        {
+            p_buf->len = data_len;
+            memcpy(p_buf->value, p_data, data_len);
+
+        }
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         BTA_GATTS_SendRsp
+**
+** Description      This function is called to send a response to a request.
+**
+** Parameters       conn_id - connection identifier.
+**                  trans_id - transaction ID.
+**                  status - response status
+**                  p_msg - response data.
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+                        tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg)
+{
+    tBTA_GATTS_API_RSP  *p_buf;
+    UINT16  len = sizeof(tBTA_GATTS_API_RSP) + sizeof(tBTA_GATTS_RSP);
+
+    if ((p_buf = (tBTA_GATTS_API_RSP *) GKI_getbuf(len)) != NULL)
+    {
+        memset(p_buf, 0, len);
+
+        p_buf->hdr.event    = BTA_GATTS_API_RSP_EVT;
+        p_buf->hdr.layer_specific = conn_id;
+        p_buf->trans_id = trans_id;
+        p_buf->status = status;
+
+        if (p_msg != NULL)
+        {
+            p_buf->p_rsp = (tBTA_GATTS_RSP *)(p_buf + 1);
+            memcpy(p_buf->p_rsp, p_msg, sizeof(tBTA_GATTS_RSP));
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Open
+**
+** Description      Open a direct open connection or add a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTS_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_OPEN_EVT;
+        p_buf->server_if = server_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct)
+{
+    tBTA_GATTS_API_CANCEL_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_GATTS_API_CANCEL_OPEN *) GKI_getbuf(sizeof(tBTA_GATTS_API_CANCEL_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_GATTS_API_CANCEL_OPEN_EVT;
+        p_buf->server_if = server_if;
+        p_buf->is_direct = is_direct;
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Close
+**
+** Description      Close a connection  a remote device.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTS_Close(UINT16 conn_id)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_GATTS_API_CLOSE_EVT;
+        p_buf->layer_specific = conn_id;
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
new file mode 100644
index 0000000..4810c05
--- /dev/null
+++ b/bta/gatt/bta_gatts_int.h
@@ -0,0 +1,246 @@
+/******************************************************************************
+ *
+ *  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 is the private file for the BTA GATT server.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_INT_H
+#define BTA_GATTS_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "bta_gatt_api.h"
+#include "gatt_api.h"
+//#include "bta_gatts_co.h"
+
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+enum
+{
+    BTA_GATTS_API_REG_EVT  = BTA_SYS_EVT_START(BTA_ID_GATTS),
+    BTA_GATTS_INT_START_IF_EVT,
+    BTA_GATTS_API_DEREG_EVT,
+    BTA_GATTS_API_CREATE_SRVC_EVT,
+    BTA_GATTS_API_INDICATION_EVT,
+
+    BTA_GATTS_API_ADD_INCL_SRVC_EVT,
+    BTA_GATTS_API_ADD_CHAR_EVT,
+    BTA_GATTS_API_ADD_DESCR_EVT,
+    BTA_GATTS_API_DEL_SRVC_EVT,
+    BTA_GATTS_API_START_SRVC_EVT,
+    BTA_GATTS_API_STOP_SRVC_EVT,
+    BTA_GATTS_API_RSP_EVT,
+    BTA_GATTS_API_OPEN_EVT,
+    BTA_GATTS_API_CANCEL_OPEN_EVT,
+    BTA_GATTS_API_CLOSE_EVT
+
+};
+typedef UINT16 tBTA_GATTS_INT_EVT;
+
+/* max number of application allowed on device */
+#define BTA_GATTS_MAX_APP_NUM   GATT_MAX_SR_PROFILES
+
+/* max number of services allowed in the device */
+#define BTA_GATTS_MAX_SRVC_NUM   GATT_MAX_SR_PROFILES
+
+/* internal strucutre for GATTC register API  */
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                app_uuid;
+    tBTA_GATTS_CBACK        *p_cback;
+}tBTA_GATTS_API_REG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTS_IF           server_if;
+}tBTA_GATTS_INT_START_IF;
+
+typedef tBTA_GATTS_INT_START_IF tBTA_GATTS_API_DEREG;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATTS_IF           server_if;
+    tBT_UUID                service_uuid;
+    UINT16                  num_handle;
+    UINT8                   inst;
+    BOOLEAN                 is_pri;
+
+} tBTA_GATTS_API_CREATE_SRVC;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBT_UUID                char_uuid;
+    tBTA_GATT_PERM          perm;
+    tBTA_GATT_CHAR_PROP     property;
+
+}tBTA_GATTS_API_ADD_CHAR;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  included_service_id;
+
+}tBTA_GATTS_API_ADD_INCL_SRVC;
+
+typedef struct
+{
+    BT_HDR                      hdr;
+    tBT_UUID                    descr_uuid;
+    tBTA_GATT_PERM              perm;
+}tBTA_GATTS_API_ADD_DESCR;
+
+typedef struct
+{
+    BT_HDR  hdr;
+    //todo BD_ADDR bd_addr;
+    UINT16  attr_id;
+    UINT16  len;
+    BOOLEAN need_confirm;
+    UINT8   value[BTA_GATT_MAX_ATTR_LEN];
+}tBTA_GATTS_API_INDICATION;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT32              trans_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATTS_RSP      *p_rsp;
+}tBTA_GATTS_API_RSP;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_GATT_TRANSPORT     transport;
+}tBTA_GATTS_API_START;
+
+
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             remote_bda;
+    tBTA_GATTS_IF       server_if;
+    BOOLEAN             is_direct;
+}tBTA_GATTS_API_OPEN;
+
+typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
+
+typedef union
+{
+    BT_HDR                          hdr;
+    tBTA_GATTS_API_REG              api_reg;
+    tBTA_GATTS_API_DEREG            api_dereg;
+    tBTA_GATTS_API_CREATE_SRVC      api_create_svc;
+    tBTA_GATTS_API_ADD_INCL_SRVC    api_add_incl_srvc;
+    tBTA_GATTS_API_ADD_CHAR         api_add_char;
+    tBTA_GATTS_API_ADD_DESCR        api_add_char_descr;
+    tBTA_GATTS_API_START            api_start;
+    tBTA_GATTS_API_INDICATION       api_indicate;
+    tBTA_GATTS_API_RSP              api_rsp;
+    tBTA_GATTS_API_OPEN             api_open;
+    tBTA_GATTS_API_CANCEL_OPEN      api_cancel_open;
+
+    tBTA_GATTS_INT_START_IF         int_start_if;
+} tBTA_GATTS_DATA;
+
+/* application registration control block */
+typedef struct
+{
+    BOOLEAN             in_use;
+    tBT_UUID            app_uuid;
+    tBTA_GATTS_CBACK    *p_cback;
+    tBTA_GATTS_IF        gatt_if;  //todo cahneg to server_if
+}tBTA_GATTS_RCB;
+
+/* service registration control block */
+typedef struct
+{
+    tBT_UUID    service_uuid;   /* service UUID */
+    UINT16      service_id;     /* service handle */
+    UINT8       inst_num;       /* instance ID */
+    UINT8       rcb_idx;
+    UINT8       idx;            /* self index of serviec CB */
+    BOOLEAN     in_use;
+
+}tBTA_GATTS_SRVC_CB;
+
+
+/* GATT server control block */
+typedef struct
+{
+    BOOLEAN             enabled;
+    tBTA_GATTS_RCB      rcb[BTA_GATTS_MAX_APP_NUM];
+    tBTA_GATTS_SRVC_CB  srvc_cb[BTA_GATTS_MAX_SRVC_NUM];
+}tBTA_GATTS_CB;
+
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* GATTC control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTS_CB  bta_gatts_cb;
+#else
+extern tBTA_GATTS_CB *bta_gatts_cb_ptr;
+    #define bta_gatts_cb (*bta_gatts_cb_ptr)
+#endif
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg);
+
+extern void bta_gatts_register(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_start_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_deregister(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA *p_msg);
+extern void bta_gatts_create_srvc(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_include_srvc(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_add_char_descr(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_delete_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_start_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_stop_service(tBTA_GATTS_SRVC_CB *p_srvc_cb, tBTA_GATTS_DATA * p_msg);
+
+extern void bta_gatts_send_rsp(tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_indicate_handle (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+
+extern void bta_gatts_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_cancel_open (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+extern void bta_gatts_close (tBTA_GATTS_CB *p_cb, tBTA_GATTS_DATA * p_msg);
+
+extern BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src);
+extern tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if);
+extern UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id);
+extern tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id);
+
+
+#endif /* BTA_GATTS_INT_H */
+
diff --git a/bta/gatt/bta_gatts_main.c b/bta/gatt/bta_gatts_main.c
new file mode 100644
index 0000000..e2b2494
--- /dev/null
+++ b/bta/gatt/bta_gatts_main.c
@@ -0,0 +1,134 @@
+/******************************************************************************
+ *
+ *  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 the GATT server main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_gatts_int.h"
+#include "gki.h"
+
+/* type for service building action functions */
+typedef void (*tBTA_GATTS_SRVC_ACT)(tBTA_GATTS_SRVC_CB *p_rcb, tBTA_GATTS_DATA *p_data);
+
+/* service building action function list */
+const tBTA_GATTS_SRVC_ACT bta_gatts_srvc_build_act[] =
+{
+    bta_gatts_add_include_srvc,
+    bta_gatts_add_char,
+    bta_gatts_add_char_descr,
+    bta_gatts_delete_service,
+    bta_gatts_start_service,
+    bta_gatts_stop_service,
+};
+
+/* GATTS control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_GATTS_CB  bta_gatts_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gatts_hdl_event
+**
+** Description      BTA GATT server main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_GATTS_CB *p_cb = &bta_gatts_cb;
+    tBTA_GATTS_SRVC_CB *p_srvc_cb = NULL;
+
+    switch (p_msg->event)
+    {
+        case BTA_GATTS_API_REG_EVT:
+            bta_gatts_register(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_INT_START_IF_EVT:
+            bta_gatts_start_if(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_DEREG_EVT:
+            bta_gatts_deregister(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CREATE_SRVC_EVT:
+            bta_gatts_create_srvc(p_cb, (tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_INDICATION_EVT:
+            bta_gatts_indicate_handle(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_OPEN_EVT:
+            bta_gatts_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CANCEL_OPEN_EVT:
+            bta_gatts_cancel_open(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_CLOSE_EVT:
+            bta_gatts_close(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_RSP_EVT:
+            bta_gatts_send_rsp(p_cb,(tBTA_GATTS_DATA *) p_msg);
+            break;
+
+        case BTA_GATTS_API_ADD_INCL_SRVC_EVT:
+        case BTA_GATTS_API_ADD_CHAR_EVT:
+        case BTA_GATTS_API_ADD_DESCR_EVT:
+        case BTA_GATTS_API_DEL_SRVC_EVT:
+        case BTA_GATTS_API_START_SRVC_EVT:
+        case BTA_GATTS_API_STOP_SRVC_EVT:
+
+            p_srvc_cb = bta_gatts_find_srvc_cb_by_srvc_id(p_cb,
+                                ((tBTA_GATTS_DATA *)p_msg)->api_add_incl_srvc.hdr.layer_specific);
+
+            if (p_srvc_cb != NULL)
+            {
+                bta_gatts_srvc_build_act[p_msg->event - BTA_GATTS_API_ADD_INCL_SRVC_EVT](p_srvc_cb, (tBTA_GATTS_DATA *) p_msg);
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("service not created");
+            }
+            break;
+
+        default:
+            break;
+    }
+
+
+    return (TRUE);
+}
+
+#endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_utils.c b/bta/gatt/bta_gatts_utils.c
new file mode 100644
index 0000000..5145c95
--- /dev/null
+++ b/bta/gatt/bta_gatts_utils.c
@@ -0,0 +1,235 @@
+/******************************************************************************
+ *
+ *  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 the GATT client utility function.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <string.h>
+#include "utl.h"
+#include "gki.h"
+#include "bta_sys.h"
+#include "bta_gatts_int.h"
+#include "bd.h"
+
+static const UINT8  base_uuid[LEN_UUID_128] = {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*******************************************************************************
+**
+** Function         bta_gatt_convert_uuid16_to_uuid128
+**
+** Description      Convert a 16 bits UUID to be an standard 128 bits one.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+static void bta_gatt_convert_uuid16_to_uuid128(UINT8 uuid_128[LEN_UUID_128], UINT16 uuid_16)
+{
+    UINT8   *p = &uuid_128[LEN_UUID_128 - 4];
+
+    memcpy (uuid_128, base_uuid, LEN_UUID_128);
+
+    UINT16_TO_STREAM(p, uuid_16);
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_alloc_srvc_cb
+**
+** Description      allocate a service control block.
+**
+** Returns          pointer to the control block, or otherwise NULL when failed.
+**
+*******************************************************************************/
+UINT8 bta_gatts_alloc_srvc_cb(tBTA_GATTS_CB *p_cb, UINT8 rcb_idx)
+{
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+    {
+        if (!p_cb->srvc_cb[i].in_use)
+        {
+            p_cb->srvc_cb[i].in_use = TRUE;
+            p_cb->srvc_cb[i].rcb_idx = rcb_idx;
+            return i;
+        }
+    }
+    return BTA_GATTS_INVALID_APP;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_find_app_rcb_by_app_if
+**
+** Description      find the index of the application control block by app ID.
+**
+** Returns          pointer to the control block if success, otherwise NULL
+**
+*******************************************************************************/
+tBTA_GATTS_RCB *bta_gatts_find_app_rcb_by_app_if(tBTA_GATTS_IF server_if)
+{
+    UINT8 i;
+    tBTA_GATTS_RCB *p_reg;
+
+    for (i = 0, p_reg = bta_gatts_cb.rcb; i < BTA_GATTS_MAX_APP_NUM; i ++, p_reg++)
+    {
+        if (p_reg->in_use && p_reg->gatt_if == server_if)
+            return p_reg;
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gatts_find_app_rcb_idx_by_app_if
+**
+** Description      find the index of the application control block by app ID.
+**
+** Returns          index of the control block, or BTA_GATTS_INVALID_APP if failed.
+**
+*******************************************************************************/
+
+UINT8 bta_gatts_find_app_rcb_idx_by_app_if(tBTA_GATTS_CB *p_cb, tBTA_GATTS_IF server_if)
+{
+    UINT8 i;
+
+    for (i = 0; i < BTA_GATTS_MAX_APP_NUM; i ++)
+    {
+        if (p_cb->rcb[i].in_use && p_cb->rcb[i].gatt_if == server_if)
+            return i;
+    }
+    return BTA_GATTS_INVALID_APP;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_find_srvc_cb_by_srvc_id
+**
+** Description      find the service control block by service ID.
+**
+** Returns          pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_srvc_id(tBTA_GATTS_CB *p_cb, UINT16 service_id)
+{
+    UINT8 i;
+    APPL_TRACE_DEBUG1("bta_gatts_find_srvc_cb_by_srvc_id  service_id=%d", service_id);
+    for (i = 0; i < BTA_GATTS_MAX_SRVC_NUM; i ++)
+    {
+        if (p_cb->srvc_cb[i].in_use &&
+            p_cb->srvc_cb[i].service_id == service_id)
+        {
+            APPL_TRACE_DEBUG1("bta_gatts_find_srvc_cb_by_srvc_id  found service cb index =%d", i);
+            return &p_cb->srvc_cb[i];
+        }
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_find_srvc_cb_by_attr_id
+**
+** Description      find the service control block by attribute ID.
+**
+** Returns          pointer to the rcb.
+**
+*******************************************************************************/
+tBTA_GATTS_SRVC_CB * bta_gatts_find_srvc_cb_by_attr_id(tBTA_GATTS_CB *p_cb, UINT16 attr_id)
+{
+    UINT8 i;
+
+    for (i = 0; i < (BTA_GATTS_MAX_SRVC_NUM); i ++)
+    {
+        if (/* middle service */
+            (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             p_cb->srvc_cb[i].in_use &&
+             p_cb->srvc_cb[i + 1].in_use &&
+             attr_id >= p_cb->srvc_cb[i].service_id &&
+             attr_id < p_cb->srvc_cb[i + 1].service_id) ||
+            /* last active service */
+            (i < (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             p_cb->srvc_cb[i].in_use &&
+             !p_cb->srvc_cb[i + 1].in_use &&
+             attr_id >= p_cb->srvc_cb[i].service_id)    ||
+            /* last service incb */
+            (i == (BTA_GATTS_MAX_SRVC_NUM - 1) &&
+             attr_id >= p_cb->srvc_cb[i].service_id)
+           )
+        {
+            return &p_cb->srvc_cb[i];
+        }
+    }
+    return NULL;
+}
+/*******************************************************************************
+**
+** Function         bta_gatts_uuid_compare
+**
+** Description      Compare two UUID to see if they are the same.
+**
+** Returns          TRUE if two uuid match; FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_uuid_compare(tBT_UUID tar, tBT_UUID src)
+{
+    UINT8  su[LEN_UUID_128], tu[LEN_UUID_128];
+    UINT8  *ps, *pt;
+
+    /* any of the UUID is unspecified */
+    if (src.len == 0 || tar.len == 0)
+    {
+        return TRUE;
+    }
+
+    /* If both are 16-bit, we can do a simple compare */
+    if (src.len == 2 && tar.len == 2)
+    {
+        return src.uu.uuid16 == tar.uu.uuid16;
+    }
+
+    /* One or both of the UUIDs is 128-bit */
+    if (src.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(su, src.uu.uuid16);
+        ps = su;
+    }
+    else
+        ps = src.uu.uuid128;
+
+    if (tar.len == LEN_UUID_16)
+    {
+        /* convert a 16 bits UUID to 128 bits value */
+        bta_gatt_convert_uuid16_to_uuid128(tu, tar.uu.uuid16);
+        pt = tu;
+    }
+    else
+        pt = tar.uu.uuid128;
+
+    return(memcmp(ps, pt, LEN_UUID_128) == 0);
+}
+
+
+
+
+#endif
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
new file mode 100644
index 0000000..de08096
--- /dev/null
+++ b/bta/hh/bta_hh_act.c
@@ -0,0 +1,1197 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 the HID host action functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_sys.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+#include "bta_hh_int.h"
+#include "bta_hh_co.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+/*****************************************************************************
+**  Local Function prototypes
+*****************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, UINT8 event, UINT32 data,
+                          BT_HDR *pdata);
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result);
+
+#if BTA_HH_DEBUG
+static char* bta_hh_get_w4_event(UINT16 event);
+static char * bta_hh_hid_event_name(UINT16 event);
+#endif
+
+/*****************************************************************************
+**  Action Functions
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_hh_api_enable
+**
+** Description      Perform necessary operations to enable HID host.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_enable(tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_STATUS      status = BTA_HH_ERR;
+    UINT8               xx;
+
+    /* initialize BTE HID */
+    HID_HostInit();
+
+    memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+
+    HID_HostSetSecurityLevel("", p_data->api_enable.sec_mask);
+
+    /* Register with L2CAP */
+    if ( HID_HostRegister (bta_hh_cback) == HID_SUCCESS)
+    {
+        /* store parameters */
+        bta_hh_cb.p_cback = p_data->api_enable.p_cback;
+
+        status = BTA_HH_OK;
+        /* initialize device CB */
+        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+        {
+            bta_hh_cb.kdev[xx].state        = BTA_HH_IDLE_ST;
+            bta_hh_cb.kdev[xx].hid_handle   = BTA_HH_INVALID_HANDLE;
+            bta_hh_cb.kdev[xx].index        = xx;
+            /* initialize control block map */
+            bta_hh_cb.cb_index[xx]          = BTA_HH_MAX_KNOWN;
+        }
+    }
+
+    /* signal BTA call back event */
+    (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+}
+/*******************************************************************************
+**
+** Function         bta_hh_api_disable
+**
+** Description      Perform necessary operations to disable HID host.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_disable(void)
+{
+    UINT8 xx;
+
+    /* service is not enabled */
+    if (bta_hh_cb.p_cback == NULL)
+        return;
+
+    /* no live connection, signal DISC_CMPL_EVT directly */
+    if (!bta_hh_cb.cnt_num)
+    {
+        bta_hh_disc_cmpl();
+    }
+    else /* otherwise, disconnect all live connections */
+    {
+        bta_hh_cb.w4_disable = TRUE;
+
+        for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+        {
+            /* send API_CLOSE event to every connected device */
+            if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
+            {
+                /* disconnect all connected devices */
+                bta_hh_sm_execute(&bta_hh_cb.kdev[xx],
+                                BTA_HH_API_CLOSE_EVT,
+                                NULL);
+            }
+        }
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_disc_cmpl
+**
+** Description      All connections have been closed, disable service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_disc_cmpl(void)
+{
+    UINT8   xx;
+    tBTA_HH_STATUS  status = BTA_HH_OK;
+
+    /* Deregister with lower layer */
+    if (HID_HostDeregister()!= HID_SUCCESS)
+        status = BTA_HH_ERR;
+
+    /* free buffer in CB holding report descriptors */
+    for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+    {
+        utl_freebuf((void **)&bta_hh_cb.kdev[xx].dscp_info.descriptor.dsc_list);
+    }
+    utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+    (* bta_hh_cb.p_cback)(BTA_HH_DISABLE_EVT, (tBTA_HH *)&status);
+    /* all connections are down, no waiting for diconnect */
+    memset(&bta_hh_cb, 0, sizeof(tBTA_HH_CB));
+}
+/*******************************************************************************
+**
+** Function         bta_hh_sdp_cback
+**
+** Description      SDP callback function.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_sdp_cback(UINT16 result, UINT16 attr_mask,
+                                  tHID_DEV_SDP_INFO *sdp_rec )
+{
+    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
+    UINT8              hdl;
+    tBTA_HH_STATUS    status = BTA_HH_ERR_SDP;
+
+    if (result == SDP_SUCCESS)
+    {
+        /* security is required for the connection, add attr_mask bit*/
+        if (p_cb->sec_mask)
+            attr_mask |= HID_SEC_REQUIRED;
+
+#if BTA_HH_DEBUG
+        APPL_TRACE_EVENT3("bta_hh_sdp_cback: p_cb: %d result 0x%02x, \
+                            attr_mask 0x%02x", \
+                            p_cb, result, attr_mask);
+#endif
+
+        /* check to see type of device is supported , and should not been added before */
+        if (bta_hh_tod_spt(p_cb, sdp_rec->sub_class))
+        {
+            /* if not added before */
+            if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+            {
+                /*  add device/update attr_mask information */
+                if(HID_HostAddDev (p_cb->addr, attr_mask, &hdl) == HID_SUCCESS)
+                {
+                    status = BTA_HH_OK;
+                    /* update cb_index[] map */
+                    bta_hh_cb.cb_index[hdl] = p_cb->index;
+                }
+                else
+                {
+                    p_cb->app_id = 0;
+                }
+            }
+            /* else : incoming connection after SDP should update the SDP information as well */
+
+            if (p_cb->app_id != 0)
+            {
+                /* update cb information with attr_mask, dscp_info etc. */
+                bta_hh_add_device_to_list(p_cb,  hdl, attr_mask,
+                                            &sdp_rec->dscp_info,
+                                            sdp_rec->sub_class,
+                                            sdp_rec->ssr_max_latency,
+                                            sdp_rec->ssr_min_tout,
+                                            p_cb->app_id);
+
+                p_cb->dscp_info.ctry_code = sdp_rec->ctry_code;
+
+                status = BTA_HH_OK;
+            }
+
+        }
+        else /* type of device is not supported */
+            status = BTA_HH_ERR_TOD_UNSPT;
+    }
+
+    /* free disc_db when SDP is completed */
+    utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+
+
+    /* send SDP_CMPL_EVT into state machine */
+    bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_di_sdp_cback
+**
+** Description      SDP DI callback function.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_di_sdp_cback(UINT16 result)
+{
+    tBTA_HH_DEV_CB     *p_cb = bta_hh_cb.p_cur;
+    tBTA_HH_STATUS         status = BTA_HH_ERR_SDP;
+    tSDP_DI_GET_RECORD  di_rec;
+    tHID_STATUS ret;
+#if BTA_HH_DEBUG
+    APPL_TRACE_EVENT2("bta_hh_di_sdp_cback: p_cb: %d result 0x%02x", p_cb, result);
+#endif
+    /* if DI record does not exist on remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be
+         * set to 0xffff and we will allow the connection to go through. Spec mandates that DI
+         * record be set, but many HID devices do not set this. So for IOP purposes, we allow the
+         * connection to go through and update the DI record to invalid DI entry.*/
+    if ((result == SDP_SUCCESS) || (result == SDP_NO_RECS_MATCH))
+    {
+        if(result == SDP_SUCCESS && SDP_GetNumDiRecords(bta_hh_cb.p_disc_db) != 0)
+        {
+            /* always update information with primary DI record */
+            if (SDP_GetDiRecord(1, &di_rec, bta_hh_cb.p_disc_db) == SDP_SUCCESS)
+            {
+                bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version);
+            }
+
+        }
+        else /* no DI recrod available */
+        {
+            bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0);
+        }
+
+        if ((ret = HID_HostGetSDPRecord(p_cb->addr,
+                                 bta_hh_cb.p_disc_db,
+                                 p_bta_hh_cfg->sdp_db_size,
+                                 bta_hh_sdp_cback)) == HID_SUCCESS)
+        {
+            status = BTA_HH_OK;
+        }
+        else
+        {
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG1 ("bta_hh_di_sdp_cback:  HID_HostGetSDPRecord failed: Status 0x%2x",
+                               ret);
+#endif
+        }
+    }
+
+
+    if (status != BTA_HH_OK)
+    {
+        utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+        /* send SDP_CMPL_EVT into state machine */
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+    }
+    return;
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_start_sdp
+**
+** Description      Start SDP service search, and obtain necessary SDP records.
+**                  Only one SDP service search request is allowed at the same
+**                  time. For every BTA_HhOpen API call, do SDP first unless SDP
+**                  has been done previously.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_STATUS          status = BTA_HH_ERR_SDP;
+    UINT8                   hdl;
+
+    p_cb->sec_mask  = p_data->api_conn.sec_mask;
+    p_cb->mode      = p_data->api_conn.mode;
+
+    /* if previously virtually cabled device, skip SDP */
+    if (p_cb->app_id)
+    {
+        status = BTA_HH_OK;
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG0("bta_hh_start_sdp:: skip SDP for known devices");
+#endif
+        if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+        {
+            if ((HID_HostAddDev (p_cb->addr, p_cb->attr_mask, &hdl)) \
+                == HID_SUCCESS)
+            {
+                /* update device CB with newly register device handle */
+                bta_hh_add_device_to_list(p_cb,  hdl, p_cb->attr_mask, NULL,
+                                          p_cb->sub_class,
+                                          p_cb->dscp_info.ssr_max_latency,
+                                          p_cb->dscp_info.ssr_min_tout,
+                                          p_cb->app_id);
+                /* update cb_index[] map */
+                bta_hh_cb.cb_index[hdl] = p_cb->index;
+            }
+            else
+            {
+                status = BTA_HH_ERR_SDP;
+            }
+        }
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+        return;
+    }
+    /* GetSDPRecord. at one time only one SDP precedure can be active */
+    else if (!bta_hh_cb.p_disc_db)
+    {
+        bta_hh_cb.p_disc_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(p_bta_hh_cfg->sdp_db_size);
+
+        if (bta_hh_cb.p_disc_db == NULL)
+        {
+            status = BTA_HH_ERR_NO_RES;
+        }
+        else
+        {
+            bta_hh_cb.p_cur = p_cb;
+            /* do DI discovery first */
+            if (SDP_DiDiscover(p_data->api_conn.bd_addr,
+                                         bta_hh_cb.p_disc_db,
+                                         p_bta_hh_cfg->sdp_db_size,
+                                         bta_hh_di_sdp_cback) != SDP_SUCCESS)
+            {
+#if BTA_HH_DEBUG
+                APPL_TRACE_DEBUG1 ("bta_hh_start_sdp:  SDP_DiDiscover failed: \
+                    Status 0x%2X",status);
+#endif
+                status = BTA_HH_ERR_SDP;
+                utl_freebuf((void **)&bta_hh_cb.p_disc_db);
+            }
+            else
+                status = BTA_HH_OK;
+        }
+    }
+
+    if (status != BTA_HH_OK)
+        bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
+
+    return;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_sdp_cmpl
+**
+** Description      When SDP completed, initiate a connection or report error depend
+**                  on SDP result.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat;
+    tBTA_HH_STATUS          status = p_data->status;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG1 ("bta_hh_sdp_cmpl:  status 0x%2X",p_data->status);
+#endif
+
+    /* initialize call back data */
+    memset((void *)&conn_dat, 0, sizeof(tBTA_HH_CONN));
+    conn_dat.handle = p_cb->hid_handle;
+    bdcpy(conn_dat.bda, p_cb->addr);
+
+    /* if SDP compl success */
+    if ( status == BTA_HH_OK)
+    {
+        /* not incoming connection doing SDP, initiate a HID connection */
+        if (!p_cb->incoming_conn)
+        {
+            tHID_STATUS ret;
+            /* set security level */
+            HID_HostSetSecurityLevel("", p_cb->sec_mask);
+
+            /* open HID connection */
+            if ((ret = HID_HostOpenDev (p_cb->hid_handle)) != HID_SUCCESS)
+            {
+#if BTA_HH_DEBUG
+                APPL_TRACE_DEBUG1 ("bta_hh_sdp_cmpl:  HID_HostOpenDev failed: \
+                    Status 0x%2X",ret);
+#endif
+                /* open fail, remove device from management device list */
+                HID_HostRemoveDev( p_cb->hid_handle);
+                status = BTA_HH_ERR;
+            }
+            else
+            {
+                status = BTA_HH_OK;
+            }
+        }
+        else /* incoming connection SDP finish */
+        {
+            bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, NULL);
+        }
+    }
+
+    if (status != BTA_HH_OK)
+    {
+        conn_dat.status = status;
+
+        (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+        /* move state machine W4_CONN ->IDLE */
+        bta_hh_sm_execute(p_cb, BTA_HH_API_CLOSE_EVT, NULL);
+
+        /* if this is an outgoing connection to an unknown device, clean up cb */
+        if (p_cb->app_id == 0 && !p_cb->incoming_conn)
+        {
+            /* clean up device control block */
+            bta_hh_clean_up_kdev(p_cb);
+        }
+
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_api_disc_act
+**
+** Description      HID Host initiate a disconnection.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CBDATA    disc_dat;
+    tHID_STATUS     status;
+
+    /* found an active connection */
+    disc_dat.handle = p_data ?(UINT8)p_data->hdr.layer_specific :p_cb->hid_handle;
+    disc_dat.status = BTA_HH_ERR;
+
+    status = HID_HostCloseDev(disc_dat.handle);
+
+    if (status)
+        (* bta_hh_cb.p_cback)(BTA_HH_CLOSE_EVT, (tBTA_HH *)&disc_dat);
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_open_cmpl_act
+**
+** Description      HID host connection completed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN        conn ;
+    UINT8   dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+                        p_cb->hid_handle;
+
+    memset((void *)&conn, 0, sizeof (tBTA_HH_CONN));
+    conn.handle = dev_handle;
+    bdcpy(conn.bda, p_cb->addr);
+
+    /* increase connection number */
+    bta_hh_cb.cnt_num ++;
+
+    /* initialize device driver */
+    bta_hh_co_open(p_cb->hid_handle, p_cb->sub_class,
+                   p_cb->attr_mask,  p_cb->app_id);
+
+    /* update SSR settings */
+    bta_sys_chg_ssr_config(BTA_ID_HH ,p_cb->app_id, p_cb->dscp_info.ssr_max_latency, p_cb->dscp_info.ssr_min_tout);
+    /* inform role manager */
+    bta_sys_conn_open( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+
+    /* set protocol mode when not default report mode */
+    if (p_cb->mode != BTA_HH_PROTO_RPT_MODE)
+    {
+        if ((HID_HostWriteDev(dev_handle,
+                              HID_TRANS_SET_PROTOCOL, HID_PAR_PROTOCOL_BOOT_MODE,
+                              0,
+                              0, NULL)) != HID_SUCCESS)
+        {
+            /* HID connection is up, while SET_PROTO fail */
+            conn.status = BTA_HH_ERR_PROTO;
+            (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+        }
+        else
+        {
+            conn.status = BTA_HH_OK;
+            p_cb->w4_evt = BTA_HH_OPEN_EVT;
+        }
+    }
+    else
+        (* bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn);
+
+    p_cb->incoming_conn = FALSE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_open_act
+**
+** Description      HID host receive HID_OPEN_EVT .
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_API_CONN    conn_data;
+
+#if BTA_HH_DEBUG
+    UINT8   dev_handle = p_data ? (UINT8)p_data->hid_cback.hdr.layer_specific : \
+                        p_cb->hid_handle;
+
+    APPL_TRACE_EVENT1 ("bta_hh_open_act:  Device[%d] connected", dev_handle);
+#endif
+
+    /* SDP has been done */
+    if (p_cb->app_id != 0)
+    {
+        bta_hh_sm_execute(p_cb, BTA_HH_OPEN_CMPL_EVT, p_data);
+    }
+    else
+    /*  app_id == 0 indicates an incoming conenction request arrives without SDP
+        performed, do it first */
+    {
+        p_cb->incoming_conn = TRUE;
+
+        memset(&conn_data, 0, sizeof(tBTA_HH_API_CONN));
+        bdcpy(conn_data.bd_addr, p_cb->addr);
+        bta_hh_start_sdp(p_cb, (tBTA_HH_DATA *)&conn_data);
+    }
+
+    return;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_data_act
+**
+** Description      HID Host process a data report
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    BT_HDR  *pdata = p_data->hid_cback.p_data;
+    UINT8   *p_rpt = (UINT8 *)(pdata + 1) + pdata->offset;
+
+    bta_hh_co_data((UINT8)p_data->hid_cback.hdr.layer_specific, p_rpt, pdata->len,
+                    p_cb->mode, p_cb->sub_class, p_cb->dscp_info.ctry_code, p_cb->addr, p_cb->app_id);
+
+    utl_freebuf((void **)&pdata);
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_handsk_act
+**
+** Description      HID Host process a handshake acknoledgement.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    tBTA_HH_CBDATA  cback_data ;
+    tBTA_HH_HSDATA  hs_data;
+    tBTA_HH_CONN    conn ;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG2("HANDSHAKE received for: event = %s data= %d",
+        bta_hh_get_w4_event(p_cb->w4_evt), p_data->hid_cback.data);
+#endif
+
+    memset(&hs_data, 0, sizeof(tBTA_HH_HSDATA));
+
+    switch (p_cb->w4_evt)
+    {
+        /* GET_ transsaction, handshake indicate unsupported request */
+        case BTA_HH_GET_PROTO_EVT:
+            hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
+            /* fall through */
+        case BTA_HH_GET_RPT_EVT:
+        case BTA_HH_GET_IDLE_EVT :
+            hs_data.handle = p_cb->hid_handle;
+            /* if handshake gives an OK code for these transaction, fill in UNSUPT */
+            if ((hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data)) == BTA_HH_OK)
+                 hs_data.status = BTA_HH_HS_TRANS_NOT_SPT;
+
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+            p_cb->w4_evt = 0;
+            break;
+
+        /* acknoledgement from HID device for SET_ transaction */
+        case BTA_HH_SET_RPT_EVT:
+        case BTA_HH_SET_PROTO_EVT:
+        case BTA_HH_SET_IDLE_EVT :
+            cback_data.handle  = p_cb->hid_handle;
+            cback_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&cback_data);
+            p_cb->w4_evt = 0;
+            break;
+
+        /* SET_PROTOCOL when open connection */
+        case BTA_HH_OPEN_EVT:
+            conn.status =p_data->hid_cback.data ? BTA_HH_ERR_PROTO: BTA_HH_OK;
+            conn.handle = p_cb->hid_handle;
+            bdcpy(conn.bda, p_cb->addr);
+            (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&conn);
+#if BTA_HH_DEBUG
+            bta_hh_trace_dev_db();
+#endif
+            p_cb->w4_evt = 0;
+            break;
+
+        default:
+            /* unknow transaction handshake response */
+            APPL_TRACE_DEBUG0("unknown transaction type");
+            break;
+    }
+
+    /* transaction achknoledgement received, inform PM for mode change */
+    bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_ctrl_dat_act
+**
+** Description      HID Host process a data report from control channel.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data)
+{
+    BT_HDR          *pdata = p_data->hid_cback.p_data;
+    UINT8           *data = (UINT8 *)(pdata + 1) + pdata->offset;
+    tBTA_HH_HSDATA    hs_data;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG1("Ctrl DATA received w4: event[%s]",
+                        bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+    hs_data.status  = BTA_HH_OK;
+    hs_data.handle  = p_cb->hid_handle;
+
+    switch (p_cb->w4_evt)
+    {
+    case BTA_HH_GET_IDLE_EVT:
+        hs_data.rsp_data.idle_rate = *data;
+        break;
+    case BTA_HH_GET_RPT_EVT:
+        hs_data.rsp_data.p_rpt_data = pdata;
+        break;
+    case BTA_HH_GET_PROTO_EVT:
+        /* match up BTE/BTA report/boot mode def*/
+        hs_data.rsp_data.proto_mode = ((*data) == HID_PAR_PROTOCOL_REPORT)? \
+                    BTA_HH_PROTO_RPT_MODE : BTA_HH_PROTO_BOOT_MODE;
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG1("GET_PROTOCOL Mode = [%s]",
+            (hs_data.rsp_data.proto_mode == BTA_HH_PROTO_RPT_MODE)? "Report" : "Boot");
+#endif
+        break;
+    /* should not expect control DATA for SET_ transaction */
+    case BTA_HH_SET_PROTO_EVT:
+        /* fall through */
+    case BTA_HH_SET_RPT_EVT:
+        /* fall through */
+    case BTA_HH_SET_IDLE_EVT :
+        /* fall through */
+    default:
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG1("invalid  transaction type for DATA payload: 4_evt[%s]",
+                        bta_hh_get_w4_event(p_cb->w4_evt));
+#endif
+        break;
+    }
+
+    /* inform PM for mode change */
+    bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+    bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+
+    (* bta_hh_cb.p_cback)(p_cb->w4_evt, (tBTA_HH *)&hs_data);
+
+    p_cb->w4_evt = 0;
+    utl_freebuf((void **)&pdata);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_close_act
+**
+** Description      HID Host process a close event
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_close_act (tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CONN            conn_dat ;
+    tBTA_HH_CBDATA          disc_dat = {BTA_HH_OK, 0};
+    UINT32                  reason = p_data->hid_cback.data;    /* Reason for closing (32-bit) */
+
+    /* if HID_HDEV_EVT_VC_UNPLUG was received, report BTA_HH_VC_UNPLUG_EVT */
+    UINT16     event = p_cb->vp ? BTA_HH_VC_UNPLUG_EVT : BTA_HH_CLOSE_EVT;
+
+    disc_dat.handle = p_cb->hid_handle;
+    disc_dat.status = p_data->hid_cback.data;
+
+    /* Check reason for closing */
+    if ((reason & (HID_L2CAP_CONN_FAIL|HID_L2CAP_REQ_FAIL)) ||  /* Failure to initialize connection (page timeout or l2cap error) */
+        (reason == HID_ERR_AUTH_FAILED) ||                      /* Authenication error (while initiating) */
+        (reason == HID_ERR_L2CAP_FAILED))                       /* Failure creating l2cap connection */
+    {
+        /* Failure in opening connection */
+        conn_dat.handle = p_cb->hid_handle;
+        conn_dat.status = (reason == HID_ERR_AUTH_FAILED) ? BTA_HH_ERR_AUTH_FAILED : BTA_HH_ERR;
+        bdcpy(conn_dat.bda, p_cb->addr);
+        HID_HostCloseDev(p_cb->hid_handle);
+
+        /* Report OPEN fail event */
+        (*bta_hh_cb.p_cback)(BTA_HH_OPEN_EVT, (tBTA_HH *)&conn_dat);
+
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+        return;
+    }
+    /* otherwise report CLOSE/VC_UNPLUG event */
+    else
+    {
+        /* finaliza device driver */
+        bta_hh_co_close(p_cb->hid_handle, p_cb->app_id);
+        /* inform role manager */
+        bta_sys_conn_close( BTA_ID_HH ,p_cb->app_id, p_cb->addr);
+        /* update total conn number */
+        bta_hh_cb.cnt_num --;
+
+        if (disc_dat.status)
+            disc_dat.status = BTA_HH_ERR;
+
+        (*bta_hh_cb.p_cback)(event, (tBTA_HH *)&disc_dat);
+
+        /* if virtually unplug, remove device */
+        if (p_cb->vp )
+        {
+            HID_HostRemoveDev( p_cb->hid_handle);
+            bta_hh_clean_up_kdev(p_cb);
+        }
+
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+    }
+
+    /* clean up control block, but retain SDP info and device handle */
+    p_cb->vp            = FALSE;
+    p_cb->w4_evt        = 0;
+
+    /* if no connection is active and HH disable is signaled, disable service */
+    if (bta_hh_cb.cnt_num == 0 && bta_hh_cb.w4_disable)
+    {
+        bta_hh_disc_cmpl();
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_get_dscp_act
+**
+** Description      Get device report descriptor
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    (*bta_hh_cb.p_cback)(BTA_HH_GET_DSCP_EVT, (tBTA_HH *)&p_cb->dscp_info);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_maint_dev_act
+**
+** Description      HID Host maintain device list.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_MAINT_DEV       *p_dev_info = &p_data->api_maintdev;
+    tBTA_HH_DEV_INFO        dev_info ;
+    UINT8                   dev_handle;
+
+    dev_info.status = BTA_HH_ERR;
+    dev_info.handle = BTA_HH_INVALID_HANDLE;
+
+    switch (p_dev_info->sub_event)
+    {
+    case BTA_HH_ADD_DEV_EVT:    /* add a device */
+        bdcpy(dev_info.bda, p_dev_info->bda);
+        /* initialize callback data */
+        if (p_cb->hid_handle == BTA_HH_INVALID_HANDLE)
+        {
+            if (HID_HostAddDev(p_dev_info->bda, p_dev_info->attr_mask, &dev_handle)\
+                            == HID_SUCCESS)
+            {
+                dev_info.handle   = dev_handle;
+                dev_info.status   = BTA_HH_OK;
+
+                /* update DI information */
+                bta_hh_update_di_info(p_cb,
+                                      p_dev_info->dscp_info.vendor_id,
+                                      p_dev_info->dscp_info.product_id,
+                                      p_dev_info->dscp_info.version);
+
+                /* add to BTA device list */
+                bta_hh_add_device_to_list(p_cb, dev_handle,
+                                          p_dev_info->attr_mask,
+                                          &p_dev_info->dscp_info.descriptor,
+                                          p_dev_info->sub_class,
+                                          p_dev_info->dscp_info.ssr_max_latency,
+                                          p_dev_info->dscp_info.ssr_min_tout,
+                                          p_dev_info->app_id);
+                /* update cb_index[] map */
+                bta_hh_cb.cb_index[dev_handle] = p_cb->index;
+            }
+        }
+        else    /* device already been added */
+        {
+            dev_info.handle = p_cb->hid_handle;
+            dev_info.status = BTA_HH_OK;
+        }
+#if BTA_HH_DEBUG
+        bta_hh_trace_dev_db();
+#endif
+        break;
+
+    case BTA_HH_RMV_DEV_EVT:    /* remove device */
+        dev_info.handle = (UINT8)p_dev_info->hdr.layer_specific;
+
+        bdcpy(dev_info.bda, p_cb->addr);
+        if (p_cb->state != BTA_HH_CONN_ST )
+        {
+            if(HID_HostRemoveDev( dev_info.handle ) == HID_SUCCESS)
+            {
+                dev_info.status  = BTA_HH_OK;
+
+                /* remove from known device list in BTA */
+                bta_hh_clean_up_kdev(p_cb);
+            }
+        }
+        break;
+
+    default:
+        APPL_TRACE_DEBUG0("invalid command");
+        break;
+    }
+
+    (* bta_hh_cb.p_cback)(p_dev_info->sub_event, (tBTA_HH *)&dev_info);
+}
+/*******************************************************************************
+**
+** Function         bta_hh_write_dev_act
+**
+** Description      Write device action. can be SET/GET/DATA transaction.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data)
+{
+    tBTA_HH_CBDATA     cbdata = {BTA_HH_OK, 0};
+    UINT16  event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+                        BTA_HH_FST_TRANS_CB_EVT;
+
+    cbdata.handle = p_cb->hid_handle;
+
+    /* match up BTE/BTA report/boot mode def */
+    if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL)
+    {
+        p_data->api_sndcmd.param = ( p_data->api_sndcmd.param == BTA_HH_PROTO_RPT_MODE) ?\
+                        HID_PAR_PROTOCOL_REPORT :HID_PAR_PROTOCOL_BOOT_MODE;
+    }
+
+    if (HID_HostWriteDev (p_cb->hid_handle,
+                       p_data->api_sndcmd.t_type,
+                       p_data->api_sndcmd.param,
+                       p_data->api_sndcmd.data,
+                       p_data->api_sndcmd.rpt_id,
+                       p_data->api_sndcmd.p_data) != HID_SUCCESS)
+    {
+        APPL_TRACE_ERROR0("HID_HostWriteDev Error ");
+        cbdata.status = BTA_HH_ERR;
+
+        if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL &&
+            p_data->api_sndcmd.t_type != HID_TRANS_DATA)
+            (* bta_hh_cb.p_cback)(event, (tBTA_HH *)&cbdata);
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+            (* bta_hh_cb.p_cback)(BTA_HH_VC_UNPLUG_EVT, (tBTA_HH *)&cbdata);
+    }
+    else
+    {
+
+        switch(p_data->api_sndcmd.t_type)
+        {
+        case HID_TRANS_SET_PROTOCOL:
+            /* fall through */
+        case HID_TRANS_GET_REPORT:
+            /* fall through */
+        case HID_TRANS_SET_REPORT:
+            /* fall through */
+        case HID_TRANS_GET_PROTOCOL:
+            /* fall through */
+        case HID_TRANS_GET_IDLE:
+            /* fall through */
+        case HID_TRANS_SET_IDLE:/* set w4_handsk event name for callback function use */
+            p_cb->w4_evt = event;
+            break;
+        case HID_TRANS_DATA:  /* output report */
+            /* fall through */
+        case HID_TRANS_CONTROL:
+            /* no handshake event will be generated */
+            /* if VC_UNPLUG is issued, set flag */
+            if (p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+                p_cb->vp = TRUE;
+
+            break;
+        /* currently not expected */
+        case HID_TRANS_DATAC:
+        default:
+            APPL_TRACE_DEBUG1("bta_hh_write_dev_act:: cmd type = %d",
+                            p_data->api_sndcmd.t_type);
+            break;
+        }
+
+        /* if not control type transaction, notify PM for energy control */
+        if (p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+        {
+            /* inform PM for mode change */
+            bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+            bta_sys_idle(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_SUSPEND)
+        {
+			bta_sys_sco_close(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+        else if (p_data->api_sndcmd.param == BTA_HH_CTRL_EXIT_SUSPEND)
+        {
+            bta_sys_busy(BTA_ID_HH, p_cb->app_id, p_cb->addr);
+        }
+    }
+
+
+    return;
+}
+
+/*****************************************************************************
+**  Static Function
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_hh_cback
+**
+** Description      BTA HH callback function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hh_cback (UINT8 dev_handle, UINT8 event, UINT32 data,
+                          BT_HDR *pdata)
+{
+    tBTA_HH_CBACK_DATA    *p_buf = NULL;
+    UINT16  sm_event = BTA_HH_INVALID_EVT;
+    UINT8   xx = 0;
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG1("bta_hh_cback::HID_event [%s]", bta_hh_hid_event_name(event));
+#endif
+
+    switch (event)
+    {
+    case HID_HDEV_EVT_OPEN:
+        sm_event = BTA_HH_INT_OPEN_EVT;
+        break;
+    case HID_HDEV_EVT_CLOSE:
+        sm_event = BTA_HH_INT_CLOSE_EVT;
+        break;
+    case HID_HDEV_EVT_INTR_DATA:
+        sm_event = BTA_HH_INT_DATA_EVT;
+        break;
+    case HID_HDEV_EVT_HANDSHAKE:
+        sm_event = BTA_HH_INT_HANDSK_EVT;
+        break;
+    case HID_HDEV_EVT_CTRL_DATA:
+        sm_event = BTA_HH_INT_CTRL_DATA;
+        break;
+    case HID_HDEV_EVT_RETRYING:
+        break;
+    case HID_HDEV_EVT_INTR_DATC:
+    case HID_HDEV_EVT_CTRL_DATC:
+        /* Unhandled events: Free buffer for DATAC */
+        utl_freebuf((void **)&pdata);
+        break;
+    case HID_HDEV_EVT_VC_UNPLUG:
+        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+        {
+            if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
+            {
+               bta_hh_cb.kdev[xx].vp = TRUE;
+               break;
+            }
+        }
+        break;
+    }
+
+    if (sm_event != BTA_HH_INVALID_EVT &&
+        (p_buf = (tBTA_HH_CBACK_DATA *)GKI_getbuf(sizeof(tBTA_HH_CBACK_DATA) +
+                    sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->hdr.event  = sm_event;
+        p_buf->hdr.layer_specific = (UINT16)dev_handle;
+        p_buf->data       = data;
+        p_buf->p_data     = pdata;
+
+        bta_sys_sendmsg(p_buf);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_get_trans_status
+**
+** Description      translate a handshake result code into BTA HH
+**                  status code
+**
+*******************************************************************************/
+static tBTA_HH_STATUS bta_hh_get_trans_status(UINT32 result)
+{
+    switch(result)
+    {
+    case HID_PAR_HANDSHAKE_RSP_SUCCESS :                /*   (0) */
+        return BTA_HH_OK;
+    case HID_PAR_HANDSHAKE_RSP_NOT_READY :              /*   (1) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_REP_ID:      /*   (2) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_UNSUPPORTED_REQ :    /*   (3) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_INVALID_PARAM :      /*   (4) */
+        return (tBTA_HH_STATUS)result;
+    case HID_PAR_HANDSHAKE_RSP_ERR_UNKNOWN :            /*   (14) */
+    case HID_PAR_HANDSHAKE_RSP_ERR_FATAL  :             /*   (15) */
+    default:
+        return BTA_HH_HS_ERROR;
+        break;
+    }
+}
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+
+#if (defined BTA_HH_DEBUG && BTA_HH_DEBUG == TRUE)
+static char* bta_hh_get_w4_event(UINT16 event)
+{
+    switch (event)
+    {
+    case BTA_HH_GET_RPT_EVT:
+        return "BTA_HH_GET_RPT_EVT";
+    case BTA_HH_SET_RPT_EVT:
+        return "BTA_HH_SET_RPT_EVT";
+    case BTA_HH_GET_PROTO_EVT:
+        return "BTA_HH_GET_PROTO_EVT";
+    case BTA_HH_SET_PROTO_EVT:
+        return "BTA_HH_SET_PROTO_EVT";
+    case BTA_HH_GET_IDLE_EVT:
+        return "BTA_HH_GET_IDLE_EVT";
+    case BTA_HH_SET_IDLE_EVT:
+        return "BTA_HH_SET_IDLE_EVT";
+    case BTA_HH_OPEN_EVT:
+        return "BTA_HH_OPEN_EVT";
+    default:
+        return "Unknown event";
+    }
+
+}
+
+static char * bta_hh_hid_event_name(UINT16 event)
+{
+    switch (event)
+    {
+    case HID_HDEV_EVT_OPEN:
+        return "HID_HDEV_EVT_OPEN";
+    case HID_HDEV_EVT_CLOSE:
+        return "HID_HDEV_EVT_CLOSE";
+    case HID_HDEV_EVT_RETRYING:
+        return "HID_HDEV_EVT_RETRYING";
+    case HID_HDEV_EVT_INTR_DATA:
+        return "HID_HDEV_EVT_INTR_DATA";
+    case HID_HDEV_EVT_INTR_DATC:
+        return "HID_HDEV_EVT_INTR_DATC";
+    case HID_HDEV_EVT_CTRL_DATA:
+        return "HID_HDEV_EVT_CTRL_DATA";
+    case HID_HDEV_EVT_CTRL_DATC:
+        return "HID_HDEV_EVT_CTRL_DATC";
+    case HID_HDEV_EVT_HANDSHAKE:
+        return "HID_HDEV_EVT_HANDSHAKE";
+    case HID_HDEV_EVT_VC_UNPLUG:
+        return "HID_HDEV_EVT_VC_UNPLUG";
+    default:
+        return "Unknown HID event";
+    }
+}
+#endif
+#endif /* BTA_HH_INCLUDED */
+
diff --git a/bta/hh/bta_hh_api.c b/bta/hh/bta_hh_api.c
new file mode 100644
index 0000000..300fc6f
--- /dev/null
+++ b/bta/hh/bta_hh_api.c
@@ -0,0 +1,447 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 the HID HOST API in the subsystem of BTA.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hh_reg =
+{
+    bta_hh_hdl_event,
+    BTA_HhDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_HhEnable
+**
+** Description      Enable the HID host.  This function must be called before
+**                  any other functions in the HID host API are called. When the
+**                  enable operation is complete the callback function will be
+**                  called with BTA_HH_ENABLE_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
+{
+    tBTA_HH_API_ENABLE *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_HH, &bta_hh_reg);
+    GKI_sched_unlock();
+
+    APPL_TRACE_ERROR0("Calling BTA_HhEnable");
+    p_buf = (tBTA_HH_API_ENABLE *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_ENABLE));
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_API_ENABLE));
+
+        p_buf->hdr.event = BTA_HH_API_ENABLE_EVT;
+        p_buf->p_cback = p_cback;
+        p_buf->sec_mask = sec_mask;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhDisable
+**
+** Description      Disable the HID host. If the server is currently
+**                  connected, the connection will be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    bta_sys_deregister(BTA_ID_HH);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_HH_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhClose
+**
+** Description      Disconnect a connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhClose(UINT8 dev_handle)
+{
+    BT_HDR    *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(BT_HDR));
+        p_buf->event            = BTA_HH_API_CLOSE_EVT;
+        p_buf->layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhOpen
+**
+** Description      Connect to a device of specified BD address in specified
+**                  protocol mode and security level.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhOpen(BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode, tBTA_SEC sec_mask)
+{
+    tBTA_HH_API_CONN *p_buf;
+
+    p_buf = (tBTA_HH_API_CONN *)GKI_getbuf((UINT16)sizeof(tBTA_HH_API_CONN));
+
+    if (p_buf!= NULL)
+    {
+        memset((void *)p_buf, 0, sizeof(tBTA_HH_API_CONN));
+
+        p_buf->hdr.event            = BTA_HH_API_OPEN_EVT;
+        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
+        p_buf->sec_mask             = sec_mask;
+        p_buf->mode                 = mode;
+        bdcpy(p_buf->bd_addr, dev_bda);
+
+        bta_sys_sendmsg((void *)p_buf);
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("No resource to send HID host Connect request.");
+    }
+}
+
+/*******************************************************************************
+**
+** Function  bta_hh_snd_write_dev
+**
+*******************************************************************************/
+static void bta_hh_snd_write_dev(UINT8 dev_handle, UINT8 t_type, UINT8 param,
+                                 UINT16 data, UINT8 rpt_id, BT_HDR  *p_data)
+{
+    tBTA_HH_CMD_DATA *p_buf;
+    UINT16          len = (UINT16) (sizeof(tBTA_HH_CMD_DATA) );
+
+    if ((p_buf = (tBTA_HH_CMD_DATA *)GKI_getbuf(len))!= NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_CMD_DATA));
+
+        p_buf->hdr.event = BTA_HH_API_WRITE_DEV_EVT;
+        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
+        p_buf->t_type   = t_type;
+        p_buf->data     = data;
+        p_buf->param    = param;
+        p_buf->p_data   = p_data;
+        p_buf->rpt_id   = rpt_id;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetReport
+**
+** Description      send SET_REPORT to device.
+**
+** Parameter        dev_handle: device handle
+**                  r_type:     report type, could be BTA_HH_RPTT_OUTPUT or
+**                              BTA_HH_RPTT_FEATURE.
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, BT_HDR *p_data)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhGetReport
+**
+** Description      Send a GET_REPORT to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type, UINT8 rpt_id, UINT16 buf_size)
+{
+    UINT8 param = (buf_size) ? (r_type | 0x08) : r_type;
+
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_REPORT, param,
+                        buf_size, rpt_id, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetProtoMode
+**
+** Description      This function set the protocol mode at specified HID handle
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetProtoMode(UINT8 dev_handle, tBTA_HH_PROTO_MODE p_type)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_PROTOCOL, (UINT8)p_type,
+                        0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhGetProtoMode
+**
+** Description      This function get protocol mode information.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetProtoMode(UINT8 dev_handle)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_PROTOCOL, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSetIdle
+**
+** Description      send SET_IDLE to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_IDLE, 0, idle_rate, 0, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetIdle
+**
+** Description      Send a GET_IDLE from HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetIdle(UINT8 dev_handle)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_GET_IDLE, 0, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSendCtrl
+**
+** Description      Send a control command to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSendCtrl(UINT8 dev_handle, tBTA_HH_TRANS_CTRL_TYPE c_type)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_CONTROL, (UINT8)c_type, 0, 0, NULL);
+}
+/*******************************************************************************
+**
+** Function         BTA_HhSendData
+**
+** Description      This function send DATA transaction to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR  *p_data)
+{
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, BTA_HH_RPTT_OUTPUT, 0, 0, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetDscpInfo
+**
+** Description      Get HID device report descriptor
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhGetDscpInfo(UINT8 dev_handle)
+{
+    BT_HDR    *p_buf;
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf((UINT16)sizeof(BT_HDR))) != NULL)
+    {
+        memset(p_buf, 0, sizeof(BT_HDR));
+        p_buf->event            = BTA_HH_API_GET_DSCP_EVT;
+        p_buf->layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HhAddDev
+**
+** Description      Add a virtually cabled device into HID-Host device list
+**                  to manage and assign a device handle for future API call,
+**                  host applciation call this API at start-up to initialize its
+**                  virtually cabled devices.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask, UINT8 sub_class,
+                  UINT8 app_id, tBTA_HH_DEV_DSCP_INFO dscp_info)
+{
+    tBTA_HH_MAINT_DEV    *p_buf;
+    UINT16  len = sizeof(tBTA_HH_MAINT_DEV) + dscp_info.descriptor.dl_len;
+
+    p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf(len);
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+        p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
+        p_buf->sub_event            = BTA_HH_ADD_DEV_EVT;
+        p_buf->hdr.layer_specific   = BTA_HH_INVALID_HANDLE;
+
+        p_buf->attr_mask            = (UINT16) attr_mask;
+        p_buf->sub_class            = sub_class;
+        p_buf->app_id               = app_id;
+        bdcpy(p_buf->bda, bda);
+
+        memcpy(&p_buf->dscp_info, &dscp_info, sizeof(tBTA_HH_DEV_DSCP_INFO));
+        if ( dscp_info.descriptor.dl_len != 0 && dscp_info.descriptor.dsc_list)
+        {
+            p_buf->dscp_info.descriptor.dl_len =  dscp_info.descriptor.dl_len;
+            p_buf->dscp_info.descriptor.dsc_list = (UINT8 *)(p_buf + 1);
+            memcpy(p_buf->dscp_info.descriptor.dsc_list, dscp_info.descriptor.dsc_list, dscp_info.descriptor.dl_len);
+        }
+        else
+        {
+            p_buf->dscp_info.descriptor.dsc_list = NULL;
+            p_buf->dscp_info.descriptor.dl_len = 0;
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_HhRemoveDev
+**
+** Description      Remove a device from the HID host devices list.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhRemoveDev(UINT8 dev_handle )
+{
+    tBTA_HH_MAINT_DEV    *p_buf;
+
+    p_buf = (tBTA_HH_MAINT_DEV *)GKI_getbuf((UINT16)sizeof(tBTA_HH_MAINT_DEV));
+
+    if (p_buf != NULL)
+    {
+        memset(p_buf, 0, sizeof(tBTA_HH_MAINT_DEV));
+
+        p_buf->hdr.event            = BTA_HH_API_MAINT_DEV_EVT;
+        p_buf->sub_event            = BTA_HH_RMV_DEV_EVT;
+        p_buf->hdr.layer_specific   = (UINT16) dev_handle;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************/
+/*                          Utility Function                                   */
+/*******************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_HhParseBootRpt
+**
+** Description      This utility function parse a boot mode report.
+**                  For keyboard report, report data will carry the keycode max
+**                  up to 6 key press in one report. Application need to convert
+**                  the keycode into keypress character according to keyboard
+**                  language.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+                        UINT16 report_len)
+{
+    p_data->dev_type = BTA_HH_DEVT_UNKNOWN;
+
+    if (p_report)
+    {
+        /* first byte is report ID */
+        switch (p_report[0])
+        {
+        case BTA_HH_KEYBD_RPT_ID: /* key board report ID */
+            p_data->dev_type = p_report[0];
+            bta_hh_parse_keybd_rpt(p_data, p_report + 1, (UINT16)(report_len -1));
+            break;
+
+        case BTA_HH_MOUSE_RPT_ID: /* mouse report ID */
+            p_data->dev_type = p_report[0];
+            bta_hh_parse_mice_rpt(p_data, p_report + 1, (UINT16)(report_len - 1));
+            break;
+
+        default:
+            APPL_TRACE_DEBUG1("Unknown boot report: %d", p_report[0]);;
+            break;
+        }
+    }
+
+    return;
+}
+
+#endif /* BTA_HH_INCLUDED */
diff --git a/bta/hh/bta_hh_cfg.c b/bta/hh/bta_hh_cfg.c
new file mode 100644
index 0000000..62a07ad
--- /dev/null
+++ b/bta/hh/bta_hh_cfg.c
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 compile-time configurable constants for the BTA Hid
+ *  Host.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "bta_hh_api.h"
+
+/* max number of device types supported by BTA */
+#define BTA_HH_MAX_DEVT_SPT         7
+
+/* size of database for service discovery */
+#ifndef BTA_HH_DISC_BUF_SIZE
+#define BTA_HH_DISC_BUF_SIZE        GKI_MAX_BUF_SIZE
+#endif
+
+/* application ID(none-zero) for each type of device */
+#define BTA_HH_APP_ID_MI            1
+#define BTA_HH_APP_ID_KB            2
+#define BTA_HH_APP_ID_RMC           3
+#define BTA_HH_APP_ID_3DSG          4
+
+
+/* The type of devices supported by BTA HH and corresponding application ID */
+tBTA_HH_SPT_TOD p_devt_list[BTA_HH_MAX_DEVT_SPT] =
+{
+    {BTA_HH_DEVT_MIC, BTA_HH_APP_ID_MI},
+    {BTA_HH_DEVT_KBD, BTA_HH_APP_ID_KB},
+    {BTA_HH_DEVT_KBD|BTA_HH_DEVT_MIC, BTA_HH_APP_ID_KB},
+    {BTA_HH_DEVT_RMC, BTA_HH_APP_ID_RMC},
+    {BTA_HH_DEVT_RMC | BTA_HH_DEVT_KBD, BTA_HH_APP_ID_RMC},
+    {BTA_HH_DEVT_MIC | BTA_HH_DEVT_DGT, BTA_HH_APP_ID_MI},
+    {BTA_HH_DEVT_UNKNOWN, BTA_HH_APP_ID_3DSG}
+};
+
+
+const tBTA_HH_CFG bta_hh_cfg =
+{
+    BTA_HH_MAX_DEVT_SPT,            /* number of supported type of devices */
+    p_devt_list,                    /* ToD & AppID list */
+    BTA_HH_DISC_BUF_SIZE            /* HH SDP discovery database size */
+};
+
+
+tBTA_HH_CFG *p_bta_hh_cfg = (tBTA_HH_CFG *)&bta_hh_cfg;
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
new file mode 100644
index 0000000..f3a8e54
--- /dev/null
+++ b/bta/hh/bta_hh_int.h
@@ -0,0 +1,248 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 BTA HID Host internal definitions
+ *
+ ******************************************************************************/
+
+#ifndef BTA_HH_INT_H
+#define BTA_HH_INT_H
+
+#include "bta_sys.h"
+#include "bd.h"
+#include "utl.h"
+#include "bta_hh_api.h"
+
+/* can be moved to bta_api.h */
+#define BTA_HH_MAX_RPT_CHARS    8
+
+
+/* state machine events, these events are handled by the state machine */
+enum
+{
+    BTA_HH_API_OPEN_EVT     = BTA_SYS_EVT_START(BTA_ID_HH),
+    BTA_HH_API_CLOSE_EVT,
+    BTA_HH_INT_OPEN_EVT,
+    BTA_HH_INT_CLOSE_EVT,
+    BTA_HH_INT_DATA_EVT,
+    BTA_HH_INT_CTRL_DATA,
+    BTA_HH_INT_HANDSK_EVT,
+    BTA_HH_SDP_CMPL_EVT,
+    BTA_HH_API_WRITE_DEV_EVT,
+    BTA_HH_API_GET_DSCP_EVT,
+    BTA_HH_API_MAINT_DEV_EVT,
+    BTA_HH_OPEN_CMPL_EVT,
+
+    /* not handled by execute state machine */
+    BTA_HH_API_ENABLE_EVT,
+    BTA_HH_API_DISABLE_EVT,
+    BTA_HH_DISC_CMPL_EVT
+};
+typedef UINT16 tBTA_HH_INT_EVT;         /* HID host internal events */
+
+#define BTA_HH_INVALID_EVT      (BTA_HH_DISC_CMPL_EVT + 1)
+
+/* event used to map between BTE event and BTA event */
+#define BTA_HH_FST_TRANS_CB_EVT         BTA_HH_GET_RPT_EVT
+#define BTA_HH_FST_BTE_TRANS_EVT        HID_TRANS_GET_REPORT
+
+/* sub event code used for device maintainence API call */
+#define BTA_HH_ADD_DEV          0
+#define BTA_HH_REMOVE_DEV       1
+
+/* state machine states */
+enum
+{
+    BTA_HH_NULL_ST,
+    BTA_HH_IDLE_ST,
+    BTA_HH_W4_CONN_ST,
+    BTA_HH_CONN_ST
+};
+typedef UINT8 tBTA_HH_STATE;
+
+/* data structure used to send a command/data to HID device */
+typedef struct
+{
+    BT_HDR           hdr;
+    UINT8            t_type;
+    UINT8            param;
+    UINT8            rpt_id;
+    UINT16           data;
+    BT_HDR           *p_data;
+}tBTA_HH_CMD_DATA;
+
+/* data type for BTA_HH_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               sec_mask;
+    UINT8               service_name[BTA_SERVICE_NAME_LEN+1];
+    tBTA_HH_CBACK   *p_cback;
+} tBTA_HH_API_ENABLE;
+
+typedef struct
+{
+    BT_HDR          hdr;
+    BD_ADDR         bd_addr;
+    UINT8           sec_mask;
+    tBTA_HH_PROTO_MODE  mode;
+}tBTA_HH_API_CONN;
+
+/* internal event data from BTE HID callback */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT32          data;
+    BT_HDR          *p_data;
+}tBTA_HH_CBACK_DATA;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    BD_ADDR             bda;
+    UINT16              attr_mask;
+    UINT16              sub_event;
+    UINT8               sub_class;
+    UINT8               app_id;
+    tBTA_HH_DEV_DSCP_INFO      dscp_info;
+}tBTA_HH_MAINT_DEV;
+
+/* union of all event data types */
+typedef union
+{
+    BT_HDR                   hdr;
+    tBTA_HH_API_ENABLE       api_enable;
+    tBTA_HH_API_CONN         api_conn;
+    tBTA_HH_CMD_DATA         api_sndcmd;
+    tBTA_HH_CBACK_DATA       hid_cback;
+    tBTA_HH_STATUS           status;
+    tBTA_HH_MAINT_DEV        api_maintdev;
+} tBTA_HH_DATA;
+
+/* device control block */
+typedef struct
+{
+    tBTA_HH_DEV_DSCP_INFO  dscp_info;      /* report descriptor and DI information */
+    BD_ADDR             addr;           /* BD-Addr of the HID device */
+    UINT16              attr_mask;      /* attribute mask */
+    UINT16              w4_evt;         /* W4_handshake event name */
+    UINT8               index;          /* index number referenced to handle index */
+    UINT8               sub_class;      /* Cod sub class */
+    UINT8               sec_mask;       /* security mask */
+    UINT8               app_id;         /* application ID for this connection */
+    UINT8               hid_handle;     /* device handle */
+    BOOLEAN             vp;             /* virtually unplug flag */
+    BOOLEAN             in_use;         /* control block currently in use */
+    BOOLEAN             incoming_conn;  /* is incoming connection? */
+    BOOLEAN             opened;         /* TRUE if device successfully opened HID connection */
+    tBTA_HH_PROTO_MODE  mode;           /* protocol mode */
+    tBTA_HH_STATE       state;          /* CB state */
+} tBTA_HH_DEV_CB;
+
+/* key board parsing control block */
+typedef struct
+{
+    BOOLEAN             mod_key[4]; /* ctrl, shift(upper), Alt, GUI */
+    BOOLEAN             num_lock;
+    BOOLEAN             caps_lock;
+    UINT8               last_report[BTA_HH_MAX_RPT_CHARS];
+} tBTA_HH_KB_CB;
+
+/******************************************************************************
+** Main Control Block
+*******************************************************************************/
+typedef struct
+{
+    tBTA_HH_KB_CB           kb_cb;                  /* key board control block,
+                                                       suppose BTA will connect
+                                                       to only one keyboard at
+                                                        the same time */
+    tBTA_HH_DEV_CB          kdev[BTA_HH_MAX_KNOWN]; /* device control block */
+    tBTA_HH_DEV_CB*         p_cur;              /* current device control
+                                                       block idx, used in sdp */
+    UINT8                   cb_index[BTA_HH_MAX_KNOWN]; /* maintain a CB index
+                                                        map to dev handle */
+    tBTA_HH_CBACK       *p_cback;               /* Application callbacks */
+    tSDP_DISCOVERY_DB*      p_disc_db;
+    UINT8                   trace_level;            /* tracing level */
+    UINT8                   cnt_num;                /* connected device number */
+    BOOLEAN                 w4_disable;             /* w4 disable flag */
+}
+tBTA_HH_CB;
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HH_CB  bta_hh_cb;
+#else
+extern tBTA_HH_CB *bta_hh_cb_ptr;
+#define bta_hh_cb (*bta_hh_cb_ptr)
+#endif
+
+/* from bta_hh_cfg.c */
+extern tBTA_HH_CFG *p_bta_hh_cfg;
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg);
+extern void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event,
+                              tBTA_HH_DATA *p_data);
+
+/* action functions */
+extern void bta_hh_api_disc_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_close_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_data_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_ctrl_dat_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA * p_data);
+extern void bta_hh_start_sdp(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_sdp_cmpl(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_write_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_get_dscp_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_handsk_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_maint_dev_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+extern void bta_hh_open_cmpl_act(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* utility functions */
+extern UINT8  bta_hh_find_cb(BD_ADDR bda);
+extern void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+             UINT8 *p_report, UINT16 report_len);
+extern void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_kb_data,
+                                  UINT8 *p_report, UINT16 report_len);
+extern BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class);
+extern void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb);
+
+extern void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+                                      UINT16 attr_mask,
+                                      tHID_DEV_DSCP_INFO *p_dscp_info,
+                                      UINT8 sub_class, UINT16 max_latency, UINT16 min_tout, UINT8 app_id);
+extern void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+                           UINT16 version);
+
+/* action functions used outside state machine */
+extern void bta_hh_api_enable(tBTA_HH_DATA *p_data);
+extern void bta_hh_api_disable(void);
+extern void bta_hh_disc_cmpl(void);
+
+
+#if BTA_HH_DEBUG
+extern void bta_hh_trace_dev_db(void);
+#endif
+
+#endif
+
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
new file mode 100644
index 0000000..a1d0ad2
--- /dev/null
+++ b/bta/hh/bta_hh_main.c
@@ -0,0 +1,441 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 the HID host main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "bta_hh_api.h"
+#include "bta_hh_int.h"
+#include "gki.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_HH_API_DISC_ACT,        /* HID host process API close action    */
+    BTA_HH_OPEN_ACT,            /* HID host process BTA_HH_EVT_OPEN     */
+    BTA_HH_CLOSE_ACT,           /* HID host process BTA_HH_EVT_CLOSE    */
+    BTA_HH_DATA_ACT,            /* HID host receive data report         */
+    BTA_HH_CTRL_DAT_ACT,
+    BTA_HH_HANDSK_ACT,
+    BTA_HH_START_SDP,           /* HID host inquery                     */
+    BTA_HH_SDP_CMPL,
+    BTA_HH_WRITE_DEV_ACT,
+    BTA_HH_GET_DSCP_ACT,
+    BTA_HH_MAINT_DEV_ACT,
+    BTA_HH_OPEN_CMPL_ACT,
+    BTA_HH_NUM_ACTIONS
+};
+
+#define BTA_HH_IGNORE       BTA_HH_NUM_ACTIONS
+
+/* type for action functions */
+typedef void (*tBTA_HH_ACTION)(tBTA_HH_DEV_CB *p_cb, tBTA_HH_DATA *p_data);
+
+/* action functions */
+const tBTA_HH_ACTION bta_hh_action[] =
+{
+    bta_hh_api_disc_act,
+    bta_hh_open_act,
+    bta_hh_close_act,
+    bta_hh_data_act,
+    bta_hh_ctrl_dat_act,
+    bta_hh_handsk_act,
+    bta_hh_start_sdp,
+    bta_hh_sdp_cmpl,
+    bta_hh_write_dev_act,
+    bta_hh_get_dscp_act,
+    bta_hh_maint_dev_act,
+    bta_hh_open_cmpl_act
+};
+
+/* state table information */
+#define BTA_HH_ACTION                   0       /* position of action */
+#define BTA_HH_NEXT_STATE               1       /* position of next state */
+#define BTA_HH_NUM_COLS                 2       /* number of columns */
+
+/* state table for idle state */
+const UINT8 bta_hh_st_idle[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                    Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_START_SDP,     BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
+/* BTA_HH_OPEN_CMPL_EVT        */    {BTA_HH_IGNORE,         BTA_HH_IDLE_ST    }
+
+};
+
+
+const UINT8 bta_hh_st_w4_conn[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                 Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_IGNORE,        BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_SDP_CMPL,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_IGNORE  ,      BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_IGNORE,        BTA_HH_W4_CONN_ST },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_IDLE_ST    },
+/* BTA_HH_OPEN_CMPL_EVT        */    {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
+};
+
+
+const UINT8 bta_hh_st_connected[][BTA_HH_NUM_COLS] =
+{
+/* Event                          Action                 Next state */
+/* BTA_HH_API_OPEN_EVT      */    {BTA_HH_IGNORE,        BTA_HH_CONN_ST    },
+/* BTA_HH_API_CLOSE_EVT     */    {BTA_HH_API_DISC_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_INT_OPEN_EVT      */    {BTA_HH_OPEN_ACT,      BTA_HH_CONN_ST    },
+/* BTA_HH_INT_CLOSE_EVT     */    {BTA_HH_CLOSE_ACT,     BTA_HH_IDLE_ST    },
+/* BTA_HH_INT_DATA_EVT      */    {BTA_HH_DATA_ACT,      BTA_HH_CONN_ST    },
+/* BTA_HH_INT_CTRL_DATA     */    {BTA_HH_CTRL_DAT_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_INT_HANDSK_EVT    */    {BTA_HH_HANDSK_ACT,    BTA_HH_CONN_ST    },
+/* BTA_HH_SDP_CMPL_EVT      */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST       },
+/* BTA_HH_API_WRITE_DEV_EVT */    {BTA_HH_WRITE_DEV_ACT, BTA_HH_CONN_ST    },
+/* BTA_HH_API_GET_DSCP_EVT  */    {BTA_HH_GET_DSCP_ACT,  BTA_HH_CONN_ST    },
+/* BTA_HH_API_MAINT_DEV_EVT */    {BTA_HH_MAINT_DEV_ACT, BTA_HH_CONN_ST    },
+/* BTA_HH_OPEN_CMPL_EVT        */    {BTA_HH_IGNORE,         BTA_HH_CONN_ST    }
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HH_ST_TBL)[BTA_HH_NUM_COLS];
+
+/* state table */
+const tBTA_HH_ST_TBL bta_hh_st_tbl[] =
+{
+    bta_hh_st_idle,
+    bta_hh_st_w4_conn,
+    bta_hh_st_connected
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HH_CB  bta_hh_cb;
+#endif
+/*****************************************************************************
+** Static functions
+*****************************************************************************/
+#if BTA_HH_DEBUG == TRUE
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code);
+static char *bta_hh_state_code(tBTA_HH_STATE state_code);
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_hh_sm_execute
+**
+** Description      State machine event handling function for HID Host
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_sm_execute(tBTA_HH_DEV_CB *p_cb, UINT16 event, tBTA_HH_DATA * p_data)
+{
+    tBTA_HH_ST_TBL  state_table;
+    UINT8           action;
+    tBTA_HH         cback_data;
+    tBTA_HH_EVT     cback_event = 0;
+#if BTA_HH_DEBUG == TRUE
+    tBTA_HH_STATE   in_state ;
+    UINT16          debug_event = event;
+#endif
+
+    memset(&cback_data, 0, sizeof(tBTA_HH));
+
+    /* handle exception, no valid control block was found */
+    if (!p_cb)
+    {
+        /* BTA HH enabled already? otherwise ignore the event although it's bad*/
+        if (bta_hh_cb.p_cback != NULL)
+        {
+            switch (event)
+            {
+            /* no control block available for new connection */
+            case BTA_HH_API_OPEN_EVT:
+                cback_event = BTA_HH_OPEN_EVT;
+                /* build cback data */
+                bdcpy(cback_data.conn.bda, ((tBTA_HH_API_CONN *)p_data)->bd_addr);
+                cback_data.conn.status  = BTA_HH_ERR_DB_FULL;
+                cback_data.conn.handle  = BTA_HH_INVALID_HANDLE;
+                break;
+            /* DB full, BTA_HhAddDev */
+            case BTA_HH_API_MAINT_DEV_EVT:
+                cback_event = p_data->api_maintdev.sub_event;
+
+                if (p_data->api_maintdev.sub_event == BTA_HH_ADD_DEV_EVT)
+                {
+                    bdcpy(cback_data.dev_info.bda, p_data->api_maintdev.bda);
+                    cback_data.dev_info.status    = BTA_HH_ERR_DB_FULL;
+                    cback_data.dev_info.handle    = BTA_HH_INVALID_HANDLE;
+                }
+                else
+                {
+                    cback_data.dev_info.status    = BTA_HH_ERR_HDL;
+                    cback_data.dev_info.handle    = (UINT8)p_data->api_maintdev.hdr.layer_specific;
+                }
+                break;
+            case BTA_HH_API_WRITE_DEV_EVT:
+                cback_event = (p_data->api_sndcmd.t_type - BTA_HH_FST_BTE_TRANS_EVT) +
+                        BTA_HH_FST_TRANS_CB_EVT;
+                if (p_data->api_sndcmd.t_type == HID_TRANS_SET_PROTOCOL ||
+                    p_data->api_sndcmd.t_type == HID_TRANS_SET_REPORT ||
+                    p_data->api_sndcmd.t_type == HID_TRANS_SET_IDLE)
+                {
+                    cback_data.dev_status.status = BTA_HH_ERR_HDL;
+                    cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                }
+                else if (p_data->api_sndcmd.t_type != HID_TRANS_DATA &&
+                    p_data->api_sndcmd.t_type != HID_TRANS_CONTROL)
+                {
+                    cback_data.hs_data.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                    cback_data.hs_data.status = BTA_HH_ERR_HDL;
+                    /* hs_data.rsp_data will be all zero, which is not valid value */
+                }
+                break;
+
+            case BTA_HH_API_CLOSE_EVT:
+                cback_event = BTA_HH_CLOSE_EVT;
+
+                cback_data.dev_status.status = BTA_HH_ERR_HDL;
+                cback_data.dev_status.handle = (UINT8)p_data->api_sndcmd.hdr.layer_specific;
+                break;
+
+            default:
+                /* invalid handle, call bad API event */
+                APPL_TRACE_ERROR1("wrong device handle: [%d]", p_data->hdr.layer_specific);
+                break;
+            }
+           if (cback_event)
+               (* bta_hh_cb.p_cback)(cback_event, &cback_data);
+        }
+    }
+    /* corresponding CB is found, go to state machine */
+    else
+    {
+#if BTA_HH_DEBUG == TRUE
+        in_state = p_cb->state;
+        APPL_TRACE_EVENT3("bta_hh_sm_execute: State 0x%02x [%s], Event [%s]",
+                          in_state, bta_hh_state_code(in_state),
+                          bta_hh_evt_code(debug_event));
+#endif
+
+        state_table = bta_hh_st_tbl[p_cb->state - 1];
+
+        event &= 0xff;
+
+        p_cb->state = state_table[event][BTA_HH_NEXT_STATE] ;
+
+        if ((action = state_table[event][BTA_HH_ACTION]) != BTA_HH_IGNORE)
+        {
+            (*bta_hh_action[action])(p_cb, p_data);
+        }
+
+#if BTA_HH_DEBUG == TRUE
+        if (in_state != p_cb->state)
+        {
+            APPL_TRACE_DEBUG3("HH State Change: [%s] -> [%s] after Event [%s]",
+                          bta_hh_state_code(in_state),
+                          bta_hh_state_code(p_cb->state),
+                          bta_hh_evt_code(debug_event));
+        }
+#endif
+    }
+
+    return;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_hdl_event
+**
+** Description      HID host main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
+{
+    UINT8           index = BTA_HH_MAX_KNOWN;
+    tBTA_HH_DEV_CB *p_cb = NULL;
+
+    switch (p_msg->event)
+    {
+        case BTA_HH_API_ENABLE_EVT:
+            bta_hh_api_enable((tBTA_HH_DATA *) p_msg);
+            break;
+
+        case BTA_HH_API_DISABLE_EVT:
+            bta_hh_api_disable();
+            break;
+
+        case BTA_HH_DISC_CMPL_EVT:          /* disable complete */
+            bta_hh_disc_cmpl();
+            break;
+
+        default:
+            /* all events processed in state machine need to find corresponding
+                CB before proceed */
+            if (p_msg->event == BTA_HH_API_OPEN_EVT)
+            {
+                index = bta_hh_find_cb(((tBTA_HH_API_CONN *)p_msg)->bd_addr);
+            }
+            else if (p_msg->event == BTA_HH_API_MAINT_DEV_EVT)
+            {
+                /* if add device */
+                if (((tBTA_HH_MAINT_DEV *)p_msg)->sub_event == BTA_HH_ADD_DEV_EVT)
+                {
+                    index = bta_hh_find_cb(((tBTA_HH_MAINT_DEV *)p_msg)->bda);
+                }
+                else /* else remove device by handle */
+                {
+                    index = bta_hh_cb.cb_index[p_msg->layer_specific];
+// btla-specific ++
+                    /* If BT disable is done while the HID device is connected and Link_Key uses unauthenticated combination
+                      * then we can get into a situation where remove_bonding is called with the index set to 0 (without getting
+                      * cleaned up). Only when VIRTUAL_UNPLUG is called do we cleanup the index and make it MAX_KNOWN.
+                      * So if REMOVE_DEVICE is called and in_use is FALSE then we should treat this as a NULL p_cb. Hence we
+                      * force the index to be MAX_KNOWN
+                      */
+                    if (bta_hh_cb.kdev[index].in_use == FALSE) {
+                           index = BTA_HH_MAX_KNOWN;
+                    }
+// btla-specific --
+                }
+            }
+            else if (p_msg->layer_specific < BTA_HH_MAX_KNOWN )
+                index = bta_hh_cb.cb_index[p_msg->layer_specific];
+
+            if (index != BTA_HH_MAX_KNOWN)
+                p_cb = &bta_hh_cb.kdev[index];
+
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG2("bta_hh_hdl_event:: handle = %d dev_cb[%d] ", p_msg->layer_specific, index);
+#endif
+            bta_hh_sm_execute(p_cb, p_msg->event, (tBTA_HH_DATA *) p_msg);
+    }
+    return (TRUE);
+}
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function         bta_hh_evt_code
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *bta_hh_evt_code(tBTA_HH_INT_EVT evt_code)
+{
+  switch(evt_code)
+    {
+    case BTA_HH_API_DISABLE_EVT:
+        return "BTA_HH_API_DISABLE_EVT";
+    case BTA_HH_API_ENABLE_EVT:
+        return "BTA_HH_API_ENABLE_EVT";
+    case BTA_HH_API_OPEN_EVT:
+        return "BTA_HH_API_OPEN_EVT";
+    case BTA_HH_API_CLOSE_EVT:
+        return "BTA_HH_API_CLOSE_EVT";
+    case BTA_HH_INT_OPEN_EVT:
+        return "BTA_HH_INT_OPEN_EVT";
+    case BTA_HH_INT_CLOSE_EVT:
+        return "BTA_HH_INT_CLOSE_EVT";
+    case BTA_HH_INT_HANDSK_EVT:
+        return "BTA_HH_INT_HANDSK_EVT";
+    case BTA_HH_INT_DATA_EVT:
+        return "BTA_HH_INT_DATA_EVT";
+    case BTA_HH_INT_CTRL_DATA:
+        return "BTA_HH_INT_CTRL_DATA";
+    case BTA_HH_API_WRITE_DEV_EVT:
+        return "BTA_HH_API_WRITE_DEV_EVT";
+    case BTA_HH_SDP_CMPL_EVT:
+        return "BTA_HH_SDP_CMPL_EVT";
+    case BTA_HH_DISC_CMPL_EVT:
+        return "BTA_HH_DISC_CMPL_EVT";
+    case BTA_HH_API_MAINT_DEV_EVT:
+        return "BTA_HH_API_MAINT_DEV_EVT";
+    case BTA_HH_API_GET_DSCP_EVT:
+        return "BTA_HH_API_GET_DSCP_EVT";
+    case BTA_HH_OPEN_CMPL_EVT:
+        return "BTA_HH_OPEN_CMPL_EVT";
+    default:
+        return "unknown HID Host event code";
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_state_code
+**
+** Description      get string representation of HID host state code.
+**
+** Returns          void
+**
+*******************************************************************************/
+static char *bta_hh_state_code(tBTA_HH_STATE state_code)
+{
+    switch (state_code)
+    {
+    case BTA_HH_NULL_ST:
+        return"BTA_HH_NULL_ST";
+    case BTA_HH_IDLE_ST:
+        return "BTA_HH_IDLE_ST";
+    case BTA_HH_W4_CONN_ST:
+        return "BTA_HH_W4_CONN_ST";
+    case BTA_HH_CONN_ST:
+        return "BTA_HH_CONN_ST";
+    default:
+        return "unknown HID Host state";
+    }
+}
+
+#endif  /* Debug Functions */
+
+#endif /* BTA_HH_INCLUDED */
diff --git a/bta/hh/bta_hh_utils.c b/bta/hh/bta_hh_utils.c
new file mode 100644
index 0000000..4349282
--- /dev/null
+++ b/bta/hh/bta_hh_utils.c
@@ -0,0 +1,417 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(BTA_HH_INCLUDED) && (BTA_HH_INCLUDED == TRUE)
+
+
+#include "bta_hh_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+#define BTA_HH_KB_CTRL_MASK         0x11
+#define BTA_HH_KB_SHIFT_MASK        0x22
+#define BTA_HH_KB_ALT_MASK          0x44
+#define BTA_HH_KB_GUI_MASK          0x88
+
+#define BTA_HH_KB_CAPS_LOCK      0x39           /* caps lock */
+#define BTA_HH_KB_NUM_LOCK       0x53           /* num lock */
+
+
+#define BTA_HH_MAX_RPT_CHARS    8
+
+static const UINT8 bta_hh_mod_key_mask[BTA_HH_MOD_MAX_KEY] =
+{
+    BTA_HH_KB_CTRL_MASK,
+    BTA_HH_KB_SHIFT_MASK,
+    BTA_HH_KB_ALT_MASK,
+    BTA_HH_KB_GUI_MASK
+};
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_find_cb
+**
+** Description      Find best available control block according to BD address.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+UINT8  bta_hh_find_cb(BD_ADDR bda)
+{
+    UINT8 xx;
+
+    /* See how many active devices there are. */
+    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    {
+        /* check if any active/known devices is a match */
+        if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
+              bdcmp(bda, bd_addr_null) != 0) )
+        {
+#if BTA_HH_DEBUG
+            APPL_TRACE_DEBUG2("found kdev_cb[%d] hid_handle = %d ", xx,
+                                bta_hh_cb.kdev[xx].hid_handle)
+#endif
+            return xx;
+        }
+#if BTA_HH_DEBUG
+        else
+            APPL_TRACE_DEBUG4("in_use ? [%d] kdev[%d].hid_handle = %d state = [%d]",
+                            bta_hh_cb.kdev[xx].in_use, xx,
+                            bta_hh_cb.kdev[xx].hid_handle,
+                            bta_hh_cb.kdev[xx].state);
+#endif
+    }
+
+    /* if no active device match, find a spot for it */
+    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    {
+        if (!bta_hh_cb.kdev[xx].in_use)
+        {
+            bdcpy(bta_hh_cb.kdev[xx].addr, bda);
+            break;
+        }
+    }
+    /* If device list full, report BTA_HH_MAX_KNOWN */
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d",
+                        xx, BTA_HH_MAX_KNOWN);
+#endif
+
+    return xx;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_clean_up_kdev
+**
+** Description      Clean up device control block when device is removed from
+**                  manitainace list, and update control block index map.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_clean_up_kdev(tBTA_HH_DEV_CB *p_cb)
+{
+    UINT8 index;
+
+    if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
+        bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_MAX_KNOWN;
+
+    /* reset device control block */
+    index = p_cb->index;                        /* Preserve index for this control block */
+
+    /* Free buffer for report descriptor info */
+    utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+    memset(p_cb, 0, sizeof (tBTA_HH_DEV_CB));   /* Reset control block */
+
+    p_cb->index = index;                        /* Restore index for this control block */
+    p_cb->state      = BTA_HH_IDLE_ST;
+    p_cb->hid_handle = BTA_HH_INVALID_HANDLE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_hh_update_di_info
+**
+** Description      Maintain a known device list for BTA HH.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
+                           UINT16 version)
+{
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
+                        vendor_id, product_id, version);
+#endif
+    p_cb->dscp_info.vendor_id     =   vendor_id;
+    p_cb->dscp_info.product_id    =   product_id;
+    p_cb->dscp_info.version       =   version;
+}
+/*******************************************************************************
+**
+** Function         bta_hh_add_device_to_list
+**
+** Description      Maintain a known device list for BTA HH.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_add_device_to_list(tBTA_HH_DEV_CB *p_cb, UINT8 handle,
+                               UINT16 attr_mask,
+                               tHID_DEV_DSCP_INFO *p_dscp_info,
+                               UINT8 sub_class,
+                               UINT16 ssr_max_latency,
+                               UINT16 ssr_min_tout,
+                               UINT8 app_id)
+{
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG1("subclass = 0x%2x", sub_class);
+#endif
+
+    p_cb->hid_handle = handle;
+    p_cb->in_use = TRUE;
+    p_cb->attr_mask = attr_mask;
+
+    p_cb->sub_class = sub_class;
+    p_cb->app_id    = app_id;
+
+    if (ssr_max_latency == HID_SSR_PARAM_INVALID)
+        p_cb->dscp_info.ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+    else
+        p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+
+    if (ssr_min_tout == HID_SSR_PARAM_INVALID)
+        p_cb->dscp_info.ssr_min_tout = BTA_HH_SSR_MIN_TOUT_DEF;
+    else
+        p_cb->dscp_info.ssr_min_tout = ssr_min_tout;
+
+    /* store report descriptor info */
+    if ( p_dscp_info)
+    {
+        utl_freebuf((void **)&p_cb->dscp_info.descriptor.dsc_list);
+
+        if (p_dscp_info->dl_len &&
+        (p_cb->dscp_info.descriptor.dsc_list =
+            (UINT8 *)GKI_getbuf(p_dscp_info->dl_len)) != NULL)
+        {
+            p_cb->dscp_info.descriptor.dl_len = p_dscp_info->dl_len;
+            memcpy(p_cb->dscp_info.descriptor.dsc_list, p_dscp_info->dsc_list,
+                    p_dscp_info->dl_len);
+        }
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_tod_spt
+**
+** Description      Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_hh_tod_spt(tBTA_HH_DEV_CB *p_cb,UINT8 sub_class)
+{
+    UINT8    xx;
+    UINT8    cod = (sub_class >> 2); /* lower two bits are reserved */
+
+    for (xx = 0 ; xx < p_bta_hh_cfg->max_devt_spt; xx ++)
+    {
+        if (cod == (UINT8) p_bta_hh_cfg->p_devt_list[xx].tod)
+        {
+            p_cb->app_id = p_bta_hh_cfg->p_devt_list[xx].app_id;
+#if BTA_HH_DEBUG
+            APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x supported", sub_class);
+#endif
+            return TRUE;
+        }
+    }
+#if BTA_HH_DEBUG
+            APPL_TRACE_EVENT1("bta_hh_tod_spt sub_class:0x%x NOT supported", sub_class);
+#endif
+    return FALSE;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_parse_keybd_rpt
+**
+** Description      This utility function parse a boot mode keyboard report.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_parse_keybd_rpt(tBTA_HH_BOOT_RPT *p_kb_data, UINT8 *p_report,
+                            UINT16 report_len)
+{
+    tBTA_HH_KB_CB       *p_kb = &bta_hh_cb.kb_cb;
+    tBTA_HH_KEYBD_RPT   *p_data = &p_kb_data->data_rpt.keybd_rpt;
+
+    UINT8        this_char, ctl_shift;
+    UINT16       xx, yy, key_idx = 0;
+    UINT8        this_report[BTA_HH_MAX_RPT_CHARS];
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG2("bta_hh_parse_keybd_rpt:  (report=%p, report_len=%d) called",
+            p_report, report_len);
+#endif
+
+    if (report_len < 2)
+        return;
+
+    ctl_shift = *p_report++;
+    report_len--;
+
+    if (report_len > BTA_HH_MAX_RPT_CHARS)
+        report_len = BTA_HH_MAX_RPT_CHARS;
+
+    memset (this_report, 0, BTA_HH_MAX_RPT_CHARS);
+    memset (p_data, 0, sizeof(tBTA_HH_KEYBD_RPT));
+    memcpy (this_report, p_report, report_len);
+
+    /* Take care of shift, control, GUI and alt, modifier keys  */
+    for (xx = 0; xx < BTA_HH_MOD_MAX_KEY; xx ++ )
+    {
+        if (ctl_shift & bta_hh_mod_key_mask[xx])
+        {
+            APPL_TRACE_DEBUG1("Mod Key[%02x] pressed", bta_hh_mod_key_mask[xx] );
+            p_kb->mod_key[xx] = TRUE;
+        }
+        else if (p_kb->mod_key[xx])
+        {
+            p_kb->mod_key[xx] = FALSE;
+        }
+        /* control key flag is set */
+        p_data->mod_key[xx]       = p_kb->mod_key[xx];
+    }
+
+    /***************************************************************************/
+    /*  First step is to remove all characters we saw in the last report       */
+    /***************************************************************************/
+    for (xx = 0; xx < report_len; xx++)
+    {
+        for (yy = 0; yy < BTA_HH_MAX_RPT_CHARS; yy++)
+        {
+            if (this_report[xx] == p_kb->last_report[yy])
+            {
+                this_report[xx] = 0;
+            }
+        }
+    }
+    /***************************************************************************/
+    /*  Now, process all the characters in the report, up to 6 keycodes        */
+    /***************************************************************************/
+    for (xx = 0; xx < report_len; xx++)
+    {
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG1("this_char = %02x", this_report[xx]);
+#endif
+        if ((this_char = this_report[xx]) == 0)
+            continue;
+        /* take the key code as the report data */
+        if (this_report[xx] == BTA_HH_KB_CAPS_LOCK)
+            p_kb->caps_lock = p_kb->caps_lock ? FALSE : TRUE;
+        else if (this_report[xx] == BTA_HH_KB_NUM_LOCK)
+            p_kb->num_lock = p_kb->num_lock ? FALSE : TRUE;
+        else
+            p_data->this_char[key_idx ++] = this_char;
+
+#if BTA_HH_DEBUG
+        APPL_TRACE_DEBUG1("found keycode %02x ",  this_report[xx]);
+#endif
+        p_data->caps_lock   = p_kb->caps_lock;
+        p_kb->num_lock      = p_kb->num_lock;
+    }
+
+    memset (p_kb->last_report, 0, BTA_HH_MAX_RPT_CHARS);
+    memcpy (p_kb->last_report, p_report, report_len);
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_parse_mice_rpt
+**
+** Description      This utility function parse a boot mode mouse report.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_parse_mice_rpt(tBTA_HH_BOOT_RPT *p_mice_data, UINT8 *p_report,
+                           UINT16 report_len)
+{
+    tBTA_HH_MICE_RPT   *p_data = &p_mice_data->data_rpt.mice_rpt;
+#if BTA_HH_DEBUG
+    UINT8       xx;
+
+    APPL_TRACE_DEBUG2("bta_hh_parse_mice_rpt:  bta_keybd_rpt_rcvd(report=%p, \
+                report_len=%d) called", p_report, report_len);
+#endif
+
+    if (report_len < 3)
+        return;
+
+    if (report_len > BTA_HH_MAX_RPT_CHARS)
+        report_len = BTA_HH_MAX_RPT_CHARS;
+
+#if BTA_HH_DEBUG
+    for (xx = 0; xx < report_len; xx++)
+    {
+        APPL_TRACE_DEBUG1("this_char = %02x", p_report[xx]);
+    }
+#endif
+
+    /* only first bytes lower 3 bits valid */
+    p_data->mouse_button     = (p_report[0] & 0x07);
+
+    /* x displacement */
+    p_data->delta_x     = p_report[1];
+
+    /* y displacement */
+    p_data->delta_y     = p_report[2];
+
+#if BTA_HH_DEBUG
+    APPL_TRACE_DEBUG1("mice button: 0x%2x", p_data->mouse_button);
+    APPL_TRACE_DEBUG2("mice move: x = %d y = %d", p_data->delta_x,
+                        p_data->delta_y );
+#endif
+
+    return;
+
+}
+
+#if BTA_HH_DEBUG
+/*******************************************************************************
+**
+** Function         bta_hh_trace_dev_db
+**
+** Description      Check to see if this type of device is supported
+**
+** Returns
+**
+*******************************************************************************/
+void bta_hh_trace_dev_db(void)
+{
+    UINT8    xx;
+
+    APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************");
+
+    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    {
+        APPL_TRACE_DEBUG3("kdev[%d] in_use[%d]  handle[%d] ",xx,
+            bta_hh_cb.kdev[xx].in_use, bta_hh_cb.kdev[xx].hid_handle);
+
+        APPL_TRACE_DEBUG4("\t\t\t attr_mask[%04x] state [%d] sub_class[%02x] index = %d",
+            bta_hh_cb.kdev[xx].attr_mask, bta_hh_cb.kdev[xx].state,
+            bta_hh_cb.kdev[xx].sub_class, bta_hh_cb.kdev[xx].index);
+    }
+    APPL_TRACE_DEBUG0("*********************************************************");
+}
+#endif
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_act.c b/bta/hl/bta_hl_act.c
new file mode 100644
index 0000000..0f46e5e
--- /dev/null
+++ b/bta/hl/bta_hl_act.c
@@ -0,0 +1,2807 @@
+/******************************************************************************
+ *
+ *  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 the HeaLth device profile (HL) action functions for
+ *  the state machine.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "gki.h"
+#include "sdp_api.h"
+#include "bta_sys.h"
+#include "port_api.h"
+#include "sdp_api.h"
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+#include "utl.h"
+#include "bd.h"
+#include "mca_defs.h"
+#include "mca_api.h"
+
+/*****************************************************************************
+**  Local Function prototypes
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE && BT_TRACE_VERBOSE == TRUE)
+static char *bta_hl_mcap_evt_code(UINT8 evt_code);
+static char *bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code);
+static char *bta_hl_cback_evt_code(UINT8 evt_code);
+#endif
+static void bta_hl_sdp_cback(UINT8 sdp_op, UINT8 app_idx, UINT8 mcl_idx,
+                             UINT8 mdl_idx, UINT16 status);
+static void bta_hl_sdp_cback0(UINT16 status);
+static void bta_hl_sdp_cback1(UINT16 status);
+static void bta_hl_sdp_cback2(UINT16 status);
+static void bta_hl_sdp_cback3(UINT16 status);
+static void bta_hl_sdp_cback4(UINT16 status);
+static void bta_hl_sdp_cback5(UINT16 status);
+static void bta_hl_sdp_cback6(UINT16 status);
+
+
+static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] = {
+    bta_hl_sdp_cback0,
+    bta_hl_sdp_cback1,
+    bta_hl_sdp_cback2,
+    bta_hl_sdp_cback3,
+    bta_hl_sdp_cback4,
+    bta_hl_sdp_cback5,
+    bta_hl_sdp_cback6
+};
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_cong_change
+**
+** Description      Action routine for processing congestion change notification
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_cong_change(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_CONG_CHG       *p_cong_chg = &p_data->mca_evt.mca_data.cong_chg;
+    tBTA_HL             evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG2("bta_hl_dch_mca_cong_change mdl_id=%d cong=%d",
+                      p_cong_chg->mdl_id,
+                      p_cong_chg->cong);
+#endif
+    evt_data.dch_cong_ind.cong          =
+    p_dcb->cong                         = p_cong_chg->cong;
+    evt_data.dch_cong_ind.mdl_handle    = p_dcb->mdl_handle;
+    evt_data.dch_cong_ind.mcl_handle    = p_mcb->mcl_handle;
+    evt_data.dch_cong_ind.app_handle    = p_acb->app_handle;
+
+    p_acb->p_cback(BTA_HL_CONG_CHG_IND_EVT ,(tBTA_HL *) &evt_data );
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_echo_test
+**
+** Description      Action routine for processing echo test request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                          tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_echo_test");
+#endif
+
+    p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_GET_ECHO_DATA;
+    p_dcb->cout_oper |= BTA_HL_CO_GET_ECHO_DATA_MASK;
+
+    bta_hl_co_get_echo_data(p_acb->app_id, p_mcb->mcl_handle,
+                            p_dcb->p_echo_tx_pkt->len,
+                            BTA_HL_GET_BUF_PTR(p_dcb->p_echo_tx_pkt),
+                            BTA_HL_CI_GET_ECHO_DATA_EVT);
+
+}
+/*******************************************************************************
+**
+** Function         bta_hl_dch_sdp_init
+**
+** Description      Action routine for processing DCH SDP initiation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                         tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_sdp_init");
+#endif
+    if ( p_mcb->sdp_oper == BTA_HL_SDP_OP_NONE)
+    {
+        p_mcb->sdp_mdl_idx = mdl_idx;
+        if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN )
+        {
+            p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_OPEN_INIT;
+
+        }
+        else
+        {
+            p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_RECONNECT_INIT;
+        }
+
+        if (bta_hl_init_sdp(p_mcb->sdp_oper, app_idx, mcl_idx, mdl_idx) != BTA_HL_STATUS_OK)
+        {
+            APPL_TRACE_ERROR0("SDP INIT failed");
+            p_mcb->sdp_oper = BTA_HL_SDP_OP_NONE;
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT, p_data);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("SDP in use");
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT, p_data);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_close_echo_test
+**
+** Description      Action routine for processing the closing of echo test
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_close_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB          *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_close_echo_test");
+#endif
+
+    switch (p_dcb->echo_oper)
+    {
+        case BTA_HL_ECHO_OP_DCH_CLOSE_CFM:
+        case BTA_HL_ECHO_OP_OPEN_IND:
+        case BTA_HL_ECHO_OP_ECHO_PKT:
+            p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST;
+            break;
+        case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
+        case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
+        case BTA_HL_ECHO_OP_LOOP_BACK:
+        default:
+            break;
+    }
+
+    if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle)!= MCA_SUCCESS)
+    {
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_rcv_data
+**
+** Description      Action routine for processing the received data
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_rcv_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                             tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_rcv_data");
+#endif
+
+    if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+    {
+        switch ( p_dcb->echo_oper)
+        {
+            case  BTA_HL_ECHO_OP_ECHO_PKT:
+
+                if (MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_data->mca_rcv_data_evt.p_pkt) != MCA_SUCCESS)
+                {
+                    utl_freebuf((void **) &p_data->mca_rcv_data_evt.p_pkt);
+                    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+                }
+                break;
+            case BTA_HL_ECHO_OP_LOOP_BACK:
+
+                p_dcb->p_echo_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
+                p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA;
+                p_dcb->cout_oper |= BTA_HL_CO_PUT_ECHO_DATA_MASK;
+                p_dcb->ci_put_echo_data_status = BTA_HL_STATUS_FAIL;
+
+                bta_hl_co_put_echo_data(p_acb->app_id, p_mcb->mcl_handle,
+                                        p_dcb->p_echo_rx_pkt->len,
+                                        BTA_HL_GET_BUF_PTR(p_dcb->p_echo_rx_pkt),
+                                        BTA_HL_CI_PUT_ECHO_DATA_EVT);
+                break;
+            default:
+                APPL_TRACE_ERROR1("Unknonw echo_oper=%d",p_dcb->echo_oper);
+                break;
+        }
+
+    }
+    else
+    {
+        p_dcb->cout_oper |= BTA_HL_CO_PUT_RX_DATA_MASK;
+        p_dcb->p_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
+
+        bta_hl_co_put_rx_data(p_acb->app_id, p_dcb->mdl_handle,
+                              p_dcb->p_rx_pkt->len,
+                              BTA_HL_GET_BUF_PTR(p_dcb->p_rx_pkt),
+                              BTA_HL_CI_PUT_RX_DATA_EVT);
+
+
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_ci_put_echo_data
+**
+** Description      Action routine for processing the call-in of the
+**                  put echo data event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_put_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                 tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_ci_put_echo_data");
+#endif
+
+    p_dcb->cout_oper &= ~BTA_HL_CO_PUT_ECHO_DATA_MASK;
+    utl_freebuf((void **) &p_dcb->p_echo_rx_pkt);
+    p_dcb->ci_put_echo_data_status = p_data->ci_get_put_echo_data.status;
+
+    p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_CLOSE_CFM;
+    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_ci_get_echo_data
+**
+** Description      Action routine for processing the call-in of the
+**                  get echo data event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_get_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                 tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL_STATUS      status;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_ci_get_echo_data");
+#endif
+
+    p_dcb->cout_oper &= ~BTA_HL_CO_GET_ECHO_DATA_MASK;
+
+    if (!p_dcb->abort_oper)
+    {
+        status = p_data->ci_get_put_echo_data.status;
+        if (status == BTA_HL_STATUS_OK)
+        {
+            p_dcb->echo_oper = BTA_HL_ECHO_OP_MDL_CREATE_CFM;
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_OPEN_EVT, p_data);
+        }
+        else
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_ci_put_rx_data
+**
+** Description      Action routine for processing the call-in of the
+**                  put rx data event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_put_rx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                               tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL             evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_ci_put_rx_data");
+#endif
+
+    p_dcb->cout_oper &= ~BTA_HL_CO_PUT_RX_DATA_MASK;
+    utl_freebuf((void **) &p_dcb->p_rx_pkt);
+    bta_hl_build_rcv_data_ind(&evt_data,
+                              p_acb->app_handle,
+                              p_mcb->mcl_handle,
+                              p_dcb->mdl_handle);
+    p_acb->p_cback(BTA_HL_DCH_RCV_DATA_IND_EVT,(tBTA_HL *) &evt_data );
+    if (p_dcb->close_pending)
+    {
+        if (!p_dcb->cout_oper)
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+        }
+
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_ci_get_tx_data
+**
+** Description      Action routine for processing the call-in of the
+**                  get tx data event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_ci_get_tx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                               tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_RESULT         result;
+    tBTA_HL_STATUS      status = BTA_HL_STATUS_OK;
+    BOOLEAN             free_buf = FALSE;
+    BOOLEAN             close_dch = FALSE;
+    tBTA_HL             evt_data;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_ci_get_tx_data");
+#endif
+
+    p_dcb->cout_oper &= ~BTA_HL_CO_GET_TX_DATA_MASK;
+
+    if (p_dcb->close_pending)
+    {
+        status = BTA_HL_STATUS_FAIL;
+        free_buf = TRUE;
+
+        if (!p_dcb->cout_oper)
+        {
+            close_dch = TRUE;
+        }
+    }
+    else
+    {
+        if ((result = MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_dcb->p_tx_pkt)) != MCA_SUCCESS)
+        {
+            if (result == MCA_BUSY)
+            {
+                status = BTA_HL_STATUS_DCH_BUSY;
+            }
+            else
+            {
+                status = BTA_HL_STATUS_FAIL;
+            }
+            free_buf = TRUE;
+        }
+        else
+        {
+            p_dcb->p_tx_pkt = NULL;
+        }
+    }
+
+    if (free_buf)
+    {
+        utl_freebuf((void **) &p_dcb->p_tx_pkt);
+    }
+
+    bta_hl_build_send_data_cfm(&evt_data,
+                               p_acb->app_handle,
+                               p_mcb->mcl_handle,
+                               p_dcb->mdl_handle,
+                               status);
+    p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT,(tBTA_HL *) &evt_data );
+
+    if (close_dch)
+    {
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_send_data
+**
+** Description      Action routine for processing api send data request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_send_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                          tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL             evt_data;
+    BOOLEAN             success = TRUE;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_send_data");
+#endif
+
+    if (!(p_dcb->cout_oper & BTA_HL_CO_GET_TX_DATA_MASK))
+    {
+        if ((p_dcb->p_tx_pkt = bta_hl_get_buf(p_data->api_send_data.pkt_size)) != NULL)
+        {
+            bta_hl_co_get_tx_data( p_acb->app_id,
+                                   p_dcb->mdl_handle,
+                                   p_data->api_send_data.pkt_size,
+                                   BTA_HL_GET_BUF_PTR(p_dcb->p_tx_pkt),
+                                   BTA_HL_CI_GET_TX_DATA_EVT);
+            p_dcb->cout_oper |= BTA_HL_CO_GET_TX_DATA_MASK;
+        }
+        else
+        {
+            success = FALSE;
+        }
+    }
+    else
+    {
+        success = FALSE;
+    }
+
+    if (!success)
+    {
+        bta_hl_build_send_data_cfm(&evt_data,
+                                   p_acb->app_handle,
+                                   p_mcb->mcl_handle,
+                                   p_dcb->mdl_handle,
+                                   BTA_HL_STATUS_FAIL);
+        p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT,(tBTA_HL *) &evt_data );
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_close_cmpl
+**
+** Description      Action routine for processing the close complete event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                           tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL             evt_data;
+    tBTA_HL_EVT         event;
+    BOOLEAN             send_evt=TRUE;
+    tBTA_HL_STATUS      status;
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_dch_close_cmpl dch oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+    APPL_TRACE_DEBUG1("bta_hl_dch_close_cmpl dch oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+    switch (p_dcb->dch_oper)
+    {
+        case BTA_HL_DCH_OP_LOCAL_OPEN:
+        case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+
+            if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+            {
+                bta_hl_build_abort_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       BTA_HL_STATUS_OK);
+                event = BTA_HL_DCH_ABORT_CFM_EVT;
+            }
+            else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK )
+            {
+                bta_hl_build_abort_ind(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle);
+                event = BTA_HL_DCH_ABORT_IND_EVT;
+            }
+            else
+            {
+                bta_hl_build_dch_open_cfm(&evt_data,
+                                          p_acb->app_handle,
+                                          p_mcb->mcl_handle,
+                                          BTA_HL_INVALID_MDL_HANDLE,
+                                          0,0,0,0,0, BTA_HL_STATUS_FAIL);
+                event = BTA_HL_DCH_OPEN_CFM_EVT;
+                if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT)
+                {
+                    event = BTA_HL_DCH_RECONNECT_CFM_EVT;
+                }
+            }
+            break;
+
+        case BTA_HL_DCH_OP_LOCAL_CLOSE:
+        case BTA_HL_DCH_OP_REMOTE_DELETE:
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+        case BTA_HL_DCH_OP_NONE:
+
+            bta_hl_build_dch_close_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       p_dcb->mdl_handle,
+                                       BTA_HL_STATUS_OK);
+            event = BTA_HL_DCH_CLOSE_CFM_EVT;
+            break;
+
+        case BTA_HL_DCH_OP_REMOTE_CLOSE:
+            bta_hl_build_dch_close_ind(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       p_dcb->mdl_handle,
+                                       p_dcb->intentional_close);
+            event = BTA_HL_DCH_CLOSE_IND_EVT;
+            break;
+
+        case BTA_HL_DCH_OP_REMOTE_OPEN:
+
+            if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+            {
+                bta_hl_build_abort_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       BTA_HL_STATUS_OK);
+                event = BTA_HL_DCH_ABORT_CFM_EVT;
+            }
+            else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK )
+            {
+                bta_hl_build_abort_ind(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle);
+                event = BTA_HL_DCH_ABORT_IND_EVT;
+            }
+            else
+            {
+                bta_hl_build_dch_close_ind(&evt_data,
+                                           p_acb->app_handle,
+                                           p_mcb->mcl_handle,
+                                           p_dcb->mdl_handle,
+                                           p_dcb->intentional_close);
+                event = BTA_HL_DCH_CLOSE_IND_EVT;
+            }
+            break;
+
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+            /* this is normal echo test close */
+        case BTA_HL_DCH_OP_REMOTE_CREATE:
+        case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+            send_evt=FALSE;
+            break;
+
+        default:
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+            APPL_TRACE_ERROR1("DCH operation not found oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+            APPL_TRACE_ERROR1("DCH operation not found oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+            send_evt=FALSE;
+            break;
+    }
+
+    if ( p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+    {
+        p_mcb->echo_test = FALSE;
+        send_evt=FALSE;
+
+        if ( p_dcb->dch_oper != BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST)
+        {
+            switch (p_dcb->echo_oper)
+            {
+                case BTA_HL_ECHO_OP_CI_GET_ECHO_DATA:
+                case BTA_HL_ECHO_OP_SDP_INIT:
+                case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
+                case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
+                case BTA_HL_ECHO_OP_LOOP_BACK:
+
+                    status = BTA_HL_STATUS_FAIL;
+                    send_evt = TRUE;
+                    break;
+                case BTA_HL_ECHO_OP_OPEN_IND:
+                case BTA_HL_ECHO_OP_ECHO_PKT:
+                    break;
+                default:
+                    APPL_TRACE_ERROR1("Invalid echo_oper=%d", p_dcb->echo_oper);
+                    break;
+            }
+        }
+        else
+        {
+            status = p_dcb->ci_put_echo_data_status;
+            send_evt = TRUE;
+        }
+
+        if (send_evt)
+        {
+            bta_hl_build_echo_test_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       status);
+            event = BTA_HL_DCH_ECHO_TEST_CFM_EVT;
+        }
+    }
+
+    bta_hl_clean_mdl_cb(app_idx, mcl_idx, mdl_idx);
+
+    if (send_evt)
+    {
+        if (p_acb->p_cback)
+        {
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+            APPL_TRACE_DEBUG1("Send Event: %s",  bta_hl_cback_evt_code(event));
+#else
+            APPL_TRACE_DEBUG1("Send Event: 0x%02x", event);
+#endif
+#endif
+            p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+        }
+    }
+    /* check cch close is in progress or not */
+    bta_hl_check_cch_close(app_idx, mcl_idx, p_data, FALSE);
+}
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_close_ind
+**
+** Description      Action routine for processing the close indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                              tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_ind dch oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper));
+#else
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_ind dch oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+    p_dcb->intentional_close = FALSE;
+    if (p_data->mca_evt.mca_data.close_ind.reason == L2CAP_DISC_OK)
+    {
+        p_dcb->intentional_close = TRUE;
+    }
+
+    if (!p_dcb->cout_oper)
+    {
+        if ((p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_OPEN) &&
+            (p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_RECONNECT))
+        {
+            p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_CLOSE;
+        }
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+    else
+    {
+        p_dcb->close_pending = TRUE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_close_cfm
+**
+** Description      Action routine for processing the close confirmation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                              tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_cfm dch_oper=%s", bta_hl_dch_oper_code(p_dcb->dch_oper) );
+#else
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_close_cfm dch_oper=%d", p_dcb->dch_oper);
+#endif
+#endif
+
+    switch (p_dcb->dch_oper)
+    {
+        case BTA_HL_DCH_OP_LOCAL_CLOSE:
+        case BTA_HL_DCH_OP_LOCAL_OPEN:
+        case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+        case BTA_HL_DCH_OP_REMOTE_DELETE:
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+        case BTA_HL_DCH_OP_NONE:
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+            break;
+        default:
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+            APPL_TRACE_ERROR1("Invalid dch_oper=%s for close cfm", bta_hl_dch_oper_code(p_dcb->dch_oper) );
+#else
+            APPL_TRACE_ERROR1("Invalid dch_oper=%d for close cfm", p_dcb->dch_oper);
+#endif
+#endif
+            break;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_close
+**
+** Description      Action routine for processing the DCH close request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_close(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                          tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB          *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB          *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB          *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL_STATUS          status = BTA_HL_STATUS_OK;
+    tBTA_HL                 evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_close");
+#endif
+    if (!p_dcb->cout_oper)
+    {
+        p_dcb->close_pending = FALSE;
+        if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle)== MCA_SUCCESS)
+        {
+            p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE;
+        }
+        else
+        {
+            status = BTA_HL_STATUS_FAIL;
+        }
+
+        if ((status != BTA_HL_STATUS_OK) &&
+            (p_mcb->cch_close_dch_oper != BTA_HL_CCH_CLOSE_OP_DCH_CLOSE))
+        {
+            bta_hl_build_dch_close_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       p_data->api_dch_close.mdl_handle,
+                                       status);
+            p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+        }
+    }
+    else
+    {
+        p_dcb->close_pending = TRUE;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_open_ind
+**
+** Description      Action routine for processing the open indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_open_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                             tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_DL_OPEN        *p_open_ind = &p_data->mca_evt.mca_data.open_ind;
+    tBTA_HL             evt_data;
+    tBTA_HL_EVT         event;
+    UINT8               old_dch_oper;
+    BOOLEAN             send_event = FALSE;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_open_ind");
+#endif
+    if ((p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_OPEN) ||
+        (p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_RECONNECT)    )
+    {
+        p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE) p_open_ind->mdl;
+        p_dcb->mtu        = p_open_ind->mtu;
+
+        evt_data.dch_open_ind.mdl_handle = p_dcb->mdl_handle;
+        evt_data.dch_open_ind.mcl_handle = p_mcb->mcl_handle;
+        evt_data.dch_open_ind.app_handle = p_acb->app_handle;
+
+        evt_data.dch_open_ind.local_mdep_id = p_dcb->local_mdep_id;
+        evt_data.dch_open_ind.mdl_id = p_dcb->mdl_id;
+        evt_data.dch_open_ind.mtu = p_dcb->mtu;
+
+        if ( p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE )
+        {
+            evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_RELIABLE;
+            if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx))
+            {
+                p_dcb->is_the_first_reliable = TRUE;
+            }
+        }
+        else
+        {
+            evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_STREAMING;
+        }
+        evt_data.dch_open_ind.first_reliable = p_dcb->is_the_first_reliable ;
+
+        old_dch_oper = p_dcb->dch_oper;
+        p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
+
+
+    }
+
+    switch (old_dch_oper)
+    {
+        case BTA_HL_DCH_OP_REMOTE_OPEN:
+
+            p_dcb->dch_mode = evt_data.dch_open_ind.dch_mode;
+            if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+            {
+                bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+                event= BTA_HL_DCH_OPEN_IND_EVT;
+                send_event= TRUE;
+            }
+            else
+            {
+                p_dcb->echo_oper = BTA_HL_ECHO_OP_ECHO_PKT;
+            }
+
+            break;
+
+        case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+
+            if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx))
+            {
+                bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+                event= BTA_HL_DCH_RECONNECT_IND_EVT;
+                send_event= TRUE;
+            }
+            else
+            {
+                if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle) == MCA_SUCCESS)
+                {
+                    p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
+                }
+                else
+                {
+                    APPL_TRACE_ERROR0("Unabel to close DCH for reconnect cfg mismatch");
+                }
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (send_event)
+    {
+        p_acb->p_cback(event ,(tBTA_HL *) &evt_data );
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_open_cfm
+**
+** Description      Action routine for processing the open confirmation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                             tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_DL_OPEN        *p_open_cfm = &p_data->mca_evt.mca_data.open_cfm;
+    tBTA_HL             evt_data;
+    tBTA_HL_EVT         event;
+    UINT8               old_dch_oper;
+    tBTA_HL_DCH_MODE    dch_mode;
+    BOOLEAN             send_event = FALSE;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_open_cfm");
+#endif
+    if ((p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN) ||
+        (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT))
+    {
+        p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE) p_open_cfm->mdl;
+        p_dcb->mtu        = p_open_cfm->mtu;
+
+        /*todo verify dch_mode, mtu and fcs for reconnect */
+        if ( p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE )
+        {
+            dch_mode = BTA_HL_DCH_MODE_RELIABLE;
+        }
+        else
+        {
+            dch_mode = BTA_HL_DCH_MODE_STREAMING;
+        }
+
+        if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+        {
+            if (dch_mode == BTA_HL_DCH_MODE_RELIABLE )
+            {
+                if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx))
+                {
+                    p_dcb->is_the_first_reliable = TRUE;
+                }
+            }
+        }
+
+        bta_hl_build_dch_open_cfm(&evt_data, p_acb->app_handle,
+                                  p_mcb->mcl_handle,
+                                  p_dcb->mdl_handle,
+                                  p_dcb->local_mdep_id,
+                                  p_dcb->mdl_id, dch_mode,
+                                  p_dcb->is_the_first_reliable,
+                                  p_dcb->mtu,
+                                  BTA_HL_STATUS_OK);
+
+        old_dch_oper = p_dcb->dch_oper;
+        p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
+    }
+
+    switch (old_dch_oper)
+    {
+        case BTA_HL_DCH_OP_LOCAL_OPEN:
+
+            p_dcb->dch_mode = dch_mode;
+            if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+            {
+                bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
+                event= BTA_HL_DCH_OPEN_CFM_EVT;
+                send_event= TRUE;
+            }
+            else
+            {
+                p_dcb->echo_oper = BTA_HL_ECHO_OP_LOOP_BACK;
+                if (MCA_WriteReq((tMCA_DL) p_dcb->mdl_handle, p_dcb->p_echo_tx_pkt)!= MCA_SUCCESS)
+                {
+                    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
+                }
+                else
+                {
+                    p_dcb->p_echo_tx_pkt = NULL;
+                }
+            }
+            break;
+
+        case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+
+            if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx))
+            {
+                bta_hl_save_mdl_cfg(app_idx, mcl_idx,mdl_idx);
+                event= BTA_HL_DCH_RECONNECT_CFM_EVT;
+                send_event= TRUE;
+            }
+            else
+            {
+                if (MCA_CloseReq((tMCA_DL) p_dcb->mdl_handle) == MCA_SUCCESS)
+                {
+                    p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
+                }
+                else
+                {
+                    APPL_TRACE_ERROR0("Unabel to close DCH for reconnect cfg mismatch");
+                }
+            }
+            break;
+        default:
+            break;
+    }
+
+    if (send_event)
+        p_acb->p_cback(event ,(tBTA_HL *) &evt_data );
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_abort_ind
+**
+** Description      Action routine for processing the abort indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                              tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_abort_ind");
+#endif
+
+    p_dcb->abort_oper |= BTA_HL_ABORT_REMOTE_MASK;
+    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_abort_cfm
+**
+** Description      Action routine for processing the abort confirmation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                              tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL             evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_abort_cfm");
+#endif
+
+    if (p_dcb->abort_oper)
+    {
+        if (p_data->mca_evt.mca_data.abort_cfm.rsp_code != MCA_RSP_SUCCESS )
+        {
+            if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+            {
+                bta_hl_build_abort_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       BTA_HL_STATUS_FAIL);
+                p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT ,(tBTA_HL *) &evt_data );
+            }
+        }
+        else
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("Not expecting Abort CFM ");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_abort
+**
+** Description      Action routine for processing the abort request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_abort(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                          tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB          *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB          *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB          *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_RESULT             mca_result;
+    tBTA_HL                 evt_data;
+
+    if (((p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT) ||
+         (p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_RECONNECT_INIT)) &&
+        (p_mcb->sdp_mdl_idx == mdl_idx) )
+    {
+        p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+        return;
+    }
+    else if (p_dcb->echo_oper == BTA_HL_ECHO_OP_CI_GET_ECHO_DATA)
+    {
+        p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+        return;
+    }
+
+    p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+
+    if ((mca_result = MCA_Abort((tMCA_CL) p_mcb->mcl_handle))!= MCA_SUCCESS)
+    {
+        if (mca_result == MCA_NO_RESOURCES)
+        {
+            p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
+        }
+        else
+        {
+            if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK)
+            {
+                bta_hl_build_abort_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       BTA_HL_STATUS_FAIL);
+                p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT ,(tBTA_HL *) &evt_data );
+            }
+            bta_hl_check_cch_close(app_idx, mcl_idx, p_data, FALSE);
+        }
+
+
+    }
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_abort abort_oper=0x%x", p_dcb->abort_oper);
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_reconnect_ind
+**
+** Description      Action routine for processing the reconnect indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL_MDL_CFG     *p_mdl_cfg;
+    tMCA_EVT_HDR        *p_reconnect_ind = &p_data->mca_evt.mca_data.reconnect_ind;
+    UINT8               mdl_cfg_idx, in_use_mdl_idx, mdep_cfg_idx;
+    UINT8               rsp_code = MCA_RSP_SUCCESS;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_dch_mca_reconnect_ind mdl_id=%d", p_reconnect_ind->mdl_id);
+#endif
+
+    if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect_ind->mdl_id, &mdl_cfg_idx))
+    {
+        if (!bta_hl_find_mdl_idx(app_idx,mcl_idx,p_reconnect_ind->mdl_id, &in_use_mdl_idx) )
+        {
+            p_mdl_cfg =  BTA_HL_GET_MDL_CFG_PTR(app_idx, mdl_cfg_idx);
+
+            if (bta_hl_find_mdep_cfg_idx(app_idx, p_mdl_cfg->local_mdep_id, &mdep_cfg_idx))
+            {
+                p_dcb->in_use               = TRUE;
+                p_dcb->dch_oper             = BTA_HL_DCH_OP_REMOTE_RECONNECT;
+                p_dcb->sec_mask             = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+                p_dcb->peer_mdep_id             = 0xFF;
+                p_dcb->local_mdep_id        = p_mdl_cfg->local_mdep_id  ;
+                p_dcb->local_mdep_cfg_idx   = mdep_cfg_idx;
+                p_dcb->local_cfg            = BTA_HL_DCH_CFG_UNKNOWN;
+                p_dcb->mdl_id               = p_reconnect_ind->mdl_id;
+                p_dcb->mdl_cfg_idx_included = TRUE;
+                p_dcb->mdl_cfg_idx          = mdl_cfg_idx;
+                p_dcb->dch_mode             = p_mdl_cfg->dch_mode;
+                bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+                                           &p_dcb->max_rx_apdu_size,
+                                           &p_dcb->max_tx_apdu_size);
+                bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+            }
+            else
+            {
+                rsp_code = MCA_RSP_BAD_MDL;
+            }
+        }
+        else
+        {
+            rsp_code = MCA_RSP_BAD_MDL;
+        }
+    }
+    else
+    {
+        rsp_code = MCA_RSP_BAD_MDL;
+    }
+
+    if (MCA_ReconnectMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+                            p_dcb->local_mdep_id,
+                            p_dcb->mdl_id,
+                            rsp_code,
+                            &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+    {
+        MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_reconnect_cfm
+**
+** Description      Action routine for processing the reconenct confirmation
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_RSP_EVT        *p_reconnect_cfm = &p_data->mca_evt.mca_data.reconnect_cfm;
+
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_reconnect_cfm");
+#endif
+    if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+    {
+        p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+        return;
+    }
+
+
+    if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT)
+    {
+        if (p_reconnect_cfm->rsp_code == MCA_RSP_SUCCESS)
+        {
+
+            bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+
+            if (MCA_DataChnlCfg((tMCA_CL) p_mcb->mcl_handle, &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+            {
+                /* should be able to abort so no checking of the return code */
+                MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+            }
+        }
+        else
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_reconnect
+**
+** Description      Action routine for processing the reconnect request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_reconnect(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                              tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_CHNL_CFG       *p_chnl_cfg=NULL;
+    UINT8               sdp_idx;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_reconnect");
+#endif
+    if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm, &sdp_idx))
+    {
+        p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+        if ( MCA_ReconnectMdl((tMCA_CL) p_mcb->mcl_handle,
+                              p_dcb->local_mdep_id,
+                              p_mcb->data_psm,
+                              p_dcb->mdl_id,
+                              p_chnl_cfg ) != MCA_SUCCESS)
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_create_rsp
+**
+** Description      Action routine for processing BTA_HL_API_DCH_CREATE_RSP_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_create_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                           tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB              *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB              *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL_API_DCH_CREATE_RSP  *p_create_rsp = &p_data->api_dch_create_rsp;
+    UINT8                       mca_rsp_code = MCA_RSP_SUCCESS;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_create_rsp");
+#endif
+    if (p_create_rsp->rsp_code == BTA_HL_DCH_CREATE_RSP_SUCCESS)
+    {
+        p_dcb->dch_oper             = BTA_HL_DCH_OP_REMOTE_OPEN;
+        p_dcb->local_cfg            = p_create_rsp->cfg_rsp;
+
+
+
+        bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+    }
+    else
+    {
+        mca_rsp_code = MCA_RSP_CFG_REJ;
+    }
+
+    if (MCA_CreateMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+                         p_dcb->local_mdep_id,
+                         p_dcb->mdl_id,
+                         p_dcb->local_cfg,
+                         mca_rsp_code,
+                         &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+    {
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_create_ind
+**
+** Description      Action routine for processing
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                               tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_CREATE_IND     *p_create_ind = &p_data->mca_evt.mca_data.create_ind;
+    UINT8               mdep_cfg_idx;
+    UINT8               cfg_rsp;
+    UINT8               rsp_code = MCA_RSP_SUCCESS;
+    BOOLEAN             send_create_ind_evt = FALSE;
+    tBTA_HL             evt_data;
+    tBTA_HL_ECHO_CFG    *p_echo_cfg;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_create_ind");
+#endif
+
+    if (bta_hl_find_mdep_cfg_idx(app_idx, p_create_ind->dep_id, &mdep_cfg_idx))
+    {
+        if (p_create_ind->dep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+        {
+            if (bta_hl_find_echo_cfg_rsp(app_idx, mcl_idx, mdep_cfg_idx,p_create_ind->cfg, &cfg_rsp ))
+            {
+                p_dcb->in_use               = TRUE;
+                p_dcb->dch_oper             = BTA_HL_DCH_OP_REMOTE_OPEN;
+                p_dcb->local_mdep_id        = p_create_ind->dep_id  ;
+                p_dcb->local_mdep_cfg_idx   = mdep_cfg_idx;
+                p_dcb->local_cfg            = cfg_rsp;
+                p_dcb->remote_cfg           = p_create_ind->cfg ;
+                p_dcb->mdl_id               = p_create_ind->mdl_id;
+                p_dcb->mdl_cfg_idx_included = FALSE;
+                p_echo_cfg                      = BTA_HL_GET_ECHO_CFG_PTR(app_idx);
+                p_dcb->max_rx_apdu_size         = p_echo_cfg->max_rx_apdu_size;
+                p_dcb->max_tx_apdu_size         = p_echo_cfg->max_tx_apdu_size;
+
+                bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+            }
+            else
+            {
+                rsp_code = MCA_RSP_CFG_REJ;
+            }
+        }
+        else
+
+        {
+            p_dcb->in_use               = TRUE;
+            p_dcb->dch_oper             = BTA_HL_DCH_OP_REMOTE_CREATE;
+            p_dcb->local_mdep_id        = p_create_ind->dep_id  ;
+            p_dcb->local_mdep_cfg_idx   = mdep_cfg_idx;
+            p_dcb->local_cfg            = BTA_HL_DCH_CFG_UNKNOWN;
+            p_dcb->remote_cfg           = p_create_ind->cfg;
+            p_dcb->mdl_id               = p_create_ind->mdl_id;
+            p_dcb->mdl_cfg_idx_included = FALSE;
+            bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+                                       &p_dcb->max_rx_apdu_size,
+                                       &p_dcb->max_tx_apdu_size);
+            send_create_ind_evt = TRUE;
+        }
+    }
+    else
+    {
+        rsp_code = MCA_RSP_BAD_MDEP;
+    }
+
+    if (send_create_ind_evt)
+    {
+        evt_data.dch_create_ind.mcl_handle =  p_mcb->mcl_handle;
+        evt_data.dch_create_ind.app_handle =  p_acb->app_handle;
+        evt_data.dch_create_ind.local_mdep_id = p_dcb->local_mdep_id;
+        evt_data.dch_create_ind.mdl_id = p_dcb->mdl_id;
+        evt_data.dch_create_ind.cfg = p_dcb->remote_cfg;
+        p_acb->p_cback(BTA_HL_DCH_CREATE_IND_EVT,(tBTA_HL *) &evt_data );
+    }
+    else
+    {
+        if (MCA_CreateMdlRsp((tMCA_CL) p_mcb->mcl_handle,
+                             p_dcb->local_mdep_id,
+                             p_dcb->mdl_id,
+                             p_dcb->local_cfg,
+                             rsp_code,
+                             &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+        {
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+        else
+        {
+            if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+            {
+                p_mcb->echo_test = TRUE;
+                p_dcb->echo_oper = BTA_HL_ECHO_OP_OPEN_IND;
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_create_cfm
+**
+** Description      Action routine for processing
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                               tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_CREATE_CFM     *p_create_cfm = &p_data->mca_evt.mca_data.create_cfm;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_create_cfm");
+#endif
+
+    if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+    {
+        p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+        return;
+    }
+
+    if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN)
+    {
+        if (p_create_cfm->rsp_code == MCA_RSP_SUCCESS)
+        {
+            if (bta_hl_validate_cfg(app_idx, mcl_idx, mdl_idx, p_create_cfm->cfg ))
+            {
+                bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
+
+                if (MCA_DataChnlCfg((tMCA_CL) p_mcb->mcl_handle, &p_dcb->chnl_cfg)!= MCA_SUCCESS)
+                {
+                    /* this should not happen */
+                    APPL_TRACE_ERROR0("Unable to create data channel");
+                    MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+                    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+                }
+                else
+                {
+                    if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+                    {
+                        p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_OPEN_CFM;
+                    }
+                }
+            }
+            else
+            {
+                MCA_Abort((tMCA_CL) p_mcb->mcl_handle);
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+            }
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("MCA Create- failed");
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_mca_create
+**
+** Description      Action routine for processing the MDL create request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_mca_create(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                           tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tMCA_RESULT         result;
+    UINT8               sdp_idx;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_dch_mca_create");
+#endif
+
+    if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm, &sdp_idx) &&
+        bta_hl_validate_peer_cfg(app_idx, mcl_idx, mdl_idx,
+                                 p_dcb->peer_mdep_id,
+                                 p_dcb->peer_mdep_role,
+                                 sdp_idx))
+    {
+
+        p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+        if ( (result = MCA_CreateMdl((tMCA_CL) p_mcb->mcl_handle,
+                                     p_dcb->local_mdep_id,
+                                     p_mcb->data_psm,
+                                     p_dcb->mdl_id,
+                                     p_dcb->peer_mdep_id,
+                                     p_dcb->local_cfg,
+                                     NULL )) != MCA_SUCCESS)
+        {
+            APPL_TRACE_ERROR1("MCA_CreateMdl FAIL mca_result=%d", result);
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("MCA Create- SDP idx or peer MDEP cfg not found");
+        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_sdp_fail
+**
+** Description      Action routine for processing the SDP failed event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_sdp_fail(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                         tBTA_HL_DATA *p_data)
+{
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_dch_sdp_fail");
+#endif
+    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback
+**
+** Description      This is the SDP callback function used by HL.
+**                  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 the scn from the
+**                  record.
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                             UINT8 mdl_idx, UINT16 status)
+{
+    tBTA_HL_MCL_CB                  *p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_SDP_REC                 *p_hdp_rec;
+    tBTA_HL_CCH_SDP                 *p_cch_buf;
+    tBTA_HL_DCH_SDP                 *p_dch_buf;
+    tSDP_DISC_REC                   *p_rec = NULL;
+    tSDP_PROTOCOL_ELEM              pe;
+    tSDP_DISC_ATTR                  *p_attr;
+    UINT8                           i, rec_cnt;
+    tBTA_HL_SUP_FEATURE_LIST_ELEM   sup_feature;
+    BOOLEAN                         sdp_parsing_ok =FALSE, result=FALSE;
+    UINT16                          event;
+    tBTA_HL_MDL_CB                  *p_dcb;
+    UINT16                          service_uuid;
+    UINT16                          name_len;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG5("bta_hl_sdp_cback status:%d sdp_oper=%d app_idx=%d, mcl_idx=%d,   mdl_idx=%d",
+                      status, sdp_oper, app_idx, mcl_idx, mdl_idx);
+#endif
+
+    rec_cnt = 0;
+    service_uuid = bta_hl_get_service_uuids(sdp_oper, app_idx, mcl_idx, mdl_idx);
+
+    if (status == SDP_SUCCESS || status == SDP_DB_FULL)
+    {
+        memset(&p_cb->sdp,0, sizeof(tBTA_HL_SDP));
+        do
+        {
+            if (bta_hl_find_service_in_db(app_idx, mcl_idx, service_uuid, &p_rec))
+            {
+                p_hdp_rec = &p_cb->sdp.sdp_rec[rec_cnt];
+                p_cb->sdp.num_recs = rec_cnt+1;
+            }
+            else
+            {
+                break;
+            }
+
+            if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe))
+            {
+                p_hdp_rec->ctrl_psm  = (UINT16) pe.params[0];
+            }
+            else
+            {
+                APPL_TRACE_WARNING0("Control PSM not found");
+                break;
+            }
+            if (SDP_FindAddProtoListsElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe))
+            {
+                p_hdp_rec->data_psm = (UINT16) pe.params[0];
+            }
+            else
+            {
+                APPL_TRACE_WARNING0("Data PSM not found");
+                break;
+            }
+
+            p_hdp_rec->srv_name[0]= '\0';
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME)) != NULL)
+            {
+                if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+                    name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+                else
+                    name_len = BT_MAX_SERVICE_NAME_LEN;
+                memcpy(p_hdp_rec->srv_name, p_attr->attr_value.v.array, name_len);
+            }
+
+            p_hdp_rec->srv_desp[0]= '\0';
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_DESCRIPTION)) != NULL)
+            {
+                if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+                    name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+                else
+                    name_len = BT_MAX_SERVICE_NAME_LEN;
+                memcpy(p_hdp_rec->srv_desp, p_attr->attr_value.v.array, name_len);
+            }
+
+
+            p_hdp_rec->provider_name[0]= '\0';
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PROVIDER_NAME)) != NULL)
+            {
+                if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
+                    name_len = (UINT16)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+                else
+                    name_len = BT_MAX_SERVICE_NAME_LEN;
+                memcpy(p_hdp_rec->provider_name, p_attr->attr_value.v.array, name_len);
+            }
+
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_MCAP_SUP_PROC))!=NULL)
+            {
+                p_hdp_rec->mcap_sup_proc = p_attr->attr_value.v.u8;
+            }
+            else
+            {
+                APPL_TRACE_WARNING0("MCAP SUP PROC not found");
+                break;
+            }
+
+            if ((p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_SUP_FEAT_LIST ))!=NULL)
+            {
+                if (bta_hl_fill_sup_feature_list (p_attr, &sup_feature))
+                {
+                    p_hdp_rec->num_mdeps = (UINT8) sup_feature.num_elems;
+                    for (i=0; i<sup_feature.num_elems; i++)
+                    {
+                        p_hdp_rec->mdep_cfg[i].data_type = sup_feature.list_elem[i].data_type;
+                        p_hdp_rec->mdep_cfg[i].mdep_id = sup_feature.list_elem[i].mdep_id;
+                        p_hdp_rec->mdep_cfg[i].mdep_role = sup_feature.list_elem[i].mdep_role;
+                        /* Check MDEP Description pointer to prevent crash due to null pointer */
+                        if (sup_feature.list_elem[i].p_mdep_desp != NULL)
+                        {
+                            BCM_STRNCPY_S(p_hdp_rec->mdep_cfg[i].mdep_desp,
+                                    sizeof(p_hdp_rec->mdep_cfg[i].mdep_desp),
+                                    sup_feature.list_elem[i].p_mdep_desp,
+                                    BTA_HL_MDEP_DESP_LEN);
+                        }
+                        else
+                        {
+                            APPL_TRACE_ERROR1("bta_hl_sdp_cback Incorrect Mdep[%d] Description (Null ptr)", i);
+                        }
+                    }
+
+                    sdp_parsing_ok = TRUE;
+                }
+                else
+                {
+                    APPL_TRACE_WARNING0("HDP supported feature list fill failed");
+                    break;
+                }
+            }
+            else
+            {
+                APPL_TRACE_WARNING0("HDP supported feature list not found");
+                break;
+            }
+#if BTA_HL_DEBUG == TRUE
+            APPL_TRACE_DEBUG3("record=%d ctrl_psm=%0x data_psm=%x",
+                              rec_cnt+1,
+                              p_hdp_rec->ctrl_psm,
+                              p_hdp_rec->data_psm );
+            APPL_TRACE_DEBUG1("srv_name=[%s]",(p_hdp_rec->srv_name[0] != '\0')? p_hdp_rec->srv_name:"NULL");
+            APPL_TRACE_DEBUG1("srv_desp=[%s]",(p_hdp_rec->srv_desp[0] != '\0')? p_hdp_rec->srv_desp:"NULL");
+            for (i=0; i<sup_feature.num_elems; i++)
+            {
+                APPL_TRACE_DEBUG5("index=0x%02x mdep_id=0x%04x data type=0x%04x mdep role=%s(0x%02x)",
+                                  (i+1),
+                                  p_hdp_rec->mdep_cfg[i].mdep_id,
+                                  p_hdp_rec->mdep_cfg[i].data_type,
+                                  (p_hdp_rec->mdep_cfg[i].mdep_role == BTA_HL_MDEP_ROLE_SOURCE)?"Src":"Snk",
+                                  p_hdp_rec->mdep_cfg[i].mdep_role);
+            }
+            APPL_TRACE_DEBUG1("provider_name=[%s]",(p_hdp_rec->provider_name[0] != '\0')? p_hdp_rec->provider_name:"NULL");
+            APPL_TRACE_DEBUG1("found MCAP sup procedure=%d",
+                              p_cb->sdp.sdp_rec[rec_cnt].mcap_sup_proc );
+#endif
+            rec_cnt++;
+            if (rec_cnt >= BTA_HL_NUM_SDP_RECS)
+            {
+                APPL_TRACE_WARNING1("No more spaces for SDP recs max_rec_cnt=%d", BTA_HL_NUM_SDP_RECS);
+                break;
+            }
+
+
+        } while (TRUE);
+    }
+
+
+    utl_freebuf((void **)&p_cb->p_db);
+
+    if ( (status == SDP_SUCCESS || status == SDP_DB_FULL) &&
+         p_cb->sdp.num_recs  &&
+         sdp_parsing_ok)
+    {
+        result = TRUE;
+    }
+    else
+    {
+        APPL_TRACE_WARNING3("SDP Failed sdp_status=%d num_recs=%d sdp_parsing_ok=%d ",
+                            status, p_cb->sdp.num_recs,sdp_parsing_ok );
+    }
+
+
+    p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
+
+    switch (sdp_oper )
+    {
+        case BTA_HL_SDP_OP_CCH_INIT:
+        case BTA_HL_SDP_OP_SDP_QUERY_NEW:
+        case BTA_HL_SDP_OP_SDP_QUERY_CURRENT:
+
+            /* send result in event back to BTA */
+            if ((p_cch_buf = (tBTA_HL_CCH_SDP *) GKI_getbuf(sizeof(tBTA_HL_CCH_SDP))) != NULL)
+            {
+                if (result)
+                {
+                    if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT)
+                    {
+                        event = BTA_HL_CCH_SDP_OK_EVT;
+                        if (p_cb->close_pending)
+                        {
+                            event = BTA_HL_CCH_SDP_FAIL_EVT;
+                        }
+                    }
+                    else
+                    {
+                        event = BTA_HL_SDP_QUERY_OK_EVT;
+                    }
+                }
+                else
+                {
+                    if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT)
+                    {
+                        event = BTA_HL_CCH_SDP_FAIL_EVT;
+                    }
+                    else
+                    {
+                        event = BTA_HL_SDP_QUERY_FAIL_EVT;
+                    }
+                }
+                p_cch_buf->hdr.event = event;
+
+                p_cch_buf->app_idx = app_idx;
+                p_cch_buf->mcl_idx = mcl_idx;
+                p_cch_buf->release_mcl_cb = FALSE;
+                if (sdp_oper == BTA_HL_SDP_OP_SDP_QUERY_NEW)
+                {
+                    p_cch_buf->release_mcl_cb = TRUE;
+                }
+
+                bta_sys_sendmsg(p_cch_buf);
+            }
+            break;
+        case BTA_HL_SDP_OP_DCH_OPEN_INIT:
+        case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
+            if ((p_dch_buf = (tBTA_HL_DCH_SDP *) GKI_getbuf(sizeof(tBTA_HL_DCH_SDP))) != NULL)
+            {
+                p_dch_buf->hdr.event = BTA_HL_DCH_SDP_FAIL_EVT;
+                p_dch_buf->app_idx = app_idx;
+                p_dch_buf->mcl_idx = mcl_idx;
+                p_dch_buf->mdl_idx = mdl_idx;
+                p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+                if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK)
+                {
+                    p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
+                    result = FALSE;
+                }
+                if (result)
+                {
+                    if (sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT)
+                    {
+                        if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID )
+                        {
+                            p_dch_buf->hdr.event = BTA_HL_DCH_ECHO_TEST_EVT;
+                        }
+                        else
+                        {
+                            p_dch_buf->hdr.event = BTA_HL_DCH_OPEN_EVT;
+                        }
+                    }
+                    else
+                    {
+                        p_dch_buf->hdr.event = BTA_HL_DCH_RECONNECT_EVT;
+                    }
+                }
+                bta_sys_sendmsg(p_dch_buf);
+            }
+            break;
+        default:
+            break;
+    }
+}
+
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback0
+**
+** Description      This is the SDP callback function used by index = 0
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback0(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[0].sdp_oper,
+                     bta_hl_cb.scb[0].app_idx,
+                     bta_hl_cb.scb[0].mcl_idx,
+                     bta_hl_cb.scb[0].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(0);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback1
+**
+** Description      This is the SDP callback function used by index = 1
+**
+** Parameters       status  - status of the SDP callabck
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback1(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[1].sdp_oper,
+                     bta_hl_cb.scb[1].app_idx,
+                     bta_hl_cb.scb[1].mcl_idx,
+                     bta_hl_cb.scb[1].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(1);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback2
+**
+** Description      This is the SDP callback function used by index = 2
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback2(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[2].sdp_oper,
+                     bta_hl_cb.scb[2].app_idx,
+                     bta_hl_cb.scb[2].mcl_idx,
+                     bta_hl_cb.scb[2].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(2);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback3
+**
+** Description      This is the SDP callback function used by index = 3
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback3(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[3].sdp_oper,
+                     bta_hl_cb.scb[3].app_idx,
+                     bta_hl_cb.scb[3].mcl_idx,
+                     bta_hl_cb.scb[3].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(3);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback4
+**
+** Description      This is the SDP callback function used by index = 4
+**
+** Parameters       status  - status of the SDP callabck
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback4(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[4].sdp_oper,
+                     bta_hl_cb.scb[4].app_idx,
+                     bta_hl_cb.scb[4].mcl_idx,
+                     bta_hl_cb.scb[4].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(4);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback5
+**
+** Description      This is the SDP callback function used by index = 5
+**
+** Parameters       status  - status of the SDP callabck
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback5(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[5].sdp_oper,
+                     bta_hl_cb.scb[5].app_idx,
+                     bta_hl_cb.scb[5].mcl_idx,
+                     bta_hl_cb.scb[5].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(5);
+}
+
+/******************************************************************************
+**
+** Function         bta_hl_sdp_cback6
+**
+** Description      This is the SDP callback function used by index = 6
+**
+** Returns          void.
+**
+******************************************************************************/
+static void bta_hl_sdp_cback6(UINT16 status)
+{
+    bta_hl_sdp_cback(bta_hl_cb.scb[6].sdp_oper,
+                     bta_hl_cb.scb[6].app_idx,
+                     bta_hl_cb.scb[6].mcl_idx,
+                     bta_hl_cb.scb[6].mdl_idx,
+                     status);
+    bta_hl_deallocate_spd_cback(6);
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_deallocate_spd_cback
+**
+** Description   Deallocate a SDP control block
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+void bta_hl_deallocate_spd_cback(UINT8 sdp_cback_idx)
+{
+    tBTA_HL_SDP_CB *p_spd_cb = &bta_hl_cb.scb[sdp_cback_idx];
+
+    memset(p_spd_cb, 0, sizeof(tBTA_HL_SDP_CB));
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_deallocate_spd_cback index=%d", sdp_cback_idx);
+#endif
+
+
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_allocate_spd_cback
+**
+** Description   Finds a not in used SDP control block index
+**
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+tSDP_DISC_CMPL_CB *bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                                             UINT8 mdl_idx,
+                                             UINT8 *p_sdp_cback_idx)
+{
+    UINT8 i;
+    tSDP_DISC_CMPL_CB *p_cbcak=NULL;
+
+
+    for (i=0; i < BTA_HL_NUM_SDP_CBACKS ; i ++)
+    {
+        if (!bta_hl_cb.scb[i].in_use)
+        {
+            p_cbcak = bta_hl_sdp_cback_arr[i];
+            bta_hl_cb.scb[i].in_use = TRUE;
+            bta_hl_cb.scb[i].sdp_oper = sdp_oper;
+            bta_hl_cb.scb[i].app_idx = app_idx;
+            bta_hl_cb.scb[i].mcl_idx = mcl_idx;
+            bta_hl_cb.scb[i].mdl_idx = mdl_idx;
+            *p_sdp_cback_idx = i;
+            break;
+        }
+    }
+
+    if (i == BTA_HL_NUM_SDP_CBACKS)
+    {
+        APPL_TRACE_WARNING0("No scb is available to allocate")
+    }
+    else
+    {
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_allocate_spd_cback cback_idx=%d ",i );
+    APPL_TRACE_DEBUG4("sdp_oper=%d, app_idx=%d, mcl_idx=%d,  mdl_idx=%d",
+                      bta_hl_cb.scb[i].sdp_oper,
+                      bta_hl_cb.scb[i].app_idx,
+                      bta_hl_cb.scb[i].mcl_idx,
+                      bta_hl_cb.scb[i].mdl_idx );
+#endif
+    }
+    return p_cbcak;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_init_sdp
+**
+** Description      Action routine for processing the SDP initiattion request
+**
+** Returns          void
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                               UINT8 mdl_idx)
+{
+    tBTA_HL_MCL_CB      *p_cb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tSDP_UUID           uuid_list;
+    UINT16              attr_list[BTA_HL_NUM_SRCH_ATTR];
+    UINT16              num_attrs = BTA_HL_NUM_SRCH_ATTR;
+    tBTA_HL_STATUS      status;
+    UINT8               sdp_cback_idx;
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG4("bta_hl_init_sdp sdp_oper=%d app_idx=%d mcl_idx=%d, mdl_idx=%d",
+                      sdp_oper, app_idx, mcl_idx, mdl_idx);
+#endif
+    if ((p_cb->sdp_cback = bta_hl_allocate_spd_cback(sdp_oper, app_idx, mcl_idx, mdl_idx, &sdp_cback_idx)) != NULL)
+    {
+        if ( p_cb->p_db ||
+             (!p_cb->p_db &&
+              (p_cb->p_db = (tSDP_DISCOVERY_DB *) GKI_getbuf(BTA_HL_DISC_SIZE)) != NULL))
+        {
+            attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
+            attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
+            attr_list[2] = ATTR_ID_BT_PROFILE_DESC_LIST;
+            attr_list[3] = ATTR_ID_ADDITION_PROTO_DESC_LISTS;
+            attr_list[4] = ATTR_ID_SERVICE_NAME;
+            attr_list[5] = ATTR_ID_SERVICE_DESCRIPTION;
+            attr_list[6] = ATTR_ID_PROVIDER_NAME;
+            attr_list[7] = ATTR_ID_HDP_SUP_FEAT_LIST;
+            attr_list[8] = ATTR_ID_HDP_DATA_EXCH_SPEC;
+            attr_list[9] = ATTR_ID_HDP_MCAP_SUP_PROC;
+
+
+            uuid_list.len = LEN_UUID_16;
+            uuid_list.uu.uuid16 = UUID_SERVCLASS_HDP_PROFILE;
+
+            SDP_InitDiscoveryDb(p_cb->p_db, BTA_HL_DISC_SIZE, 1, &uuid_list, num_attrs, attr_list);
+
+            if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db, p_cb->sdp_cback))
+            {
+                status = BTA_HL_STATUS_FAIL;
+            }
+            else
+            {
+                status = BTA_HL_STATUS_OK;
+            }
+        }
+        else    /* No services available */
+        {
+            status = BTA_HL_STATUS_NO_RESOURCE;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+    }
+
+    if (status != BTA_HL_STATUS_OK)
+    {
+        utl_freebuf((void **)&p_cb->p_db);
+        if (status != BTA_HL_STATUS_SDP_NO_RESOURCE )
+        {
+            bta_hl_deallocate_spd_cback(sdp_cback_idx);
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_sdp_init
+**
+** Description      Action routine for processing the CCH SDP init event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_sdp_init(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_MCL_CB      *p_cb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_init_sdp");
+#endif
+    if ( p_cb->sdp_oper == BTA_HL_SDP_OP_NONE)
+    {
+        p_cb->sdp_oper = BTA_HL_SDP_OP_CCH_INIT;
+
+        if (bta_hl_init_sdp( p_cb->sdp_oper, app_idx, mcl_idx, 0xFF) != BTA_HL_STATUS_OK)
+        {
+            p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
+            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
+        }
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("SDP in use");
+        bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_mca_open
+**
+** Description      Action routine for processing the CCH open request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_open(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    UINT8               sdp_idx;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_mca_open");
+#endif
+
+    if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->req_ctrl_psm, &sdp_idx))
+    {
+        p_mcb->ctrl_psm = p_mcb->sdp.sdp_rec[sdp_idx].ctrl_psm;
+        p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
+        if ( MCA_ConnectReq((tMCA_HANDLE) p_acb->app_handle,
+                            p_mcb->bd_addr,
+                            p_mcb->ctrl_psm ,
+                            p_mcb->sec_mask) != MCA_SUCCESS)
+        {
+
+            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_mca_close
+**
+** Description      Action routine for processing the CCH close request
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_mca_close");
+#endif
+    if (p_mcb->sdp_oper != BTA_HL_SDP_OP_CCH_INIT)
+    {
+        if ( MCA_DisconnectReq((tMCA_HANDLE) p_acb->app_handle) != MCA_SUCCESS)
+        {
+            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+        }
+    }
+    else
+    {
+        p_mcb->close_pending = TRUE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_close_cmpl
+**
+** Description      Action routine for processing the CCH close complete event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+    tBTA_HL             evt_data;
+    tBTA_HL_EVT         event;
+    BOOLEAN             send_evt=TRUE;
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_close_cmpl");
+#endif
+    bta_sys_conn_close(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
+
+    switch (p_mcb->cch_oper)
+    {
+        case BTA_HL_CCH_OP_LOCAL_OPEN:
+            bta_hl_build_cch_open_cfm(&evt_data, p_acb->app_handle,
+                                      p_mcb->mcl_handle,
+                                      p_mcb->bd_addr,
+                                      BTA_HL_STATUS_FAIL);
+            event = BTA_HL_CCH_OPEN_CFM_EVT;
+            break;
+        case BTA_HL_CCH_OP_LOCAL_CLOSE:
+            bta_hl_build_cch_close_cfm(&evt_data,  p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       BTA_HL_STATUS_OK);
+            event = BTA_HL_CCH_CLOSE_CFM_EVT;
+            break;
+        case BTA_HL_CCH_OP_REMOTE_CLOSE:
+            bta_hl_build_cch_close_ind(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       p_mcb->intentional_close);
+            event = BTA_HL_CCH_CLOSE_IND_EVT;
+            break;
+        default:
+            send_evt=FALSE;
+            break;
+    }
+
+
+    memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+
+    if (send_evt)p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+
+    bta_hl_check_deregistration(app_idx, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_mca_disconnect
+**
+** Description      Action routine for processing the CCH disconnect indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb;
+    UINT8              i;
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_mca_disconnect");
+#endif
+
+    p_mcb->intentional_close = FALSE;
+    if (p_data->mca_evt.mca_data.disconnect_ind.reason == L2CAP_DISC_OK)
+    {
+        p_mcb->intentional_close = TRUE;
+    }
+
+    for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+    {
+        p_dcb= BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, i);
+        if (p_dcb->in_use && (p_dcb->dch_state != BTA_HL_DCH_IDLE_ST))
+        {
+            if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE )
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+            }
+            else
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_MCA_CLOSE_IND_EVT, p_data);
+            }
+        }
+    }
+    bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_mca_rsp_tout
+**
+** Description      Action routine for processing the MCAP response timeout
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_mca_rsp_tout");
+#endif
+
+    p_mcb->rsp_tout = TRUE;
+
+    bta_hl_check_cch_close(app_idx,mcl_idx,p_data,TRUE);
+}
+/*******************************************************************************
+**
+** Function         bta_hl_cch_mca_connect
+**
+** Description      Action routine for processing the CCH connect indication
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL             evt_data;
+    tBTA_HL_EVT         event;
+    BOOLEAN             send_event=TRUE;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_cch_mca_connect");
+#endif
+
+    p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
+    bdcpy(p_mcb->bd_addr, p_data->mca_evt.mca_data.connect_ind.bd_addr);
+    p_mcb->cch_mtu = p_data->mca_evt.mca_data.connect_ind.mtu;
+
+    bta_sys_conn_open(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
+    switch (p_mcb->cch_oper)
+    {
+        case BTA_HL_CCH_OP_LOCAL_OPEN:
+            bta_hl_build_cch_open_cfm(&evt_data, p_acb->app_handle,
+                                      p_mcb->mcl_handle,
+                                      p_mcb->bd_addr,
+                                      BTA_HL_STATUS_OK);
+            event = BTA_HL_CCH_OPEN_CFM_EVT;
+            break;
+        case BTA_HL_CCH_OP_REMOTE_OPEN:
+            bta_hl_build_cch_open_ind(&evt_data, p_acb->app_handle,
+                                      p_mcb->mcl_handle,
+                                      p_mcb->bd_addr);
+            event = BTA_HL_CCH_OPEN_IND_EVT;
+            break;
+        default:
+            send_event = FALSE;
+            break;
+    }
+
+    p_mcb->cch_oper = BTA_HL_CCH_OP_NONE;
+    if (send_event) p_acb->p_cback(event,(tBTA_HL *) &evt_data );
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_mcap_ctrl_cback
+**
+** Description      MCAP control callback function for HL.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_mcap_ctrl_cback (tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
+                             tMCA_CTRL *p_data)
+{
+    tBTA_HL_MCA_EVT * p_msg;
+    BOOLEAN send_event=TRUE;
+    UINT16 mca_event;
+
+#if (BTA_HL_DEBUG == TRUE)
+#if (BT_TRACE_VERBOSE == TRUE)
+    APPL_TRACE_EVENT1("bta_hl_mcap_ctrl_cback event[%s]",bta_hl_mcap_evt_code(event));
+#else
+    APPL_TRACE_EVENT1("bta_hl_mcap_ctrl_cback event[0x%02x]", event);
+#endif
+#endif
+
+    switch (event)
+    {
+
+        case MCA_CREATE_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CREATE_IND_EVT;
+            break;
+        case MCA_CREATE_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CREATE_CFM_EVT;
+            break;
+        case MCA_RECONNECT_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_RECONNECT_IND_EVT;
+            break;
+        case MCA_RECONNECT_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_RECONNECT_CFM_EVT;
+            break;
+        case MCA_ABORT_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_ABORT_IND_EVT;
+            break;
+        case MCA_ABORT_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_ABORT_CFM_EVT;
+            break;
+        case MCA_DELETE_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_DELETE_IND_EVT;
+            break;
+        case MCA_DELETE_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_DELETE_CFM_EVT;
+            break;
+        case MCA_CONNECT_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CONNECT_IND_EVT;
+            break;
+        case MCA_DISCONNECT_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_DISCONNECT_IND_EVT;
+            break;
+        case MCA_OPEN_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_OPEN_IND_EVT;
+            break;
+        case MCA_OPEN_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_OPEN_CFM_EVT;
+            break;
+        case MCA_CLOSE_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CLOSE_IND_EVT;
+            break;
+        case MCA_CLOSE_CFM_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CLOSE_CFM_EVT;
+            break;
+        case MCA_CONG_CHG_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_CONG_CHG_EVT;
+            break;
+        case MCA_RSP_TOUT_IND_EVT:
+            mca_event = (UINT16) BTA_HL_MCA_RSP_TOUT_IND_EVT;
+            break;
+        case MCA_ERROR_RSP_EVT:
+
+        default:
+            send_event=FALSE;
+            break;
+    }
+
+    if ((p_msg = (tBTA_HL_MCA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_EVT))) != NULL)
+    {
+        p_msg->hdr.event = mca_event;
+        p_msg->app_handle = (tBTA_HL_APP_HANDLE) handle;
+        p_msg->mcl_handle = (tBTA_HL_MCL_HANDLE) mcl;
+        memcpy (&p_msg->mca_data, p_data, sizeof(tMCA_CTRL));
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_mcap_data_cback
+**
+** Description      MCAP data callback function for HL.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_mcap_data_cback (tMCA_DL mdl, BT_HDR *p_pkt)
+{
+    tBTA_HL_MCA_RCV_DATA_EVT *p_msg;
+
+    UINT8 app_idx, mcl_idx, mdl_idx;
+    if (bta_hl_find_mdl_idx_using_handle ((tBTA_HL_MDL_HANDLE)mdl, &app_idx, &mcl_idx, &mdl_idx))
+    {
+        if ((p_msg = (tBTA_HL_MCA_RCV_DATA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_RCV_DATA_EVT))) != NULL)
+        {
+            p_msg->hdr.event = BTA_HL_MCA_RCV_DATA_EVT;
+            p_msg->app_idx = app_idx;
+            p_msg->mcl_idx = mcl_idx;
+            p_msg->mdl_idx = mdl_idx;
+            p_msg->p_pkt = p_pkt;
+            bta_sys_sendmsg(p_msg);
+        }
+    }
+}
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE && BT_TRACE_VERBOSE == TRUE)
+
+/*******************************************************************************
+**
+** Function         bta_hl_mcap_evt_code
+**
+** Description      get the MCAP event string pointer
+**
+** Returns          char * - event string pointer
+**
+*******************************************************************************/
+static char *bta_hl_mcap_evt_code(UINT8 evt_code)
+{
+
+    switch (evt_code)
+    {
+
+        case MCA_ERROR_RSP_EVT:
+            return "MCA_ERROR_RSP_EVT";
+        case MCA_CREATE_IND_EVT:
+            return "MCA_CREATE_IND_EVT";
+        case MCA_CREATE_CFM_EVT:
+            return "MCA_CREATE_CFM_EVT";
+        case MCA_RECONNECT_IND_EVT:
+            return "MCA_RECONNECT_IND_EVT";
+        case MCA_RECONNECT_CFM_EVT:
+            return "MCA_RECONNECT_CFM_EVT";
+        case MCA_ABORT_IND_EVT:
+            return "MCA_ABORT_IND_EVT";
+        case MCA_ABORT_CFM_EVT:
+            return "MCA_ABORT_CFM_EVT";
+        case MCA_DELETE_IND_EVT:
+            return "MCA_DELETE_IND_EVT";
+        case MCA_DELETE_CFM_EVT:
+            return "MCA_DELETE_CFM_EVT";
+
+        case MCA_CONNECT_IND_EVT:
+            return "MCA_CONNECT_IND_EVT";
+        case MCA_DISCONNECT_IND_EVT:
+            return "MCA_DISCONNECT_IND_EVT";
+        case MCA_OPEN_IND_EVT:
+            return "MCA_OPEN_IND_EVT";
+        case MCA_OPEN_CFM_EVT:
+            return "MCA_OPEN_CFM_EVT";
+        case MCA_CLOSE_IND_EVT:
+            return "MCA_CLOSE_IND_EVT";
+        case MCA_CLOSE_CFM_EVT:
+            return "MCA_CLOSE_CFM_EVT";
+        case MCA_CONG_CHG_EVT:
+            return "MCA_CONG_CHG_EVT";
+        case MCA_RSP_TOUT_IND_EVT:
+            return "MCA_RSP_TOUT_IND_EVT";
+        default:
+            return "Unknown MCAP event code";
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_cback_evt_code
+**
+** Description      get the HDP event string pointer
+**
+** Returns          char * - event string pointer
+**
+*******************************************************************************/
+static char *bta_hl_cback_evt_code(UINT8 evt_code)
+{
+
+    switch (evt_code)
+    {
+
+        case BTA_HL_CCH_OPEN_IND_EVT:
+            return "BTA_HL_CCH_OPEN_IND_EVT";
+        case BTA_HL_CCH_OPEN_CFM_EVT:
+            return "BTA_HL_CCH_OPEN_CFM_EVT";
+        case BTA_HL_CCH_CLOSE_IND_EVT:
+            return "BTA_HL_CCH_CLOSE_IND_EVT";
+        case     BTA_HL_CCH_CLOSE_CFM_EVT:
+            return "BTA_HL_CCH_CLOSE_CFM_EVT";
+        case BTA_HL_DCH_OPEN_IND_EVT:
+            return "BTA_HL_DCH_OPEN_IND_EVT";
+        case BTA_HL_DCH_OPEN_CFM_EVT:
+            return "BTA_HL_DCH_OPEN_CFM_EVT";
+        case BTA_HL_DCH_CLOSE_IND_EVT:
+            return "BTA_HL_DCH_CLOSE_IND_EVT";
+        case BTA_HL_DCH_CLOSE_CFM_EVT:
+            return "BTA_HL_DCH_CLOSE_CFM_EVT";
+        case BTA_HL_DCH_RCV_DATA_IND_EVT:
+            return "BTA_HL_DCH_RCV_DATA_IND_EVT";
+        case BTA_HL_REGISTER_CFM_EVT:
+            return "BTA_HL_REGISTER_CFM_EVT";
+        case BTA_HL_DEREGISTER_CFM_EVT:
+            return "BTA_HL_DEREGISTER_CFM_EVT";
+        case BTA_HL_DCH_RECONNECT_CFM_EVT:
+            return "BTA_HL_DCH_RECONNECT_CFM_EVT";
+        case BTA_HL_DCH_RECONNECT_IND_EVT:
+            return "BTA_HL_DCH_RECONNECT_IND_EVT";
+        case BTA_HL_DCH_ECHO_TEST_CFM_EVT:
+            return "BTA_HL_DCH_ECHO_TEST_CFM_EVT";
+        case BTA_HL_SDP_QUERY_CFM_EVT:
+            return "BTA_HL_SDP_QUERY_CFM_EVT";
+        case BTA_HL_CONG_CHG_IND_EVT:
+            return "BTA_HL_CONG_CHG_IND_EVT";
+        case BTA_HL_DCH_CREATE_IND_EVT:
+            return "BTA_HL_DCH_CREATE_IND_EVT";
+        case BTA_HL_DELETE_MDL_IND_EVT:
+            return "BTA_HL_DELETE_MDL_IND_EVT";
+        case BTA_HL_DELETE_MDL_CFM_EVT:
+            return "BTA_HL_DELETE_MDL_CFM_EVT";
+        case BTA_HL_DCH_ABORT_IND_EVT:
+            return "BTA_HL_DCH_ABORT_IND_EVT";
+        case BTA_HL_DCH_ABORT_CFM_EVT:
+            return "BTA_HL_DCH_ABORT_CFM_EVT";
+        default:
+            return "Unknown HDP event code";
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_oper_code
+**
+** Description      Get the DCH operation string
+**
+** Returns          char * - DCH operation string pointer
+**
+*******************************************************************************/
+static char *bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code)
+{
+
+    switch (oper_code)
+    {
+        case BTA_HL_DCH_OP_NONE:
+            return "BTA_HL_DCH_OP_NONE";
+        case BTA_HL_DCH_OP_REMOTE_CREATE:
+            return "BTA_HL_DCH_OP_REMOTE_CREATE";
+        case BTA_HL_DCH_OP_LOCAL_OPEN:
+            return "BTA_HL_DCH_OP_LOCAL_OPEN";
+        case BTA_HL_DCH_OP_REMOTE_OPEN:
+            return "BTA_HL_DCH_OP_REMOTE_OPEN";
+        case BTA_HL_DCH_OP_LOCAL_CLOSE:
+            return "BTA_HL_DCH_OP_LOCAL_CLOSE";
+        case BTA_HL_DCH_OP_REMOTE_CLOSE:
+            return "BTA_HL_DCH_OP_REMOTE_CLOSE";
+        case BTA_HL_DCH_OP_LOCAL_DELETE:
+            return "BTA_HL_DCH_OP_LOCAL_DELETE";
+        case BTA_HL_DCH_OP_REMOTE_DELETE:
+            return "BTA_HL_DCH_OP_REMOTE_DELETE";
+        case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+            return "BTA_HL_DCH_OP_LOCAL_RECONNECT";
+        case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+            return "BTA_HL_DCH_OP_REMOTE_RECONNECT";
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
+            return "BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST";
+        case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
+            return "BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT";
+        default:
+            return "Unknown DCH oper code";
+    }
+}
+
+
+#endif  /* Debug Functions */
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_api.c b/bta/hl/bta_hl_api.c
new file mode 100644
index 0000000..8c8d621
--- /dev/null
+++ b/bta/hl/bta_hl_api.c
@@ -0,0 +1,485 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the implementation of the API for the HeaLth device profile (HL)
+ *  subsystem of BTA, Broadcom Corp's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "gki.h"
+#include "bd.h"
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_hl_reg =
+{
+    bta_hl_hdl_event,
+    BTA_HlDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_HlEnable
+**
+** Description      Enable the HL subsystems.  This function must be
+**                  called before any other functions in the HL API are called.
+**                  When the enable operation is completed the callback function
+**                  will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
+**
+** Parameters       p_cback - HL event call back function
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlEnable(tBTA_HL_CTRL_CBACK *p_ctrl_cback)
+{
+    tBTA_HL_API_ENABLE *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_HL, &bta_hl_reg);
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_HL_API_ENABLE *)GKI_getbuf(sizeof(tBTA_HL_API_ENABLE))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_HL_API_ENABLE_EVT;
+        p_buf->p_cback      = p_ctrl_cback;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDisable
+**
+** Description     Disable the HL subsystem.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    bta_sys_deregister(BTA_ID_HL);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_HL_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlRegister
+**
+** Description      Register an HDP application
+**
+** Parameters       app_id        - Application ID
+**                  p_reg_param   - non-platform related parameters for the
+**                                  HDP application
+**                  p_cback       - HL event callback fucntion
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlRegister(UINT8  app_id,
+                    tBTA_HL_REG_PARAM *p_reg_param,
+                    tBTA_HL_CBACK *p_cback)
+{
+    tBTA_HL_API_REGISTER *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_REGISTER *)GKI_getbuf((UINT16)sizeof(tBTA_HL_API_REGISTER))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_HL_API_REGISTER_EVT;
+        p_buf->app_id       = app_id;
+        p_buf->sec_mask     = (p_reg_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+        p_buf->p_cback = p_cback;
+        if (p_reg_param->p_srv_name)
+        {
+            BCM_STRNCPY_S(p_buf->srv_name, sizeof(p_buf->srv_name),
+                          p_reg_param->p_srv_name, BTA_SERVICE_NAME_LEN);
+            p_buf->srv_name[BTA_SERVICE_NAME_LEN] = '\0';
+        }
+        else
+            p_buf->srv_name[0]= '\0';
+
+        if (p_reg_param->p_srv_desp)
+        {
+            BCM_STRNCPY_S(p_buf->srv_desp, sizeof(p_buf->srv_desp),
+                          p_reg_param->p_srv_desp, BTA_SERVICE_DESP_LEN);
+            p_buf->srv_desp[BTA_SERVICE_DESP_LEN]= '\0';
+        }
+        else
+            p_buf->srv_desp[0]= '\0';
+
+        if (p_reg_param->p_provider_name)
+        {
+            BCM_STRNCPY_S(p_buf->provider_name, sizeof(p_buf->provider_name),
+                          p_reg_param->p_provider_name, BTA_PROVIDER_NAME_LEN);
+            p_buf->provider_name[BTA_PROVIDER_NAME_LEN]= '\0';
+        }
+        else
+            p_buf->provider_name[0]= '\0';
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDeregister
+**
+** Description      Deregister an HDP application
+**
+** Parameters       app_handle - Application handle
+**
+** Returns           void
+**
+*******************************************************************************/
+void BTA_HlDeregister(tBTA_HL_APP_HANDLE app_handle)
+{
+    tBTA_HL_API_DEREGISTER  *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DEREGISTER *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DEREGISTER)))) != NULL)
+    {
+        p_buf->hdr.event   = BTA_HL_API_DEREGISTER_EVT;
+        p_buf->app_handle  = app_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+/*******************************************************************************
+**
+** Function         BTA_HlCchOpen
+**
+** Description      Open a Control channel connection with the specified BD address
+**
+** Parameters       app_handle - Application Handle
+**                  p_open_param - parameters for opening a control channel
+**
+** Returns          void
+**
+**                  Note: The control PSM value is used to select which
+**                  HDP insatnce should be used in case the peer device support
+**                  multiple HDP instances. Also, if the control PSM value is zero
+**                  then the first HDP instance is used for the control channel setup
+*******************************************************************************/
+void BTA_HlCchOpen(tBTA_HL_APP_HANDLE app_handle,
+                   tBTA_HL_CCH_OPEN_PARAM *p_open_param)
+{
+    tBTA_HL_API_CCH_OPEN *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_CCH_OPEN *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_CCH_OPEN)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_CCH_OPEN_EVT;
+        p_buf->app_handle       = app_handle;
+        p_buf->sec_mask = (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+        bdcpy(p_buf->bd_addr, p_open_param->bd_addr);
+        p_buf->ctrl_psm       = p_open_param->ctrl_psm;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlCchClose
+**
+** Description      Close a Control channel connection with the specified MCL
+**                  handle
+**
+** Parameters       mcl_handle - MCL handle
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle)
+{
+    tBTA_HL_API_CCH_CLOSE *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_CCH_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_CCH_CLOSE)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_CCH_CLOSE_EVT;
+        p_buf->mcl_handle       = mcl_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchOpen
+**
+** Description      Open a data channel connection with the specified DCH parameters
+**
+** Parameters       mcl_handle - MCL handle
+**                  p_open_param - parameters for opening a data channel
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
+                   tBTA_HL_DCH_OPEN_PARAM *p_open_param)
+{
+    tBTA_HL_API_DCH_OPEN *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_OPEN *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_OPEN)))) != NULL)
+    {
+        p_buf->hdr.event            = BTA_HL_API_DCH_OPEN_EVT;
+        p_buf->mcl_handle           = mcl_handle;
+        p_buf->ctrl_psm             = p_open_param->ctrl_psm;
+        p_buf->local_mdep_id        = p_open_param->local_mdep_id;
+        p_buf->peer_mdep_id         = p_open_param->peer_mdep_id;
+        p_buf->local_cfg            = p_open_param->local_cfg;
+        p_buf->sec_mask             = (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchReconnect
+**
+** Description      Reconnect a data channel with the specified MDL_ID
+**
+** Parameters       mcl_handle      - MCL handle
+*8                  p_recon_param   - parameters for reconnecting a data channel
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
+                        tBTA_HL_DCH_RECONNECT_PARAM *p_recon_param)
+{
+    tBTA_HL_API_DCH_RECONNECT *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_RECONNECT *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_RECONNECT)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_DCH_RECONNECT_EVT;
+        p_buf->mcl_handle       = mcl_handle;
+        p_buf->ctrl_psm         = p_recon_param->ctrl_psm;
+        p_buf->mdl_id           = p_recon_param->mdl_id;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchClose
+**
+** Description      Close a data channel with the specified MDL handle
+**
+** Parameters       mdl_handle  - MDL handle
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle)
+{
+    tBTA_HL_API_DCH_CLOSE *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_CLOSE *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_CLOSE)))) != NULL)
+    {
+        p_buf->hdr.event    = BTA_HL_API_DCH_CLOSE_EVT;
+        p_buf->mdl_handle   = mdl_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchAbort
+**
+** Description      Abort the current data channel setup with the specified MCL
+**                  handle
+**
+** Parameters       mcl_handle  - MCL handle
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle)
+{
+    tBTA_HL_API_DCH_ABORT *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_ABORT *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_ABORT)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_DCH_ABORT_EVT;
+        p_buf->mcl_handle       = mcl_handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlSendData
+**
+** Description      Send an APDU to the peer device
+**
+** Parameters       mdl_handle  - MDL handle
+**                  pkt_size    - size of the data packet to be sent
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle,
+                    UINT16           pkt_size)
+{
+    tBTA_HL_API_SEND_DATA *p_buf = NULL;
+
+    if ((p_buf = (tBTA_HL_API_SEND_DATA *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_SEND_DATA)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_SEND_DATA_EVT;
+        p_buf->mdl_handle       = mdl_handle;
+        p_buf->pkt_size         = pkt_size;
+        bta_sys_sendmsg(p_buf);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDeleteMdl
+**
+** Description      Delete the specified MDL_ID within the specified MCL handle
+**
+** Parameters       mcl_handle  - MCL handle
+**                  mdl_id      - MDL ID
+**
+** Returns          void
+**
+**                  note: If mdl_id = 0xFFFF then this means to delete all MDLs
+**                        and this value can only be used with DeleteMdl request only
+**                        not other requests
+**
+*******************************************************************************/
+void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle,
+                     tBTA_HL_MDL_ID mdl_id )
+{
+    tBTA_HL_API_DELETE_MDL *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DELETE_MDL *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DELETE_MDL)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_DELETE_MDL_EVT;
+        p_buf->mcl_handle       = mcl_handle;
+        p_buf->mdl_id           = mdl_id;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchEchoTest
+**
+** Description      Initiate an echo test with the specified MCL handle
+**
+** Parameters       mcl_handle           - MCL handle
+*8                  p_echo_test_param   -  parameters for echo testing
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchEchoTest( tBTA_HL_MCL_HANDLE  mcl_handle,
+                        tBTA_HL_DCH_ECHO_TEST_PARAM *p_echo_test_param)
+{
+    tBTA_HL_API_DCH_ECHO_TEST   *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_ECHO_TEST *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_ECHO_TEST)))) != NULL)
+    {
+        p_buf->hdr.event     = BTA_HL_API_DCH_ECHO_TEST_EVT;
+        p_buf->mcl_handle    = mcl_handle;
+        p_buf->ctrl_psm      = p_echo_test_param->ctrl_psm;
+        p_buf->local_cfg     = p_echo_test_param->local_cfg;
+        p_buf->pkt_size      = p_echo_test_param->pkt_size;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_HlSdpQuery
+**
+** Description      SDP query request for the specified BD address
+**
+** Parameters       app_handle      - application handle
+**                  bd_addr         - BD address
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlSdpQuery(tBTA_HL_APP_HANDLE app_handle,
+                    BD_ADDR bd_addr)
+{
+    tBTA_HL_API_SDP_QUERY *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_SDP_QUERY *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_SDP_QUERY)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_SDP_QUERY_EVT;
+        p_buf->app_handle       = app_handle;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchCreateMdlRsp
+**
+** Description      Set the Response and configuration values for the Create MDL
+**                  request
+**
+** Parameters       mcl_handle  - MCL handle
+**                  p_rsp_param - parameters specified whether the request should
+**                                be accepted or not and if it should be accepted
+**                                then it also specified the configuration response
+**                                value
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
+                        tBTA_HL_DCH_CREATE_RSP_PARAM *p_rsp_param)
+{
+    tBTA_HL_API_DCH_CREATE_RSP *p_buf;
+
+    if ((p_buf = (tBTA_HL_API_DCH_CREATE_RSP *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_API_DCH_CREATE_RSP)))) != NULL)
+    {
+        p_buf->hdr.event        = BTA_HL_API_DCH_CREATE_RSP_EVT;
+        p_buf->mcl_handle       = mcl_handle;
+        p_buf->mdl_id           = p_rsp_param->mdl_id;
+        p_buf->local_mdep_id    = p_rsp_param->local_mdep_id;
+        p_buf->rsp_code         = p_rsp_param->rsp_code;
+        p_buf->cfg_rsp          = p_rsp_param->cfg_rsp;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_ci.c b/bta/hl/bta_hl_ci.c
new file mode 100644
index 0000000..bd04b44
--- /dev/null
+++ b/bta/hl/bta_hl_ci.c
@@ -0,0 +1,171 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the implementation file for the HeaLth device profile (HL)
+ *  subsystem call-in functions.
+ *
+ ******************************************************************************/
+#include "bta_api.h"
+#include "btm_api.h"
+#include "bta_sys.h"
+#include "bta_hl_api.h"
+#include "bta_hl_co.h"
+#include "bta_hl_int.h"
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_get_tx_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_get_tx_data call-out function.
+**
+** Parameters       mdl_handle -MDL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_tx_data(  tBTA_HL_MDL_HANDLE mdl_handle,
+                                            tBTA_HL_STATUS status,
+                                            UINT16 evt )
+{
+    tBTA_HL_CI_GET_PUT_DATA  *p_evt;
+
+#if  (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG3("bta_hl_ci_get_tx_data mdl_handle=%d status=%d evt=%d\n",
+                      mdl_handle, status, evt);
+#endif
+
+    if ((p_evt = (tBTA_HL_CI_GET_PUT_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_GET_PUT_DATA))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->mdl_handle =  mdl_handle;
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_put_rx_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_put_rx_data call-out function.
+**
+** Parameters       mdl_handle -MDL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_rx_data(  tBTA_HL_MDL_HANDLE mdl_handle,
+                                            tBTA_HL_STATUS status,
+                                            UINT16 evt )
+{
+    tBTA_HL_CI_GET_PUT_DATA  *p_evt;
+#if  (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG3("bta_hl_ci_put_rx_data mdl_handle=%d status=%d evt=%d\n",
+                      mdl_handle, status, evt);
+#endif
+
+    if ((p_evt = (tBTA_HL_CI_GET_PUT_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_GET_PUT_DATA))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->mdl_handle =  mdl_handle;
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_get_echo_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_get_echo_data call-out function.
+**
+** Parameters       mcl_handle -MCL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_get_echo_data(  tBTA_HL_MCL_HANDLE mcl_handle,
+                                              tBTA_HL_STATUS status,
+                                              UINT16 evt )
+{
+    tBTA_HL_CI_ECHO_DATA  *p_evt;
+
+#if  (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG3("bta_hl_ci_get_echo_data mcl_handle=%d status=%d evt=%d\n",
+                      mcl_handle, status, evt);
+#endif
+
+    if ((p_evt = (tBTA_HL_CI_ECHO_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_ECHO_DATA))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->mcl_handle =  mcl_handle;
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_put_echo_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_put_echo_data call-out function.
+**
+** Parameters       mcl_handle -MCL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_echo_data(  tBTA_HL_MCL_HANDLE mcl_handle,
+                                              tBTA_HL_STATUS status,
+                                              UINT16 evt )
+{
+    tBTA_HL_CI_ECHO_DATA  *p_evt;
+
+#if  (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG3("bta_hl_ci_put_echo_data mcl_handle=%d status=%d evt=%d\n",
+                      mcl_handle, status, evt);
+#endif
+
+    if ((p_evt = (tBTA_HL_CI_ECHO_DATA *)GKI_getbuf(sizeof(tBTA_HL_CI_ECHO_DATA))) != NULL)
+    {
+        p_evt->hdr.event = evt;
+        p_evt->mcl_handle =  mcl_handle;
+        p_evt->status = status;
+        bta_sys_sendmsg(p_evt);
+    }
+}
+
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
new file mode 100644
index 0000000..648eb2c
--- /dev/null
+++ b/bta/hl/bta_hl_int.h
@@ -0,0 +1,858 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1998-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 is the private file for the message access equipment (MSE)
+ *  subsystem.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_INT_H
+#define BTA_HL_INT_H
+
+#include "bt_target.h"
+#include "bta_sys.h"
+#include "obx_api.h"
+#include "bta_hl_api.h"
+#include "bta_hl_co.h"
+#include "l2cdefs.h"
+
+
+typedef UINT16 (tBTA_HL_ALLOCATE_PSM) (void);
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+#ifndef BTA_HL_DISC_SIZE
+#define BTA_HL_DISC_SIZE                1600
+#endif
+#define BTA_HL_NUM_SRCH_ATTR            10
+#define BTA_HL_MIN_SDP_MDEP_LEN         7
+
+/* L2CAP defualt parameters */
+#define BTA_HL_L2C_TX_WIN_SIZE          10
+#define BTA_HL_L2C_MAX_TRANSMIT         32
+#define BTA_HL_L2C_RTRANS_TOUT          2000
+#define BTA_HL_L2C_MON_TOUT             12000
+#define BTA_HL_L2C_MPS                  1017
+#define BTA_HL_L2C_USER_RX_POOL_ID      L2CAP_DEFAULT_ERM_POOL_ID
+#define BTA_HL_L2C_USER_TX_POOL_ID      L2CAP_DEFAULT_ERM_POOL_ID /* todo this should be based on data type */
+#define BTA_HL_L2C_FCR_RX_POOL_ID       L2CAP_DEFAULT_ERM_POOL_ID
+#define BTA_HL_L2C_FCR_TX_POOL_ID       L2CAP_DEFAULT_ERM_POOL_ID
+
+/* L2CAP FCS setting*/
+#define BTA_HL_MCA_USE_FCS              MCA_FCS_USE
+#define BTA_HL_MCA_NO_FCS               MCA_FCS_BYPASS
+#define BTA_HL_L2C_USE_FCS              1
+#define BTA_HL_L2C_NO_FCS               0
+#define BTA_HL_DEFAULT_SOURCE_FCS       BTA_HL_L2C_USE_FCS
+
+/* SDP Operations */
+#define BTA_HL_SDP_OP_NONE                  0
+#define BTA_HL_SDP_OP_CCH_INIT              1
+#define BTA_HL_SDP_OP_DCH_OPEN_INIT         2
+#define BTA_HL_SDP_OP_DCH_RECONNECT_INIT    3
+#define BTA_HL_SDP_OP_SDP_QUERY_NEW         4
+#define BTA_HL_SDP_OP_SDP_QUERY_CURRENT     5
+
+typedef UINT8 tBTA_HL_SDP_OPER;
+
+/* CCH Operations */
+#define     BTA_HL_CCH_OP_NONE            0
+#define     BTA_HL_CCH_OP_LOCAL_OPEN      1
+#define     BTA_HL_CCH_OP_REMOTE_OPEN     2
+#define     BTA_HL_CCH_OP_LOCAL_CLOSE     3
+#define     BTA_HL_CCH_OP_REMOTE_CLOSE    4
+
+typedef UINT8 tBTA_HL_CCH_OPER;
+
+/* Pending DCH close operations when closing a CCH */
+#define    BTA_HL_CCH_CLOSE_OP_DCH_NONE     0
+#define    BTA_HL_CCH_CLOSE_OP_DCH_ABORT    1
+#define    BTA_HL_CCH_CLOSE_OP_DCH_CLOSE    2
+typedef UINT8 tBTA_HL_CCH_CLOSE_DCH_OPER;
+
+/* DCH Operations */
+#define    BTA_HL_DCH_OP_NONE                    0
+#define    BTA_HL_DCH_OP_REMOTE_CREATE           1
+#define    BTA_HL_DCH_OP_LOCAL_OPEN              2
+#define    BTA_HL_DCH_OP_REMOTE_OPEN             3
+#define    BTA_HL_DCH_OP_LOCAL_CLOSE             4
+#define    BTA_HL_DCH_OP_REMOTE_CLOSE            5
+#define    BTA_HL_DCH_OP_LOCAL_DELETE            6
+#define    BTA_HL_DCH_OP_REMOTE_DELETE           7
+#define    BTA_HL_DCH_OP_LOCAL_RECONNECT         8
+#define    BTA_HL_DCH_OP_REMOTE_RECONNECT        9
+#define    BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST   10
+#define    BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT   11
+
+typedef UINT8 tBTA_HL_DCH_OPER;
+
+/* Echo test Operations */
+#define    BTA_HL_ECHO_OP_NONE                 0
+#define    BTA_HL_ECHO_OP_CI_GET_ECHO_DATA     1
+#define    BTA_HL_ECHO_OP_SDP_INIT             2
+#define    BTA_HL_ECHO_OP_MDL_CREATE_CFM       3
+#define    BTA_HL_ECHO_OP_DCH_OPEN_CFM         4
+#define    BTA_HL_ECHO_OP_LOOP_BACK            5
+#define    BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA     6
+#define    BTA_HL_ECHO_OP_DCH_CLOSE_CFM        7
+#define    BTA_HL_ECHO_OP_OPEN_IND             8
+#define    BTA_HL_ECHO_OP_ECHO_PKT             9
+
+typedef UINT8 tBTA_HL_ECHO_OPER;
+
+/* abort status mask for abort_oper */
+
+#define BTA_HL_ABORT_NONE_MASK      0x00
+#define BTA_HL_ABORT_PENDING_MASK   0x01
+#define BTA_HL_ABORT_LOCAL_MASK     0x10
+#define BTA_HL_ABORT_REMOTE_MASK    0x20
+#define BTA_HL_ABORT_CCH_CLOSE_MASK 0x40
+
+/* call out mask for cout_oper */
+#define BTA_HL_CO_NONE_MASK          0x00
+#define BTA_HL_CO_GET_TX_DATA_MASK   0x01
+#define BTA_HL_CO_PUT_RX_DATA_MASK   0x02
+#define BTA_HL_CO_GET_ECHO_DATA_MASK 0x04
+#define BTA_HL_CO_PUT_ECHO_DATA_MASK 0x08
+
+typedef struct
+{
+    UINT16      mtu;
+    UINT8       fcs;                    /* '0' No FCS, otherwise '1' */
+} tBTA_HL_L2CAP_CFG_INFO;
+
+
+/* State Machine Events */
+enum
+{
+    /* these events are handled by the state machine */
+    BTA_HL_CCH_OPEN_EVT     = BTA_SYS_EVT_START(BTA_ID_HL),
+    BTA_HL_CCH_SDP_OK_EVT,
+    BTA_HL_CCH_SDP_FAIL_EVT,
+    BTA_HL_MCA_CONNECT_IND_EVT,
+    BTA_HL_MCA_DISCONNECT_IND_EVT,
+    BTA_HL_CCH_CLOSE_EVT,
+    BTA_HL_CCH_CLOSE_CMPL_EVT,
+    BTA_HL_MCA_RSP_TOUT_IND_EVT,
+    /* DCH EVENT */
+    BTA_HL_DCH_SDP_INIT_EVT,
+    BTA_HL_DCH_OPEN_EVT,
+    BTA_HL_MCA_CREATE_IND_EVT,
+    BTA_HL_MCA_CREATE_CFM_EVT,
+    BTA_HL_MCA_OPEN_IND_EVT,
+
+    BTA_HL_MCA_OPEN_CFM_EVT,
+    BTA_HL_DCH_CLOSE_EVT,
+    BTA_HL_MCA_CLOSE_IND_EVT,
+    BTA_HL_MCA_CLOSE_CFM_EVT,
+    BTA_HL_API_SEND_DATA_EVT,
+
+    BTA_HL_MCA_RCV_DATA_EVT,
+    BTA_HL_DCH_CLOSE_CMPL_EVT,
+    BTA_HL_DCH_RECONNECT_EVT,
+    BTA_HL_DCH_SDP_FAIL_EVT,
+    BTA_HL_MCA_RECONNECT_IND_EVT,
+
+    BTA_HL_MCA_RECONNECT_CFM_EVT,
+    BTA_HL_DCH_CLOSE_ECHO_TEST_EVT,
+    BTA_HL_API_DCH_CREATE_RSP_EVT,
+    BTA_HL_DCH_ABORT_EVT,
+    BTA_HL_MCA_ABORT_IND_EVT,
+
+    BTA_HL_MCA_ABORT_CFM_EVT,
+    BTA_HL_MCA_CONG_CHG_EVT,
+    BTA_HL_CI_GET_TX_DATA_EVT,
+    BTA_HL_CI_PUT_RX_DATA_EVT,
+    BTA_HL_CI_GET_ECHO_DATA_EVT,
+    BTA_HL_DCH_ECHO_TEST_EVT,
+    BTA_HL_CI_PUT_ECHO_DATA_EVT,
+
+    /* these events are handled outside the state machine */
+    BTA_HL_API_ENABLE_EVT,
+    BTA_HL_API_DISABLE_EVT,
+    BTA_HL_API_REGISTER_EVT,
+    BTA_HL_API_DEREGISTER_EVT,
+    BTA_HL_API_CCH_OPEN_EVT,
+    BTA_HL_API_CCH_CLOSE_EVT,
+    BTA_HL_API_DCH_OPEN_EVT,
+    BTA_HL_API_DCH_RECONNECT_EVT,
+    BTA_HL_API_DCH_CLOSE_EVT,
+    BTA_HL_API_DELETE_MDL_EVT,
+    BTA_HL_API_DCH_ABORT_EVT,
+
+    BTA_HL_API_DCH_ECHO_TEST_EVT,
+    BTA_HL_API_SDP_QUERY_EVT,
+    BTA_HL_SDP_QUERY_OK_EVT,
+    BTA_HL_SDP_QUERY_FAIL_EVT,
+    BTA_HL_MCA_DELETE_IND_EVT,
+    BTA_HL_MCA_DELETE_CFM_EVT
+};
+typedef UINT16 tBTA_HL_INT_EVT;
+
+#define BTA_HL_DCH_EVT_MIN BTA_HL_DCH_SDP_INIT_EVT
+#define BTA_HL_DCH_EVT_MAX 0xFFFF
+
+
+/* state machine states */
+enum
+{
+    BTA_HL_CCH_IDLE_ST = 0,      /* Idle  */
+    BTA_HL_CCH_OPENING_ST,       /* Opening a connection*/
+    BTA_HL_CCH_OPEN_ST,          /* Connection is open */
+    BTA_HL_CCH_CLOSING_ST        /* Closing is in progress */
+};
+typedef UINT8 tBTA_HL_CCH_STATE;
+
+enum
+{
+    BTA_HL_DCH_IDLE_ST = 0,      /* Idle  */
+    BTA_HL_DCH_OPENING_ST,       /* Opening a connection*/
+    BTA_HL_DCH_OPEN_ST,          /* Connection is open */
+    BTA_HL_DCH_CLOSING_ST        /* Closing is in progress */
+};
+typedef UINT8 tBTA_HL_DCH_STATE;
+
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_HL_CTRL_CBACK  *p_cback;        /* pointer to control callback function */
+} tBTA_HL_API_ENABLE;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT8               app_id;
+    tBTA_HL_CBACK       *p_cback;        /* pointer to application callback function */
+    tBTA_HL_DEVICE_TYPE dev_type;           /* sink, source or dual roles */
+    tBTA_SEC            sec_mask;           /* security mask for accepting conenction*/
+    char                srv_name[BTA_SERVICE_NAME_LEN +1];        /* service name to be used in the SDP; null terminated*/
+    char                srv_desp[BTA_SERVICE_DESP_LEN +1];        /* service description to be used in the SDP; null terminated */
+    char                provider_name[BTA_PROVIDER_NAME_LEN +1];   /* provide name to be used in the SDP; null terminated */
+} tBTA_HL_API_REGISTER;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_API_DEREGISTER;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_APP_HANDLE      app_handle;
+    UINT16                  ctrl_psm;
+    BD_ADDR                 bd_addr;        /* Address of peer device */
+    tBTA_SEC                sec_mask;       /* security mask for initiating connection*/
+} tBTA_HL_API_CCH_OPEN;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+} tBTA_HL_API_CCH_CLOSE;
+
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    UINT16                  ctrl_psm;
+    tBTA_HL_MDEP_ID         local_mdep_id;     /* local MDEP ID */
+    tBTA_HL_MDEP_ID         peer_mdep_id;      /* peer mdep id */
+    tBTA_HL_DCH_CFG         local_cfg;
+    tBTA_SEC                sec_mask;          /* security mask for initiating connection*/
+} tBTA_HL_API_DCH_OPEN;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    UINT16                  ctrl_psm;
+    tBTA_HL_MDL_ID          mdl_id;
+} tBTA_HL_API_DCH_RECONNECT;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+} tBTA_HL_API_DCH_CLOSE;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_MDL_ID          mdl_id;
+} tBTA_HL_API_DELETE_MDL;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_HL_MCL_HANDLE mcl_handle;
+} tBTA_HL_API_DCH_ABORT;
+
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_HL_MDL_HANDLE  mdl_handle;
+    UINT16              pkt_size;
+} tBTA_HL_API_SEND_DATA;
+
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_HL_MCL_HANDLE  mcl_handle;
+    UINT16              ctrl_psm;
+    UINT16              pkt_size;
+    tBTA_HL_DCH_CFG     local_cfg;
+} tBTA_HL_API_DCH_ECHO_TEST;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   app_idx;
+    UINT8                   mcl_idx;
+    BOOLEAN                 release_mcl_cb;
+}tBTA_HL_CCH_SDP;
+
+
+/* MCA callback event parameters. */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_HL_APP_HANDLE  app_handle;
+    tBTA_HL_MCL_HANDLE  mcl_handle;
+    tMCA_CTRL       mca_data;
+} tBTA_HL_MCA_EVT;
+
+
+/* MCA callback event parameters. */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT8           app_idx;
+    UINT8           mcl_idx;
+    UINT8           mdl_idx;
+    BT_HDR          *p_pkt;
+} tBTA_HL_MCA_RCV_DATA_EVT;
+
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT8                   app_idx;
+    UINT8                   mcl_idx;
+    UINT8                   mdl_idx;
+}tBTA_HL_DCH_SDP;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_APP_HANDLE      app_handle;
+    BD_ADDR                 bd_addr;        /* Address of peer device */
+} tBTA_HL_API_SDP_QUERY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_MDL_ID          mdl_id;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    tBTA_HL_DCH_CREATE_RSP  rsp_code;
+    tBTA_HL_DCH_CFG         cfg_rsp;
+} tBTA_HL_API_DCH_CREATE_RSP;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_STATUS          status;
+} tBTA_HL_CI_GET_PUT_DATA;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_STATUS          status;
+} tBTA_HL_CI_ECHO_DATA;
+
+/* union of all state machine event data types */
+typedef union
+{
+    BT_HDR                      hdr;
+    tBTA_HL_API_ENABLE          api_enable; /* data for BTA_MSE_API_ENABLE_EVT */
+    tBTA_HL_API_REGISTER        api_reg;
+    tBTA_HL_API_DEREGISTER      api_dereg;
+    tBTA_HL_API_CCH_OPEN        api_cch_open;
+    tBTA_HL_API_CCH_CLOSE       api_cch_close;
+    tBTA_HL_API_DCH_CREATE_RSP  api_dch_create_rsp;
+    tBTA_HL_API_DCH_OPEN        api_dch_open;
+    tBTA_HL_API_DCH_RECONNECT   api_dch_reconnect;
+    tBTA_HL_API_DCH_CLOSE       api_dch_close;
+    tBTA_HL_API_DELETE_MDL      api_delete_mdl;
+    tBTA_HL_API_DCH_ABORT       api_dch_abort;
+    tBTA_HL_API_SEND_DATA       api_send_data;
+    tBTA_HL_API_DCH_ECHO_TEST   api_dch_echo_test;
+    tBTA_HL_API_SDP_QUERY       api_sdp_query;
+
+    tBTA_HL_CCH_SDP             cch_sdp;
+    tBTA_HL_MCA_EVT             mca_evt;
+    tBTA_HL_MCA_RCV_DATA_EVT    mca_rcv_data_evt;
+    tBTA_HL_DCH_SDP             dch_sdp; /* for DCH_OPEN_EVT and DCH_RECONNECT_EVT */
+    tBTA_HL_CI_GET_PUT_DATA     ci_get_put_data;
+    tBTA_HL_CI_ECHO_DATA        ci_get_put_echo_data;
+} tBTA_HL_DATA;
+
+
+typedef struct
+{
+    BOOLEAN                 in_use;
+    UINT16                  mdl_id;
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_DCH_OPER        dch_oper;
+    BOOLEAN                 intentional_close;
+    tBTA_HL_DCH_STATE       dch_state;
+    UINT8                   abort_oper;
+    UINT16                  req_data_psm;
+    UINT16                  max_rx_apdu_size;
+    UINT16                  max_tx_apdu_size;
+    BT_HDR                  *p_tx_pkt;
+    BT_HDR                  *p_rx_pkt;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    UINT8                   local_mdep_cfg_idx;
+    tBTA_HL_DCH_CFG         local_cfg;
+    tBTA_HL_DCH_CFG         remote_cfg;
+    tBTA_HL_MDEP_ID         peer_mdep_id;
+    UINT16  peer_data_type;
+    tBTA_HL_MDEP_ROLE       peer_mdep_role;
+    tBTA_HL_DCH_MODE        dch_mode;
+    tBTA_SEC                sec_mask;
+    BOOLEAN                 is_the_first_reliable;
+    BOOLEAN                 delete_mdl;
+    UINT16                  mtu;
+    tMCA_CHNL_CFG           chnl_cfg;
+    BOOLEAN                 mdl_cfg_idx_included;
+    UINT8                   mdl_cfg_idx;
+    UINT8                   echo_oper;
+    BOOLEAN                 cong;
+    BOOLEAN                 close_pending;
+    UINT8                   cout_oper;
+    BT_HDR                  *p_echo_tx_pkt;
+    BT_HDR                  *p_echo_rx_pkt;
+    tBTA_HL_STATUS          ci_put_echo_data_status;
+}tBTA_HL_MDL_CB;
+
+typedef struct
+{
+    tBTA_HL_MDL_CB          mdl[BTA_HL_NUM_MDLS_PER_MCL];
+    tBTA_HL_DELETE_MDL      delete_mdl;
+    BOOLEAN                 in_use;
+    tBTA_HL_CCH_STATE       cch_state;
+    UINT16                  req_ctrl_psm;
+    UINT16                  ctrl_psm;
+    UINT16                  data_psm;
+    BD_ADDR                 bd_addr;
+    UINT16                  cch_mtu;
+    UINT16                  sec_mask;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tSDP_DISCOVERY_DB       *p_db;         /* pointer to discovery database */
+    tSDP_DISC_CMPL_CB       *sdp_cback;
+    tBTA_HL_SDP_OPER        sdp_oper;
+    BOOLEAN                 close_pending;
+    UINT8                   sdp_mdl_idx;
+    tBTA_HL_SDP             sdp;
+    UINT8                   cch_oper;
+    BOOLEAN                 intentional_close;
+    BOOLEAN                 rsp_tout;
+    UINT8                   timer_oper;
+    BOOLEAN                 echo_test;
+    UINT8                   echo_mdl_idx;
+    UINT8                   cch_close_dch_oper;
+}tBTA_HL_MCL_CB;
+
+typedef struct
+{
+    tBTA_HL_MCL_CB       mcb[BTA_HL_NUM_MCLS]; /* application Control Blocks */
+    tBTA_HL_CBACK        *p_cback;            /* pointer to control callback function */
+    BOOLEAN              in_use;              /* this CB is in use*/
+    BOOLEAN              deregistering;
+    UINT8                app_id;
+    UINT32               sdp_handle;    /* SDP record handle */
+    tBTA_HL_SUP_FEATURE  sup_feature;
+    tBTA_HL_MDL_CFG      mdl_cfg[BTA_HL_NUM_MDL_CFGS];
+    tBTA_HL_DEVICE_TYPE  dev_type;
+    tBTA_HL_APP_HANDLE   app_handle;
+    UINT16               ctrl_psm;   /* L2CAP PSM for the MCAP control channel */
+    UINT16               data_psm;   /* L2CAP PSM for the MCAP data channel */
+    UINT16               sec_mask;   /* Security mask for BTM_SetSecurityLevel() */
+
+    char                 srv_name[BTA_SERVICE_NAME_LEN +1];        /* service name to be used in the SDP; null terminated*/
+    char                 srv_desp[BTA_SERVICE_DESP_LEN +1];        /* service description to be used in the SDP; null terminated */
+    char                 provider_name[BTA_PROVIDER_NAME_LEN +1];   /* provide name to be used in the SDP; null terminated */
+
+    tMCA_CTRL_CBACK      *p_mcap_cback;            /* pointer to MCAP callback function */
+    tMCA_DATA_CBACK      *p_data_cback;
+}tBTA_HL_APP_CB;
+
+
+typedef struct
+{
+    BOOLEAN             in_use;
+    tBTA_HL_SDP_OPER    sdp_oper;
+    UINT8               app_idx;
+    UINT8               mcl_idx;
+    UINT8               mdl_idx;
+}tBTA_HL_SDP_CB;
+
+typedef struct
+{
+    BOOLEAN         in_use;
+    UINT8           app_idx;
+    UINT8           mcl_idx;
+}tBTA_HL_TIMER_CB;
+
+typedef struct
+{
+    tBTA_HL_APP_CB        acb[BTA_HL_NUM_APPS];      /* HL Control Blocks */
+    tBTA_HL_CTRL_CBACK    *p_ctrl_cback;            /* pointer to control callback function */
+    BOOLEAN               enable;
+    BOOLEAN               disabling;
+
+    tBTA_HL_SDP_CB        scb[BTA_HL_NUM_SDP_CBACKS];
+    tBTA_HL_TIMER_CB      tcb[BTA_HL_NUM_TIMERS];
+    BOOLEAN               enable_random_psm;
+    tBTA_HL_ALLOCATE_PSM  *p_alloc_psm;
+}tBTA_HL_CB;
+
+/******************************************************************************
+**  Configuration Definitions
+*******************************************************************************/
+/* Configuration structure */
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* HL control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_HL_CB  bta_hl_cb;
+#else
+extern tBTA_HL_CB *bta_hl_cb_ptr;
+    #define bta_hl_cb (*bta_hl_cb_ptr)
+#endif
+
+#define BTA_HL_GET_CB_PTR() &(bta_hl_cb)
+#define BTA_HL_GET_APP_CB_PTR(app_idx) &(bta_hl_cb.acb[(app_idx)])
+#define BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx) &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)])
+#define BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx) &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)].mdl[mdl_idx])
+#define BTA_HL_GET_MDL_CFG_PTR(app_idx, item_idx) &(bta_hl_cb.acb[(app_idx)].mdl_cfg[(item_idx)])
+#define BTA_HL_GET_ECHO_CFG_PTR(app_idx)  &(bta_hl_cb.acb[(app_idx)].sup_feature.echo_cfg)
+#define BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx)  &(bta_hl_cb.acb[(app_idx)].sup_feature.mdep[mdep_cfg_idx].mdep_cfg)
+#define BTA_HL_GET_DATA_CFG_PTR(app_idx, mdep_cfg_idx, data_cfg_idx)  \
+           &(bta_hl_cb.acb[(app_idx)].sup_feature.mdep[mdep_cfg_idx].mdep_cfg.data_cfg[data_cfg_idx])
+#define BTA_HL_GET_BUF_PTR(p_pkt) ((UINT8 *)((UINT8 *) (p_pkt+1) + p_pkt->offset))
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+    /* main */
+    extern BOOLEAN bta_hl_hdl_event(BT_HDR *p_msg);
+    /* sdp */
+    extern BOOLEAN bta_hl_fill_sup_feature_list( const tSDP_DISC_ATTR  *p_attr,
+                                                 tBTA_HL_SUP_FEATURE_LIST_ELEM *p_list);
+
+    extern tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx);
+    extern tSDP_DISC_REC *bta_hl_find_sink_or_src_srv_class_in_db (const tSDP_DISCOVERY_DB *p_db,
+                                                                   const tSDP_DISC_REC *p_start_rec);
+
+    /* action routines */
+    extern void bta_hl_dch_ci_get_tx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_ci_put_rx_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_ci_get_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                            tBTA_HL_DATA *p_data);
+
+    extern void bta_hl_dch_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                     tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_ci_put_echo_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                            tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_send_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                     tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_sdp_fail(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                    tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_cong_change(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                           tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_reconnect_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                             tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_reconnect_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                             tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_reconnect(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                         tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_sdp_init(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                    tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_close_echo_test(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                           tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_create_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                      tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_rcv_data(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                        tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                      tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_close_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                         tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_close_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                         tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_close(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                     tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_delete_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+
+    extern void bta_hl_dch_mca_delete_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_delete(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                      tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_abort_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                         tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_abort_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                         tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_abort(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                     tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_open_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                        tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_open_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                        tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_create_ind(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_create_cfm(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                          tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_mca_create(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                      tBTA_HL_DATA *p_data);
+    extern void bta_hl_deallocate_spd_cback(UINT8 sdp_cback_idx);
+    extern tSDP_DISC_CMPL_CB *bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                                                        UINT8 mdl_idx,
+                                                        UINT8 *p_sdp_cback_idx);
+    extern tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                                          UINT8 mdl_idx);
+    extern void bta_hl_cch_sdp_init(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_mca_open(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_mca_close(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_close_cmpl(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_mca_disconnect(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_mca_rsp_tout(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+    extern void bta_hl_cch_mca_connect(UINT8 app_idx, UINT8 mcl_idx,  tBTA_HL_DATA *p_data);
+
+    /* State machine drivers  */
+    extern void bta_hl_cch_sm_execute(UINT8 inst_idx, UINT8 mcl_idx,
+                                      UINT16 event, tBTA_HL_DATA *p_data);
+    extern void bta_hl_dch_sm_execute(UINT8 inst_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                      UINT16 event, tBTA_HL_DATA *p_data);
+    /* MCAP callback functions  */
+    extern void bta_hl_mcap_ctrl_cback(tMCA_HANDLE handle, tMCA_CL mcl, UINT8 event,
+                                       tMCA_CTRL *p_data);
+
+    extern void bta_hl_mcap_data_cback(tMCA_DL mdl, BT_HDR *p_pkt);
+
+    /* utility functions  */
+    extern BOOLEAN bta_hl_set_ctrl_psm_for_dch(UINT8 app_idx, UINT8 mcl_idx,
+                                               UINT8 mdl_idx, UINT16 ctrl_psm);
+    extern BOOLEAN bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP *p_sdp,
+                                                      UINT16 ctrl_psm,
+                                                      UINT8 *p_sdp_idx);
+    extern UINT8 bta_hl_set_user_tx_pool_id(UINT16 max_tx_size);
+    extern UINT8 bta_hl_set_user_rx_pool_id(UINT16 mtu);
+    extern UINT8 bta_hl_set_tx_win_size(UINT16 mtu, UINT16 mps);
+    extern UINT16 bta_hl_set_mps(UINT16 mtu);
+    extern void bta_hl_clean_mdl_cb(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx);
+    extern BT_HDR * bta_hl_get_buf(UINT16 data_size);
+    extern BOOLEAN bta_hl_find_service_in_db( UINT8 app_idx, UINT8 mcl_idx,
+                                              UINT16 service_uuid,
+                                              tSDP_DISC_REC **pp_rec );
+    extern UINT16 bta_hl_get_service_uuids(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                                           UINT8 mdl_idx );
+    extern BOOLEAN bta_hl_find_echo_cfg_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdep_idx, UINT8 cfg,
+                                            UINT8 *p_cfg_rsp);
+    extern BOOLEAN bta_hl_validate_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                       UINT8 cfg);
+    extern BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
+                                              UINT8 *p_app_idx,
+                                              UINT8  *p_mcl_idx);
+    extern BOOLEAN bta_hl_find_dch_cb_indexes(tBTA_HL_DATA *p_msg,
+                                              UINT8 *p_app_idx,
+                                              UINT8 *p_mcl_idx,
+                                              UINT8 *p_mdl_idx);
+    extern UINT16  bta_hl_allocate_mdl_id(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx );
+    extern BOOLEAN bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
+                                                    UINT8 *p_app_idx, UINT8 *p_mcl_idx,
+                                                    UINT8 *p_mdl_idx);
+    extern BOOLEAN bta_hl_find_mdl_idx(UINT8 app_idx, UINT8 mcl_idx, UINT16 mdl_id,
+                                       UINT8 *p_mdl_idx);
+    extern BOOLEAN bta_hl_find_an_active_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                                 UINT8 *p_mdl_idx);
+    extern BOOLEAN bta_hl_find_dch_setup_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                                 UINT8 *p_mdl_idx);
+    extern BOOLEAN bta_hl_find_an_in_use_mcl_idx(UINT8 app_idx,
+                                                 UINT8 *p_mcl_idx);
+    extern BOOLEAN bta_hl_find_an_in_use_app_idx(UINT8 *p_app_idx);
+    extern BOOLEAN bta_hl_find_app_idx(UINT8 app_id, UINT8 *p_app_idx);
+    extern BOOLEAN bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
+                                                    UINT8 *p_app_idx);
+    extern BOOLEAN bta_hl_find_mcl_idx_using_handle( tBTA_HL_MCL_HANDLE mcl_handle,
+                                                     UINT8 *p_app_idx, UINT8 *p_mcl_idx);
+    extern BOOLEAN bta_hl_find_mcl_idx(UINT8 app_idx, BD_ADDR p_bd_addr, UINT8 *p_mcl_idx);
+    extern BOOLEAN bta_hl_is_the_first_reliable_existed(UINT8 app_idx, UINT8 mcl_idx );
+    extern BOOLEAN  bta_hl_find_non_active_mdl_cfg(UINT8 app_idx, UINT8 start_mdl_cfg_idx,
+                                                   UINT8 *p_mdl_cfg_idx);
+    extern BOOLEAN  bta_hl_find_avail_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                                  UINT8 *p_mdl_cfg_idx);
+    extern BOOLEAN  bta_hl_find_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                            tBTA_HL_MDL_ID mdl_id, UINT8 *p_mdl_cfg_idx);
+    extern BOOLEAN  bta_hl_get_cur_time(UINT8 app_idx, UINT8 *p_cur_time);
+    extern void bta_hl_sort_cfg_time_idx(UINT8 app_idx, UINT8 *a, UINT8 n);
+    extern void  bta_hl_compact_mdl_cfg_time(UINT8 app_idx);
+    extern BOOLEAN  bta_hl_is_mdl_exsit_in_mcl(UINT8 app_idx, BD_ADDR bd_addr,
+                                               tBTA_HL_MDL_ID mdl_id);
+    extern BOOLEAN  bta_hl_delete_mdl_cfg(UINT8 app_idx, BD_ADDR bd_addr,
+                                          tBTA_HL_MDL_ID mdl_id);
+    extern BOOLEAN  bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id);
+    extern BOOLEAN bta_hl_find_mdep_cfg_idx(UINT8 app_idx,
+                                            tBTA_HL_MDEP_ID local_mdep_id, UINT8 *p_mdep_cfg_idx);
+    extern void bta_hl_find_rxtx_apdu_size(UINT8 app_idx, UINT8 mdep_cfg_idx,
+                                           UINT16 *p_rx_apu_size,
+                                           UINT16 *p_tx_apu_size);
+    extern BOOLEAN bta_hl_validate_peer_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                            tBTA_HL_MDEP_ID peer_mdep_id,
+                                            tBTA_HL_MDEP_ROLE peer_mdep_role,
+                                            UINT8 sdp_idx);
+    extern tBTA_HL_STATUS bta_hl_chk_local_cfg(UINT8 app_idx, UINT8 mcl_idx,
+                                               UINT8 mdep_cfg_idx,
+                                               tBTA_HL_DCH_CFG local_cfg);
+
+    extern BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx,
+                                                    tBTA_HL_API_DCH_RECONNECT *p_reconnect,
+                                                    UINT8 *p_mdep_cfg_idx, UINT8 *p_mdl_cfg_idx);
+    extern BOOLEAN bta_hl_find_avail_mcl_idx(UINT8 app_idx, UINT8 *p_mcl_idx);
+    extern BOOLEAN bta_hl_find_avail_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                             UINT8 *p_mdl_idx);
+    extern BOOLEAN bta_hl_is_a_duplicate_id(UINT8 app_id);
+    extern BOOLEAN bta_hl_find_avail_app_idx(UINT8 *p_idx);
+    extern tBTA_HL_STATUS bta_hl_app_registration(UINT8 app_idx);
+    extern void bta_hl_discard_data(UINT16 event, tBTA_HL_DATA *p_data);
+    extern void bta_hl_save_mdl_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx );
+    extern void bta_hl_set_dch_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx, tBTA_HL_DATA *p_data);
+    extern BOOLEAN bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd, tBTA_HL_L2CAP_CFG_INFO *p_cfg);
+    extern BOOLEAN bta_hl_validate_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx);
+    extern BOOLEAN bta_hl_is_cong_on(UINT8 app_id, BD_ADDR bd_addr, tBTA_HL_MDL_ID mdl_id);
+    extern void bta_hl_check_cch_close(UINT8 app_idx, UINT8 mcl_idx,
+                                       tBTA_HL_DATA *p_data, BOOLEAN check_dch_setup);
+    extern void bta_hl_clean_app(UINT8 app_idx);
+    extern void bta_hl_check_deregistration(UINT8 app_idx, tBTA_HL_DATA *p_data );
+    extern void bta_hl_check_disable(tBTA_HL_DATA *p_data );
+    extern void  bta_hl_build_abort_ind(tBTA_HL *p_evt_data,
+                                        tBTA_HL_APP_HANDLE app_handle,
+                                        tBTA_HL_MCL_HANDLE mcl_handle);
+    extern void  bta_hl_build_abort_cfm(tBTA_HL *p_evt_data,
+                                        tBTA_HL_APP_HANDLE app_handle,
+                                        tBTA_HL_MCL_HANDLE mcl_handle,
+                                        tBTA_HL_STATUS status);
+    extern void  bta_hl_build_dch_close_cfm(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_MDL_HANDLE mdl_handle,
+                                            tBTA_HL_STATUS status);
+    extern void  bta_hl_build_dch_close_ind(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_MDL_HANDLE mdl_handle,
+                                            BOOLEAN intentional);
+    extern void  bta_hl_build_send_data_cfm(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_MDL_HANDLE mdl_handle,
+                                            tBTA_HL_STATUS status );
+    extern void  bta_hl_build_rcv_data_ind(tBTA_HL *p_evt_data,
+                                           tBTA_HL_APP_HANDLE app_handle,
+                                           tBTA_HL_MCL_HANDLE mcl_handle,
+                                           tBTA_HL_MDL_HANDLE mdl_handle);
+    extern void  bta_hl_build_cch_open_cfm(tBTA_HL *p_evt_data,
+                                           tBTA_HL_APP_HANDLE app_handle,
+                                           tBTA_HL_MCL_HANDLE mcl_handle,
+                                           BD_ADDR bd_addr,
+                                           tBTA_HL_STATUS status );
+    extern void  bta_hl_build_cch_open_ind(tBTA_HL *p_evt_data,
+                                           tBTA_HL_APP_HANDLE app_handle,
+                                           tBTA_HL_MCL_HANDLE mcl_handle,
+                                           BD_ADDR bd_addr);
+    extern void  bta_hl_build_cch_close_cfm(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_STATUS status );
+    extern void   bta_hl_build_cch_close_ind(tBTA_HL *p_evt_data,
+                                             tBTA_HL_APP_HANDLE app_handle,
+                                             tBTA_HL_MCL_HANDLE mcl_handle,
+                                             BOOLEAN intentional);
+
+    extern void  bta_hl_build_dch_open_cfm(tBTA_HL *p_evt_data,
+                                           tBTA_HL_APP_HANDLE app_handle,
+                                           tBTA_HL_MCL_HANDLE mcl_handle,
+                                           tBTA_HL_MDL_HANDLE mdl_handle,
+                                           tBTA_HL_MDEP_ID local_mdep_id,
+                                           tBTA_HL_MDL_ID mdl_id,
+                                           tBTA_HL_DCH_MODE dch_mode,
+                                           BOOLEAN first_reliable,
+                                           UINT16 mtu,
+                                           tBTA_HL_STATUS status);
+
+    extern void  bta_hl_build_delete_mdl_cfm(tBTA_HL *p_evt_data,
+                                             tBTA_HL_APP_HANDLE app_handle,
+                                             tBTA_HL_MCL_HANDLE mcl_handle,
+                                             tBTA_HL_MDL_ID mdl_id,
+                                             tBTA_HL_STATUS status);
+    extern void  bta_hl_build_echo_test_cfm(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_STATUS status );
+    extern void  bta_hl_build_sdp_query_cfm(tBTA_HL *p_evt_data,
+                                            tBTA_HL_APP_HANDLE app_handle,
+                                            BD_ADDR bd_addr,
+                                            tBTA_HL_SDP *p_sdp,
+                                            tBTA_HL_STATUS status);
+
+#if (BTA_HL_DEBUG == TRUE)
+    extern  char *bta_hl_status_code(tBTA_HL_STATUS status);
+    extern char *bta_hl_evt_code(tBTA_HL_INT_EVT evt_code);
+#endif
+#ifdef __cplusplus
+}
+#endif
+#endif /* BTA_MSE_INT_H */
+
+
diff --git a/bta/hl/bta_hl_main.c b/bta/hl/bta_hl_main.c
new file mode 100644
index 0000000..afac4c3
--- /dev/null
+++ b/bta/hl/bta_hl_main.c
@@ -0,0 +1,1920 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1998-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 the HeaLth device profile main functions and state
+ *  machine.
+ *
+ ******************************************************************************/
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+
+
+#include "bta_hl_api.h"
+#include "bta_hl_int.h"
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+#include "l2c_api.h"
+#include "mca_defs.h"
+
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+static char *bta_hl_cch_state_code(tBTA_HL_CCH_STATE state_code);
+static char *bta_hl_dch_state_code(tBTA_HL_DCH_STATE state_code);
+#endif
+
+extern UINT16 L2CA_AllocateRandomPsm(void);
+extern UINT16 L2CA_AllocatePsm(void);
+/*****************************************************************************
+** DCH State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for DCH */
+/* The order of this enumeration must be the same as bta_hl_dch_act_tbl[] */
+enum
+{
+    BTA_HL_DCH_MCA_CREATE,
+    BTA_HL_DCH_MCA_CREATE_CFM,
+    BTA_HL_DCH_MCA_CREATE_IND,
+    BTA_HL_DCH_MCA_OPEN_CFM,
+    BTA_HL_DCH_MCA_OPEN_IND,
+    BTA_HL_DCH_MCA_CLOSE,
+    BTA_HL_DCH_MCA_CLOSE_CFM,
+    BTA_HL_DCH_MCA_CLOSE_IND,
+    BTA_HL_DCH_CLOSE_CMPL,
+    BTA_HL_DCH_MCA_RCV_DATA,
+
+    BTA_HL_DCH_SDP_INIT,
+    BTA_HL_DCH_MCA_RECONNECT,
+    BTA_HL_DCH_MCA_RECONNECT_IND,
+    BTA_HL_DCH_MCA_RECONNECT_CFM,
+    BTA_HL_DCH_CLOSE_ECHO_TEST,
+    BTA_HL_DCH_CREATE_RSP,
+    BTA_HL_DCH_MCA_ABORT,
+    BTA_HL_DCH_MCA_ABORT_IND,
+    BTA_HL_DCH_MCA_ABORT_CFM,
+    BTA_HL_DCH_MCA_CONG_CHANGE,
+
+    BTA_HL_DCH_SDP_FAIL,
+    BTA_HL_DCH_SEND_DATA,
+    BTA_HL_DCH_CI_GET_TX_DATA,
+    BTA_HL_DCH_CI_PUT_RX_DATA,
+    BTA_HL_DCH_CI_GET_ECHO_DATA,
+    BTA_HL_DCH_ECHO_TEST,
+    BTA_HL_DCH_CI_PUT_ECHO_DATA,
+    BTA_HL_DCH_IGNORE
+};
+
+typedef void (*tBTA_HL_DCH_ACTION)(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx, tBTA_HL_DATA *p_data);
+
+static const tBTA_HL_DCH_ACTION bta_hl_dch_action[] =
+{
+    bta_hl_dch_mca_create,
+    bta_hl_dch_mca_create_cfm,
+    bta_hl_dch_mca_create_ind,
+    bta_hl_dch_mca_open_cfm,
+    bta_hl_dch_mca_open_ind,
+    bta_hl_dch_mca_close,
+    bta_hl_dch_mca_close_cfm,
+    bta_hl_dch_mca_close_ind,
+    bta_hl_dch_close_cmpl,
+    bta_hl_dch_mca_rcv_data,
+
+    bta_hl_dch_sdp_init,
+    bta_hl_dch_mca_reconnect,
+    bta_hl_dch_mca_reconnect_ind,
+    bta_hl_dch_mca_reconnect_cfm,
+    bta_hl_dch_close_echo_test,
+    bta_hl_dch_create_rsp,
+    bta_hl_dch_mca_abort,
+    bta_hl_dch_mca_abort_ind,
+    bta_hl_dch_mca_abort_cfm,
+    bta_hl_dch_mca_cong_change,
+
+    bta_hl_dch_sdp_fail,
+    bta_hl_dch_send_data,
+    bta_hl_dch_ci_get_tx_data,
+    bta_hl_dch_ci_put_rx_data,
+    bta_hl_dch_ci_get_echo_data,
+    bta_hl_dch_echo_test,
+    bta_hl_dch_ci_put_echo_data,
+};
+
+
+/* state table information */
+#define BTA_HL_DCH_ACTIONS             1       /* number of actions */
+#define BTA_HL_DCH_ACTION_COL          0       /* position of action */
+#define BTA_HL_DCH_NEXT_STATE          1       /* position of next state */
+#define BTA_HL_DCH_NUM_COLS            2       /* number of columns in state tables */
+
+/* state table for idle state */
+static const UINT8 bta_hl_dch_st_idle[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event                                Action 1                    Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT   */     {BTA_HL_DCH_SDP_INIT,           BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_OPEN_EVT       */     {BTA_HL_DCH_MCA_CREATE,         BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */     {BTA_HL_DCH_MCA_CREATE_IND,     BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT   */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_OPEN_CFM_EVT   */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_EVT      */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT  */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT  */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_API_SEND_DATA_EVT  */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT   */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT  */     {BTA_HL_DCH_MCA_RECONNECT,      BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT   */     {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/   {BTA_HL_DCH_MCA_RECONNECT_IND,  BTA_HL_DCH_OPENING_ST},
+
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/   {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_ABORT_EVT */          {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */      {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+
+/* BTA_HL_MCA_ABORT_CFM_EVT */      {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */       {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT  */    {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT  */    {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT  */  {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT  */     {BTA_HL_DCH_ECHO_TEST,          BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT  */  {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_IDLE_ST}
+};
+
+/* state table for opening state */
+static const UINT8 bta_hl_dch_st_opening[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event                                Action 1                    Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT   */   {BTA_HL_DCH_SDP_INIT,             BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_OPEN_EVT       */   {BTA_HL_DCH_MCA_CREATE,           BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */   {BTA_HL_DCH_IGNORE,               BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */   {BTA_HL_DCH_MCA_CREATE_CFM,       BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT   */   {BTA_HL_DCH_MCA_OPEN_IND,         BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT   */   {BTA_HL_DCH_MCA_OPEN_CFM,         BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_EVT      */   {BTA_HL_DCH_IGNORE,               BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT  */   {BTA_HL_DCH_MCA_CLOSE_IND,        BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT  */   {BTA_HL_DCH_MCA_CLOSE_CFM,        BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT  */   {BTA_HL_DCH_IGNORE,               BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT   */   {BTA_HL_DCH_IGNORE,               BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */   {BTA_HL_DCH_CLOSE_CMPL,           BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT  */   {BTA_HL_DCH_MCA_RECONNECT,        BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT   */   {BTA_HL_DCH_SDP_FAIL,             BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/ {BTA_HL_DCH_IGNORE,               BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/ {BTA_HL_DCH_MCA_RECONNECT_CFM,    BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_CREATE_RSP,         BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_ABORT_EVT */          {BTA_HL_DCH_MCA_ABORT,          BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */      {BTA_HL_DCH_MCA_ABORT_IND,      BTA_HL_DCH_OPENING_ST},
+
+/* BTA_HL_MCA_ABORT_CFM_EVT */      {BTA_HL_DCH_MCA_ABORT_CFM,      BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */       {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT  */    {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT  */    {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT  */  {BTA_HL_DCH_CI_GET_ECHO_DATA,   BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT  */     {BTA_HL_DCH_ECHO_TEST,          BTA_HL_DCH_OPENING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT  */  {BTA_HL_DCH_IGNORE,             BTA_HL_DCH_OPENING_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_hl_dch_st_open[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event                                Action 1                  Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_OPEN_EVT       */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_EVT      */     {BTA_HL_DCH_MCA_CLOSE,        BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT  */     {BTA_HL_DCH_MCA_CLOSE_IND,    BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT  */     {BTA_HL_DCH_MCA_CLOSE_CFM,    BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT  */     {BTA_HL_DCH_SEND_DATA,        BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT   */     {BTA_HL_DCH_MCA_RCV_DATA,     BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */     {BTA_HL_DCH_CLOSE_CMPL,       BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/   {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/   {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_CLOSE_ECHO_TEST,  BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_ABORT_EVT */          {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */      {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+
+/* BTA_HL_DCH_ABORT_CFM_EVT */      {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */       {BTA_HL_DCH_MCA_CONG_CHANGE,  BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT  */    {BTA_HL_DCH_CI_GET_TX_DATA,   BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT  */    {BTA_HL_DCH_CI_PUT_RX_DATA,   BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT  */  {BTA_HL_DCH_CI_GET_ECHO_DATA, BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_OPEN_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT  */  {BTA_HL_DCH_CI_PUT_ECHO_DATA, BTA_HL_DCH_OPEN_ST}
+};
+
+
+/* state table for closing state */
+static const UINT8 bta_hl_dch_st_closing[][BTA_HL_DCH_NUM_COLS] =
+{
+/* Event                                Action 1                  Next state */
+/* BTA_HL_DCH_SDP_INIT_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_OPEN_EVT       */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CREATE_IND_EVT */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CREATE_CFM_EVT */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_OPEN_IND_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_OPEN_CFM_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_EVT      */     {BTA_HL_DCH_MCA_CLOSE,        BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_IND_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CLOSE_CFM_EVT  */     {BTA_HL_DCH_MCA_CLOSE_CFM,    BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_SEND_DATA_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+
+/* BTA_HL_MCA_RCV_DATA_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_CMPL_EVT */     {BTA_HL_DCH_CLOSE_CMPL,       BTA_HL_DCH_IDLE_ST},
+/* BTA_HL_DCH_RECONNECT_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_SDP_FAIL_EVT   */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_IND_EVT*/   {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_RECONNECT_CFM_EVT*/   {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_CLOSE_ECHO_TEST_EVT*/ {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_API_DCH_CREATE_RSP_EVT */ {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_ABORT_EVT */          {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_ABORT_IND_EVT */      {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+
+/* BTA_HL_DCH_ABORT_CFM_EVT */      {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_MCA_CONG_CHG_EVT */       {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_GET_TX_DATA_EVT  */    {BTA_HL_DCH_CI_GET_TX_DATA,   BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_PUT_RX_DATA_EVT  */    {BTA_HL_DCH_CI_PUT_RX_DATA,   BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_GET_ECHO_DATA_EVT  */  {BTA_HL_DCH_CI_GET_ECHO_DATA, BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_DCH_ECHO_TEST_EVT  */     {BTA_HL_DCH_IGNORE,           BTA_HL_DCH_CLOSING_ST},
+/* BTA_HL_CI_PUT_ECHO_DATA_EVT  */  {BTA_HL_DCH_CI_PUT_ECHO_DATA, BTA_HL_DCH_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_HL_DCH_ST_TBL)[BTA_HL_DCH_NUM_COLS];
+
+/* state table */
+const tBTA_HL_DCH_ST_TBL bta_hl_dch_st_tbl[] =
+{
+    bta_hl_dch_st_idle,
+    bta_hl_dch_st_opening,
+    bta_hl_dch_st_open,
+    bta_hl_dch_st_closing
+};
+
+/*****************************************************************************
+** CCH State Table
+*****************************************************************************/
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+/* state machine action enumeration list for CCH */
+enum
+{
+    BTA_HL_CCH_SDP_INIT,
+    BTA_HL_CCH_MCA_OPEN,
+    BTA_HL_CCH_MCA_CLOSE,
+    BTA_HL_CCH_CLOSE_CMPL,
+    BTA_HL_CCH_MCA_CONNECT,
+    BTA_HL_CCH_MCA_DISCONNECT,
+    BTA_HL_CCH_MCA_RSP_TOUT,
+    BTA_HL_CCH_IGNORE
+};
+
+/* type for action functions */
+typedef void (*tBTA_HL_CCH_ACTION)(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data);
+
+/* action function list for MAS */
+const tBTA_HL_CCH_ACTION bta_hl_cch_action[] =
+{
+    bta_hl_cch_sdp_init,
+    bta_hl_cch_mca_open,
+    bta_hl_cch_mca_close,
+    bta_hl_cch_close_cmpl,
+    bta_hl_cch_mca_connect,
+    bta_hl_cch_mca_disconnect,
+    bta_hl_cch_mca_rsp_tout
+};
+
+
+/* state table information */
+#define BTA_HL_CCH_ACTIONS             1       /* number of actions */
+#define BTA_HL_CCH_NEXT_STATE          1       /* position of next state */
+#define BTA_HL_CCH_NUM_COLS            2       /* number of columns in state tables */
+
+
+/* state table for MAS idle state */
+static const UINT8 bta_hl_cch_st_idle[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event                          Action 1                  Next state */
+/* BTA_HL_CCH_OPEN_EVT           */ {BTA_HL_CCH_SDP_INIT,       BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT         */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT       */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT    */ {BTA_HL_CCH_MCA_CONNECT,    BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_EVT          */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT     */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT     */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_IDLE_ST}
+};
+
+/* state table for obex/rfcomm connection state */
+static const UINT8 bta_hl_cch_st_opening[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event                          Action 1               Next state */
+/* BTA_HL_CCH_OPEN_EVT           */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT         */ {BTA_HL_CCH_MCA_OPEN,       BTA_HL_CCH_OPENING_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT       */ {BTA_HL_CCH_CLOSE_CMPL,     BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT    */ {BTA_HL_CCH_MCA_CONNECT,    BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT          */ {BTA_HL_CCH_MCA_CLOSE,      BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT     */ {BTA_HL_CCH_CLOSE_CMPL,     BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT   */ {BTA_HL_CCH_MCA_RSP_TOUT,   BTA_HL_CCH_CLOSING_ST}
+};
+
+/* state table for open state */
+static const UINT8 bta_hl_cch_st_open[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event                          Action 1                  Next state */
+/* BTA_HL_CCH_OPEN_EVT           */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_CCH_SDP_OK_EVT         */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT       */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT    */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT          */ {BTA_HL_CCH_MCA_CLOSE,      BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT     */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT   */ {BTA_HL_CCH_MCA_RSP_TOUT,   BTA_HL_CCH_CLOSING_ST}
+};
+
+/* state table for closing state */
+static const UINT8 bta_hl_cch_st_closing[][BTA_HL_CCH_NUM_COLS] =
+{
+/* Event                          Action 1                  Next state */
+/* BTA_HL_CCH_OPEN_EVT           */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_SDP_OK_EVT         */ {BTA_HL_CCH_CLOSE_CMPL,     BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_CCH_SDP_FAIL_EVT       */ {BTA_HL_CCH_CLOSE_CMPL,     BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_CONNECT_IND_EVT    */ {BTA_HL_CCH_MCA_CONNECT,    BTA_HL_CCH_OPEN_ST},
+/* BTA_HL_MCA_DISCONNECT_IND_EVT */ {BTA_HL_CCH_MCA_DISCONNECT, BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_EVT          */ {BTA_HL_CCH_MCA_CLOSE,      BTA_HL_CCH_CLOSING_ST},
+/* BTA_HL_CCH_CLOSE_CMPL_EVT     */ {BTA_HL_CCH_CLOSE_CMPL,     BTA_HL_CCH_IDLE_ST},
+/* BTA_HL_MCA_RSP_TOUT_IND_EVT   */ {BTA_HL_CCH_IGNORE,         BTA_HL_CCH_CLOSING_ST}
+};
+
+/* type for state table CCH */
+typedef const UINT8 (*tBTA_HL_CCH_ST_TBL)[BTA_HL_CCH_NUM_COLS];
+
+/* MAS state table */
+const tBTA_HL_CCH_ST_TBL bta_hl_cch_st_tbl[] =
+{
+    bta_hl_cch_st_idle,
+    bta_hl_cch_st_opening,
+    bta_hl_cch_st_open,
+    bta_hl_cch_st_closing
+};
+
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* HL control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_HL_CB  bta_hl_cb;
+#endif
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_sm_execute
+**
+** Description      State machine event handling function for CCH
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_sm_execute(UINT8 app_idx, UINT8 mcl_idx,
+                           UINT16 event, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_CCH_ST_TBL  state_table;
+    UINT8               action;
+    int                 i;
+    tBTA_HL_MCL_CB      *p_cb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+    tBTA_HL_CCH_STATE in_state = p_cb->cch_state;
+    UINT16             cur_evt = event;
+    APPL_TRACE_DEBUG3("HDP CCH Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+                      bta_hl_cch_state_code(in_state),
+                      bta_hl_evt_code(cur_evt));
+#endif
+
+    /* look up the state table for the current state */
+    state_table = bta_hl_cch_st_tbl[p_cb->cch_state];
+
+    event &= 0x00FF;
+
+    /* set next state */
+    p_cb->cch_state = state_table[event][BTA_HL_CCH_NEXT_STATE];
+
+    for (i = 0; i < BTA_HL_CCH_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_HL_CCH_IGNORE)
+        {
+            (*bta_hl_cch_action[action])(app_idx, mcl_idx, p_data);
+        }
+        else
+        {
+            /* discard HDP data */
+            bta_hl_discard_data(p_data->hdr.event, p_data);
+            break;
+        }
+    }
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+    if (in_state != p_cb->cch_state)
+    {
+        APPL_TRACE_DEBUG3("HL CCH State Change: [%s] -> [%s] after [%s]",
+                          bta_hl_cch_state_code(in_state),
+                          bta_hl_cch_state_code(p_cb->cch_state),
+                          bta_hl_evt_code(cur_evt));
+    }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_sm_execute
+**
+** Description      State machine event handling function for DCH
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_dch_sm_execute(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                           UINT16 event, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_DCH_ST_TBL  state_table;
+    UINT8               action;
+    int                 i;
+    tBTA_HL_MDL_CB      *p_cb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+    tBTA_HL_DCH_STATE in_state = p_cb->dch_state;
+    UINT16             cur_evt = event;
+    APPL_TRACE_DEBUG3("HDP DCH Event Handler: State 0x%02x [%s], Event [%s]", in_state,
+                      bta_hl_dch_state_code(in_state),
+                      bta_hl_evt_code(cur_evt));
+#endif
+
+    /* look up the state table for the current state */
+    state_table = bta_hl_dch_st_tbl[p_cb->dch_state];
+    event -= BTA_HL_DCH_EVT_MIN;
+
+    /* set next state */
+    p_cb->dch_state = state_table[event][BTA_HL_DCH_NEXT_STATE];
+
+    for (i = 0; i < BTA_HL_DCH_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_HL_DCH_IGNORE)
+        {
+            (*bta_hl_dch_action[action])(app_idx, mcl_idx, mdl_idx, p_data);
+        }
+        else
+        {
+            /* discard mas data */
+            bta_hl_discard_data(p_data->hdr.event, p_data);
+            break;
+        }
+    }
+
+
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+    if (in_state != p_cb->dch_state)
+    {
+        APPL_TRACE_DEBUG3("HL DCH State Change: [%s] -> [%s] after [%s]",
+                          bta_hl_dch_state_code(in_state),
+                          bta_hl_dch_state_code(p_cb->dch_state),
+                          bta_hl_evt_code(cur_evt));
+    }
+#endif
+}
+/*******************************************************************************
+**
+** Function         bta_hl_api_enable
+**
+** Description      Process the API enable request to enable the HL subsystem
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_enable(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_CTRL    evt_data;
+
+    /* If already enabled then reject this request */
+    if (p_cb->enable)
+    {
+        APPL_TRACE_ERROR0("HL is already enabled");
+        evt_data.enable_cfm.status = BTA_HL_STATUS_FAIL;
+        if (p_data->api_enable.p_cback)
+            p_data->api_enable.p_cback(BTA_HL_CTRL_ENABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+        return;
+    }
+
+    /* Done with checking. now perform the enable oepration*/
+    /* initialize control block */
+    memset(p_cb, 0, sizeof(tBTA_HL_CB));
+    p_cb->enable = TRUE;
+    p_cb->p_ctrl_cback = p_data->api_enable.p_cback;
+    evt_data.enable_cfm.status = BTA_HL_STATUS_OK;
+    if (p_data->api_enable.p_cback)
+        p_data->api_enable.p_cback(BTA_HL_CTRL_ENABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+
+}
+/*******************************************************************************
+**
+** Function         bta_hl_api_disable
+**
+** Description      Process the API disable request to disable the HL subsystem
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_disable(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_CTRL    evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+
+    if (p_cb->enable)
+    {
+        p_cb->disabling = TRUE;
+        bta_hl_check_disable(p_data);
+    }
+    else
+    {
+        status = BTA_HL_STATUS_FAIL;
+        evt_data.disable_cfm.status = status;
+        if (p_cb->p_ctrl_cback) p_cb->p_ctrl_cback(BTA_HL_CTRL_DISABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_disable status =%s", bta_hl_status_code(status));
+    }
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_register
+**
+** Description      Process the API registration request to register an HDP applciation
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_register(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    UINT8           app_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_FAIL;
+
+    if (p_cb->enable)
+    {
+        if (!bta_hl_is_a_duplicate_id(p_data->api_reg.app_id))
+        {
+            if (bta_hl_find_avail_app_idx(&app_idx))
+            {
+                p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+                p_acb->in_use = TRUE;
+                p_acb->app_id = p_data->api_reg.app_id;
+                p_acb->p_cback = p_data->api_reg.p_cback;
+                p_acb->sec_mask = p_data->api_reg.sec_mask;
+                p_acb->dev_type = p_data->api_reg.dev_type;
+                BCM_STRNCPY_S(p_acb->srv_name, sizeof(p_acb->srv_name), p_data->api_reg.srv_name, BTA_SERVICE_NAME_LEN);
+                BCM_STRNCPY_S(p_acb->srv_desp, sizeof(p_acb->srv_desp), p_data->api_reg.srv_desp, BTA_SERVICE_DESP_LEN);
+                BCM_STRNCPY_S(p_acb->provider_name, sizeof(p_acb->provider_name), p_data->api_reg.provider_name, BTA_PROVIDER_NAME_LEN);
+                bta_hl_cb.p_alloc_psm = L2CA_AllocatePSM;
+                p_acb->ctrl_psm = bta_hl_cb.p_alloc_psm();
+                p_acb->data_psm = bta_hl_cb.p_alloc_psm();
+                p_acb->p_mcap_cback = bta_hl_mcap_ctrl_cback;
+                status = bta_hl_app_registration(app_idx);
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_RESOURCE;
+            }
+        }
+        else
+        {
+            status = BTA_HL_STATUS_DUPLICATE_APP_ID;
+        }
+    }
+
+    if (status != BTA_HL_STATUS_OK)
+    {
+        if ((status != BTA_HL_STATUS_DUPLICATE_APP_ID) &&
+            (status != BTA_HL_STATUS_NO_RESOURCE))
+        {
+            memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
+        }
+    }
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_register status =%s", bta_hl_status_code(status));
+    }
+#endif
+
+    evt_data.reg_cfm.status = status;
+    evt_data.reg_cfm.app_id = p_data->api_reg.app_id;
+    evt_data.reg_cfm.app_handle = p_acb->app_handle;
+    if (p_data->api_reg.p_cback)
+    {
+        p_data->api_reg.p_cback(BTA_HL_REGISTER_CFM_EVT, (tBTA_HL *) &evt_data);
+    }
+
+    if (status == BTA_HL_STATUS_OK)
+    {
+        evt_data.sdp_info_ind.app_handle = p_acb->app_handle;
+        evt_data.sdp_info_ind.ctrl_psm = p_acb->ctrl_psm;
+        evt_data.sdp_info_ind.data_psm = p_acb->data_psm;
+        evt_data.sdp_info_ind.data_x_spec = BTA_HL_SDP_IEEE_11073_20601;
+        evt_data.sdp_info_ind.mcap_sup_procs = BTA_HL_MCAP_SUP_PROC_MASK ;
+
+        if (p_data->api_reg.p_cback)
+        {
+            p_data->api_reg.p_cback(BTA_HL_SDP_INFO_IND_EVT, (tBTA_HL *) &evt_data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_deregister
+**
+** Description      Process the API de-registration request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_deregister(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+
+    UINT8           app_idx;
+    tBTA_HL_APP_CB  *p_acb;
+
+    if (bta_hl_find_app_idx_using_handle(p_data->api_dereg.app_handle, &app_idx))
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        p_acb->deregistering= TRUE;
+        bta_hl_check_deregistration(app_idx,p_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR1("Inavlide app_handle=%d", p_data->api_dereg.app_handle);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_cch_open
+**
+** Description      Process the API CCH open request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_cch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+
+    if (bta_hl_find_app_idx_using_handle(p_data->api_cch_open.app_handle, &app_idx))
+    {
+
+        if (!bta_hl_find_mcl_idx(app_idx, p_data->api_cch_open.bd_addr, &mcl_idx))
+        {
+            if (bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                p_mcb->in_use = TRUE;
+                p_mcb->req_ctrl_psm = p_data->api_cch_open.ctrl_psm;
+                p_mcb->sec_mask = p_data->api_cch_open.sec_mask;
+                bdcpy(p_mcb->bd_addr, p_data->api_cch_open.bd_addr);
+                p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_OPEN;
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_RESOURCE;
+            }
+        }
+        else
+        {
+            /* Only one MCL per BD_ADDR */
+            status = BTA_HL_STATUS_FAIL;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_APP_HANDLE;
+    }
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_cch_open status =%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_OPEN_EVT, p_data);
+            break;
+        case BTA_HL_STATUS_NO_RESOURCE:
+        case BTA_HL_STATUS_FAIL:
+            bta_hl_build_cch_open_cfm(&evt_data, p_data->api_cch_open.app_handle,
+                                      0,
+                                      p_data->api_cch_open.bd_addr,
+                                      status);
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            p_acb->p_cback(BTA_HL_CCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        default:
+            APPL_TRACE_ERROR1("status code=%d", status);
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_cch_close
+**
+** Description      Process the API CCH close request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_cch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_cch_close.mcl_handle, &app_idx,  &mcl_idx))
+    {
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+        p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+    }
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_cch_close status =%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            bta_hl_check_cch_close(app_idx, mcl_idx, p_data, TRUE);
+            break;
+
+        case BTA_HL_STATUS_FAIL:
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            bta_hl_build_cch_close_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_data->api_cch_close.mcl_handle,
+                                       status);
+            p_acb->p_cback(BTA_HL_CCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+
+        default:
+            APPL_TRACE_ERROR1("status code=%d", status);
+            break;
+
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_dch_open
+**
+** Description      Process the API DCH open request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_open(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL                     evt_data;
+    tBTA_HL_STATUS              status = BTA_HL_STATUS_OK;
+    UINT8                       app_idx, mcl_idx, mdl_idx;
+    tBTA_HL_APP_CB              *p_acb;
+    tBTA_HL_MCL_CB              *p_mcb;
+    tBTA_HL_MDL_CB              *p_dcb;
+    tBTA_HL_MDEP_CFG            *p_mdep_cfg;
+    UINT8                       mdep_cfg_idx;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+        if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+        {
+            if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+            {
+                p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+                if (bta_hl_find_mdep_cfg_idx(app_idx, p_data->api_dch_open.local_mdep_id, &mdep_cfg_idx))
+                {
+                    if ( mdep_cfg_idx &&
+                         (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SINK))
+                    {
+                        p_data->api_dch_open.local_cfg = BTA_HL_DCH_CFG_NO_PREF;
+                    }
+
+                    if ((status = bta_hl_chk_local_cfg(app_idx,mcl_idx,mdep_cfg_idx,p_data->api_dch_open.local_cfg))
+                        == BTA_HL_STATUS_OK)
+                    {
+
+                        if (p_data->api_dch_open.local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+                        {
+                            if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+                            {
+                                p_mdep_cfg = BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx);
+                                p_dcb->in_use                   = TRUE;
+                                p_dcb->dch_oper                 = BTA_HL_DCH_OP_LOCAL_OPEN;
+                                p_dcb->sec_mask                 = p_data->api_dch_open.sec_mask;
+                                p_dcb->local_mdep_id            = p_data->api_dch_open.local_mdep_id;
+                                p_dcb->peer_mdep_id             = p_data->api_dch_open.peer_mdep_id;
+
+                                if (p_mdep_cfg->mdep_role == BTA_HL_MDEP_ROLE_SINK)
+                                {
+                                    p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SOURCE;
+                                }
+                                else
+                                {
+                                    p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SINK;
+                                }
+
+                                p_dcb->local_mdep_cfg_idx   = mdep_cfg_idx;
+                                p_dcb->local_cfg            = p_data->api_dch_open.local_cfg;
+
+                                bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+                                                           &p_dcb->max_rx_apdu_size,
+                                                           &p_dcb->max_tx_apdu_size);
+                                p_dcb->mdl_id               = bta_hl_allocate_mdl_id(app_idx,mcl_idx,mdl_idx);
+                                p_dcb->mdl_cfg_idx_included = FALSE;
+                            }
+                            else
+                            {
+                                status =  BTA_HL_STATUS_INVALID_CTRL_PSM;
+                            }
+
+                        }
+                        else
+                        {
+                            status =  BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID;
+                        }
+                    }
+                }
+                else
+                {
+                    status =  BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID;
+                }
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_RESOURCE;
+            }
+        }
+        else
+        {
+            status =  BTA_HL_STATUS_NO_CCH;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_dch_open status =%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            if (p_mcb->sdp.num_recs)
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_OPEN_EVT, p_data);
+            }
+            else
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+            }
+            break;
+        case BTA_HL_STATUS_INVALID_DCH_CFG:
+        case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+        case BTA_HL_STATUS_NO_CCH:
+        case BTA_HL_STATUS_NO_RESOURCE:
+        case BTA_HL_STATUS_FAIL:
+        case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
+        case BTA_HL_STATUS_INVALID_CTRL_PSM:
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            bta_hl_build_dch_open_cfm(&evt_data,
+                                      p_acb->app_handle,
+                                      p_data->api_dch_open.mcl_handle,
+                                      BTA_HL_INVALID_MDL_HANDLE,
+                                      0,0,0,0,0, status);
+            p_acb->p_cback(BTA_HL_DCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        default:
+            APPL_TRACE_ERROR1("Status code=%d", status);
+            break;
+
+    }
+
+}
+/*******************************************************************************
+**
+** Function         bta_hl_api_dch_close
+**
+** Description      Process the API DCH close request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_close(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx, mdl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+    tBTA_HL_MDL_CB  *p_dcb;
+
+
+    if (bta_hl_find_mdl_idx_using_handle(p_data->api_dch_close.mdl_handle, &app_idx, &mcl_idx, &mdl_idx ))
+    {
+        p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+        if (p_dcb->dch_state != BTA_HL_DCH_OPEN_ST)
+        {
+            status =  BTA_HL_STATUS_FAIL;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MDL_HANDLE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_dch_close status =%s", bta_hl_status_code(status));
+    }
+#endif
+
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+            break;
+        case BTA_HL_STATUS_FAIL:
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            bta_hl_build_dch_close_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       p_data->api_dch_close.mdl_handle,
+                                       status);
+
+            p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        default:
+            APPL_TRACE_ERROR1("Status code=%d", status);
+            break;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_dch_reconnect
+**
+** Description      Process the API DCH reconnect request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_reconnect(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx, mdl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+    tBTA_HL_MDL_CB  *p_dcb;
+    UINT8           mdep_cfg_idx;
+    UINT8           mdl_cfg_idx;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+        if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+        {
+            if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+            {
+                p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+                if (bta_hl_validate_reconnect_params(app_idx, mcl_idx,  &(p_data->api_dch_reconnect),
+                                                     &mdep_cfg_idx, &mdl_cfg_idx ))
+                {
+                    if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx) &&
+                        (p_acb->mdl_cfg[mdl_cfg_idx].dch_mode != BTA_HL_DCH_MODE_RELIABLE))
+                    {
+                        status =  BTA_HL_STATUS_NO_FIRST_RELIABLE;
+                    }
+                    else
+                    {
+                        if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+                        {
+                            p_dcb->in_use                   = TRUE;
+                            p_dcb->dch_oper                 = BTA_HL_DCH_OP_LOCAL_RECONNECT;
+                            p_dcb->sec_mask                 = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+                            p_dcb->local_mdep_id            = p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id;
+                            p_dcb->local_mdep_cfg_idx       = mdep_cfg_idx;
+                            p_dcb->local_cfg                = BTA_HL_DCH_CFG_UNKNOWN;
+                            p_dcb->mdl_id                   = p_data->api_dch_reconnect.mdl_id;
+                            p_dcb->mdl_cfg_idx_included     = TRUE;
+                            p_dcb->mdl_cfg_idx              = mdl_cfg_idx;
+                            p_dcb->dch_mode                 = p_acb->mdl_cfg[mdl_cfg_idx].dch_mode;
+                            bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
+                                                       &p_dcb->max_rx_apdu_size,
+                                                       &p_dcb->max_tx_apdu_size);
+                        }
+                        else
+                        {
+                            status =  BTA_HL_STATUS_INVALID_CTRL_PSM;
+                        }
+                    }
+                }
+                else
+                {
+                    status =  BTA_HL_STATUS_INVALID_RECONNECT_CFG;
+                }
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_RESOURCE;
+            }
+        }
+        else
+        {
+            status =  BTA_HL_STATUS_NO_CCH;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_dch_reconnect status=%s", bta_hl_status_code(status));
+    }
+#endif
+
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            if (p_mcb->sdp.num_recs)
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_RECONNECT_EVT, p_data);
+            }
+            else
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+            }
+            break;
+        case BTA_HL_STATUS_INVALID_RECONNECT_CFG:
+        case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+        case BTA_HL_STATUS_NO_CCH:
+        case BTA_HL_STATUS_NO_RESOURCE:
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            bta_hl_build_dch_open_cfm(&evt_data,
+                                      p_acb->app_handle,
+                                      p_data->api_dch_reconnect.mcl_handle,
+                                      BTA_HL_INVALID_MDL_HANDLE,
+                                      0,p_data->api_dch_reconnect.mdl_id,0,0,0, status);
+            p_acb->p_cback(BTA_HL_DCH_RECONNECT_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        default:
+            APPL_TRACE_ERROR1("Status code=%d", status);
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_dch_echo_test
+**
+** Description      Process the API Echo test request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_echo_test(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL             evt_data;
+    tBTA_HL_STATUS      status = BTA_HL_STATUS_OK;
+    UINT8               app_idx, mcl_idx, mdl_idx;
+    tBTA_HL_APP_CB      *p_acb;
+    tBTA_HL_MCL_CB      *p_mcb;
+    tBTA_HL_MDL_CB      *p_dcb;
+    tBTA_HL_ECHO_CFG    *p_echo_cfg;
+
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_echo_test.mcl_handle, &app_idx,  &mcl_idx))
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+        if (p_mcb->cch_state == BTA_HL_CCH_OPEN_ST)
+        {
+            if (!p_mcb->echo_test )
+            {
+                if (bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+                {
+                    p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+
+                    if ((p_data->api_dch_echo_test.local_cfg == BTA_HL_DCH_CFG_RELIABLE) ||
+                        (p_data->api_dch_echo_test.local_cfg == BTA_HL_DCH_CFG_STREAMING))
+                    {
+                        if ((p_dcb->p_echo_tx_pkt = bta_hl_get_buf(p_data->api_dch_echo_test.pkt_size)) != NULL )
+                        {
+                            if (bta_hl_set_ctrl_psm_for_dch(app_idx, mcl_idx, mdl_idx, p_data->api_dch_open.ctrl_psm))
+                            {
+                                p_dcb->in_use                   = TRUE;
+                                p_dcb->dch_oper                 = BTA_HL_DCH_OP_LOCAL_OPEN;
+                                p_dcb->sec_mask                 = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
+                                p_dcb->local_mdep_cfg_idx       = BTA_HL_ECHO_TEST_MDEP_CFG_IDX;
+                                p_dcb->local_cfg                = p_data->api_dch_echo_test.local_cfg;
+                                p_dcb->local_mdep_id            = BTA_HL_ECHO_TEST_MDEP_ID;
+                                p_dcb->peer_mdep_id             = BTA_HL_ECHO_TEST_MDEP_ID;
+                                p_dcb->mdl_id                   = bta_hl_allocate_mdl_id(app_idx,mcl_idx,mdl_idx);
+                                p_dcb->mdl_cfg_idx_included     = FALSE;
+                                p_echo_cfg                      = BTA_HL_GET_ECHO_CFG_PTR(app_idx);
+                                p_dcb->max_rx_apdu_size         = p_echo_cfg->max_rx_apdu_size;
+                                p_dcb->max_tx_apdu_size         = p_echo_cfg->max_tx_apdu_size;
+                                p_mcb->echo_test                = TRUE;
+                                p_mcb->echo_mdl_idx             = mdl_idx;
+                            }
+                            else
+                            {
+                                status =  BTA_HL_STATUS_INVALID_CTRL_PSM;
+                            }
+                        }
+                        else
+                        {
+                            status = BTA_HL_STATUS_NO_RESOURCE;
+                        }
+                    }
+                    else
+                    {
+                        status = BTA_HL_STATUS_INVALID_DCH_CFG;
+                    }
+                }
+                else
+                {
+                    status = BTA_HL_STATUS_NO_RESOURCE;
+                }
+            }
+            else
+            {
+                status = BTA_HL_STATUS_ECHO_TEST_BUSY;
+            }
+        }
+        else
+        {
+            status =  BTA_HL_STATUS_NO_CCH;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_NO_MCL;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_dch_echo_test status=%s", bta_hl_status_code(status));
+    }
+#endif
+
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            if (p_mcb->sdp.num_recs)
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ECHO_TEST_EVT, p_data);
+            }
+            else
+            {
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_INIT_EVT, p_data);
+            }
+            break;
+        case BTA_HL_STATUS_NO_CCH:
+        case BTA_HL_STATUS_ECHO_TEST_BUSY:
+        case BTA_HL_STATUS_NO_RESOURCE:
+        case BTA_HL_STATUS_INVALID_DCH_CFG:
+            bta_hl_build_echo_test_cfm(&evt_data,
+                                       p_acb->app_handle,
+                                       p_mcb->mcl_handle,
+                                       status);
+            p_acb->p_cback(BTA_HL_DCH_ECHO_TEST_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+
+        default:
+            APPL_TRACE_ERROR1("Status code=%s", status);
+            break;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_sdp_query
+**
+** Description      Process the API SDP query request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_sdp_query(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+
+
+    if (bta_hl_find_app_idx_using_handle(p_data->api_sdp_query.app_handle, &app_idx))
+    {
+        if (!bta_hl_find_mcl_idx(app_idx, p_data->api_sdp_query.bd_addr, &mcl_idx))
+        {
+            if (bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                p_mcb->in_use = TRUE;
+                bdcpy(p_mcb->bd_addr, p_data->api_sdp_query.bd_addr);
+                p_mcb->sdp_oper  = BTA_HL_SDP_OP_SDP_QUERY_NEW ;
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_RESOURCE;
+            }
+        }
+        else
+        {
+            p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            if (p_mcb->sdp_oper != BTA_HL_SDP_OP_NONE)
+            {
+                status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+            }
+            else
+            {
+                p_mcb->sdp_oper  = BTA_HL_SDP_OP_SDP_QUERY_CURRENT;
+            }
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_APP_HANDLE;
+    }
+
+    if (status == BTA_HL_STATUS_OK)
+    {
+        status = bta_hl_init_sdp( p_mcb->sdp_oper, app_idx, mcl_idx, 0xFF);
+        if ( (status != BTA_HL_STATUS_OK) &&
+             (p_mcb->sdp_oper == BTA_HL_SDP_OP_SDP_QUERY_NEW) )
+        {
+            memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+        }
+    }
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_sdp_query status=%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_NO_RESOURCE:
+        case BTA_HL_STATUS_FAIL:
+        case BTA_HL_STATUS_SDP_NO_RESOURCE:
+            bta_hl_build_sdp_query_cfm(&evt_data,
+                                       p_data->api_sdp_query.app_handle,
+                                       p_data->api_sdp_query.bd_addr,
+                                       NULL,
+                                       status);
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        case BTA_HL_STATUS_OK:
+            break;
+        default:
+            APPL_TRACE_ERROR1("Status code=%d", status);
+            break;
+    }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_sdp_query_results
+**
+** Description      Process the SDP query results
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_sdp_query_results(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL             evt_data;
+    tBTA_HL_STATUS      status = BTA_HL_STATUS_OK;
+    UINT8               app_idx = p_data->cch_sdp.app_idx;
+    UINT8               mcl_idx = p_data->cch_sdp.mcl_idx;
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR( app_idx);
+    tBTA_HL_MCL_CB      *p_mcb =  BTA_HL_GET_MCL_CB_PTR( app_idx,  mcl_idx);
+    tBTA_HL_SDP         *p_sdp=NULL;
+    tBTA_HL_SDP_OPER    sdp_oper;
+    UINT16              event;
+    BOOLEAN             release_sdp_buf=FALSE;
+
+    event = p_data->hdr.event;
+    sdp_oper = p_mcb->sdp_oper;
+
+    if ( event == BTA_HL_SDP_QUERY_OK_EVT)
+    {
+        if ((p_sdp = (tBTA_HL_SDP *)GKI_getbuf((UINT16)(sizeof(tBTA_HL_SDP)))) != NULL)
+        {
+            memcpy(p_sdp, &p_mcb->sdp, sizeof(tBTA_HL_SDP));
+            release_sdp_buf = TRUE;
+        }
+        else
+        {
+            status = BTA_HL_STATUS_SDP_NO_RESOURCE;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_SDP_FAIL;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_sdp_query_results status=%s", bta_hl_status_code(status));
+    }
+#endif
+
+    bta_hl_build_sdp_query_cfm(&evt_data,p_acb->app_handle,
+                               p_mcb->bd_addr,p_sdp,status);
+    p_acb->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+
+    if (release_sdp_buf)
+    {
+        utl_freebuf((void **) &p_sdp);
+    }
+
+    if (p_data->cch_sdp.release_mcl_cb)
+    {
+        memset(p_mcb, 0 ,sizeof(tBTA_HL_MCL_CB));
+    }
+    else
+    {
+        if (p_mcb->close_pending)
+        {
+            bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
+        }
+
+        if (!p_mcb->ctrl_psm)
+        {
+            /* this is a control channel acceptor do not store the sdp records*/
+            memset(&p_mcb->sdp, 0, sizeof(tBTA_HL_SDP));
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_delete_mdl
+**
+** Description      Process the API DELETE MDL request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_delete_mdl(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_delete_mdl.mcl_handle, &app_idx, &mcl_idx ))
+    {
+        if (bta_hl_is_mdl_value_valid(p_data->api_delete_mdl.mdl_id))
+        {
+            p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            if (bta_hl_is_mdl_exsit_in_mcl(app_idx,
+                                           p_mcb->bd_addr,
+                                           p_data->api_delete_mdl.mdl_id))
+            {
+
+
+                p_mcb->delete_mdl.mcl_handle =  p_data->api_delete_mdl.mcl_handle;
+                p_mcb->delete_mdl.mdl_id = p_data->api_delete_mdl.mdl_id;
+                p_mcb->delete_mdl.delete_req_pending = TRUE;
+
+                if (MCA_Delete((tMCA_CL) p_mcb->mcl_handle,
+                               p_data->api_delete_mdl.mdl_id)!= MCA_SUCCESS)
+                {
+                    status = BTA_HL_STATUS_FAIL;
+                    memset(&p_mcb->delete_mdl, 0, sizeof(tBTA_HL_DELETE_MDL));
+                }
+            }
+            else
+            {
+                status = BTA_HL_STATUS_NO_MDL_ID_FOUND;
+            }
+        }
+        else
+        {
+            status = BTA_HL_STATUS_INVALID_MDL_ID;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_delete_mdl status=%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            break;
+        case BTA_HL_STATUS_FAIL:
+        case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+        case BTA_HL_STATUS_INVALID_MDL_ID:
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            bta_hl_build_delete_mdl_cfm(&evt_data,
+                                        p_acb->app_handle,
+                                        p_data->api_delete_mdl.mcl_handle,
+                                        p_data->api_delete_mdl.mdl_id,
+                                        status);
+
+            p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        case BTA_HL_STATUS_INVALID_APP_HANDLE:
+        default:
+            APPL_TRACE_ERROR1("status code =%d", status);
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_mca_delete_mdl_cfm
+**
+** Description      Process the DELETE MDL confirmation event
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_mca_delete_mdl_cfm(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx;
+    tMCA_RSP_EVT    *p_delete_cfm = &p_data->mca_evt.mca_data.delete_cfm;
+    tBTA_HL_MCL_CB  *p_mcb;
+    BOOLEAN         send_cfm_evt = TRUE;
+    tBTA_HL_APP_CB  *p_acb;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->mca_evt.mcl_handle, &app_idx, &mcl_idx))
+    {
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+        if ( p_mcb->delete_mdl.delete_req_pending)
+        {
+            if (p_delete_cfm->rsp_code == MCA_RSP_SUCCESS   )
+            {
+
+                if (!bta_hl_delete_mdl_cfg(app_idx,
+                                           p_mcb->bd_addr ,
+                                           p_delete_cfm->mdl_id))
+                {
+                    status = BTA_HL_STATUS_FAIL;
+                }
+            }
+            else
+            {
+                status = BTA_HL_STATUS_FAIL;
+            }
+
+            memset(&p_mcb->delete_mdl, 0, sizeof(tBTA_HL_DELETE_MDL));
+        }
+        else
+        {
+            send_cfm_evt = FALSE;
+        }
+    }
+    else
+    {
+        send_cfm_evt = FALSE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_delete_mdl status=%s", bta_hl_status_code(status));
+    }
+#endif
+
+    if (send_cfm_evt)
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        bta_hl_build_delete_mdl_cfm(&evt_data,
+                                    p_acb->app_handle,
+                                    p_mcb->mcl_handle,
+                                    p_delete_cfm->mdl_id,
+                                    status);
+
+        p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_mca_delete_mdl_ind
+**
+** Description      Process the DELETE MDL indication event
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_mca_delete_mdl_ind(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+    tBTA_HL         evt_data;
+    UINT8           app_idx, mcl_idx, mdl_idx;
+    tMCA_EVT_HDR    *p_delete_ind = &p_data->mca_evt.mca_data.delete_ind;
+    tBTA_HL_MCL_CB  *p_mcb;
+    tBTA_HL_MDL_CB  *p_dcb;
+    BOOLEAN         send_ind_evt = TRUE;
+    tBTA_HL_APP_CB  *p_acb;
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->mca_evt.mcl_handle, &app_idx, &mcl_idx) )
+    {
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+
+        if (bta_hl_find_mdl_idx(app_idx, mcl_idx, p_delete_ind->mdl_id, &mdl_idx ))
+        {
+            p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+            p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_DELETE;
+        }
+        if (bta_hl_delete_mdl_cfg(app_idx,
+                                  p_mcb->bd_addr ,
+                                  p_delete_ind->mdl_id))
+        {
+            send_ind_evt = TRUE;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!send_ind_evt)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_mca_delete_mdl_ind is_send_ind_evt =%d", send_ind_evt);
+    }
+#endif
+
+    if (send_ind_evt)
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+        evt_data.delete_mdl_ind.mcl_handle = p_mcb->mcl_handle;
+        evt_data.delete_mdl_ind.app_handle = p_acb->app_handle;
+        evt_data.delete_mdl_ind.mdl_id = p_delete_ind->mdl_id;
+        p_acb->p_cback(BTA_HL_DELETE_MDL_IND_EVT,(tBTA_HL *) &evt_data );
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_api_dch_abort
+**
+** Description      Process the API DCH abort request
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_hl_api_dch_abort(tBTA_HL_CB *p_cb, tBTA_HL_DATA *p_data)
+{
+
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    UINT8           app_idx, mcl_idx, mdl_idx;
+    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_MCL_CB  *p_mcb;
+    tBTA_HL_MDL_CB  *p_dcb;
+    tBTA_HL         evt_data;
+
+
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_abort.mcl_handle, &app_idx, &mcl_idx ))
+    {
+
+        if (!bta_hl_find_dch_setup_mdl_idx(app_idx, mcl_idx, &mdl_idx ))
+        {
+            status = BTA_HL_STATUS_NO_MDL_ID_FOUND;
+        }
+        else
+        {
+            p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+            if (p_dcb->abort_oper)
+            {
+                /* abort already in progress*/
+                status = BTA_HL_STATUS_FAIL;
+            }
+            else
+            {
+                p_dcb->abort_oper = BTA_HL_ABORT_LOCAL_MASK;
+            }
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_INVALID_MCL_HANDLE;
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+    if (status != BTA_HL_STATUS_OK)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_api_dch_abort status=%s", bta_hl_status_code(status));
+    }
+#endif
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+            break;
+        case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+        case BTA_HL_STATUS_FAIL:
+
+            p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            bta_hl_build_abort_cfm(&evt_data,
+                                   p_acb->app_handle,
+                                   p_mcb->mcl_handle,
+                                   BTA_HL_STATUS_FAIL);
+            p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT,(tBTA_HL *) &evt_data );
+            break;
+        case BTA_HL_STATUS_INVALID_BD_ADDR:
+        case BTA_HL_STATUS_INVALID_APP_HANDLE:
+        default:
+            APPL_TRACE_ERROR1("Status code=%d", status);
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_hdl_event
+**
+** Description      HL main event handling function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_hl_hdl_event(BT_HDR *p_msg)
+{
+    UINT8 app_idx, mcl_idx, mdl_idx;
+    BOOLEAN success = TRUE;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("BTA HL Event Handler: Event [%s]",
+                      bta_hl_evt_code(p_msg->event));
+#endif
+
+    switch (p_msg->event)
+    {
+        case BTA_HL_API_ENABLE_EVT:
+            bta_hl_api_enable(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DISABLE_EVT:
+            bta_hl_api_disable(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_REGISTER_EVT:
+            bta_hl_api_register(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DEREGISTER_EVT:
+            bta_hl_api_deregister(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_CCH_OPEN_EVT:
+            bta_hl_api_cch_open(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_CCH_CLOSE_EVT:
+            bta_hl_api_cch_close(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DCH_OPEN_EVT:
+            bta_hl_api_dch_open(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DCH_CLOSE_EVT:
+            bta_hl_api_dch_close(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DELETE_MDL_EVT:
+            bta_hl_api_delete_mdl(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DCH_RECONNECT_EVT:
+            bta_hl_api_dch_reconnect(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+        case BTA_HL_API_DCH_ECHO_TEST_EVT:
+            bta_hl_api_dch_echo_test(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+        case BTA_HL_API_SDP_QUERY_EVT:
+            bta_hl_api_sdp_query(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+        case BTA_HL_MCA_DELETE_CFM_EVT:
+            bta_hl_mca_delete_mdl_cfm(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+        case BTA_HL_MCA_DELETE_IND_EVT:
+            bta_hl_mca_delete_mdl_ind(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+        case BTA_HL_SDP_QUERY_OK_EVT:
+        case BTA_HL_SDP_QUERY_FAIL_EVT:
+            bta_hl_sdp_query_results(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+        case BTA_HL_API_DCH_ABORT_EVT:
+            bta_hl_api_dch_abort(&bta_hl_cb, (tBTA_HL_DATA *) p_msg);
+            break;
+
+
+        default:
+            if (p_msg->event < BTA_HL_DCH_EVT_MIN)
+            {
+                if (bta_hl_find_cch_cb_indexes((tBTA_HL_DATA *) p_msg, &app_idx, &mcl_idx))
+                {
+                    bta_hl_cch_sm_execute( app_idx,
+                                           mcl_idx,
+                                           p_msg->event, (tBTA_HL_DATA *) p_msg);
+                }
+                else
+                {
+#if BTA_HL_DEBUG == TRUE
+                    APPL_TRACE_ERROR1("unable to find control block indexes for CCH: [event=%s]",
+                                      bta_hl_evt_code(p_msg->event));
+#else
+                    APPL_TRACE_ERROR1("unable to find control block indexes for CCH: [event=%d]", p_msg->event);
+#endif
+                    success = FALSE;
+                }
+            }
+            else
+            {
+                if (bta_hl_find_dch_cb_indexes((tBTA_HL_DATA *) p_msg, &app_idx, &mcl_idx, &mdl_idx))
+                {
+                    bta_hl_dch_sm_execute( app_idx,
+                                           mcl_idx,
+                                           mdl_idx,
+                                           p_msg->event, (tBTA_HL_DATA *) p_msg);
+                }
+                else
+                {
+
+#if BTA_HL_DEBUG == TRUE
+                    APPL_TRACE_ERROR1("unable to find control block indexes for DCH : [event=%s]",
+                                      bta_hl_evt_code(p_msg->event));
+#else
+                    APPL_TRACE_ERROR1("unable to find control block indexes for DCH: [event=%d]", p_msg->event);
+#endif
+                    success = FALSE;
+                }
+            }
+
+            break;
+    }
+
+    return(success);
+}
+
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE) && (BT_USE_TRACES == TRUE)
+
+/*******************************************************************************
+**
+** Function         bta_hl_cch_state_code
+**
+** Description      Map CCH state code to the corresponding state string
+**
+** Returns          string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_hl_cch_state_code(tBTA_HL_CCH_STATE state_code)
+{
+    switch (state_code)
+    {
+        case BTA_HL_CCH_IDLE_ST:
+            return "BTA_HL_CCH_IDLE_ST";
+        case BTA_HL_CCH_OPENING_ST:
+            return "BTA_HL_CCH_OPENING_ST";
+        case BTA_HL_CCH_OPEN_ST:
+            return "BTA_HL_CCH_OPEN_ST";
+        case BTA_HL_CCH_CLOSING_ST:
+            return "BTA_HL_CCH_CLOSING_ST";
+        default:
+            return "Unknown CCH state code";
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_dch_state_code
+**
+** Description      Map DCH state code to the corresponding state string
+**
+** Returns          string pointer for the associated state name
+**
+*******************************************************************************/
+static char *bta_hl_dch_state_code(tBTA_HL_DCH_STATE state_code)
+{
+    switch (state_code)
+    {
+        case BTA_HL_DCH_IDLE_ST:
+            return "BTA_HL_DCH_IDLE_ST";
+        case BTA_HL_DCH_OPENING_ST:
+            return "BTA_HL_DCH_OPENING_ST";
+        case BTA_HL_DCH_OPEN_ST:
+            return "BTA_HL_DCH_OPEN_ST";
+        case BTA_HL_DCH_CLOSING_ST:
+            return "BTA_HL_DCH_CLOSING_ST";
+        default:
+            return "Unknown DCH state code";
+    }
+}
+#endif  /* Debug Functions */
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
new file mode 100644
index 0000000..15620e8
--- /dev/null
+++ b/bta/hl/bta_hl_sdp.c
@@ -0,0 +1,436 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1998-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.
+ *
+ ******************************************************************************/
+
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+#include "sdp_api.h"
+#include "bta_hl_int.h"
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_fill_sup_feature_list
+**
+** Description      Fill the supported features from teh SDP record
+**
+** Returns          TRUE if found, FALSE if not
+**                  If found, the passed protocol list element is filled in.
+**
+*******************************************************************************/
+BOOLEAN bta_hl_fill_sup_feature_list( const tSDP_DISC_ATTR  *p_attr,
+                                      tBTA_HL_SUP_FEATURE_LIST_ELEM *p_list)
+{
+    tSDP_DISC_ATTR  *p_sattr;
+    UINT8           seq_len, item_cnt;
+    UINT8           list_cnt=0;
+    BOOLEAN         status=TRUE;
+
+    for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr; p_attr = p_attr->p_next_attr)
+    {
+        /* mdep sequence */
+        if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE)
+        {
+            return(FALSE);
+        }
+        seq_len =SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
+        item_cnt=0;
+
+        for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4) ; p_sattr = p_sattr->p_next_attr)
+        {
+            /* for each mdep list */
+
+            p_list->list_elem[list_cnt].p_mdep_desp = NULL;
+            switch (item_cnt)
+            {
+                case 0:
+                    p_list->list_elem[list_cnt].mdep_id = p_sattr->attr_value.v.u8;
+                    break;
+                case 1:
+                    p_list->list_elem[list_cnt].data_type = p_sattr->attr_value.v.u16;
+                    break;
+                case 2:
+                    p_list->list_elem[list_cnt].mdep_role = (tBTA_HL_MDEP_ROLE) p_sattr->attr_value.v.u8;
+                    break;
+                case 3:
+                    p_list->list_elem[list_cnt].p_mdep_desp    = (char *) p_sattr->attr_value.v.array;
+                    break;
+            }
+
+            item_cnt++;
+        }
+        list_cnt++;
+    }
+    p_list->num_elems = list_cnt;
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_compose_supported_feature_list
+**
+** Description      This function is called to compose a data sequence from
+**                  the supported  feature element list struct pointer
+**
+** Returns          the length of the data sequence
+**
+*******************************************************************************/
+int bta_hl_compose_supported_feature_list( UINT8 *p, UINT16 num_elem,
+                                           const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list)
+{
+    UINT16          xx, str_len, seq_len;
+    UINT8           *p_head = p;
+
+    for (xx = 0; xx < num_elem; xx++, p_elem_list++)
+    {
+        UINT8_TO_BE_STREAM  (p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+        seq_len=7;
+        str_len=0;
+        if (p_elem_list->p_mdep_desp)
+        {
+            str_len = strlen(p_elem_list->p_mdep_desp)+1;
+            seq_len += str_len+2; /* todo add a # symbol for 2 */
+        }
+
+        *p++ = (UINT8) seq_len;
+
+        UINT8_TO_BE_STREAM  (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
+        UINT8_TO_BE_STREAM  (p, p_elem_list->mdep_id);
+        UINT8_TO_BE_STREAM  (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
+        UINT16_TO_BE_STREAM (p, p_elem_list->data_type);
+        UINT8_TO_BE_STREAM  (p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
+        UINT8_TO_BE_STREAM  (p, p_elem_list->mdep_role);
+
+        if (str_len)
+        {
+            UINT8_TO_BE_STREAM  (p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+            UINT8_TO_BE_STREAM  (p, str_len);
+            ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len);
+        }
+    }
+
+    return(p - p_head);
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_add_sup_feature_list
+**
+** Description      This function is called to add a protocol descriptor list to
+**                  a record. This would be through the SDP database maintenance API.
+**                  If the protocol list already exists in the record, it is replaced
+**                  with the new list.
+**
+** Returns          TRUE if added OK, else FALSE
+**
+*******************************************************************************/
+BOOLEAN bta_hl_add_sup_feature_list (UINT32 handle, UINT16 num_elem,
+                                     const tBTA_HL_SUP_FEATURE_ELEM *p_elem_list)
+{
+    UINT8       *p_buf;
+    int         offset;
+    BOOLEAN     result = FALSE;
+
+    if ((p_buf = (UINT8 *)GKI_getbuf(BTA_HL_SUP_FEATURE_SDP_BUF_SIZE)) != NULL)
+    {
+        offset = bta_hl_compose_supported_feature_list(p_buf, num_elem, p_elem_list);
+        result = SDP_AddAttribute (handle, ATTR_ID_HDP_SUP_FEAT_LIST,
+                                   DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buf);
+        GKI_freebuf(p_buf);
+    }
+    return result;
+}
+/*****************************************************************************
+**
+**  Function:    bta_hl_sdp_register
+**
+**  Purpose:     Register an HDP application with SDP
+**
+**  Parameters:  p_cb           - Pointer to MA instance control block
+**               p_service_name - MA server name
+**               inst_id        - MAS instance ID
+**               msg_type       - Supported message type(s)
+**
+**
+**  Returns:     void
+**
+*****************************************************************************/
+tBTA_HL_STATUS bta_hl_sdp_register (UINT8 app_idx)
+{
+    UINT16                          svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
+    tSDP_PROTOCOL_ELEM              proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
+    tSDP_PROTO_LIST_ELEM            add_proto_list;
+    tBTA_HL_SUP_FEATURE_LIST_ELEM   sup_feature_list;
+    UINT16                          browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
+    UINT8                           i,j, cnt,mdep_id, mdep_role;
+    UINT8                           data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
+    UINT8                           mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
+    UINT16                          profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
+    UINT16                          version = BTA_HL_VERSION_01_00;
+    UINT8                           num_services=1;
+    tBTA_HL_APP_CB                  *p_cb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    BOOLEAN                         result = TRUE;
+    tBTA_HL_STATUS                  status = BTA_HL_STATUS_OK;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_sdp_register app_idx=%d",app_idx);
+#endif
+
+    if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
+        (!p_cb->sup_feature.advertize_source_sdp))
+    {
+        return BTA_HL_STATUS_OK;
+    }
+
+    if ((p_cb->sdp_handle  = SDP_CreateRecord()) == 0)
+    {
+        return BTA_HL_STATUS_SDP_NO_RESOURCE;
+    }
+
+    num_services=1;
+    svc_class_id_list[0]= UUID_SERVCLASS_HDP_SOURCE;
+    if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK)
+    {
+        svc_class_id_list[0]= UUID_SERVCLASS_HDP_SINK;
+    }
+    else
+    {
+        if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE)
+        {
+            /* dual role */
+            num_services=2;
+            svc_class_id_list[1]= UUID_SERVCLASS_HDP_SINK;
+        }
+    }
+    result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services, svc_class_id_list);
+
+    if (result)
+    {
+        /* add the protocol element sequence */
+        proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+        proto_elem_list[0].num_params = 1;
+        proto_elem_list[0].params[0] = p_cb->ctrl_psm;
+        proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
+        proto_elem_list[1].num_params = 1;
+        proto_elem_list[1].params[0] = version;
+        result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS, proto_elem_list);
+
+        result &= SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
+    }
+
+    if (result)
+    {
+        add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
+        add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
+        add_proto_list.list_elem[0].num_params = 1;
+        add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
+        add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
+        add_proto_list.list_elem[1].num_params = 0;
+        result &= SDP_AddAdditionProtoLists(p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS,
+                                            (tSDP_PROTO_LIST_ELEM *)&add_proto_list);
+    }
+
+    if (result)
+    {
+        if (p_cb->srv_name[0] )
+        {
+            result &= SDP_AddAttribute(p_cb->sdp_handle,
+                                       (UINT16)ATTR_ID_SERVICE_NAME,
+                                       (UINT8)TEXT_STR_DESC_TYPE,
+                                       (UINT32)(strlen(p_cb->srv_name) + 1),
+                                       (UINT8 *)p_cb->srv_name);
+        } /* end of setting optional service name */
+    }
+
+    if (result)
+    {
+        if (p_cb->srv_desp[0] )
+        {
+            result &= SDP_AddAttribute(p_cb->sdp_handle,
+                                       (UINT16)ATTR_ID_SERVICE_DESCRIPTION,
+                                       (UINT8)TEXT_STR_DESC_TYPE,
+                                       (UINT32)(strlen(p_cb->srv_desp) + 1),
+                                       (UINT8 *)p_cb->srv_desp);
+
+        } /* end of setting optional service description */
+
+    }
+
+    if (result)
+    {
+        if (p_cb->provider_name[0] )
+        {
+            result &= SDP_AddAttribute(p_cb->sdp_handle,
+                                       (UINT16)ATTR_ID_PROVIDER_NAME,
+                                       (UINT8)TEXT_STR_DESC_TYPE,
+                                       (UINT32)(strlen(p_cb->provider_name) + 1),
+                                       (UINT8 *)p_cb->provider_name);
+        } /* end of setting optional provider name */
+    }
+
+    /* add supported feture list */
+
+    if (result)
+    {
+        cnt=0;
+        for (i=1; i<= p_cb->sup_feature.num_of_mdeps; i++)
+        {
+            mdep_id = (UINT8)p_cb->sup_feature.mdep[i].mdep_id;
+            mdep_role = (UINT8)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
+
+            for (j=0; j<p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types; j++)
+            {
+                sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
+                sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
+                sup_feature_list.list_elem[cnt].data_type = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
+                if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0')
+                {
+                    sup_feature_list.list_elem[cnt].p_mdep_desp = p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
+                }
+                else
+                {
+                    sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
+                }
+
+                cnt++;
+                if (cnt>BTA_HL_NUM_SUP_FEATURE_ELEMS)
+                {
+                    result = FALSE;
+                    break;
+                }
+            }
+        }
+        sup_feature_list.num_elems = cnt;
+        result &=   bta_hl_add_sup_feature_list (p_cb->sdp_handle,
+                                                 sup_feature_list.num_elems,
+                                                 sup_feature_list.list_elem);
+    }
+    if (result)
+    {
+        result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC, UINT_DESC_TYPE,
+                                   (UINT32)1, (UINT8*)&data_exchange_spec);
+    }
+
+    if (result)
+    {
+
+        result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC, UINT_DESC_TYPE,
+                                   (UINT32)1, (UINT8*)&mcap_sup_proc);
+    }
+
+    if (result)
+    {
+        result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, browse_list);
+    }
+
+    if (result)
+    {
+        for(i=0; i < num_services; i++)
+        {
+            bta_sys_add_uuid(svc_class_id_list[i]);
+            APPL_TRACE_DEBUG2("dbg bta_sys_add_uuid i=%d uuid=0x%x", i, svc_class_id_list[i]); //todo
+        }
+    }
+    else
+    {
+        if (p_cb->sdp_handle)
+        {
+            SDP_DeleteRecord(p_cb->sdp_handle);
+            p_cb->sdp_handle = 0;
+        }
+        status = BTA_HL_STATUS_SDP_FAIL;
+    }
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_sdp_register status=%s", bta_hl_status_code(status));
+#endif
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_find_sink_or_src_srv_class_in_db
+**
+** Description      This function queries an SDP database for either a HDP Sink or
+**                  Source service class ID.
+**                  If the p_start_rec pointer is NULL, it looks from the beginning
+**                  of the database, else it continues from the next record after
+**                  p_start_rec.
+**
+** Returns          Pointer to record containing service class, or NULL
+**
+*******************************************************************************/
+tSDP_DISC_REC *bta_hl_find_sink_or_src_srv_class_in_db (const tSDP_DISCOVERY_DB *p_db,
+                                                        const tSDP_DISC_REC *p_start_rec)
+{
+#if SDP_CLIENT_ENABLED == TRUE
+    tSDP_DISC_REC   *p_rec;
+    tSDP_DISC_ATTR  *p_attr, *p_sattr;
+
+    /* Must have a valid database */
+    if (p_db == NULL)
+        return(NULL);
+
+
+    if (!p_start_rec)
+    {
+
+        p_rec = p_db->p_first_rec;
+    }
+    else
+    {
+        p_rec = p_start_rec->p_next_rec;
+    }
+
+    while (p_rec)
+    {
+        p_attr = p_rec->p_first_attr;
+        while (p_attr)
+        {
+            if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST)
+                && (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE))
+            {
+                for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr; p_sattr = p_sattr->p_next_attr)
+                {
+                    if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE)
+                        && (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2)
+                        && ( (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK) ||
+                             (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE)) )
+                    {
+                        return(p_rec);
+                    }
+                }
+                break;
+            }
+
+            p_attr = p_attr->p_next_attr;
+        }
+
+        p_rec = p_rec->p_next_rec;
+    }
+#endif
+    /* If here, no matching UUID found */
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_find_sink_or_src_srv_class_in_db failed");
+#endif
+
+    return(NULL);
+}
+#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
new file mode 100644
index 0000000..7f94a9c
--- /dev/null
+++ b/bta/hl/bta_hl_utils.c
@@ -0,0 +1,3337 @@
+/******************************************************************************
+ *
+ *  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 implements utility functions for the HeaLth device profile
+ *  (HL).
+ *
+ ******************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bt_target.h"
+#if defined(HL_INCLUDED) && (HL_INCLUDED == TRUE)
+
+
+#include "gki.h"
+#include "utl.h"
+#include "bd.h"
+#include "bta_fs_api.h"
+#include "bta_hl_int.h"
+#include "bta_hl_co.h"
+#include "mca_defs.h"
+#include "mca_api.h"
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_ctrl_psm_for_dch
+**
+** Description    This function set the control PSM for the DCH setup
+**
+** Returns     BOOLEAN - TRUE - control PSM setting is successful
+*******************************************************************************/
+BOOLEAN bta_hl_set_ctrl_psm_for_dch(UINT8 app_idx, UINT8 mcl_idx,
+                                    UINT8 mdl_idx, UINT16 ctrl_psm)
+{
+    tBTA_HL_MCL_CB *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN success = TRUE, update_ctrl_psm = FALSE;
+
+    if (p_mcb->sdp.num_recs)
+    {
+        if (p_mcb->ctrl_psm != ctrl_psm)
+        {
+            /* can not use a different ctrl PSM than the current one*/
+            success = FALSE;
+        }
+    }
+    else
+    {
+        /* No SDP info control i.e. channel was opened by the peer */
+        update_ctrl_psm = TRUE;
+    }
+
+    if (success && update_ctrl_psm)
+    {
+        p_mcb->ctrl_psm = ctrl_psm;
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+    if (!success)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_set_ctrl_psm_for_dch num_recs=%d success=%d update_ctrl_psm=%d ctrl_psm=0x%x ",
+                          p_mcb->sdp.num_recs, success, update_ctrl_psm, ctrl_psm );
+    }
+#endif
+
+    return success;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_sdp_idx_using_ctrl_psm
+**
+** Description
+**
+** Returns      UINT8 pool_id
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP *p_sdp,
+                                           UINT16 ctrl_psm,
+                                           UINT8 *p_sdp_idx)
+{
+    BOOLEAN found=FALSE;
+    tBTA_HL_SDP_REC     *p_rec;
+    UINT8 i;
+
+    if (ctrl_psm != 0)
+    {
+        for (i=0; i<p_sdp->num_recs; i++)
+        {
+            p_rec = &p_sdp->sdp_rec[i];
+            if (p_rec->ctrl_psm == ctrl_psm)
+            {
+                *p_sdp_idx = i;
+                found = TRUE;
+                break;
+            }
+        }
+    }
+    else
+    {
+        *p_sdp_idx = 0;
+        found = TRUE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_sdp_idx_using_ctrl_psm found=%d sdp_idx=%d ctrl_psm=0x%x ",
+                          found, *p_sdp_idx, ctrl_psm );
+    }
+#endif
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_user_tx_pool_id
+**
+** Description  This function sets the user tx pool id
+**
+** Returns      UINT8 pool_id
+**
+*******************************************************************************/
+
+UINT8 bta_hl_set_user_tx_pool_id(UINT16 max_tx_size)
+{
+    UINT8 pool_id;
+
+    if (max_tx_size > GKI_get_pool_bufsize (OBX_FCR_TX_POOL_ID))
+    {
+        pool_id = BTA_HL_LRG_DATA_POOL_ID;
+    }
+    else
+    {
+        pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG3("bta_hl_set_user_rx_pool_id pool_id=%d max_tx_size=%d default_ertm_pool_size=%d",
+                      pool_id, max_tx_size, GKI_get_pool_bufsize (OBX_FCR_TX_POOL_ID));
+#endif
+
+    return pool_id;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_user_rx_pool_id
+**
+** Description  This function sets the user trx pool id
+**
+** Returns      UINT8 pool_id
+**
+*******************************************************************************/
+
+UINT8 bta_hl_set_user_rx_pool_id(UINT16 mtu)
+{
+    UINT8 pool_id;
+
+    if (mtu > GKI_get_pool_bufsize (OBX_FCR_RX_POOL_ID))
+    {
+        pool_id = BTA_HL_LRG_DATA_POOL_ID;
+    }
+    else
+    {
+        pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG3("bta_hl_set_user_rx_pool_id pool_id=%d mtu=%d default_ertm_pool_size=%d",
+                      pool_id, mtu, GKI_get_pool_bufsize (OBX_FCR_RX_POOL_ID));
+#endif
+
+    return pool_id;
+}
+
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_tx_win_size
+**
+** Description  This function sets the tx window size
+**
+** Returns      UINT8 tx_win_size
+**
+*******************************************************************************/
+UINT8 bta_hl_set_tx_win_size(UINT16 mtu, UINT16 mps)
+{
+    UINT8 tx_win_size;
+
+    if (mtu <= mps)
+    {
+        tx_win_size =1;
+    }
+    else
+    {
+        if (mps > 0)
+        {
+            tx_win_size = (mtu/mps)+1;
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("The MPS is zero");
+            tx_win_size = 10;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG3("bta_hl_set_tx_win_size win_size=%d mtu=%d mps=%d",
+                      tx_win_size, mtu, mps);
+#endif
+    return tx_win_size;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_mps
+**
+** Description  This function sets the MPS
+**
+** Returns      UINT16 MPS
+**
+*******************************************************************************/
+UINT16 bta_hl_set_mps(UINT16 mtu)
+{
+    UINT16 mps;
+    if (mtu > BTA_HL_L2C_MPS)
+    {
+        mps = BTA_HL_L2C_MPS;
+    }
+    else
+    {
+        mps = mtu;
+    }
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG2("bta_hl_set_mps mps=%d mtu=%d",
+                      mps, mtu);
+#endif
+    return mps;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_clean_mdl_cb
+**
+** Description  This function clean up the specified MDL control block
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_hl_clean_mdl_cb(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx)
+{
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG3("bta_hl_clean_mdl_cb app_idx=%d mcl_idx=%d mdl_idx=%d",
+                      app_idx, mcl_idx, mdl_idx);
+#endif
+    utl_freebuf((void **) &p_dcb->p_tx_pkt);
+    utl_freebuf((void **) &p_dcb->p_rx_pkt);
+    utl_freebuf((void **) &p_dcb->p_echo_tx_pkt);
+    utl_freebuf((void **) &p_dcb->p_echo_rx_pkt);
+
+    memset((void *)p_dcb, 0 , sizeof(tBTA_HL_MDL_CB));
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_get_buf
+**
+** Description  This function allocate a buffer based on the specified data size
+**
+** Returns      BT_HDR *.
+**
+*******************************************************************************/
+BT_HDR * bta_hl_get_buf(UINT16 data_size)
+{
+    BT_HDR *p_new;
+    UINT16 size = data_size + L2CAP_MIN_OFFSET + BT_HDR_SIZE;
+
+    if (size < GKI_MAX_BUF_SIZE)
+    {
+        p_new = (BT_HDR *)GKI_getbuf(size);
+    }
+    else
+    {
+        p_new = (BT_HDR *) GKI_getpoolbuf(BTA_HL_LRG_DATA_POOL_ID);
+    }
+
+    if (p_new)
+    {
+        p_new->len = data_size;
+        p_new->offset = L2CAP_MIN_OFFSET;
+    }
+
+    return p_new;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_service_in_db
+**
+** Description  This function check the specified service class(es) can be find in
+**              the received SDP database
+**
+** Returns      BOOLEAN TRUE - found
+**                      FALSE - not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_service_in_db( UINT8 app_idx, UINT8 mcl_idx,
+                                   UINT16 service_uuid,
+                                   tSDP_DISC_REC **pp_rec )
+{
+    tBTA_HL_MCL_CB          *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN found = TRUE;
+
+    switch (service_uuid)
+    {
+        case UUID_SERVCLASS_HDP_SINK:
+        case UUID_SERVCLASS_HDP_SOURCE:
+            if ((*pp_rec = SDP_FindServiceInDb(p_mcb->p_db, service_uuid,
+                                               *pp_rec)) == NULL)
+            {
+                found = FALSE;
+            }
+            break;
+        default:
+            if (((*pp_rec = bta_hl_find_sink_or_src_srv_class_in_db(p_mcb->p_db,
+                                                                    *pp_rec)) == NULL))
+            {
+                found = FALSE;
+            }
+            break;
+    }
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_get_service_uuids
+**
+**
+** Description  This function finds the service class(es) for both CCH and DCH oeprations
+**
+** Returns      UINT16 - service_id
+**                       if service_uuid = 0xFFFF then it means service uuid
+**                       can be either Sink or Source
+**
+*******************************************************************************/
+UINT16 bta_hl_get_service_uuids(UINT8 sdp_oper, UINT8 app_idx, UINT8 mcl_idx,
+                                UINT8 mdl_idx )
+{
+    tBTA_HL_MDL_CB          *p_dcb;
+    UINT16                  service_uuid = 0xFFFF; /* both Sink and Source */
+
+    switch (sdp_oper)
+    {
+
+        case BTA_HL_SDP_OP_DCH_OPEN_INIT:
+        case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
+            p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+            if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+            {
+                if (p_dcb->peer_mdep_role == BTA_HL_MDEP_ROLE_SINK)
+                {
+                    service_uuid = UUID_SERVCLASS_HDP_SINK;
+                }
+                else
+                {
+                    service_uuid = UUID_SERVCLASS_HDP_SOURCE;
+                }
+            }
+            break;
+        case BTA_HL_SDP_OP_CCH_INIT:
+        default:
+            /* use default that is both Sink and Source */
+            break;
+    }
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_get_service_uuids service_uuid=0x%x",service_uuid );
+#endif
+    return service_uuid;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_echo_cfg_rsp
+**
+**
+** Description  This function finds the configuration response for the echo test
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_echo_cfg_rsp(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdep_idx, UINT8 cfg,
+                                 UINT8 *p_cfg_rsp)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MDEP        *p_mdep= &p_acb->sup_feature.mdep[mdep_idx];
+    BOOLEAN             status =TRUE;
+
+    if (p_mdep->mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+    {
+        if ((cfg == BTA_HL_DCH_CFG_RELIABLE) || (cfg == BTA_HL_DCH_CFG_STREAMING))
+        {
+            *p_cfg_rsp = cfg;
+        }
+        else if (cfg == BTA_HL_DCH_CFG_NO_PREF )
+        {
+            *p_cfg_rsp = BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG;
+        }
+        else
+        {
+            status = FALSE;
+            APPL_TRACE_ERROR0("Inavlid echo cfg value");
+        }
+        return status;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!status)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_find_echo_cfg_rsp status=failed app_idx=%d mcl_idx=%d mdep_idx=%d cfg=%d",
+                          app_idx, mcl_idx, mdep_idx, cfg);
+    }
+#endif
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_validate_dch_cfg
+**
+** Description  This function validate the DCH configuration
+**
+** Returns      BOOLEAN - TRUE cfg is valid
+**                        FALSE not valid
+**
+*******************************************************************************/
+BOOLEAN bta_hl_validate_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                            UINT8 cfg)
+{
+    tBTA_HL_MDL_CB      *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    BOOLEAN is_valid =FALSE;
+
+
+    if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx) &&
+        (cfg != BTA_HL_DCH_CFG_RELIABLE))
+    {
+        APPL_TRACE_ERROR0("the first DCH should be a reliable channel");
+        return is_valid;
+    }
+
+    switch (p_dcb->local_cfg)
+    {
+        case BTA_HL_DCH_CFG_NO_PREF:
+
+            if ((cfg == BTA_HL_DCH_CFG_RELIABLE) || (cfg == BTA_HL_DCH_CFG_STREAMING))
+            {
+                is_valid = TRUE;
+            }
+            break;
+        case BTA_HL_DCH_CFG_RELIABLE:
+        case BTA_HL_DCH_CFG_STREAMING:
+            if (p_dcb->local_cfg == cfg )
+            {
+                is_valid = TRUE;
+            }
+            break;
+        default:
+            break;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!is_valid)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_validate_dch_open_cfg is_valid=%d, cfg=%d", is_valid, cfg );
+    }
+#endif
+    return is_valid;
+}
+
+/*******************************************************************************
+**
+** Function       bta_hl_find_cch_cb_indexes
+**
+** Description  This function finds the indexes needed for the CCH state machine
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_cch_cb_indexes(tBTA_HL_DATA *p_msg,
+                                   UINT8 *p_app_idx,
+                                   UINT8  *p_mcl_idx)
+{
+    BOOLEAN found = FALSE;
+    tBTA_HL_MCL_CB      *p_mcb;
+    UINT8               app_idx, mcl_idx;
+
+    switch (p_msg->hdr.event)
+    {
+        case BTA_HL_CCH_SDP_OK_EVT:
+        case BTA_HL_CCH_SDP_FAIL_EVT:
+            app_idx = p_msg->cch_sdp.app_idx;
+            mcl_idx = p_msg->cch_sdp.mcl_idx;
+            found = TRUE;
+            break;
+
+        case BTA_HL_MCA_CONNECT_IND_EVT:
+
+            if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle, &app_idx))
+            {
+                if (bta_hl_find_mcl_idx(app_idx, p_msg->mca_evt.mca_data.connect_ind.bd_addr, &mcl_idx))
+                {
+                    /* local initiated */
+                    found = TRUE;
+                }
+                else if (!bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx)&&
+                         bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx))
+                {
+                    /* remote initiated */
+                    p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                    p_mcb->in_use = TRUE;
+                    p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_OPEN;
+                    found = TRUE;
+                }
+            }
+            break;
+
+        case BTA_HL_MCA_DISCONNECT_IND_EVT:
+
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,  &mcl_idx))
+            {
+                found = TRUE;
+            }
+            else if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle, &app_idx) &&
+                     bta_hl_find_mcl_idx(app_idx, p_msg->mca_evt.mca_data.disconnect_ind.bd_addr, &mcl_idx))
+            {
+                found = TRUE;
+            }
+
+            if (found)
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
+                {
+                    p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_CLOSE;
+                }
+            }
+            break;
+
+        case BTA_HL_MCA_RSP_TOUT_IND_EVT:
+
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,  &mcl_idx))
+            {
+                found = TRUE;
+            }
+
+            if (found)
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                if (p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE)
+                {
+                    p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+                }
+            }
+            break;
+        default:
+            break;
+    }
+
+
+    if (found)
+    {
+        *p_app_idx = app_idx;
+        *p_mcl_idx = mcl_idx;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_find_cch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d",
+                          bta_hl_evt_code(p_msg->hdr.event), found, app_idx, mcl_idx);
+    }
+#endif
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function       bta_hl_find_dch_cb_indexes
+**
+** Description  This function finds the indexes needed for the DCH state machine
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_dch_cb_indexes(tBTA_HL_DATA *p_msg,
+                                   UINT8 *p_app_idx,
+                                   UINT8 *p_mcl_idx,
+                                   UINT8 *p_mdl_idx)
+{
+    BOOLEAN         found = FALSE;
+    tBTA_HL_MCL_CB  *p_mcb;
+    UINT8           app_idx, mcl_idx, mdl_idx;
+
+    switch (p_msg->hdr.event)
+    {
+        case BTA_HL_MCA_CREATE_CFM_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,  p_msg->mca_evt.mca_data.create_cfm.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+
+        case BTA_HL_MCA_CREATE_IND_EVT:
+        case BTA_HL_MCA_RECONNECT_IND_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_avail_mdl_idx( app_idx,  mcl_idx, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+
+        case BTA_HL_MCA_OPEN_CFM_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,  p_msg->mca_evt.mca_data.open_cfm.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+
+        case BTA_HL_MCA_OPEN_IND_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,  p_msg->mca_evt.mca_data.open_ind.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+
+        case BTA_HL_MCA_CLOSE_CFM_EVT:
+
+            if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_cfm.mdl,
+                                                 &app_idx, &mcl_idx, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_MCA_CLOSE_IND_EVT:
+
+            if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_ind.mdl,
+                                                 &app_idx, &mcl_idx, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_API_SEND_DATA_EVT:
+
+            if (bta_hl_find_mdl_idx_using_handle(p_msg->api_send_data.mdl_handle,
+                                                 &app_idx, &mcl_idx, &mdl_idx ))
+            {
+                found = TRUE;
+            }
+
+            break;
+
+        case BTA_HL_MCA_CONG_CHG_EVT:
+
+            if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.cong_chg.mdl,
+                                                 &app_idx, &mcl_idx, &mdl_idx ))
+            {
+                found = TRUE;
+            }
+
+            break;
+
+        case BTA_HL_MCA_RCV_DATA_EVT:
+            app_idx = p_msg->mca_rcv_data_evt.app_idx;
+            mcl_idx = p_msg->mca_rcv_data_evt.mcl_idx;
+            mdl_idx = p_msg->mca_rcv_data_evt.mdl_idx;
+            found = TRUE;
+            break;
+        case BTA_HL_DCH_RECONNECT_EVT:
+        case BTA_HL_DCH_OPEN_EVT:
+        case BTA_HL_DCH_ECHO_TEST_EVT:
+        case BTA_HL_DCH_SDP_FAIL_EVT:
+            app_idx = p_msg->dch_sdp.app_idx;
+            mcl_idx = p_msg->dch_sdp.mcl_idx;
+            mdl_idx = p_msg->dch_sdp.mdl_idx;
+            found = TRUE;
+            break;
+        case BTA_HL_MCA_RECONNECT_CFM_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,  p_msg->mca_evt.mca_data.reconnect_cfm.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+
+
+        case BTA_HL_API_DCH_CREATE_RSP_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->api_dch_create_rsp.mcl_handle, &app_idx, &mcl_idx)&&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,p_msg->api_dch_create_rsp.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_MCA_ABORT_IND_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx, &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,p_msg->mca_evt.mca_data.abort_ind.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_MCA_ABORT_CFM_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,  &mcl_idx) &&
+                bta_hl_find_mdl_idx( app_idx,  mcl_idx,  p_msg->mca_evt.mca_data.abort_cfm.mdl_id, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_CI_GET_TX_DATA_EVT:
+        case BTA_HL_CI_PUT_RX_DATA_EVT:
+            if (bta_hl_find_mdl_idx_using_handle(p_msg->ci_get_put_data.mdl_handle, &app_idx, &mcl_idx, &mdl_idx))
+            {
+                found = TRUE;
+            }
+            break;
+        case BTA_HL_CI_GET_ECHO_DATA_EVT:
+        case BTA_HL_CI_PUT_ECHO_DATA_EVT:
+            if (bta_hl_find_mcl_idx_using_handle(p_msg->ci_get_put_echo_data.mcl_handle, &app_idx, &mcl_idx))
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+                mdl_idx = p_mcb->echo_mdl_idx;
+                found = TRUE;
+            }
+            break;
+
+        default:
+            break;
+
+    }
+
+    if (found)
+    {
+        *p_app_idx = app_idx;
+        *p_mcl_idx = mcl_idx;
+        *p_mdl_idx = mdl_idx;
+    }
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG5("bta_hl_find_dch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+                          bta_hl_evt_code(p_msg->hdr.event), found, *p_app_idx, *p_mcl_idx, *p_mdl_idx  );
+    }
+#endif
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_allocate_mdl_id
+**
+** Description  This function allocates a MDL ID
+**
+** Returns      UINT16 - MDL ID
+**
+*******************************************************************************/
+UINT16  bta_hl_allocate_mdl_id(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx )
+{
+    UINT16  mdl_id=0;
+    tBTA_HL_MCL_CB      *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN duplicate_id;
+    UINT8 i, mdl_cfg_idx;
+
+    do
+    {
+        duplicate_id = FALSE;
+        mdl_id = ((mdl_id+1) & 0xFEFF);
+        /* check mdl_ids that are used for the current conenctions */
+        for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+        {
+            if (p_mcb->mdl[i].in_use &&
+                (i != mdl_idx) &&
+                (p_mcb->mdl[i].mdl_id == mdl_id) )
+            {
+                duplicate_id = TRUE;
+                break;
+            }
+        }
+
+        if (duplicate_id)
+        {
+            /* start from the beginning to get another MDL value*/
+            continue;
+        }
+        else
+        {
+            /* check mdl_ids that are stored in the persistent memory */
+            if (bta_hl_find_mdl_cfg_idx(app_idx,mcl_idx, mdl_id, &mdl_cfg_idx))
+            {
+                duplicate_id = TRUE;
+            }
+            else
+            {
+                /* found a new MDL value */
+                break;
+            }
+        }
+
+    }while (TRUE);
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_allocate_mdl OK mdl_id=%d",  mdl_id);
+#endif
+    return mdl_id;
+}
+/*******************************************************************************
+**
+** Function      bta_hl_find_mdl_idx
+**
+** Description  This function finds the MDL index based on mdl_id
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdl_idx(UINT8 app_idx, UINT8 mcl_idx, UINT16 mdl_id,
+                            UINT8 *p_mdl_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+    {
+        if (p_mcb->mdl[i].in_use  &&
+            (mdl_id !=0) &&
+            (p_mcb->mdl[i].mdl_id== mdl_id))
+        {
+            found = TRUE;
+            *p_mdl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_mdl_idx found=%d mdl_id=%d mdl_idx=%d ",
+                          found, mdl_id, i);
+    }
+#endif
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_an_active_mdl_idx
+**
+** Description  This function finds an active MDL
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_active_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                      UINT8 *p_mdl_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+    {
+        if (p_mcb->mdl[i].in_use  &&
+            (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPEN_ST))
+        {
+            found = TRUE;
+            *p_mdl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (found)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_find_an_opened_mdl_idx found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+                          found, app_idx, mcl_idx, i);
+    }
+#endif
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_dch_setup_mdl_idx
+**
+** Description  This function finds a MDL which in the DCH setup state
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_dch_setup_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                      UINT8 *p_mdl_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+    {
+        if (p_mcb->mdl[i].in_use  &&
+            (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPENING_ST))
+        {
+            found = TRUE;
+            *p_mdl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (found)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_find_dch_setup_mdl_idx found=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
+                          found, app_idx, mcl_idx, i);
+    }
+#endif
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_an_in_use_mcl_idx
+**
+** Description  This function finds an in-use MCL control block index
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_in_use_mcl_idx(UINT8 app_idx,
+                                      UINT8 *p_mcl_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb;
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+    {
+        p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, i);
+        if (p_mcb->in_use  &&
+            (p_mcb->cch_state != BTA_HL_CCH_IDLE_ST))
+        {
+            found = TRUE;
+            *p_mcl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_an_in_use_mcl_idx found=%d app_idx=%d mcl_idx=%d ",
+                          found, app_idx, i);
+    }
+#endif
+
+    return found;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_an_in_use_app_idx
+**
+** Description  This function finds an in-use application control block index
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_an_in_use_app_idx(UINT8 *p_app_idx)
+{
+    tBTA_HL_APP_CB      *p_acb ;
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        p_acb  = BTA_HL_GET_APP_CB_PTR(i);
+        if (p_acb->in_use)
+        {
+            found = TRUE;
+            *p_app_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_an_in_use_app_idx found=%d app_idx=%d ",
+                          found, i);
+    }
+#endif
+
+    return found;
+}
+/*******************************************************************************
+**
+** Function      bta_hl_find_app_idx
+**
+** Description  This function finds the application control block index based on
+**              the application ID
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_app_idx(UINT8 app_id, UINT8 *p_app_idx)
+{
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        if (bta_hl_cb.acb[i].in_use &&
+            (bta_hl_cb.acb[i].app_id == app_id))
+        {
+            found = TRUE;
+            *p_app_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG3("bta_hl_find_app_idx found=%d app_id=%d idx=%d ",
+                      found, app_id, i);
+#endif
+
+    return found;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_app_idx_using_handle
+**
+** Description  This function finds the application control block index based on
+**              the application handle
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
+                                         UINT8 *p_app_idx)
+{
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        if (bta_hl_cb.acb[i].in_use &&
+            (bta_hl_cb.acb[i].app_handle == app_handle))
+        {
+            found = TRUE;
+            *p_app_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_app_idx_using_mca_handle status=%d handle=%d app_idx=%d ",
+                          found, app_handle , i);
+    }
+#endif
+
+    return found;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mcl_idx_using_handle
+**
+** Description  This function finds the MCL control block index based on
+**              the MCL handle
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mcl_idx_using_handle( tBTA_HL_MCL_HANDLE mcl_handle,
+                                          UINT8 *p_app_idx, UINT8 *p_mcl_idx)
+{
+    tBTA_HL_APP_CB  *p_acb;
+    BOOLEAN         found=FALSE;
+    UINT8 i,j;
+
+    for (i=0; i<BTA_HL_NUM_APPS; i++)
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(i);
+        if (p_acb->in_use)
+        {
+            for (j=0; j < BTA_HL_NUM_MCLS ; j++)
+            {
+                if ( p_acb->mcb[j].mcl_handle == mcl_handle )
+                {
+                    found = TRUE;
+                    *p_app_idx = i;
+                    *p_mcl_idx = j;
+                    break;
+                }
+            }
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_mcl_idx_using_handle found=%d app_idx=%d mcl_idx=%d",
+                          found, i, j);
+    }
+#endif
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mcl_idx
+**
+** Description  This function finds the MCL control block index based on
+**              the peer BD address
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mcl_idx(UINT8 app_idx, BD_ADDR p_bd_addr, UINT8 *p_mcl_idx)
+{
+    BOOLEAN found=FALSE;
+    UINT8 i;
+    tBTA_HL_MCL_CB  *p_mcb;
+
+    for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+    {
+        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, i);
+
+        if (bta_hl_cb.acb[app_idx].mcb[i].in_use &&
+            (!memcmp (bta_hl_cb.acb[app_idx].mcb[i].bd_addr, p_bd_addr, BD_ADDR_LEN)))
+        {
+            found = TRUE;
+            *p_mcl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_mcl_idx found=%d idx=%d",
+                          found, i);
+    }
+#endif
+    return found;
+}
+
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mdl_idx_using_handle
+**
+** Description  This function finds the MDL control block index based on
+**              the MDL handle
+**
+** Returns      BOOLEAN TRUE-found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
+                                         UINT8 *p_app_idx,UINT8 *p_mcl_idx,
+                                         UINT8 *p_mdl_idx)
+{
+    tBTA_HL_APP_CB      *p_acb;
+    tBTA_HL_MCL_CB      *p_mcb;
+    tBTA_HL_MDL_CB      *p_dcb;
+    BOOLEAN found=FALSE;
+    UINT8 i,j,k;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(i);
+        if (p_acb->in_use)
+        {
+            for (j=0; j< BTA_HL_NUM_MCLS; j++)
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(i,j);
+                if (p_mcb->in_use)
+                {
+                    for (k=0; k< BTA_HL_NUM_MDLS_PER_MCL; k++)
+                    {
+                        p_dcb = BTA_HL_GET_MDL_CB_PTR(i,j,k);
+                        if (p_dcb->in_use)
+                        {
+                            if (p_dcb->mdl_handle == mdl_handle)
+                            {
+                                found = TRUE;
+                                *p_app_idx = i;
+                                *p_mcl_idx =j;
+                                *p_mdl_idx = k;
+                                break;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_mdl_idx_using_handle found=%d mdl_handle=%d  ",
+                          found, mdl_handle);
+    }
+#endif
+    return found;
+}
+/*******************************************************************************
+**
+** Function      bta_hl_is_the_first_reliable_existed
+**
+** Description  This function checks whether the first reliable DCH channel
+**              has been setup on the MCL or not
+**
+** Returns      BOOLEAN - TRUE exist
+**                        FALSE does not exist
+**
+*******************************************************************************/
+BOOLEAN bta_hl_is_the_first_reliable_existed(UINT8 app_idx, UINT8 mcl_idx )
+{
+    tBTA_HL_MCL_CB      *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN is_existed =FALSE;
+    UINT8 i ;
+
+    for (i=0; i< BTA_HL_NUM_MDLS_PER_MCL; i++)
+    {
+        if (p_mcb->mdl[i].in_use && p_mcb->mdl[i].is_the_first_reliable)
+        {
+            is_existed = TRUE;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_is_the_first_reliable_existed is_existed=%d  ",is_existed );
+#endif
+    return is_existed;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_non_active_mdl_cfg
+**
+** Description  This function finds a valid MDL configiration index and this
+**              MDL ID is not active
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_find_non_active_mdl_cfg(UINT8 app_idx, UINT8 start_mdl_cfg_idx,
+                                        UINT8 *p_mdl_cfg_idx)
+{
+
+    tBTA_HL_MCL_CB      *p_mcb;
+    tBTA_HL_MDL_CB      *p_dcb;
+    tBTA_HL_MDL_CFG     *p_mdl;
+    BOOLEAN             mdl_in_use;
+    BOOLEAN             found = FALSE;
+    UINT8               i,j,k;
+
+    for (i = start_mdl_cfg_idx; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        mdl_in_use = FALSE;
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        for (j=0; j< BTA_HL_NUM_MCLS; j++)
+        {
+            p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, j);
+            if (p_mcb->in_use &&
+                !memcmp(p_mdl->peer_bd_addr,p_mcb->bd_addr,BD_ADDR_LEN))
+            {
+
+                for (k=0; k<BTA_HL_NUM_MDLS_PER_MCL; k++)
+                {
+                    p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, j, k);
+
+                    if (p_dcb->in_use &&  p_mdl->mdl_id == p_dcb->mdl_id)
+                    {
+                        mdl_in_use = TRUE;
+                        break;
+                    }
+                }
+            }
+
+            if (mdl_in_use)
+            {
+                break;
+            }
+        }
+
+        if (!mdl_in_use)
+        {
+            *p_mdl_cfg_idx = i;
+            found = TRUE;
+            break;
+        }
+    }
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mdl_cfg_idx
+**
+** Description  This function finds an available MDL configiration index
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_find_avail_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                       UINT8 *p_mdl_cfg_idx)
+{
+    tBTA_HL_MDL_CFG     *p_mdl, *p_mdl1, *p_mdl2;
+    UINT8               i;
+    BOOLEAN             found=FALSE;
+    UINT8               first_mdl_cfg_idx, second_mdl_cfg_idx, older_mdl_cfg_idx;
+    BOOLEAN             done;
+
+
+    for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (!p_mdl->active  )
+        {
+            /* found an unused space to store mdl cfg*/
+            found=TRUE;
+            *p_mdl_cfg_idx =i;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        /* all available mdl cfg spaces are in use so we need to find the mdl cfg which is
+        not currently in use and has the the oldest time stamp to remove*/
+
+        found = TRUE;
+        if (bta_hl_find_non_active_mdl_cfg(app_idx,0, &first_mdl_cfg_idx))
+        {
+            if (bta_hl_find_non_active_mdl_cfg(app_idx,(UINT8) (first_mdl_cfg_idx+1), &second_mdl_cfg_idx))
+            {
+                done = FALSE;
+                while (!done)
+                {
+                    p_mdl1 = BTA_HL_GET_MDL_CFG_PTR(app_idx, first_mdl_cfg_idx);
+                    p_mdl2 = BTA_HL_GET_MDL_CFG_PTR(app_idx, second_mdl_cfg_idx);
+
+                    if (p_mdl1->time < p_mdl2->time)
+                    {
+                        older_mdl_cfg_idx =  first_mdl_cfg_idx;
+                    }
+                    else
+                    {
+                        older_mdl_cfg_idx =  second_mdl_cfg_idx;
+                    }
+
+                    if (bta_hl_find_non_active_mdl_cfg(app_idx,(UINT8) (second_mdl_cfg_idx+1), &second_mdl_cfg_idx))
+                    {
+                        first_mdl_cfg_idx = older_mdl_cfg_idx;
+                    }
+                    else
+                    {
+                        done = TRUE;
+                    }
+                }
+
+                *p_mdl_cfg_idx = older_mdl_cfg_idx;
+
+            }
+            else
+            {
+                *p_mdl_cfg_idx = first_mdl_cfg_idx;
+            }
+
+        }
+        else
+        {
+            found = FALSE;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_avail_mdl_cfg_idx found=%d mdl_cfg_idx=%d ",found, *p_mdl_cfg_idx  );
+    }
+#endif
+
+    return found;
+
+
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mdl_cfg_idx
+**
+** Description  This function finds the MDL configuration index based on
+**              the MDL ID
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_find_mdl_cfg_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                 tBTA_HL_MDL_ID mdl_id, UINT8 *p_mdl_cfg_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CFG     *p_mdl;
+    UINT8 i ;
+    BOOLEAN found=FALSE;
+    for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (p_mdl->active &&
+            (!memcmp (p_mcb->bd_addr, p_mdl->peer_bd_addr, BD_ADDR_LEN))&&
+            (p_mdl->mdl_id == mdl_id))
+        {
+            found=TRUE;
+            *p_mdl_cfg_idx =i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_mdl_cfg_idx found=%d mdl_cfg_idx=%d ",found, i );
+    }
+#endif
+
+    return found;
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_get_cur_time
+**
+** Description  This function get the cuurent time value
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_get_cur_time(UINT8 app_idx, UINT8 *p_cur_time)
+{
+    tBTA_HL_MDL_CFG     *p_mdl;
+    UINT8 i, j, time_latest, time;
+    BOOLEAN found=FALSE, result=TRUE;
+
+    for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (p_mdl->active)
+        {
+            found=TRUE;
+            time_latest = p_mdl->time;
+            for (j=(i+1); j< BTA_HL_NUM_MDL_CFGS; j++ )
+            {
+                p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, j);
+                if (p_mdl->active)
+                {
+                    time = p_mdl->time;
+                    if (time > time_latest)
+                    {
+                        time_latest = time;
+                    }
+                }
+            }
+            break;
+        }
+    }
+
+
+    if (found)
+    {
+        if (time_latest < BTA_HL_MAX_TIME)
+        {
+            *p_cur_time = time_latest+1;
+        }
+        else
+        {
+            /* need to wrap around */
+            result = FALSE;
+        }
+    }
+    else
+    {
+        *p_cur_time = BTA_HL_MIN_TIME;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!result)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_get_cur_time result=%s cur_time=%d",
+                          (result?"OK":"FAIL"), *p_cur_time);
+    }
+#endif
+
+    return result;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_sort_cfg_time_idx
+**
+** Description  This function sort the mdl configuration idx stored in array a
+**              based on decending time value
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+void bta_hl_sort_cfg_time_idx(UINT8 app_idx, UINT8 *a, UINT8 n)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    UINT8 temp_time, temp_idx;
+    INT16 i, j;
+    for (i = 1; i < n; ++i)
+    {
+        temp_idx = a[i];
+        temp_time = p_acb->mdl_cfg[temp_idx].time;
+        j = i - 1;
+        while ((j >= 0) && (temp_time < p_acb->mdl_cfg[a[j]].time))
+        {
+            a[j + 1] = a[j];
+            --j;
+        }
+        a[j + 1] = temp_idx;
+    }
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_compact_mdl_cfg_time
+**
+** Description  This function finds the MDL configuration index based on
+**              the MDL ID
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+void  bta_hl_compact_mdl_cfg_time(UINT8 app_idx)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MDL_CFG     *p_mdl;
+    UINT8 i, time_min, cnt=0;
+    UINT8   s_arr[BTA_HL_NUM_MDL_CFGS];
+
+
+    for (i=0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (p_mdl->active )
+        {
+            s_arr[cnt]= i;
+            cnt++;
+        }
+    }
+
+
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_compact_mdl_cfg_time cnt=%d ",cnt );
+#endif
+
+
+    if (cnt)
+    {
+        bta_hl_sort_cfg_time_idx(app_idx, s_arr, cnt);
+        time_min = BTA_HL_MIN_TIME;
+        for (i=0;i<cnt; i++)
+        {
+            p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, s_arr[i]);
+            p_mdl->time = time_min + i;
+            bta_hl_co_save_mdl(p_acb->app_id, s_arr[i], p_mdl);
+        }
+    }
+
+
+}
+
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_is_mdl_exsit_in_mcl
+**
+** Description  This function checks whether the MDL ID
+**              has already existed in teh MCL or not
+**
+** Returns      BOOLEAN - TRUE exist
+**                        FALSE does not exist
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_is_mdl_exsit_in_mcl(UINT8 app_idx, BD_ADDR bd_addr,
+                                    tBTA_HL_MDL_ID mdl_id)
+{
+    tBTA_HL_MDL_CFG     *p_mdl;
+    BOOLEAN             found = FALSE;
+    UINT8               i;
+
+    for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (p_mdl->active &&
+            !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN))
+        {
+            if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+            {
+                if (p_mdl->mdl_id == mdl_id)
+                {
+                    found = TRUE;
+                    break;
+                }
+            }
+            else
+            {
+                found = TRUE;
+                break;
+            }
+        }
+    }
+
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_delete_mdl_cfg
+**
+** Description  This function delete the specified MDL ID
+**
+** Returns      BOOLEAN - TRUE Success
+**                        FALSE Failed
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_delete_mdl_cfg(UINT8 app_idx, BD_ADDR bd_addr,
+                               tBTA_HL_MDL_ID mdl_id)
+{
+    tBTA_HL_MDL_CFG     *p_mdl;
+    BOOLEAN             success = FALSE;
+    UINT8               i;
+    tBTA_HL_APP_CB      *p_acb= BTA_HL_GET_APP_CB_PTR(app_idx);
+    UINT8               app_id = p_acb->app_id;
+
+    for (i = 0; i< BTA_HL_NUM_MDL_CFGS; i++)
+    {
+        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
+        if (p_mdl->active &&
+            !memcmp(p_mdl->peer_bd_addr, bd_addr,BD_ADDR_LEN))
+        {
+            if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+            {
+                if (p_mdl->mdl_id == mdl_id)
+                {
+                    bta_hl_co_delete_mdl(app_id, i);
+                    memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
+                    success = TRUE;
+                    break;
+                }
+            }
+            else
+            {
+                bta_hl_co_delete_mdl(app_id, i);
+                memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
+                success = TRUE;
+            }
+        }
+    }
+
+    return success;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_is_mdl_value_valid
+**
+**
+** Description  This function checks the specified MDL ID is in valid range or not
+**
+** Returns      BOOLEAN - TRUE Success
+**                        FALSE Failed
+**
+** note:   mdl_id range   0x0000 reserved,
+**                        0x0001-oxFEFF dynamic range,
+**                        0xFF00-0xFFFE reserved,
+**                        0xFFFF indicates all MDLs (for delete operation only)
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id)
+{
+    BOOLEAN             status = TRUE;
+
+    if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS)
+    {
+        if (mdl_id != 0)
+        {
+            if (mdl_id > BTA_HL_MAX_MDL_VAL )
+            {
+                status = FALSE;
+            }
+        }
+        else
+        {
+            status = FALSE;
+        }
+    }
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_mdep_cfg_idx
+**
+** Description  This function finds the MDEP configuration index based
+**                on the local MDEP ID
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_mdep_cfg_idx(UINT8 app_idx,  tBTA_HL_MDEP_ID local_mdep_id,
+                                 UINT8 *p_mdep_cfg_idx)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_SUP_FEATURE     *p_sup_feature= &p_acb->sup_feature;
+    BOOLEAN found =FALSE;
+    UINT8 i;
+
+    for (i=0; i< p_sup_feature->num_of_mdeps; i++)
+    {
+        if ( p_sup_feature->mdep[i].mdep_id == local_mdep_id)
+        {
+            found = TRUE;
+            *p_mdep_cfg_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_find_mdep_cfg_idx found=%d mdep_idx=%d local_mdep_id=%d ",
+                          found,i, local_mdep_id );
+    }
+#endif
+    return found;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_rxtx_apdu_size
+**
+** Description  This function finds the maximum APDU rx and tx sizes based on
+**              the MDEP configuration data
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_hl_find_rxtx_apdu_size(UINT8 app_idx, UINT8 mdep_cfg_idx,
+                                UINT16 *p_rx_apu_size,
+                                UINT16 *p_tx_apu_size)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MDEP_CFG     *p_mdep_cfg;
+    UINT8 i;
+    UINT16 max_rx_apdu_size=0, max_tx_apdu_size=0;
+
+    p_mdep_cfg = &p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg;
+
+
+    for (i=0; i< p_mdep_cfg->num_of_mdep_data_types ; i++)
+    {
+
+        if (max_rx_apdu_size < p_mdep_cfg->data_cfg[i].max_rx_apdu_size)
+        {
+            max_rx_apdu_size = p_mdep_cfg->data_cfg[i].max_rx_apdu_size;
+        }
+
+        if (max_tx_apdu_size < p_mdep_cfg->data_cfg[i].max_tx_apdu_size)
+        {
+            max_tx_apdu_size = p_mdep_cfg->data_cfg[i].max_tx_apdu_size;
+        }
+    }
+
+
+    *p_rx_apu_size = max_rx_apdu_size;
+    *p_tx_apu_size = max_tx_apdu_size;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG2("bta_hl_find_rxtx_apdu_size max_rx_apdu_size=%d max_tx_apdu_size=%d ",
+                      max_rx_apdu_size, max_tx_apdu_size );
+#endif
+
+
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_validate_peer_cfg
+**
+** Description  This function validates the peer DCH configuration
+**
+** Returns      BOOLEAN - TRUE validation is successful
+**                        FALSE validation failed
+**
+*******************************************************************************/
+BOOLEAN bta_hl_validate_peer_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,
+                                 tBTA_HL_MDEP_ID peer_mdep_id,
+                                 tBTA_HL_MDEP_ROLE peer_mdep_role,
+                                 UINT8 sdp_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    tBTA_HL_SDP_REC     *p_rec;
+    BOOLEAN peer_found =FALSE;
+    UINT8 i;
+
+    APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg sdp_idx=%d", sdp_idx);
+
+
+    if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID)
+    {
+        return TRUE;
+    }
+
+    p_rec = &p_mcb->sdp.sdp_rec[sdp_idx];
+    for (i=0; i< p_rec->num_mdeps; i++)
+    {
+        if ( (p_rec->mdep_cfg[i].mdep_id == peer_mdep_id) &&
+             (p_rec->mdep_cfg[i].mdep_role == peer_mdep_role))
+        {
+            peer_found = TRUE;
+
+            break;
+        }
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+    if (!peer_found)
+    {
+        APPL_TRACE_DEBUG1("bta_hl_validate_peer_cfg failed num_mdeps=%d",p_rec->num_mdeps);
+    }
+#endif
+    return peer_found;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_chk_local_cfg
+**
+** Description  This function check whether the local DCH configuration is OK or not
+**
+** Returns      tBTA_HL_STATUS - OK - local DCH configuration is OK
+**                               NO_FIRST_RELIABLE - the streaming DCH configuration
+**                                                   is not OK and it needs to use
+**                                                   reliable DCH configuration
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_chk_local_cfg(UINT8 app_idx, UINT8 mcl_idx,
+                                    UINT8 mdep_cfg_idx,
+                                    tBTA_HL_DCH_CFG local_cfg)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
+
+    if ( mdep_cfg_idx &&
+         (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SOURCE) &&
+         (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) &&
+         (local_cfg != BTA_HL_DCH_CFG_RELIABLE))
+    {
+        status =  BTA_HL_STATUS_NO_FIRST_RELIABLE;
+        APPL_TRACE_ERROR0("BTA_HL_STATUS_INVALID_DCH_CFG");
+    }
+
+    return status;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_validate_reconnect_params
+**
+** Description  This function validates the reconnect parameters
+**
+** Returns      BOOLEAN - TRUE validation is successful
+**                        FALSE validation failed
+*******************************************************************************/
+BOOLEAN bta_hl_validate_reconnect_params(UINT8 app_idx, UINT8 mcl_idx,
+                                         tBTA_HL_API_DCH_RECONNECT *p_reconnect,
+                                         UINT8 *p_mdep_cfg_idx, UINT8 *p_mdl_cfg_idx)
+{
+    tBTA_HL_APP_CB      *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_SUP_FEATURE *p_sup_feature = &p_acb->sup_feature;
+    UINT8               num_mdeps;
+    UINT8               mdl_cfg_idx;
+    BOOLEAN local_mdep_id_found =FALSE;
+    BOOLEAN mdl_cfg_found =FALSE;
+    BOOLEAN            status=FALSE;
+    UINT8 i, in_use_mdl_idx;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_validate_reconnect_params  mdl_id=%d", p_reconnect->mdl_id);
+#endif
+    if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect->mdl_id, &mdl_cfg_idx))
+    {
+        mdl_cfg_found = TRUE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!mdl_cfg_found)
+    {
+        APPL_TRACE_DEBUG0("mdl_cfg_found not found");
+    }
+#endif
+
+
+    if (mdl_cfg_found)
+    {
+        num_mdeps = p_sup_feature->num_of_mdeps;
+        for (i=0; i< num_mdeps ; i++)
+        {
+            if ( p_sup_feature->mdep[i].mdep_id == p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id)
+            {
+                local_mdep_id_found = TRUE;
+                *p_mdep_cfg_idx =i;
+                *p_mdl_cfg_idx = mdl_cfg_idx;
+                break;
+            }
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!local_mdep_id_found)
+    {
+        APPL_TRACE_DEBUG0("local_mdep_id not found");
+    }
+#endif
+
+
+    if (local_mdep_id_found)
+    {
+        if (!bta_hl_find_mdl_idx(app_idx,mcl_idx, p_reconnect->mdl_id, &in_use_mdl_idx))
+        {
+            status= TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR1("mdl_id=%d is curreltly in use",p_reconnect->mdl_id);
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!status)
+    {
+        APPL_TRACE_DEBUG3("Reconnect validation failed local_mdep_id found=%d mdl_cfg_idx found=%d in_use_mdl_idx=%d ",
+                          local_mdep_id_found,  mdl_cfg_found, in_use_mdl_idx);
+    }
+#endif
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_avail_mcl_idx
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_mcl_idx(UINT8 app_idx, UINT8 *p_mcl_idx)
+{
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MCLS ; i ++)
+    {
+        if (!bta_hl_cb.acb[app_idx].mcb[i].in_use)
+        {
+            found = TRUE;
+            *p_mcl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_avail_mcl_idx found=%d idx=%d",
+                          found, i);
+    }
+#endif
+    return found;
+}
+
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_avail_mdl_idx
+**
+** Description  This function finds an available MDL control block index
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_mdl_idx(UINT8 app_idx, UINT8 mcl_idx,
+                                  UINT8 *p_mdl_idx)
+{
+    tBTA_HL_MCL_CB      *p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_MDLS_PER_MCL ; i ++)
+    {
+        if (!p_mcb->mdl[i].in_use)
+        {
+            memset((void *)&p_mcb->mdl[i],0, sizeof(tBTA_HL_MDL_CB));
+            found = TRUE;
+            *p_mdl_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_avail_mdl_idx found=%d idx=%d",
+                          found, i);
+    }
+#endif
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_is_a_duplicate_id
+**
+** Description  This function finds the application has been used or not
+**
+** Returns      BOOLEAN - TRUE the app_id is a duplicate ID
+**                        FALSE not a duplicate ID
+*******************************************************************************/
+BOOLEAN bta_hl_is_a_duplicate_id(UINT8 app_id)
+{
+    BOOLEAN is_duplicate=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        if (bta_hl_cb.acb[i].in_use &&
+            (bta_hl_cb.acb[i].app_id == app_id))
+        {
+            is_duplicate = TRUE;
+
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (is_duplicate)
+    {
+
+        APPL_TRACE_DEBUG2("bta_hl_is_a_duplicate_id app_id=%d is_duplicate=%d",
+                          app_id, is_duplicate);
+    }
+#endif
+
+    return is_duplicate;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_find_avail_app_idx
+**
+** Description  This function finds an available application control block index
+**
+** Returns      BOOLEAN - TRUE found
+**                        FALSE not found
+**
+*******************************************************************************/
+BOOLEAN bta_hl_find_avail_app_idx(UINT8 *p_idx)
+{
+    BOOLEAN found=FALSE;
+    UINT8 i;
+
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        if (!bta_hl_cb.acb[i].in_use)
+        {
+            found = TRUE;
+            *p_idx = i;
+            break;
+        }
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!found)
+    {
+        APPL_TRACE_DEBUG2("bta_hl_find_avail_app_idx found=%d app_idx=%d",
+                          found, i);
+    }
+#endif
+    return found;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_app_registration
+**
+** Description  This function registers an HDP application MCAP and DP
+**
+** Returns      tBTA_HL_STATUS -registration status
+**
+*******************************************************************************/
+tBTA_HL_STATUS bta_hl_app_registration(UINT8 app_idx)
+{
+    tBTA_HL_STATUS  status = BTA_HL_STATUS_OK;
+    tBTA_HL_APP_CB  *p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tMCA_REG        reg;
+    tMCA_CS         mca_cs;
+    UINT8           i, num_of_mdeps;
+
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("bta_hl_app_registration app_idx=%d", app_idx);
+#endif
+
+    reg.ctrl_psm = p_acb->ctrl_psm;
+    reg.data_psm = p_acb->data_psm;
+    reg.sec_mask = p_acb->sec_mask;
+    reg.rsp_tout = BTA_HL_MCAP_RSP_TOUT;
+
+    if ( (p_acb->app_handle = (tBTA_HL_APP_HANDLE) MCA_Register(&reg, bta_hl_mcap_ctrl_cback))!=0)
+    {
+        mca_cs.type = MCA_TDEP_ECHO;
+        mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
+        mca_cs.p_data_cback = bta_hl_mcap_data_cback;
+
+        if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
+                          &(p_acb->sup_feature.mdep[0].mdep_id),
+                          &mca_cs) == MCA_SUCCESS)
+        {
+            if (p_acb->sup_feature.mdep[0].mdep_id != BTA_HL_ECHO_TEST_MDEP_ID)
+            {
+                status = BTA_HL_STATUS_MCAP_REG_FAIL;
+                APPL_TRACE_ERROR1("BAD MDEP ID for echo test mdep_id=%d",
+                                  p_acb->sup_feature.mdep[0].mdep_id );
+            }
+        }
+        else
+        {
+            status = BTA_HL_STATUS_MCAP_REG_FAIL;
+            APPL_TRACE_ERROR0("MCA_CreateDep for echo test(mdep_id=0) failed");
+        }
+
+
+        if ((status == BTA_HL_STATUS_OK) &&
+            bta_hl_co_get_num_of_mdep(p_acb->app_id, &num_of_mdeps))
+        {
+            p_acb->sup_feature.num_of_mdeps = num_of_mdeps+1;
+
+            for (i=1; i<p_acb->sup_feature.num_of_mdeps; i++)
+            {
+                mca_cs.type = MCA_TDEP_DATA;
+                mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
+                mca_cs.p_data_cback = bta_hl_mcap_data_cback;
+
+                if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
+                                  &(p_acb->sup_feature.mdep[i].mdep_id), &mca_cs) == MCA_SUCCESS)
+                {
+                    if (bta_hl_co_get_mdep_config(p_acb->app_id,
+                                                  i,
+                                                  p_acb->sup_feature.mdep[i].mdep_id,
+                                                  &p_acb->sup_feature.mdep[i].mdep_cfg))
+                    {
+                        if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SOURCE)
+                        {
+                            p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SOURCE;
+                        }
+                        else if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role == BTA_HL_MDEP_ROLE_SINK)
+                        {
+                            p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SINK;
+                        }
+                        else
+                        {
+                            status = BTA_HL_STATUS_MDEP_CO_FAIL;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        status = BTA_HL_STATUS_MDEP_CO_FAIL;
+                        break;
+                    }
+                }
+                else
+                {
+                    status = BTA_HL_STATUS_MCAP_REG_FAIL;
+                    break;
+                }
+            }
+
+
+
+            if ((status == BTA_HL_STATUS_OK) &&
+                (p_acb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE))
+            {
+                /* this is a source only applciation */
+                p_acb->sup_feature.advertize_source_sdp =
+                bta_hl_co_advrtise_source_sdp(p_acb->app_id);
+            }
+
+            if ((status == BTA_HL_STATUS_OK)&&
+                (!bta_hl_co_get_echo_config(p_acb->app_id, &p_acb->sup_feature.echo_cfg)))
+            {
+                status = BTA_HL_STATUS_ECHO_CO_FAIL;
+            }
+
+            if ((status == BTA_HL_STATUS_OK)&&
+                (!bta_hl_co_load_mdl_config(p_acb->app_id, BTA_HL_NUM_MDL_CFGS, &p_acb->mdl_cfg[0])))
+            {
+                status = BTA_HL_STATUS_MDL_CFG_CO_FAIL;
+            }
+        }
+        else
+        {
+            status = BTA_HL_STATUS_MDEP_CO_FAIL;
+        }
+    }
+    else
+    {
+        status = BTA_HL_STATUS_MCAP_REG_FAIL;
+    }
+
+    if (status == BTA_HL_STATUS_OK)
+    {
+        status = bta_hl_sdp_register(app_idx);
+    }
+
+    return status;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_discard_data
+**
+** Description  This function discard an HDP event
+**
+** Returns     void
+**
+*******************************************************************************/
+void bta_hl_discard_data(UINT16 event, tBTA_HL_DATA *p_data)
+{
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_ERROR1("BTA HL Discard event=%s",bta_hl_evt_code(event));
+
+#endif
+
+    switch (event)
+    {
+        case BTA_HL_API_SEND_DATA_EVT:
+            break;
+
+        case BTA_HL_MCA_RCV_DATA_EVT:
+            utl_freebuf((void**)&p_data->mca_rcv_data_evt.p_pkt);
+            break;
+
+        default:
+            /*Nothing to free*/
+            break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_save_mdl_cfg
+**
+** Description    This function saves the MDL configuration
+**
+** Returns     void
+**
+*******************************************************************************/
+void bta_hl_save_mdl_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx )
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    UINT8 mdl_cfg_idx;
+    tBTA_HL_MDL_ID mdl_id;
+    BOOLEAN      found=TRUE;
+    tBTA_HL_MDL_CFG mdl_cfg;
+    tBTA_HL_MDEP *p_mdep_cfg;
+    tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+    UINT8 time_val;
+    mdl_id = p_dcb->mdl_id;
+    if (!bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx))
+    {
+        if (!bta_hl_find_avail_mdl_cfg_idx(app_idx, mcl_idx, &mdl_cfg_idx))
+        {
+            APPL_TRACE_ERROR0("No space to save the MDL config");
+            found= FALSE; /*no space available*/
+        }
+    }
+
+    if (found)
+    {
+        bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
+        if (!bta_hl_get_cur_time(app_idx, &time_val ))
+        {
+            bta_hl_compact_mdl_cfg_time(app_idx);
+            bta_hl_get_cur_time(app_idx, &time_val);
+        }
+        mdl_cfg.active = TRUE;
+        mdl_cfg.time = time_val;
+        mdl_cfg.mdl_id  = p_dcb->mdl_id;
+        mdl_cfg.dch_mode = p_dcb->dch_mode;
+        mdl_cfg.mtu = l2cap_cfg.mtu;
+        mdl_cfg.fcs = l2cap_cfg.fcs;
+
+        bdcpy(mdl_cfg.peer_bd_addr, p_mcb->bd_addr);
+        mdl_cfg.local_mdep_id= p_dcb->local_mdep_id;
+        p_mdep_cfg = &p_acb->sup_feature.mdep[p_dcb->local_mdep_cfg_idx];
+        mdl_cfg.local_mdep_role= p_mdep_cfg->mdep_cfg.mdep_role;
+        memcpy(&p_acb->mdl_cfg[mdl_cfg_idx], &mdl_cfg, sizeof(tBTA_HL_MDL_CFG));
+        bta_hl_co_save_mdl(p_acb->app_id, mdl_cfg_idx, &mdl_cfg);
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (found)
+    {
+        if (p_dcb->mtu != l2cap_cfg.mtu)
+        {
+            APPL_TRACE_WARNING2("MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from l2cap mtu=%d",
+                                p_dcb->mtu, l2cap_cfg.mtu);
+        }
+        APPL_TRACE_DEBUG1("bta_hl_save_mdl_cfg saved=%d", found);
+        APPL_TRACE_DEBUG4("Saved. L2cap cfg mdl_id=%d mtu=%d fcs=%d dch_mode=%d",
+                          mdl_cfg.mdl_id, mdl_cfg.mtu, mdl_cfg.fcs,  mdl_cfg.dch_mode);
+    }
+#endif
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_set_dch_chan_cfg
+**
+** Description    This function setups the L2CAP DCH channel configuration
+**
+** Returns     void
+*******************************************************************************/
+void bta_hl_set_dch_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx,tBTA_HL_DATA *p_data)
+{
+    tBTA_HL_APP_CB *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MDL_CB *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    UINT8 l2cap_mode = L2CAP_FCR_ERTM_MODE;
+    tBTA_HL_SUP_FEATURE *p_sup_feature= &p_acb->sup_feature;
+    UINT8 local_mdep_cfg_idx = p_dcb->local_mdep_cfg_idx;
+
+    switch (p_dcb->dch_oper)
+    {
+        case BTA_HL_DCH_OP_LOCAL_RECONNECT:
+        case BTA_HL_DCH_OP_REMOTE_RECONNECT:
+            if (p_dcb->dch_mode  == BTA_HL_DCH_MODE_STREAMING)
+                l2cap_mode = L2CAP_FCR_STREAM_MODE;
+            break;
+        case BTA_HL_DCH_OP_LOCAL_OPEN:
+            if (p_data->mca_evt.mca_data.create_cfm.cfg == BTA_HL_DCH_CFG_STREAMING)
+                l2cap_mode = L2CAP_FCR_STREAM_MODE;
+            break;
+        case BTA_HL_DCH_OP_REMOTE_OPEN:
+            if (p_dcb->local_cfg == BTA_HL_DCH_CFG_STREAMING )
+                l2cap_mode = L2CAP_FCR_STREAM_MODE;
+            break;
+        default:
+            APPL_TRACE_ERROR1("Invalid dch oper=%d for set dch chan cfg", p_dcb->dch_oper);
+            break;
+    }
+    p_dcb->chnl_cfg.fcr_opt.mode        = l2cap_mode;
+    p_dcb->chnl_cfg.fcr_opt.mps         = bta_hl_set_mps(p_dcb->max_rx_apdu_size);
+    p_dcb->chnl_cfg.fcr_opt.tx_win_sz   = bta_hl_set_tx_win_size(p_dcb->max_rx_apdu_size,
+                                                                 p_dcb->chnl_cfg.fcr_opt.mps);
+    p_dcb->chnl_cfg.fcr_opt.max_transmit= BTA_HL_L2C_MAX_TRANSMIT;
+    p_dcb->chnl_cfg.fcr_opt.rtrans_tout = BTA_HL_L2C_RTRANS_TOUT;
+    p_dcb->chnl_cfg.fcr_opt.mon_tout    = BTA_HL_L2C_MON_TOUT;
+
+    p_dcb->chnl_cfg.user_rx_pool_id     = bta_hl_set_user_rx_pool_id(p_dcb->max_rx_apdu_size);
+    p_dcb->chnl_cfg.user_tx_pool_id     = bta_hl_set_user_tx_pool_id(p_dcb->max_tx_apdu_size);
+    p_dcb->chnl_cfg.fcr_rx_pool_id      = BTA_HL_L2C_FCR_RX_POOL_ID;
+    p_dcb->chnl_cfg.fcr_tx_pool_id      = BTA_HL_L2C_FCR_TX_POOL_ID;
+    p_dcb->chnl_cfg.data_mtu            = p_dcb->max_rx_apdu_size;
+
+    p_dcb->chnl_cfg.fcs = BTA_HL_MCA_NO_FCS;
+    if (local_mdep_cfg_idx !=  BTA_HL_ECHO_TEST_MDEP_CFG_IDX)
+    {
+        if (p_sup_feature->mdep[local_mdep_cfg_idx].mdep_cfg.mdep_role ==
+            BTA_HL_MDEP_ROLE_SOURCE)
+        {
+            p_dcb->chnl_cfg.fcs = BTA_HL_DEFAULT_SOURCE_FCS;
+        }
+    }
+    else
+    {
+        p_dcb->chnl_cfg.fcs = BTA_HL_MCA_USE_FCS;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG1("L2CAP Params l2cap_mode[3-ERTM 4-STREAM]=%d", l2cap_mode);
+    APPL_TRACE_DEBUG2("Use FCS =%s mtu=%d", ((p_dcb->chnl_cfg.fcs & 1)?"YES":"NO"),
+                      p_dcb->chnl_cfg.data_mtu);
+    APPL_TRACE_DEBUG5("tx_win_sz=%d, max_transmit=%d, rtrans_tout=%d, mon_tout=%d, mps=%d",
+                      p_dcb->chnl_cfg.fcr_opt.tx_win_sz,
+                      p_dcb->chnl_cfg.fcr_opt.max_transmit,
+                      p_dcb->chnl_cfg.fcr_opt.rtrans_tout,
+                      p_dcb->chnl_cfg.fcr_opt.mon_tout,
+                      p_dcb->chnl_cfg.fcr_opt.mps);
+
+    APPL_TRACE_DEBUG4("USER rx_pool_id=%d, tx_pool_id=%d, FCR rx_pool_id=%d, tx_pool_id=%d",
+                      p_dcb->chnl_cfg.user_rx_pool_id,
+                      p_dcb->chnl_cfg.user_tx_pool_id,
+                      p_dcb->chnl_cfg.fcr_rx_pool_id,
+                      p_dcb->chnl_cfg.fcr_tx_pool_id);
+
+#endif
+
+
+
+
+
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_get_l2cap_cfg
+**
+** Description    This function get the current L2CAP channel configuration
+**
+** Returns     BOOLEAN - TRUE - operation is successful
+*******************************************************************************/
+BOOLEAN bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd, tBTA_HL_L2CAP_CFG_INFO *p_cfg)
+{
+    BOOLEAN success = FALSE;
+    UINT16 lcid;
+    tL2CAP_CFG_INFO *p_our_cfg;
+    tL2CAP_CH_CFG_BITS our_cfg_bits;
+    tL2CAP_CFG_INFO *p_peer_cfg;
+    tL2CAP_CH_CFG_BITS peer_cfg_bits;
+
+    lcid = MCA_GetL2CapChannel((tMCA_DL) mdl_hnd);
+    if ( lcid &&
+         L2CA_GetCurrentConfig(lcid, &p_our_cfg, &our_cfg_bits, &p_peer_cfg,
+                               &peer_cfg_bits))
+    {
+        p_cfg->fcs = BTA_HL_MCA_NO_FCS;
+        if (our_cfg_bits & L2CAP_CH_CFG_MASK_FCS)
+        {
+            p_cfg->fcs |= p_our_cfg->fcs;
+        }
+        else
+        {
+            p_cfg->fcs = BTA_HL_MCA_USE_FCS;
+        }
+
+        if (p_cfg->fcs != BTA_HL_MCA_USE_FCS )
+        {
+            if (peer_cfg_bits & L2CAP_CH_CFG_MASK_FCS)
+            {
+                p_cfg->fcs |= p_peer_cfg->fcs;
+            }
+            else
+            {
+                p_cfg->fcs = BTA_HL_MCA_USE_FCS;
+            }
+        }
+
+        p_cfg->mtu =0;
+        if (peer_cfg_bits & L2CAP_CH_CFG_MASK_MTU)
+        {
+            p_cfg->mtu = p_peer_cfg->mtu;
+        }
+        else
+        {
+            p_cfg->mtu = L2CAP_DEFAULT_MTU;
+        }
+        success = TRUE;
+    }
+
+#if BTA_HL_DEBUG == TRUE
+    if (!success)
+    {
+        APPL_TRACE_DEBUG3("bta_hl_get_l2cap_cfg success=%d mdl=%d lcid=%d", success, mdl_hnd, lcid);
+        APPL_TRACE_DEBUG2("l2cap mtu=%d fcs=%d", p_cfg->mtu, p_cfg->fcs);
+    }
+#endif
+
+    return success;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_validate_chan_cfg
+**
+** Description    This function validates the L2CAP channel configuration
+**
+** Returns     BOOLEAN - TRUE - validation is successful
+*******************************************************************************/
+BOOLEAN bta_hl_validate_chan_cfg(UINT8 app_idx, UINT8 mcl_idx, UINT8 mdl_idx)
+{
+    tBTA_HL_APP_CB *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MDL_CB *p_dcb  = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+    BOOLEAN success = FALSE;
+    UINT8 mdl_cfg_idx;
+    tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+
+
+    if (bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg) &&
+        bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx))
+    {
+        if ((p_acb->mdl_cfg[mdl_cfg_idx].mtu <= l2cap_cfg.mtu) &&
+            (p_acb->mdl_cfg[mdl_cfg_idx].fcs == l2cap_cfg.fcs) &&
+            (p_acb->mdl_cfg[mdl_cfg_idx].dch_mode == p_dcb->dch_mode))
+        {
+            success = TRUE;
+        }
+    }
+
+
+#if BTA_HL_DEBUG == TRUE
+
+    if (p_dcb->mtu != l2cap_cfg.mtu)
+    {
+        APPL_TRACE_WARNING2("MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from l2cap mtu=%d",
+                            p_dcb->mtu, l2cap_cfg.mtu);
+    }
+
+    if (!success)
+    {
+        APPL_TRACE_DEBUG4("bta_hl_validate_chan_cfg success=%d app_idx=%d mcl_idx=%d mdl_idx=%d",success, app_idx, mcl_idx, mdl_idx);
+        APPL_TRACE_DEBUG3("Cur. L2cap cfg mtu=%d fcs=%d dch_mode=%d", l2cap_cfg.mtu, l2cap_cfg.fcs, p_dcb->dch_mode);
+        APPL_TRACE_DEBUG3("From saved: L2cap cfg mtu=%d fcs=%d dch_mode=%d", p_acb->mdl_cfg[mdl_cfg_idx].mtu,
+                          p_acb->mdl_cfg[mdl_cfg_idx].fcs , p_acb->mdl_cfg[mdl_cfg_idx].dch_mode);
+    }
+#endif
+
+    return success;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_is_cong_on
+**
+** Description    This function checks whether the congestion condition is on or not
+**
+** Returns      BOOLEAN - TRUE DCH is congested
+**                        FALSE not congested
+**
+*******************************************************************************/
+BOOLEAN  bta_hl_is_cong_on(UINT8 app_id, BD_ADDR bd_addr, tBTA_HL_MDL_ID mdl_id)
+
+{
+    tBTA_HL_MDL_CB      *p_dcb;
+    UINT8   app_idx, mcl_idx, mdl_idx;
+    BOOLEAN cong_status = TRUE;
+
+    if (bta_hl_find_app_idx(app_id, &app_idx))
+    {
+        if (bta_hl_find_mcl_idx(app_idx, bd_addr, &mcl_idx ))
+        {
+            if (bta_hl_find_mdl_idx(app_idx, mcl_idx, mdl_id, &mdl_idx ))
+            {
+                p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+                cong_status  = p_dcb->cong;
+            }
+        }
+    }
+
+    return cong_status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_check_cch_close
+**
+** Description   This function checks whether there is a pending CCH close request
+**               or not
+**
+** Returns      void
+*******************************************************************************/
+void bta_hl_check_cch_close(UINT8 app_idx, UINT8 mcl_idx, tBTA_HL_DATA *p_data, BOOLEAN check_dch_setup )
+{
+    tBTA_HL_MCL_CB      *p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+    tBTA_HL_MDL_CB      *p_dcb;
+    UINT8               mdl_idx;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG1("bta_hl_check_cch_close cch_close_dch_oper=%d",p_mcb->cch_close_dch_oper );
+#endif
+
+    if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE)
+    {
+        if (check_dch_setup && bta_hl_find_dch_setup_mdl_idx(app_idx, mcl_idx, &mdl_idx))
+        {
+            p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
+            if (!p_mcb->rsp_tout)
+            {
+                p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_ABORT;
+
+                if (!p_dcb->abort_oper)
+                {
+                    p_dcb->abort_oper |= BTA_HL_ABORT_CCH_CLOSE_MASK;
+                    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT, p_data);
+                }
+            }
+            else
+            {
+                p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
+                bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
+            }
+        }
+        else if (bta_hl_find_an_active_mdl_idx(app_idx, mcl_idx,&mdl_idx))
+        {
+            p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
+            bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT, p_data);
+        }
+        else
+        {
+            p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_NONE;
+            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_EVT, p_data);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_hl_clean_app
+**
+** Description      Cleans up the HDP application resources and control block
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_clean_app(UINT8 app_idx)
+{
+    tBTA_HL_APP_CB         *p_acb   = BTA_HL_GET_APP_CB_PTR(app_idx);
+    int i, num_act_apps=0;
+
+#if BTA_HL_DEBUG == TRUE
+    APPL_TRACE_DEBUG0("bta_hl_clean_app");
+#endif
+    MCA_Deregister((tMCA_HANDLE)p_acb->app_handle);
+
+    if (p_acb->sdp_handle) SDP_DeleteRecord(p_acb->sdp_handle);
+
+    memset((void *) p_acb, 0, sizeof(tBTA_HL_APP_CB));
+
+    /* check any application is still active */
+    for (i=0; i < BTA_HL_NUM_APPS ; i ++)
+    {
+        p_acb = BTA_HL_GET_APP_CB_PTR(i);
+        if (p_acb->in_use) num_act_apps++;
+    }
+
+    if (!num_act_apps)
+    {
+        bta_sys_remove_uuid(UUID_SERVCLASS_HDP_PROFILE);
+    }
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_check_deregistration
+**
+** Description   This function checks whether there is a pending deregistration
+**               request or not
+**
+** Returns      void
+*******************************************************************************/
+void bta_hl_check_deregistration(UINT8 app_idx, tBTA_HL_DATA *p_data )
+{
+    tBTA_HL_APP_CB      *p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+    tBTA_HL_MCL_CB      *p_mcb;
+    UINT8               mcl_idx;
+    tBTA_HL             evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_check_deregistration");
+#endif
+
+    if (p_acb->deregistering)
+    {
+        if (bta_hl_find_an_in_use_mcl_idx(app_idx, &mcl_idx))
+        {
+            p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
+            if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
+            {
+                p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+                bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
+            }
+        }
+        else
+        {
+            /* all cchs are closed */
+            evt_data.dereg_cfm.app_handle = p_acb->app_handle;
+            evt_data.dereg_cfm.status = BTA_HL_STATUS_OK;
+            p_acb->p_cback(BTA_HL_DEREGISTER_CFM_EVT, (tBTA_HL *) &evt_data );
+            bta_hl_clean_app(app_idx);
+            bta_hl_check_disable(p_data);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_check_disable
+**
+** Description   This function checks whether there is a pending disable
+**               request or not
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_hl_check_disable(tBTA_HL_DATA *p_data )
+{
+    tBTA_HL_CB          *p_cb= &bta_hl_cb;
+    tBTA_HL_APP_CB      *p_acb;
+    UINT8               app_idx;
+    tBTA_HL_CTRL        evt_data;
+
+#if (BTA_HL_DEBUG == TRUE)
+    APPL_TRACE_DEBUG0("bta_hl_check_disable");
+#endif
+
+    if (bta_hl_cb.disabling)
+    {
+        if (bta_hl_find_an_in_use_app_idx(&app_idx))
+        {
+            p_acb  = BTA_HL_GET_APP_CB_PTR(app_idx);
+            if (!p_acb->deregistering)
+            {
+                p_acb->deregistering = TRUE;
+                bta_hl_check_deregistration(app_idx, p_data);
+            }
+        }
+        else
+        {
+            /* all apps are deregistered */
+            bta_sys_deregister(BTA_ID_HL);
+            evt_data.disable_cfm.status = BTA_HL_STATUS_OK;
+            if (p_cb->p_ctrl_cback) p_cb->p_ctrl_cback(BTA_HL_CTRL_DISABLE_CFM_EVT, (tBTA_HL_CTRL *) &evt_data);
+            memset((void *) p_cb, 0, sizeof(tBTA_HL_CB));
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_abort_cfm
+**
+** Description   This function builds the abort confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_abort_cfm(tBTA_HL *p_evt_data,
+                             tBTA_HL_APP_HANDLE app_handle,
+                             tBTA_HL_MCL_HANDLE mcl_handle,
+                             tBTA_HL_STATUS status)
+{
+    p_evt_data->dch_abort_cfm.status = status;
+    p_evt_data->dch_abort_cfm.mcl_handle = mcl_handle;
+    p_evt_data->dch_abort_cfm.app_handle = app_handle;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_abort_ind
+**
+** Description   This function builds the abort indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_abort_ind(tBTA_HL *p_evt_data,
+                             tBTA_HL_APP_HANDLE app_handle,
+                             tBTA_HL_MCL_HANDLE mcl_handle)
+{
+    p_evt_data->dch_abort_ind.mcl_handle = mcl_handle;
+    p_evt_data->dch_abort_ind.app_handle = app_handle;
+}
+/*******************************************************************************
+**
+** Function      bta_hl_build_close_cfm
+**
+** Description   This function builds the close confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_dch_close_cfm(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 tBTA_HL_MDL_HANDLE mdl_handle,
+                                 tBTA_HL_STATUS status)
+{
+    p_evt_data->dch_close_cfm.status = status;
+    p_evt_data->dch_close_cfm.mdl_handle = mdl_handle;
+    p_evt_data->dch_close_cfm.mcl_handle = mcl_handle;
+    p_evt_data->dch_close_cfm.app_handle = app_handle;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_dch_close_ind
+**
+** Description   This function builds the close indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_dch_close_ind(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 tBTA_HL_MDL_HANDLE mdl_handle,
+                                 BOOLEAN intentional)
+{
+    p_evt_data->dch_close_ind.mdl_handle = mdl_handle;
+    p_evt_data->dch_close_ind.mcl_handle = mcl_handle;
+    p_evt_data->dch_close_ind.app_handle = app_handle;
+    p_evt_data->dch_close_ind.intentional = intentional;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_send_data_cfm
+**
+** Description   This function builds the send data confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_send_data_cfm(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 tBTA_HL_MDL_HANDLE mdl_handle,
+                                 tBTA_HL_STATUS status )
+{
+
+    p_evt_data->dch_send_data_cfm.mdl_handle = mdl_handle;
+    p_evt_data->dch_send_data_cfm.mcl_handle = mcl_handle;
+    p_evt_data->dch_send_data_cfm.app_handle = app_handle;
+    p_evt_data->dch_send_data_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_rcv_data_ind
+**
+** Description   This function builds the received data indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_rcv_data_ind(tBTA_HL *p_evt_data,
+                                tBTA_HL_APP_HANDLE app_handle,
+                                tBTA_HL_MCL_HANDLE mcl_handle,
+                                tBTA_HL_MDL_HANDLE mdl_handle)
+{
+    p_evt_data->dch_rcv_data_ind.mdl_handle = mdl_handle;
+    p_evt_data->dch_rcv_data_ind.mcl_handle = mcl_handle;
+    p_evt_data->dch_rcv_data_ind.app_handle = app_handle;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_cch_open_cfm
+**
+** Description   This function builds the CCH open confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_cch_open_cfm(tBTA_HL *p_evt_data,
+                                tBTA_HL_APP_HANDLE app_handle,
+                                tBTA_HL_MCL_HANDLE mcl_handle,
+                                BD_ADDR bd_addr,
+                                tBTA_HL_STATUS status )
+{
+
+    p_evt_data->cch_open_cfm.app_handle = app_handle;
+    p_evt_data->cch_open_cfm.mcl_handle = mcl_handle;
+    bdcpy(p_evt_data->cch_open_cfm.bd_addr, bd_addr);
+    p_evt_data->cch_open_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_cch_open_ind
+**
+** Description   This function builds the CCH open indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_cch_open_ind(tBTA_HL *p_evt_data, tBTA_HL_APP_HANDLE app_handle,
+                                tBTA_HL_MCL_HANDLE mcl_handle,
+                                BD_ADDR bd_addr )
+{
+
+    p_evt_data->cch_open_ind.app_handle = app_handle;
+    p_evt_data->cch_open_ind.mcl_handle = mcl_handle;
+    bdcpy(p_evt_data->cch_open_ind.bd_addr, bd_addr);
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_cch_close_cfm
+**
+** Description   This function builds the CCH close confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_cch_close_cfm(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 tBTA_HL_STATUS status )
+{
+    p_evt_data->cch_close_cfm.mcl_handle = mcl_handle;
+    p_evt_data->cch_close_cfm.app_handle = app_handle;
+    p_evt_data->cch_close_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_cch_close_ind
+**
+** Description   This function builds the CCH colse indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_cch_close_ind(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 BOOLEAN intentional)
+{
+    p_evt_data->cch_close_ind.mcl_handle = mcl_handle;
+    p_evt_data->cch_close_ind.app_handle = app_handle;
+    p_evt_data->cch_close_ind.intentional = intentional;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_dch_open_cfm
+**
+** Description   This function builds the DCH open confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_dch_open_cfm(tBTA_HL *p_evt_data,
+                                tBTA_HL_APP_HANDLE app_handle,
+                                tBTA_HL_MCL_HANDLE mcl_handle,
+                                tBTA_HL_MDL_HANDLE mdl_handle,
+                                tBTA_HL_MDEP_ID local_mdep_id,
+                                tBTA_HL_MDL_ID mdl_id,
+                                tBTA_HL_DCH_MODE dch_mode,
+                                BOOLEAN first_reliable,
+                                UINT16 mtu,
+                                tBTA_HL_STATUS status)
+
+{
+    p_evt_data->dch_open_cfm.mdl_handle = mdl_handle;
+    p_evt_data->dch_open_cfm.mcl_handle = mcl_handle;
+    p_evt_data->dch_open_cfm.app_handle = app_handle;
+    p_evt_data->dch_open_cfm.local_mdep_id = local_mdep_id;
+    p_evt_data->dch_open_cfm.mdl_id = mdl_id;
+    p_evt_data->dch_open_cfm.dch_mode = dch_mode;
+    p_evt_data->dch_open_cfm.first_reliable = first_reliable;
+    p_evt_data->dch_open_cfm.mtu = mtu;
+    p_evt_data->dch_open_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_sdp_query_cfm
+**
+** Description   This function builds the SDP query indication event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_sdp_query_cfm(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 BD_ADDR bd_addr,
+                                 tBTA_HL_SDP *p_sdp,
+                                 tBTA_HL_STATUS status)
+
+{
+    p_evt_data->sdp_query_cfm.app_handle = app_handle;
+    bdcpy(p_evt_data->sdp_query_cfm.bd_addr, bd_addr);
+    p_evt_data->sdp_query_cfm.p_sdp = p_sdp;
+    p_evt_data->sdp_query_cfm.status = status;
+}
+
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_delete_mdl_cfm
+**
+** Description   This function builds the delete MDL confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_delete_mdl_cfm(tBTA_HL *p_evt_data,
+                                  tBTA_HL_APP_HANDLE app_handle,
+                                  tBTA_HL_MCL_HANDLE mcl_handle,
+                                  tBTA_HL_MDL_ID mdl_id,
+                                  tBTA_HL_STATUS status)
+
+{
+    p_evt_data->delete_mdl_cfm.mcl_handle = mcl_handle;
+    p_evt_data->delete_mdl_cfm.app_handle = app_handle;
+    p_evt_data->delete_mdl_cfm.mdl_id = mdl_id;
+    p_evt_data->delete_mdl_cfm.status = status;
+}
+
+/*******************************************************************************
+**
+** Function      bta_hl_build_echo_test_cfm
+**
+** Description   This function builds the echo test confirmation event data
+**
+** Returns      None
+**
+*******************************************************************************/
+void  bta_hl_build_echo_test_cfm(tBTA_HL *p_evt_data,
+                                 tBTA_HL_APP_HANDLE app_handle,
+                                 tBTA_HL_MCL_HANDLE mcl_handle,
+                                 tBTA_HL_STATUS status )
+{
+    p_evt_data->echo_test_cfm.mcl_handle = mcl_handle;
+    p_evt_data->echo_test_cfm.app_handle = app_handle;
+    p_evt_data->echo_test_cfm.status = status;
+}
+
+
+/*****************************************************************************
+**  Debug Functions
+*****************************************************************************/
+#if (BTA_HL_DEBUG == TRUE)
+
+/*******************************************************************************
+**
+** Function         bta_hl_status_code
+**
+** Description      get the status string pointer
+**
+** Returns          char * - status string pointer
+**
+*******************************************************************************/
+char *bta_hl_status_code(tBTA_HL_STATUS status)
+{
+    switch (status)
+    {
+        case BTA_HL_STATUS_OK:
+            return "BTA_HL_STATUS_OK";
+        case BTA_HL_STATUS_FAIL:
+            return "BTA_HL_STATUS_FAIL";
+        case BTA_HL_STATUS_ABORTED:
+            return "BTA_HL_STATUS_ABORTED";
+        case BTA_HL_STATUS_NO_RESOURCE:
+            return "BTA_HL_STATUS_NO_RESOURCE";
+        case BTA_HL_STATUS_LAST_ITEM:
+            return "BTA_HL_STATUS_LAST_ITEM";
+        case BTA_HL_STATUS_DUPLICATE_APP_ID:
+            return "BTA_HL_STATUS_DUPLICATE_APP_ID";
+        case BTA_HL_STATUS_INVALID_APP_HANDLE:
+            return "BTA_HL_STATUS_INVALID_APP_HANDLE";
+        case BTA_HL_STATUS_INVALID_MCL_HANDLE:
+            return "BTA_HL_STATUS_INVALID_MCL_HANDLE";
+        case BTA_HL_STATUS_MCAP_REG_FAIL:
+            return "BTA_HL_STATUS_MCAP_REG_FAIL";
+        case BTA_HL_STATUS_MDEP_CO_FAIL:
+            return "BTA_HL_STATUS_MDEP_CO_FAIL";
+        case BTA_HL_STATUS_ECHO_CO_FAIL:
+            return "BTA_HL_STATUS_ECHO_CO_FAIL";
+        case BTA_HL_STATUS_MDL_CFG_CO_FAIL:
+            return "BTA_HL_STATUS_MDL_CFG_CO_FAIL";
+        case BTA_HL_STATUS_SDP_NO_RESOURCE:
+            return "BTA_HL_STATUS_SDP_NO_RESOURCE";
+        case BTA_HL_STATUS_SDP_FAIL:
+            return "BTA_HL_STATUS_SDP_FAIL";
+        case BTA_HL_STATUS_NO_CCH:
+            return "BTA_HL_STATUS_NO_CCH";
+        case BTA_HL_STATUS_NO_MCL:
+            return "BTA_HL_STATUS_NO_MCL";
+
+        case BTA_HL_STATUS_NO_FIRST_RELIABLE:
+            return "BTA_HL_STATUS_NO_FIRST_RELIABLE";
+        case BTA_HL_STATUS_INVALID_DCH_CFG:
+            return "BTA_HL_STATUS_INVALID_DCH_CFG";
+        case BTA_HL_STATUS_INVALID_BD_ADDR:
+            return "BTA_HL_STATUS_INVALID_BD_ADDR";
+        case BTA_HL_STATUS_INVALID_RECONNECT_CFG:
+            return "BTA_HL_STATUS_INVALID_RECONNECT_CFG";
+        case BTA_HL_STATUS_ECHO_TEST_BUSY:
+            return "BTA_HL_STATUS_ECHO_TEST_BUSY";
+        case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
+            return "BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID";
+        case BTA_HL_STATUS_INVALID_MDL_ID:
+            return "BTA_HL_STATUS_INVALID_MDL_ID";
+        case BTA_HL_STATUS_NO_MDL_ID_FOUND:
+            return "BTA_HL_STATUS_NO_MDL_ID_FOUND";
+        case BTA_HL_STATUS_DCH_BUSY:
+            return "BTA_HL_STATUS_DCH_BUSY";
+        default:
+            return "Unknown status code";
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_hl_evt_code
+**
+** Description      Maps HL event code to the corresponding event string
+**
+** Returns          string pointer for the associated event name
+**
+*******************************************************************************/
+char *bta_hl_evt_code(tBTA_HL_INT_EVT evt_code)
+{
+    switch (evt_code)
+    {
+        case BTA_HL_CCH_OPEN_EVT:
+            return "BTA_HL_CCH_OPEN_EVT";
+        case BTA_HL_CCH_SDP_OK_EVT:
+            return "BTA_HL_CCH_SDP_OK_EVT";
+        case BTA_HL_CCH_SDP_FAIL_EVT:
+            return "BTA_HL_CCH_SDP_FAIL_EVT";
+        case BTA_HL_MCA_CONNECT_IND_EVT:
+            return "BTA_HL_MCA_CONNECT_IND_EVT";
+        case BTA_HL_MCA_DISCONNECT_IND_EVT:
+            return "BTA_HL_MCA_DISCONNECT_IND_EVT";
+
+        case BTA_HL_CCH_CLOSE_EVT:
+            return "BTA_HL_CCH_CLOSE_EVT";
+        case BTA_HL_CCH_CLOSE_CMPL_EVT:
+            return "BTA_HL_CCH_CLOSE_CMPL_EVT";
+        case BTA_HL_DCH_OPEN_EVT:
+            return "BTA_HL_DCH_OPEN_EVT";
+        case BTA_HL_MCA_CREATE_IND_EVT:
+            return "BTA_HL_MCA_CREATE_IND_EVT";
+        case BTA_HL_MCA_CREATE_CFM_EVT:
+            return "BTA_HL_MCA_CREATE_CFM_EVT";
+        case BTA_HL_MCA_OPEN_IND_EVT:
+            return "BTA_HL_MCA_OPEN_IND_EVT";
+        case BTA_HL_MCA_OPEN_CFM_EVT:
+            return "BTA_HL_MCA_OPEN_CFM_EVT";
+        case BTA_HL_DCH_CLOSE_EVT:
+            return "BTA_HL_DCH_CLOSE_EVT";
+        case BTA_HL_MCA_CLOSE_IND_EVT:
+            return "BTA_HL_MCA_CLOSE_IND_EVT";
+        case BTA_HL_MCA_CLOSE_CFM_EVT:
+            return "BTA_HL_MCA_CLOSE_CFM_EVT";
+        case BTA_HL_API_SEND_DATA_EVT:
+            return "BTA_HL_API_SEND_DATA_EVT";
+        case BTA_HL_MCA_RCV_DATA_EVT:
+            return "BTA_HL_MCA_RCV_DATA_EVT";
+        case BTA_HL_DCH_CLOSE_CMPL_EVT:
+            return "BTA_HL_DCH_CLOSE_CMPL_EVT";
+
+        case BTA_HL_API_ENABLE_EVT:
+            return "BTA_HL_API_ENABLE_EVT";
+        case BTA_HL_API_DISABLE_EVT:
+            return "BTA_HL_API_DISABLE_EVT";
+        case BTA_HL_API_REGISTER_EVT:
+            return "BTA_HL_API_REGISTER_EVT";
+        case BTA_HL_API_DEREGISTER_EVT:
+            return "BTA_HL_API_DEREGISTER_EVT";
+
+        case BTA_HL_API_CCH_OPEN_EVT:
+            return "BTA_HL_API_CCH_OPEN_EVT";
+
+        case BTA_HL_API_CCH_CLOSE_EVT:
+            return "BTA_HL_API_CCH_CLOSE_EVT";
+        case BTA_HL_API_DCH_OPEN_EVT:
+            return "BTA_HL_API_DCH_OPEN_EVT";
+
+        case BTA_HL_API_DCH_RECONNECT_EVT:
+            return "BTA_HL_API_DCH_RECONNECT_EVT";
+        case BTA_HL_API_DCH_CLOSE_EVT:
+            return "BTA_HL_API_DCH_CLOSE_EVT";
+        case BTA_HL_API_DELETE_MDL_EVT:
+            return "BTA_HL_API_DELETE_MDL_EVT";
+        case BTA_HL_API_DCH_ABORT_EVT:
+            return "BTA_HL_API_DCH_ABORT_EVT";
+
+        case BTA_HL_DCH_RECONNECT_EVT:
+            return "BTA_HL_DCH_RECONNECT_EVT";
+        case BTA_HL_DCH_SDP_INIT_EVT:
+            return "BTA_HL_DCH_SDP_INIT_EVT";
+        case BTA_HL_DCH_SDP_FAIL_EVT:
+            return "BTA_HL_DCH_SDP_FAIL_EVT";
+        case BTA_HL_API_DCH_ECHO_TEST_EVT:
+            return "BTA_HL_API_DCH_ECHO_TEST_EVT";
+        case BTA_HL_DCH_CLOSE_ECHO_TEST_EVT:
+            return "BTA_HL_DCH_CLOSE_ECHO_TEST_EVT";
+        case BTA_HL_MCA_RECONNECT_IND_EVT:
+            return "BTA_HL_MCA_RECONNECT_IND_EVT";
+        case BTA_HL_MCA_RECONNECT_CFM_EVT:
+            return "BTA_HL_MCA_RECONNECT_CFM_EVT";
+        case BTA_HL_API_DCH_CREATE_RSP_EVT:
+            return "BTA_HL_API_DCH_CREATE_RSP_EVT";
+        case BTA_HL_DCH_ABORT_EVT:
+            return "BTA_HL_DCH_ABORT_EVT";
+        case BTA_HL_MCA_ABORT_IND_EVT:
+            return "BTA_HL_MCA_ABORT_IND_EVT";
+        case BTA_HL_MCA_ABORT_CFM_EVT:
+            return "BTA_HL_MCA_ABORT_CFM_EVT";
+        case BTA_HL_MCA_DELETE_IND_EVT:
+            return "BTA_HL_MCA_DELETE_IND_EVT";
+        case BTA_HL_MCA_DELETE_CFM_EVT:
+            return "BTA_HL_MCA_DELETE_CFM_EVT";
+        case BTA_HL_MCA_CONG_CHG_EVT:
+            return "BTA_HL_MCA_CONG_CHG_EVT";
+        case BTA_HL_CI_GET_TX_DATA_EVT:
+            return "BTA_HL_CI_GET_TX_DATA_EVT";
+        case BTA_HL_CI_PUT_RX_DATA_EVT:
+            return "BTA_HL_CI_PUT_RX_DATA_EVT";
+        case BTA_HL_CI_GET_ECHO_DATA_EVT:
+            return "BTA_HL_CI_GET_ECHO_DATA_EVT";
+        case BTA_HL_DCH_ECHO_TEST_EVT:
+            return "BTA_HL_DCH_ECHO_TEST_EVT";
+        case BTA_HL_CI_PUT_ECHO_DATA_EVT:
+            return "BTA_HL_CI_PUT_ECHO_DATA_EVT";
+        case BTA_HL_API_SDP_QUERY_EVT:
+            return "BTA_HL_API_SDP_QUERY_EVT";
+        case BTA_HL_SDP_QUERY_OK_EVT:
+            return "BTA_HL_SDP_QUERY_OK_EVT";
+        case BTA_HL_SDP_QUERY_FAIL_EVT:
+            return "BTA_HL_SDP_QUERY_FAIL_EVT";
+        case BTA_HL_MCA_RSP_TOUT_IND_EVT:
+            return "BTA_HL_MCA_RSP_TOUT_IND_EVT";
+
+        default:
+            return "Unknown HL event code";
+    }
+}
+
+#endif  /* Debug Functions */
+#endif // HL_INCLUDED
+
+
+
+
+
+
+
+
diff --git a/bta/include/bd.h b/bta/include/bd.h
new file mode 100644
index 0000000..33c3de1
--- /dev/null
+++ b/bta/include/bd.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  BD address services.
+ *
+ ******************************************************************************/
+#ifndef BD_H
+#define BD_H
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* bd addr length and type */
+#ifndef BD_ADDR_LEN
+#define BD_ADDR_LEN     6
+typedef UINT8 BD_ADDR[BD_ADDR_LEN];
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* global constant for "any" bd addr */
+extern const BD_ADDR bd_addr_any;
+extern const BD_ADDR bd_addr_null;
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bdcpy
+**
+** Description      Copy bd addr b to a.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bdcpy(BD_ADDR a, const BD_ADDR b);
+
+/*******************************************************************************
+**
+** Function         bdcmp
+**
+** Description      Compare bd addr b to a.
+**
+**
+** Returns          Zero if b==a, nonzero otherwise (like memcmp).
+**
+*******************************************************************************/
+extern int bdcmp(const BD_ADDR a, const BD_ADDR b);
+
+/*******************************************************************************
+**
+** Function         bdcmpany
+**
+** Description      Compare bd addr to "any" bd addr.
+**
+**
+** Returns          Zero if a equals bd_addr_any.
+**
+*******************************************************************************/
+extern int bdcmpany(const BD_ADDR a);
+
+/*******************************************************************************
+**
+** Function         bdsetany
+**
+** Description      Set bd addr to "any" bd addr.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bdsetany(BD_ADDR a);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BD_H */
+
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
new file mode 100644
index 0000000..f16687c
--- /dev/null
+++ b/bta/include/bta_ag_api.h
@@ -0,0 +1,514 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for the audio gateway (AG) subsystem
+ *  of BTA, Broadcom's Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_API_H
+#define BTA_AG_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* AG feature masks */
+#define BTA_AG_FEAT_3WAY    0x00000001   /* Three-way calling */
+#define BTA_AG_FEAT_ECNR    0x00000002   /* Echo cancellation and/or noise reduction */
+#define BTA_AG_FEAT_VREC    0x00000004   /* Voice recognition */
+#define BTA_AG_FEAT_INBAND  0x00000008   /* In-band ring tone */
+#define BTA_AG_FEAT_VTAG    0x00000010   /* Attach a phone number to a voice tag */
+#define BTA_AG_FEAT_REJECT  0x00000020   /* Ability to reject incoming call */
+#define BTA_AG_FEAT_ECS     0x00000040   /* Enhanced Call Status */
+#define BTA_AG_FEAT_ECC     0x00000080   /* Enhanced Call Control */
+#define BTA_AG_FEAT_EXTERR  0x00000100   /* Extended error codes */
+#define BTA_AG_FEAT_CODEC   0x00000200   /* Codec Negotiation */
+#define BTA_AG_FEAT_VOIP    0x00000400   /* VoIP call */
+/* Proprietary features: using 31 ~ 16 bits */
+#define BTA_AG_FEAT_BTRH    0x00010000   /* CCAP incoming call hold */
+#define BTA_AG_FEAT_UNAT    0x00020000   /* Pass unknown AT commands to application */
+#define BTA_AG_FEAT_NOSCO   0x00040000   /* No SCO control performed by BTA AG */
+#define BTA_AG_FEAT_NO_ESCO 0x00080000   /* Do not allow or use eSCO */
+
+typedef UINT32 tBTA_AG_FEAT;
+
+/* AG parse mode */
+#define BTA_AG_PARSE            0 /* Perform AT command parsing in AG */
+#define BTA_AG_PASS_THROUGH     1 /* Pass data directly to phoneÂ’s AT command interpreter */
+
+typedef UINT8 tBTA_AG_PARSE_MODE;
+
+/* AG open status */
+#define BTA_AG_SUCCESS          0 /* Connection successfully opened */
+#define BTA_AG_FAIL_SDP         1 /* Open failed due to SDP */
+#define BTA_AG_FAIL_RFCOMM      2 /* Open failed due to RFCOMM */
+#define BTA_AG_FAIL_RESOURCES   3 /* out of resources failure  */
+
+typedef UINT8 tBTA_AG_STATUS;
+
+/* handle values used with BTA_AgResult */
+#define BTA_AG_HANDLE_NONE      0
+#define BTA_AG_HANDLE_ALL       0xFFFF
+/* It is safe to use the same value as BTA_AG_HANDLE_ALL
+ * HANDLE_ALL is used for delivering indication
+ * SCO_NO_CHANGE is used for changing sco behavior
+ * They donot interfere with each other
+ */
+#define BTA_AG_HANDLE_SCO_NO_CHANGE 0xFFFF
+
+/* AG result codes used with BTA_AgResult */
+#define BTA_AG_SPK_RES              0   /* Update speaker volume */
+#define BTA_AG_MIC_RES              1   /* Update microphone volume */
+#define BTA_AG_INBAND_RING_RES      2   /* Update inband ring state */
+#define BTA_AG_CIND_RES             3   /* Send indicator response for AT+CIND */
+#define BTA_AG_BINP_RES             4   /* Send phone number for voice tag for AT+BINP */
+#define BTA_AG_IND_RES              5   /* Update an indicator value */
+#define BTA_AG_BVRA_RES             6   /* Update voice recognition state */
+#define BTA_AG_CNUM_RES             7   /* Send subscriber number response for AT+CNUM */
+#define BTA_AG_BTRH_RES             8   /* Send CCAP incoming call hold */
+#define BTA_AG_CLCC_RES             9   /* Query list of calls */
+#define BTA_AG_COPS_RES             10  /* Read network operator */
+#define BTA_AG_IN_CALL_RES          11  /* Indicate incoming phone call */
+#define BTA_AG_IN_CALL_CONN_RES     12  /* Incoming phone call connected */
+#define BTA_AG_CALL_WAIT_RES        13  /* Call waiting notification */
+#define BTA_AG_OUT_CALL_ORIG_RES    14  /* Outgoing phone call origination */
+#define BTA_AG_OUT_CALL_ALERT_RES   15  /* Outgoing phone call alerting remote party */
+#define BTA_AG_OUT_CALL_CONN_RES    16  /* Outgoing phone call connected */
+#define BTA_AG_CALL_CANCEL_RES      17  /* Incoming/outgoing 3-way canceled before connected */
+#define BTA_AG_END_CALL_RES         18  /* End call */
+#define BTA_AG_IN_CALL_HELD_RES     19  /* Incoming call held */
+#define BTA_AG_UNAT_RES             20  /* Response to unknown AT command event */
+
+typedef UINT8 tBTA_AG_RES;
+
+/* HFP peer features */
+#define BTA_AG_PEER_FEAT_ECNR       0x0001  /* Echo cancellation and/or noise reduction */
+#define BTA_AG_PEER_FEAT_3WAY       0x0002  /* Call waiting and three-way calling */
+#define BTA_AG_PEER_FEAT_CLI        0x0004  /* Caller ID presentation capability */
+#define BTA_AG_PEER_FEAT_VREC       0x0008  /* Voice recognition activation */
+#define BTA_AG_PEER_FEAT_VOL        0x0010  /* Remote volume control */
+#define BTA_AG_PEER_FEAT_ECS        0x0020  /* Enhanced Call Status */
+#define BTA_AG_PEER_FEAT_ECC        0x0040  /* Enhanced Call Control */
+#define BTA_AG_PEER_FEAT_CODEC      0x0080  /* Codec Negotiation */
+#define BTA_AG_PEER_FEAT_VOIP       0x0100  /* VoIP call */
+
+typedef UINT16 tBTA_AG_PEER_FEAT;
+
+/* HFP peer supported codec masks */
+#define BTA_AG_CODEC_NONE           BTM_SCO_CODEC_NONE
+#define BTA_AG_CODEC_CVSD           BTM_SCO_CODEC_CVSD      /* CVSD */
+#define BTA_AG_CODEC_MSBC           BTM_SCO_CODEC_MSBC      /* mSBC */
+typedef UINT16 tBTA_AG_PEER_CODEC;
+
+/* HFP errcode - Set when BTA_AG_OK_ERROR is returned in 'ok_flag' */
+#define BTA_AG_ERR_PHONE_FAILURE    0       /* Phone Failure */
+#define BTA_AG_ERR_NO_CONN_PHONE    1       /* No connection to phone */
+#define BTA_AG_ERR_OP_NOT_ALLOWED   3       /* Operation not allowed */
+#define BTA_AG_ERR_OP_NOT_SUPPORTED 4       /* Operation not supported */
+#define BTA_AG_ERR_PHSIM_PIN_REQ    5       /* PH-SIM PIN required */
+#define BTA_AG_ERR_SIM_NOT_INSERTED 10      /* SIM not inserted */
+#define BTA_AG_ERR_SIM_PIN_REQ      11      /* SIM PIN required */
+#define BTA_AG_ERR_SIM_PUK_REQ      12      /* SIM PUK required */
+#define BTA_AG_ERR_SIM_FAILURE      13      /* SIM failure */
+#define BTA_AG_ERR_SIM_BUSY         14      /* SIM busy */
+#define BTA_AG_ERR_INCORRECT_PWD    16      /* Incorrect password */
+#define BTA_AG_ERR_SIM_PIN2_REQ     17      /* SIM PIN2 required */
+#define BTA_AG_ERR_SIM_PUK2_REQ     18      /* SIM PUK2 required */
+#define BTA_AG_ERR_MEMORY_FULL      20      /* Memory full */
+#define BTA_AG_ERR_INVALID_INDEX    21      /* Invalid index */
+#define BTA_AG_ERR_MEMORY_FAILURE   23      /* Memory failure */
+#define BTA_AG_ERR_TEXT_TOO_LONG    24      /* Text string too long */
+#define BTA_AG_ERR_INV_CHAR_IN_TSTR 25      /* Invalid characters in text string */
+#define BTA_AG_ERR_DSTR_TOO_LONG    26      /* Dial string too long */
+#define BTA_AG_ERR_INV_CHAR_IN_DSTR 27      /* Invalid characters in dial string */
+#define BTA_AG_ERR_NO_NETWORK_SERV  30      /* No network service */
+#define BTA_AG_ERR_NETWORK_TIME_OUT 31      /* Network timeout */
+#define BTA_AG_ERR_NO_NET_EMG_ONLY  32      /* Network not allowed - emergency service only */
+#define BTA_AG_ERR_VOIP_CS_CALLS    33      /* AG cannot create simultaneous VoIP and CS calls */
+#define BTA_AG_ERR_NOT_FOR_VOIP     34      /* Not supported on this call type(VoIP) */
+#define BTA_AG_ERR_SIP_RESP_CODE    35      /* SIP 3 digit response code */
+
+#if 0   /* Not Used in Bluetooth HFP 1.5 Specification */
+#define BTA_AG_ERR_PHADAP_LNK_RES   2       /* Phone-adapter link reserved */
+#define BTA_AG_ERR_PHFSIM_PIN_REQ   6       /* PH-FSIM PIN required */
+#define BTA_AG_ERR_PHFSIM_PUK_REQ   7       /* PH-FSIM PUK required */
+#define BTA_AG_ERR_SIM_WRONG        15      /* SIM wrong */
+#define BTA_AG_ERR_NOT_FOUND        22      /* Not found */
+#define BTA_AG_ERR_NETWORK_TIMEOUT  31      /* Network timeout */
+#define BTA_AG_ERR_NET_PIN_REQ      40      /* Network personalization PIN required */
+#define BTA_AG_ERR_NET_PUK_REQ      41      /* Network personalization PUK required */
+#define BTA_AG_ERR_SUBSET_PIN_REQ   42      /* Network subset personalization PIN required */
+#define BTA_AG_ERR_SUBSET_PUK_REQ   43      /* Network subset personalization PUK required */
+#define BTA_AG_ERR_SERVPRO_PIN_REQ  44      /* Service provider personalization PIN required */
+#define BTA_AG_ERR_SERVPRO_PUK_REQ  45      /* Service provider personalization PUK required */
+#define BTA_AG_ERR_CORP_PIN_REQ     46      /* Corporate personalization PIN required */
+#define BTA_AG_ERR_CORP_PUK_REQ     47      /* Corporate personalization PUK required */
+#define BTA_AG_ERR_UNKNOWN          100    /* Unknown error */
+/* GPRS-related errors */
+#define BTA_AG_ERR_ILL_MS           103    /* Illegal MS (#3) */
+#define BTA_AG_ERR_ILL_ME           106    /* Illegal ME (#6) */
+#define BTA_AG_ERR_GPRS_NOT_ALLOWED 107    /* GPRS services not allowed (#7) */
+#define BTA_AG_ERR_PLMN_NOT_ALLOWED 111    /* PLMN services not allowed (#11) */
+#define BTA_AG_ERR_LOC_NOT_ALLOWED  112    /* Location area not allowed (#12) */
+#define BTA_AG_ERR_ROAM_NOT_ALLOWED 113    /* Roaming not allowed in this location area (#13) */
+/* Errors related to a failure to Activate a Context */
+#define BTA_AG_ERR_OPT_NOT_SUPP     132    /* Service option not supported (#32) */
+#define BTA_AG_ERR_OPT_NOT_SUBSCR   133    /* Requested service option not subscribed (#33) */
+#define BTA_AG_ERR_OPT_OUT_OF_ORDER 134    /* Service option temporarily out of order (#34) */
+#define BTA_AG_ERR_PDP_AUTH_FAILURE 149    /* PDP authentication failure */
+/* Other GPRS errors */
+#define BTA_AG_ERR_INV_MOBILE_CLASS 150    /* Invalid mobile class */
+#define BTA_AG_ERR_UNSPEC_GPRS_ERR  148    /* Unspecified GPRS error */
+#endif  /* Unused error codes */
+
+
+/* HFP result data 'ok_flag' */
+#define BTA_AG_OK_CONTINUE          0       /* Send out response (more responses coming) */
+#define BTA_AG_OK_DONE              1       /* Send out response followed by OK (finished) */
+#define BTA_AG_OK_ERROR             2       /* Error response */
+
+/* BTRH values */
+#define BTA_AG_BTRH_SET_HOLD        0       /* Put incoming call on hold */
+#define BTA_AG_BTRH_SET_ACC         1       /* Accept incoming call on hold */
+#define BTA_AG_BTRH_SET_REJ         2       /* Reject incoming call on hold */
+#define BTA_AG_BTRH_READ            3       /* Read the current value */
+#define BTA_AG_BTRH_NO_RESP         4       /* Not in RH States (reply to read) */
+
+/* ASCII character string of arguments to the AT command or result */
+#ifndef BTA_AG_AT_MAX_LEN
+#define BTA_AG_AT_MAX_LEN           256
+#endif
+
+/* data associated with BTA_AG_IND_RES */
+typedef struct
+{
+    UINT16          id;
+    UINT16          value;
+} tBTA_AG_IND;
+
+/* data type for BTA_AgResult() */
+typedef struct
+{
+    char            str[BTA_AG_AT_MAX_LEN+1];
+    tBTA_AG_IND     ind;
+    UINT16          num;
+    UINT16          audio_handle;
+    UINT16          errcode;        /* Valid only if 'ok_flag' is set to BTA_AG_OK_ERROR */
+    UINT8           ok_flag;        /* Indicates if response is finished, and if error occurred */
+    BOOLEAN         state;
+} tBTA_AG_RES_DATA;
+
+/* AG callback events */
+#define BTA_AG_ENABLE_EVT       0  /* AG enabled */
+#define BTA_AG_REGISTER_EVT     1  /* AG registered */
+#define BTA_AG_OPEN_EVT         2  /* AG connection open */
+#define BTA_AG_CLOSE_EVT        3  /* AG connection closed */
+#define BTA_AG_CONN_EVT         4  /* Service level connection opened */
+#define BTA_AG_AUDIO_OPEN_EVT   5  /* Audio connection open */
+#define BTA_AG_AUDIO_CLOSE_EVT  6  /* Audio connection closed */
+#define BTA_AG_SPK_EVT          7  /* Speaker volume changed */
+#define BTA_AG_MIC_EVT          8  /* Microphone volume changed */
+#define BTA_AG_AT_CKPD_EVT      9  /* CKPD from the HS */
+#define BTA_AG_DISABLE_EVT      30 /* AG disabled       */
+
+/* Values below are for HFP only */
+#define BTA_AG_AT_A_EVT         10 /* Answer a call */
+#define BTA_AG_AT_D_EVT         11 /* Place a call using number or memory dial */
+#define BTA_AG_AT_CHLD_EVT      12 /* Call hold */
+#define BTA_AG_AT_CHUP_EVT      13 /* Hang up a call */
+#define BTA_AG_AT_CIND_EVT      14 /* Read indicator settings */
+#define BTA_AG_AT_VTS_EVT       15 /* Transmit DTMF tone */
+#define BTA_AG_AT_BINP_EVT      16 /* Retrieve number from voice tag */
+#define BTA_AG_AT_BLDN_EVT      17 /* Place call to last dialed number */
+#define BTA_AG_AT_BVRA_EVT      18 /* Enable/disable voice recognition */
+#define BTA_AG_AT_NREC_EVT      19 /* Disable echo canceling */
+#define BTA_AG_AT_CNUM_EVT      20 /* Retrieve subscriber number */
+#define BTA_AG_AT_BTRH_EVT      21 /* CCAP-style incoming call hold */
+#define BTA_AG_AT_CLCC_EVT      22 /* Query list of current calls */
+#define BTA_AG_AT_COPS_EVT      23 /* Query list of current calls */
+#define BTA_AG_AT_UNAT_EVT      24 /* Unknown AT command */
+#define BTA_AG_AT_CBC_EVT       25 /* Battery Level report from HF */
+#define BTA_AG_AT_BAC_EVT       26 /* Codec select */
+#define BTA_AG_AT_BCS_EVT       27 /* Codec select */
+
+typedef UINT8 tBTA_AG_EVT;
+
+/* data associated with most non-AT events */
+typedef struct
+{
+    UINT16              handle;
+    UINT8               app_id;
+} tBTA_AG_HDR;
+
+/* data associated with BTA_AG_REGISTER_EVT */
+typedef struct
+{
+    tBTA_AG_HDR         hdr;
+    tBTA_AG_STATUS      status;
+} tBTA_AG_REGISTER;
+
+/* data associated with BTA_AG_OPEN_EVT */
+typedef struct
+{
+    tBTA_AG_HDR         hdr;
+    BD_ADDR             bd_addr;
+    tBTA_SERVICE_ID     service_id;
+    tBTA_AG_STATUS      status;
+} tBTA_AG_OPEN;
+
+/* data associated with BTA_AG_CONN_EVT */
+typedef struct
+{
+    tBTA_AG_HDR         hdr;
+    tBTA_AG_PEER_FEAT   peer_feat;
+    tBTA_AG_PEER_CODEC  peer_codec;
+} tBTA_AG_CONN;
+
+/* data associated with AT command event */
+typedef struct
+{
+    tBTA_AG_HDR         hdr;
+    char                str[BTA_AG_AT_MAX_LEN+1];
+    UINT16              num;
+    UINT8               idx;    /* call number used by CLCC and CHLD */
+} tBTA_AG_VAL;
+
+/* union of data associated with AG callback */
+typedef union
+{
+    tBTA_AG_HDR         hdr;
+    tBTA_AG_REGISTER    reg;
+    tBTA_AG_OPEN        open;
+    tBTA_AG_CONN        conn;
+    tBTA_AG_VAL         val;
+} tBTA_AG;
+
+/* AG callback */
+typedef void (tBTA_AG_CBACK)(tBTA_AG_EVT event, tBTA_AG *p_data);
+
+/* indicator constants HFP 1.1 and later */
+#define BTA_AG_IND_CALL             1   /* position of call indicator */
+#define BTA_AG_IND_CALLSETUP        2   /* position of callsetup indicator */
+#define BTA_AG_IND_SERVICE          3   /* position of service indicator */
+
+/* indicator constants HFP 1.5 and later */
+#define BTA_AG_IND_SIGNAL           4   /* position of signal strength indicator */
+#define BTA_AG_IND_ROAM             5   /* position of roaming indicator */
+#define BTA_AG_IND_BATTCHG          6   /* position of battery charge indicator */
+#define BTA_AG_IND_CALLHELD         7   /* position of callheld indicator */
+#define BTA_AG_IND_BEARER           8   /* position of bearer indicator */
+
+/* call indicator values */
+#define BTA_AG_CALL_INACTIVE        0   /* Phone call inactive */
+#define BTA_AG_CALL_ACTIVE          1   /* Phone call active */
+
+/* callsetup indicator values */
+#define BTA_AG_CALLSETUP_NONE       0   /* Not currently in call set up */
+#define BTA_AG_CALLSETUP_INCOMING   1   /* Incoming call process ongoing */
+#define BTA_AG_CALLSETUP_OUTGOING   2   /* Outgoing call set up is ongoing */
+#define BTA_AG_CALLSETUP_ALERTING   3   /* Remote party being alerted in an outgoing call */
+
+/* service indicator values */
+#define BTA_AG_SERVICE_NONE         0   /* Neither CS nor VoIP service is available     */
+#define BTA_AG_SERVICE_CS           1   /* Only CS service is available                 */
+#define BTA_AG_SERVICE_VOIP         2   /* Only VoIP service is available               */
+#define BTA_AG_SERVICE_CS_VOIP      3   /* Both CS and VoIP services available          */
+
+/* callheld indicator values */
+#define BTA_AG_CALLHELD_INACTIVE    0   /* No held calls */
+#define BTA_AG_CALLHELD_ACTIVE      1   /* Call held and call active */
+#define BTA_AG_CALLHELD_NOACTIVE    2   /* Call held and no call active */
+
+/* signal strength indicator values */
+#define BTA_AG_ROAMING_INACTIVE     0   /* Phone call inactive */
+#define BTA_AG_ROAMING_ACTIVE       1   /* Phone call active */
+
+/* bearer indicator values */
+#define BTA_AG_BEARER_WLAN          0   /* WLAN         */
+#define BTA_AG_BEARER_BLUETOOTH     1   /* Bluetooth    */
+#define BTA_AG_BEARER_WIRED         2   /* Wired        */
+#define BTA_AG_BEARER_2G3G          3   /* 2G 3G        */
+#define BTA_AG_BEARER_WIMAX         4   /* WIMAX        */
+#define BTA_AG_BEARER_RES1          5   /* Reserved     */
+#define BTA_AG_BEARER_RES2          6   /* Reserved     */
+#define BTA_AG_BEARER_RES3          7   /* Reserved     */
+
+/* AG configuration structure */
+typedef struct
+{
+    char         *cind_info;
+    INT32        conn_tout;
+    UINT16       sco_pkt_types;
+    char         *chld_val_ecc;
+    char         *chld_val;
+} tBTA_AG_CFG;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_AgEnable
+**
+** Description      Enable the audio gateway service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_AG_ENABLE_EVT. This function must
+**                  be called before other function in the AG API are
+**                  called.
+**
+** Returns          BTA_SUCCESS if OK, BTA_FAILURE otherwise.
+**
+*******************************************************************************/
+BTA_API tBTA_STATUS BTA_AgEnable(tBTA_AG_PARSE_MODE parse_mode, tBTA_AG_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_AgDisable
+**
+** Description      Disable the audio gateway service
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgDisable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_AgRegister
+**
+** Description      Register an Audio Gateway service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgRegister(tBTA_SERVICE_MASK services, tBTA_SEC sec_mask,
+                tBTA_AG_FEAT features, char *p_service_names[], UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         BTA_AgDeregister
+**
+** Description      Deregister an audio gateway service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgDeregister(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AgOpen
+**
+** Description      Opens a connection to a headset or hands-free device.
+**                  When connection is open callback function is called
+**                  with a BTA_AG_OPEN_EVT. Only the data connection is
+**                  opened. The audio connection is not opened.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgOpen(UINT16 handle, BD_ADDR bd_addr, tBTA_SEC sec_mask, tBTA_SERVICE_MASK services);
+
+/*******************************************************************************
+**
+** Function         BTA_AgClose
+**
+** Description      Close the current connection to a headset or a handsfree
+**                  Any current audio connection will also be closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgClose(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AgAudioOpen
+**
+** Description      Opens an audio connection to the currently connected
+**                  headset or hnadsfree
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgAudioOpen(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AgAudioClose
+**
+** Description      Close the currently active audio connection to a headset
+**                  or hnadsfree. The data connection remains open
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgAudioClose(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AgResult
+**
+** Description      Send an AT result code to a headset or hands-free device.
+**                  This function is only used when the AG parse mode is set
+**                  to BTA_AG_PARSE.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgResult(UINT16 handle, tBTA_AG_RES result, tBTA_AG_RES_DATA *p_data);
+
+/*******************************************************************************
+**
+** Function         BTA_AgSetCodec
+**
+** Description      Specify the codec type to be used for the subsequent
+**                  audio connection.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AgSetCodec(UINT16 handle, tBTA_AG_PEER_CODEC codec);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AG_API_H */
+
+
diff --git a/bta/include/bta_ag_ci.h b/bta/include/bta_ag_ci.h
new file mode 100644
index 0000000..3bc0e53
--- /dev/null
+++ b/bta/include/bta_ag_ci.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for audio gateway call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_CI_H
+#define BTA_AG_CI_H
+
+#include "bta_ag_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_ag_ci_rx_write
+**
+** Description      This function is called to send data to the AG when the AG
+**                  is configured for AT command pass-through.  The function
+**                  copies data to an event buffer and sends it.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_ci_rx_write(UINT16 handle, char *p_data, UINT16 len);
+
+/******************************************************************************
+**
+** Function         bta_ag_ci_slc_ready
+**
+** Description      This function is called to notify AG that SLC is up at
+**                  the application. This funcion is only used when the app
+**                  is running in pass-through mode.
+**
+** Returns          void
+**
+******************************************************************************/
+BTA_API extern void bta_ag_ci_slc_ready(UINT16 handle);
+
+// btla-specific ++
+/******************************************************************************
+**
+** Function         bta_ag_ci_wbs_command
+**
+** Description      This function is called to notify AG that a WBS command is
+**                  received
+**
+** Returns          void
+**
+******************************************************************************/
+BTA_API extern void bta_ag_ci_wbs_command (UINT16 handle, char *p_data, UINT16 len);
+// btla-specific --
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AG_CI_H */
+
diff --git a/bta/include/bta_ag_co.h b/bta/include/bta_ag_co.h
new file mode 100644
index 0000000..c6a3392
--- /dev/null
+++ b/bta/include/bta_ag_co.h
@@ -0,0 +1,112 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for audio gateway call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AG_CO_H
+#define BTA_AG_CO_H
+
+#include "bta_ag_api.h"
+
+/* Definitions for audio state callout function "state" parameter */
+#define BTA_AG_CO_AUD_STATE_OFF         0
+#define BTA_AG_CO_AUD_STATE_OFF_XFER    1   /* Closed pending transfer of audio */
+#define BTA_AG_CO_AUD_STATE_ON          2
+#define BTA_AG_CO_AUD_STATE_SETUP       3
+
+/*******************************************************************************
+**
+** Function         bta_ag_co_init
+**
+** Description      This callout function is executed by AG when it is
+**                  started by calling BTA_AgEnable().  This function can be
+**                  used by the phone to initialize audio paths or for other
+**                  initialization purposes.
+**
+**
+** Returns          Void.
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_init(void);
+
+/*******************************************************************************
+**
+** Function         bta_ag_co_audio_state
+**
+** Description      This function is called by the AG before the audio connection
+**                  is brought up, after it comes up, and after it goes down.
+**
+** Parameters       handle - handle of the AG instance
+**                  state - Audio state
+**                      BTA_AG_CO_AUD_STATE_OFF      - Audio has been turned off
+**                      BTA_AG_CO_AUD_STATE_OFF_XFER - Audio is closed pending transfer
+**                      BTA_AG_CO_AUD_STATE_ON       - Audio has been turned on
+**                      BTA_AG_CO_AUD_STATE_SETUP    - Audio is about to be turned on
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_audio_state(UINT16 handle, UINT8 app_id, UINT8 state);
+
+/*******************************************************************************
+**
+** Function         bta_ag_co_data_open
+**
+** Description      This function is executed by AG when a service level connection
+**                  is opened.  The phone can use this function to set
+**                  up data paths or perform any required initialization or
+**                  set up particular to the connected service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_data_open(UINT16 handle, tBTA_SERVICE_ID service);
+
+/*******************************************************************************
+**
+** Function         bta_ag_co_data_close
+**
+** Description      This function is called by AG when a service level
+**                  connection is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_data_close(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         bta_ag_co_tx_write
+**
+** Description      This function is called by the AG to send data to the
+**                  phone when the AG is configured for AT command pass-through.
+**                  The implementation of this function must copy the data to
+**                  the phoneÂ’s memory.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_ag_co_tx_write(UINT16 handle, UINT8 *p_data, UINT16 len);
+
+#endif /* BTA_AG_CO_H */
+
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
new file mode 100644
index 0000000..81dff39
--- /dev/null
+++ b/bta/include/bta_api.h
@@ -0,0 +1,1730 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for BTA, Broadcom's Bluetooth
+ *  application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_API_H
+#define BTA_API_H
+
+#include "data_types.h"
+#include "bt_target.h"
+#include "bt_types.h"
+#include "btm_api.h"
+#include "uipc_msg.h"
+
+#if BLE_INCLUDED == TRUE
+#include "btm_ble_api.h"
+#endif
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Status Return Value */
+#define BTA_SUCCESS             0           /* Successful operation. */
+#define BTA_FAILURE             1           /* Generic failure. */
+#define BTA_PENDING             2           /* API cannot be completed right now */
+#define BTA_BUSY                3
+#define BTA_NO_RESOURCES        4
+#define BTA_WRONG_MODE          5
+
+typedef UINT8 tBTA_STATUS;
+
+/*
+ * Service ID
+ *
+ * NOTES: When you add a new Service ID for BTA AND require to change the value of BTA_MAX_SERVICE_ID,
+ *        make sure that the correct security ID of the new service from Security service definitions (btm_api.h)
+ *        should be added to bta_service_id_to_btm_srv_id_lkup_tbl table in bta_dm_act.c.
+ */
+
+#define BTA_RES_SERVICE_ID      0           /* Reserved */
+#define BTA_SPP_SERVICE_ID      1           /* Serial port profile. */
+#define BTA_DUN_SERVICE_ID      2           /* Dial-up networking profile. */
+#define BTA_A2DP_SOURCE_SERVICE_ID      3   /* A2DP Source profile. */
+#define BTA_LAP_SERVICE_ID      4           /* LAN access profile. */
+#define BTA_HSP_SERVICE_ID      5           /* Headset profile. */
+#define BTA_HFP_SERVICE_ID      6           /* Hands-free profile. */
+#define BTA_OPP_SERVICE_ID      7           /* Object push  */
+#define BTA_FTP_SERVICE_ID      8           /* File transfer */
+#define BTA_CTP_SERVICE_ID      9           /* Cordless Terminal */
+#define BTA_ICP_SERVICE_ID      10          /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_ID     11          /* Synchronization */
+#define BTA_BPP_SERVICE_ID      12          /* Basic printing profile */
+#define BTA_BIP_SERVICE_ID      13          /* Basic Imaging profile */
+#define BTA_PANU_SERVICE_ID     14          /* PAN User */
+#define BTA_NAP_SERVICE_ID      15          /* PAN Network access point */
+#define BTA_GN_SERVICE_ID       16          /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_ID      17          /* SIM Access profile */
+#define BTA_A2DP_SERVICE_ID     18          /* A2DP Sink */
+#define BTA_AVRCP_SERVICE_ID    19          /* A/V remote control */
+#define BTA_HID_SERVICE_ID      20          /* HID */
+#define BTA_VDP_SERVICE_ID      21          /* Video distribution */
+#define BTA_PBAP_SERVICE_ID     22          /* PhoneBook Access Server*/
+#define BTA_HSP_HS_SERVICE_ID   23          /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_ID   24          /* HSP HS role */
+#define BTA_MAP_SERVICE_ID      25          /* Message Access Profile */
+#define BTA_MN_SERVICE_ID       26          /* Message Notification Service */
+#define BTA_HDP_SERVICE_ID      27          /* Health Device Profile */
+#define BTA_PCE_SERVICE_ID      28          /* PhoneBook Access Client*/
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+/* BLE profile service ID */
+#define BTA_BLE_SERVICE_ID      29          /* GATT profile */
+
+// btla-specific ++
+#define BTA_USER_SERVICE_ID     30          /* User requested UUID */
+
+#define BTA_MAX_SERVICE_ID      31
+// btla-specific --
+#else
+#define BTA_USER_SERVICE_ID     29          /* User requested UUID */
+#define BTA_MAX_SERVICE_ID      30
+#endif
+/* service IDs (BTM_SEC_SERVICE_FIRST_EMPTY + 1) to (BTM_SEC_MAX_SERVICES - 1)
+ * are used by BTA JV */
+#define BTA_FIRST_JV_SERVICE_ID     (BTM_SEC_SERVICE_FIRST_EMPTY + 1)
+#define BTA_LAST_JV_SERVICE_ID      (BTM_SEC_MAX_SERVICES - 1)
+
+typedef UINT8 tBTA_SERVICE_ID;
+
+/* Service ID Mask */
+#define BTA_RES_SERVICE_MASK        0x00000001  /* Reserved */
+#define BTA_SPP_SERVICE_MASK        0x00000002  /* Serial port profile. */
+#define BTA_DUN_SERVICE_MASK        0x00000004  /* Dial-up networking profile. */
+#define BTA_FAX_SERVICE_MASK        0x00000008  /* Fax profile. */
+#define BTA_LAP_SERVICE_MASK        0x00000010  /* LAN access profile. */
+#define BTA_HSP_SERVICE_MASK        0x00000020  /* HSP AG role. */
+#define BTA_HFP_SERVICE_MASK        0x00000040  /* HFP AG role */
+#define BTA_OPP_SERVICE_MASK        0x00000080  /* Object push  */
+#define BTA_FTP_SERVICE_MASK        0x00000100  /* File transfer */
+#define BTA_CTP_SERVICE_MASK        0x00000200  /* Cordless Terminal */
+#define BTA_ICP_SERVICE_MASK        0x00000400  /* Intercom Terminal */
+#define BTA_SYNC_SERVICE_MASK       0x00000800  /* Synchronization */
+#define BTA_BPP_SERVICE_MASK        0x00001000  /* Print server */
+#define BTA_BIP_SERVICE_MASK        0x00002000  /* Basic Imaging */
+#define BTA_PANU_SERVICE_MASK       0x00004000  /* PAN User */
+#define BTA_NAP_SERVICE_MASK        0x00008000  /* PAN Network access point */
+#define BTA_GN_SERVICE_MASK         0x00010000  /* PAN Group Ad-hoc networks */
+#define BTA_SAP_SERVICE_MASK        0x00020000  /* PAN Group Ad-hoc networks */
+#define BTA_A2DP_SERVICE_MASK       0x00040000  /* Advanced audio distribution */
+#define BTA_AVRCP_SERVICE_MASK      0x00080000  /* A/V remote control */
+#define BTA_HID_SERVICE_MASK        0x00100000  /* HID */
+#define BTA_VDP_SERVICE_MASK        0x00200000  /* Video distribution */
+#define BTA_PBAP_SERVICE_MASK       0x00400000  /* Phone Book Server */
+#define BTA_HSP_HS_SERVICE_MASK     0x00800000  /* HFP HS role */
+#define BTA_HFP_HS_SERVICE_MASK     0x01000000  /* HSP HS role */
+#define BTA_MAS_SERVICE_MASK        0x02000000  /* Message Access Profile */
+#define BTA_MN_SERVICE_MASK         0x04000000  /* Message Notification Profile */
+#define BTA_HL_SERVICE_MASK         0x08000000  /* Health Device Profile */
+#define BTA_PCE_SERVICE_MASK        0x10000000  /* Phone Book Client */
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_BLE_SERVICE_MASK        0x20000000  /* GATT based service */
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK       0x40000000  /* Message Notification Profile */
+// btla-specific --
+#else
+// btla-specific ++
+#define BTA_USER_SERVICE_MASK       0x20000000  /* Message Notification Profile */
+// btla-specific --
+#endif
+
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
+#define BTA_ALL_SERVICE_MASK        0x3FFFFFFF  /* All services supported by BTA. */
+#else
+#define BTA_ALL_SERVICE_MASK        0x1FFFFFFF  /* All services supported by BTA. */
+#endif
+
+typedef UINT32 tBTA_SERVICE_MASK;
+
+/* extended service mask, including mask with one or more GATT UUID */
+typedef struct
+{
+    tBTA_SERVICE_MASK   srvc_mask;
+    UINT8               num_uuid;
+    tBT_UUID            *p_uuid;
+}tBTA_SERVICE_MASK_EXT;
+
+/* Security Setting Mask */
+#define BTA_SEC_NONE            BTM_SEC_NONE                                         /* No security. */
+#define BTA_SEC_AUTHORIZE       (BTM_SEC_IN_AUTHORIZE )                              /* Authorization required (only needed for out going connection )*/
+#define BTA_SEC_AUTHENTICATE    (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_OUT_AUTHENTICATE) /* Authentication required. */
+#define BTA_SEC_ENCRYPT         (BTM_SEC_IN_ENCRYPT | BTM_SEC_OUT_ENCRYPT)           /* Encryption required. */
+
+typedef UINT8 tBTA_SEC;
+
+/* Ignore for Discoverable, Connectable, Pairable and Connectable Paired only device modes */
+
+#define BTA_DM_IGNORE           0xFF
+
+
+/* Discoverable Modes */
+#define BTA_DM_NON_DISC         BTM_NON_DISCOVERABLE        /* Device is not discoverable. */
+#define BTA_DM_GENERAL_DISC     BTM_GENERAL_DISCOVERABLE    /* General discoverable. */
+#define BTA_DM_LIMITED_DISC     BTM_LIMITED_DISCOVERABLE    /* Limited discoverable. */
+
+// btla-specific ++
+typedef UINT16 tBTA_DM_DISC;
+// btla-specific --
+
+/* Connectable Modes */
+#define BTA_DM_NON_CONN         BTM_NON_CONNECTABLE         /* Device is not connectable. */
+#define BTA_DM_CONN             BTM_CONNECTABLE             /* Device is connectable. */
+
+// btla-specific ++
+typedef UINT16 tBTA_DM_CONN;
+// btla-specific --
+
+/* Pairable Modes */
+#define BTA_DM_PAIRABLE         1
+#define BTA_DM_NON_PAIRABLE     0
+
+/* Connectable Paired Only Mode */
+#define BTA_DM_CONN_ALL         0
+#define BTA_DM_CONN_PAIRED      1
+
+/* Inquiry Modes */
+#define BTA_DM_GENERAL_INQUIRY  BTM_GENERAL_INQUIRY         /* Perform general inquiry. */
+#define BTA_DM_LIMITED_INQUIRY  BTM_LIMITED_INQUIRY         /* Perform limited inquiry. */
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_BLE_INQUIRY_NONE    BTM_BLE_INQUIRY_NONE
+#define BTA_BLE_GENERAL_INQUIRY BTM_BLE_GENERAL_INQUIRY      /* Perform LE general inquiry. */
+#define BTA_BLE_LIMITED_INQUIRY BTM_BLE_LIMITED_INQUIRY      /* Perform LE limited inquiry. */
+#endif
+typedef UINT8 tBTA_DM_INQ_MODE;
+
+/* Inquiry Filter Type */
+#define BTA_DM_INQ_CLR          BTM_CLR_INQUIRY_FILTER          /* Clear inquiry filter. */
+#define BTA_DM_INQ_DEV_CLASS    BTM_FILTER_COND_DEVICE_CLASS    /* Filter on device class. */
+#define BTA_DM_INQ_BD_ADDR      BTM_FILTER_COND_BD_ADDR         /* Filter on a specific  BD address. */
+
+typedef UINT8 tBTA_DM_INQ_FILT;
+
+/* Authorize Response */
+#define BTA_DM_AUTH_PERM        0      /* Authorized for future connections to the service */
+#define BTA_DM_AUTH_TEMP        1      /* Authorized for current connection only */
+#define BTA_DM_NOT_AUTH         2      /* Not authorized for the service */
+
+typedef UINT8 tBTA_AUTH_RESP;
+
+/* M/S preferred roles */
+#define BTA_ANY_ROLE          0x00
+#define BTA_MASTER_ROLE_PREF  0x01
+#define BTA_MASTER_ROLE_ONLY  0x02
+
+typedef UINT8 tBTA_PREF_ROLES;
+
+enum
+{
+
+    BTA_DM_NO_SCATTERNET,        /* Device doesn't support scatternet, it might
+                                    support "role switch during connection" for
+                                    an incoming connection, when it already has
+                                    another connection in master role */
+    BTA_DM_PARTIAL_SCATTERNET,   /* Device supports partial scatternet. It can have
+                                    simulateous connection in Master and Slave roles
+                                    for short period of time */
+    BTA_DM_FULL_SCATTERNET       /* Device can have simultaneous connection in master
+                                    and slave roles */
+
+};
+
+
+/* Inquiry filter device class condition */
+typedef struct
+{
+    DEV_CLASS       dev_class;        /* device class of interest */
+    DEV_CLASS       dev_class_mask;   /* mask to determine the bits of device class of interest */
+} tBTA_DM_COD_COND;
+
+
+/* Inquiry Filter Condition */
+typedef union
+{
+    BD_ADDR              bd_addr;            /* BD address of  device to filter. */
+    tBTA_DM_COD_COND     dev_class_cond;     /* Device class filter condition */
+} tBTA_DM_INQ_COND;
+
+/* Inquiry Parameters */
+typedef struct
+{
+    tBTA_DM_INQ_MODE    mode;           /* Inquiry mode, limited or general. */
+    UINT8               duration;       /* Inquiry duration in 1.28 sec units. */
+    UINT8               max_resps;      /* Maximum inquiry responses.  Set to zero for unlimited responses. */
+    BOOLEAN             report_dup;     /* report duplicated inquiry response with higher RSSI value */
+    tBTA_DM_INQ_FILT    filter_type;    /* Filter condition type. */
+    tBTA_DM_INQ_COND    filter_cond;    /* Filter condition data. */
+} tBTA_DM_INQ;
+
+typedef struct
+{
+    UINT8   bta_dm_eir_min_name_len;        /* minimum length of local name when it is shortened */
+#if (BTA_EIR_CANNED_UUID_LIST == TRUE)
+    UINT8   bta_dm_eir_uuid16_len;          /* length of 16-bit UUIDs */
+    UINT8  *bta_dm_eir_uuid16;              /* 16-bit UUIDs */
+#else
+    UINT32  uuid_mask[BTM_EIR_SERVICE_ARRAY_SIZE]; /* mask of UUID list in EIR */
+#endif
+    INT8   *bta_dm_eir_inq_tx_power;        /* Inquiry TX power         */
+    UINT8   bta_dm_eir_flag_len;            /* length of flags in bytes */
+    UINT8  *bta_dm_eir_flags;               /* flags for EIR */
+    UINT8   bta_dm_eir_manufac_spec_len;    /* length of manufacturer specific in bytes */
+    UINT8  *bta_dm_eir_manufac_spec;        /* manufacturer specific */
+} tBTA_DM_EIR_CONF;
+
+#if BLE_INCLUDED == TRUE
+/* ADV data flag bit definition used for BTM_BLE_AD_TYPE_FLAG */
+#define BTA_BLE_LIMIT_DISC_FLAG     BTM_BLE_LIMIT_DISC_FLAG
+#define BTA_BLE_GEN_DISC_FLAG       BTM_BLE_GEN_DISC_FLAG
+#define BTA_BLE_BREDR_NOT_SPT       BTM_BLE_BREDR_NOT_SPT
+#define BTA_BLE_NON_LIMIT_DISC_FLAG BTM_BLE_NON_LIMIT_DISC_FLAG
+#define BTA_BLE_ADV_FLAG_MASK       BTM_BLE_ADV_FLAG_MASK
+#define BTA_BLE_LIMIT_DISC_MASK     BTM_BLE_LIMIT_DISC_MASK
+
+#define BTA_BLE_AD_BIT_DEV_NAME     BTM_BLE_AD_BIT_DEV_NAME
+#define BTA_BLE_AD_BIT_FLAGS        BTM_BLE_AD_BIT_FLAGS
+#define BTA_BLE_AD_BIT_MANU         BTM_BLE_AD_BIT_MANU
+#define BTA_BLE_AD_BIT_TX_PWR       BTM_BLE_AD_BIT_TX_PWR
+#define BTA_BLE_AD_BIT_ATTR         BTM_BLE_AD_BIT_ATTR
+#define BTA_BLE_AD_BIT_INT_RANGE    BTM_BLE_AD_BIT_INT_RANGE
+#define BTA_BLE_AD_BIT_SERVICE      BTM_BLE_AD_BIT_SERVICE
+#define BTA_BLE_AD_BIT_SERVICE_SOL  BTM_BLE_AD_BIT_SERVICE_SOL
+#define BTA_BLE_AD_BIT_SERVICE_DATA BTM_BLE_AD_BIT_SERVICE_DATA
+#define BTA_BLE_AD_BIT_SIGN_DATA    BTM_BLE_AD_BIT_SIGN_DATA
+typedef  UINT16  tBTA_BLE_AD_MASK;
+
+/* slave preferred connection interval range */
+typedef struct
+{
+    UINT16  low;
+    UINT16  hi;
+
+}tBTA_BLE_INT_RANGE;
+
+/* Service tag supported in the device */
+typedef struct
+{
+    UINT8       num_service;
+    BOOLEAN     list_cmpl;
+    UINT16      *p_uuid;
+}tBTA_BLE_SERVICE;
+
+/* attribute data */
+typedef struct
+{
+    UINT16       uuid;
+    UINT16       data_len;
+    UINT8       *p_data;
+}tBTA_BLE_ATTR;
+
+#define BTA_BLE_NUM_AD_ATTR_MAX         BTM_BLE_NUM_AD_ATTR_MAX
+
+/* attribute list contained in adv data */
+typedef struct
+{
+    UINT8               num_attr;
+    tBTA_BLE_ATTR       attr_list[BTA_BLE_NUM_AD_ATTR_MAX];
+}tBTA_BLE_ATTR_DATA;
+
+typedef struct
+{
+    UINT8       len;
+    UINT8      *p_val;
+}tBTA_BLE_MANU;
+
+typedef struct
+{
+    tBTA_BLE_MANU       manu;        /* manufactuer data */
+    tBTA_BLE_INT_RANGE  int_range;      /* slave prefered conn interval range */
+    tBTA_BLE_SERVICE    services;       /* services */
+    tBTA_BLE_ATTR_DATA  attr;           /* attribute data */
+    UINT8               flag;
+}tBTA_BLE_ADV_DATA;
+
+/* These are the fields returned in each device adv packet.  It
+** is returned in the results callback if registered.
+*/
+typedef struct
+{
+    UINT8               conn_mode;
+    tBTA_BLE_AD_MASK    ad_mask;        /* mask of the valid adv data field */
+    UINT8               flag;
+    UINT8               tx_power_level;
+    UINT8               remote_name_len;
+    UINT8               *p_remote_name;
+    tBTA_BLE_ATTR_DATA  attr_data;
+    tBTA_BLE_SERVICE    service;
+} tBTA_BLE_INQ_DATA;
+#endif
+
+typedef INT8 tBTA_DM_RSSI_VALUE;
+typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
+
+
+/* signal strength mask */
+#define BTA_SIG_STRENGTH_RSSI_MASK          1
+#define BTA_SIG_STRENGTH_LINK_QUALITY_MASK  2
+
+typedef UINT8 tBTA_SIG_STRENGTH_MASK;
+
+
+/* Security Callback Events */
+#define BTA_DM_ENABLE_EVT               0       /* Enable Event */
+#define BTA_DM_DISABLE_EVT              1       /* Disable Event */
+#define BTA_DM_PIN_REQ_EVT              2       /* PIN request. */
+#define BTA_DM_AUTH_CMPL_EVT            3       /* Authentication complete indication. */
+#define BTA_DM_AUTHORIZE_EVT            4       /* Authorization request. */
+#define BTA_DM_LINK_UP_EVT              5       /* Connection UP event */
+#define BTA_DM_LINK_DOWN_EVT            6       /* Connection DOWN event */
+#define BTA_DM_SIG_STRENGTH_EVT         7       /* Signal strength for bluetooth connection */
+#define BTA_DM_BUSY_LEVEL_EVT           8       /* System busy level */
+#define BTA_DM_BOND_CANCEL_CMPL_EVT     9       /* Bond cancel complete indication */
+#define BTA_DM_SP_CFM_REQ_EVT           10      /* Simple Pairing User Confirmation request. */
+#define BTA_DM_SP_KEY_NOTIF_EVT         11      /* Simple Pairing Passkey Notification */
+#define BTA_DM_SP_RMT_OOB_EVT           12      /* Simple Pairing Remote OOB Data request. */
+#define BTA_DM_SP_KEYPRESS_EVT          13      /* Key press notification event. */
+#define BTA_DM_ROLE_CHG_EVT             14      /* Role Change event. */
+#define BTA_DM_BLE_KEY_EVT              15      /* BLE SMP key event for peer device keys */
+#define BTA_DM_BLE_SEC_REQ_EVT          16      /* BLE SMP security request */
+#define BTA_DM_BLE_PASSKEY_NOTIF_EVT    17      /* SMP passkey notification event */
+#define BTA_DM_BLE_PASSKEY_REQ_EVT      18      /* SMP passkey request event */
+#define BTA_DM_BLE_OOB_REQ_EVT          19      /* SMP OOB request event */
+#define BTA_DM_BLE_LOCAL_IR_EVT         20      /* BLE local IR event */
+#define BTA_DM_BLE_LOCAL_ER_EVT         21      /* BLE local ER event */
+// btla-specific ++
+#define BTA_DM_BLE_AUTH_CMPL_EVT        22      /* BLE Auth complete */
+// btla-specific --
+#define BTA_DM_DEV_UNPAIRED_EVT         23
+#define BTA_DM_HW_ERROR_EVT             24      /* BT Chip H/W error */
+typedef UINT8 tBTA_DM_SEC_EVT;
+
+/* Structure associated with BTA_DM_ENABLE_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address of local device. */
+    tBTA_STATUS    status;
+} tBTA_DM_ENABLE;
+
+/* Structure associated with BTA_DM_PIN_REQ_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    DEV_CLASS       dev_class;          /* Class of Device */
+} tBTA_DM_PIN_REQ;
+
+/* BLE related definition */
+
+#define BTA_DM_AUTH_FAIL_BASE                   (HCI_ERR_MAX_ERR + 10)
+#define BTA_DM_AUTH_CONVERT_SMP_CODE(x)        (BTA_DM_AUTH_FAIL_BASE + (x))
+#define BTA_DM_AUTH_SMP_PASSKEY_FAIL             BTA_DM_AUTH_CONVERT_SMP_CODE (SMP_PASSKEY_ENTRY_FAIL)
+#define BTA_DM_AUTH_SMP_OOB_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_OOB_FAIL)
+#define BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL          (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_AUTH_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL      (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_VALUE_ERR)
+#define BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT        (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_NOT_SUPPORT)
+#define BTA_DM_AUTH_SMP_ENC_KEY_SIZE            (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_KEY_SIZE)
+#define BTA_DM_AUTH_SMP_INVALID_CMD             (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_CMD)
+#define BTA_DM_AUTH_SMP_UNKNOWN_ERR             (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_FAIL_UNKNOWN)
+#define BTA_DM_AUTH_SMP_REPEATED_ATTEMPT        (BTA_DM_AUTH_FAIL_BASE + SMP_REPEATED_ATTEMPTS)
+#define BTA_DM_AUTH_SMP_INTERNAL_ERR            (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_INTERNAL_ERR)
+#define BTA_DM_AUTH_SMP_UNKNOWN_IO              (BTA_DM_AUTH_FAIL_BASE + SMP_UNKNOWN_IO_CAP)
+#define BTA_DM_AUTH_SMP_INIT_FAIL               (BTA_DM_AUTH_FAIL_BASE + SMP_INIT_FAIL)
+#define BTA_DM_AUTH_SMP_CONFIRM_FAIL            (BTA_DM_AUTH_FAIL_BASE + SMP_CONFIRM_FAIL)
+#define BTA_DM_AUTH_SMP_BUSY                    (BTA_DM_AUTH_FAIL_BASE + SMP_BUSY)
+#define BTA_DM_AUTH_SMP_ENC_FAIL                (BTA_DM_AUTH_FAIL_BASE + SMP_ENC_FAIL)
+#define BTA_DM_AUTH_SMP_RSP_TIMEOUT             (BTA_DM_AUTH_FAIL_BASE + SMP_RSP_TIMEOUT)
+
+/* connection parameter boundary value and dummy value */
+#define BTA_DM_BLE_SCAN_INT_MIN          BTM_BLE_SCAN_INT_MIN
+#define BTA_DM_BLE_SCAN_INT_MAX          BTM_BLE_SCAN_INT_MAX
+#define BTA_DM_BLE_SCAN_WIN_MIN          BTM_BLE_SCAN_WIN_MIN
+#define BTA_DM_BLE_SCAN_WIN_MAX          BTM_BLE_SCAN_WIN_MAX
+#define BTA_DM_BLE_CONN_INT_MIN          BTM_BLE_CONN_INT_MIN
+#define BTA_DM_BLE_CONN_INT_MAX          BTM_BLE_CONN_INT_MAX
+#define BTA_DM_BLE_CONN_LATENCY_MAX      BTM_BLE_CONN_LATENCY_MAX
+#define BTA_DM_BLE_CONN_SUP_TOUT_MIN     BTM_BLE_CONN_SUP_TOUT_MIN
+#define BTA_DM_BLE_CONN_SUP_TOUT_MAX     BTM_BLE_CONN_SUP_TOUT_MAX
+#define BTA_DM_BLE_CONN_PARAM_UNDEF      BTM_BLE_CONN_PARAM_UNDEF  /* use this value when a specific value not to be overwritten */
+
+
+#define BTA_LE_KEY_PENC      BTM_LE_KEY_PENC  /* encryption information of peer device */
+#define BTA_LE_KEY_PID       BTM_LE_KEY_PID   /* identity key of the peer device */
+#define BTA_LE_KEY_PCSRK     BTM_LE_KEY_PCSRK   /* peer SRK */
+#define BTA_LE_KEY_LENC      BTM_LE_KEY_LENC        /* master role security information:div */
+#define BTA_LE_KEY_LID       BTM_LE_KEY_LID         /* master device ID key */
+#define BTA_LE_KEY_LCSRK     BTM_LE_KEY_LCSRK        /* local CSRK has been deliver to peer */
+typedef UINT8 tBTA_LE_KEY_TYPE; /* can be used as a bit mask */
+
+
+typedef tBTM_LE_PENC_KEYS  tBTA_LE_PENC_KEYS ;
+typedef tBTM_LE_PCSRK_KEYS tBTA_LE_PCSRK_KEYS;
+typedef tBTM_LE_LENC_KEYS  tBTA_LE_LENC_KEYS  ;
+typedef tBTM_LE_LCSRK_KEYS tBTA_LE_LCSRK_KEYS ;
+
+typedef union
+{
+    tBTA_LE_PENC_KEYS   penc_key;       /* received peer encryption key */
+    tBTA_LE_PCSRK_KEYS  psrk_key;       /* received peer device SRK */
+    BT_OCTET16          pid_key;        /* peer device ID key */
+    tBTA_LE_LENC_KEYS   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+    tBTA_LE_LCSRK_KEYS  lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
+}tBTA_LE_KEY_VALUE;
+
+#define BTA_BLE_LOCAL_KEY_TYPE_ID         1
+#define BTA_BLE_LOCAL_KEY_TYPE_ER         2
+typedef UINT8 tBTA_DM_BLE_LOCAL_KEY_MASK;
+
+typedef struct
+{
+    BT_OCTET16       ir;
+    BT_OCTET16       irk;
+    BT_OCTET16       dhk;
+}tBTA_BLE_LOCAL_ID_KEYS;
+
+#define BTA_DM_SEC_GRANTED              BTA_SUCCESS
+#define BTA_DM_SEC_PAIR_NOT_SPT         BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT
+#define BTA_DM_SEC_REP_ATTEMPTS         BTA_DM_AUTH_SMP_REPEATED_ATTEMPT
+typedef UINT8 tBTA_DM_BLE_SEC_GRANT;
+
+
+#define BTA_DM_BLE_ONN_NONE             BTM_BLE_CONN_NONE
+#define BTA_DM_BLE_CONN_AUTO            BTM_BLE_CONN_AUTO
+#define BTA_DM_BLE_CONN_SELECTIVE       BTM_BLE_CONN_SELECTIVE
+typedef UINT8 tBTA_DM_BLE_CONN_TYPE;
+
+typedef BOOLEAN (tBTA_DM_BLE_SEL_CBACK)(BD_ADDR random_bda, UINT8 *p_remote_name);
+
+/* Structure associated with BTA_DM_BLE_SEC_REQ_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;        /* peer address */
+    BD_NAME         bd_name;        /* peer device name */
+} tBTA_DM_BLE_SEC_REQ;
+
+typedef struct
+{
+    BD_ADDR                 bd_addr;        /* peer address */
+    tBTM_LE_KEY_TYPE        key_type;
+    tBTM_LE_KEY_VALUE       key_value;
+}tBTA_DM_BLE_KEY;
+
+/* Structure associated with BTA_DM_AUTH_CMPL_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    BOOLEAN         key_present;        /* Valid link key value in key element */
+    LINK_KEY        key;                /* Link key associated with peer device. */
+    UINT8           key_type;           /* The type of Link Key */
+    BOOLEAN         success;            /* TRUE of authentication succeeded, FALSE if failed. */
+    UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
+
+} tBTA_DM_AUTH_CMPL;
+
+
+/* Structure associated with BTA_DM_AUTHORIZE_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    BD_NAME         bd_name;            /* Name of peer device. */
+    tBTA_SERVICE_ID service;            /* Service ID to authorize. */
+// btla-specific ++
+    DEV_CLASS      dev_class;
+// btla-specific --
+} tBTA_DM_AUTHORIZE;
+
+/* Structure associated with BTA_DM_LINK_UP_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+} tBTA_DM_LINK_UP;
+
+/* Structure associated with BTA_DM_LINK_DOWN_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    UINT8           status;             /* connection open/closed */
+} tBTA_DM_LINK_DOWN;
+
+/* Structure associated with BTA_DM_ROLE_CHG_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    UINT8           new_role;           /* the new connection role */
+} tBTA_DM_ROLE_CHG;
+
+/* Structure associated with BTA_DM_SIG_STRENGTH_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;            /* BD address peer device. */
+    tBTA_SIG_STRENGTH_MASK mask;        /* mask for the values that are valid */
+    tBTA_DM_RSSI_VALUE  rssi_value;
+    tBTA_DM_LINK_QUALITY_VALUE link_quality_value;
+
+} tBTA_DM_SIG_STRENGTH;
+
+/* Structure associated with BTA_DM_BUSY_LEVEL_EVT */
+typedef struct
+{
+    UINT8           level;     /* when paging or inquiring, level is 10.
+                                    Otherwise, the number of ACL links */
+} tBTA_DM_BUSY_LEVEL;
+
+#define BTA_IO_CAP_OUT      BTM_IO_CAP_OUT      /* DisplayOnly */
+#define BTA_IO_CAP_IO       BTM_IO_CAP_IO       /* DisplayYesNo */
+#define BTA_IO_CAP_IN       BTM_IO_CAP_IN       /* KeyboardOnly */
+#define BTA_IO_CAP_NONE     BTM_IO_CAP_NONE     /* NoInputNoOutput */
+typedef tBTM_IO_CAP     tBTA_IO_CAP;
+
+#define BTA_AUTH_SP_NO    BTM_AUTH_SP_NO      /* 0 MITM Protection Not Required - Single Profile/non-bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SP_YES   BTM_AUTH_SP_YES     /* 1 MITM Protection Required - Single Profile/non-bonding
+                                                Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_AP_NO    BTM_AUTH_AP_NO      /* 2 MITM Protection Not Required - All Profiles/dedicated bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_AP_YES   BTM_AUTH_AP_YES     /* 3 MITM Protection Required - All Profiles/dedicated bonding
+                                                Use IO Capabilities to determine authentication procedure */
+#define BTA_AUTH_SPGB_NO  BTM_AUTH_SPGB_NO    /* 4 MITM Protection Not Required - Single Profiles/general bonding
+                                                Numeric comparison with automatic accept allowed */
+#define BTA_AUTH_SPGB_YES BTM_AUTH_SPGB_YES   /* 5 MITM Protection Required - Single Profiles/general bonding
+                                                Use IO Capabilities to determine authentication procedure */
+typedef tBTM_AUTH_REQ   tBTA_AUTH_REQ;
+
+#define BTA_AUTH_DD_BOND    BTM_AUTH_DD_BOND  /* 2 this bit is set for dedicated bonding */
+#define BTA_AUTH_GEN_BOND   BTM_AUTH_SPGB_NO  /* 4 this bit is set for general bonding */
+#define BTA_AUTH_BONDS      BTM_AUTH_BONDS    /* 6 the general/dedicated bonding bits  */
+
+#define BTA_LE_AUTH_NO_BOND    BTM_LE_AUTH_REQ_NO_BOND  /* 0*/
+#define BTA_LE_AUTH_BOND       BTM_LE_AUTH_REQ_BOND     /* 1 << 0 */
+#define BTA_LE_AUTH_REQ_MITM   BTM_LE_AUTH_REQ_MITM    /* 1 << 2 */
+typedef tBTM_LE_AUTH_REQ       tBTA_LE_AUTH_REQ;       /* combination of the above bit pattern */
+
+#define BTA_OOB_NONE        BTM_OOB_NONE
+#define BTA_OOB_PRESENT     BTM_OOB_PRESENT
+#if BTM_OOB_INCLUDED == TRUE
+#define BTA_OOB_UNKNOWN     BTM_OOB_UNKNOWN
+#endif
+typedef tBTM_OOB_DATA   tBTA_OOB_DATA;
+
+/* Structure associated with BTA_DM_SP_CFM_REQ_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+    UINT32          num_val;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+    BOOLEAN         just_works;     /* TRUE, if "Just Works" association model */
+    tBTA_AUTH_REQ   loc_auth_req;   /* Authentication required for local device */
+    tBTA_AUTH_REQ   rmt_auth_req;   /* Authentication required for peer device */
+    tBTA_IO_CAP     loc_io_caps;    /* IO Capabilities of local device */
+    tBTA_AUTH_REQ   rmt_io_caps;    /* IO Capabilities of remote device */
+} tBTA_DM_SP_CFM_REQ;
+
+enum
+{
+    BTA_SP_KEY_STARTED,         /* passkey entry started */
+    BTA_SP_KEY_ENTERED,         /* passkey digit entered */
+    BTA_SP_KEY_ERASED,          /* passkey digit erased */
+    BTA_SP_KEY_CLEARED,         /* passkey cleared */
+    BTA_SP_KEY_COMPLT           /* passkey entry completed */
+};
+typedef UINT8   tBTA_SP_KEY_TYPE;
+
+/* Structure associated with BTA_DM_SP_KEYPRESS_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* peer address */
+    tBTA_SP_KEY_TYPE   notif_type;
+}tBTA_DM_SP_KEY_PRESS;
+
+/* Structure associated with BTA_DM_SP_KEY_NOTIF_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+    UINT32          passkey;        /* the numeric value for comparison. If just_works, do not show this number to UI */
+} tBTA_DM_SP_KEY_NOTIF;
+
+/* Structure associated with BTA_DM_SP_RMT_OOB_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;        /* peer address */
+    DEV_CLASS       dev_class;      /* peer CoD */
+    BD_NAME         bd_name;        /* peer device name */
+} tBTA_DM_SP_RMT_OOB;
+
+/* Structure associated with BTA_DM_BOND_CANCEL_CMPL_EVT */
+typedef struct
+{
+    tBTA_STATUS     result;    /* TRUE of bond cancel succeeded, FALSE if failed. */
+} tBTA_DM_BOND_CANCEL_CMPL;
+
+/* Union of all security callback structures */
+typedef union
+{
+    tBTA_DM_ENABLE      enable;         /* BTA enabled */
+    tBTA_DM_PIN_REQ     pin_req;        /* PIN request. */
+    tBTA_DM_AUTH_CMPL   auth_cmpl;      /* Authentication complete indication. */
+    tBTA_DM_AUTHORIZE   authorize;      /* Authorization request. */
+    tBTA_DM_LINK_UP     link_up;       /* ACL connection down event */
+    tBTA_DM_LINK_DOWN   link_down;       /* ACL connection down event */
+    tBTA_DM_SIG_STRENGTH sig_strength;  /* rssi and link quality value */
+    tBTA_DM_BUSY_LEVEL  busy_level;     /* System busy level */
+    tBTA_DM_SP_CFM_REQ  cfm_req;        /* user confirm request */
+    tBTA_DM_SP_KEY_NOTIF key_notif;     /* passkey notification */
+    tBTA_DM_SP_RMT_OOB  rmt_oob;        /* remote oob */
+    tBTA_DM_BOND_CANCEL_CMPL bond_cancel_cmpl; /* Bond Cancel Complete indication */
+    tBTA_DM_SP_KEY_PRESS   key_press;   /* key press notification event */
+    tBTA_DM_ROLE_CHG     role_chg;       /* role change event */
+    tBTA_DM_BLE_SEC_REQ  ble_req;        /* BLE SMP related request */
+    tBTA_DM_BLE_KEY      ble_key;        /* BLE SMP keys used when pairing */
+    tBTA_BLE_LOCAL_ID_KEYS  ble_id_keys;  /* IR event */
+    BT_OCTET16              ble_er;       /* ER event data */
+} tBTA_DM_SEC;
+
+/* Security callback */
+typedef void (tBTA_DM_SEC_CBACK)(tBTA_DM_SEC_EVT event, tBTA_DM_SEC *p_data);
+
+/* Vendor Specific Command Callback */
+typedef tBTM_VSC_CMPL_CB        tBTA_VENDOR_CMPL_CBACK;
+
+/* Search callback events */
+#define BTA_DM_INQ_RES_EVT              0       /* Inquiry result for a peer device. */
+#define BTA_DM_INQ_CMPL_EVT             1       /* Inquiry complete. */
+#define BTA_DM_DISC_RES_EVT             2       /* Discovery result for a peer device. */
+#define BTA_DM_DISC_BLE_RES_EVT         3       /* Discovery result for BLE GATT based servoce on a peer device. */
+#define BTA_DM_DISC_CMPL_EVT            4       /* Discovery complete. */
+#define BTA_DM_DI_DISC_CMPL_EVT         5       /* Discovery complete. */
+#define BTA_DM_SEARCH_CANCEL_CMPL_EVT   6       /* Search cancelled */
+
+typedef UINT8 tBTA_DM_SEARCH_EVT;
+
+#define BTA_DM_INQ_RES_IGNORE_RSSI      BTM_INQ_RES_IGNORE_RSSI /* 0x7f RSSI value not supplied (ignore it) */
+
+/* Structure associated with BTA_DM_INQ_RES_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;                /* BD address peer device. */
+    DEV_CLASS       dev_class;              /* Device class of peer device. */
+    BOOLEAN         remt_name_not_required; /* Application sets this flag if it already knows the name of the device */
+                                            /* If the device name is known to application BTA skips the remote name request */
+    BOOLEAN         is_limited;             /* TRUE, if the limited inquiry bit is set in the CoD */
+    INT8            rssi;                   /* The rssi value */
+    UINT8           *p_eir;                 /* received EIR */
+#if (BLE_INCLUDED == TRUE)
+    UINT8               inq_result_type;
+    UINT8               ble_addr_type;
+    tBTM_BLE_EVT_TYPE   ble_evt_type;
+    tBT_DEVICE_TYPE     device_type;
+#endif
+
+} tBTA_DM_INQ_RES;
+
+/* Structure associated with BTA_DM_INQ_CMPL_EVT */
+typedef struct
+{
+    UINT8           num_resps;          /* Number of inquiry responses. */
+} tBTA_DM_INQ_CMPL;
+
+/* Structure associated with BTA_DM_DI_DISC_CMPL_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    UINT8               num_record;     /* Number of DI record */
+    tBTA_STATUS         result;
+} tBTA_DM_DI_DISC_CMPL;
+
+/* Structure associated with BTA_DM_DISC_RES_EVT */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    BD_NAME             bd_name;        /* Name of peer device. */
+    tBTA_SERVICE_MASK   services;       /* Services found on peer device. */
+// btla-specific ++
+    UINT8           *   p_raw_data;     /* Raw data for discovery DB */
+    UINT32              raw_data_size;  /* size of raw data */
+    tBT_DEVICE_TYPE     device_type;    /* device type in case it is BLE device */
+    UINT32              num_uuids;
+    UINT8               *p_uuid_list;
+// btla-specific --
+    tBTA_STATUS         result;
+} tBTA_DM_DISC_RES;
+
+/* Structure associated with tBTA_DM_DISC_BLE_RES */
+typedef struct
+{
+    BD_ADDR             bd_addr;        /* BD address peer device. */
+    BD_NAME             bd_name;        /* Name of peer device. */
+    tBT_UUID            service;        /* GATT based Services UUID found on peer device. */
+} tBTA_DM_DISC_BLE_RES;
+
+
+/* Union of all search callback structures */
+typedef union
+{
+    tBTA_DM_INQ_RES     inq_res;        /* Inquiry result for a peer device. */
+    tBTA_DM_INQ_CMPL    inq_cmpl;       /* Inquiry complete. */
+    tBTA_DM_DISC_RES    disc_res;       /* Discovery result for a peer device. */
+    tBTA_DM_DISC_BLE_RES    disc_ble_res;   /* discovery result for GATT based service */
+    tBTA_DM_DI_DISC_CMPL    di_disc;        /* DI discovery result for a peer device */
+
+} tBTA_DM_SEARCH;
+
+/* Search callback */
+typedef void (tBTA_DM_SEARCH_CBACK)(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data);
+
+/* Execute call back */
+typedef void (tBTA_DM_EXEC_CBACK) (void * p_param);
+
+/* Encryption callback*/
+typedef void (tBTA_DM_ENCRYPT_CBACK) (BD_ADDR bd_addr, tBTA_STATUS result);
+
+#if BLE_INCLUDED == TRUE
+#define BTA_DM_BLE_SEC_NONE         BTM_BLE_SEC_NONE
+#define BTA_DM_BLE_SEC_ENCRYPT      BTM_BLE_SEC_ENCRYPT
+#define BTA_DM_BLE_SEC_NO_MITM      BTM_BLE_SEC_ENCRYPT_NO_MITM
+#define BTA_DM_BLE_SEC_MITM         BTM_BLE_SEC_ENCRYPT_MITM
+typedef tBTM_BLE_SEC_ACT            tBTA_DM_BLE_SEC_ACT;
+#else
+typedef UINT8                       tBTA_DM_BLE_SEC_ACT;
+#endif
+
+/* Maximum service name length */
+#define BTA_SERVICE_NAME_LEN    35
+#define BTA_SERVICE_DESP_LEN    BTA_SERVICE_NAME_LEN
+#define BTA_PROVIDER_NAME_LEN   BTA_SERVICE_NAME_LEN
+
+
+/* link policy masks  */
+#define BTA_DM_LP_SWITCH        HCI_ENABLE_MASTER_SLAVE_SWITCH
+#define BTA_DM_LP_HOLD          HCI_ENABLE_HOLD_MODE
+#define BTA_DM_LP_SNIFF         HCI_ENABLE_SNIFF_MODE
+#define BTA_DM_LP_PARK          HCI_ENABLE_PARK_MODE
+typedef UINT16 tBTA_DM_LP_MASK;
+
+/* power mode actions  */
+#define BTA_DM_PM_NO_ACTION    0x00       /* no change to the current pm setting */
+#define BTA_DM_PM_PARK         0x10       /* prefers park mode */
+#define BTA_DM_PM_SNIFF        0x20       /* prefers sniff mode */
+#define BTA_DM_PM_SNIFF1       0x21       /* prefers sniff1 mode */
+#define BTA_DM_PM_SNIFF2       0x22       /* prefers sniff2 mode */
+#define BTA_DM_PM_SNIFF3       0x23       /* prefers sniff3 mode */
+#define BTA_DM_PM_SNIFF4       0x24       /* prefers sniff4 mode */
+#define BTA_DM_PM_SNIFF5       0x25       /* prefers sniff5 mode */
+#define BTA_DM_PM_SNIFF6       0x26       /* prefers sniff6 mode */
+#define BTA_DM_PM_SNIFF7       0x27       /* prefers sniff7 mode */
+#define BTA_DM_PM_SNIFF_USER0  0x28       /* prefers user-defined sniff0 mode (testtool only) */
+#define BTA_DM_PM_SNIFF_USER1  0x29       /* prefers user-defined sniff1 mode (testtool only) */
+#define BTA_DM_PM_ACTIVE       0x40       /* prefers active mode */
+#define BTA_DM_PM_RETRY        0x80       /* retry power mode based on current settings */
+#define BTA_DM_PM_NO_PREF      0x01       /* service has no prefernce on power mode setting. eg. connection to service got closed */
+
+typedef UINT8 tBTA_DM_PM_ACTTION;
+
+/* index to bta_dm_ssr_spec */
+#define BTA_DM_PM_SSR0          0
+#define BTA_DM_PM_SSR1          1
+#define BTA_DM_PM_SSR2          2
+#define BTA_DM_PM_SSR3          3
+#define BTA_DM_PM_SSR4          4
+#define BTA_DM_PM_SSR5          5
+#define BTA_DM_PM_SSR6          6
+
+#define BTA_DM_PM_NUM_EVTS      9
+
+#ifndef BTA_DM_PM_PARK_IDX
+#define BTA_DM_PM_PARK_IDX      5 /* the actual index to bta_dm_pm_md[] for PARK mode */
+#endif
+
+#define BTA_DM_SW_BB_TO_MM      BTM_SW_BB_TO_MM
+#define BTA_DM_SW_MM_TO_BB      BTM_SW_MM_TO_BB
+#define BTA_DM_SW_BB_TO_BTC     BTM_SW_BB_TO_BTC
+#define BTA_DM_SW_BTC_TO_BB     BTM_SW_BTC_TO_BB
+
+typedef tBTM_SW_DIR tBTA_DM_SW_DIR;
+
+/* Switch callback events */
+#define BTA_DM_SWITCH_CMPL_EVT      0       /* Completion of the Switch API */
+
+typedef UINT8 tBTA_DM_SWITCH_EVT;
+typedef void (tBTA_DM_SWITCH_CBACK)(tBTA_DM_SWITCH_EVT event, tBTA_STATUS status);
+
+/* Audio routing out configuration */
+#define BTA_DM_ROUTE_NONE       0x00    /* No Audio output */
+#define BTA_DM_ROUTE_DAC        0x01    /* routing over analog output */
+#define BTA_DM_ROUTE_I2S        0x02    /* routing over digital (I2S) output */
+#define BTA_DM_ROUTE_BT_MONO    0x04    /* routing over SCO */
+#define BTA_DM_ROUTE_BT_STEREO  0x08    /* routing over BT Stereo */
+#define BTA_DM_ROUTE_HOST       0x10    /* routing over Host */
+#define BTA_DM_ROUTE_FMTX       0x20    /* routing over FMTX */
+#define BTA_DM_ROUTE_FMRX       0x40    /* routing over FMRX */
+#define BTA_DM_ROUTE_BTSNK      0x80    /* routing over BT SNK */
+
+typedef UINT8 tBTA_DM_ROUTE_PATH;
+
+
+/* Device Identification (DI) data structure
+*/
+/* Used to set the DI record */
+typedef tSDP_DI_RECORD          tBTA_DI_RECORD;
+/* Used to get the DI record */
+typedef tSDP_DI_GET_RECORD      tBTA_DI_GET_RECORD;
+/* SDP discovery database */
+typedef tSDP_DISCOVERY_DB       tBTA_DISCOVERY_DB;
+
+#ifndef         BTA_DI_NUM_MAX
+#define         BTA_DI_NUM_MAX       3
+#endif
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_EnableBluetooth
+**
+** Description      This function initializes BTA and prepares BTA and the
+**                  Bluetooth protocol stack for use.  This function is
+**                  typically called at startup or when Bluetooth services
+**                  are required by the phone.  This function must be called
+**                  before calling any other API function.
+**
+**
+** Returns          BTA_SUCCESS if successful.
+**                  BTA_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_EnableBluetooth(tBTA_DM_SEC_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DisableBluetooth
+**
+** Description      This function disables BTA and the Bluetooth protocol
+**                  stack.  It is called when BTA is no longer being used
+**                  by any application in the system.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DisableBluetooth(void);
+
+/*******************************************************************************
+**
+** Function         BTA_EnableTestMode
+**
+** Description      Enables bluetooth device under test mode
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_EnableTestMode(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DisableTestMode
+**
+** Description      Disable bluetooth device under test mode
+**
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DisableTestMode(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DmIsDeviceUp
+**
+** Description      This function tests whether the Bluetooth module is up
+**                  and ready.  This is a direct execution function that
+**                  may lock task scheduling on some platforms.
+**
+**
+** Returns          TRUE if the module is ready.
+**                  FALSE if the module is not ready.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmIsDeviceUp(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetDeviceName
+**
+** Description      This function sets the Bluetooth name of the local device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetDeviceName(char *p_name);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetVisibility
+**
+** Description      This function sets the Bluetooth connectable,discoverable,
+**                  pairable and conn paired only modesmodes of the local device.
+**                  This controls whether other Bluetooth devices can find and connect to
+**                  the local device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode, UINT8 pairable_mode, UINT8 conn_filter);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetScanParam
+**
+** Description      This function sets the parameters for page scan and
+**                  inquiry scan.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetScanParam (UINT16 page_scan_interval, UINT16 page_scan_window,
+                                  UINT16 inquiry_scan_interval, UINT16 inquiry_scan_window);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetAfhChannels
+**
+** Description      This function sets the AFH first and
+**                  last disable channel, so channels within
+**                  that range are disabled.
+**                  In order to use this API, BTM_BYPASS_AMP_AUTO_AFH must be set
+**                  to be TRUE
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetAfhChannels(UINT8 first, UINT8 last);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmVendorSpecificCommand
+**
+** Description      This function sends the vendor specific command
+**                  to the controller
+**
+**
+** Returns          tBTA_STATUS
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmVendorSpecificCommand (UINT16 opcode, UINT8 param_len,UINT8 *p_param_buf, tBTA_VENDOR_CMPL_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearch
+**
+** Description      This function searches for peer Bluetooth devices.  It
+**                  first performs an inquiry; for each device found from the
+**                  inquiry it gets the remote name of the device.  If
+**                  parameter services is nonzero, service discovery will be
+**                  performed on each device for the services specified.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearch(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK services,
+                                 tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchCancel
+**
+** Description      This function cancels a search that has been initiated
+**                  by calling BTA_DmSearch().
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearchCancel(void);
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscover
+**
+** Description      This function performs service discovery for the services
+**                  of a particular peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscover(BD_ADDR bd_addr, tBTA_SERVICE_MASK services,
+                                   tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverUUID
+**
+** Description      This function performs service discovery for the services
+**                  of a particular peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscoverUUID(BD_ADDR bd_addr, tSDP_UUID *uuid,
+                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetCachedRemoteName
+**
+** Description      Retieve cached remote name if available
+**
+** Returns          BTA_SUCCESS if cached name was retrieved
+**                  BTA_FAILURE if cached name is not available
+**
+*******************************************************************************/
+tBTA_STATUS BTA_DmGetCachedRemoteName(BD_ADDR remote_device, UINT8 **pp_cached_name);
+// btla-specific --
+
+/*******************************************************************************
+**
+** Function         BTA_DmIsMaster
+**
+** Description      This function checks if the local device is the master of
+**                  the link to the given device
+**
+** Returns          TRUE if master.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmIsMaster(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBond
+**
+** Description      This function initiates a bonding procedure with a peer
+**                  device.  The bonding procedure enables authentication
+**                  and optionally encryption on the Bluetooth link.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBond(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBondCancel
+**
+** Description      This function cancels a bonding procedure with a peer
+**                  device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBondCancel(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmPinReply
+**
+** Description      This function provides a PIN when one is requested by DM
+**                  during a bonding procedure.  The application should call
+**                  this function after the security callback is called with
+**                  a BTA_DM_PIN_REQ_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPinReply(BD_ADDR bd_addr, BOOLEAN accept, UINT8 pin_len,
+                                   UINT8 *p_pin);
+
+/*******************************************************************************
+**
+** Function         BTA_DmLinkPolicy
+**
+** Description      This function sets/clears the link policy mask to the given
+**                  bd_addr.
+**                  If clearing the sniff or park mode mask, the link is put
+**                  in active mode.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmLinkPolicy(BD_ADDR bd_addr, tBTA_DM_LP_MASK policy_mask,
+                                     BOOLEAN set);
+
+#if (BTM_OOB_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmLocalOob
+**
+** Description      This function retrieves the OOB data from local controller.
+**                  The result is reported by bta_dm_co_loc_oob().
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmLocalOob(void);
+#endif /* BTM_OOB_INCLUDED */
+
+/*******************************************************************************
+**
+** Function         BTA_DmConfirm
+**
+** Description      This function accepts or rejects the numerical value of the
+**                  Simple Pairing process on BTA_DM_SP_CFM_REQ_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmConfirm(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
+** Function         BTA_DmPasskeyCancel
+**
+** Description      This function is called to cancel the simple pairing process
+**                  reported by BTA_DM_SP_KEY_NOTIF_EVT
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPasskeyCancel(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevice
+**
+** Description      This function adds a device to the security database list
+**                  of peer devices. This function would typically be called
+**                  at system startup to initialize the security database with
+**                  known peer devices.  This is a direct execution function
+**                  that may lock task scheduling on some platforms.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddDevice(BD_ADDR bd_addr, DEV_CLASS dev_class,
+                                    LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+                                    BOOLEAN is_trusted, UINT8 key_type,
+                                    tBTA_IO_CAP io_cap);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddDevWithName
+**
+** Description      This function is newer version of  BTA_DmAddDevice()
+**                  which added bd_name and features as input parameters.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddDevWithName (BD_ADDR bd_addr, DEV_CLASS dev_class,
+                                      BD_NAME bd_name, BD_FEATURES features,
+                                      LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+                                      BOOLEAN is_trusted, UINT8 key_type, tBTA_IO_CAP io_cap);
+
+/*******************************************************************************
+**
+** Function         BTA_DmRemoveDevice
+**
+** Description      This function removes a device from the security database.
+**                  This is a direct execution function that may lock task
+**                  scheduling on some platforms.
+**
+**
+** Returns          BTA_SUCCESS if successful.
+**                  BTA_FAIL if operation failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmRemoveDevice(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAuthorizeReply
+**
+** Description      This function provides an authorization reply when
+**                  authorization is requested by BTA.  The application calls
+**                  this function after the security callback is called with
+**                  a BTA_DM_AUTHORIZE_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAuthorizeReply(BD_ADDR bd_addr, tBTA_SERVICE_ID service,
+                                         tBTA_AUTH_RESP response);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSignalStrength
+**
+** Description      This function initiates RSSI and channnel quality
+**                  measurments. BTA_DM_SIG_STRENGTH_EVT is sent to
+**                  application with the values of RSSI and channel
+**                  quality
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSignalStrength(tBTA_SIG_STRENGTH_MASK mask, UINT16 period, BOOLEAN start);
+
+/*******************************************************************************
+**
+** Function         BTA_DmWriteInqTxPower
+**
+** Description      This command is used to write the inquiry transmit power level
+**                  used to transmit the inquiry (ID) data packets.
+**
+** Parameters       tx_power - tx inquiry power to use, valid value is -70 ~ 20
+
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmWriteInqTxPower(INT8 tx_power);
+
+/*******************************************************************************
+**
+** Function         BTA_DmEirAddUUID
+**
+** Description      This function is called to add UUID into EIR.
+**
+** Parameters       tBT_UUID - UUID
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmEirAddUUID (tBT_UUID *p_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_DmEirRemoveUUID
+**
+** Description      This function is called to remove UUID from EIR.
+**
+** Parameters       tBT_UUID - UUID
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmEirRemoveUUID (tBT_UUID *p_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEIRConfig
+**
+** Description      This function is called to override the BTA default EIR parameters.
+**                  This funciton is only valid in a system where BTU & App task
+**                  are in the same memory space.
+**
+** Parameters       Pointer to User defined EIR config
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetEIRConfig (tBTA_DM_EIR_CONF *p_eir_cfg);
+
+/*******************************************************************************
+**
+** Function         BTA_CheckEirData
+**
+** Description      This function is called to get EIR data from significant part.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  type   - finding EIR data type
+**                  p_length - return the length of EIR data
+**
+** Returns          pointer of EIR data
+**
+*******************************************************************************/
+BTA_API extern UINT8 *BTA_CheckEirData( UINT8 *p_eir, UINT8 tag, UINT8 *p_length );
+
+/*******************************************************************************
+**
+** Function         BTA_GetEirService
+**
+** Description      This function is called to get BTA service mask from EIR.
+**
+** Parameters       p_eir - pointer of EIR significant part
+**                  p_services - return the BTA service mask
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GetEirService( UINT8 *p_eir, tBTA_SERVICE_MASK *p_services );
+
+/*******************************************************************************
+**
+** Function         BTA_DmUseSsr
+**
+** Description      This function is called to check if the connected peer device
+**                  supports SSR or not.
+**
+** Returns          TRUE, if SSR is supported
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_DmUseSsr( BD_ADDR bd_addr );
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetLocalDiRecord
+**
+** Description      This function adds a DI record to the local SDP database.
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmSetLocalDiRecord( tBTA_DI_RECORD *p_device_info,
+	                          UINT32 *p_handle );
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetLocalDiRecord
+**
+** Description      Get a specified DI record to the local SDP database. If no
+**                  record handle is provided, the primary DI record will be
+**                  returned.
+**
+** Returns          BTA_SUCCESS if record set sucessfully, otherwise error code.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmGetLocalDiRecord( tBTA_DI_GET_RECORD *p_device_info,
+	                          UINT32 *p_handle );
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiDiscover
+**
+** Description      This function queries a remote device for DI information.
+**
+** Returns          None.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiDiscover( BD_ADDR remote_device, tBTA_DISCOVERY_DB *p_db,
+                       UINT32 len, tBTA_DM_SEARCH_CBACK *p_cback );
+
+/*******************************************************************************
+**
+** Function         BTA_DmGetDiRecord
+**
+** Description      This function retrieves a remote device's DI record from
+**                  the specified database.
+**
+** Returns          None.
+**
+*******************************************************************************/
+BTA_API extern tBTA_STATUS BTA_DmGetDiRecord( UINT8 get_record_index, tBTA_DI_GET_RECORD *p_device_info,
+                        tBTA_DISCOVERY_DB *p_db );
+
+/*******************************************************************************
+**
+** Function         BTA_SysFeatures
+**
+** Description      This function is called to set system features.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_SysFeatures (UINT16 sys_features);
+
+/*******************************************************************************
+**
+** Function         bta_dmexecutecallback
+**
+** Description      This function will request BTA to execute a call back in the context of BTU task
+**                  This API was named in lower case because it is only intended
+**                  for the internal customers(like BTIF).
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dmexecutecallback (tBTA_DM_EXEC_CBACK* p_callback, void * p_param);
+
+#if (BTM_SCO_HCI_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         BTA_DmPcmInitSamples
+**
+** Description      initialize the down sample converter.
+**
+**                  src_sps: original samples per second (source audio data)
+**                            (ex. 44100, 48000)
+**                  bits: number of bits per pcm sample (16)
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmPcmInitSamples (UINT32 src_sps, UINT32 bits, UINT32 n_channels);
+
+/**************************************************************************************
+** Function         BTA_DmPcmResample
+**
+** Description      Down sampling utility to convert higher sampling rate into 8K/16bits
+**                  PCM samples.
+**
+** Parameters       p_src: pointer to the buffer where the original sampling PCM
+**                              are stored.
+**                  in_bytes:  Length of the input PCM sample buffer in byte.
+**                  p_dst:      pointer to the buffer which is to be used to store
+**                              the converted PCM samples.
+**
+**
+** Returns          INT32: number of samples converted.
+**
+**************************************************************************************/
+BTA_API extern INT32 BTA_DmPcmResample (void *p_src, UINT32 in_bytes, void *p_dst);
+#endif
+
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+/* BLE related API functions */
+/*******************************************************************************
+**
+** Function         BTA_DmBleSecurityGrant
+**
+** Description      Grant security request access.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  res              - security grant status.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSecurityGrant(BD_ADDR bd_addr, tBTA_DM_BLE_SEC_GRANT res);
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetBgConnType
+**
+** Description      This function is called to set BLE connectable mode for a
+**                  peripheral device.
+**
+** Parameters       bg_conn_type: it can be auto connection, or selective connection.
+**                  p_select_cback: callback function when selective connection procedure
+**                              is being used.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetBgConnType(tBTA_DM_BLE_CONN_TYPE bg_conn_type, tBTA_DM_BLE_SEL_CBACK *p_select_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBlePasskeyReply
+**
+** Description      Send BLE SMP passkey reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - passkey entry sucessful or declined.
+**                  passkey          - passkey value, must be a 6 digit number,
+**                                     can be lead by 0.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey);
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleDevice
+**
+** Description      Add a BLE device.  This function will be normally called
+**                  during host startup to restore all required information
+**                  for a LE device stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  dev_type         - Remote device's device type.
+**                  addr_type        - LE device address type.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddBleDevice(BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type,
+                                       tBT_DEVICE_TYPE dev_type);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmAddBleKey
+**
+** Description      Add/modify LE device information.  This function will be
+**                  normally called during host startup to restore all required
+**                  information stored in the NVRAM.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  p_le_key         - LE key values.
+**                  key_type         - LE SMP key type.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmAddBleKey (BD_ADDR bd_addr, tBTA_LE_KEY_VALUE *p_le_key,
+                                     tBTA_LE_KEY_TYPE key_type);
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBlePrefConnParams
+**
+** Description      This function is called to set the preferred connection
+**                  parameters when default connection parameter is not desired.
+**
+** Parameters:      bd_addr          - BD address of the peripheral
+**                  min_conn_int     - minimum preferred connection interval
+**                  max_conn_int     - maximum preferred connection interval
+**                  slave_latency    - preferred slave latency
+**                  supervision_tout - preferred supervision timeout
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
+                               UINT16 min_conn_int, UINT16 max_conn_int,
+                               UINT16 slave_latency, UINT16 supervision_tout );
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetBleConnScanParams
+**
+** Description      This function is called to set scan parameters used in
+**                  BLE connection request
+**
+** Parameters:      bd_addr          - BD address of the peripheral
+**                  scan_interval    - scan interval
+**                  scan_window      - scan window
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetBleConnScanParams(UINT16 scan_interval,
+                                               UINT16 scan_window );
+
+/*******************************************************************************
+**
+** Function         BTA_DmSearchExt
+**
+** Description      This function searches for peer Bluetooth devices. It performs
+**                  an inquiry and gets the remote name for devices. Service
+**                  discovery is done if services is non zero
+**
+** Parameters       p_dm_inq: inquiry conditions
+**                  services: if service is not empty, service discovery will be done.
+**                            for all GATT based service condition, put num_uuid, and
+**                            p_uuid is the pointer to the list of UUID values.
+**                  p_cback: callback functino when search is completed.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSearchExt(tBTA_DM_INQ *p_dm_inq, tBTA_SERVICE_MASK_EXT *p_services,
+                                    tBTA_DM_SEARCH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_DmDiscoverExt
+**
+** Description      This function does service discovery for services of a
+**                  peer device. When services.num_uuid is 0, it indicates all
+**                  GATT based services are to be searched; other wise a list of
+**                  UUID of interested services should be provided through
+**                  services.p_uuid.
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmDiscoverExt(BD_ADDR bd_addr, tBTA_SERVICE_MASK_EXT *p_services,
+                                    tBTA_DM_SEARCH_CBACK *p_cback, BOOLEAN sdp_search);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmSetEncryption
+**
+** Description      This function is called to ensure that connection is
+**                  encrypted.  Should be called only on an open connection.
+**                  Typically only needed for connections that first want to
+**                  bring up unencrypted links, then later encrypt them.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  p_callback    - Pointer to callback function to indicat the
+**                                  link encryption status
+**                  sec_act       - This is the security action to indicate
+**                                  what knid of BLE security level is required for
+**                                  the BLE link if the BLE is supported
+**                                  Note: This parameter is ignored for the BR/EDR link
+**                                        or the BLE is not supported
+**
+** Returns          void
+**
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
+                            tBTA_DM_BLE_SEC_ACT sec_act);
+
+#endif
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function         BTA_DmSetAfhChannelAssessment
+**
+** Description      This function is called to set the channel assessment mode on or off
+**
+** Returns          status
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
+// btla-specific --
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_API_H */
+
diff --git a/bta/include/bta_ar_api.h b/bta/include/bta_ar_api.h
new file mode 100644
index 0000000..b451cb4
--- /dev/null
+++ b/bta/include/bta_ar_api.h
@@ -0,0 +1,140 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the public interface file for the simulatenous advanced
+ *  audio/video streaming (AV) source and sink of BTA, Broadcom's Bluetooth
+ *  application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AR_API_H
+#define BTA_AR_API_H
+
+#include "avdt_api.h"
+#include "avct_api.h"
+#include "avrc_api.h"
+#include "sdp_api.h"
+#include "bta_av_api.h"
+#include "bta_sys.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/* This event signal to AR user that other profile is connected */
+#define BTA_AR_AVDT_CONN_EVT    (AVDT_MAX_EVT + 1)
+
+/*******************************************************************************
+**
+** Function         bta_ar_init
+**
+** Description      This function is called from bta_sys_init().
+**                  to initialize the control block
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_init(void);
+
+/*******************************************************************************
+**
+** Function         bta_ar_reg_avdt
+**
+** Description      This function is called to register to AVDTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_reg_avdt(tAVDT_REG *p_reg, tAVDT_CTRL_CBACK *p_cback, tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function         bta_ar_dereg_avdt
+**
+** Description      This function is called to de-register from AVDTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_dereg_avdt(tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function         bta_ar_avdt_conn
+**
+** Description      This function is called to let ar know that some AVDTP profile
+**                  is connected for this sys_id.
+**                  If the other sys modules started a timer for PENDING_EVT,
+**                  the timer can be stopped now.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_avdt_conn(tBTA_SYS_ID sys_id, BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         bta_ar_reg_avct
+**
+** Description      This function is called to register to AVCTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_reg_avct(UINT16 mtu, UINT16 mtu_br, UINT8 sec_mask, tBTA_SYS_ID sys_id);
+
+/*******************************************************************************
+**
+** Function         bta_ar_dereg_avct
+**
+** Description      This function is called to deregister from AVCTP.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_ar_dereg_avct(tBTA_SYS_ID sys_id);
+
+/******************************************************************************
+**
+** Function         bta_ar_reg_avrc
+**
+** Description      This function is called to register an SDP record for AVRCP.
+**
+** Returns          void
+**
+******************************************************************************/
+extern void bta_ar_reg_avrc(UINT16 service_uuid, char *p_service_name,
+							 char *p_provider_name, UINT16 categories, tBTA_SYS_ID sys_id);
+
+/******************************************************************************
+**
+** Function         bta_ar_dereg_avrc
+**
+** Description      This function is called to de-register/delete an SDP record for AVRCP.
+**
+** Returns          void
+**
+******************************************************************************/
+extern void bta_ar_dereg_avrc(UINT16 service_uuid, tBTA_SYS_ID sys_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AR_API_H */
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
new file mode 100644
index 0000000..eb77279
--- /dev/null
+++ b/bta/include/bta_av_api.h
@@ -0,0 +1,765 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the public interface file for the advanced audio/video streaming
+ *  (AV) subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_API_H
+#define BTA_AV_API_H
+
+#include "avrc_api.h"
+#include "avdt_api.h"
+#include "a2d_api.h"
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/* Set to TRUE if seperate authorization prompt desired for AVCTP besides A2DP authorization */
+/* Typically FALSE when AVRCP is used in conjunction with A2DP */
+#ifndef BTA_AV_WITH_AVCTP_AUTHORIZATION
+#define BTA_AV_WITH_AVCTP_AUTHORIZATION     FALSE
+#endif
+
+/* AV status values */
+#define BTA_AV_SUCCESS          0       /* successful operation */
+#define BTA_AV_FAIL             1       /* generic failure */
+#define BTA_AV_FAIL_SDP         2       /* service not found */
+#define BTA_AV_FAIL_STREAM      3       /* stream connection failed */
+#define BTA_AV_FAIL_RESOURCES   4       /* no resources */
+#define BTA_AV_FAIL_ROLE        5       /* failed due to role management related issues */
+
+typedef UINT8 tBTA_AV_STATUS;
+
+/* AV features masks */
+#define BTA_AV_FEAT_RCTG        0x0001  /* remote control target */
+#define BTA_AV_FEAT_RCCT        0x0002  /* remote control controller */
+#define BTA_AV_FEAT_PROTECT     0x0004  /* streaming media contect protection */
+#define BTA_AV_FEAT_VENDOR      0x0008  /* remote control vendor dependent commands */
+#define BTA_AV_FEAT_REPORT      0x0020  /* use reporting service for VDP */
+#define BTA_AV_FEAT_METADATA    0x0040  /* remote control Metadata Transfer command/response */
+#define BTA_AV_FEAT_MULTI_AV    0x0080  /* use multi-av, if controller supports it */
+#define BTA_AV_FEAT_BROWSE      0x0010  /* use browsing channel */
+#define BTA_AV_FEAT_MASTER      0x0100  /* stream only as master role */
+#define BTA_AV_FEAT_ADV_CTRL    0x0200  /* remote control Advanced Control command/response */
+#define BTA_AV_FEAT_DELAY_RPT   0x0400  /* allow delay reporting */
+#define BTA_AV_FEAT_ACP_START   0x0800  /* start stream when 2nd SNK was accepted   */
+
+/* Internal features */
+#define BTA_AV_FEAT_NO_SCO_SSPD 0x8000  /* Do not suspend av streaming as to AG events(SCO or Call) */
+
+typedef UINT16 tBTA_AV_FEAT;
+
+/* AV channel values */
+#define BTA_AV_CHNL_MSK             0xC0
+#define BTA_AV_CHNL_AUDIO           0x40  /* audio channel */
+#define BTA_AV_CHNL_VIDEO           0x80  /* video channel */
+typedef UINT8 tBTA_AV_CHNL;
+
+
+#define BTA_AV_HNDL_MSK             0x3F
+typedef UINT8 tBTA_AV_HNDL;
+/* handle index to mask */
+#define BTA_AV_HNDL_TO_MSK(h)       ((UINT8)(1 << (h)))
+
+/* tBTA_AV_HNDL to mask */
+#define BTA_AV_HNDL_TYPE_TO_MSK(h)  ((UINT8)(1 << (h&BTA_AV_HNDL_MSK)))
+
+/* offset of codec type in codec info byte array */
+#define BTA_AV_CODEC_TYPE_IDX       AVDT_CODEC_TYPE_INDEX   /* 2 */
+
+
+
+/* maximum number of streams created: 1 for audio, 1 for video */
+#ifndef BTA_AV_NUM_STRS
+#define BTA_AV_NUM_STRS         2
+#endif
+
+#ifndef BTA_AV_MAX_SEPS
+#define BTA_AV_MAX_SEPS         2
+#endif
+
+#ifndef BTA_AV_MAX_A2DP_MTU
+ /*#define BTA_AV_MAX_A2DP_MTU     668 //224 (DM5) * 3 - 4(L2CAP header) */
+#define BTA_AV_MAX_A2DP_MTU     1008
+#endif
+
+#ifndef BTA_AV_MAX_VDP_MTU
+#define BTA_AV_MAX_VDP_MTU      1008
+#endif
+
+
+/* codec type */
+#define BTA_AV_CODEC_SBC        A2D_MEDIA_CT_SBC        /* SBC media codec type */
+#define BTA_AV_CODEC_M12        A2D_MEDIA_CT_M12        /* MPEG-1, 2 Audio media codec type */
+#define BTA_AV_CODEC_M24        A2D_MEDIA_CT_M24        /* MPEG-2, 4 AAC media codec type */
+#define BTA_AV_CODEC_ATRAC      A2D_MEDIA_CT_ATRAC      /* ATRAC family media codec type */
+#define BTA_AV_CODEC_H263_P0    VDP_MEDIA_CT_H263_P0    /* H.263 baseline (profile 0) */
+#define BTA_AV_CODEC_MPEG4      VDP_MEDIA_CT_MPEG4      /* MPEG-4 Visual Simple Profile */
+#define BTA_AV_CODEC_H263_P3    VDP_MEDIA_CT_H263_P3    /* H.263 profile 3 */
+#define BTA_AV_CODEC_H263_P8    VDP_MEDIA_CT_H263_P8    /* H.263 profile 8 */
+#define BTA_AV_CODEC_VEND       VDP_MEDIA_CT_VEND       /* Non-VDP */
+
+typedef UINT8 tBTA_AV_CODEC;
+
+/* Company ID in BT assigned numbers */
+#define BTA_AV_BT_VENDOR_ID     VDP_BT_VENDOR_ID        /* Broadcom Corporation */
+
+/* vendor specific codec ID */
+#define BTA_AV_CODEC_ID_H264    VDP_CODEC_ID_H264       /* Non-VDP codec ID - H.264 */
+#define BTA_AV_CODEC_ID_IMG     VDP_CODEC_ID_IMG        /* Non-VDP codec ID - images/slideshow */
+
+/* operation id list for BTA_AvRemoteCmd */
+#define BTA_AV_RC_SELECT        AVRC_ID_SELECT      /* select */
+#define BTA_AV_RC_UP            AVRC_ID_UP          /* up */
+#define BTA_AV_RC_DOWN          AVRC_ID_DOWN        /* down */
+#define BTA_AV_RC_LEFT          AVRC_ID_LEFT        /* left */
+#define BTA_AV_RC_RIGHT         AVRC_ID_RIGHT       /* right */
+#define BTA_AV_RC_RIGHT_UP      AVRC_ID_RIGHT_UP    /* right-up */
+#define BTA_AV_RC_RIGHT_DOWN    AVRC_ID_RIGHT_DOWN  /* right-down */
+#define BTA_AV_RC_LEFT_UP       AVRC_ID_LEFT_UP     /* left-up */
+#define BTA_AV_RC_LEFT_DOWN     AVRC_ID_LEFT_DOWN   /* left-down */
+#define BTA_AV_RC_ROOT_MENU     AVRC_ID_ROOT_MENU   /* root menu */
+#define BTA_AV_RC_SETUP_MENU    AVRC_ID_SETUP_MENU  /* setup menu */
+#define BTA_AV_RC_CONT_MENU     AVRC_ID_CONT_MENU   /* contents menu */
+#define BTA_AV_RC_FAV_MENU      AVRC_ID_FAV_MENU    /* favorite menu */
+#define BTA_AV_RC_EXIT          AVRC_ID_EXIT        /* exit */
+#define BTA_AV_RC_0             AVRC_ID_0           /* 0 */
+#define BTA_AV_RC_1             AVRC_ID_1           /* 1 */
+#define BTA_AV_RC_2             AVRC_ID_2           /* 2 */
+#define BTA_AV_RC_3             AVRC_ID_3           /* 3 */
+#define BTA_AV_RC_4             AVRC_ID_4           /* 4 */
+#define BTA_AV_RC_5             AVRC_ID_5           /* 5 */
+#define BTA_AV_RC_6             AVRC_ID_6           /* 6 */
+#define BTA_AV_RC_7             AVRC_ID_7           /* 7 */
+#define BTA_AV_RC_8             AVRC_ID_8           /* 8 */
+#define BTA_AV_RC_9             AVRC_ID_9           /* 9 */
+#define BTA_AV_RC_DOT           AVRC_ID_DOT         /* dot */
+#define BTA_AV_RC_ENTER         AVRC_ID_ENTER       /* enter */
+#define BTA_AV_RC_CLEAR         AVRC_ID_CLEAR       /* clear */
+#define BTA_AV_RC_CHAN_UP       AVRC_ID_CHAN_UP     /* channel up */
+#define BTA_AV_RC_CHAN_DOWN     AVRC_ID_CHAN_DOWN   /* channel down */
+#define BTA_AV_RC_PREV_CHAN     AVRC_ID_PREV_CHAN   /* previous channel */
+#define BTA_AV_RC_SOUND_SEL     AVRC_ID_SOUND_SEL   /* sound select */
+#define BTA_AV_RC_INPUT_SEL     AVRC_ID_INPUT_SEL   /* input select */
+#define BTA_AV_RC_DISP_INFO     AVRC_ID_DISP_INFO   /* display information */
+#define BTA_AV_RC_HELP          AVRC_ID_HELP        /* help */
+#define BTA_AV_RC_PAGE_UP       AVRC_ID_PAGE_UP     /* page up */
+#define BTA_AV_RC_PAGE_DOWN     AVRC_ID_PAGE_DOWN   /* page down */
+#define BTA_AV_RC_POWER         AVRC_ID_POWER       /* power */
+#define BTA_AV_RC_VOL_UP        AVRC_ID_VOL_UP      /* volume up */
+#define BTA_AV_RC_VOL_DOWN      AVRC_ID_VOL_DOWN    /* volume down */
+#define BTA_AV_RC_MUTE          AVRC_ID_MUTE        /* mute */
+#define BTA_AV_RC_PLAY          AVRC_ID_PLAY        /* play */
+#define BTA_AV_RC_STOP          AVRC_ID_STOP        /* stop */
+#define BTA_AV_RC_PAUSE         AVRC_ID_PAUSE       /* pause */
+#define BTA_AV_RC_RECORD        AVRC_ID_RECORD      /* record */
+#define BTA_AV_RC_REWIND        AVRC_ID_REWIND      /* rewind */
+#define BTA_AV_RC_FAST_FOR      AVRC_ID_FAST_FOR    /* fast forward */
+#define BTA_AV_RC_EJECT         AVRC_ID_EJECT       /* eject */
+#define BTA_AV_RC_FORWARD       AVRC_ID_FORWARD     /* forward */
+#define BTA_AV_RC_BACKWARD      AVRC_ID_BACKWARD    /* backward */
+#define BTA_AV_RC_ANGLE         AVRC_ID_ANGLE       /* angle */
+#define BTA_AV_RC_SUBPICT       AVRC_ID_SUBPICT     /* subpicture */
+#define BTA_AV_RC_F1            AVRC_ID_F1          /* F1 */
+#define BTA_AV_RC_F2            AVRC_ID_F2          /* F2 */
+#define BTA_AV_RC_F3            AVRC_ID_F3          /* F3 */
+#define BTA_AV_RC_F4            AVRC_ID_F4          /* F4 */
+#define BTA_AV_RC_F5            AVRC_ID_F5          /* F5 */
+#define BTA_AV_VENDOR           AVRC_ID_VENDOR      /* vendor unique */
+
+typedef UINT8 tBTA_AV_RC;
+
+/* state flag for pass through command */
+#define BTA_AV_STATE_PRESS      AVRC_STATE_PRESS    /* key pressed */
+#define BTA_AV_STATE_RELEASE    AVRC_STATE_RELEASE  /* key released */
+
+typedef UINT8 tBTA_AV_STATE;
+
+/* command codes for BTA_AvVendorCmd */
+#define BTA_AV_CMD_CTRL         AVRC_CMD_CTRL
+#define BTA_AV_CMD_STATUS       AVRC_CMD_STATUS
+#define BTA_AV_CMD_SPEC_INQ     AVRC_CMD_SPEC_INQ
+#define BTA_AV_CMD_NOTIF        AVRC_CMD_NOTIF
+#define BTA_AV_CMD_GEN_INQ      AVRC_CMD_GEN_INQ
+
+typedef UINT8 tBTA_AV_CMD;
+
+/* response codes for BTA_AvVendorRsp */
+#define BTA_AV_RSP_NOT_IMPL     AVRC_RSP_NOT_IMPL
+#define BTA_AV_RSP_ACCEPT       AVRC_RSP_ACCEPT
+#define BTA_AV_RSP_REJ          AVRC_RSP_REJ
+#define BTA_AV_RSP_IN_TRANS     AVRC_RSP_IN_TRANS
+#define BTA_AV_RSP_IMPL_STBL    AVRC_RSP_IMPL_STBL
+#define BTA_AV_RSP_CHANGED      AVRC_RSP_CHANGED
+#define BTA_AV_RSP_INTERIM      AVRC_RSP_INTERIM
+
+typedef UINT8 tBTA_AV_CODE;
+
+/* error codes for BTA_AvProtectRsp */
+#define BTA_AV_ERR_NONE             A2D_SUCCESS         /* Success, no error */
+#define BTA_AV_ERR_BAD_STATE        AVDT_ERR_BAD_STATE  /* Message cannot be processed in this state */
+#define BTA_AV_ERR_RESOURCE         AVDT_ERR_RESOURCE   /* Insufficient resources */
+#define BTA_AV_ERR_BAD_CP_TYPE      A2D_BAD_CP_TYPE     /* The requested Content Protection Type is not supported */
+#define BTA_AV_ERR_BAD_CP_FORMAT    A2D_BAD_CP_FORMAT   /* The format of Content Protection Data is not correct */
+
+typedef UINT8 tBTA_AV_ERR;
+
+
+/* AV callback events */
+#define BTA_AV_ENABLE_EVT       0       /* AV enabled */
+#define BTA_AV_REGISTER_EVT     1       /* registered to AVDT */
+#define BTA_AV_OPEN_EVT         2       /* connection opened */
+#define BTA_AV_CLOSE_EVT        3       /* connection closed */
+#define BTA_AV_START_EVT        4       /* stream data transfer started */
+#define BTA_AV_STOP_EVT         5       /* stream data transfer stopped */
+#define BTA_AV_PROTECT_REQ_EVT  6       /* content protection request */
+#define BTA_AV_PROTECT_RSP_EVT  7       /* content protection response */
+#define BTA_AV_RC_OPEN_EVT      8       /* remote control channel open */
+#define BTA_AV_RC_CLOSE_EVT     9       /* remote control channel closed */
+#define BTA_AV_REMOTE_CMD_EVT   10      /* remote control command */
+#define BTA_AV_REMOTE_RSP_EVT   11      /* remote control response */
+#define BTA_AV_VENDOR_CMD_EVT   12      /* vendor dependent remote control command */
+#define BTA_AV_VENDOR_RSP_EVT   13      /* vendor dependent remote control response */
+#define BTA_AV_RECONFIG_EVT     14      /* reconfigure response */
+#define BTA_AV_SUSPEND_EVT      15      /* suspend response */
+#define BTA_AV_PENDING_EVT      16      /* incoming connection pending:
+                                         * signal channel is open and stream is not open
+                                         * after BTA_AV_SIG_TIME_VAL ms */
+#define BTA_AV_META_MSG_EVT     17      /* metadata messages */
+#define BTA_AV_REJECT_EVT       18      /* incoming connection rejected */
+#define BTA_AV_RC_FEAT_EVT      19      /* remote control channel peer supported features update */
+/* Max BTA event */
+#define BTA_AV_MAX_EVT          20
+
+typedef UINT8 tBTA_AV_EVT;
+
+/* Event associated with BTA_AV_ENABLE_EVT */
+typedef struct
+{
+    tBTA_AV_FEAT    features;
+} tBTA_AV_ENABLE;
+
+/* Event associated with BTA_AV_REGISTER_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;       /* audio/video */
+    tBTA_AV_HNDL    hndl;       /* Handle associated with the stream. */
+    UINT8           app_id;     /* ID associated with call to BTA_AvRegister() */
+    tBTA_AV_STATUS  status;
+} tBTA_AV_REGISTER;
+
+/* data associated with BTA_AV_OPEN_EVT */
+#define BTA_AV_EDR_2MBPS        0x01
+#define BTA_AV_EDR_3MBPS        0x02
+typedef UINT8 tBTA_AV_EDR;
+
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    BD_ADDR         bd_addr;
+    tBTA_AV_STATUS  status;
+    BOOLEAN         starting;
+    tBTA_AV_EDR     edr;        /* 0, if peer device does not support EDR */
+} tBTA_AV_OPEN;
+
+/* data associated with BTA_AV_CLOSE_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+} tBTA_AV_CLOSE;
+
+/* data associated with BTA_AV_START_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    tBTA_AV_STATUS  status;
+    BOOLEAN         initiator; /* TRUE, if local device initiates the START */
+    BOOLEAN         suspending;
+} tBTA_AV_START;
+
+/* data associated with BTA_AV_SUSPEND_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    BOOLEAN         initiator; /* TRUE, if local device initiates the SUSPEND */
+    tBTA_AV_STATUS  status;
+} tBTA_AV_SUSPEND;
+
+/* data associated with BTA_AV_RECONFIG_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    tBTA_AV_STATUS  status;
+} tBTA_AV_RECONFIG;
+
+/* data associated with BTA_AV_PROTECT_REQ_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    UINT8           *p_data;
+    UINT16          len;
+} tBTA_AV_PROTECT_REQ;
+
+/* data associated with BTA_AV_PROTECT_RSP_EVT */
+typedef struct
+{
+    tBTA_AV_CHNL    chnl;
+    tBTA_AV_HNDL    hndl;
+    UINT8           *p_data;
+    UINT16          len;
+    tBTA_AV_ERR     err_code;
+} tBTA_AV_PROTECT_RSP;
+
+/* data associated with BTA_AV_RC_OPEN_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    tBTA_AV_FEAT    peer_features;
+    BD_ADDR         peer_addr;
+    tBTA_AV_STATUS  status;
+} tBTA_AV_RC_OPEN;
+
+/* data associated with BTA_AV_RC_CLOSE_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    BD_ADDR         peer_addr;
+} tBTA_AV_RC_CLOSE;
+
+/* data associated with BTA_AV_RC_FEAT_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    tBTA_AV_FEAT    peer_features;
+} tBTA_AV_RC_FEAT;
+
+/* data associated with BTA_AV_REMOTE_CMD_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    tBTA_AV_RC      rc_id;
+    tBTA_AV_STATE   key_state;
+    UINT8           len;
+    UINT8           *p_data;
+    tAVRC_HDR       hdr;    /* Message header. */
+    UINT8           label;
+} tBTA_AV_REMOTE_CMD;
+
+/* data associated with BTA_AV_REMOTE_RSP_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    tBTA_AV_RC      rc_id;
+    tBTA_AV_STATE   key_state;
+    UINT8           len;
+    UINT8           *p_data;
+    tBTA_AV_CODE    rsp_code;
+    UINT8           label;
+} tBTA_AV_REMOTE_RSP;
+
+/* data associated with BTA_AV_VENDOR_CMD_EVT, BTA_AV_VENDOR_RSP_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    UINT16          len;            /* Max vendor dependent message is 512 */
+    UINT8           label;
+    tBTA_AV_CODE    code;
+    UINT32          company_id;
+    UINT8           *p_data;
+} tBTA_AV_VENDOR;
+
+/* data associated with BTA_AV_META_MSG_EVT */
+typedef struct
+{
+    UINT8           rc_handle;
+    UINT16          len;
+    UINT8           label;
+    tBTA_AV_CODE    code;
+    UINT32          company_id;
+    UINT8           *p_data;
+    tAVRC_MSG       *p_msg;
+} tBTA_AV_META_MSG;
+
+/* data associated with BTA_AV_PENDING_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;
+} tBTA_AV_PEND;
+
+/* data associated with BTA_AV_REJECT_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;
+    tBTA_AV_HNDL    hndl;       /* Handle associated with the stream that rejected the connection. */
+} tBTA_AV_REJECT;
+
+
+/* union of data associated with AV callback */
+typedef union
+{
+    tBTA_AV_CHNL        chnl;
+    tBTA_AV_ENABLE      enable;
+    tBTA_AV_REGISTER    registr;
+    tBTA_AV_OPEN        open;
+    tBTA_AV_CLOSE       close;
+    tBTA_AV_START       start;
+    tBTA_AV_PROTECT_REQ protect_req;
+    tBTA_AV_PROTECT_RSP protect_rsp;
+    tBTA_AV_RC_OPEN     rc_open;
+    tBTA_AV_RC_CLOSE    rc_close;
+    tBTA_AV_REMOTE_CMD  remote_cmd;
+    tBTA_AV_REMOTE_RSP  remote_rsp;
+    tBTA_AV_VENDOR      vendor_cmd;
+    tBTA_AV_VENDOR      vendor_rsp;
+    tBTA_AV_RECONFIG    reconfig;
+    tBTA_AV_SUSPEND     suspend;
+    tBTA_AV_PEND        pend;
+    tBTA_AV_META_MSG    meta_msg;
+    tBTA_AV_REJECT      reject;
+    tBTA_AV_RC_FEAT     rc_feat;
+} tBTA_AV;
+
+
+#define BTA_AVC_PACKET_LEN                  AVRC_PACKET_LEN
+#define BTA_VENDOR_DATA_OFFSET              6
+#define BTA_VENDOR_HEADER_LEN               4
+#define BTA_MAX_VENDOR_DEPENDENT_DATA_LEN   (BTA_AVC_PACKET_LEN-BTA_VENDOR_DATA_OFFSET-BTA_VENDOR_HEADER_LEN)
+#define BTA_GROUP_NAVI_MSG_OP_DATA_LEN      5
+
+#define BTA_ERROR_INVALID_CMD           AVRC_STS_BAD_CMD
+#define BTA_ERROR_INVALID_PARAM         AVRC_STS_BAD_PARAM
+#define BTA_ERROR_BAD_CONTENTS          AVRC_STS_NOT_FOUND
+#define BTA_ERROR_INTERNAL              AVRC_STS_INTERNAL_ERR
+
+#define BTA_AV_META_SINGLE_PACKET       AVRC_PKT_SINGLE
+
+#define BTA_AV_CO_METADATA              AVRC_CO_METADATA
+
+/* AV callback */
+typedef void (tBTA_AV_CBACK)(tBTA_AV_EVT event, tBTA_AV *p_data);
+
+/* type for stream state machine action functions */
+typedef void (*tBTA_AV_ACT)(void *p_cb, void *p_data);
+
+/* type for registering VDP */
+typedef void (tBTA_AV_REG) (tAVDT_CS *p_cs, char *p_service_name, void *p_data);
+
+/* AV configuration structure */
+typedef struct
+{
+    UINT32  company_id;         /* AVRCP Company ID */
+    UINT16  avrc_mtu;           /* AVRCP MTU at L2CAP for control channel */
+    UINT16  avrc_br_mtu;        /* AVRCP MTU at L2CAP for browsing channel */
+    UINT16  avrc_ct_cat;        /* AVRCP controller categories */
+    UINT16  avrc_tg_cat;        /* AVRCP target categories */
+    UINT16  sig_mtu;            /* AVDTP signaling channel MTU at L2CAP */
+    UINT16  audio_mtu;          /* AVDTP audio transport channel MTU at L2CAP */
+    const UINT16 *p_audio_flush_to;/* AVDTP audio transport channel flush timeout */
+    UINT16  audio_mqs;          /* AVDTP audio channel max data queue size */
+    UINT16  video_mtu;          /* AVDTP video transport channel MTU at L2CAP */
+    UINT16  video_flush_to;     /* AVDTP video transport channel flush timeout */
+    BOOLEAN avrc_group;         /* TRUE, to accept AVRC 1.3 group nevigation command */
+    UINT8   num_co_ids;         /* company id count in p_meta_co_ids */
+    UINT8   num_evt_ids;        /* event id count in p_meta_evt_ids */
+    tBTA_AV_CODE  rc_pass_rsp;  /* the default response code for pass through commands */
+    const UINT32 *p_meta_co_ids;/* the metadata Get Capabilities response for company id */
+    const UINT8 *p_meta_evt_ids;/* the the metadata Get Capabilities response for event id */
+    const tBTA_AV_ACT *p_act_tbl;/* the action function table for VDP stream */
+    tBTA_AV_REG       *p_reg;   /* action function to register VDP */
+} tBTA_AV_CFG;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_AvEnable
+**
+** Description      Enable the advanced audio/video service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_AV_ENABLE_EVT. This function must
+**                  be called before other function in the AV API are
+**                  called.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvEnable(tBTA_SEC sec_mask, tBTA_AV_FEAT features,
+                          tBTA_AV_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_AvDisable
+**
+** Description      Disable the advanced audio/video service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDisable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_AvRegister
+**
+** Description      Register the audio or video service to stack. When the
+**                  operation is complete the callback function will be
+**                  called with a BTA_AV_REGISTER_EVT. This function must
+**                  be called before AVDT stream is open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvRegister(tBTA_AV_CHNL chnl, const char *p_service_name,
+                            UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         BTA_AvDeregister
+**
+** Description      Deregister the audio or video service
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDeregister(tBTA_AV_HNDL hndl);
+
+/*******************************************************************************
+**
+** Function         BTA_AvOpen
+**
+** Description      Opens an advanced audio/video connection to a peer device.
+**                  When connection is open callback function is called
+**                  with a BTA_AV_OPEN_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvOpen(BD_ADDR bd_addr, tBTA_AV_HNDL handle,
+                        BOOLEAN use_rc, tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function         BTA_AvClose
+**
+** Description      Close the current streams.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvClose(tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvDisconnect
+**
+** Description      Close the connection to the address.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvDisconnect(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_AvStart
+**
+** Description      Start audio/video stream data transfer.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvStart(void);
+
+/*******************************************************************************
+**
+** Function         BTA_AvStop
+**
+** Description      Stop audio/video stream data transfer.
+**                  If suspend is TRUE, this function sends AVDT suspend signal
+**                  to the connected peer(s).
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvStop(BOOLEAN suspend);
+
+/*******************************************************************************
+**
+** Function         BTA_AvReconfig
+**
+** Description      Reconfigure the audio/video stream.
+**                  If suspend is TRUE, this function tries the suspend/reconfigure
+**                  procedure first.
+**                  If suspend is FALSE or when suspend/reconfigure fails,
+**                  this function closes and re-opens the AVDT connection.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvReconfig(tBTA_AV_HNDL hndl, BOOLEAN suspend, UINT8 sep_info_idx,
+                            UINT8 *p_codec_info, UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function         BTA_AvProtectReq
+**
+** Description      Send a content protection request.  This function can only
+**                  be used if AV is enabled with feature BTA_AV_FEAT_PROTECT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvProtectReq(tBTA_AV_HNDL hndl, UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_AvProtectRsp
+**
+** Description      Send a content protection response.  This function must
+**                  be called if a BTA_AV_PROTECT_REQ_EVT is received.
+**                  This function can only be used if AV is enabled with
+**                  feature BTA_AV_FEAT_PROTECT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvProtectRsp(tBTA_AV_HNDL hndl, UINT8 error_code, UINT8 *p_data,
+                              UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_AvRemoteCmd
+**
+** Description      Send a remote control command.  This function can only
+**                  be used if AV is enabled with feature BTA_AV_FEAT_RCCT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvRemoteCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_RC rc_id,
+                             tBTA_AV_STATE key_state);
+
+/*******************************************************************************
+**
+** Function         BTA_AvVendorCmd
+**
+** Description      Send a vendor dependent remote control command.  This
+**                  function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_VENDOR.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvVendorCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE cmd_code,
+                             UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_AvVendorRsp
+**
+** Description      Send a vendor dependent remote control response.
+**                  This function must be called if a BTA_AV_VENDOR_CMD_EVT
+**                  is received. This function can only be used if AV is
+**                  enabled with feature BTA_AV_FEAT_VENDOR.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvVendorRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+                             UINT8 *p_data, UINT16 len, UINT32 company_id);
+
+
+/*******************************************************************************
+**
+** Function         BTA_AvOpenRc
+**
+** Description      Open an AVRCP connection toward the device with the
+**                  specified handle
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvOpenRc(tBTA_AV_HNDL handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvCloseRc
+**
+** Description      Close an AVRCP connection
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvCloseRc(UINT8 rc_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_AvMetaRsp
+**
+** Description      Send a Metadata command/response. The message contained
+**                  in p_pkt can be composed with AVRC utility functions.
+**                  This function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_METADATA.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvMetaRsp(UINT8 rc_handle, UINT8 label, tBTA_AV_CODE rsp_code,
+                               BT_HDR *p_pkt);
+
+/*******************************************************************************
+**
+** Function         BTA_AvMetaCmd
+**
+** Description      Send a Metadata/Advanced Control command. The message contained
+**                  in p_pkt can be composed with AVRC utility functions.
+**                  This function can only be used if AV is enabled with feature
+**                  BTA_AV_FEAT_METADATA.
+**                  This message is sent only when the peer supports the TG role.
+*8                  The only command makes sense right now is the absolute volume command.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_AvMetaCmd(UINT8 rc_handle, UINT8 label, tBTA_AV_CMD cmd_code, BT_HDR *p_pkt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AV_API_H */
diff --git a/bta/include/bta_av_ci.h b/bta/include/bta_av_ci.h
new file mode 100644
index 0000000..63668a9
--- /dev/null
+++ b/bta/include/bta_av_ci.h
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 is the interface file for advanced audio/video call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_CI_H
+#define BTA_AV_CI_H
+
+#include "bta_av_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_av_ci_src_data_ready
+**
+** Description      This function sends an event to the AV indicating that
+**                  the phone has audio stream data ready to send and AV
+**                  should call bta_av_co_audio_src_data_path() or
+**                  bta_av_co_video_src_data_path().
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_ci_src_data_ready(tBTA_AV_CHNL chnl);
+
+/*******************************************************************************
+**
+** Function         bta_av_ci_setconfig
+**
+** Description      This function must be called in response to function
+**                  bta_av_co_audio_setconfig() or bta_av_co_video_setconfig.
+**                  Parameter err_code is set to an AVDTP status value;
+**                  AVDT_SUCCESS if the codec configuration is ok,
+**                  otherwise error.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_ci_setconfig(tBTA_AV_HNDL hndl, UINT8 err_code,
+                                        UINT8 category, UINT8 num_seid, UINT8 *p_seid,
+                                        BOOLEAN recfg_needed);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_AV_CI_H */
+
diff --git a/bta/include/bta_av_co.h b/bta/include/bta_av_co.h
new file mode 100644
index 0000000..862ac5e
--- /dev/null
+++ b/bta/include/bta_av_co.h
@@ -0,0 +1,392 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for advanced audio/video call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_CO_H
+#define BTA_AV_CO_H
+
+#include "l2c_api.h"
+#include "bta_av_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* TRUE to use SCMS-T content protection */
+#ifndef BTA_AV_CO_CP_SCMS_T
+#define BTA_AV_CO_CP_SCMS_T     FALSE
+#endif
+
+/* the content protection IDs assigned by BT SIG */
+#define BTA_AV_CP_SCMS_T_ID     0x0002
+#define BTA_AV_CP_DTCP_ID       0x0001
+
+#define BTA_AV_CP_LOSC                  2
+#define BTA_AV_CP_INFO_LEN              3
+
+#define BTA_AV_CP_SCMS_COPY_MASK        3
+#define BTA_AV_CP_SCMS_COPY_FREE        2
+#define BTA_AV_CP_SCMS_COPY_ONCE        1
+#define BTA_AV_CP_SCMS_COPY_NEVER       0
+
+#define BTA_AV_CO_DEFAULT_AUDIO_OFFSET      AVDT_MEDIA_OFFSET
+
+enum
+{
+    BTA_AV_CO_ST_INIT,
+    BTA_AV_CO_ST_IN,
+    BTA_AV_CO_ST_OUT,
+    BTA_AV_CO_ST_OPEN,
+    BTA_AV_CO_ST_STREAM
+};
+
+
+/* data type for the Audio Codec Information*/
+typedef struct
+{
+    UINT16  bit_rate;       /* SBC encoder bit rate in kbps */
+    UINT16  bit_rate_busy;  /* SBC encoder bit rate in kbps */
+    UINT16  bit_rate_swampd;/* SBC encoder bit rate in kbps */
+    UINT8   busy_level;     /* Busy level indicating the bit-rate to be used */
+    UINT8   codec_info[AVDT_CODEC_SIZE];
+    UINT8   codec_type;     /* Codec type */
+} tBTA_AV_AUDIO_CODEC_INFO;
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_init
+**
+** Description      This callout function is executed by AV when it is
+**                  started by calling BTA_AvEnable().  This function can be
+**                  used by the phone to initialize audio paths or for other
+**                  initialization purposes.
+**
+**
+** Returns          Stream codec and content protection capabilities info.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_av_co_audio_init(UINT8 *p_codec_type, UINT8 *p_codec_info,
+                                   UINT8 *p_num_protect, UINT8 *p_protect_info, UINT8 index);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_disc_res
+**
+** Description      This callout function is executed by AV to report the
+**                  number of stream end points (SEP) were found during the
+**                  AVDT stream discovery process.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps,
+                                             UINT8 num_snk, BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_disc_res
+**
+** Description      This callout function is executed by AV to report the
+**                  number of stream end points (SEP) were found during the
+**                  AVDT stream discovery process.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_disc_res(tBTA_AV_HNDL hndl, UINT8 num_seps,
+                                             UINT8 num_snk, BD_ADDR addr);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_getconfig
+**
+** Description      This callout function is executed by AV to retrieve the
+**                  desired codec and content protection configuration for the
+**                  audio stream.
+**
+**
+** Returns          Stream codec and content protection configuration info.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_av_co_audio_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                         UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+                                         UINT8 *p_num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_getconfig
+**
+** Description      This callout function is executed by AV to retrieve the
+**                  desired codec and content protection configuration for the
+**                  video stream.
+**
+**
+** Returns          Stream codec and content protection configuration info.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_av_co_video_getconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                         UINT8 *p_codec_info, UINT8 *p_sep_info_idx, UINT8 seid,
+                                         UINT8 *p_num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_setconfig
+**
+** Description      This callout function is executed by AV to set the
+**                  codec and content protection configuration of the audio stream.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                        UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+                                        UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_setconfig
+**
+** Description      This callout function is executed by AV to set the
+**                  codec and content protection configuration of the video stream.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_setconfig(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                        UINT8 *p_codec_info, UINT8 seid, BD_ADDR addr,
+                                        UINT8 num_protect, UINT8 *p_protect_info);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_open
+**
+** Description      This function is called by AV when the audio stream connection
+**                  is opened.
+**                  BTA-AV maintains the MTU of A2DP streams.
+**                  If this is the 2nd audio stream, mtu is the smaller of the 2
+**                  streams.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_open(tBTA_AV_HNDL hndl,
+                                         tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+                                         UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_open
+**
+** Description      This function is called by AV when the video stream connection
+**                  is opened.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_open(tBTA_AV_HNDL hndl,
+                                         tBTA_AV_CODEC codec_type, UINT8 *p_codec_info,
+                                         UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_close
+**
+** Description      This function is called by AV when the audio stream connection
+**                  is closed.
+**                  BTA-AV maintains the MTU of A2DP streams.
+**                  When one stream is closed and no other audio stream is open,
+**                  mtu is reported as 0.
+**                  Otherwise, the MTU remains open is reported.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                          UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_close
+**
+** Description      This function is called by AV when the video stream connection
+**                  is closed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_close(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+                                          UINT16 mtu);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_start
+**
+** Description      This function is called by AV when the audio streaming data
+**                  transfer is started.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+        UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_start
+**
+** Description      This function is called by AV when the video streaming data
+**                  transfer is started.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_start(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,
+        UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_stop
+**
+** Description      This function is called by AV when the audio streaming data
+**                  transfer is stopped.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_stop
+**
+** Description      This function is called by AV when the video streaming data
+**                  transfer is stopped.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_stop(tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_src_data_path
+**
+** Description      This function is called to get the next data buffer from
+**                  the audio codec
+**
+** Returns          NULL if data is not ready.
+**                  Otherwise, a GKI buffer (BT_HDR*) containing the audio data.
+**
+*******************************************************************************/
+BTA_API extern void * bta_av_co_audio_src_data_path(tBTA_AV_CODEC codec_type,
+                                                    UINT32 *p_len, UINT32 *p_timestamp);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_src_data_path
+**
+** Description      This function is called to get the next data buffer from
+**                  the video codec.
+**
+** Returns          NULL if data is not ready.
+**                  Otherwise, a video data buffer (UINT8*).
+**
+*******************************************************************************/
+BTA_API extern void * bta_av_co_video_src_data_path(tBTA_AV_CODEC codec_type,
+                                                    UINT32 *p_len, UINT32 *p_timestamp);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_drop
+**
+** Description      An Audio packet is dropped. .
+**                  It's very likely that the connected headset with this handle
+**                  is moved far away. The implementation may want to reduce
+**                  the encoder bit rate setting to reduce the packet size.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_drop(tBTA_AV_HNDL hndl);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_report_conn
+**
+** Description      This function is called by AV when the reporting channel is
+**                  opened (open=TRUE) or closed (open=FALSE).
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_report_conn (BOOLEAN open, UINT8 avdt_handle);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_report_rr
+**
+** Description      This function is called by AV when a Receiver Report is
+**                  received
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_report_rr (UINT32 packet_lost);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_audio_delay
+**
+** Description      This function is called by AV when the audio stream connection
+**                  needs to send the initial delay report to the connected SRC.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_audio_delay(tBTA_AV_HNDL hndl, UINT16 delay);
+
+/*******************************************************************************
+**
+** Function         bta_av_co_video_delay
+**
+** Description      This function is called by AV when the video stream connection
+**                  needs to send the initial delay report to the connected SRC.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_av_co_video_delay(tBTA_AV_HNDL hndl, UINT16 delay);
+
+#endif /* BTA_AV_CO_H */
+
diff --git a/bta/include/bta_av_sbc.h b/bta/include/bta_av_sbc.h
new file mode 100644
index 0000000..98eb6ae
--- /dev/null
+++ b/bta/include/bta_av_sbc.h
@@ -0,0 +1,207 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the interface to utility functions for dealing with SBC data
+ *  frames and codec capabilities.
+ *
+ ******************************************************************************/
+#ifndef BTA_AV_SBC_H
+#define BTA_AV_SBC_H
+
+/*****************************************************************************
+**  constants
+*****************************************************************************/
+
+/* SBC packet header size */
+#define BTA_AV_SBC_HDR_SIZE         A2D_SBC_MPL_HDR_LEN
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_init_up_sample
+**
+** Description      initialize the up sample
+**
+**                  src_sps: samples per second (source audio data)
+**                  dst_sps: samples per second (converted audio data)
+**                  bits: number of bits per pcm sample
+**                  n_channels: number of channels (i.e. mono(1), stereo(2)...)
+**
+** Returns          none
+**
+*******************************************************************************/
+extern void bta_av_sbc_init_up_sample (UINT32 src_sps, UINT32 dst_sps,
+                                       UINT16 bits, UINT16 n_channels);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (number of bytes)
+**                  dst_samples: The size of p_dst (number of bytes)
+**
+** Note:            An AE reported an issue with this function.
+**                  When called with bta_av_sbc_up_sample(src, uint8_array_dst..)
+**                  the byte before uint8_array_dst may get overwritten.
+**                  Using uint16_array_dst avoids the problem.
+**                  This issue is related to endian-ness and is hard to resolve
+**                  in a generic manner.
+** **************** Please use uint16 array as dst.
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample (void *p_src, void *p_dst,
+                                 UINT32 src_samples, UINT32 dst_samples,
+                                 UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_16s (16bits-stereo)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 4 bytes)
+**                  dst_samples: The size of p_dst (in uint of 4 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_16s (void *p_src, void *p_dst,
+                                 UINT32 src_samples, UINT32 dst_samples,
+                                 UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_16m (16bits-mono)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 2 bytes)
+**                  dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_16m (void *p_src, void *p_dst,
+                                     UINT32 src_samples, UINT32 dst_samples,
+                                     UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_8s (8bits-stereo)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (in uint of 2 bytes)
+**                  dst_samples: The size of p_dst (in uint of 2 bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_8s (void *p_src, void *p_dst,
+                                 UINT32 src_samples, UINT32 dst_samples,
+                                 UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_up_sample_8m (8bits-mono)
+**
+** Description      Given the source (p_src) audio data and
+**                  source speed (src_sps, samples per second),
+**                  This function converts it to audio data in the desired format
+**
+**                  p_src: the data buffer that holds the source audio data
+**                  p_dst: the data buffer to hold the converted audio data
+**                  src_samples: The number of source samples (number of bytes)
+**                  dst_samples: The size of p_dst (number of bytes)
+**
+** Returns          The number of bytes used in p_dst
+**                  The number of bytes used in p_src (in *p_ret)
+**
+*******************************************************************************/
+extern int bta_av_sbc_up_sample_8m (void *p_src, void *p_dst,
+                                     UINT32 src_samples, UINT32 dst_samples,
+                                     UINT32 *p_ret);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_cfg_for_cap
+**
+** Description      Determine the preferred SBC codec configuration for the
+**                  given codec capabilities.  The function is passed the
+**                  preferred codec configuration and the peer codec
+**                  capabilities for the stream.  The function attempts to
+**                  match the preferred capabilities with the configuration
+**                  as best it can.  The resulting codec configuration is
+**                  returned in the same memory used for the capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**                  Codec configuration in p_cap.
+**
+*******************************************************************************/
+extern UINT8 bta_av_sbc_cfg_for_cap(UINT8 *p_peer, tA2D_SBC_CIE *p_cap, tA2D_SBC_CIE *p_pref);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_cfg_in_cap
+**
+** Description      This function checks whether an SBC codec configuration
+**                  is allowable for the given codec capabilities.
+**
+** Returns          0 if ok, nonzero if error.
+**
+*******************************************************************************/
+extern UINT8 bta_av_sbc_cfg_in_cap(UINT8 *p_cfg, tA2D_SBC_CIE *p_cap);
+
+/*******************************************************************************
+**
+** Function         bta_av_sbc_bld_hdr
+**
+** Description      This function builds the packet header for MPF1.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void bta_av_sbc_bld_hdr(BT_HDR *p_buf, UINT16 fr_per_pkt);
+
+#endif /* BTA_AV_SBC_H */
+
diff --git a/bta/include/bta_dm_ci.h b/bta/include/bta_dm_ci.h
new file mode 100644
index 0000000..bf0983e
--- /dev/null
+++ b/bta/include/bta_dm_ci.h
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for device mananger call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CI_H
+#define BTA_DM_CI_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_io_req
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_io_req(), if *p_oob_data is set to BTA_OOB_UNKNOWN
+**                  by bta_dm_co_io_req().
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_ci_io_req(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+                                     tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         bta_dm_ci_rmt_oob
+**
+** Description      This function must be called in response to function
+**                  bta_dm_co_rmt_oob() to provide the OOB data associated
+**                  with the remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_ci_rmt_oob(BOOLEAN accept, BD_ADDR bd_addr,
+                                      BT_OCTET16 c, BT_OCTET16 r);
+/*******************************************************************************
+**
+** Function         bta_dm_sco_ci_data_ready
+**
+** Description      This function sends an event to indicating that the phone
+**                  has SCO data ready..
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_ci_data_ready(UINT16 event, UINT16 sco_handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/bta/include/bta_dm_co.h b/bta/include/bta_dm_co.h
new file mode 100644
index 0000000..864104e
--- /dev/null
+++ b/bta/include/bta_dm_co.h
@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for device mananger callout functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_DM_CO_H
+#define BTA_DM_CO_H
+
+#include "bta_sys.h"
+
+
+#ifndef BTA_SCO_OUT_PKT_SIZE
+    #define BTA_SCO_OUT_PKT_SIZE    BTM_SCO_DATA_SIZE_MAX
+#endif
+
+#define BTA_SCO_CODEC_PCM       0       /* used for regular SCO */
+#define BTA_SCO_CODEC_SBC       1       /* used for WBS */
+typedef UINT8   tBTA_SCO_CODEC_TYPE;
+
+#define BTA_DM_SCO_SAMP_RATE_8K     8000
+#define BTA_DM_SCO_SAMP_RATE_16K    16000
+
+/* SCO codec information */
+typedef struct
+{
+    tBTA_SCO_CODEC_TYPE   codec_type;
+}tBTA_CODEC_INFO;
+
+#define BTA_DM_SCO_ROUTE_PCM	BTM_SCO_ROUTE_PCM
+#define BTA_DM_SCO_ROUTE_HCI	BTM_SCO_ROUTE_HCI
+
+typedef tBTM_SCO_ROUTE_TYPE tBTA_DM_SCO_ROUTE_TYPE;
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_req
+**
+** Description      This callout function is executed by DM to get IO capabilities
+**                  of the local device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_io_req(BD_ADDR bd_addr, tBTA_IO_CAP *p_io_cap,
+                                     tBTA_OOB_DATA *p_oob_data, tBTA_AUTH_REQ *p_auth_req,
+                                     BOOLEAN is_orig);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_io_rsp
+**
+** Description      This callout function is executed by DM to report IO capabilities
+**                  of the peer device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**                  io_cap - The remote Input/Output capabilities
+**                  oob_data - TRUE, if OOB data is available for the peer device.
+**                  auth_req - TRUE, if MITM protection is required.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_io_rsp(BD_ADDR bd_addr, tBTA_IO_CAP io_cap,
+                                     tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_lk_upgrade
+**
+** Description      This callout function is executed by DM to check if the
+**                  platform wants allow link key upgrade
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_upgrade - TRUE, if link key upgrade is desired.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void  bta_dm_co_lk_upgrade(BD_ADDR bd_addr, BOOLEAN *p_upgrade );
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_loc_oob
+**
+** Description      This callout function is executed by DM to report the OOB
+**                  data of the local device for the Simple Pairing process
+**
+** Parameters       valid - TRUE, if the local OOB data is retrieved from LM
+**                  c     - Simple Pairing Hash C
+**                  r     - Simple Pairing Randomnizer R
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_loc_oob(BOOLEAN valid, BT_OCTET16 c, BT_OCTET16 r);
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_rmt_oob
+**
+** Description      This callout function is executed by DM to request the OOB
+**                  data for the remote device for the Simple Pairing process
+**
+** Parameters       bd_addr  - The peer device
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_rmt_oob(BD_ADDR bd_addr);
+
+/*****************************************************************************
+**  SCO over HCI Function Declarations
+*****************************************************************************/
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_init
+**
+** Description      This function can be used by the phone to initialize audio
+**                  codec or for other initialization purposes before SCO connection
+**                  is opened.
+**
+**
+** Returns          Void.
+**
+*******************************************************************************/
+BTA_API extern tBTA_DM_SCO_ROUTE_TYPE bta_dm_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
+                                                         tBTA_CODEC_INFO *p_codec_info, UINT8 app_id);
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_open
+**
+** Description      This function is executed when a SCO connection is open.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_close
+**
+** Description      This function is called when a SCO connection is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_close(void);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_out_data
+**
+** Description      This function is called to send SCO data over HCI.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_out_data(BT_HDR  **p_buf);
+
+/*******************************************************************************
+**
+** Function         bta_dm_sco_co_in_data
+**
+** Description      This function is called to send incoming SCO data to application.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_sco_co_in_data(BT_HDR  *p_buf, tBTM_SCO_DATA_FLAG status);
+
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_io_req
+**
+** Description      This callout function is executed by DM to get BLE IO capabilities
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req -  Auth request setting (Bonding and MITM required or not)
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr,  tBTA_IO_CAP *p_io_cap,
+                                        tBTA_OOB_DATA *p_oob_data,
+                                        tBTA_LE_AUTH_REQ *p_auth_req,
+                                        UINT8 *p_max_key_size,
+                                        tBTA_LE_KEY_TYPE *p_init_key,
+                                        tBTA_LE_KEY_TYPE  *p_resp_key );
+
+
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_local_key_reload
+**
+** Description      This callout function is to load the local BLE keys if available
+**                  on the device.
+**
+** Parameters       none
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_load_local_keys (tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+                                                   tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+
+// btla-specific ++
+/*******************************************************************************
+**
+** Function         bta_dm_co_ble_io_req
+**
+** Description      This callout function is executed by DM to get BLE IO capabilities
+**                  before SMP pairing gets going.
+**
+** Parameters       bd_addr  - The peer device
+**                  *p_io_cap - The local Input/Output capabilities
+**                  *p_oob_data - TRUE, if OOB data is available for the peer device.
+**                  *p_auth_req -  Auth request setting (Bonding and MITM required or not)
+**                  *p_max_key_size - max key size local device supported.
+**                  *p_init_key - initiator keys.
+**                  *p_resp_key - responder keys.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_dm_co_ble_io_req(BD_ADDR bd_addr,  tBTA_IO_CAP *p_io_cap,
+                         tBTA_OOB_DATA *p_oob_data,
+                         tBTA_LE_AUTH_REQ *p_auth_req,
+                         UINT8 *p_max_key_size,
+                         tBTA_LE_KEY_TYPE *p_init_key,
+                         tBTA_LE_KEY_TYPE  *p_resp_key );
+// btla-specific --
+
+#endif
diff --git a/bta/include/bta_fs_api.h b/bta/include/bta_fs_api.h
new file mode 100644
index 0000000..a3c34e0
--- /dev/null
+++ b/bta/include/bta_fs_api.h
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for the file system of BTA, Broadcom's
+ *  Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_API_H
+#define BTA_FS_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Configuration structure */
+typedef struct
+{
+    UINT16  max_file_len;           /* Maximum size file name */
+    UINT16  max_path_len;           /* Maximum path length (includes appended file name) */
+    char    path_separator;         /* 0x2f ('/'), or 0x5c ('\') */
+} tBTA_FS_CFG;
+
+extern tBTA_FS_CFG * p_bta_fs_cfg;
+
+#endif /* BTA_FS_API_H */
diff --git a/bta/include/bta_fs_ci.h b/bta/include/bta_fs_ci.h
new file mode 100644
index 0000000..e2b5093
--- /dev/null
+++ b/bta/include/bta_fs_ci.h
@@ -0,0 +1,256 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for file system call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_CI_H
+#define BTA_FS_CI_H
+
+#include "bta_fs_co.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Open Complete Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+    UINT32            file_size;
+    int               fd;
+    const char        *p_file;
+} tBTA_FS_CI_OPEN_EVT;
+
+/* Read Ready Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+    int               fd;
+    UINT16            num_read;
+} tBTA_FS_CI_READ_EVT;
+
+/* Write Ready Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+    int               fd;
+} tBTA_FS_CI_WRITE_EVT;
+
+/* Get Directory Entry Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+} tBTA_FS_CI_GETDIR_EVT;
+
+/* Resume Information Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+    BD_ADDR_PTR       p_addr;
+    UINT8             *p_sess_info;
+    UINT32            timeout;
+    UINT32            offset;
+    UINT8             ssn;
+    UINT8             info;
+} tBTA_FS_CI_RESUME_EVT;
+
+/* Action Complete Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_FS_CO_STATUS status;
+} tBTA_FS_CI_ACTION_EVT;
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_write
+**
+** Description      This function sends an event to BTA indicating the phone
+**                  has written the number of bytes specified in the call-out
+**                  function, bta_fs_co_write(), and is ready for more data.
+**                  This function is used to control the TX data flow.
+**                  Note: The data buffer is released by the stack aioer
+**                        calling this function.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK, BTA_FS_CO_NOSPACE, or BTA_FS_CO_FAIL
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_write(int fd, tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_read
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  read in the requested amount of data specified in the
+**                  bta_fs_co_read() call-out function.  It should only be called
+**                  when the requested number of bytes has been read in, or aioer
+**                  the end of the file has been detected.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_FS_CO_OK if full buffer of data,
+**                           BTA_FS_CO_EOF if the end of file has been reached,
+**                           BTA_FS_CO_FAIL if an error has occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_read(int fd, UINT16 num_bytes_read,
+                                   tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_open
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  finished opening a file for reading or writing.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK if file was opened in mode specified
+**                                          in the call-out function.
+**                           BTA_FS_CO_EACCES if the file exists, but contains
+**                                          the wrong access permissions.
+**                           BTA_FS_CO_FAIL if any other error has occurred.
+**                  file_size - The total size of the file
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_open(int fd, tBTA_FS_CO_STATUS status,
+                                   UINT32 file_size, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_direntry
+**
+** Description      This function is called in response to the
+**                  bta_fs_co_getdirentry call-out function.
+**
+** Parameters       status - BTA_FS_CO_OK if p_entry points to a valid entry.
+**                           BTA_FS_CO_EODIR if no more entries (p_entry is ignored).
+**                           BTA_FS_CO_FAIL if any errors have occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_direntry(tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_resume
+**
+** Description      This function is called in response to the
+**                  bta_fs_co_resume call-out function.
+**
+** Parameters       p_sess_info - the stored session ID and related information.
+**                  ssn     - the stored session sequence number.
+**                  info    - the stored BTA specific information (like last active operation).
+**                  status  - BTA_FS_CO_OK if p_entry points to a valid entry.
+**                            BTA_FS_CO_FAIL if any errors have occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_resume (BD_ADDR_PTR p_addr, UINT8 *p_sess_info,
+                                      UINT32 timeout, UINT32 offset, UINT8 ssn, UINT8 info,
+                                      tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_action
+**
+** Description      This function is called in response to one of the action
+**                  call-out functions: bta_fs_co_copy, bta_fs_co_rename or
+**                  bta_fs_co_set_perms.
+**
+** Parameters       status  - BTA_FS_CO_OK if the action is succession.
+**                            BTA_FS_CO_FAIL if any errors have occurred.
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_action(tBTA_FS_CO_STATUS status, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function         bta_fs_ci_resume_op
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  finished opening a file for reading or writing on resume.
+**
+** Parameters       fd - file descriptor passed to the stack in the
+**                       bta_fs_ci_open call-in function.
+**                  status - BTA_FS_CO_OK if file was opened in mode specified
+**                                          in the call-out function.
+**                           BTA_FS_CO_EACCES if the file exists, but contains
+**                                          the wrong access permissions.
+**                           BTA_FS_CO_FAIL if any other error has occurred.
+**                  p_file - The file name associated with fd
+**                  file_size - The total size of the file
+**                  evt - Used Internally by BTA -> MUST be same value passed
+**                       in call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_ci_resume_op(int fd, tBTA_FS_CO_STATUS status, const char *p_file,
+                                        UINT32 file_size, UINT16 evt);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_FS_CI_H */
+
diff --git a/bta/include/bta_fs_co.h b/bta/include/bta_fs_co.h
new file mode 100644
index 0000000..7ab16fa
--- /dev/null
+++ b/bta/include/bta_fs_co.h
@@ -0,0 +1,703 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for the synchronization server call-out
+ *  functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_FS_CO_H
+#define BTA_FS_CO_H
+
+#include <time.h>
+
+#include "bta_api.h"
+#include "goep_fs.h"
+#include "obx_api.h"
+
+/*****************************************************************************
+**  Constants and Data Types
+*****************************************************************************/
+
+#ifndef BTA_FS_CO_MAX_SSN_ENTRIES
+#define BTA_FS_CO_MAX_SSN_ENTRIES   10
+#endif
+
+/* Maximum path length supported by FS_CO */
+#ifndef BTA_FS_CO_PATH_LEN
+#define BTA_FS_CO_PATH_LEN          294
+#endif
+
+#ifndef BTA_FS_CO_TEST_ROOT
+#define BTA_FS_CO_TEST_ROOT         "test_files"
+#endif
+
+#define BTA_FS_CO_TEST_TYPE_NONE    0
+#define BTA_FS_CO_TEST_TYPE_REJECT  1
+#define BTA_FS_CO_TEST_TYPE_SUSPEND 2
+
+#ifndef BTA_FS_CO_TEST_AB_END
+#define BTA_FS_CO_TEST_AB_END   BTA_FS_CO_TEST_TYPE_NONE
+#endif
+
+/**************************
+**  Common Definitions
+***************************/
+
+/* Status codes returned by call-out functions, or in call-in functions as status */
+#define BTA_FS_CO_OK            GOEP_OK
+#define BTA_FS_CO_FAIL          GOEP_FAIL   /* Used to pass all other errors */
+#define BTA_FS_CO_EACCES        GOEP_EACCES
+#define BTA_FS_CO_ENOTEMPTY     GOEP_ENOTEMPTY
+#define BTA_FS_CO_EOF           GOEP_EOF
+#define BTA_FS_CO_EODIR         GOEP_EODIR
+#define BTA_FS_CO_ENOSPACE      GOEP_ENOSPACE/* Returned in bta_fs_ci_open if no room */
+#define BTA_FS_CO_EIS_DIR       GOEP_EIS_DIR
+#define BTA_FS_CO_RESUME        GOEP_RESUME /* used in ci_open, on resume */
+#define BTA_FS_CO_NONE          GOEP_NONE /* used in ci_open, on resume (no file to resume) */
+
+typedef UINT16 tBTA_FS_CO_STATUS;
+
+/* the index to the permission flags */
+#define BTA_FS_PERM_USER    0
+#define BTA_FS_PERM_GROUP   1
+#define BTA_FS_PERM_OTHER   2
+/* max number of the permission flags */
+#define BTA_FS_PERM_SIZE    3
+
+/* Flags passed to the open function (bta_fs_co_open)
+**      Values are OR'd together. (First 3 are
+**      mutually exclusive.
+*/
+#define BTA_FS_O_RDONLY         GOEP_O_RDONLY
+#define BTA_FS_O_WRONLY         GOEP_O_WRONLY
+#define BTA_FS_O_RDWR           GOEP_O_RDWR
+
+#define BTA_FS_O_CREAT          GOEP_O_CREAT
+#define BTA_FS_O_EXCL           GOEP_O_EXCL
+#define BTA_FS_O_TRUNC          GOEP_O_TRUNC
+
+#define BTA_FS_O_MODE_MASK(x)      (((UINT16)(x)) & 0x0003)
+
+/* Origin for the bta_fs_co_seek function  */
+#define BTA_FS_SEEK_SET         GOEP_SEEK_SET
+#define BTA_FS_SEEK_CUR         GOEP_SEEK_CUR
+#define BTA_FS_SEEK_END         GOEP_SEEK_END
+
+/* mode field in bta_fs_co_access callout */
+#define BTA_FS_ACC_EXIST        GOEP_ACC_EXIST
+#define BTA_FS_ACC_READ         GOEP_ACC_READ
+#define BTA_FS_ACC_RDWR         GOEP_ACC_RDWR
+
+#define BTA_FS_LEN_UNKNOWN      GOEP_LEN_UNKNOWN
+#define BTA_FS_INVALID_FD       GOEP_INVALID_FD
+#define BTA_FS_INVALID_APP_ID   (0xFF)  /* this app_id is reserved */
+
+/* mode field in tBTA_FS_DIRENTRY (OR'd together) */
+#define BTA_FS_A_RDONLY         GOEP_A_RDONLY
+#define BTA_FS_A_DIR            GOEP_A_DIR      /* Entry is a sub directory */
+
+#define BTA_FS_CTIME_LEN        GOEP_CTIME_LEN  /* Creation time "yyyymmddTHHMMSSZ" */
+
+/* Return structure type for a directory entry */
+typedef struct
+{
+    UINT32  refdata;            /* holder for OS specific data used to get next entry */
+    UINT32  filesize;
+    char    crtime[BTA_FS_CTIME_LEN]; /* "yyyymmddTHHMMSSZ", or "" if none */
+    char    *p_name;            /* Contains the addr of memory to copy name into */
+    UINT8   mode;               /* BTA_FS_A_RDONLY and/or BTA_FS_A_DIR */
+} tBTA_FS_DIRENTRY;
+
+/* session state */
+enum
+{
+    BTA_FS_CO_SESS_ST_NONE,
+    BTA_FS_CO_SESS_ST_ACTIVE,
+    BTA_FS_CO_SESS_ST_SUSPEND,
+    BTA_FS_CO_SESS_ST_RESUMING
+};
+typedef UINT8   tBTA_FS_CO_SESS_ST;
+
+
+
+/* a data type to keep an array of ssn/file offset - the info can be saved to NV */
+typedef struct
+{
+    char        path[BTA_FS_CO_PATH_LEN + 1];   /* the "current path". path[0]==0-> root */
+    char        file[BTA_FS_CO_PATH_LEN + 1];   /* file[0] !=0 on resume -> the previous suspended session had opened files */
+    int         oflags;  /* the flag to open the file */
+    BD_ADDR     bd_addr;
+    UINT8       sess_info[OBX_SESSION_INFO_SIZE];
+    UINT32      offset;         /* last file offset */
+    UINT32      timeout;        /* the timeout value on suspend */
+    time_t      suspend_time;   /* the time of suspend */
+    UINT16      nbytes;         /* number of bytes for last read/write */
+    UINT8       ssn;
+    UINT8       info;           /* info for BTA on the client side */
+    UINT8       app_id;
+    tBTA_FS_CO_SESS_ST  sess_st;
+} tBTA_FS_CO_SESSION;
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+/**************************
+**  Common Functions
+***************************/
+/*******************************************************************************
+**
+** Function         bta_fs_co_init
+**
+** Description      This function is executed as a part of the start up sequence
+**                  to make sure the control block is initialized.
+**
+** Parameters       void.
+**
+** Returns          void
+**
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_init(void);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_open
+**
+** Description      This function is executed by BTA when a file is opened.
+**                  The phone uses this function to open
+**                  a file for reading or writing.
+**
+** Parameters       p_path  - Fully qualified path and file name.
+**                  oflags  - permissions and mode (see constants above)
+**                  size    - size of file to put (0 if unavailable or not applicable)
+**                  evt     - event that must be passed into the call-in function.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+**                  Note: Upon completion of the request, a file descriptor (int),
+**                        if successful, and an error code (tBTA_FS_CO_STATUS)
+**                        are returned in the call-in function, bta_fs_ci_open().
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_open(const char *p_path, int oflags, UINT32 size,
+                           UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_session_info
+**
+** Description      This function is executed by BTA when a reliable session is
+**                  established (p_sess_info != NULL) or ended (p_sess_info == NULL).
+**
+** Parameters       bd_addr     - the peer address
+**                  p_sess_info - the session ID and related information.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_session_info(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
+                                           tBTA_FS_CO_SESS_ST new_st, char *p_path, UINT8 *p_info, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_resume_op
+**
+** Description      This function is executed by BTA when a reliable session is
+**                  resumed and there was an interrupted operation.
+**
+** Parameters       offset  - the session ID and related information.
+**                  evt     - event that must be passed into the call-in function.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_resume_op(UINT32 offset, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_suspend
+**
+** Description      This function is executed by BTA when a reliable session is
+**                  suspended.
+**
+** Parameters       bd_addr - the peer address
+**                  ssn     - the session sequence number.
+**                  info    - the BTA specific information (like last active operation).
+**                  p_offset- the location to receive object offset of the suspended session
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_suspend(BD_ADDR bd_addr, UINT8 *p_sess_info, UINT8 ssn,
+                                      UINT32 *p_timeout, UINT32 *p_offset, UINT8 info, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_resume
+**
+** Description      This function is executed by BTA when resuming a session.
+**                  This is used to retrieve the session ID and related information
+**
+** Parameters       evt     - event that must be passed into the call-in function.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+**                  Note: Upon completion of the request, the related session information,
+**                        if successful, and an error code (tBTA_FS_CO_STATUS)
+**                        are returned in the call-in function, bta_fs_ci_resume().
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_resume(UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_sess_ssn
+**
+** Description      This function is executed by BTA when resuming a session.
+**                  This is used to inform call-out module if the ssn/file offset
+**                  needs to be adjusted.
+**
+** Parameters       ssn     - the session sequence number of the first request
+**                            after resume.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_ssn(int fd, UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_setdir
+**
+** Description      This function is executed by BTA when the server changes the
+**                  local path
+**
+** Parameters       p_path  - the new path.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_setdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_close
+**
+** Description      This function is called by BTA when a connection to a
+**                  client is closed.
+**
+** Parameters       fd      - file descriptor of file to close.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful],
+**                      [BTA_FS_CO_FAIL if failed  ]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_close(int fd, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_read
+**
+** Description      This function is called by BTA to read in data from the
+**                  previously opened file on the phone.
+**
+** Parameters       fd      - file descriptor of file to read from.
+**                  p_buf   - buffer to read the data into.
+**                  nbytes  - number of bytes to read into the buffer.
+**                  evt     - event that must be passed into the call-in function.
+**                  ssn     - session sequence number. Ignored, if bta_fs_co_open
+**							  was not called with BTA_FS_CO_RELIABLE.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+**                  Note: Upon completion of the request, bta_fs_ci_read() is
+**                        called with the buffer of data, along with the number
+**                        of bytes read into the buffer, and a status.  The
+**                        call-in function should only be called when ALL requested
+**                        bytes have been read, the end of file has been detected,
+**                        or an error has occurred.
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_read(int fd, UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
+                           UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_write
+**
+** Description      This function is called by io to send file data to the
+**                  phone.
+**
+** Parameters       fd      - file descriptor of file to write to.
+**                  p_buf   - buffer to read the data from.
+**                  nbytes  - number of bytes to write out to the file.
+**                  evt     - event that must be passed into the call-in function.
+**                  ssn     - session sequence number. Ignored, if bta_fs_co_open
+**							  was not called with BTA_FS_CO_RELIABLE.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+**                  Note: Upon completion of the request, bta_fs_ci_write() is
+**                        called with the file descriptor and the status.  The
+**                        call-in function should only be called when ALL requested
+**                        bytes have been written, or an error has been detected,
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_write(int fd, const UINT8 *p_buf, UINT16 nbytes, UINT16 evt,
+                            UINT8 ssn, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_seek
+**
+** Description      This function is called by io to move the file pointer
+**                  of a previously opened file to the specified location for
+**                  the next read or write operation.
+**
+** Parameters       fd      - file descriptor of file.
+**                  offset  - Number of bytes from origin.
+**                  origin  - Initial position: BTA_FS_SEEK_SET, BTA_FS_SEEK_CUR,
+**                            or BTA_FS_SEEK_END.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_seek (int fd, INT32 offset, INT16 origin, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_access
+**
+** Description      This function is called to check the existence of a file or
+**                  directory.
+**
+** Parameters       p_path   - (input) file or directory to access (fully qualified path).
+**                  mode     - (input) [BTA_FS_ACC_EXIST, BTA_FS_ACC_READ, or BTA_FS_ACC_RDWR]
+**                  p_is_dir - (output) returns TRUE if p_path specifies a directory.
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                   [BTA_FS_CO_OK if it exists]
+**                   [BTA_FS_CO_EACCES if permissions are wrong]
+**                   [BTA_FS_CO_FAIL if it does not exist]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_access(const char *p_path, int mode,
+                                          BOOLEAN *p_is_dir, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_mkdir
+**
+** Description      This function is called to create a directory with
+**                  the pathname given by path. The pathname is a null terminated
+**                  string. All components of the path must already exist.
+**
+** Parameters       p_path   - (input) name of directory to create (fully qualified path).
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                  [BTA_FS_CO_OK if successful]
+**                  [BTA_FS_CO_FAIL if unsuccessful]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_mkdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_rmdir
+**
+** Description      This function is called to remove a directory whose
+**                  name is given by path. The directory must be empty.
+**
+** Parameters       p_path   - (input) name of directory to remove (fully qualified path).
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful]
+**                      [BTA_FS_CO_EACCES if read-only]
+**                      [BTA_FS_CO_ENOTEMPTY if directory is not empty]
+**                      [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_rmdir(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_unlink
+**
+** Description      This function is called by to remove a file whose name
+**                  is given by p_path.
+**
+** Parameters       p_path   - (input) name of file to remove (fully qualified path).
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful]
+**                      [BTA_FS_CO_EACCES if read-only]
+**                      [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_STATUS bta_fs_co_unlink(const char *p_path, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_getdirentry
+**
+** Description      This function is called to retrieve a directory entry for the
+**                  specified path.  The first/next directory should be filled
+**                  into the location specified by p_entry.
+**
+** Parameters       p_path      - directory to search (Fully qualified path)
+**                  first_item  - TRUE if first search, FALSE if next search
+**                                      (p_cur contains previous)
+**                  p_entry (input/output) - Points to last entry data (valid when
+**                                           first_item is FALSE)
+**                  evt     - event that must be passed into the call-in function.
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+**                  Note: Upon completion of the request, the status is passed
+**                        in the bta_fs_ci_direntry() call-in function.
+**                        BTA_FS_CO_OK is returned when p_entry is valid,
+**                        BTA_FS_CO_EODIR is returned when no more entries [finished]
+**                        BTA_FS_CO_FAIL is returned if an error occurred
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_getdirentry(const char *p_path, BOOLEAN first_item,
+                                   tBTA_FS_DIRENTRY *p_entry, UINT16 evt,
+                                   UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_copy
+**
+** Description      This function is called to copy a file/directory whose
+**                  name is given by p_src_path to p_dest_path.
+**
+** Parameters       p_src_path  - (input) name of file/directory to be copied (fully qualified path).
+**                  p_dest_path - (input) new name of file/directory(fully qualified path).
+**                  p_perms     - the permission of the new object.
+**                  evt     - event that must be passed into the call-in function.
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful]
+**                      [BTA_FS_CO_EIS_DIR if p_src_path is a folder]
+**                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+**                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
+**                      [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_copy(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_rename
+**
+** Description      This function is called to move a file/directory whose
+**                  name is given by p_src_path to p_dest_path.
+**
+** Parameters       p_src_path  - (input) name of file/directory to be moved (fully qualified path).
+**                  p_dest_path - (input) new name of file/directory(fully qualified path).
+**                  p_perms     - the permission of the new object.
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful]
+**                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+**                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
+**                      [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_rename(const char *p_src_path, const char *p_dest_path, UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_set_perms
+**
+** Description      This function is called to set the permission a file/directory
+**                  with name as p_src_path.
+**
+** Parameters       p_src_path  - (input) name of file/directory to set permission (fully qualified path).
+**                  p_perms     - the permission .
+**                  app_id   - (input) application ID specified in the enable functions.
+**                                     It can be used to identify which profile is the caller
+**                                     of the call-out function.
+**
+** Returns          (tBTA_FS_CO_STATUS) status of the call.
+**                      [BTA_FS_CO_OK if successful]
+**                      [BTA_FS_CO_EACCES if p_dest_path already exists or could not be created (invalid path);
+**                                        or p_src_path is a directory and p_dest_path specifies a different path. ]
+**                      [BTA_FS_CO_FAIL otherwise]
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_set_perms(const char *p_src_path,  UINT8 *p_perms, UINT16 evt, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_sess_fopen
+**
+** Description      This function is called by bta_fs_co_open to keep track of
+**                  the opened file (for reliable session suspend/resume.)
+**
+** Parameters       p_path  - Fully qualified path and file name.
+**                  oflags  - permissions and mode (see constants above)
+**                  app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_fopen(const char *p_path, int oflags, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_sess_fclose
+**
+** Description      This function is called by bta_fs_co_close
+**
+** Parameters       app_id  - application ID specified in the enable functions.
+**                            It can be used to identify which profile is the caller
+**                            of the call-out function.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_fclose(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_sess_offset
+**
+** Description      This function is called by bta_fs_co_write to keep track of
+**                  the last file offset (Only the receiving side needs to keep
+**                  track of the file offset)
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_sess_offset(UINT8 ssn, INT32 pos, UINT16 nbytes, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_suspended_addr
+**
+** Description      find the peer address of the suspended session control block
+**                  for the given an app_id.
+**
+** Returns          the control block found.
+**
+*******************************************************************************/
+BTA_API extern UINT8 *bta_fs_co_suspended_addr(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_num_suspended_session
+**
+** Description      find the number of suspended session control blocks for the
+**                  given an app_id.
+**
+** Returns          the number of control blocks found.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_fs_co_num_suspended_session(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_get_active_session
+**
+** Description      find the active session control block for the given an app_id.
+**
+** Returns          the control block found.
+**
+*******************************************************************************/
+BTA_API extern tBTA_FS_CO_SESSION *bta_fs_co_get_active_session(UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_fs_co_init_db
+**
+** Description      Initialize the session control blocks for platform.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_fs_co_init_db (tBTA_FS_CO_SESSION *p_first);
+
+/*******************************************************************************
+**
+** Function         bta_fs_convert_oflags
+**
+** Description      This function converts the open flags from BTA into MFS.
+**
+** Returns          BTA FS status value.
+**
+*******************************************************************************/
+BTA_API extern int bta_fs_convert_bta_oflags(int bta_oflags);
+
+#endif /* BTA_FS_CO_H */
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
new file mode 100644
index 0000000..0404847
--- /dev/null
+++ b/bta/include/bta_gatt_api.h
@@ -0,0 +1,1219 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for BTA GATT.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATT_API_H
+#define BTA_GATT_API_H
+
+#include "bta_api.h"
+#include "gatt_api.h"
+
+#ifndef     BTA_GATT_INCLUDED
+#define     BTA_GATT_INCLUDED     FALSE
+#endif
+
+
+#if ((BLE_INCLUDED == FALSE) && (BTA_GATT_INCLUDED == TRUE))
+#undef BTA_GATT_INCLUDED
+#define BTA_GATT_INCLUDED        FALSE
+#endif
+
+
+#ifndef     BTA_GATT_DEBUG
+#define     BTA_GATT_DEBUG       FALSE
+#endif
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/**************************
+**  Common Definitions
+***************************/
+/* GATT ID */
+typedef struct
+{
+    tBT_UUID    uuid;           /* uuid of the attribute */
+    UINT8       inst_id;        /* instance ID */
+} tBTA_GATT_ID;
+
+/* Success code and error codes */
+#define  BTA_GATT_OK                        GATT_SUCCESS
+#define  BTA_GATT_INVALID_HANDLE            GATT_INVALID_HANDLE                /* 0x0001 */
+#define  BTA_GATT_READ_NOT_PERMIT           GATT_READ_NOT_PERMIT               /* 0x0002 */
+#define  BTA_GATT_WRITE_NOT_PERMIT          GATT_WRITE_NOT_PERMIT              /* 0x0003 */
+#define  BTA_GATT_INVALID_PDU               GATT_INVALID_PDU                   /* 0x0004 */
+#define  BTA_GATT_INSUF_AUTHENTICATION      GATT_INSUF_AUTHENTICATION          /* 0x0005 */
+#define  BTA_GATT_REQ_NOT_SUPPORTED         GATT_REQ_NOT_SUPPORTED             /* 0x0006 */
+#define  BTA_GATT_INVALID_OFFSET            GATT_INVALID_OFFSET                /* 0x0007 */
+#define  BTA_GATT_INSUF_AUTHORIZATION       GATT_INSUF_AUTHORIZATION           /* 0x0008 */
+#define  BTA_GATT_PREPARE_Q_FULL            GATT_PREPARE_Q_FULL                /* 0x0009 */
+#define  BTA_GATT_NOT_FOUND                 GATT_NOT_FOUND                     /* 0x000a */
+#define  BTA_GATT_NOT_LONG                  GATT_NOT_LONG                      /* 0x000b */
+#define  BTA_GATT_INSUF_KEY_SIZE            GATT_INSUF_KEY_SIZE                /* 0x000c */
+#define  BTA_GATT_INVALID_ATTR_LEN          GATT_INVALID_ATTR_LEN              /* 0x000d */
+#define  BTA_GATT_ERR_UNLIKELY              GATT_ERR_UNLIKELY                  /* 0x000e */
+#define  BTA_GATT_INSUF_ENCRYPTION          GATT_INSUF_ENCRYPTION              /* 0x000f */
+#define  BTA_GATT_UNSUPPORT_GRP_TYPE        GATT_UNSUPPORT_GRP_TYPE            /* 0x0010 */
+#define  BTA_GATT_INSUF_RESOURCE            GATT_INSUF_RESOURCE                /* 0x0011 */
+
+
+#define  BTA_GATT_ILLEGAL_PARAMETER         GATT_ILLEGAL_PARAMETER             /* 0x0087 */
+#define  BTA_GATT_NO_RESOURCES              GATT_NO_RESOURCES                  /* 0x0080 */
+#define  BTA_GATT_INTERNAL_ERROR            GATT_INTERNAL_ERROR                /* 0x0081 */
+#define  BTA_GATT_WRONG_STATE               GATT_WRONG_STATE                   /* 0x0082 */
+#define  BTA_GATT_DB_FULL                   GATT_DB_FULL                       /* 0x0083 */
+#define  BTA_GATT_BUSY                      GATT_BUSY                          /* 0x0084 */
+#define  BTA_GATT_ERROR                     GATT_ERROR                         /* 0x0085 */
+#define  BTA_GATT_CMD_STARTED               GATT_CMD_STARTED                   /* 0x0086 */
+#define  BTA_GATT_PENDING                   GATT_PENDING                       /* 0x0088 */
+#define  BTA_GATT_AUTH_FAIL                 GATT_AUTH_FAIL                     /* 0x0089 */
+#define  BTA_GATT_MORE                      GATT_MORE                          /* 0x008a */
+#define  BTA_GATT_INVALID_CFG               GATT_INVALID_CFG                   /* 0x008b */
+#define  BTA_GATT_DUP_REG                   0x008c
+#define  BTA_GATT_ALREADY_OPEN              0x008d                              /* 0x008d */
+typedef UINT8 tBTA_GATT_STATUS;
+
+#define BTA_GATT_INVALID_CONN_ID   GATT_INVALID_CONN_ID
+
+
+/* Client callback function events */
+#define BTA_GATTC_REG_EVT           0   /* GATT client is registered. */
+#define BTA_GATTC_DEREG_EVT         1   /* GATT client deregistered event */
+#define BTA_GATTC_OPEN_EVT          2   /* GATTC open request status  event */
+#define BTA_GATTC_READ_CHAR_EVT     3   /* GATT read characteristic event */
+#define BTA_GATTC_WRITE_CHAR_EVT    4   /* GATT write characteristic or char descriptor event */
+#define BTA_GATTC_CLOSE_EVT         5   /* GATTC  close request status event */
+#define BTA_GATTC_SEARCH_CMPL_EVT   6   /* GATT discovery complete event */
+#define BTA_GATTC_SEARCH_RES_EVT    7   /* GATT discovery result event */
+#define BTA_GATTC_READ_DESCR_EVT    8   /* GATT read characterisitc descriptor event */
+#define BTA_GATTC_WRITE_DESCR_EVT   9   /* GATT write characteristic descriptor event */
+#define BTA_GATTC_NOTIF_EVT         10  /* GATT attribute notification event */
+#define BTA_GATTC_PREP_WRITE_EVT    11  /* GATT prepare write  event */
+#define BTA_GATTC_EXEC_EVT          12  /* execute write complete event */
+#define BTA_GATTC_ACL_EVT           13  /* ACL up event */
+#define BTA_GATTC_CANCEL_OPEN_EVT   14   /*  cancel open event */
+#define BTA_GATTC_SRVC_CHG_EVT      15  /* service change event */
+typedef UINT8 tBTA_GATTC_EVT;
+
+typedef tGATT_IF tBTA_GATTC_IF;
+
+typedef struct
+{
+    UINT16              unit;       /* as UUIUD defined by SIG */
+    UINT16              descr;       /* as UUID as defined by SIG */
+    tGATT_FORMAT        format;
+    INT8                exp;
+    UINT8               name_spc;   /* The name space of the description */
+}tBTA_GATT_CHAR_PRES;
+
+#define BTA_GATT_CLT_CONFIG_NONE               GATT_CLT_CONFIG_NONE         /* 0x0000    */
+#define BTA_GATT_CLT_CONFIG_NOTIFICATION       GATT_CLT_CONFIG_NOTIFICATION /* 0x0001 */
+#define BTA_GATT_CLT_CONFIG_INDICATION         GATT_CLT_CONFIG_INDICATION   /* 0x0002 */
+typedef UINT16  tBTA_GATT_CLT_CHAR_CONFIG;
+
+/* characteristic descriptor: server configuration value
+*/
+#define BTA_GATT_SVR_CONFIG_NONE            GATT_SVR_CONFIG_NONE            /* 0x0000 */
+#define BTA_GATT_SVR_CONFIG_BROADCAST       GATT_SVR_CONFIG_BROADCAST       /*  0x0001 */
+typedef UINT16  tBTA_GATT_SVR_CHAR_CONFIG;
+
+/* Characteristic Aggregate Format attribute value
+*/
+#define BTA_GATT_AGGR_HANDLE_NUM_MAX        10
+typedef struct
+{
+    UINT8                   num_handle;
+    UINT16                  handle_list[BTA_GATT_AGGR_HANDLE_NUM_MAX];
+} tBTA_GATT_CHAR_AGGRE;
+typedef tGATT_VALID_RANGE           tBTA_GATT_VALID_RANGE;
+
+typedef struct
+{
+    UINT16  len;
+    UINT8   *p_value;
+}tBTA_GATT_UNFMT;
+
+#define BTA_GATT_MAX_ATTR_LEN       GATT_MAX_ATTR_LEN
+
+#define BTA_GATTC_TYPE_WRITE             GATT_WRITE
+#define BTA_GATTC_TYPE_WRITE_NO_RSP      GATT_WRITE_NO_RSP
+typedef UINT8 tBTA_GATTC_WRITE_TYPE;
+
+#define BTA_GATT_CONN_UNKNOWN                   0
+#define BTA_GATT_CONN_NO_RESOURCES              GATT_CONN_NO_RESOURCES        /* connection fail for l2cap resource failure */
+#define BTA_GATT_CONN_TIMEOUT                   GATT_CONN_TIMEOUT             /* 0x08 connection timeout  */
+#define BTA_GATT_CONN_TERMINATE_PEER_USER       GATT_CONN_TERMINATE_PEER_USER /* 0x13 connection terminate by peer user  */
+#define BTA_GATT_CONN_TERMINATE_LOCAL_HOST      GATT_CONN_TERMINATE_LOCAL_HOST/* 0x16 connectionterminated by local host  */
+#define BTA_GATT_CONN_FAIL_ESTABLISH            GATT_CONN_FAIL_ESTABLISH      /* 0x03E connection fail to establish  */
+#define BTA_GATT_CONN_LMP_TIMEOUT               GATT_CONN_LMP_TIMEOUT          /* 0x22 connection fail for LMP response tout */
+#define BTA_GATT_CONN_CANCEL                    GATT_CONN_CANCEL               /* 0x0100 L2CAP connection cancelled  */
+#define BTA_GATT_CONN_NONE                      0x0101                          /* 0x0101 no connection to cancel  */
+typedef UINT16 tBTA_GATT_REASON;
+
+typedef struct
+{
+    tBTA_GATT_ID        id;
+    BOOLEAN             is_primary;
+}tBTA_GATT_SRVC_ID;
+
+typedef struct
+{
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_ID            char_id;
+}tBTA_GATTC_CHAR_ID;
+
+typedef struct
+{
+    tBTA_GATTC_CHAR_ID      char_id;
+    tBT_UUID                descr_type;
+}tBTA_GATTC_CHAR_DESCR_ID;
+
+typedef struct
+{
+    tBTA_GATT_SRVC_ID       srvc_id;
+    tBTA_GATT_SRVC_ID       incl_svc_id;
+}tBTA_GATTC_INCL_SVC_ID;
+
+#define     BTA_GATT_TYPE_CHAR          0
+#define     BTA_GATT_TYPE_CHAR_DESCR    1
+typedef UINT8 tBTA_GATT_ID_TYPE;
+
+typedef struct
+{
+    tBTA_GATT_ID_TYPE               id_type;
+    union
+    {
+        tBTA_GATTC_CHAR_ID         char_id;
+        tBTA_GATTC_CHAR_DESCR_ID   char_descr_id;
+
+    }                       id_value;
+}tBTA_GATTC_ATTR_ID;
+
+#define BTA_GATTC_MULTI_MAX    GATT_MAX_READ_MULTI_HANDLES
+
+typedef struct
+{
+    UINT8                       num_attr;
+    tBTA_GATTC_ATTR_ID          id_list[BTA_GATTC_MULTI_MAX];
+
+}tBTA_GATTC_MULTI;
+
+#define BTA_GATT_AUTH_REQ_NONE           GATT_AUTH_REQ_NONE
+#define BTA_GATT_AUTH_REQ_NO_MITM        GATT_AUTH_REQ_NO_MITM            /* unauthenticated encryption */
+#define BTA_GATT_AUTH_REQ_MITM           GATT_AUTH_REQ_MITM               /* authenticated encryption */
+#define BTA_GATT_AUTH_REQ_SIGNED_NO_MITM GATT_AUTH_REQ_SIGNED_NO_MITM
+#define BTA_GATT_AUTH_REQ_SIGNED_MITM    GATT_AUTH_REQ_SIGNED_MITM
+
+typedef tGATT_AUTH_REQ tBTA_GATT_AUTH_REQ;
+
+enum
+{
+    BTA_GATTC_ATTR_TYPE_INCL_SRVC,
+    BTA_GATTC_ATTR_TYPE_CHAR,
+    BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
+    BTA_GATTC_ATTR_TYPE_SRVC
+};
+typedef UINT8 tBTA_GATTC_ATTR_TYPE;
+
+
+typedef struct
+{
+    tBT_UUID    uuid;
+    UINT16      s_handle;
+    UINT16      e_handle;   /* used for service only */
+    UINT8       attr_type;
+    UINT8       id;
+    UINT8       prop;       /* used when attribute type is characteristic */
+    BOOLEAN     is_primary; /* used when attribute type is service */
+}tBTA_GATTC_NV_ATTR;
+
+/* callback data structure */
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    tBTA_GATTC_IF       client_if;
+// btla-specific ++
+    tBT_UUID            app_uuid;
+// btla-specific --
+}tBTA_GATTC_REG;
+
+typedef struct
+{
+    UINT8                       num_pres_fmt;   /* number of presentation format aggregated*/
+    tBTA_GATTC_CHAR_DESCR_ID    pre_format[BTA_GATTC_MULTI_MAX];
+}tBTA_GATT_CHAR_AGGRE_VALUE;
+
+typedef union
+{
+    tBTA_GATT_CHAR_AGGRE_VALUE      aggre_value;
+    tBTA_GATT_UNFMT                 unformat;
+
+}tBTA_GATT_READ_VAL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATT_SRVC_ID   srvc_id;
+    tBTA_GATT_ID        char_id;
+    tBT_UUID            descr_type;
+    tBTA_GATT_READ_VAL  *p_value;
+}tBTA_GATTC_READ;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+    tBTA_GATT_SRVC_ID   srvc_id;
+    tBTA_GATT_ID        char_id;
+    tBT_UUID            descr_type;
+}tBTA_GATTC_WRITE;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTC_EXEC_CMPL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTC_SEARCH_CMPL;
+
+typedef struct
+{
+    UINT16              conn_id;
+    tBTA_GATT_SRVC_ID   service_uuid;
+}tBTA_GATTC_SRVC_RES;
+
+
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    UINT16              conn_id;
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+}tBTA_GATTC_OPEN;
+
+typedef struct
+{
+    tBTA_GATT_STATUS    status;
+    UINT16              conn_id;
+    tBTA_GATTC_IF       client_if;
+    BD_ADDR             remote_bda;
+    tBTA_GATT_REASON    reason;         /* disconnect reason code, not useful when connect event is reported */
+}tBTA_GATTC_CLOSE;
+
+typedef struct
+{
+    UINT16              conn_id;
+    BD_ADDR             bda;
+    tBTA_GATTC_CHAR_ID  char_id;
+    tBT_UUID            descr_type;
+    UINT16              len;
+    UINT8               value[BTA_GATT_MAX_ATTR_LEN];
+    BOOLEAN             is_notify;
+}tBTA_GATTC_NOTIFY;
+
+// btla-specific ++
+typedef struct
+{
+    tBTA_GATT_STATUS        status;
+    tBTA_GATTC_IF           client_if;
+    UINT16                  conn_id;
+    BD_ADDR                 remote_bda;
+}tBTA_GATTC_OPEN_CLOSE;
+// btla-specific --
+
+typedef union
+{
+    tBTA_GATT_STATUS        status;
+
+    tBTA_GATTC_SEARCH_CMPL  search_cmpl;          /* discovery complete */
+    tBTA_GATTC_SRVC_RES     srvc_res;          /* discovery result */
+    tBTA_GATTC_REG          reg_oper;              /* registration data */
+    tBTA_GATTC_OPEN         open;
+    tBTA_GATTC_CLOSE        close;
+    tBTA_GATTC_READ         read;             /* read attribute/descriptor data */
+    tBTA_GATTC_WRITE        write;            /* write complete data */
+    tBTA_GATTC_EXEC_CMPL    exec_cmpl;       /*  execute complete */
+    tBTA_GATTC_NOTIFY       notify;           /* notification/indication event data */
+    BD_ADDR                 remote_bda;     /* service change event */
+} tBTA_GATTC;
+
+/* Client callback function */
+typedef void (tBTA_GATTC_CBACK)(tBTA_GATTC_EVT event, tBTA_GATTC *p_data);
+
+
+/* GATT Server Data Structure */
+/* Server callback function events */
+#define BTA_GATTS_REG_EVT                               0
+#define BTA_GATTS_READ_EVT                              GATTS_REQ_TYPE_READ         /* 1 */
+#define BTA_GATTS_WRITE_EVT                             GATTS_REQ_TYPE_WRITE        /* 2 */
+#define BTA_GATTS_EXEC_WRITE_EVT                        GATTS_REQ_TYPE_WRITE_EXEC   /* 3 */
+#define BTA_GATTS_MTU_EVT                               GATTS_REQ_TYPE_MTU          /* 4 */
+#define BTA_GATTS_CONF_EVT                              GATTS_REQ_TYPE_CONF         /* 5 */
+#define BTA_GATTS_DEREG_EVT                             6
+#define BTA_GATTS_CREATE_EVT                            7
+#define BTA_GATTS_ADD_INCL_SRVC_EVT                     8
+#define BTA_GATTS_ADD_CHAR_EVT                          9
+#define BTA_GATTS_ADD_CHAR_DESCR_EVT                    10
+#define BTA_GATTS_DELELTE_EVT                           11
+#define BTA_GATTS_START_EVT                             12
+#define BTA_GATTS_STOP_EVT                              13
+#define BTA_GATTS_CONNECT_EVT                           14
+#define BTA_GATTS_DISCONNECT_EVT                        15
+#define BTA_GATTS_OPEN_EVT                              16
+#define BTA_GATTS_CANCEL_OPEN_EVT                       17
+#define BTA_GATTS_CLOSE_EVT                             18
+
+typedef UINT8  tBTA_GATTS_EVT;
+typedef tGATT_IF tBTA_GATTS_IF;
+
+/* Attribute permissions
+*/
+#define BTA_GATT_PERM_READ              GATT_PERM_READ              /* bit 0 -  0x0001 */
+#define BTA_GATT_PERM_READ_ENCRYPTED    GATT_PERM_READ_ENCRYPTED    /* bit 1 -  0x0002 */
+#define BTA_GATT_PERM_READ_ENC_MITM     GATT_PERM_READ_ENC_MITM     /* bit 2 -  0x0004 */
+#define BTA_GATT_PERM_WRITE             GATT_PERM_WRITE             /* bit 4 -  0x0010 */
+#define BTA_GATT_PERM_WRITE_ENCRYPTED   GATT_PERM_WRITE_ENCRYPTED   /* bit 5 -  0x0020 */
+#define BTA_GATT_PERM_WRITE_ENC_MITM    GATT_PERM_WRITE_ENC_MITM    /* bit 6 -  0x0040 */
+#define BTA_GATT_PERM_WRITE_SIGNED      GATT_PERM_WRITE_SIGNED      /* bit 7 -  0x0080 */
+#define BTA_GATT_PERM_WRITE_SIGNED_MITM GATT_PERM_WRITE_SIGNED_MITM /* bit 8 -  0x0100 */
+typedef UINT16 tBTA_GATT_PERM;
+
+#define BTA_GATTS_INVALID_APP   0xff
+
+#define BTA_GATTS_INVALID_IF    0
+
+/* definition of characteristic properties */
+#define BTA_GATT_CHAR_PROP_BIT_BROADCAST    GATT_CHAR_PROP_BIT_BROADCAST    /* 0x01 */
+#define BTA_GATT_CHAR_PROP_BIT_READ         GATT_CHAR_PROP_BIT_READ    /* 0x02 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE_NR     GATT_CHAR_PROP_BIT_WRITE_NR    /* 0x04 */
+#define BTA_GATT_CHAR_PROP_BIT_WRITE        GATT_CHAR_PROP_BIT_WRITE       /* 0x08 */
+#define BTA_GATT_CHAR_PROP_BIT_NOTIFY       GATT_CHAR_PROP_BIT_NOTIFY      /* 0x10 */
+#define BTA_GATT_CHAR_PROP_BIT_INDICATE     GATT_CHAR_PROP_BIT_INDICATE    /* 0x20 */
+#define BTA_GATT_CHAR_PROP_BIT_AUTH         GATT_CHAR_PROP_BIT_AUTH        /* 0x40 */
+#define BTA_GATT_CHAR_PROP_BIT_EXT_PROP     GATT_CHAR_PROP_BIT_EXT_PROP    /* 0x80 */
+typedef UINT8 tBTA_GATT_CHAR_PROP;
+
+#ifndef BTA_GATTC_CHAR_DESCR_MAX
+#define BTA_GATTC_CHAR_DESCR_MAX        7
+#endif
+
+/***********************  NV callback Data Definitions   **********************
+*/
+typedef struct
+{
+    tBT_UUID app_uuid128;
+    tBT_UUID svc_uuid;
+    UINT16   svc_inst;
+    UINT16   s_handle;
+    UINT16   e_handle;
+    BOOLEAN  is_primary;      /* primary service or secondary */
+} tBTA_GATTS_HNDL_RANGE;
+
+#define BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT       GATTS_SRV_CHG_CMD_ADD_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT    GATTS_SRV_CHG_CMD_UPDATE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT    GATTS_SRV_CHG_CMD_REMOVE_CLIENT
+#define BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS  GATTS_SRV_CHG_CMD_READ_NUM_CLENTS
+#define BTA_GATTS_SRV_CHG_CMD_READ_CLENT       GATTS_SRV_CHG_CMD_READ_CLENT
+typedef tGATTS_SRV_CHG_CMD tBTA_GATTS_SRV_CHG_CMD;
+
+typedef tGATTS_SRV_CHG     tBTA_GATTS_SRV_CHG;
+typedef tGATTS_SRV_CHG_REQ tBTA_GATTS_SRV_CHG_REQ;
+typedef tGATTS_SRV_CHG_RSP tBTA_GATTS_SRV_CHG_RSP;
+
+enum
+{
+    BTA_GATT_TRANSPORT_LE,
+    BTA_GATT_TRANSPORT_BR_EDR,
+    BTA_GATT_TRANSPORT_LE_BR_EDR
+};
+typedef UINT8 tBTA_GATT_TRANSPORT;
+
+/* attribute value */
+typedef tGATT_VALUE tBTA_GATT_VALUE;
+
+/* attribute response data */
+typedef tGATTS_RSP tBTA_GATTS_RSP;
+
+/* attribute request data from the client */
+#define BTA_GATT_PREP_WRITE_CANCEL   0x00
+#define BTA_GATT_PREP_WRITE_EXEC     0x01
+typedef tGATT_EXEC_FLAG tBTA_GATT_EXEC_FLAG;
+
+/* read request always based on UUID */
+typedef tGATT_READ_REQ tTA_GBATT_READ_REQ;
+
+/* write request data */
+typedef tGATT_WRITE_REQ tBTA_GATT_WRITE_REQ;
+
+/* callback data for server access request from client */
+typedef tGATTS_DATA tBTA_GATTS_REQ_DATA;
+
+typedef struct
+{
+    BD_ADDR             remote_bda;
+    UINT32              trans_id;
+    UINT16              conn_id;
+    tBTA_GATTS_REQ_DATA *p_data;
+}tBTA_GATTS_REQ;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    tBTA_GATT_STATUS    status;
+// btla-specific ++
+    tBT_UUID            uuid;
+// btla-specific --
+}tBTA_GATTS_REG_OPER;
+
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+// btla-specific ++
+    UINT16              svc_instance;
+    BOOLEAN             is_primary;
+    tBTA_GATT_STATUS    status;
+    tBT_UUID            uuid;
+// btla-specific --
+}tBTA_GATTS_CREATE;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+    UINT16              attr_id;
+    tBTA_GATT_STATUS    status;
+// btla-specific ++
+    tBT_UUID            char_uuid;
+// btla-specific --
+}tBTA_GATTS_ADD_RESULT;
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    UINT16              service_id;
+    tBTA_GATT_STATUS    status;
+}tBTA_GATTS_SRVC_OPER;
+
+
+typedef struct
+{
+    tBTA_GATTS_IF       server_if;
+    BD_ADDR             remote_bda;
+    UINT16              conn_id;
+    tBTA_GATT_REASON    reason; /* report disconnect reason */
+}tBTA_GATTS_CONN;
+
+/* GATTS callback data */
+typedef union
+{
+    tBTA_GATTS_REG_OPER     reg_oper;
+    tBTA_GATTS_CREATE       create;
+    tBTA_GATTS_SRVC_OPER    srvc_oper;
+    tBTA_GATT_STATUS        status; /*  BTA_GATTS_CONF_EVT */
+    tBTA_GATTS_ADD_RESULT   add_result;  /* add included service: BTA_GATTS_ADD_INCL_SRVC_EVT
+                                           add char : BTA_GATTS_ADD_CHAR_EVT
+                                           add char descriptor: BTA_GATTS_ADD_CHAR_DESCR_EVT */
+    tBTA_GATTS_REQ          req_data;
+    tBTA_GATTS_CONN         conn;       /* BTA_GATTS_CONN_EVT */
+
+}tBTA_GATTS;
+
+
+/* Server callback function */
+typedef void (tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event,  tBTA_GATTS *p_data);
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+**  Client Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTC module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_client_cb - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTC_CBACK *p_client_cb);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_AppDeregister
+**
+** Description      This function is called to deregister an application
+**                  from BTA GATTC module.
+**
+** Parameters       client_if - client interface identifier.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_AppDeregister (tBTA_GATTC_IF client_if);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Open
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Open(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_CancelOpen
+**
+** Description      Open a direct connection or add a background auto connection
+**                  bd address
+**
+** Parameters       client_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_CancelOpen(tBTA_GATTC_IF client_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Close
+**
+** Description      Close a connection to a GATT server.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Close(UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ServiceSearchRequest
+**
+** Description      This function is called to request a GATT service discovery
+**                    on a GATT server. This function report service search result
+**                  by a callback event, and followed by a service search complete
+**                  event.
+**
+** Parameters       conn_id: connection ID.
+**                  p_srvc_uuid: a UUID of the service application is interested in.
+**                              If Null, discover for all services.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ServiceSearchRequest(UINT16 conn_id, tBT_UUID *p_srvc_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstChar
+**
+** Description      This function is called to find the first charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the characteristic is belonged to.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter to carry the characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstChar (UINT16              conn_id,
+                                                         tBTA_GATT_SRVC_ID   *p_srvc_id,
+                                                         tBT_UUID            *p_char_uuid_cond,
+                                                         tBTA_GATTC_CHAR_ID  *p_char_result,
+                                                         tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextChar
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_char_id: start the characteristic search from the next record
+**                           after the one identified by char_id.
+**                  p_char_uuid_cond: Characteristic UUID, if NULL find the first available
+**                               characteristic.
+**                  p_char_result: output parameter which will store the GATT
+**                                  characteristic ID.
+**                  p_property: output parameter, characteristic property.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetNextChar (UINT16 conn_id,
+                                                        tBTA_GATTC_CHAR_ID  *p_start_char_id,
+                                                        tBT_UUID            *p_char_uuid_cond,
+                                                        tBTA_GATTC_CHAR_ID  *p_char_result,
+                                                        tBTA_GATT_CHAR_PROP *p_property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstCharDescr
+**
+** Description      This function is called to find the first charatceristic descriptor of the
+**                  charatceristic on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_char_id: the characteristic ID of which the descriptor is belonged to.
+**                  p_descr_uuid_cond: Characteristic Descr UUID, if NULL find the first available
+**                               characteristic.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstCharDescr (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id,
+                                                tBT_UUID *p_descr_uuid_cond,
+                                                tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextCharDescr
+**
+** Description      This function is called to find the next charatceristic of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_descr_id: start the characteristic search from the next record
+**                           after the one identified by p_start_descr_id.
+**                  p_descr_uuid_cond: Characteristic descriptor UUID, if NULL find
+**                               the first available characteristic descriptor.
+**                  p_descr_result: output parameter which will store the GATT
+**                                  characteristic descriptor ID.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetNextCharDescr (UINT16 conn_id,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_start_descr_id,
+                                             tBT_UUID           *p_descr_uuid_cond,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_descr_result);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetFirstIncludedService
+**
+** Description      This function is called to find the first included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_srvc_id: the service ID of which the included service is belonged to.
+**                  p_uuid_cond: include service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetFirstIncludedService(UINT16 conn_id,
+                                                                   tBTA_GATT_SRVC_ID    *p_srvc_id,
+                                                                   tBT_UUID               *p_uuid_cond,
+                                                                   tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_GetNextIncludedService
+**
+** Description      This function is called to find the next included service of the
+**                  service on the given server.
+**
+** Parameters       conn_id: connection ID which identify the server.
+**                  p_start_id: start the search from the next record
+**                                  after the one identified by p_start_id.
+**                  p_uuid_cond: Included service UUID, if NULL find the first available
+**                               included service.
+**                  p_result: output parameter which will store the GATT ID
+**                              of the included service found.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS  BTA_GATTC_GetNextIncludedService(UINT16 conn_id,
+                                                                  tBTA_GATTC_INCL_SVC_ID *p_start_id,
+                                                                  tBT_UUID             *p_uuid_cond,
+                                                                  tBTA_GATTC_INCL_SVC_ID *p_result);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharacteristic
+**
+** Description      This function is called to read a service's characteristics of
+**                    the given characteritisc ID.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_char_id - characteritic ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadCharacteristic (UINT16 conn_id,
+                                                  tBTA_GATTC_CHAR_ID *p_char_id,
+                                                  tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadCharDescr
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_descr_id - characteritic descriptor ID to read.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadCharDescr (UINT16 conn_id,
+                                             tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                                             tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharValue
+**
+** Description      This function is called to write characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to write.
+**                    write_type - type of write.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_WriteCharValue (UINT16 conn_id,
+                                              tBTA_GATTC_CHAR_ID *p_char_id,
+                                              tBTA_GATTC_WRITE_TYPE  write_type,
+                                              UINT16 len,
+                                              UINT8 *p_value,
+                                              tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_WriteCharDescr
+**
+** Description      This function is called to write characteristic descriptor value.
+**
+** Parameters       conn_id - connection ID
+**                    p_char_descr_id - characteristic descriptor ID to write.
+**                    write_type - type of write.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_WriteCharDescr (UINT16 conn_id,
+                                              tBTA_GATTC_CHAR_DESCR_ID *p_char_descr_id,
+                                              tBTA_GATTC_WRITE_TYPE  write_type,
+                                              tBTA_GATT_UNFMT   *p_data,
+                                              tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_SendIndConfirm
+**
+** Description      This function is called to send handle value confirmation.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - characteristic ID to confrim.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_SendIndConfirm (UINT16 conn_id, tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_RegisterForNotifications
+**
+** Description      This function is called to register for notification of a service.
+**
+** Parameters       client_if   - client interface.
+**                  remote_bda  - target GATT server.
+**                  p_char_id   - pointer to GATT characteristic ID.
+**
+** Returns          OK if registration succeed, otherwise failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_RegisterForNotifications (tBTA_GATTC_IF      client_if,
+                                                                    BD_ADDR            remote_bda,
+                                                                    tBTA_GATTC_CHAR_ID *p_char_id);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_DeregisterForNotifications
+**
+** Description      This function is called to de-register for notification of a servbice.
+**
+** Parameters       client_if - client interface.
+**                  remote_bda - target GATT server.
+**                  p_char_id - pointer to a GATT characteristic ID.
+**
+** Returns          OK if deregistration succeed, otherwise failed.
+**
+*******************************************************************************/
+BTA_API extern tBTA_GATT_STATUS BTA_GATTC_DeregisterForNotifications (tBTA_GATTC_IF      client_if,
+                                                                      BD_ADDR            remote_bda,
+                                                                      tBTA_GATTC_CHAR_ID *p_char_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_PrepareWrite
+**
+** Description      This function is called to prepare write a characteristic value.
+**
+** Parameters       conn_id - connection ID.
+**                    p_char_id - GATT characteritic ID of the service.
+**                  offset - offset of the write value.
+**                  len: length of the data to be written.
+**                  p_value - the value to be written.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_PrepareWrite  (UINT16 conn_id,
+                                             tBTA_GATTC_CHAR_ID *p_char_id,
+                                             UINT16 offset,
+                                             UINT16 len,
+                                             UINT8 *p_value,
+                                             tBTA_GATT_AUTH_REQ auth_req);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ExecuteWrite
+**
+** Description      This function is called to execute write a prepare write sequence.
+**
+** Parameters       conn_id - connection ID.
+**                    is_execute - execute or cancel.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ExecuteWrite  (UINT16 conn_id, BOOLEAN is_execute);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTC_ReadMultiple
+**
+** Description      This function is called to read multiple characteristic or
+**                  characteristic descriptors.
+**
+** Parameters       conn_id - connectino ID.
+**                    p_read_multi - read multiple parameters.
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_ReadMultiple(UINT16 conn_id, tBTA_GATTC_MULTI *p_read_multi,
+                                           tBTA_GATT_AUTH_REQ auth_req);
+
+
+
+
+/*******************************************************************************
+**  BTA GATT Server API
+********************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppRegister
+**
+** Description      This function is called to register application callbacks
+**                    with BTA GATTS module.
+**
+** Parameters       p_app_uuid - applicaiton UUID
+**                  p_cback - pointer to the application callback function.
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_AppRegister(tBT_UUID *p_app_uuid, tBTA_GATTS_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AppDeregister
+**
+** Description      De-register with BTA GATT Server.
+**
+** Parameters       server_if: server interface
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_AppDeregister(tBTA_GATTS_IF server_if);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CreateService
+**
+** Description      Create a service. When service creation is done, a callback
+**                  event BTA_GATTS_CREATE_SRVC_EVT is called to report status
+**                  and service ID to the profile. The service ID obtained in
+**                  the callback function needs to be used when adding included
+**                  service and characteristics/descriptors into the service.
+**
+** Parameters       server_if: server interface.
+**                  p_service_uuid: service UUID.
+**                  inst: instance ID number of this service.
+**                  num_handle: numble of handle requessted for this service.
+**                  is_primary: is this service a primary one or not.
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_CreateService(tBTA_GATTS_IF server_if, tBT_UUID *p_service_uuid,
+                                                UINT8 inst, UINT16 num_handle, BOOLEAN is_primary);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddIncludeService
+**
+** Description      This function is called to add an included service. After included
+**                  service is included, a callback event BTA_GATTS_ADD_INCL_SRVC_EVT
+**                  is reported the included service ID.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  included_service_id: the service ID to be included.
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_AddIncludeService(UINT16 service_id, UINT16 included_service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharacteristic
+**
+** Description      This function is called to add a characteristic into a service.
+**
+** Parameters       service_id: service ID to which this included service is to
+**                              be added.
+**                  p_char_uuid : Characteristic UUID.
+**                  perm      : Characteristic value declaration attribute permission.
+**                  property  : Characteristic Properties
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_AddCharacteristic (UINT16 service_id,  tBT_UUID   *p_char_uuid,
+                                                     tBTA_GATT_PERM perm, tBTA_GATT_CHAR_PROP property);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_AddCharDescriptor
+**
+** Description      This function is called to add characteristic descriptor. When
+**                  it's done, a callback event BTA_GATTS_ADD_DESCR_EVT is called
+**                  to report the status and an ID number for this descriptor.
+**
+** Parameters       service_id: service ID to which this charatceristic descriptor is to
+**                              be added.
+**                  perm: descriptor access permission.
+**                  p_descr_uuid: descriptor UUID.
+**                  p_descr_params: descriptor value if it's read only descriptor.
+**
+** Returns          returns status.
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_AddCharDescriptor (UINT16 service_id,
+                                                     tBTA_GATT_PERM perm,
+                                                     tBT_UUID  * p_descr_uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_DeleteService
+**
+** Description      This function is called to delete a service. When this is done,
+**                  a callback event BTA_GATTS_DELETE_EVT is report with the status.
+**
+** Parameters       service_id: service_id to be deleted.
+**
+** Returns          returns none.
+**
+*******************************************************************************/
+    BTA_API extern void  BTA_GATTS_DeleteService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StartService
+**
+** Description      This function is called to start a service.
+**
+** Parameters       service_id: the service ID to be started.
+**                  sup_transport: supported trasnport.
+**
+** Returns          None.
+**
+*******************************************************************************/
+    BTA_API extern void  BTA_GATTS_StartService(UINT16 service_id, tBTA_GATT_TRANSPORT sup_transport);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_StopService
+**
+** Description      This function is called to stop a service.
+**
+** Parameters       service_id - service to be topped.
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_StopService(UINT16 service_id);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_HandleValueIndication
+**
+** Description      This function is called to read a characteristics descriptor.
+**
+** Parameters       conn_id - connection identifier.
+**					attr_id - attribute ID to indicate.
+**                  data_len - indicate data length.
+**                  p_data: data to indicate.
+**                  need_confirm - if this indication expects a confirmation or not.
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_HandleValueIndication (UINT16 conn_id, UINT16 attr_id,
+                                                         UINT16 data_len,
+                                                         UINT8 *p_data,
+                                                         BOOLEAN need_confirm);
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_SendRsp
+**
+** Description      This function is called to send a response to a request.
+**
+** Parameters       conn_id - connection identifier.
+**                  trans_id - transaction ID.
+**                  status - response status
+**                  p_msg - response data.
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_SendRsp (UINT16 conn_id, UINT32 trans_id,
+                                           tBTA_GATT_STATUS status, tBTA_GATTS_RSP *p_msg);
+
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Open
+**
+** Description      Open a direct open connection or add a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_Open(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_CancelOpen
+**
+** Description      Cancel a direct open connection or remove a background auto connection
+**                  bd address
+**
+** Parameters       server_if: server interface.
+**                  remote_bda: remote device BD address.
+**                  is_direct: direct connection or background auto connection
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_CancelOpen(tBTA_GATTS_IF server_if, BD_ADDR remote_bda, BOOLEAN is_direct);
+
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Close
+**
+** Description      Close a connection  a remote device.
+**
+** Parameters       conn_id: connectino ID to be closed.
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_Close(UINT16 conn_id);
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+
+#endif /* BTA_GATT_API_H */
+
diff --git a/bta/include/bta_gattc_ci.h b/bta/include/bta_gattc_ci.h
new file mode 100644
index 0000000..1525e3e
--- /dev/null
+++ b/bta/include/bta_gattc_ci.h
@@ -0,0 +1,120 @@
+/******************************************************************************
+ *
+ *  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 is the interface file for GATT call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CI_H
+#define BTA_GATTC_CI_H
+
+#include "bta_gatt_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* Open Complete Event */
+typedef struct
+{
+    BT_HDR            hdr;
+    tBTA_GATT_STATUS  status;
+} tBTA_GATTC_CI_EVT;
+
+#define BTA_GATTC_NV_LOAD_MAX   10
+
+/* Read Ready Event */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_GATT_STATUS    status;
+    UINT16              num_attr;
+    tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
+} tBTA_GATTC_CI_LOAD;
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_open
+**
+** Description      This function sends an event to indicate server cache open
+**                  completed.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_open(BD_ADDR server_bda, UINT16 evt,
+                                            tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_cache_load
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  load the servere cache and ready to send it to the stack.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  num_bytes_read - number of bytes read into the buffer
+**                      specified in the read callout-function.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_load(BD_ADDR server_bda, UINT16 evt,
+                                            UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_atrr,
+                                            tBTA_GATT_STATUS status, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_ci_save
+**
+** Description      This function sends an event to BTA indicating the phone has
+**                  save the server cache.
+**
+** Parameters       server_bda - server BDA of this cache.
+**                  status - BTA_GATT_OK if full buffer of data,
+**                           BTA_GATT_FAIL if an error has occurred.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_ci_cache_save(BD_ADDR server_bda, UINT16 evt,
+                                            tBTA_GATT_STATUS status, UINT16 conn_id);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_GATTC_CI_H */
+
diff --git a/bta/include/bta_gattc_co.h b/bta/include/bta_gattc_co.h
new file mode 100644
index 0000000..d2392b8
--- /dev/null
+++ b/bta/include/bta_gattc_co.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the interface file for BTA GATT client call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTC_CO_H
+#define BTA_GATTC_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_open
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is ready to be sent.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache open is done.
+**                  conn_id: connection ID of this cache operation attach to.
+**                  to_save: open cache to save or to load.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt,
+                                            UINT16 conn_id, BOOLEAN to_save);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_close
+**
+** Description      This callout function is executed by GATTC when a GATT server
+**                  cache is written completely.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  conn_id: connection ID of this cache operation attach to.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_save
+**
+** Description      This callout function is executed by GATT when a server cache
+**                  is available to save.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  p_attr: pointer to the list of attributes to save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_save(BD_ADDR server_bda, UINT16 evt,
+                                          UINT16 num_attr, tBTA_GATTC_NV_ATTR *p_attr,
+                                          UINT16 attr_index, UINT16 conn_id);
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_load
+**
+** Description      This callout function is executed by GATT when server cache
+**                  is required to load.
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**                  evt: call in event to be passed in when cache save is done.
+**                  num_attr: number of attribute to be save.
+**                  attr_index: starting attribute index of the save operation.
+**                  conn_id: connection ID of this cache operation attach to.
+** Returns
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
+                                            UINT16 start_index, UINT16 conn_id);
+
+#endif /* BTA_GATT_CO_H */
+
diff --git a/bta/include/bta_gatts_co.h b/bta/include/bta_gatts_co.h
new file mode 100644
index 0000000..86f65dc
--- /dev/null
+++ b/bta/include/bta_gatts_co.h
@@ -0,0 +1,82 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the interface file for BTA GATT server call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_GATTS_CO_H
+#define BTA_GATTS_CO_H
+
+#include "bta_gatt_api.h"
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_update_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range ios to be added or removed.
+**
+** Parameter        is_add: true is to add a handle range; otherwise is to delete.
+**                  p_hndl_range: handle range.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gatts_co_update_handle_range(BOOLEAN is_add, tBTA_GATTS_HNDL_RANGE *p_hndl_range);
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_srv_chg
+**
+** Description      This call-out is to read/write/remove service change related
+**                  informaiton. The request consists of the cmd and p_req and the
+**                  response is returned in p_rsp
+**
+** Parameter        cmd - request command
+**                  p_req - request paramters
+**                  p_rsp - response data for the request
+**
+** Returns          TRUE - if the request is processed successfully and
+**                         the response is returned in p_rsp.
+**                  FASLE - if the request can not be processed
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_gatts_co_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+                                            tBTA_GATTS_SRV_CHG_REQ *p_req,
+                                            tBTA_GATTS_SRV_CHG_RSP *p_rsp);
+
+/*******************************************************************************
+**
+** Function         bta_gatts_co_load_handle_range
+**
+** Description      This callout function is executed by GATTS when a GATT server
+**                  handle range is requested to be loaded from NV.
+**
+** Parameter
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern  BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+                                                       tBTA_GATTS_HNDL_RANGE *p_handle);
+
+
+#endif /* BTA_GATTS_CO_H */
+
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
new file mode 100644
index 0000000..f613d30
--- /dev/null
+++ b/bta/include/bta_hh_api.h
@@ -0,0 +1,479 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#ifndef BTA_HH_API_H
+#define BTA_HH_API_H
+
+#include "bta_api.h"
+#include "hidh_api.h"
+
+/*****************************************************************************
+**  Constants and Type Definitions
+*****************************************************************************/
+#ifndef BTA_HH_DEBUG
+#define BTA_HH_DEBUG    FALSE
+#endif
+
+#ifndef BTA_HH_SSR_MAX_LATENCY_DEF
+#define BTA_HH_SSR_MAX_LATENCY_DEF  1600
+#endif
+
+#ifndef BTA_HH_SSR_MIN_TOUT_DEF
+#define BTA_HH_SSR_MIN_TOUT_DEF     2
+#endif
+
+/* BTA HID Host callback events */
+#define BTA_HH_ENABLE_EVT       0       /* HH enabled */
+#define BTA_HH_DISABLE_EVT      1       /* HH disabled */
+#define BTA_HH_OPEN_EVT         2       /* connection opened */
+#define BTA_HH_CLOSE_EVT        3       /* connection closed */
+#define BTA_HH_GET_RPT_EVT      4       /* BTA_HhGetReport callback */
+#define BTA_HH_SET_RPT_EVT      5       /* BTA_HhSetReport callback */
+#define BTA_HH_GET_PROTO_EVT    6       /* BTA_GetProtoMode callback */
+#define BTA_HH_SET_PROTO_EVT    7       /* BTA_HhSetProtoMode callback */
+#define BTA_HH_GET_IDLE_EVT     8       /* BTA_HhGetIdle comes callback */
+#define BTA_HH_SET_IDLE_EVT     9       /* BTA_HhSetIdle finish callback */
+#define BTA_HH_GET_DSCP_EVT     10      /* Get report descripotor */
+#define BTA_HH_ADD_DEV_EVT      11      /* Add Device callback */
+#define BTA_HH_RMV_DEV_EVT      12      /* remove device finished */
+#define BTA_HH_VC_UNPLUG_EVT    13      /* virtually unplugged */
+#define BTA_HH_UPDATE_UCD_EVT   14
+#define BTA_HH_API_ERR_EVT      15      /* API error is caught */
+
+typedef UINT16 tBTA_HH_EVT;
+
+/* defined the minimum offset */
+#define BTA_HH_MIN_OFFSET       L2CAP_MIN_OFFSET+1
+
+#define BTA_HH_MAX_KNOWN        HID_HOST_MAX_DEVICES
+/* invalid device handle */
+#define BTA_HH_INVALID_HANDLE   0xff
+
+/* type of protocol mode */
+#define BTA_HH_PROTO_RPT_MODE                   (0x00)
+#define BTA_HH_PROTO_BOOT_MODE                  (0x01)
+#define BTA_HH_PROTO_UNKNOWN                    (0xff)
+typedef UINT8   tBTA_HH_PROTO_MODE;
+
+enum
+{
+    BTA_HH_KEYBD_RPT_ID  =               1,
+    BTA_HH_MOUSE_RPT_ID
+};
+typedef UINT8 tBTA_HH_BOOT_RPT_ID;
+
+/* type of devices, bit mask */
+#define BTA_HH_DEVT_UNKNOWN      0x00
+#define BTA_HH_DEVT_JOS          0x01           /* joy stick */
+#define BTA_HH_DEVT_GPD          0x02           /* game pad */
+#define BTA_HH_DEVT_RMC          0x03           /* remote control */
+#define BTA_HH_DEVT_SED          0x04           /* sensing device */
+#define BTA_HH_DEVT_DGT          0x05           /* Digitizer tablet */
+#define BTA_HH_DEVT_CDR          0x06           /* card reader */
+#define BTA_HH_DEVT_KBD          0x10           /* keyboard */
+#define BTA_HH_DEVT_MIC          0x20           /* pointing device */
+#define BTA_HH_DEVT_COM          0x30           /* Combo keyboard/pointing */
+#define BTA_HH_DEVT_OTHER        0x80
+typedef UINT8  tBTA_HH_DEVT;
+
+enum
+{
+    BTA_HH_OK,
+    BTA_HH_HS_HID_NOT_READY,    /* handshake error : device not ready */
+    BTA_HH_HS_INVALID_RPT_ID,   /* handshake error : invalid report ID */
+    BTA_HH_HS_TRANS_NOT_SPT,    /* handshake error : transaction not spt */
+    BTA_HH_HS_INVALID_PARAM,    /* handshake error : invalid paremter */
+    BTA_HH_HS_ERROR,            /* handshake error : unspecified HS error */
+    BTA_HH_ERR,                 /* general BTA HH error */
+    BTA_HH_ERR_SDP,             /* SDP error */
+    BTA_HH_ERR_PROTO,           /* SET_Protocol error,
+                                    only used in BTA_HH_OPEN_EVT callback */
+    BTA_HH_ERR_DB_FULL,         /* device database full error, used in
+                                   BTA_HH_OPEN_EVT/BTA_HH_ADD_DEV_EVT */
+    BTA_HH_ERR_TOD_UNSPT,       /* type of device not supported */
+    BTA_HH_ERR_NO_RES,          /* out of system resources */
+    BTA_HH_ERR_AUTH_FAILED,     /* authentication fail */
+    BTA_HH_ERR_HDL
+};
+typedef UINT8 tBTA_HH_STATUS;
+
+
+#define BTA_HH_VIRTUAL_CABLE           HID_VIRTUAL_CABLE
+#define BTA_HH_NORMALLY_CONNECTABLE    HID_NORMALLY_CONNECTABLE
+#define BTA_HH_RECONN_INIT             HID_RECONN_INIT
+#define BTA_HH_SDP_DISABLE             HID_SDP_DISABLE
+#define BTA_HH_BATTERY_POWER           HID_BATTERY_POWER
+#define BTA_HH_REMOTE_WAKE             HID_REMOTE_WAKE
+#define BTA_HH_SUP_TOUT_AVLBL          HID_SUP_TOUT_AVLBL
+#define BTA_HH_SEC_REQUIRED             HID_SEC_REQUIRED
+typedef UINT16 tBTA_HH_ATTR_MASK;
+
+
+/* supported type of device and corresponding application ID */
+typedef struct
+{
+    tBTA_HH_DEVT        tod;        /* type of device               */
+    UINT8               app_id;     /* corresponding application ID */
+}tBTA_HH_SPT_TOD;
+
+/* configuration struct */
+typedef struct
+{
+    UINT8                max_devt_spt; /* max number of types of devices spt */
+    tBTA_HH_SPT_TOD     *p_devt_list;  /* supported types of device list     */
+    UINT16               sdp_db_size;
+}tBTA_HH_CFG;
+
+enum
+{
+    BTA_HH_RPTT_RESRV,      /* reserved         */
+    BTA_HH_RPTT_INPUT,      /* input report     */
+    BTA_HH_RPTT_OUTPUT,     /* output report    */
+    BTA_HH_RPTT_FEATURE     /* feature report   */
+};
+typedef UINT8 tBTA_HH_RPT_TYPE;
+
+/* HID_CONTROL operation code used in BTA_HhSendCtrl()
+*/
+enum
+{
+    BTA_HH_CTRL_NOP         = 0 + HID_PAR_CONTROL_NOP ,/* mapping from BTE */
+    BTA_HH_CTRL_HARD_RESET,                            /* hard reset       */
+    BTA_HH_CTRL_SOFT_RESET,                            /* soft reset       */
+    BTA_HH_CTRL_SUSPEND,                               /* enter suspend    */
+    BTA_HH_CTRL_EXIT_SUSPEND,                          /* exit suspend     */
+    BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG                   /* virtual unplug   */
+};
+typedef UINT8 tBTA_HH_TRANS_CTRL_TYPE;
+
+typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR;
+
+/* id DI is not existing in remote device, vendor_id in tBTA_HH_DEV_DSCP_INFO will be set to 0xffff */
+#define BTA_HH_VENDOR_ID_INVALID       0xffff
+
+
+/* report descriptor information */
+typedef struct
+{
+    UINT16              vendor_id;      /* vendor ID */
+    UINT16              product_id;     /* product ID */
+    UINT16              version;        /* version */
+    UINT16              ssr_max_latency;    /* SSR max latency */
+    UINT16              ssr_min_tout;       /* SSR min timeout */
+    UINT8               ctry_code;      /*Country Code.*/
+    tBTA_HH_DEV_DESCR   descriptor;
+}tBTA_HH_DEV_DSCP_INFO;
+
+/* callback event data for BTA_HH_OPEN_EVT */
+typedef struct
+{
+    BD_ADDR         bda;                /* HID device bd address    */
+    tBTA_HH_STATUS  status;             /* operation status         */
+    UINT8           handle;             /* device handle            */
+} tBTA_HH_CONN;
+
+typedef tBTA_HH_CONN tBTA_HH_DEV_INFO;
+
+/* callback event data */
+typedef struct
+{
+    tBTA_HH_STATUS              status;     /* operation status         */
+    UINT8                       handle;     /* device handle            */
+} tBTA_HH_CBDATA;
+
+enum
+{
+    BTA_HH_MOD_CTRL_KEY,
+    BTA_HH_MOD_SHFT_KEY,
+    BTA_HH_MOD_ALT_KEY,
+    BTA_HH_MOD_GUI_KEY,
+    BTA_HH_MOD_MAX_KEY
+};
+
+/* parsed boot mode keyboard report */
+typedef struct
+{
+    UINT8               this_char[6];       /* virtual key code     */
+    BOOLEAN             mod_key[BTA_HH_MOD_MAX_KEY];
+                                            /* ctrl, shift, Alt, GUI */
+                                            /* modifier key: is Shift key pressed */
+                                            /* modifier key: is Ctrl key pressed  */
+                                            /* modifier key: is Alt key pressed   */
+                                            /* modifier key: GUI up/down */
+    BOOLEAN             caps_lock;          /* is caps locked       */
+    BOOLEAN             num_lock;           /* is Num key pressed   */
+} tBTA_HH_KEYBD_RPT;
+
+/* parsed boot mode mouse report */
+typedef struct
+{
+    UINT8               mouse_button;       /* mouse button is clicked   */
+    INT8                delta_x;            /* displacement x            */
+    INT8                delta_y;            /* displacement y            */
+}tBTA_HH_MICE_RPT;
+
+/* parsed Boot report */
+typedef struct
+{
+    tBTA_HH_BOOT_RPT_ID dev_type;           /* type of device report */
+    union
+    {
+        tBTA_HH_KEYBD_RPT   keybd_rpt;      /* keyboard report      */
+        tBTA_HH_MICE_RPT    mice_rpt;       /* mouse report         */
+    }                   data_rpt;
+} tBTA_HH_BOOT_RPT;
+
+/* handshake data */
+typedef struct
+{
+    tBTA_HH_STATUS  status;                 /* handshake status */
+    UINT8           handle;                 /* device handle    */
+    union
+    {
+        tBTA_HH_PROTO_MODE      proto_mode; /* GET_PROTO_EVT :protocol mode */
+        BT_HDR                  *p_rpt_data;   /* GET_RPT_EVT   : report data  */
+        UINT8                   idle_rate;  /* GET_IDLE_EVT  : idle rate    */
+    }               rsp_data;
+
+}tBTA_HH_HSDATA;
+
+/* union of data associated with HD callback */
+typedef union
+{
+    tBTA_HH_DEV_INFO        dev_info;           /* BTA_HH_ADD_DEV_EVT, BTA_HH_RMV_DEV_EVT   */
+    tBTA_HH_CONN            conn;               /* BTA_HH_OPEN_EVT      */
+    tBTA_HH_CBDATA          dev_status;         /* BTA_HH_CLOSE_EVT,
+                                                   BTA_HH_SET_PROTO_EVT
+                                                   BTA_HH_SET_RPT_EVT
+                                                   BTA_HH_SET_IDLE_EVT  */
+
+    tBTA_HH_STATUS          status;             /* BTA_HH_ENABLE_EVT */
+    tBTA_HH_DEV_DSCP_INFO   dscp_info;          /* BTA_HH_GET_DSCP_EVT */
+    tBTA_HH_HSDATA          hs_data;            /* GET_ transaction callback
+                                                   BTA_HH_GET_RPT_EVT
+                                                   BTA_HH_GET_PROTO_EVT
+                                                   BTA_HH_GET_IDLE_EVT */
+} tBTA_HH;
+
+/* BTA HH callback function */
+typedef void (tBTA_HH_CBACK) (tBTA_HH_EVT event, tBTA_HH *p_data);
+
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_HhRegister
+**
+** Description      This function enable HID host and registers HID-Host with
+**                  lower layers.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_HhDeregister
+**
+** Description      This function is called when the host is about power down.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhDisable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_HhOpen
+**
+** Description      This function is called to start an inquiry and read SDP
+**                  record of responding devices; connect to a device if only
+**                  one active HID device is found.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhOpen (BD_ADDR dev_bda, tBTA_HH_PROTO_MODE mode,
+                                tBTA_SEC sec_mask);
+
+/*******************************************************************************
+**
+** Function         BTA_HhClose
+**
+** Description      This function disconnects the device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhClose(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSetProtoMode
+**
+** Description      This function set the protocol mode at specified HID handle
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetProtoMode(UINT8 handle, tBTA_HH_PROTO_MODE t_type);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetProtoMode
+**
+** Description      This function get the protocol mode of a specified HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetProtoMode(UINT8 dev_handle);
+/*******************************************************************************
+**
+** Function         BTA_HhSetReport
+**
+** Description      send SET_REPORT to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+                                        BT_HDR *p_data);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetReport
+**
+** Description      Send a GET_REPORT to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetReport(UINT8 dev_handle, tBTA_HH_RPT_TYPE r_type,
+                                    UINT8 rpt_id, UINT16 buf_size);
+/*******************************************************************************
+**
+** Function         BTA_HhSendCtrl
+**
+** Description      Send HID_CONTROL request to a HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSendCtrl(UINT8 dev_handle,
+                                   tBTA_HH_TRANS_CTRL_TYPE c_type);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSetIdle
+**
+** Description      send SET_IDLE to device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSetIdle(UINT8 dev_handle, UINT16 idle_rate);
+
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetIdle
+**
+** Description      Send a GET_IDLE from HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhSendData
+**
+** Description      Send DATA transaction to a HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhSendData(UINT8 dev_handle, BD_ADDR dev_bda, BT_HDR  *p_buf);
+
+/*******************************************************************************
+**
+** Function         BTA_HhGetDscpInfo
+**
+** Description      Get report descriptor of the device
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetDscpInfo(UINT8 dev_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HhAddDev
+**
+** Description      Add a virtually cabled device into HID-Host device list
+**                  to manage and assign a device handle for future API call,
+**                  host applciation call this API at start-up to initialize its
+**                  virtually cabled devices.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhAddDev(BD_ADDR bda, tBTA_HH_ATTR_MASK attr_mask,
+                                 UINT8 sub_class, UINT8 app_id,
+                                 tBTA_HH_DEV_DSCP_INFO dscp_info);
+/*******************************************************************************
+**
+** Function         BTA_HhRemoveDev
+**
+** Description      Remove a device from the HID host devices list.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhRemoveDev(UINT8 dev_handle );
+/*******************************************************************************
+**
+**              Parsing Utility Functions
+**
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         BTA_HhParseBootRpt
+**
+** Description      This utility function parse a boot mode report.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
+                                       UINT16 report_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* BTA_HH_API_H */
diff --git a/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
new file mode 100644
index 0000000..8f648df
--- /dev/null
+++ b/bta/include/bta_hh_co.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2005-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 is the interface file for hid host call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HH_CO_H
+#define BTA_HH_CO_H
+
+#include "bta_hh_api.h"
+
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_data
+**
+** Description      This callout function is executed by HH when data is received
+**                  in interupt channel.
+**
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_data(UINT8 dev_handle, UINT8 *p_rpt, UINT16 len,
+                                   tBTA_HH_PROTO_MODE  mode, UINT8 sub_class,
+                                   UINT8 ctry_code, BD_ADDR peer_addr, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_open
+**
+** Description      This callout function is executed by HH when connection is
+**                  opened, and application may do some device specific
+**                  initialization.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_open(UINT8 dev_handle, UINT8 sub_class,
+                                   UINT16 attr_mask, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_hh_co_close
+**
+** Description      This callout function is executed by HH when connection is
+**                  closed, and device specific finalizatio nmay be needed.
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_hh_co_close(UINT8 dev_handle, UINT8 app_id);
+
+#endif /* BTA_HH_CO_H */
+
diff --git a/bta/include/bta_hl_api.h b/bta/include/bta_hl_api.h
new file mode 100644
index 0000000..e7febf8
--- /dev/null
+++ b/bta/include/bta_hl_api.h
@@ -0,0 +1,908 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the public interface file for the HeaLth device profile (HL)
+ *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_API_H
+#define BTA_HL_API_H
+
+#include "bta_api.h"
+#include "btm_api.h"
+#include "mca_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/* Extra Debug Code */
+#ifndef BTA_HL_DEBUG
+#define BTA_HL_DEBUG           TRUE
+#endif
+
+#ifndef BTA_HL_NUM_APPS
+#define BTA_HL_NUM_APPS                 3
+#endif
+
+#ifndef BTA_HL_NUM_MDEPS
+#define BTA_HL_NUM_MDEPS                5
+#endif
+
+#ifndef BTA_HL_NUM_MCLS
+#define BTA_HL_NUM_MCLS                 7
+#endif
+
+#ifndef BTA_HL_NUM_MDLS_PER_MDEP
+#define BTA_HL_NUM_MDLS_PER_MDEP        4
+#endif
+
+#ifndef BTA_HL_NUM_MDLS_PER_MCL
+#define BTA_HL_NUM_MDLS_PER_MCL         10
+#endif
+
+#ifndef BTA_HL_NUM_DATA_TYPES
+#define BTA_HL_NUM_DATA_TYPES            5   /* maximum number of data types can be supported
+                                                per MDEP ID */
+#endif
+
+#define BTA_HL_MCAP_RSP_TOUT            2    /* 2 seconds */
+
+#ifndef BTA_HL_CCH_NUM_FILTER_ELEMS
+#define BTA_HL_CCH_NUM_FILTER_ELEMS     3
+#endif
+
+#ifndef BTA_HL_NUM_SDP_CBACKS
+#define BTA_HL_NUM_SDP_CBACKS           7
+#endif
+
+#ifndef BTA_HL_NUM_SDP_RECS
+#define BTA_HL_NUM_SDP_RECS             3
+#endif
+
+#ifndef BTA_HL_NUM_SDP_MDEPS
+#define BTA_HL_NUM_SDP_MDEPS            10
+#endif
+
+#ifndef BTA_HL_NUM_SVC_ELEMS
+#define BTA_HL_NUM_SVC_ELEMS            2
+#endif
+
+#ifndef BTA_HL_NUM_PROTO_ELEMS
+#define BTA_HL_NUM_PROTO_ELEMS          2
+#endif
+
+#define BTA_HL_VERSION_01_00            0x0100
+#define BTA_HL_NUM_ADD_PROTO_LISTS      1
+#define BTA_HL_NUM_ADD_PROTO_ELEMS      2
+#define BTA_HL_MDEP_SEQ_SIZE            20
+#define BTA_HL_VAL_ARRY_SIZE            320
+
+#ifndef BTA_HL_NUM_MDL_CFGS
+#define BTA_HL_NUM_MDL_CFGS             16    /* numer of MDL cfg saved in the persistent memory*/
+#endif
+
+#define BTA_HL_NUM_TIMERS               7
+
+#define BTA_HL_CCH_RSP_TOUT             2000
+#define BTA_HL_LRG_POOL_ID              GKI_POOL_ID_7
+#define BTA_HL_MAX_TIME                 255
+#define BTA_HL_MIN_TIME                 1
+#define BTA_HL_INVALID_APP_HANDLE       0xFF
+#define BTA_HL_INVALID_MCL_HANDLE       0xFF
+#define BTA_HL_INVALID_MDL_HANDLE       0xFFFF
+
+#define BTA_HL_STATUS_OK                    0
+#define BTA_HL_STATUS_FAIL                  1   /* Used to pass all other errors */
+#define BTA_HL_STATUS_ABORTED               2
+#define BTA_HL_STATUS_NO_RESOURCE           3
+#define BTA_HL_STATUS_LAST_ITEM             4
+#define BTA_HL_STATUS_DUPLICATE_APP_ID      5
+#define BTA_HL_STATUS_INVALID_APP_HANDLE    6
+#define BTA_HL_STATUS_INVALID_MCL_HANDLE    7
+#define BTA_HL_STATUS_MCAP_REG_FAIL         8
+#define BTA_HL_STATUS_MDEP_CO_FAIL          9
+#define BTA_HL_STATUS_ECHO_CO_FAIL          10
+#define BTA_HL_STATUS_MDL_CFG_CO_FAIL       11
+#define BTA_HL_STATUS_SDP_NO_RESOURCE       12
+#define BTA_HL_STATUS_SDP_FAIL              13
+#define BTA_HL_STATUS_NO_CCH                14
+#define BTA_HL_STATUS_NO_MCL                15
+
+#define BTA_HL_STATUS_NO_FIRST_RELIABLE     17
+#define BTA_HL_STATUS_INVALID_DCH_CFG       18
+#define BTA_HL_STATUS_INVALID_MDL_HANDLE    19
+#define BTA_HL_STATUS_INVALID_BD_ADDR       20
+#define BTA_HL_STATUS_INVALID_RECONNECT_CFG 21
+#define BTA_HL_STATUS_ECHO_TEST_BUSY        22
+#define BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID 23
+#define BTA_HL_STATUS_INVALID_MDL_ID        24
+#define BTA_HL_STATUS_NO_MDL_ID_FOUND       25
+#define BTA_HL_STATUS_DCH_BUSY              26  /* DCH is congested*/
+#define BTA_HL_STATUS_INVALID_CTRL_PSM      27
+
+typedef UINT8 tBTA_HL_STATUS;
+typedef tMCA_HANDLE tBTA_HL_APP_HANDLE;
+typedef tMCA_CL     tBTA_HL_MCL_HANDLE;
+typedef tMCA_DL     tBTA_HL_MDL_HANDLE;
+enum
+{
+    BTA_HL_DEVICE_TYPE_SINK,
+    BTA_HL_DEVICE_TYPE_SOURCE,
+    BTA_HL_DEVICE_TYPE_DUAL
+};
+
+typedef UINT8 tBTA_HL_DEVICE_TYPE;
+
+
+
+#define BTA_HL_SDP_IEEE_11073_20601             0x01
+
+#define BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT          2 /* 0x02 */
+#define BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT        4 /* 0x04 */
+#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE          0 /* 0x08 */
+#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER         0 /* 0x10 */
+
+#define BTA_HL_MCAP_SUP_PROC_MASK  (BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT | \
+                                    BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT | \
+                                    BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE | \
+                                    BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER)
+#define BTA_HL_MDEP_ROLE_SOURCE         0x00
+#define BTA_HL_MDEP_ROLE_SINK           0x01
+
+typedef UINT8 tBTA_HL_MDEP_ROLE;
+
+#define BTA_HL_MDEP_ROLE_MASK_SOURCE    0x01     /* bit mask */
+#define BTA_HL_MDEP_ROLE_MASK_SINK      0x02
+typedef UINT8 tBTA_HL_MDEP_ROLE_MASK;
+
+
+#define BTA_HL_ECHO_TEST_MDEP_ID        0
+#define BTA_HL_ECHO_TEST_MDEP_CFG_IDX   0
+
+#define BTA_HL_INVALID_MDEP_ID     0xFF
+typedef tMCA_DEP tBTA_HL_MDEP_ID; /* 0 is for echo test,
+                                   0x01-0x7F availave for use,
+                                   0x80-0xFF reserved*/
+
+
+#define BTA_HL_DELETE_ALL_MDL_IDS   0xFFFF
+#define BTA_HL_MAX_MDL_VAL          0xFEFF
+typedef UINT16 tBTA_HL_MDL_ID;  /* 0x0000 reserved,
+                                   0x0001-0xFEFF dynamic range,
+                                   0xFF00-0xFFFE reserved,
+                                   0xFFFF indicates all MDLs*/
+
+#define BTA_HL_MDEP_DESP_LEN       35
+
+#define BTA_HL_DCH_MODE_RELIABLE    0
+#define BTA_HL_DCH_MODE_STREAMING   1
+
+typedef UINT8 tBTA_HL_DCH_MODE;
+
+#define BTA_HL_DCH_CFG_NO_PREF      0
+#define BTA_HL_DCH_CFG_RELIABLE     1
+#define BTA_HL_DCH_CFG_STREAMING    2
+#define BTA_HL_DCH_CFG_UNKNOWN      0xFF
+
+typedef UINT8 tBTA_HL_DCH_CFG;
+
+/* The Default DCH CFG for the echo test when the device is a Source */
+#define BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG BTA_HL_DCH_CFG_RELIABLE
+
+#define BTA_HL_DCH_CREATE_RSP_SUCCESS 0
+#define BTA_HL_DCH_CREATE_RSP_CFG_REJ 1
+
+typedef UINT8 tBTA_HL_DCH_CREATE_RSP;
+
+#define BTA_HL_MCAP_SUP_PROC_RECONNECT_INIT 0x02
+#define BTA_HL_MCAP_SUP_PROC_RECONNECT_APT  0x04
+#define BTA_HL_MCAP_SUP_PROC_CSP_SLAVE      0x08
+#define BTA_HL_MCAP_SUP_PROC_CSP_MASTER     0x10
+
+typedef UINT8 tBTA_HL_SUP_PROC_MASK;
+
+typedef struct
+{
+    UINT16                  max_rx_apdu_size;  /* local rcv MTU */
+    UINT16                  max_tx_apdu_size;  /* maximum TX APDU size*/
+} tBTA_HL_ECHO_CFG;
+
+
+typedef struct
+{
+    UINT16                  data_type;
+    UINT16                  max_rx_apdu_size;  /* local rcv MTU */
+    UINT16                  max_tx_apdu_size;  /* maximum TX APDU size*/
+    char                    desp[BTA_HL_MDEP_DESP_LEN+1];
+} tBTA_HL_MDEP_DATA_TYPE_CFG;
+
+
+typedef struct
+{
+    tBTA_HL_MDEP_ROLE           mdep_role;
+    UINT8                       num_of_mdep_data_types;
+    tBTA_HL_MDEP_DATA_TYPE_CFG  data_cfg[BTA_HL_NUM_DATA_TYPES];
+} tBTA_HL_MDEP_CFG;
+
+typedef struct
+{
+    tBTA_HL_MDEP_ID         mdep_id;  /* MDEP ID 0x01-0x7F */
+    tBTA_HL_MDEP_CFG        mdep_cfg;
+} tBTA_HL_MDEP;
+
+typedef struct
+{
+    tBTA_HL_MDEP            mdep[BTA_HL_NUM_MDEPS];
+    tBTA_HL_ECHO_CFG        echo_cfg;
+    tBTA_HL_MDEP_ROLE_MASK  app_role_mask;
+    BOOLEAN                 advertize_source_sdp;
+    UINT8                   num_of_mdeps;
+} tBTA_HL_SUP_FEATURE;
+
+typedef struct
+{
+    BOOLEAN                 delete_req_pending;
+    tBTA_HL_MDL_ID          mdl_id;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+} tBTA_HL_DELETE_MDL;
+
+typedef struct
+{
+    UINT8                   time;
+    UINT16                  mtu;
+    tBTA_HL_MDL_ID          mdl_id;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    tBTA_HL_MDEP_ROLE       local_mdep_role;
+    BOOLEAN                 active;     /* true if this item is in use */
+    tBTA_HL_DCH_MODE        dch_mode;
+    UINT8                   fcs;
+    BD_ADDR                 peer_bd_addr;
+} tBTA_HL_MDL_CFG;
+
+
+/* Maximum number of supported feature list items (list_elem in tSDP_SUP_FEATURE_ELEM) */
+#define BTA_HL_NUM_SUP_FEATURE_ELEMS     10
+#define BTA_HL_SUP_FEATURE_SDP_BUF_SIZE  512
+/* This structure is used to add supported feature lists and find supported feature elements */
+typedef struct
+{
+    UINT8       mdep_id;
+    UINT16      data_type;
+    tBTA_HL_MDEP_ROLE       mdep_role;
+    char        *p_mdep_desp;
+} tBTA_HL_SUP_FEATURE_ELEM;
+
+typedef struct
+{
+    UINT16                      num_elems;
+    tBTA_HL_SUP_FEATURE_ELEM   list_elem[BTA_HL_NUM_SUP_FEATURE_ELEMS];
+} tBTA_HL_SUP_FEATURE_LIST_ELEM;
+
+
+typedef struct
+{
+    tBTA_HL_DEVICE_TYPE     dev_type;           /* sink, source or dual roles */
+    tBTA_SEC                sec_mask;           /* security mask for accepting conenction*/
+    const char              *p_srv_name;        /* service name to be used in the SDP; null terminated*/
+    const char              *p_srv_desp;        /* service description to be used in the SDP; null terminated */
+    const char              *p_provider_name;   /* provide name to be used in the SDP; null terminated */
+} tBTA_HL_REG_PARAM;
+
+typedef struct
+{
+    UINT16                  ctrl_psm;
+    BD_ADDR                 bd_addr;           /* Address of peer device */
+    tBTA_SEC                sec_mask;          /* security mask for initiating connection*/
+} tBTA_HL_CCH_OPEN_PARAM;
+
+
+typedef struct
+{
+    UINT16                  ctrl_psm;
+    tBTA_HL_MDEP_ID         local_mdep_id;     /* local MDEP ID */
+    tBTA_HL_MDEP_ID         peer_mdep_id;      /* peer mdep id */
+    tBTA_HL_DCH_CFG         local_cfg;
+    tBTA_SEC                sec_mask;          /* security mask for initiating connection*/
+} tBTA_HL_DCH_OPEN_PARAM;
+
+
+typedef struct
+{
+    UINT16                  ctrl_psm;
+    tBTA_HL_MDL_ID          mdl_id;
+} tBTA_HL_DCH_RECONNECT_PARAM;
+
+
+typedef struct
+{
+    UINT16                  ctrl_psm;
+    UINT16                  pkt_size;
+    tBTA_HL_DCH_CFG         local_cfg;
+} tBTA_HL_DCH_ECHO_TEST_PARAM;
+
+typedef struct
+{
+    UINT16                  buf_size;
+    UINT8                   p_buf;        /* buffer pointer */
+} tBTA_HL_DCH_BUF_INFO;
+
+typedef struct
+{
+    tBTA_HL_MDEP_ID         local_mdep_id;  /* local MDEP ID */
+    tBTA_HL_MDL_ID          mdl_id;
+    tBTA_HL_DCH_CREATE_RSP  rsp_code;
+    tBTA_HL_DCH_CFG         cfg_rsp;
+} tBTA_HL_DCH_CREATE_RSP_PARAM;
+
+typedef struct
+{
+    UINT16              data_type;
+    UINT8               mdep_id;
+    tBTA_HL_MDEP_ROLE   mdep_role;
+    char                mdep_desp[BTA_HL_MDEP_DESP_LEN+1];
+}tBTA_HL_SDP_MDEP_CFG;
+
+typedef struct
+{
+    UINT16                  ctrl_psm;
+    UINT16                  data_psm;
+    UINT8                   mcap_sup_proc;
+    UINT8                   num_mdeps; /* number of mdep elements from SDP*/
+    char                    srv_name[BTA_SERVICE_NAME_LEN+1];
+    char                    srv_desp[BTA_SERVICE_DESP_LEN+1];
+    char                    provider_name[BTA_PROVIDER_NAME_LEN+1];
+    tBTA_HL_SDP_MDEP_CFG    mdep_cfg[BTA_HL_NUM_SDP_MDEPS];
+} tBTA_HL_SDP_REC;
+
+typedef struct
+{
+    UINT8                num_recs;
+    tBTA_HL_SDP_REC      sdp_rec[BTA_HL_NUM_SDP_RECS];
+} tBTA_HL_SDP;
+
+/* HL control callback function events */
+enum
+{
+    BTA_HL_CTRL_ENABLE_CFM_EVT            = 0,
+    BTA_HL_CTRL_DISABLE_CFM_EVT
+};
+typedef UINT8 tBTA_HL_CTRL_EVT;
+/* Structure associated with BTA_HL_ENABLE_EVT
+   BTA_HL_DISABLE_EVT */
+
+typedef struct
+{
+    tBTA_HL_STATUS  status;
+} tBTA_HL_CTRL_ENABLE_DISABLE;
+
+typedef union
+{
+    tBTA_HL_CTRL_ENABLE_DISABLE  enable_cfm;
+    tBTA_HL_CTRL_ENABLE_DISABLE  disable_cfm;
+} tBTA_HL_CTRL;
+
+/* HL instance callback function events */
+enum
+{
+    BTA_HL_REGISTER_CFM_EVT           =0,
+    BTA_HL_DEREGISTER_CFM_EVT,
+    BTA_HL_CCH_OPEN_IND_EVT,
+    BTA_HL_CCH_OPEN_CFM_EVT,
+    BTA_HL_CCH_CLOSE_IND_EVT,
+    BTA_HL_CCH_CLOSE_CFM_EVT,
+    BTA_HL_DCH_CREATE_IND_EVT,
+    BTA_HL_DCH_OPEN_IND_EVT,
+    BTA_HL_DCH_OPEN_CFM_EVT,
+    BTA_HL_DCH_CLOSE_IND_EVT,
+    BTA_HL_DCH_CLOSE_CFM_EVT,
+    BTA_HL_DCH_RECONNECT_IND_EVT,
+    BTA_HL_DCH_RECONNECT_CFM_EVT,
+
+    BTA_HL_DCH_ABORT_IND_EVT,
+    BTA_HL_DCH_ABORT_CFM_EVT,
+    BTA_HL_DELETE_MDL_IND_EVT,
+    BTA_HL_DELETE_MDL_CFM_EVT,
+    BTA_HL_DCH_SEND_DATA_CFM_EVT,
+    BTA_HL_DCH_RCV_DATA_IND_EVT,
+    BTA_HL_CONG_CHG_IND_EVT,
+    BTA_HL_DCH_ECHO_TEST_CFM_EVT,
+    BTA_HL_SDP_QUERY_CFM_EVT,
+    BTA_HL_SDP_INFO_IND_EVT
+};
+typedef UINT8 tBTA_HL_EVT;
+
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;        /* start status */
+    UINT8                   app_id;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_REGISTER_CFM;
+
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;        /* start status */
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_DEREGISTER_CFM;
+
+
+typedef struct
+{
+    BOOLEAN                 intentional;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_CCH_CLOSE_IND;
+
+
+typedef struct
+{
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_MCL_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;             /* connection status */
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_MCL_CFM;
+
+typedef struct
+{
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    BD_ADDR                 bd_addr; /* address of peer device */
+} tBTA_HL_CCH_OPEN_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;             /* connection status */
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    BD_ADDR                 bd_addr;            /* address of peer device */
+} tBTA_HL_CCH_OPEN_CFM;
+
+typedef struct
+{
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    tBTA_HL_MDL_ID          mdl_id;             /* MCAP data link ID for this
+                                                   data channel conenction    */
+    tBTA_HL_DCH_CFG         cfg;                /* dch cfg requested by the peer device */
+} tBTA_HL_DCH_CREATE_IND;
+
+typedef struct
+{
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    tBTA_HL_MDL_ID          mdl_id;             /* MCAP data link ID for this
+                                                   data channel conenction    */
+    tBTA_HL_DCH_MODE        dch_mode;           /* data channel mode - reliable or streaming*/
+
+    BOOLEAN                 first_reliable;  /* whether this is the first reliable data channel */
+    UINT16                  mtu;
+} tBTA_HL_DCH_OPEN_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;             /* connection status */
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    tBTA_HL_MDEP_ID         local_mdep_id;
+    tBTA_HL_MDL_ID          mdl_id;             /* MCAP data link ID for this
+                                                   data channel conenction    */
+    tBTA_HL_DCH_MODE        dch_mode;           /* data channel mode - reliable or streaming*/
+    BOOLEAN                 first_reliable;     /* whether this is the first reliable data channel */
+    UINT16                  mtu;
+} tBTA_HL_DCH_OPEN_CFM;
+
+
+typedef struct
+{
+    BOOLEAN                 intentional;
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_DCH_CLOSE_IND;
+
+
+typedef struct
+{
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_MDL_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+} tBTA_HL_MDL_CFM;
+
+typedef struct
+{
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    tBTA_HL_MDL_ID          mdl_id;
+} tBTA_HL_DELETE_MDL_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    tBTA_HL_MDL_ID          mdl_id;
+} tBTA_HL_DELETE_MDL_CFM;
+
+typedef struct
+{
+    tBTA_HL_MDL_HANDLE      mdl_handle;
+    tBTA_HL_MCL_HANDLE      mcl_handle;
+    tBTA_HL_APP_HANDLE      app_handle;
+    BOOLEAN                 cong;
+} tBTA_HL_DCH_CONG_IND;
+
+typedef struct
+{
+    tBTA_HL_APP_HANDLE      app_handle;
+    UINT16                  ctrl_psm;
+    UINT16                  data_psm;
+    UINT8                   data_x_spec;
+    UINT8                   mcap_sup_procs;
+} tBTA_HL_SDP_INFO_IND;
+
+typedef struct
+{
+    tBTA_HL_STATUS          status;
+    tBTA_HL_APP_HANDLE      app_handle;
+    BD_ADDR                 bd_addr;
+    tBTA_HL_SDP             *p_sdp;
+} tBTA_HL_SDP_QUERY_CFM;
+
+typedef union
+{
+    tBTA_HL_REGISTER_CFM        reg_cfm;
+    tBTA_HL_DEREGISTER_CFM      dereg_cfm;
+    tBTA_HL_CCH_OPEN_IND        cch_open_ind;
+    tBTA_HL_CCH_OPEN_CFM        cch_open_cfm;
+    tBTA_HL_CCH_CLOSE_IND       cch_close_ind;
+    tBTA_HL_MCL_CFM             cch_close_cfm;
+    tBTA_HL_DCH_CREATE_IND      dch_create_ind;
+    tBTA_HL_DCH_OPEN_IND        dch_open_ind;
+    tBTA_HL_DCH_OPEN_CFM        dch_open_cfm;
+    tBTA_HL_DCH_CLOSE_IND       dch_close_ind;
+    tBTA_HL_MDL_CFM             dch_close_cfm;
+    tBTA_HL_DCH_OPEN_IND        dch_reconnect_ind;
+    tBTA_HL_DCH_OPEN_CFM        dch_reconnect_cfm;
+    tBTA_HL_MCL_IND             dch_abort_ind;
+    tBTA_HL_MCL_CFM             dch_abort_cfm;
+    tBTA_HL_DELETE_MDL_IND      delete_mdl_ind;
+    tBTA_HL_DELETE_MDL_CFM      delete_mdl_cfm;
+    tBTA_HL_MDL_CFM             dch_send_data_cfm;
+    tBTA_HL_MDL_IND             dch_rcv_data_ind;
+    tBTA_HL_DCH_CONG_IND        dch_cong_ind;
+    tBTA_HL_MCL_CFM             echo_test_cfm;
+    tBTA_HL_SDP_QUERY_CFM       sdp_query_cfm;
+    tBTA_HL_SDP_INFO_IND        sdp_info_ind;
+
+} tBTA_HL;
+
+/* HL callback functions */
+typedef void tBTA_HL_CTRL_CBACK(tBTA_HL_CTRL_EVT event, tBTA_HL_CTRL *p_data);
+typedef void tBTA_HL_CBACK(tBTA_HL_EVT event, tBTA_HL *p_data);
+
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**************************
+**  API Functions
+***************************/
+
+/*******************************************************************************
+**
+** Function         BTA_HlEnable
+**
+** Description      Enable the HL subsystems.  This function must be
+**                  called before any other functions in the HL API are called.
+**                  When the enable operation is completed the callback function
+**                  will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
+**
+** Parameters       p_cback - HL event call back function
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlEnable(tBTA_HL_CTRL_CBACK *p_ctrl_cback);
+/*******************************************************************************
+**
+** Function         BTA_HlDisable
+**
+** Description     Disable the HL subsystem.
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDisable(void);
+/*******************************************************************************
+**
+** Function         BTA_HlRegister
+**
+** Description      Register a HDP application
+**
+**
+** Parameters       app_id        - hdp application ID
+**                  p_reg_param   - non-platform related parameters for the
+**                                  HDP application
+**                  p_cback       - HL event callback fucntion
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlRegister(UINT8  app_id,
+                                       tBTA_HL_REG_PARAM *p_reg_param,
+                                       tBTA_HL_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_HlDeregister
+**
+** Description      Deregister an HDP application
+**
+** Parameters       app_handle - Application handle
+**
+** Returns         void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDeregister(tBTA_HL_APP_HANDLE app_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HlCchOpen
+**
+** Description      Open a Control channel connection with the specified BD address
+**                  and the control PSM value is used to select which
+**                  HDP insatnce should be used in case the peer device support
+**                  multiple HDP instances.
+**
+**
+** Parameters       app_handle - Application Handle
+**                  p_open_param - parameters for opening a control channel
+**
+** Returns          void
+**
+**                  Note: If the control PSM value is zero then the first HDP
+**                        instance is used for the control channel setup
+*******************************************************************************/
+    BTA_API extern void BTA_HlCchOpen(tBTA_HL_APP_HANDLE app_handle,
+                                      tBTA_HL_CCH_OPEN_PARAM *p_open_param);
+
+/*******************************************************************************
+**
+** Function         BTA_HlCchClose
+**
+** Description      Close a Control channel connection with the specified MCL
+**                  handle
+**
+** Parameters       mcl_handle - MCL handle
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern  void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchOpen
+**
+** Description      Open a data channel connection with the specified DCH parameters
+**
+** Parameters       mcl_handle - MCL handle
+**                  p_open_param - parameters for opening a data channel
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern  void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
+                                       tBTA_HL_DCH_OPEN_PARAM *p_open_param);
+/*******************************************************************************
+**
+** Function         BTA_HlDchReconnect
+**
+** Description      Reconnect a data channel with the specified MDL_ID
+**
+** Parameters       mcl_handle      - MCL handle
+*8                  p_recon_param   - parameters for reconnecting a data channel
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
+                                            tBTA_HL_DCH_RECONNECT_PARAM *p_recon_param);
+/*******************************************************************************
+**
+** Function         BTA_HlDchClose
+**
+** Description      Close a data channel with the specified MDL handle
+**
+** Parameters       mdl_handle  - MDL handle
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchAbort
+**
+** Description      Abort the current data channel setup with the specified MCL
+**                  handle
+**
+** Parameters       mcl_handle  - MCL handle
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle);
+
+/*******************************************************************************
+**
+** Function         BTA_HlSendData
+**
+** Description      Send an APDU to the peer device
+**
+** Parameters       mdl_handle  - MDL handle
+**                  pkt_size    - size of the data packet to be sent
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle,
+                                       UINT16           pkt_size);
+
+/*******************************************************************************
+**
+** Function         BTA_HlDeleteMdl
+**
+** Description      Delete the specified MDL_ID within the specified MCL handle
+**
+** Parameters       mcl_handle  - MCL handle
+**                  mdl_id      - MDL ID
+**
+** Returns          void
+**
+**                  note: If mdl_id = 0xFFFF then this means to delete all MDLs
+**                        and this value can only be used with DeleteMdl request only
+**                        not other requests
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle,
+                                        tBTA_HL_MDL_ID mdl_id );
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchEchoTest
+**
+** Description      Initiate an echo test with the specified MCL handle
+**
+** Parameters       mcl_handle           - MCL handle
+*8                  p_echo_test_param   -  parameters for echo testing
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDchEchoTest( tBTA_HL_MCL_HANDLE  mcl_handle,
+                                           tBTA_HL_DCH_ECHO_TEST_PARAM *p_echo_test_param);
+
+/*******************************************************************************
+**
+** Function         BTA_HlSdpQuery
+**
+** Description      SDP query request for the specified BD address
+**
+** Parameters       app_handle      - application handle
+**                  bd_addr         - BD address
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern  void BTA_HlSdpQuery(tBTA_HL_APP_HANDLE app_handle,
+                                        BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_HlDchCreateMdlRsp
+**
+** Description      Set the Response and configuration values for the Create MDL
+**                  request
+**
+** Parameters       mcl_handle  - MCL handle
+**                  p_rsp_param - parameters specified whether the request should
+**                                be accepted or not and if it should be accepted
+**                                then it also specified the configuration response
+**                                value
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
+                                           tBTA_HL_DCH_CREATE_RSP_PARAM *p_rsp_param);
+
+
+
+#ifdef __cplusplus
+
+}
+#endif
+
+#endif /* BTA_HL_API_H */
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/bta/include/bta_hl_ci.h b/bta/include/bta_hl_ci.h
new file mode 100644
index 0000000..4d3951c
--- /dev/null
+++ b/bta/include/bta_hl_ci.h
@@ -0,0 +1,125 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for the HL (HeaLth device profile) subsystem
+ *  call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_CI_H
+#define BTA_HL_CI_H
+
+#include "bta_api.h"
+#include "bta_hl_api.h"
+
+
+/*****************************************************************************
+**  Constants and Data Types
+*****************************************************************************/
+/**************************
+**  Common Definitions
+***************************/
+/* Read Ready Event */
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+/**************************
+**  Common Functions
+***************************/
+/*******************************************************************************
+**
+** Function         bta_hl_ci_get_tx_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_get_tx_data call-out function.
+**
+** Parameters       mdl_handle -MDL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern  void bta_hl_ci_get_tx_data(  tBTA_HL_MDL_HANDLE mdl_handle,
+                                             tBTA_HL_STATUS status,
+                                             UINT16 evt );
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_put_rx_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_put_rx_data call-out function.
+**
+** Parameters       mdl_handle -MDL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern  void bta_hl_ci_put_rx_data(  tBTA_HL_MDL_HANDLE mdl_handle,
+                                             tBTA_HL_STATUS status,
+                                             UINT16 evt );
+
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_get_echo_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_get_echo_data call-out function.
+**
+** Parameters       mcl_handle -MCL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern  void bta_hl_ci_get_echo_data(  tBTA_HL_MCL_HANDLE mcl_handle,
+                                               tBTA_HL_STATUS status,
+                                               UINT16 evt );
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_ci_put_echo_data
+**
+** Description      This function is called in response to the
+**                  bta_hl_co_put_echo_data call-out function.
+**
+** Parameters       mcl_handle -MCL handle
+**                  status - BTA_MA_STATUS_OK if operation is successful
+**                           BTA_MA_STATUS_FAIL if any errors have occurred.
+**                  evt    - evt from the call-out function
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_ci_put_echo_data(  tBTA_HL_MCL_HANDLE mcl_handle,
+                                              tBTA_HL_STATUS status,
+                                              UINT16 evt );
+#endif /* BTA_HL_CI_H */
+
+
diff --git a/bta/include/bta_hl_co.h b/bta/include/bta_hl_co.h
new file mode 100644
index 0000000..46f8290
--- /dev/null
+++ b/bta/include/bta_hl_co.h
@@ -0,0 +1,232 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This is the interface file for the HL (HeaLth device profile) subsystem
+ *  call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_HL_CO_H
+#define BTA_HL_CO_H
+
+#include "bta_api.h"
+#include "bta_hl_api.h"
+
+/*****************************************************************************
+**  Constants and Data Types
+*****************************************************************************/
+/**************************
+**  Common Definitions
+***************************/
+
+
+/*******************************************************************************
+**
+** Function        bta_hl_co_get_num_of_mdep
+**
+** Description     This function is called to get the number of MDEPs for this
+**                 application ID
+**
+** Parameters      app_id - application ID
+**                 p_num_of_mdep (output) - number of MDEP configurations supported
+**                                          by the application
+**
+** Returns         Bloolean - TRUE success
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_num_of_mdep(UINT8 app_id, UINT8 *p_num_of_mdep);
+/*******************************************************************************
+**
+** Function        bta_hl_co_advrtise_source_sdp
+**
+** Description     This function is called to find out whether the SOURCE MDEP
+**                 configuration information should be advertize in the SDP or nopt
+**
+** Parameters      app_id - application ID
+**
+** Returns         Bloolean - TRUE advertise the SOURCE MDEP configuration
+**                            information
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_advrtise_source_sdp(UINT8 app_id);
+/*******************************************************************************
+**
+** Function        bta_hl_co_get_mdep_config
+**
+** Description     This function is called to get the supported feature
+**                 configuration for the specified mdep index and it also assigns
+**                 the MDEP ID for the specified mdep index
+**
+** Parameters      app_id - HDP application ID
+**                 mdep_idx - the mdep index
+**                 mdep_id  - the assigned MDEP ID for the specified medp_idx
+**                 p_mdl_cfg (output) - pointer to the MDEP configuration
+**
+**
+** Returns         Bloolean - TRUE success
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_mdep_config(UINT8 app_id,
+                                                 UINT8 mdep_idx,
+                                                 tBTA_HL_MDEP_ID mdep_id,
+                                                 tBTA_HL_MDEP_CFG *p_mdep_cfg);
+
+
+/*******************************************************************************
+**
+** Function        bta_hl_co_get_echo_config
+**
+** Description     This function is called to get the echo test
+**                 maximum APDU size configuration
+**
+** Parameters      app_id - HDP application ID
+**                 p_echo_cfg (output) - pointer to the Echo test maximum APDU size
+**                                       configuration
+**
+** Returns         Bloolean - TRUE success
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_get_echo_config(UINT8  app_id,
+                                                 tBTA_HL_ECHO_CFG *p_echo_cfg);
+
+
+/*******************************************************************************
+**
+** Function        bta_hl_co_save_mdl
+**
+** Description     This function is called to save a MDL configuration item in persistent
+**                 storage
+**
+** Parameters      app_id - HDP application ID
+**                 item_idx - the MDL configuration storage index
+**                 p_mdl_cfg - pointer to the MDL configuration data
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_save_mdl(UINT8 app_id, UINT8 item_idx, tBTA_HL_MDL_CFG *p_mdl_cfg );
+/*******************************************************************************
+**
+** Function        bta_hl_co_delete_mdl
+**
+** Description     This function is called to delete a MDL configuration item in persistent
+**                 storage
+**
+** Parameters      app_id - HDP application ID
+**                 item_idx - the MDL configuration storage index
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_delete_mdl(UINT8 app_id, UINT8 item_idx);
+/*******************************************************************************
+**
+** Function         bta_hl_co_get_mdl_config
+**
+** Description     This function is called to get the MDL configuration
+**                 from teh persistent memory. This function shall only be called
+*8                 once after the device is powered up
+**
+** Parameters      app_id - HDP application ID
+**                 buffer_size - the unit of the buffer size is sizeof(tBTA_HL_MDL_CFG)
+**                 p_mdl_buf - Point to the starting location of the buffer
+**
+** Returns         BOOLEAN
+**
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN bta_hl_co_load_mdl_config (UINT8 app_id, UINT8 buffer_size,
+                                                  tBTA_HL_MDL_CFG *p_mdl_buf );
+
+
+/*******************************************************************************
+**
+** Function         bta_hl_co_get_tx_data
+**
+** Description     Get the data to be sent
+**
+** Parameters      app_id - HDP application ID
+**                 mdl_handle - MDL handle
+**                 buf_size - the size of the buffer
+**                 p_buf - the buffer pointer
+**                 evt - the evt to be passed back to the HL in the
+**                       bta_hl_ci_get_tx_data call-in function
+**
+** Returns        Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_get_tx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+                                           UINT16 buf_size, UINT8 *p_buf, UINT16 evt);
+
+
+/*******************************************************************************
+**
+** Function        bta_hl_co_put_rx_data
+**
+** Description     Put the received data
+**
+** Parameters      app_id - HDP application ID
+**                 mdl_handle - MDL handle
+**                 data_size - the size of the data
+**                 p_data - the data pointer
+**                 evt - the evt to be passed back to the HL in the
+**                       bta_hl_ci_put_rx_data call-in function
+**
+** Returns        Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_put_rx_data (UINT8 app_id, tBTA_HL_MDL_HANDLE mdl_handle,
+                                           UINT16 data_size, UINT8 *p_data, UINT16 evt);
+/*******************************************************************************
+**
+** Function         bta_hl_co_get_tx_data
+**
+** Description     Get the Echo data to be sent
+**
+** Parameters      app_id - HDP application ID
+**                 mcl_handle - MCL handle
+**                 buf_size - the size of the buffer
+**                 p_buf - the buffer pointer
+**                 evt - the evt to be passed back to the HL in the
+**                       bta_hl_ci_get_tx_data call-in function
+**
+** Returns        Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_get_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+                                             UINT16 buf_size, UINT8 *p_buf, UINT16 evt);
+
+/*******************************************************************************
+**
+** Function        bta_hl_co_put_echo_data
+**
+** Description     Put the received loopback echo data
+**
+** Parameters      app_id - HDP application ID
+**                 mcl_handle - MCL handle
+**                 data_size - the size of the data
+**                 p_data - the data pointer
+**                 evt - the evt to be passed back to the HL in the
+**                       bta_hl_ci_put_echo_data call-in function
+**
+** Returns        Void
+**
+*******************************************************************************/
+BTA_API extern void bta_hl_co_put_echo_data (UINT8 app_id, tBTA_HL_MCL_HANDLE mcl_handle,
+                                             UINT16 data_size, UINT8 *p_data, UINT16 evt);
+
+#endif /* BTA_HL_CO_H */
diff --git a/bta/include/bta_jv_api.h b/bta/include/bta_jv_api.h
new file mode 100644
index 0000000..73a9164
--- /dev/null
+++ b/bta/include/bta_jv_api.h
@@ -0,0 +1,1122 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file the BTA Java I/F
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_API_H
+#define BTA_JV_API_H
+
+#include "data_types.h"
+#include "bt_target.h"
+#include "bt_types.h"
+#include "bta_api.h"
+#include "btm_api.h"
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/* status values */
+#define BTA_JV_SUCCESS             0            /* Successful operation. */
+#define BTA_JV_FAILURE             1            /* Generic failure. */
+#define BTA_JV_BUSY                2            /* Temporarily can not handle this request. */
+#define BTA_JV_NO_DATA             3            /* no data. */
+
+typedef UINT8 tBTA_JV_STATUS;
+#define BTA_JV_INTERNAL_ERR        (-1) /* internal error. */
+
+#define BTA_JV_MAX_UUIDS        SDP_MAX_UUID_FILTERS
+#define BTA_JV_MAX_ATTRS        SDP_MAX_ATTR_FILTERS
+#define BTA_JV_MAX_SDP_REC      SDP_MAX_RECORDS
+#if SDP_FOR_JV_INCLUDED == TRUE
+#define BTA_JV_MAX_L2C_CONN     (GAP_MAX_CONNECTIONS + 1)
+#else
+#define BTA_JV_MAX_L2C_CONN     GAP_MAX_CONNECTIONS
+#endif
+#define BTA_JV_MAX_SCN          PORT_MAX_RFC_PORTS /* same as BTM_MAX_SCN (in btm_int.h) */
+#define BTA_JV_MAX_RFC_CONN     MAX_RFC_PORTS
+
+#ifndef BTA_JV_DEF_RFC_MTU
+#define BTA_JV_DEF_RFC_MTU      (3*330)
+#endif
+
+/* */
+#ifndef BTA_JV_MAX_RFC_SR_SESSION
+#define BTA_JV_MAX_RFC_SR_SESSION   3
+#endif
+
+/* BTA_JV_MAX_RFC_SR_SESSION can not be bigger than MAX_BD_CONNECTIONS */
+#if (BTA_JV_MAX_RFC_SR_SESSION > MAX_BD_CONNECTIONS)
+#undef BTA_JV_MAX_RFC_SR_SESSION
+#define BTA_JV_MAX_RFC_SR_SESSION   MAX_BD_CONNECTIONS
+#endif
+
+#define BTA_JV_FIRST_SERVICE_ID BTA_FIRST_JV_SERVICE_ID
+#define BTA_JV_LAST_SERVICE_ID  BTA_LAST_JV_SERVICE_ID
+#define BTA_JV_NUM_SERVICE_ID   (BTA_LAST_JV_SERVICE_ID - BTA_FIRST_JV_SERVICE_ID + 1)
+
+/* Discoverable modes */
+enum
+{
+    BTA_JV_DISC_NONE,
+    BTA_JV_DISC_LIMITED,
+    BTA_JV_DISC_GENERAL
+};
+typedef UINT16 tBTA_JV_DISC;
+
+/* Security Mode (BTA_JvGetSecurityMode) */
+#define BTA_JV_SEC_MODE_UNDEFINED   BTM_SEC_MODE_UNDEFINED  /* 0 */
+#define BTA_JV_SEC_MODE_NONE        BTM_SEC_MODE_NONE       /* 1 */
+#define BTA_JV_SEC_MODE_SERVICE     BTM_SEC_MODE_SERVICE    /* 2 */
+#define BTA_JV_SEC_MODE_LINK        BTM_SEC_MODE_LINK       /* 3 */
+#define BTA_JV_SEC_MODE_SP          BTM_SEC_MODE_SP         /* 4 */
+#define BTA_JV_SEC_MODE_SP_DEBUG    BTM_SEC_MODE_SP_DEBUG   /* 5 */
+typedef UINT8 tBTA_JV_SEC_MODE;
+
+#define BTA_JV_ROLE_SLAVE       BTM_ROLE_SLAVE
+#define BTA_JV_ROLE_MASTER      BTM_ROLE_MASTER
+typedef UINT32 tBTA_JV_ROLE;
+
+#define BTA_JV_SERVICE_LMTD_DISCOVER    BTM_COD_SERVICE_LMTD_DISCOVER   /* 0x0020 */
+#define BTA_JV_SERVICE_POSITIONING      BTM_COD_SERVICE_POSITIONING     /* 0x0100 */
+#define BTA_JV_SERVICE_NETWORKING       BTM_COD_SERVICE_NETWORKING      /* 0x0200 */
+#define BTA_JV_SERVICE_RENDERING        BTM_COD_SERVICE_RENDERING       /* 0x0400 */
+#define BTA_JV_SERVICE_CAPTURING        BTM_COD_SERVICE_CAPTURING       /* 0x0800 */
+#define BTA_JV_SERVICE_OBJ_TRANSFER     BTM_COD_SERVICE_OBJ_TRANSFER    /* 0x1000 */
+#define BTA_JV_SERVICE_AUDIO            BTM_COD_SERVICE_AUDIO           /* 0x2000 */
+#define BTA_JV_SERVICE_TELEPHONY        BTM_COD_SERVICE_TELEPHONY       /* 0x4000 */
+#define BTA_JV_SERVICE_INFORMATION      BTM_COD_SERVICE_INFORMATION     /* 0x8000 */
+
+
+
+/* Java I/F callback events */
+/* events received by tBTA_JV_DM_CBACK */
+#define BTA_JV_ENABLE_EVT           0  /* JV enabled */
+#define BTA_JV_SET_DISCOVER_EVT     1  /* the result for BTA_JvSetDiscoverability */
+#define BTA_JV_LOCAL_ADDR_EVT       2  /* Local device address */
+#define BTA_JV_LOCAL_NAME_EVT       3  /* Local device name */
+#define BTA_JV_REMOTE_NAME_EVT      4  /* Remote device name */
+#define BTA_JV_SET_ENCRYPTION_EVT   5  /* Set Encryption */
+#define BTA_JV_GET_SCN_EVT          6  /* Reserved an SCN */
+#define BTA_JV_GET_PSM_EVT          7  /* Reserved a PSM */
+#define BTA_JV_DISCOVERY_COMP_EVT   8  /* SDP discovery complete */
+#define BTA_JV_SERVICES_LEN_EVT     9  /* the result for BTA_JvGetServicesLength */
+#define BTA_JV_SERVICE_SEL_EVT      10 /* the result for BTA_JvServiceSelect */
+#define BTA_JV_CREATE_RECORD_EVT    11 /* the result for BTA_JvCreateRecord */
+#define BTA_JV_UPDATE_RECORD_EVT    12 /* the result for BTA_JvUpdateRecord */
+#define BTA_JV_ADD_ATTR_EVT         13 /* the result for BTA_JvAddAttribute */
+#define BTA_JV_DELETE_ATTR_EVT      14 /* the result for BTA_JvDeleteAttribute */
+#define BTA_JV_CANCEL_DISCVRY_EVT   15 /* the result for BTA_JvCancelDiscovery */
+
+/* events received by tBTA_JV_L2CAP_CBACK */
+#define BTA_JV_L2CAP_OPEN_EVT       16 /* open status of L2CAP connection */
+#define BTA_JV_L2CAP_CLOSE_EVT      17 /* L2CAP connection closed */
+#define BTA_JV_L2CAP_START_EVT      18 /* L2CAP server started */
+#define BTA_JV_L2CAP_CL_INIT_EVT    19 /* L2CAP client initiated a connection */
+#define BTA_JV_L2CAP_DATA_IND_EVT   20 /* L2CAP connection received data */
+#define BTA_JV_L2CAP_CONG_EVT       21 /* L2CAP connection congestion status changed */
+#define BTA_JV_L2CAP_READ_EVT       22 /* the result for BTA_JvL2capRead */
+#define BTA_JV_L2CAP_RECEIVE_EVT    23 /* the result for BTA_JvL2capReceive*/
+#define BTA_JV_L2CAP_WRITE_EVT      24 /* the result for BTA_JvL2capWrite*/
+
+/* events received by tBTA_JV_RFCOMM_CBACK */
+#define BTA_JV_RFCOMM_OPEN_EVT      25 /* open status of RFCOMM Client connection */
+#define BTA_JV_RFCOMM_CLOSE_EVT     26 /* RFCOMM connection closed */
+#define BTA_JV_RFCOMM_START_EVT     27 /* RFCOMM server started */
+#define BTA_JV_RFCOMM_CL_INIT_EVT   28 /* RFCOMM client initiated a connection */
+#define BTA_JV_RFCOMM_DATA_IND_EVT  29 /* RFCOMM connection received data */
+#define BTA_JV_RFCOMM_CONG_EVT      30 /* RFCOMM connection congestion status changed */
+#define BTA_JV_RFCOMM_READ_EVT      31 /* the result for BTA_JvRfcommRead */
+#define BTA_JV_RFCOMM_WRITE_EVT     32 /* the result for BTA_JvRfcommWrite*/
+#define BTA_JV_RFCOMM_SRV_OPEN_EVT  33 /* open status of Server RFCOMM connection */
+#define BTA_JV_MAX_EVT              34 /* max number of JV events */
+
+typedef UINT16 tBTA_JV_EVT;
+
+/* data associated with BTA_JV_SET_DISCOVER_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    tBTA_JV_DISC    disc_mode;  /* The current discoverable mode */
+} tBTA_JV_SET_DISCOVER;
+
+/* data associated with BTA_JV_DISCOVERY_COMP_EVT_ */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    int scn;                    /* channel # */
+} tBTA_JV_DISCOVERY_COMP;
+
+/* data associated with BTA_JV_SET_ENCRYPTION_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    BD_ADDR     bd_addr;        /* The peer address */
+} tBTA_JV_SET_ENCRYPTION;
+
+/* data associated with BTA_JV_SERVICES_LEN_EVT */
+typedef struct
+{
+    INT32       num_services;       /* -1, if error. Otherwise, the number of
+                                     * services collected from peer */
+    UINT16      *p_services_len;    /* this points the same location as the
+                                     * parameter in BTA_JvGetServicesLength() */
+} tBTA_JV_SERVICES_LEN;
+
+/* data associated with BTA_JV_SERVICE_SEL_EVT */
+typedef struct
+{
+    BD_ADDR     bd_addr;            /* The peer address */
+    UINT16      service_len;        /* the length of this record */
+} tBTA_JV_SERVICE_SEL;
+
+/* data associated with BTA_JV_CREATE_RECORD_EVT */
+typedef struct
+{
+   tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+} tBTA_JV_CREATE_RECORD;
+
+/* data associated with BTA_JV_UPDATE_RECORD_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The SDP record handle was updated */
+} tBTA_JV_UPDATE_RECORD;
+
+/* data associated with BTA_JV_ADD_ATTR_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The SDP record handle was updated */
+} tBTA_JV_ADD_ATTR;
+
+/* data associated with BTA_JV_DELETE_ATTR_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The SDP record handle was updated */
+} tBTA_JV_DELETE_ATTR;
+
+/* data associated with BTA_JV_L2CAP_OPEN_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    BD_ADDR         rem_bda;    /* The peer address */
+    INT32           tx_mtu;     /* The transmit MTU */
+} tBTA_JV_L2CAP_OPEN;
+
+/* data associated with BTA_JV_L2CAP_CLOSE_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    BOOLEAN         async;      /* FALSE, if local initiates disconnect */
+} tBTA_JV_L2CAP_CLOSE;
+
+/* data associated with BTA_JV_L2CAP_START_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT8           sec_id;     /* security ID used by this server */
+} tBTA_JV_L2CAP_START;
+
+/* data associated with BTA_JV_L2CAP_CL_INIT_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT8           sec_id;     /* security ID used by this client */
+} tBTA_JV_L2CAP_CL_INIT;
+
+/* data associated with BTA_JV_L2CAP_CONG_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    BOOLEAN         cong;       /* TRUE, congested. FALSE, uncongested */
+} tBTA_JV_L2CAP_CONG;
+
+/* data associated with BTA_JV_L2CAP_READ_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT32          req_id;     /* The req_id in the associated BTA_JvL2capRead() */
+    UINT8           *p_data;    /* This points the same location as the p_data
+                                 * parameter in BTA_JvL2capRead () */
+    UINT16          len;        /* The length of the data read. */
+} tBTA_JV_L2CAP_READ;
+
+/* data associated with BTA_JV_L2CAP_RECEIVE_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT32          req_id;     /* The req_id in the associated BTA_JvL2capReceive() */
+    UINT8           *p_data;    /* This points the same location as the p_data
+                                 * parameter in BTA_JvL2capReceive () */
+    UINT16          len;        /* The length of the data read. */
+} tBTA_JV_L2CAP_RECEIVE;
+
+/* data associated with BTA_JV_L2CAP_WRITE_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT32          req_id;     /* The req_id in the associated BTA_JvL2capWrite() */
+    UINT16          len;        /* The length of the data written. */
+    BOOLEAN         cong;       /* congestion status */
+} tBTA_JV_L2CAP_WRITE;
+
+/* data associated with BTA_JV_RFCOMM_OPEN_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    BD_ADDR         rem_bda;    /* The peer address */
+} tBTA_JV_RFCOMM_OPEN;
+/* data associated with BTA_JV_RFCOMM_SRV_OPEN_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;             /* Whether the operation succeeded or failed. */
+    UINT32          handle;             /* The connection handle */
+    UINT32          new_listen_handle;  /* The new listen handle */
+    BD_ADDR         rem_bda;            /* The peer address */
+} tBTA_JV_RFCOMM_SRV_OPEN;
+
+
+/* data associated with BTA_JV_RFCOMM_CLOSE_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;      /* Whether the operation succeeded or failed. */
+    UINT32          port_status; /* PORT status */
+    UINT32          handle;      /* The connection handle */
+    BOOLEAN         async;       /* FALSE, if local initiates disconnect */
+} tBTA_JV_RFCOMM_CLOSE;
+
+/* data associated with BTA_JV_RFCOMM_START_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT8           sec_id;     /* security ID used by this server */
+    BOOLEAN         use_co;     /* TRUE to use co_rfc_data */
+} tBTA_JV_RFCOMM_START;
+
+/* data associated with BTA_JV_RFCOMM_CL_INIT_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT8           sec_id;     /* security ID used by this client */
+    BOOLEAN         use_co;     /* TRUE to use co_rfc_data */
+} tBTA_JV_RFCOMM_CL_INIT;
+/*data associated with BTA_JV_L2CAP_DATA_IND_EVT & BTA_JV_RFCOMM_DATA_IND_EVT */
+typedef struct
+{
+    UINT32          handle;     /* The connection handle */
+} tBTA_JV_DATA_IND;
+
+/* data associated with BTA_JV_RFCOMM_CONG_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    BOOLEAN         cong;       /* TRUE, congested. FALSE, uncongested */
+} tBTA_JV_RFCOMM_CONG;
+
+/* data associated with BTA_JV_RFCOMM_READ_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT32          req_id;     /* The req_id in the associated BTA_JvRfcommRead() */
+    UINT8           *p_data;    /* This points the same location as the p_data
+                                 * parameter in BTA_JvRfcommRead () */
+    UINT16          len;        /* The length of the data read. */
+} tBTA_JV_RFCOMM_READ;
+
+/* data associated with BTA_JV_RFCOMM_WRITE_EVT */
+typedef struct
+{
+    tBTA_JV_STATUS  status;     /* Whether the operation succeeded or failed. */
+    UINT32          handle;     /* The connection handle */
+    UINT32          req_id;     /* The req_id in the associated BTA_JvRfcommWrite() */
+    int             len;        /* The length of the data written. */
+    BOOLEAN         cong;       /* congestion status */
+} tBTA_JV_RFCOMM_WRITE;
+
+
+/* union of data associated with JV callback */
+typedef union
+{
+    tBTA_JV_STATUS          status;         /* BTA_JV_ENABLE_EVT */
+    tBTA_JV_DISCOVERY_COMP  disc_comp;      /* BTA_JV_DISCOVERY_COMP_EVT */
+    tBTA_JV_SET_DISCOVER    set_discover;   /* BTA_JV_SET_DISCOVER_EVT */
+    tBTA_JV_SET_ENCRYPTION  set_encrypt;    /* BTA_JV_SET_ENCRYPTION_EVT */
+    BD_ADDR                 bd_addr;        /* BTA_JV_LOCAL_ADDR_EVT */
+    UINT8                   *p_name;        /* BTA_JV_LOCAL_NAME_EVT,
+                                               BTA_JV_REMOTE_NAME_EVT */
+    UINT8                   scn;            /* BTA_JV_GET_SCN_EVT */
+    UINT16                  psm;            /* BTA_JV_GET_PSM_EVT */
+    tBTA_JV_SERVICES_LEN    servs_len;      /* BTA_JV_SERVICES_LEN_EVT */
+    tBTA_JV_SERVICE_SEL     serv_sel;       /* BTA_JV_SERVICE_SEL_EVT */
+    tBTA_JV_CREATE_RECORD   create_rec;     /* BTA_JV_CREATE_RECORD_EVT */
+    tBTA_JV_UPDATE_RECORD   update_rec;     /* BTA_JV_UPDATE_RECORD_EVT */
+    tBTA_JV_ADD_ATTR        add_attr;       /* BTA_JV_ADD_ATTR_EVT */
+    tBTA_JV_DELETE_ATTR     del_attr;       /* BTA_JV_DELETE_ATTR_EVT */
+    tBTA_JV_L2CAP_OPEN      l2c_open;       /* BTA_JV_L2CAP_OPEN_EVT */
+    tBTA_JV_L2CAP_CLOSE     l2c_close;      /* BTA_JV_L2CAP_CLOSE_EVT */
+    tBTA_JV_L2CAP_START     l2c_start;      /* BTA_JV_L2CAP_START_EVT */
+    tBTA_JV_L2CAP_CL_INIT   l2c_cl_init;    /* BTA_JV_L2CAP_CL_INIT_EVT */
+    tBTA_JV_L2CAP_CONG      l2c_cong;       /* BTA_JV_L2CAP_CONG_EVT */
+    tBTA_JV_L2CAP_READ      l2c_read;       /* BTA_JV_L2CAP_READ_EVT */
+    tBTA_JV_L2CAP_WRITE     l2c_write;      /* BTA_JV_L2CAP_WRITE_EVT */
+    tBTA_JV_RFCOMM_OPEN     rfc_open;       /* BTA_JV_RFCOMM_OPEN_EVT */
+    tBTA_JV_RFCOMM_SRV_OPEN rfc_srv_open;   /* BTA_JV_RFCOMM_SRV_OPEN_EVT */
+    tBTA_JV_RFCOMM_CLOSE    rfc_close;      /* BTA_JV_RFCOMM_CLOSE_EVT */
+    tBTA_JV_RFCOMM_START    rfc_start;      /* BTA_JV_RFCOMM_START_EVT */
+    tBTA_JV_RFCOMM_CL_INIT  rfc_cl_init;    /* BTA_JV_RFCOMM_CL_INIT_EVT */
+    tBTA_JV_RFCOMM_CONG     rfc_cong;       /* BTA_JV_RFCOMM_CONG_EVT */
+    tBTA_JV_RFCOMM_READ     rfc_read;       /* BTA_JV_RFCOMM_READ_EVT */
+    tBTA_JV_RFCOMM_WRITE    rfc_write;      /* BTA_JV_RFCOMM_WRITE_EVT */
+    tBTA_JV_DATA_IND        data_ind;    /* BTA_JV_L2CAP_DATA_IND_EVT
+                                               BTA_JV_RFCOMM_DATA_IND_EVT */
+} tBTA_JV;
+
+/* JAVA DM Interface callback */
+typedef void (tBTA_JV_DM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void * user_data);
+
+/* JAVA RFCOMM interface callback */
+typedef void* (tBTA_JV_RFCOMM_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data, void *user_data);
+
+/* JAVA L2CAP interface callback */
+typedef void (tBTA_JV_L2CAP_CBACK)(tBTA_JV_EVT event, tBTA_JV *p_data);
+
+/* JV configuration structure */
+typedef struct
+{
+    UINT16  sdp_raw_size;           /* The size of p_sdp_raw_data */
+    UINT16  sdp_db_size;            /* The size of p_sdp_db */
+    UINT8   *p_sdp_raw_data;        /* The data buffer to keep raw data */
+    tSDP_DISCOVERY_DB   *p_sdp_db;  /* The data buffer to keep SDP database */
+} tBTA_JV_CFG;
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_JvEnable
+**
+** Description      Enable the Java I/F service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_JV_ENABLE_EVT. This function must
+**                  be called before other functions in the JV API are
+**                  called.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_JvDisable
+**
+** Description      Disable the Java I/F
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_JvDisable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsEnable
+**
+** Description      Get the JV registration status.
+**
+** Returns          TRUE, if registered
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsEnable(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetDiscoverability
+**
+** Description      This function sets the Bluetooth  discoverable modes
+**                  of the local device.  This controls whether other
+**                  Bluetooth devices can find the local device.
+**
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_SET_DISCOVER_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetDiscoverability
+**
+** Description      This function gets the Bluetooth
+**                  discoverable modes of local device
+**
+** Returns          The current Bluetooth discoverable mode.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_DISC BTA_JvGetDiscoverability(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetLocalDeviceAddr
+**
+** Description      This function obtains the local Bluetooth device address.
+**                  The local Bluetooth device address is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetLocalDeviceName
+**
+** Description      This function obtains the name of the local device
+**                  The local Bluetooth device name is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetRemoteDeviceName
+**
+** Description      This function obtains the name of the specified device.
+**                  The Bluetooth device name is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetPreknownDevice
+**
+** Description      This function obtains the Bluetooth address in the inquiry
+**                  database collected via the previous call to BTA_DmSearch().
+**
+** Returns          The number of preknown devices if p_bd_addr is NULL
+**                  BTA_JV_SUCCESS if successful.
+**                  BTA_JV_INTERNAL_ERR(-1) if internal failure.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetDeviceClass
+**
+** Description      This function obtains the local Class of Device.
+**
+** Returns          DEV_CLASS, A three-byte array of UINT8 that contains the
+**                  Class of Device information. The definitions are in the
+**                  "Bluetooth Assigned Numbers".
+**
+*******************************************************************************/
+BTA_API extern UINT8 * BTA_JvGetDeviceClass(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetServiceClass
+**
+** Description      This function sets the service class of local Class of Device
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service);
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetEncryption
+**
+** Description      This function ensures that the connection to the given device
+**                  is encrypted.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_SET_ENCRYPTION_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsAuthenticated
+**
+** Description      This function checks if the peer device is authenticated
+**
+** Returns          TRUE if authenticated.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsTrusted
+**
+** Description      This function checks if the peer device is trusted
+**                  (previously paired)
+**
+** Returns          TRUE if trusted.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsAuthorized
+**
+** Description      This function checks if the peer device is authorized
+**
+** Returns          TRUE if authorized.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsEncrypted
+**
+** Description      This function checks if the link to peer device is encrypted
+**
+** Returns          TRUE if encrypted.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BTA_API extern BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetSecurityMode
+**
+** Description      This function returns the current Bluetooth security mode
+**                  of the local device
+**
+** Returns          The current Bluetooth security mode.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void);
+
+/* BTA_JvIsMaster is replaced by BTA_DmIsMaster */
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetSCN
+**
+** Description      This function reserves a SCN (server channel number) for
+**                  applications running over RFCOMM. It is primarily called by
+**                  server profiles/applications to register their SCN into the
+**                  SDP database. The SCN is reported by the tBTA_JV_DM_CBACK
+**                  callback with a BTA_JV_GET_SCN_EVT.
+**                  If the SCN reported is 0, that means all SCN resources are
+**                  exhausted.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetSCN(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvFreeSCN
+**
+** Description      This function frees a server channel number that was used
+**                  by an application running over RFCOMM.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetPSM
+**
+** Description      This function reserves a PSM (Protocol Service Multiplexer)
+**                  applications running over L2CAP. It is primarily called by
+**                  server profiles/applications to register their PSM into the
+**                  SDP database.
+**
+** Returns          The next free PSM
+**
+*******************************************************************************/
+BTA_API extern UINT16 BTA_JvGetPSM(void);
+
+/*******************************************************************************
+**
+** Function         BTA_JvStartDiscovery
+**
+** Description      This function performs service discovery for the services
+**                  provided by the given peer device. When the operation is
+**                  complete the tBTA_JV_DM_CBACK callback function will be
+**                  called with a BTA_JV_DISCOVERY_COMP_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid,
+                           tSDP_UUID *p_uuid_list, void* user_data);
+
+/*******************************************************************************
+**
+** Function         BTA_JvCancelDiscovery
+**
+** Description      This function cancels an active service discovery.
+**                  When the operation is
+**                  complete the tBTA_JV_DM_CBACK callback function will be
+**                  called with a BTA_JV_CANCEL_DISCVRY_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetServicesLength
+**
+** Description      This function obtains the number of services and the length
+**                  of each service found in the SDP database (result of last
+**                  BTA_JvStartDiscovery().When the operation is complete the
+**                  tBTA_JV_DM_CBACK callback function will be called with a
+**                  BTA_JV_SERVICES_LEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetServicesResult
+**
+** Description      This function returns a number of service records found
+**                  during current service search, equals to the number returned
+**                  by previous call to BTA_JvGetServicesLength.
+**                  The contents of each SDP record will be returned under a
+**                  TLV (type, len, value) representation in the data buffer
+**                  provided by the caller.
+**
+** Returns          -1, if error. Otherwise, the number of services
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs);
+
+/*******************************************************************************
+**
+** Function         BTA_JvServiceSelect
+**
+** Description      This function checks if the SDP database contains the given
+**                  service UUID. When the operation is complete the
+**                  tBTA_JV_DM_CBACK callback function will be called with a
+**                  BTA_JV_SERVICE_SEL_EVT with the length of the service record.
+**                  If the service is not found or error, -1 is reported.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid);
+
+/*******************************************************************************
+**
+** Function         BTA_JvServiceResult
+**
+** Description      This function returns the contents of the SDP record from
+**                  last BTA_JvServiceSelect. The contents will be returned under
+**                  a TLV (type, len, value) representation in the data buffer
+**                  provided by the caller.
+**
+** Returns          -1, if error. Otherwise, the length of service record.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvServiceResult(UINT8 *TLV);
+
+/*******************************************************************************
+**
+** Function         BTA_JvCreateRecord
+**
+** Description      Create a service record in the local SDP database by user in
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_CREATE_RECORD_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvCreateRecordByUser(void* user_data);
+
+/*******************************************************************************
+**
+** Function         BTA_JvUpdateRecord
+**
+** Description      Update a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_UPDATE_RECORD_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids,
+                           UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvAddAttribute
+**
+** Description      Add an attribute to a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_ADD_ATTR_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id,
+                           UINT8 *p_value, INT32 value_size);
+
+/*******************************************************************************
+**
+** Function         BTA_JvDeleteAttribute
+**
+** Description      Delete an attribute from a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_DELETE_ATTR_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id);
+
+/*******************************************************************************
+**
+** Function         BTA_JvDeleteRecord
+**
+** Description      Delete a service record in the local SDP database.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_JvReadRecord
+**
+** Description      Read a service record in the local SDP database.
+**
+** Returns          -1, if the record is not found.
+**                  Otherwise, the offset (0 or 1) to start of data in p_data.
+**
+**                  The size of data copied into p_data is in *p_data_len.
+**
+*******************************************************************************/
+BTA_API extern INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capConnect
+**
+** Description      Initiate a connection as a L2CAP client to the given BD
+**                  Address.
+**                  When the connection is initiated or failed to initiate,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT
+**                  When the connection is established or failed,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role,  UINT16 remote_psm, UINT16 rx_mtu,
+                           BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capClose
+**
+** Description      This function closes an L2CAP client connection
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capStartServer
+**
+** Description      This function starts an L2CAP server and listens for an L2CAP
+**                  connection from a remote Bluetooth device.  When the server
+**                  is started successfully, tBTA_JV_L2CAP_CBACK is called with
+**                  BTA_JV_L2CAP_START_EVT.  When the connection is established,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+                           UINT16 local_psm, UINT16 rx_mtu,
+                           tBTA_JV_L2CAP_CBACK *p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capStopServer
+**
+** Description      This function stops the L2CAP server. If the server has an
+**                  active connection, it would be closed.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capRead
+**
+** Description      This function reads data from an L2CAP connection
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_READ_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id,
+                                              UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capReceive
+**
+** Description      This function reads data from an L2CAP connection
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_RECEIVE_EVT.
+**                  If there are more data queued in L2CAP than len, the extra data will be discarded.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id,
+                                              UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capReady
+**
+** Description      This function determined if there is data to read from
+**                  an L2CAP connection
+**
+** Returns          BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+**                  BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size);
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capWrite
+**
+** Description      This function writes data to an L2CAP connection
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_WRITE_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id,
+                                               UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommConnect
+**
+** Description      This function makes an RFCOMM conection to a remote BD
+**                  Address.
+**                  When the connection is initiated or failed to initiate,
+**                  tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT
+**                  When the connection is established or failed,
+**                  tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr,
+                           tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommClose
+**
+** Description      This function closes an RFCOMM connection
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommStartServer
+**
+** Description      This function starts listening for an RFCOMM connection
+**                  request from a remote Bluetooth device.  When the server is
+**                  started successfully, tBTA_JV_RFCOMM_CBACK is called
+**                  with BTA_JV_RFCOMM_START_EVT.
+**                  When the connection is established, tBTA_JV_RFCOMM_CBACK
+**                  is called with BTA_JV_RFCOMM_OPEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session,
+                           tBTA_JV_RFCOMM_CBACK *p_cback, void *user_data);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommStopServer
+**
+** Description      This function stops the RFCOMM server. If the server has an
+**                  active connection, it would be closed.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommRead
+**
+** Description      This function reads data from an RFCOMM connection
+**                  When the operation is complete, tBTA_JV_RFCOMM_CBACK is
+**                  called with BTA_JV_RFCOMM_READ_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id,
+                                               UINT8 *p_data, UINT16 len);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommReady
+**
+** Description      This function determined if there is data to read from
+**                  an RFCOMM connection
+**
+** Returns          BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+**                  BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size);
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommWrite
+**
+** Description      This function writes data to an RFCOMM connection
+**                  When the operation is complete, tBTA_JV_RFCOMM_CBACK is
+**                  called with BTA_JV_RFCOMM_WRITE_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+BTA_API extern tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id);
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommGetPortHdl
+**
+** Description    This function fetches the rfcomm port handle
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_JV_API_H */
+
diff --git a/bta/include/bta_jv_co.h b/bta/include/bta_jv_co.h
new file mode 100644
index 0000000..098766c
--- /dev/null
+++ b/bta/include/bta_jv_co.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2007-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 is the interface file for java interface call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_CO_H
+#define BTA_JV_CO_H
+
+#include "bta_jv_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function         bta_jv_co_rfc_data
+**
+** Description      This function is called by JV to send data to the java glue
+**                  code when the RX data path is configured to use a call-out
+**
+** Returns          void
+**
+*******************************************************************************/
+
+BTA_API extern int bta_co_rfc_data_incoming(void *user_data, BT_HDR *p_buf);
+BTA_API extern int bta_co_rfc_data_outgoing_size(void *user_data, int *size);
+BTA_API extern int bta_co_rfc_data_outgoing(void *user_data, UINT8* buf, UINT16 size);
+
+#endif /* BTA_DG_CO_H */
+
diff --git a/bta/include/bta_op_api.h b/bta/include/bta_op_api.h
new file mode 100644
index 0000000..c26ea35
--- /dev/null
+++ b/bta/include/bta_op_api.h
@@ -0,0 +1,67 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for the object push (OP) client and
+ *  server subsystem of BTA, Broadcom's Bluetooth application layer for
+ *  mobile phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_OP_API_H
+#define BTA_OP_API_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+/* Extra Debug Code */
+#ifndef BTA_OPS_DEBUG
+#define BTA_OPS_DEBUG           FALSE
+#endif
+
+#ifndef BTA_OPC_DEBUG
+#define BTA_OPC_DEBUG           FALSE
+#endif
+
+
+/* Object format */
+#define BTA_OP_VCARD21_FMT          1       /* vCard 2.1 */
+#define BTA_OP_VCARD30_FMT          2       /* vCard 3.0 */
+#define BTA_OP_VCAL_FMT             3       /* vCal 1.0 */
+#define BTA_OP_ICAL_FMT             4       /* iCal 2.0 */
+#define BTA_OP_VNOTE_FMT            5       /* vNote */
+#define BTA_OP_VMSG_FMT             6       /* vMessage */
+#define BTA_OP_OTHER_FMT            0xFF    /* other format */
+
+typedef UINT8 tBTA_OP_FMT;
+
+/* Object format mask */
+#define BTA_OP_VCARD21_MASK         0x01    /* vCard 2.1 */
+#define BTA_OP_VCARD30_MASK         0x02    /* vCard 3.0 */
+#define BTA_OP_VCAL_MASK            0x04    /* vCal 1.0 */
+#define BTA_OP_ICAL_MASK            0x08    /* iCal 2.0 */
+#define BTA_OP_VNOTE_MASK           0x10    /* vNote */
+#define BTA_OP_VMSG_MASK            0x20    /* vMessage */
+#define BTA_OP_ANY_MASK             0x40    /* Any type of object. */
+
+typedef UINT8 tBTA_OP_FMT_MASK;
+
+#endif /* BTA_OP_API_H */
+
diff --git a/bta/include/bta_pan_api.h b/bta/include/bta_pan_api.h
new file mode 100644
index 0000000..2166766
--- /dev/null
+++ b/bta/include/bta_pan_api.h
@@ -0,0 +1,201 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the public interface file for the Personal Area Networking (PAN)
+ *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_API_H
+#define BTA_PAN_API_H
+
+#include "bta_api.h"
+#include "pan_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+#define BTA_PAN_SUCCESS          0
+#define BTA_PAN_FAIL             1
+
+typedef UINT8 tBTA_PAN_STATUS;
+
+
+/* PAN Callback events */
+#define BTA_PAN_ENABLE_EVT       0       /* PAN service is enabled. */
+#define BTA_PAN_SET_ROLE_EVT     1       /* PAN roles registered */
+#define BTA_PAN_OPENING_EVT      2       /* Connection is being opened. */
+#define BTA_PAN_OPEN_EVT         3       /* Connection has been opened. */
+#define BTA_PAN_CLOSE_EVT        4       /* Connection has been closed. */
+
+typedef UINT8 tBTA_PAN_EVT;
+
+
+/* pan roles */
+#define BTA_PAN_ROLE_PANU        PAN_ROLE_CLIENT
+#define BTA_PAN_ROLE_GN          PAN_ROLE_GN_SERVER
+#define BTA_PAN_ROLE_NAP         PAN_ROLE_NAP_SERVER
+
+
+typedef UINT8   tBTA_PAN_ROLE;
+
+/*  information regarding PAN roles */
+typedef struct
+{
+    char *p_srv_name;  /* service name for the PAN role */
+    UINT8 app_id;      /* application id */
+    tBTA_SEC sec_mask; /* security setting for the role */
+
+} tBTA_PAN_ROLE_INFO;
+
+
+/* Event associated with BTA_PAN_SET_ROLE_EVT */
+typedef struct
+{
+    tBTA_PAN_STATUS status;     /* status of set role event */
+    tBTA_PAN_ROLE   role;       /* PAN roles successfully registered */
+} tBTA_PAN_SET_ROLE;
+
+/* Event associated with BTA_PAN_OPENING_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;    /* BD address of peer device. */
+    UINT16          handle;     /* Handle associated with this connection. */
+
+} tBTA_PAN_OPENING;
+
+
+/* Event associated with BTA_PAN_OPEN_EVT */
+typedef struct
+{
+    BD_ADDR         bd_addr;    /* BD address of peer device. */
+    UINT16          handle;     /* Handle associated with this connection. */
+    tBTA_PAN_STATUS status;     /* status of open event */
+    tBTA_PAN_ROLE   local_role; /* Local device PAN role for the connection */
+    tBTA_PAN_ROLE   peer_role;  /* Peer device PAN role for the connection */
+
+} tBTA_PAN_OPEN;
+
+/* Event associated with BTA_PAN_CLOSE_EVT */
+typedef struct
+{
+    UINT16          handle;     /* Handle associated with the connection. */
+} tBTA_PAN_CLOSE;
+
+/* Union of all PAN callback structures */
+typedef union
+{
+    tBTA_PAN_SET_ROLE   set_role;   /* set_role event */
+    tBTA_PAN_OPEN       open;       /* Connection has been opened. */
+    tBTA_PAN_OPENING    opening;    /* Connection being opened */
+    tBTA_PAN_CLOSE      close;      /* Connection has been closed. */
+} tBTA_PAN;
+
+/* Number of PAN connections */
+#ifndef BTA_PAN_NUM_CONN
+#define BTA_PAN_NUM_CONN         4
+#endif
+
+/* PAN callback */
+typedef void (tBTA_PAN_CBACK)(tBTA_PAN_EVT event, tBTA_PAN *p_data);
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         BTA_PanEnable
+**
+** Description      Enable PAN service.  This function must be
+**                  called before any other functions in the PAN API are called.
+**                  When the enable operation is complete the callback function
+**                  will be called with a BTA_PAN_ENABLE_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanEnable(tBTA_PAN_CBACK p_cback);
+
+/*******************************************************************************
+**
+** Function         BTA_PanDisable
+**
+** Description      Disable PAN service.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanDisable(void);
+
+
+/*******************************************************************************
+**
+** Function         BTA_PanSetRole
+**
+** Description      Sets PAN roles. When the enable operation is complete
+**                  the callback function will be called with a BTA_PAN_SET_ROLE_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_PanSetRole(tBTA_PAN_ROLE role, tBTA_PAN_ROLE_INFO *p_user_info, tBTA_PAN_ROLE_INFO *p_gn_info,
+                                        tBTA_PAN_ROLE_INFO *p_nap_info);
+
+
+/*******************************************************************************
+**
+** Function         BTA_PanOpen
+**
+** Description      Opens a connection to a peer device.
+**                  When connection is open callback function is called
+**                  with a BTA_PAN_OPEN_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_PanOpen(BD_ADDR bd_addr, tBTA_PAN_ROLE    local_role, tBTA_PAN_ROLE  peer_role);
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_PanClose
+**
+** Description      Close a PAN  connection to a peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_PanClose(UINT16 handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_PAN_API_H */
+
diff --git a/bta/include/bta_pan_ci.h b/bta/include/bta_pan_ci.h
new file mode 100644
index 0000000..faeef54
--- /dev/null
+++ b/bta/include/bta_pan_ci.h
@@ -0,0 +1,151 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the interface file for pan call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_CI_H
+#define BTA_PAN_CI_H
+
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_tx_ready
+**
+** Description      This function sends an event to PAN indicating the phone is
+**                  ready for more data and PAN should call bta_pan_co_tx_path().
+**                  This function is used when the TX data path is configured
+**                  to use a pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_tx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_rx_ready
+**
+** Description      This function sends an event to PAN indicating the phone
+**                  has data available to send to PAN and PAN should call
+**                  bta_pan_co_rx_path().  This function is used when the RX
+**                  data path is configured to use a pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_rx_ready(UINT16 handle);
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_tx_flow
+**
+** Description      This function is called to enable or disable data flow on
+**                  the TX path.  The phone should call this function to
+**                  disable data flow when it is congested and cannot handle
+**                  any more data sent by bta_pan_co_tx_write() or
+**                  bta_pan_co_tx_writebuf().  This function is used when the
+**                  TX data path is configured to use a push interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_tx_flow(UINT16 handle, BOOLEAN enable);
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_rx_writebuf
+**
+** Description      This function is called to send data to the phone when
+**                  the RX path is configured to use a push interface with
+**                  zero copy.  The function sends an event to PAN containing
+**                  the data buffer.  The buffer must be allocated using
+**                  functions GKI_getbuf() or GKI_getpoolbuf().  The buffer
+**                  will be freed by BTA; the phone must not free the buffer.
+**
+**
+** Returns          TRUE if flow enabled
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_rx_writebuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf, BOOLEAN ext);
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_readbuf
+**
+** Description      This function is called by the phone to read data from PAN
+**                  when the TX path is configured to use a pull interface.
+**                  The phone must free the buffer using function GKI_freebuf() when
+**                  it is through processing the buffer.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern BT_HDR * bta_pan_ci_readbuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 *p_protocol,
+                                 BOOLEAN* p_ext, BOOLEAN* p_forward);
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_set_pfilters
+**
+** Description      This function is called to set protocol filters
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_set_pfilters(UINT16 handle, UINT16 num_filters, UINT16 *p_start_array, UINT16 *p_end_array);
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_set_mfilters
+**
+** Description      This function is called to set multicast filters
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filters, UINT8 *p_start_array,
+                                                    UINT8 *p_end_array);
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_PAN_CI_H */
+
diff --git a/bta/include/bta_pan_co.h b/bta/include/bta_pan_co.h
new file mode 100644
index 0000000..5b20fad
--- /dev/null
+++ b/bta/include/bta_pan_co.h
@@ -0,0 +1,201 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the interface file for data gateway call-out functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_CO_H
+#define BTA_PAN_CO_H
+
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+
+/* BT_HDR buffer offset */
+#define BTA_PAN_MIN_OFFSET       PAN_MINIMUM_OFFSET
+
+
+/* Data Flow Mask */
+#define BTA_PAN_RX_PUSH          0x00        /* RX push. */
+#define BTA_PAN_RX_PUSH_BUF      0x01        /* RX push with zero copy. */
+#define BTA_PAN_RX_PULL          0x02        /* RX pull. */
+#define BTA_PAN_TX_PUSH          0x00        /* TX push. */
+#define BTA_PAN_TX_PUSH_BUF      0x10        /* TX push with zero copy. */
+#define BTA_PAN_TX_PULL          0x20        /* TX pull. */
+
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_init
+**
+** Description      This callout function is executed by PAN when a server is
+**                  started by calling BTA_PanEnable().  This function can be
+**                  used by the phone to initialize data paths or for other
+**                  initialization purposes.  The function must return the
+**                  data flow mask as described below.
+**
+**
+** Returns          Data flow mask.
+**
+*******************************************************************************/
+BTA_API extern UINT8 bta_pan_co_init(UINT8 *q_level);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_open
+**
+** Description      This function is executed by PAN when a connection
+**                  is opened.  The phone can use this function to set
+**                  up data paths or perform any required initialization.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_open(UINT16 handle, UINT8 app_id, tBTA_PAN_ROLE local_role, tBTA_PAN_ROLE peer_role, BD_ADDR peer_addr);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_close
+**
+** Description      This function is called by PAN when a connection to a
+**                  server is closed.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_close(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_tx_path
+**
+** Description      This function is called by PAN to transfer data on the
+**                  TX path; that is, data being sent from BTA to the phone.
+**                  This function is used when the TX data path is configured
+**                  to use the pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_path(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_rx_path
+**
+** Description      This function is called by PAN to transfer data on the
+**                  RX path; that is, data being sent from the phone to BTA.
+**                  This function is used when the RX data path is configured
+**                  to use the pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_rx_path(UINT16 handle, UINT8 app_id);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_tx_write
+**
+** Description      This function is called by PAN to send data to the phone
+**                  when the TX path is configured to use a push interface.
+**                  The implementation of this function must copy the data to
+**                  the phone's memory.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_write(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, UINT8 *p_data,
+                                UINT16 len, BOOLEAN ext, BOOLEAN forward);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_tx_writebuf
+**
+** Description      This function is called by PAN to send data to the phone
+**                  when the TX path is configured to use a push interface with
+**                  zero copy.  The phone must free the buffer using function
+**                  GKI_freebuf() when it is through processing the buffer.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_tx_writebuf(UINT16 handle, UINT8 app_id, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
+                                   BOOLEAN ext, BOOLEAN forward);
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_rx_flow
+**
+** Description      This function is called by PAN to enable or disable
+**                  data flow on the RX path when it is configured to use
+**                  a push interface.  If data flow is disabled the phone must
+**                  not call bta_pan_ci_rx_write() or bta_pan_ci_rx_writebuf()
+**                  until data flow is enabled again.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_rx_flow(UINT16 handle, UINT8 app_id, BOOLEAN enable);
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_filt_ind
+**
+** Description      protocol filter indication from peer device
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_pfilt_ind(UINT16 handle, BOOLEAN indication, tBTA_PAN_STATUS result,
+                                    UINT16 len, UINT8 *p_filters);
+
+/*******************************************************************************
+**
+** Function         bta_pan_co_mfilt_ind
+**
+** Description      multicast filter indication from peer device
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void bta_pan_co_mfilt_ind(UINT16 handle,  BOOLEAN indication, tBTA_PAN_STATUS result,
+                                    UINT16 len, UINT8 *p_filters);
+
+#endif /* BTA_PAN_CO_H */
+
diff --git a/bta/include/bta_pbs_api.h b/bta/include/bta_pbs_api.h
new file mode 100644
index 0000000..c3563c2
--- /dev/null
+++ b/bta/include/bta_pbs_api.h
@@ -0,0 +1,49 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for the phone book access (PB) server
+ *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
+ *  phones.
+ *
+ ******************************************************************************/
+#ifndef BTA_PB_API_H
+#define BTA_PB_API_H
+
+#include "bta_api.h"
+#include "btm_api.h"
+#include "bta_sys.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/**************************
+**  Common Definitions
+***************************/
+
+/* Profile supported features */
+#define BTA_PBS_SUPF_DOWNLOAD     0x0001
+#define BTA_PBS_SURF_BROWSE       0x0002
+
+/* Profile supported repositories */
+#define BTA_PBS_REPOSIT_LOCAL      0x01    /* Local PhoneBook */
+#define BTA_PBS_REPOSIT_SIM        0x02    /* SIM card PhoneBook */
+
+#endif
diff --git a/bta/include/bta_sys_ci.h b/bta/include/bta_sys_ci.h
new file mode 100644
index 0000000..4818386
--- /dev/null
+++ b/bta/include/bta_sys_ci.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the interface file for system call-in functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_CI_H
+#define BTA_SYS_CI_H
+
+#include "bta_api.h"
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_ci_enabled
+**
+** Description      This function must be called in response to function
+**                  bta_sys_hw_co_enable(), when HW is indeed enabled
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API  void bta_sys_hw_ci_enabled(tBTA_SYS_HW_MODULE module );
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_ci_disabled
+**
+** Description      This function must be called in response to function
+**                  bta_sys_hw_co_disable() when HW is really OFF
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_ci_disabled( tBTA_SYS_HW_MODULE module  );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/bta/include/bta_sys_co.h b/bta/include/bta_sys_co.h
new file mode 100644
index 0000000..92118a3
--- /dev/null
+++ b/bta/include/bta_sys_co.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the interface file for system callout functions.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_CO_H
+#define BTA_SYS_CO_H
+
+#include "bta_sys.h"
+
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_co_enable
+**
+** Description      This function is called by the stack to power up the HW
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_co_enable( tBTA_SYS_HW_MODULE module );
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_co_disable
+**
+** Description     This function is called by the stack to power down the HW
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_hw_co_disable( tBTA_SYS_HW_MODULE module );
+
+
+#endif
diff --git a/bta/include/ptim.h b/bta/include/ptim.h
new file mode 100644
index 0000000..80e50bd
--- /dev/null
+++ b/bta/include/ptim.h
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Protocol timer services.
+ *
+ ******************************************************************************/
+#ifndef PTIM_H
+#define PTIM_H
+
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+typedef struct
+{
+    TIMER_LIST_Q        timer_queue;        /* GKI timer queue */
+    INT32               period;             /* Timer period in milliseconds */
+    UINT32              last_gki_ticks;     /* GKI ticks since last time update called */
+    UINT8               timer_id;           /* GKI timer id */
+} tPTIM_CB;
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         ptim_init
+**
+** Description      Initialize a protocol timer service control block.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void ptim_init(tPTIM_CB *p_cb, UINT16 period, UINT8 timer_id);
+
+/*******************************************************************************
+**
+** Function         ptim_timer_update
+**
+** Description      Update the protocol timer list and handle expired timers.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void ptim_timer_update(tPTIM_CB *p_cb);
+
+/*******************************************************************************
+**
+** Function         ptim_start_timer
+**
+** Description      Start a protocol timer for the specified amount
+**                  of time in milliseconds.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void ptim_start_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout);
+
+/*******************************************************************************
+**
+** Function         ptim_stop_timer
+**
+** Description      Stop a protocol timer.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void ptim_stop_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PTIM_H */
diff --git a/bta/include/utl.h b/bta/include/utl.h
new file mode 100644
index 0000000..df08b5a
--- /dev/null
+++ b/bta/include/utl.h
@@ -0,0 +1,169 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Basic utility functions.
+ *
+ ******************************************************************************/
+#ifndef UTL_H
+#define UTL_H
+
+#include "data_types.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+/*** class of device settings ***/
+#define BTA_UTL_SET_COD_MAJOR_MINOR     0x01
+#define BTA_UTL_SET_COD_SERVICE_CLASS   0x02 /* only set the bits in the input */
+#define BTA_UTL_CLR_COD_SERVICE_CLASS   0x04
+#define BTA_UTL_SET_COD_ALL             0x08 /* take service class as the input (may clear some set bits!!) */
+#define BTA_UTL_INIT_COD                0x0a
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+/** for utl_set_device_class() **/
+typedef struct
+{
+    UINT8       minor;
+    UINT8       major;
+    UINT16      service;
+} tBTA_UTL_COD;
+
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         utl_str2int
+**
+** Description      This utility function converts a character string to an
+**                  integer.  Acceptable values in string are 0-9.  If invalid
+**                  string or string value too large, -1 is returned.
+**
+**
+** Returns          Integer value or -1 on error.
+**
+*******************************************************************************/
+extern INT16 utl_str2int(const char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_strucmp
+**
+** Description      This utility function compares two strings in uppercase.
+**                  String p_s must be uppercase.  String p_t is converted to
+**                  uppercase if lowercase.  If p_s ends first, the substring
+**                  match is counted as a match.
+**
+**
+** Returns          0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+extern int utl_strucmp(const char *p_s, const char *p_t);
+
+/*******************************************************************************
+**
+** Function         utl_itoa
+**
+** Description      This utility function converts a UINT16 to a string.  The
+**                  string is NULL-terminated.  The length of the string is
+**                  returned.
+**
+**
+** Returns          Length of string.
+**
+*******************************************************************************/
+extern UINT8 utl_itoa(UINT16 i, char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_freebuf
+**
+** Description      This function calls GKI_freebuf to free the buffer passed
+**                  in, if buffer pointer is not NULL, and also initializes
+**                  buffer pointer to NULL.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+extern void utl_freebuf(void **p);
+
+/*******************************************************************************
+**
+** Function         utl_set_device_class
+**
+** Description      This function updates the local Device Class.
+**
+** Parameters:
+**                  p_cod   - Pointer to the device class to set to
+**
+**                  cmd     - the fields of the device class to update.
+**                            BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+**                            BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+**                            BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+**                            BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+**                            BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function         utl_isintstr
+**
+** Description      This utility function checks if the given string is an
+**                  integer string or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isintstr(const char *p_s);
+
+/*******************************************************************************
+**
+** Function         utl_isdialstr
+**
+** Description      This utility function checks if the given string contains
+**                  only dial digits or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+extern BOOLEAN utl_isdialstr(const char *p_s);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UTL_H */
diff --git a/bta/jv/bta_jv_act.c b/bta/jv/bta_jv_act.c
new file mode 100644
index 0000000..77d18d9
--- /dev/null
+++ b/bta/jv/bta_jv_act.c
@@ -0,0 +1,2360 @@
+/******************************************************************************
+ *
+ *  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 file contains action functions for advanced audio.
+ *
+ ******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <arpa/inet.h>
+
+#include "bt_types.h"
+#include "gki.h"
+#include "bd.h"
+#include "utl.h"
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+#include "bta_jv_co.h"
+#include "btm_api.h"
+#include "btm_int.h"
+#include "sdp_api.h"
+#include "l2c_api.h"
+#include "port_api.h"
+#include <string.h>
+#include "rfcdefs.h"
+#include "avct_api.h"
+#include "avdt_api.h"
+
+
+#include <cutils/log.h>
+#define info(fmt, ...)  ALOGI ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
+#define debug(fmt, ...) ALOGD ("%s: " fmt,__FUNCTION__,  ## __VA_ARGS__)
+#define error(fmt, ...) ALOGE ("## ERROR : %s: " fmt "##",__FUNCTION__,  ## __VA_ARGS__)
+#define asrt(s) if(!(s)) ALOGE ("## %s assert %s failed at line:%d ##",__FUNCTION__, #s, __LINE__)
+
+
+
+#define HDL2CB(handle) \
+    UINT32  __hi = ((handle) & BTA_JV_RFC_HDL_MASK) - 1; \
+    UINT32  __si = BTA_JV_RFC_HDL_TO_SIDX(handle); \
+    tBTA_JV_RFC_CB  *p_cb = &bta_jv_cb.rfc_cb[__hi]; \
+    tBTA_JV_PCB   *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[__si] - 1]
+
+extern void uuid_to_string(bt_uuid_t *p_uuid, char *str);
+static inline void logu(const char* title, const uint8_t * p_uuid)
+{
+    char uuids[128];
+    uuid_to_string((bt_uuid_t*)p_uuid, uuids);
+    ALOGD("%s: %s", title, uuids);
+}
+
+
+static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb);
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_local_device_addr_cback
+**
+** Description  Callback from btm after local bdaddr is read
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_get_local_device_addr_cback(BD_ADDR bd_addr)
+{
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_ADDR_EVT, (tBTA_JV *)bd_addr, 0);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_remote_device_name_cback
+**
+** Description  Callback from btm after remote name is read
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_get_remote_device_name_cback(tBTM_REMOTE_DEV_NAME *p_name)
+{
+    tBTA_JV evt_data;
+    evt_data.p_name = p_name->remote_bd_name;
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_REMOTE_NAME_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_alloc_sec_id
+**
+** Description  allocate a security id
+**
+** Returns
+**
+*******************************************************************************/
+UINT8 bta_jv_alloc_sec_id(void)
+{
+    UINT8 ret = 0;
+    int i;
+    for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
+    {
+        if(0 == bta_jv_cb.sec_id[i])
+        {
+            bta_jv_cb.sec_id[i] = BTA_JV_FIRST_SERVICE_ID + i;
+            ret = bta_jv_cb.sec_id[i];
+            break;
+        }
+    }
+    return ret;
+
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_sec_id
+**
+** Description  free the given security id
+**
+** Returns
+**
+*******************************************************************************/
+static void bta_jv_free_sec_id(UINT8 *p_sec_id)
+{
+    UINT8 sec_id = *p_sec_id;
+    *p_sec_id = 0;
+    if(sec_id >= BTA_JV_FIRST_SERVICE_ID && sec_id <= BTA_JV_LAST_SERVICE_ID)
+    {
+        BTM_SecClrService(sec_id);
+        bta_jv_cb.sec_id[sec_id - BTA_JV_FIRST_SERVICE_ID] = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_alloc_rfc_cb
+**
+** Description  allocate a control block for the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_RFC_CB * bta_jv_alloc_rfc_cb(UINT16 port_handle, tBTA_JV_PCB **pp_pcb)
+{
+    tBTA_JV_RFC_CB *p_cb = NULL;
+    tBTA_JV_PCB *p_pcb;
+    int i;
+    for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
+    {
+        if(0 == bta_jv_cb.rfc_cb[i].handle )
+        {
+            p_cb = &bta_jv_cb.rfc_cb[i];
+            p_cb->handle            = i + 1;
+            p_cb->max_sess          = 1;
+            p_cb->rfc_hdl[0]        = port_handle;
+            APPL_TRACE_DEBUG2( "bta_jv_alloc_rfc_cb port_handle:%d handle:%d",
+                port_handle, p_cb->handle);
+            p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
+            p_pcb->handle = p_cb->handle;
+            p_pcb->port_handle = port_handle;
+            *pp_pcb = p_pcb;
+            break;
+        }
+    }
+    return p_cb;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfc_port_to_pcb
+**
+** Description  find the port control block associated with the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_PCB * bta_jv_rfc_port_to_pcb(UINT16 port_handle)
+{
+    tBTA_JV_PCB *p_pcb = NULL;
+
+    if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle)
+    {
+        p_pcb = &bta_jv_cb.port_cb[port_handle - 1];
+    }
+
+    return p_pcb;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfc_port_to_cb
+**
+** Description  find the RFCOMM control block associated with the given port handle
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_RFC_CB * bta_jv_rfc_port_to_cb(UINT16 port_handle)
+{
+    tBTA_JV_RFC_CB *p_cb = NULL;
+    UINT32 handle;
+
+    if ((port_handle > 0) && (port_handle <= MAX_RFC_PORTS) && bta_jv_cb.port_cb[port_handle - 1].handle)
+    {
+        handle = bta_jv_cb.port_cb[port_handle - 1].handle;
+        handle &= BTA_JV_RFC_HDL_MASK;
+        if (handle)
+            p_cb = &bta_jv_cb.rfc_cb[handle - 1];
+    }
+    return p_cb;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_rfc_pcb
+**
+** Description  free the given port control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_rfc_pcb(tBTA_JV_PCB *p_pcb)
+{
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+    BOOLEAN         remove = FALSE;
+    BOOLEAN         is_server = TRUE;
+    UINT16          port_handle;
+
+    APPL_TRACE_DEBUG2( "bta_jv_free_rfc_pcb handle:%d s:%d", p_pcb->port_handle, p_pcb->state);
+
+    if (p_pcb->port_handle)
+    {
+        if(BTA_JV_ST_NONE != p_pcb->state)
+        {
+            remove = TRUE;
+            if(p_pcb->state <= BTA_JV_ST_CL_MAX)
+                is_server = FALSE;
+            port_handle = p_pcb->port_handle;
+        }
+        p_pcb->port_handle = 0;
+        p_pcb->state = BTA_JV_ST_NONE;
+
+        //Initialize congestion flags
+        p_pcb->cong = FALSE;
+
+        if(remove)
+        {
+            if(is_server)
+            {
+                if(RFCOMM_RemoveServer(port_handle) != PORT_SUCCESS)
+                    status = BTA_JV_FAILURE;
+            }
+            else
+            {
+                if(RFCOMM_RemoveConnection(port_handle) != PORT_SUCCESS)
+                    status = BTA_JV_FAILURE;
+            }
+        }
+    }
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_rfc_cb
+**
+** Description  free the given RFCOMM control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_rfc_cb(tBTA_JV_RFC_CB *p_cb)
+{
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+    UINT8           i;
+    APPL_TRACE_DEBUG1( "bta_jv_free_rfc_cb max_sess:%d", p_cb->max_sess);
+    for (i=0; i<p_cb->max_sess; i++)
+    {
+        APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]);
+        if (p_cb->rfc_hdl[i])
+            bta_jv_free_rfc_pcb (&bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1]);
+    }
+
+    p_cb->scn = 0;
+    bta_jv_free_sec_id(&p_cb->sec_id);
+    p_cb->p_cback = NULL;
+    p_cb->handle = 0;
+
+    return status;
+}
+static tBTA_JV_STATUS bta_jv_free_rfc_listen_cb(tBTA_JV_RFC_CB *p_cb)
+{
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+    UINT8           i;
+    debug( "max_sess:%d", p_cb->max_sess);
+    for (i=0; i<p_cb->max_sess; i++)
+    {
+        APPL_TRACE_DEBUG2( "[%d]: port=%d", i, p_cb->rfc_hdl[i]);
+        if (p_cb->rfc_hdl[i])
+        {
+            tBTA_JV_PCB *p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+            if(p_pcb->state == BTA_JV_ST_SR_LISTEN)
+            {
+                debug( "free listen pcb: scn:%d, ueser_data:%d", p_cb->scn, (int)p_pcb->user_data);
+                p_pcb->user_data = 0;
+                bta_jv_free_rfc_pcb (p_pcb);
+                p_cb->max_sess = 1;
+                break;
+            }
+        }
+    }
+    //p_cb->scn = 0;
+    bta_jv_free_sec_id(&p_cb->sec_id);
+    //p_cb->p_cback = NULL;
+    //p_cb->handle = 0;
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_l2c_cb
+**
+** Description  free the given L2CAP control block
+**
+** Returns
+**
+*******************************************************************************/
+tBTA_JV_STATUS bta_jv_free_l2c_cb(tBTA_JV_L2C_CB *p_cb)
+{
+#if 0
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+
+    if(BTA_JV_ST_NONE != p_cb->state)
+    {
+#if SDP_FOR_JV_INCLUDED == TRUE
+        if(BTA_JV_L2C_FOR_SDP_HDL == p_cb->handle)
+        {
+            bta_jv_cb.sdp_data_size = 0;
+            if(SDP_ConnClose(bta_jv_cb.sdp_for_jv))
+            {
+                bta_jv_cb.sdp_for_jv = 0;
+            }
+            else
+                status = BTA_JV_FAILURE;
+        }
+        else
+#endif
+        if(GAP_ConnClose(p_cb->handle) != BT_PASS)
+            status = BTA_JV_FAILURE;
+    }
+    p_cb->psm = 0;
+    p_cb->state = BTA_JV_ST_NONE;
+    bta_jv_free_sec_id(&p_cb->sec_id);
+    p_cb->p_cback = NULL;
+    return status;
+#endif
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_alloc_sdp_id
+**
+** Description  allocate a SDP id for the given SDP record handle
+**
+** Returns
+**
+*******************************************************************************/
+UINT32 bta_jv_alloc_sdp_id(UINT32 sdp_handle)
+{
+    int j;
+    UINT32 id = 0;
+
+    /* find a free entry */
+    for (j = 0; j < BTA_JV_MAX_SDP_REC; j++)
+    {
+        if (bta_jv_cb.sdp_handle[j] == 0)
+        {
+            bta_jv_cb.sdp_handle[j] = sdp_handle;
+            id = (UINT32)(j + 1);
+            break;
+        }
+    }
+    /* the SDP record handle reported is the (index + 1) to control block */
+    return id;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_sdp_id
+**
+** Description  free the sdp id
+**
+** Returns
+**
+*******************************************************************************/
+void bta_jv_free_sdp_id(UINT32 sdp_id)
+{
+    if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC)
+    {
+        bta_jv_cb.sdp_handle[sdp_id - 1] = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_sdp_handle
+**
+** Description  find the SDP handle associated with the given sdp id
+**
+** Returns
+**
+*******************************************************************************/
+UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id)
+{
+    UINT32 sdp_handle = 0;
+
+    if(sdp_id > 0 && sdp_id <= BTA_JV_MAX_SDP_REC)
+    {
+        sdp_handle = bta_jv_cb.sdp_handle[sdp_id - 1];
+    }
+    return sdp_handle;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_check_psm
+**
+** Description  for now use only the legal PSM per JSR82 spec
+**
+** Returns      TRUE, if allowed
+**
+*******************************************************************************/
+BOOLEAN bta_jv_check_psm(UINT16 psm)
+{
+    BOOLEAN ret = FALSE;
+
+    if(L2C_IS_VALID_PSM(psm) )
+    {
+        if(psm < 0x1001)
+        {
+            /* see if this is defined by spec */
+            switch(psm)
+            {
+            case SDP_PSM:           /* 1 */
+            case BT_PSM_RFCOMM:     /* 3 */
+                /* do not allow java app to use these 2 PSMs */
+                break;
+
+            case TCS_PSM_INTERCOM:  /* 5 */
+            case TCS_PSM_CORDLESS:  /* 7 */
+                if( FALSE == bta_sys_is_register(BTA_ID_CT) &&
+                    FALSE == bta_sys_is_register(BTA_ID_CG) )
+                    ret = TRUE;
+                break;
+
+            case BT_PSM_BNEP:       /* F */
+                if(FALSE == bta_sys_is_register(BTA_ID_PAN))
+                    ret = TRUE;
+                break;
+
+            case HID_PSM_CONTROL:   /* 0x11 */
+            case HID_PSM_INTERRUPT: /* 0x13 */
+                //FIX: allow HID Device and HID Host to coexist
+                if( FALSE == bta_sys_is_register(BTA_ID_HD) ||
+                    FALSE == bta_sys_is_register(BTA_ID_HH) )
+                    ret = TRUE;
+                break;
+
+            case AVCT_PSM:          /* 0x17 */
+            case AVDT_PSM:          /* 0x19 */
+                if ((FALSE == bta_sys_is_register(BTA_ID_AV)) &&
+                   (FALSE == bta_sys_is_register(BTA_ID_AVK)))
+                    ret = TRUE;
+                break;
+
+            default:
+                ret = TRUE;
+                break;
+            }
+        }
+        else
+            ret = TRUE;
+    }
+    return ret;
+
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_enable
+**
+** Description  Initialises the JAVA I/F
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_enable(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+    bta_jv_cb.p_dm_cback = p_data->enable.p_cback;
+    bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, (tBTA_JV *)&status, 0);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_disable
+**
+** Description  Disables the BT device manager
+**              free the resources used by java
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_disable (tBTA_JV_MSG *p_data)
+{
+    int i;
+
+    bta_jv_cb.p_dm_cback = NULL;
+    /* delete the SDP records created by java apps */
+    for(i=0; i<BTA_JV_MAX_SDP_REC; i++)
+    {
+        if(bta_jv_cb.sdp_handle[i])
+        {
+            APPL_TRACE_DEBUG1( "delete SDP record: %d", bta_jv_cb.sdp_handle[i]);
+            SDP_DeleteRecord(bta_jv_cb.sdp_handle[i]);
+            bta_jv_cb.sdp_handle[i] = 0;
+        }
+    }
+
+    /* free the SCNs allocated by java apps */
+    for(i=0; i<BTA_JV_MAX_SCN; i++)
+    {
+        if(bta_jv_cb.scn[i])
+        {
+            APPL_TRACE_DEBUG1( "free scn: %d", (i+1));
+            BTM_FreeSCN((UINT8)(i+1));
+            bta_jv_cb.scn[i] = FALSE;
+        }
+    }
+
+    /* disconnect L2CAP connections */
+    for(i=0; i<BTA_JV_MAX_L2C_CONN; i++)
+    {
+        bta_jv_free_l2c_cb(&bta_jv_cb.l2c_cb[i]);
+    }
+
+    /* disconnect RFCOMM connections */
+    for(i=0; i<BTA_JV_MAX_RFC_CONN; i++)
+    {
+        bta_jv_free_rfc_cb(&bta_jv_cb.rfc_cb[i]);
+    }
+
+    /* free the service records allocated by java apps */
+    for(i=0; i<BTA_JV_NUM_SERVICE_ID; i++)
+    {
+        if(bta_jv_cb.sec_id[i])
+        {
+            BTM_SecClrService(bta_jv_cb.sec_id[i]);
+            bta_jv_cb.sec_id[i] = 0;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_set_discoverability
+**
+** Description  Sets discoverability
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_set_discoverability (tBTA_JV_MSG *p_data)
+{
+    tBTA_JV     evt_data;
+
+    evt_data.set_discover.status = BTA_JV_FAILURE;
+    /* initialize the default value for the event as the current mode */
+    evt_data.set_discover.disc_mode = BTM_ReadDiscoverability(NULL, NULL);
+
+    if(BTM_SUCCESS == BTM_SetDiscoverability((UINT8)p_data->set_discoverability.disc_mode, 0, 0))
+    {
+        evt_data.set_discover.status     = BTA_JV_SUCCESS;
+        /* update the mode, after BTM_SetDiscoverability() is successful */
+        evt_data.set_discover.disc_mode  = p_data->set_discoverability.disc_mode;
+    }
+
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_SET_DISCOVER_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_local_device_addr
+**
+** Description  Reads the local Bluetooth device address
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_get_local_device_addr(tBTA_JV_MSG *p_data)
+{
+    BTM_ReadLocalDeviceAddr((tBTM_CMPL_CB *)bta_jv_get_local_device_addr_cback);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_local_device_name
+**
+** Description  Reads the local Bluetooth device name
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_get_local_device_name(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV evt_data;
+    char *name;
+
+    BTM_ReadLocalDeviceName(&name);
+    evt_data.p_name = (UINT8*)name;
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_LOCAL_NAME_EVT, &evt_data, 0);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_remote_device_name
+**
+** Description  Reads the local Bluetooth device name
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_get_remote_device_name(tBTA_JV_MSG *p_data)
+{
+
+    BTM_ReadRemoteDeviceName(p_data->get_rmt_name.bd_addr,
+        (tBTM_CMPL_CB *)bta_jv_get_remote_device_name_cback);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_set_service_class
+**
+** Description  update the service class field of device class
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_set_service_class (tBTA_JV_MSG *p_data)
+{
+    tBTA_UTL_COD cod;
+
+    /* set class of device */
+    /* BTA_JvSetServiceClass(UINT32 service) assumes that the service class passed to the API function as defined in the assigned number page.
+    For example: the object transfer bit is bit 20 of the 24-bit Class of device; the value of this bit is 0x00100000 (value 1)
+    Our btm_api.h defines this bit as #define BTM_COD_SERVICE_OBJ_TRANSFER        0x1000 // (value 2)
+    This reflects that the service class defined at btm is UINT16, which starts at bit 8 of the 24 bit Class of Device
+    The following statement converts from (value 1) into (value 2) */
+    cod.service = (p_data->set_service.service >> 8);
+    utl_set_device_class(&cod, BTA_UTL_SET_COD_SERVICE_CLASS);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_sec_cback
+**
+** Description  callback function to handle set encryption complete event
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_sec_cback (BD_ADDR bd_addr, void *p_ref_data, tBTM_STATUS result)
+{
+    tBTA_JV_SET_ENCRYPTION  set_enc;
+    if(bta_jv_cb.p_dm_cback)
+    {
+        bdcpy(set_enc.bd_addr, bd_addr);
+        set_enc.status = result;
+        if (result > BTA_JV_BUSY)
+            set_enc.status = BTA_JV_FAILURE;
+        bta_jv_cb.p_dm_cback(BTA_JV_SET_ENCRYPTION_EVT, (tBTA_JV *)&set_enc, 0);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_set_encryption
+**
+** Description  Reads the local Bluetooth device name
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_set_encryption(tBTA_JV_MSG *p_data)
+{
+    BTM_SetEncryption(p_data->set_encrypt.bd_addr, bta_jv_sec_cback, NULL);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_scn
+**
+** Description  obtain a free SCN
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_get_scn(tBTA_JV_MSG *p_data)
+{
+#if 0
+    UINT8   scn;
+    scn = BTM_AllocateSCN();
+    if(scn)
+        bta_jv_cb.scn[scn-1] = TRUE;
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_GET_SCN_EVT, (tBTA_JV *)&scn);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_free_scn
+**
+** Description  free a SCN
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_free_scn(tBTA_JV_MSG *p_data)
+{
+    UINT8   scn = p_data->free_scn.scn;
+
+    if (scn > 0 && scn <= BTA_JV_MAX_SCN && bta_jv_cb.scn[scn-1])
+    {
+        /* this scn is used by JV */
+        bta_jv_cb.scn[scn-1] = FALSE;
+        BTM_FreeSCN(scn);
+    }
+}
+static inline tBT_UUID shorten_sdp_uuid(const tBT_UUID* u)
+{
+    static uint8_t bt_base_uuid[] =
+       {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB };
+
+    logu("in, uuid:", u);
+    debug("uuid len:%d", u->len);
+    if(u->len == 16)
+    {
+        if(memcmp(&u->uu.uuid128[4], &bt_base_uuid[4], 12) == 0)
+        {
+            tBT_UUID su;
+            memset(&su, 0, sizeof(su));
+            if(u->uu.uuid128[0] == 0 && u->uu.uuid128[1] == 0)
+            {
+                su.len = 2;
+                uint16_t u16;
+                memcpy(&u16, &u->uu.uuid128[2], sizeof(u16));
+                su.uu.uuid16 = ntohs(u16);
+                debug("shorten to 16 bits uuid: %x", su.uu.uuid16);
+            }
+            else
+            {
+                su.len = 4;
+                uint32_t u32;
+                memcpy(&u32, &u->uu.uuid128[0], sizeof(u32));
+                su.uu.uuid32 = ntohl(u32);
+                debug("shorten to 32 bits uuid: %x", su.uu.uuid32);
+            }
+            return su;
+        }
+    }
+    debug("cannot shorten none-reserved 128 bits uuid");
+    return *u;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_start_discovery_cback
+**
+** Description  Callback for Start Discovery
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_start_discovery_cback(UINT16 result, void * user_data)
+{
+    tBTA_JV_STATUS status;
+    UINT8          old_sdp_act = bta_jv_cb.sdp_active;
+
+    debug( "bta_jv_start_discovery_cback res: 0x%x", result);
+
+    bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
+    if(bta_jv_cb.p_dm_cback)
+    {
+        if (old_sdp_act == BTA_JV_SDP_ACT_CANCEL)
+        {
+            debug("BTA_JV_SDP_ACT_CANCEL");
+            status = BTA_JV_SUCCESS;
+            bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, user_data);
+        }
+        else
+        {
+            tBTA_JV_DISCOVERY_COMP dcomp;
+            dcomp.scn = 0;
+            status = BTA_JV_FAILURE;
+            if (result == SDP_SUCCESS || result == SDP_DB_FULL)
+            {
+                tSDP_DISC_REC       *p_sdp_rec = NULL;
+                tSDP_PROTOCOL_ELEM  pe;
+                logu("bta_jv_cb.uuid", bta_jv_cb.uuid.uu.uuid128);
+                tBT_UUID su = shorten_sdp_uuid(&bta_jv_cb.uuid);
+                logu("shorten uuid:", su.uu.uuid128);
+                p_sdp_rec = SDP_FindServiceUUIDInDb(p_bta_jv_cfg->p_sdp_db, &su, p_sdp_rec);
+                debug("p_sdp_rec:%p", p_sdp_rec);
+                if(p_sdp_rec && SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe))
+                {
+                    dcomp.scn = (UINT8) pe.params[0];
+                    status = BTA_JV_SUCCESS;
+                }
+            }
+
+            dcomp.status = status;
+            bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&dcomp, user_data);
+        }
+        //free sdp db
+        //utl_freebuf(&(p_bta_jv_cfg->p_sdp_db));
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_start_discovery
+**
+** Description  Discovers services on a remote device
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_start_discovery(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    debug("in, sdp_active:%d", bta_jv_cb.sdp_active);
+    if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE)
+    {
+        /* SDP is still in progress */
+        status = BTA_JV_BUSY;
+        if(bta_jv_cb.p_dm_cback)
+            bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
+        return;
+    }
+/*
+    if(p_data->start_discovery.num_uuid == 0)
+    {
+        p_data->start_discovery.num_uuid = 1;
+        p_data->start_discovery.uuid_list[0].len       = 2;
+        p_data->start_discovery.uuid_list[0].uu.uuid16 = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+    }
+*/
+    /* init the database/set up the filter */
+    debug("call SDP_InitDiscoveryDb, p_data->start_discovery.num_uuid:%d",
+        p_data->start_discovery.num_uuid);
+    SDP_InitDiscoveryDb (p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
+                    p_data->start_discovery.num_uuid, p_data->start_discovery.uuid_list, 0, NULL);
+
+    /* tell SDP to keep the raw data */
+    p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
+    p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;
+
+    bta_jv_cb.p_sel_raw_data     = 0;
+    bta_jv_cb.uuid = p_data->start_discovery.uuid_list[0];
+
+    bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
+    if (!SDP_ServiceSearchAttributeRequest2(p_data->start_discovery.bd_addr,
+                                   p_bta_jv_cfg->p_sdp_db,
+                                   bta_jv_start_discovery_cback, p_data->start_discovery.user_data))
+    {
+        bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
+        /* failed to start SDP. report the failure right away */
+        if(bta_jv_cb.p_dm_cback)
+            bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, (tBTA_JV *)&status, p_data->start_discovery.user_data);
+    }
+    /*
+    else report the result when the cback is called
+    */
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_cancel_discovery
+**
+** Description  Cancels an active discovery
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_cancel_discovery(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_SUCCESS;
+    if (bta_jv_cb.sdp_active == BTA_JV_SDP_ACT_YES)
+    {
+        if (SDP_CancelServiceSearch (p_bta_jv_cfg->p_sdp_db))
+        {
+            bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_CANCEL;
+            return;
+        }
+    }
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_CANCEL_DISCVRY_EVT, (tBTA_JV *)&status, p_data->cancel_discovery.user_data);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_services_length
+**
+** Description  Obtain the length of each record in the SDP DB.
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_get_services_length(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_SERVICES_LEN    evt_data;
+    UINT8   *p, *np, *op, type;
+    UINT32  raw_used, raw_cur;
+    UINT32  len;
+
+    evt_data.num_services = -1;
+    evt_data.p_services_len = p_data->get_services_length.p_services_len;
+    if(p_bta_jv_cfg->p_sdp_db->p_first_rec)
+    {
+        /* the database is valid */
+        evt_data.num_services = 0;
+        p = p_bta_jv_cfg->p_sdp_db->raw_data;
+        raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+        while(raw_used && p)
+        {
+            op = p;
+            type = *p++;
+            np = sdpu_get_len_from_type(p, type, &len);
+            p = np + len;
+            raw_cur = p - op;
+            if(raw_used >= raw_cur)
+            {
+                raw_used -= raw_cur;
+            }
+            else
+            {
+                /* error. can not continue */
+                break;
+            }
+            if(p_data->get_services_length.inc_hdr)
+            {
+                evt_data.p_services_len[evt_data.num_services++] = len + np - op;
+            }
+            else
+            {
+                evt_data.p_services_len[evt_data.num_services++] = len;
+            }
+        } /* end of while */
+    }
+
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_SERVICES_LEN_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_service_select
+**
+** Description  Obtain the length of given UUID in the SDP DB.
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_service_select(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_SERVICE_SEL     serv_sel;
+    tSDP_DISC_REC *p_rec, *p_tmp;
+    UINT8   *p, *np, *op, type;
+    UINT32  raw_used, raw_cur;
+    UINT32  len;
+
+    serv_sel.service_len = 0;
+    bta_jv_cb.p_sel_raw_data     = 0;
+    p_rec = SDP_FindServiceInDb (p_bta_jv_cfg->p_sdp_db, p_data->service_select.uuid, NULL);
+    if(p_rec)
+    {
+        /* found the record in the database */
+        /* the database must be valid */
+        p = p_bta_jv_cfg->p_sdp_db->raw_data;
+        raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+        p_tmp = p_bta_jv_cfg->p_sdp_db->p_first_rec;
+        while(raw_used && p && p_tmp)
+        {
+            op = p;
+            type = *p++;
+            np = sdpu_get_len_from_type(p, type, &len);
+            if(p_tmp == p_rec)
+            {
+                bta_jv_cb.p_sel_raw_data = op;
+                bta_jv_cb.sel_len = len;
+                serv_sel.service_len = len;
+                bdcpy(serv_sel.bd_addr, p_rec->remote_bd_addr);
+                APPL_TRACE_DEBUG1( "bta_jv_service_select found uuid: 0x%x",
+                    p_data->service_select.uuid);
+                break;
+            }
+            p = np + len;
+            raw_cur = p - op;
+            if(raw_used >= raw_cur)
+            {
+                raw_used -= raw_cur;
+            }
+            else
+            {
+                /* error. can not continue */
+                break;
+            }
+            p_tmp = p_tmp->p_next_rec;
+        } /* end of while */
+    }
+    APPL_TRACE_DEBUG1( "service_len: %d", serv_sel.service_len);
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_SERVICE_SEL_EVT, (tBTA_JV *)&serv_sel);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_create_record
+**
+** Description  Create an SDP record with the given attributes
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_create_record(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_API_CREATE_RECORD *cr = &(p_data->create_record);
+    tBTA_JV_CREATE_RECORD   evt_data;
+    evt_data.status = BTA_JV_SUCCESS;
+    if(bta_jv_cb.p_dm_cback)
+        //callback user immediately to create his own sdp record in stack thread context
+        bta_jv_cb.p_dm_cback(BTA_JV_CREATE_RECORD_EVT, (tBTA_JV *)&evt_data, cr->user_data);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_update_record
+**
+** Description  Update an SDP record with the given attributes
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_update_record(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_API_UPDATE_RECORD *ur = &(p_data->update_record);
+    tBTA_JV_UPDATE_RECORD   evt_data;
+    UINT32 handle;
+    INT32 i;
+    UINT8 *ptr;
+    UINT8 *next_ptr;
+    UINT8 *end;
+    UINT32 len;
+    UINT8 type;
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = ur->handle;
+
+    handle = bta_jv_get_sdp_handle(ur->handle);
+
+    if(handle)
+    {
+        /* this is a record created by JV */
+        for (i = 0; i < ur->array_len; i++)
+        {
+            ptr = ur->p_values[i];
+            end = ptr + ur->p_value_sizes[i];
+
+            while (ptr < end)
+            {
+                type = *ptr;
+                next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len);
+
+                if(ATTR_ID_SERVICE_RECORD_HDL != ur->p_ids[i])
+                {
+                if (!SDP_AddAttribute(handle, ur->p_ids[i], (UINT8)((type >> 3) & 0x1f),
+                    len, next_ptr))
+                {
+                    /* failed on updating attributes.  */
+                    if(bta_jv_cb.p_dm_cback)
+                        bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data);
+                    return;
+                }
+                }
+
+                ptr = next_ptr + len;
+            } /* end of while */
+        } /* end of for */
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_UPDATE_RECORD_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_add_attribute
+**
+** Description  Add an attribute to an SDP record
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_add_attribute(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_API_ADD_ATTRIBUTE *aa = &(p_data->add_attr);
+    tBTA_JV_ADD_ATTR   evt_data;
+    UINT32 handle;
+    UINT8 type;
+    UINT32 len;
+    UINT8 *ptr;
+    UINT8 *next_ptr;
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = aa->handle;
+    handle = bta_jv_get_sdp_handle(aa->handle);
+
+    if(handle)
+    {
+        /* this is a record created by JV */
+        ptr = aa->p_value;
+        type = *ptr;
+        next_ptr = sdpu_get_len_from_type(ptr + 1, *ptr, &len);
+        APPL_TRACE_DEBUG3( "bta_jv_add_attribute: ptr chg:%d len:%d, size:%d",
+            (next_ptr - ptr), len, aa->value_size);
+        if(ATTR_ID_SERVICE_RECORD_HDL != aa->attr_id && /* do not allow the SDP record handle to be updated */
+            ((INT32)(next_ptr - ptr + len) == aa->value_size) && /* double check data size */
+            SDP_AddAttribute(handle, aa->attr_id, (UINT8)((type >> 3) & 0x1f),
+                    len, next_ptr))
+        {
+            evt_data.status = BTA_JV_SUCCESS;
+        }
+    }
+
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_ADD_ATTR_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_delete_attribute
+**
+** Description  Delete an attribute from the given SDP record
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_delete_attribute(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_API_ADD_ATTRIBUTE *da = &(p_data->add_attr);
+    tBTA_JV_DELETE_ATTR   evt_data;
+    UINT32 handle;
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = da->handle;
+    handle = bta_jv_get_sdp_handle(da->handle);
+
+    if(handle)
+    {
+        /* this is a record created by JV */
+        if(SDP_DeleteAttribute(handle, da->attr_id))
+            evt_data.status = BTA_JV_SUCCESS;
+    }
+
+    if(bta_jv_cb.p_dm_cback)
+        bta_jv_cb.p_dm_cback(BTA_JV_DELETE_ATTR_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_delete_record
+**
+** Description  Delete an SDP record
+**
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_delete_record(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_API_ADD_ATTRIBUTE *dr = &(p_data->add_attr);
+    UINT32 handle;
+
+    handle = bta_jv_get_sdp_handle(dr->handle);
+
+    if(handle)
+    {
+        /* this is a record created by JV */
+        SDP_DeleteRecord(handle);
+        bta_jv_free_sdp_id(dr->handle);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_client_cback
+**
+** Description  handles the l2cap client events
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_l2cap_client_cback(UINT16 gap_handle, UINT16 event)
+{
+#if 0
+    tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
+    tBTA_JV     evt_data;
+
+    if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
+        return;
+
+    APPL_TRACE_DEBUG2( "bta_jv_l2cap_client_cback: %d evt:x%x",
+        gap_handle, event);
+    evt_data.l2c_open.status = BTA_JV_SUCCESS;
+    evt_data.l2c_open.handle = gap_handle;
+    switch (event)
+    {
+    case GAP_EVT_CONN_OPENED:
+        bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
+        evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
+        p_cb->state = BTA_JV_ST_CL_OPEN;
+        p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+        break;
+
+    case GAP_EVT_CONN_CLOSED:
+        p_cb->state = BTA_JV_ST_NONE;
+        bta_jv_free_sec_id(&p_cb->sec_id);
+        evt_data.l2c_close.async = TRUE;
+        p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data);
+        p_cb->p_cback = NULL;
+        break;
+
+    case GAP_EVT_CONN_DATA_AVAIL:
+        evt_data.handle = gap_handle;
+        p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+        break;
+
+    case GAP_EVT_CONN_CONGESTED:
+    case GAP_EVT_CONN_UNCONGESTED:
+        p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
+        evt_data.l2c_cong.cong = p_cb->cong;
+        p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data);
+        break;
+
+    default:
+        break;
+    }
+#endif
+}
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function     bta_jv_sdp_res_cback
+**
+** Description  Callback for Start Discovery
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_sdp_res_cback (UINT16 event, tSDP_DATA *p_data)
+{
+    tBTA_JV evt_data;
+    tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL];
+
+    APPL_TRACE_DEBUG2( "bta_jv_sdp_res_cback: %d evt:x%x",
+        bta_jv_cb.sdp_for_jv, event);
+
+    if(!bta_jv_cb.sdp_for_jv)
+        return;
+
+    evt_data.l2c_open.status = BTA_JV_SUCCESS;
+    evt_data.l2c_open.handle = BTA_JV_L2C_FOR_SDP_HDL;
+
+    switch(event)
+    {
+    case SDP_EVT_OPEN:
+        bdcpy(evt_data.l2c_open.rem_bda, p_data->open.peer_addr);
+        evt_data.l2c_open.tx_mtu = p_data->open.peer_mtu;
+        p_cb->state = BTA_JV_ST_SR_OPEN;
+        p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+        break;
+    case SDP_EVT_DATA_IND:
+        evt_data.handle = BTA_JV_L2C_FOR_SDP_HDL;
+        memcpy(p_bta_jv_cfg->p_sdp_raw_data, p_data->data.p_data, p_data->data.data_len);
+        APPL_TRACE_DEBUG2( "data size: %d/%d ", bta_jv_cb.sdp_data_size, p_data->data.data_len);
+        bta_jv_cb.sdp_data_size = p_data->data.data_len;
+        p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+        break;
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_sdp_cback
+**
+** Description  Callback for Start Discovery
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_sdp_cback(UINT16 result)
+{
+    tBTA_JV_L2CAP_CLOSE close;
+    tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[BTA_JV_L2C_FOR_SDP_HDL];
+    APPL_TRACE_DEBUG1( "bta_jv_sdp_cback: result:x%x", result);
+
+    if(p_cb->p_cback)
+    {
+        close.handle    = BTA_JV_L2C_FOR_SDP_HDL;
+        close.async     = FALSE;
+        close.status    = BTA_JV_SUCCESS;
+        bta_jv_free_sec_id(&p_cb->sec_id);
+        p_cb->p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&close);
+    }
+
+    bta_jv_cb.sdp_for_jv = 0;
+    p_cb->p_cback = NULL;
+
+}
+#endif
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_connect
+**
+** Description  makes an l2cap client connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_connect(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2C_CB      *p_cb;
+    tBTA_JV_L2CAP_CL_INIT  evt_data;
+    UINT16  handle=GAP_INVALID_HANDLE;
+    UINT8   sec_id;
+    tL2CAP_CFG_INFO cfg;
+    tBTA_JV_API_L2CAP_CONNECT *cc = &(p_data->l2cap_connect);
+
+    memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+    cfg.mtu_present = TRUE;
+    cfg.mtu = cc->rx_mtu;
+    /* TODO: DM role manager
+    L2CA_SetDesireRole(cc->role);
+    */
+
+    sec_id = bta_jv_alloc_sec_id();
+    evt_data.sec_id = sec_id;
+    evt_data.status = BTA_JV_FAILURE;
+    if (sec_id)
+    {
+#if SDP_FOR_JV_INCLUDED == TRUE
+        if(SDP_PSM == cc->remote_psm && 0 == bta_jv_cb.sdp_for_jv)
+        {
+            bta_jv_cb.sdp_for_jv = SDP_ConnOpen(cc->peer_bd_addr,
+                                       bta_jv_sdp_res_cback,
+                                       bta_jv_sdp_cback);
+            if(bta_jv_cb.sdp_for_jv)
+            {
+                bta_jv_cb.sdp_data_size = 0;
+                handle = BTA_JV_L2C_FOR_SDP_HDL;
+                evt_data.status = BTA_JV_SUCCESS;
+            }
+        }
+        else
+#endif
+        if(bta_jv_check_psm(cc->remote_psm)) /* allowed */
+        {
+            if( (handle = GAP_ConnOpen("", sec_id, 0, cc->peer_bd_addr, cc->remote_psm,
+                &cfg, cc->sec_mask, GAP_FCR_CHAN_OPT_BASIC,
+                bta_jv_l2cap_client_cback)) != GAP_INVALID_HANDLE )
+            {
+                evt_data.status = BTA_JV_SUCCESS;
+            }
+        }
+    }
+
+    if (evt_data.status == BTA_JV_SUCCESS)
+    {
+        p_cb = &bta_jv_cb.l2c_cb[handle];
+        p_cb->handle = handle;
+        p_cb->p_cback = cc->p_cback;
+        p_cb->psm = 0;  /* not a server */
+        p_cb->sec_id = sec_id;
+        p_cb->state = BTA_JV_ST_CL_OPENING;
+    }
+    else
+    {
+        bta_jv_free_sec_id(&sec_id);
+    }
+    evt_data.handle = handle;
+    cc->p_cback(BTA_JV_L2CAP_CL_INIT_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_close
+**
+** Description  Close an L2CAP client connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_close(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2CAP_CLOSE  evt_data;
+    tBTA_JV_API_L2CAP_CLOSE *cc = &(p_data->l2cap_close);
+    tBTA_JV_L2CAP_CBACK *p_cback = cc->p_cb->p_cback;
+
+    evt_data.handle = cc->handle;
+    evt_data.status = bta_jv_free_l2c_cb(cc->p_cb);
+    evt_data.async = FALSE;
+
+    if (p_cback)
+        p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data);
+    else
+        APPL_TRACE_ERROR0("### NO CALLBACK SET !!! ###");
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         bta_jv_l2cap_server_cback
+**
+** Description      handles the l2cap server callback
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_jv_l2cap_server_cback(UINT16 gap_handle, UINT16 event)
+{
+#if 0
+    tBTA_JV_L2C_CB  *p_cb = &bta_jv_cb.l2c_cb[gap_handle];
+    tBTA_JV evt_data;
+    tBTA_JV_L2CAP_CBACK *p_cback;
+
+    if(gap_handle >= BTA_JV_MAX_L2C_CONN && !p_cb->p_cback)
+        return;
+
+    APPL_TRACE_DEBUG2( "bta_jv_l2cap_server_cback: %d evt:x%x",
+        gap_handle, event);
+    evt_data.l2c_open.status = BTA_JV_SUCCESS;
+    evt_data.l2c_open.handle = gap_handle;
+
+    switch (event)
+    {
+    case GAP_EVT_CONN_OPENED:
+        bdcpy(evt_data.l2c_open.rem_bda, GAP_ConnGetRemoteAddr(gap_handle));
+        evt_data.l2c_open.tx_mtu = GAP_ConnGetRemMtuSize(gap_handle);
+        p_cb->state = BTA_JV_ST_SR_OPEN;
+        p_cb->p_cback(BTA_JV_L2CAP_OPEN_EVT, &evt_data);
+        break;
+
+    case GAP_EVT_CONN_CLOSED:
+        evt_data.l2c_close.async = TRUE;
+        evt_data.l2c_close.handle = p_cb->handle;
+        p_cback = p_cb->p_cback;
+        evt_data.l2c_close.status = bta_jv_free_l2c_cb(p_cb);
+        p_cback(BTA_JV_L2CAP_CLOSE_EVT, &evt_data);
+        break;
+
+    case GAP_EVT_CONN_DATA_AVAIL:
+        evt_data.handle = gap_handle;
+        p_cb->p_cback(BTA_JV_L2CAP_DATA_IND_EVT, &evt_data);
+        break;
+
+    case GAP_EVT_CONN_CONGESTED:
+    case GAP_EVT_CONN_UNCONGESTED:
+        p_cb->cong = (event == GAP_EVT_CONN_CONGESTED) ? TRUE : FALSE;
+        evt_data.l2c_cong.cong = p_cb->cong;
+        p_cb->p_cback(BTA_JV_L2CAP_CONG_EVT, &evt_data);
+        break;
+
+    default:
+        break;
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_start_server
+**
+** Description  starts an L2CAP server
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_start_server(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2C_CB      *p_cb;
+    UINT8   sec_id;
+    UINT16  handle;
+    tL2CAP_CFG_INFO cfg;
+    tBTA_JV_L2CAP_START evt_data;
+    tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
+
+    memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+
+    //FIX: MTU=0 means not present
+    if (ls->rx_mtu >0)
+    {
+        cfg.mtu_present = TRUE;
+        cfg.mtu = ls->rx_mtu;
+    }
+    else
+    {
+        cfg.mtu_present = FALSE;
+        cfg.mtu = 0;
+    }
+
+    /* TODO DM role manager
+    L2CA_SetDesireRole(ls->role);
+    */
+
+    sec_id = bta_jv_alloc_sec_id();
+    if (0 == sec_id || (FALSE == bta_jv_check_psm(ls->local_psm)) ||
+        (handle = GAP_ConnOpen("JV L2CAP", sec_id, 1, 0, ls->local_psm, &cfg,
+            ls->sec_mask, GAP_FCR_CHAN_OPT_BASIC, bta_jv_l2cap_server_cback)) == GAP_INVALID_HANDLE)
+    {
+        bta_jv_free_sec_id(&sec_id);
+        evt_data.status = BTA_JV_FAILURE;
+    }
+    else
+    {
+        /* default JV implementation requires explicit call
+           to allow incoming connections when ready*/
+
+        GAP_SetAcceptReady(handle, FALSE);
+
+        p_cb = &bta_jv_cb.l2c_cb[handle];
+        evt_data.status = BTA_JV_SUCCESS;
+        evt_data.handle = handle;
+        evt_data.sec_id = sec_id;
+        p_cb->p_cback = ls->p_cback;
+        p_cb->handle = handle;
+        p_cb->sec_id = sec_id;
+        p_cb->state = BTA_JV_ST_SR_LISTEN;
+        p_cb->psm = ls->local_psm;
+    }
+    ls->p_cback(BTA_JV_L2CAP_START_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_stop_server
+**
+** Description  stops an L2CAP server
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_stop_server(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2C_CB      *p_cb;
+    tBTA_JV_L2CAP_CLOSE  evt_data;
+    tBTA_JV_API_L2CAP_SERVER *ls = &(p_data->l2cap_server);
+    tBTA_JV_L2CAP_CBACK *p_cback;
+    int i;
+
+    for(i=0; i<BTA_JV_MAX_L2C_CONN; i++)
+    {
+        if(bta_jv_cb.l2c_cb[i].psm == ls->local_psm)
+        {
+            p_cb = &bta_jv_cb.l2c_cb[i];
+            p_cback = p_cb->p_cback;
+            evt_data.handle = p_cb->handle;
+            evt_data.status = bta_jv_free_l2c_cb(p_cb);
+            evt_data.async = FALSE;
+            p_cback(BTA_JV_L2CAP_CLOSE_EVT, (tBTA_JV *)&evt_data);
+            break;
+        }
+    }
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_read
+**
+** Description  Read data from an L2CAP connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_read(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2CAP_READ evt_data;
+    tBTA_JV_API_L2CAP_READ *rc = &(p_data->l2cap_read);
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = rc->handle;
+    evt_data.req_id = rc->req_id;
+    evt_data.p_data = rc->p_data;
+    evt_data.len    = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+    if(BTA_JV_L2C_FOR_SDP_HDL == rc->handle)
+    {
+        evt_data.len = rc->len;
+        if(evt_data.len > bta_jv_cb.sdp_data_size)
+            evt_data.len = bta_jv_cb.sdp_data_size;
+
+        memcpy(rc->p_data, p_bta_jv_cfg->p_sdp_raw_data, evt_data.len);
+        bta_jv_cb.sdp_data_size = 0;
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+    else
+#endif
+    if (BT_PASS == GAP_ConnReadData(rc->handle, rc->p_data, rc->len, &evt_data.len))
+    {
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+
+    rc->p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function     bta_jv_l2cap_write
+**
+** Description  Write data to an L2CAP connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_l2cap_write(tBTA_JV_MSG *p_data)
+{
+#if 0
+    tBTA_JV_L2CAP_WRITE evt_data;
+    tBTA_JV_API_L2CAP_WRITE *ls = &(p_data->l2cap_write);
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = ls->handle;
+    evt_data.req_id = ls->req_id;
+    evt_data.cong   = ls->p_cb->cong;
+    evt_data.len    = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+    if(BTA_JV_L2C_FOR_SDP_HDL == ls->handle)
+    {
+        UINT8   *p;
+        BT_HDR  *p_msg = (BT_HDR *) GKI_getbuf ((UINT16)(ls->len + BT_HDR_SIZE + L2CAP_MIN_OFFSET));
+        if(p_msg)
+        {
+            p_msg->offset = L2CAP_MIN_OFFSET;
+            p = (UINT8 *)(p_msg + 1) + L2CAP_MIN_OFFSET;
+            p_msg->len = ls->len;
+            memcpy(p, ls->p_data, p_msg->len);
+            if(SDP_WriteData (bta_jv_cb.sdp_for_jv, p_msg))
+            {
+                evt_data.len    = ls->len;
+                evt_data.status = BTA_JV_SUCCESS;
+            }
+        }
+    }
+    else
+#endif
+    if (!evt_data.cong &&
+        BT_PASS == GAP_ConnWriteData(ls->handle, ls->p_data, ls->len, &evt_data.len))
+    {
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+
+    ls->p_cb->p_cback(BTA_JV_L2CAP_WRITE_EVT, (tBTA_JV *)&evt_data);
+#endif
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_port_data_co_cback
+**
+** Description  port data callback function of rfcomm
+**              connections
+**
+** Returns      void
+**
+*******************************************************************************/
+/*
+#define DATA_CO_CALLBACK_TYPE_INCOMING          1
+#define DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE     2
+#define DATA_CO_CALLBACK_TYPE_OUTGOING          3
+*/
+static int bta_jv_port_data_co_cback(UINT16 port_handle, UINT8 *buf, UINT16 len, int type)
+{
+    tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+    tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+
+    if (p_cb != NULL)
+    {
+        switch(type)
+        {
+            case DATA_CO_CALLBACK_TYPE_INCOMING:
+                return bta_co_rfc_data_incoming(p_pcb->user_data, (BT_HDR*)buf);
+            case DATA_CO_CALLBACK_TYPE_OUTGOING_SIZE:
+                return bta_co_rfc_data_outgoing_size(p_pcb->user_data, (int*)buf);
+            case DATA_CO_CALLBACK_TYPE_OUTGOING:
+                return bta_co_rfc_data_outgoing(p_pcb->user_data, buf, len);
+            default:
+                APPL_TRACE_ERROR1("unknown callout type:%d", type);
+                break;
+        }
+    }
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_port_mgmt_cl_cback
+**
+** Description  callback for port mamangement function of rfcomm
+**              client connections
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_port_mgmt_cl_cback(UINT32 code, UINT16 port_handle)
+{
+    tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+    tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+    tBTA_JV evt_data;
+    BD_ADDR rem_bda;
+    UINT16 lcid;
+    tBTA_JV_RFCOMM_CBACK *p_cback;  /* the callback function */
+
+    APPL_TRACE_DEBUG1( "bta_jv_port_mgmt_cl_cback:%d", port_handle);
+    if(NULL == p_cb || NULL == p_cb->p_cback)
+        return;
+
+    APPL_TRACE_DEBUG3( "bta_jv_port_mgmt_cl_cback code=%d port_handle:%d handle:%d",
+        code, port_handle, p_cb->handle);
+
+    PORT_CheckConnection(port_handle, rem_bda, &lcid);
+
+    if(code == PORT_SUCCESS)
+    {
+        evt_data.rfc_open.handle = p_cb->handle;
+        evt_data.rfc_open.status = BTA_JV_SUCCESS;
+        bdcpy(evt_data.rfc_open.rem_bda, rem_bda);
+        p_pcb->state = BTA_JV_ST_CL_OPEN;
+        p_cb->p_cback(BTA_JV_RFCOMM_OPEN_EVT, &evt_data, p_pcb->user_data);
+    }
+    else
+    {
+        evt_data.rfc_close.handle = p_cb->handle;
+        evt_data.rfc_close.status = BTA_JV_FAILURE;
+        evt_data.rfc_close.port_status = code;
+        evt_data.rfc_close.async = TRUE;
+        if (p_pcb->state == BTA_JV_ST_CL_CLOSING)
+        {
+            evt_data.rfc_close.async = FALSE;
+        }
+        p_pcb->state = BTA_JV_ST_NONE;
+        p_pcb->cong = FALSE;
+        p_cback = p_cb->p_cback;
+        bta_jv_free_rfc_cb(p_cb);
+
+        p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, p_pcb->user_data);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_port_event_cl_cback
+**
+** Description  Callback for RFCOMM client port events
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_port_event_cl_cback(UINT32 code, UINT16 port_handle)
+{
+    tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+    tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+    tBTA_JV evt_data;
+
+    APPL_TRACE_DEBUG1( "bta_jv_port_event_cl_cback:%d", port_handle);
+    if(NULL == p_cb || NULL == p_cb->p_cback)
+        return;
+
+    APPL_TRACE_DEBUG3( "bta_jv_port_event_cl_cback code=x%x port_handle:%d handle:%d",
+        code, port_handle, p_cb->handle);
+    if (code & PORT_EV_RXCHAR)
+    {
+        evt_data.data_ind.handle = p_cb->handle;
+        p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, p_pcb->user_data);
+    }
+
+    if (code & PORT_EV_FC)
+    {
+        p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
+        evt_data.rfc_cong.cong = p_pcb->cong;
+        evt_data.rfc_cong.handle = p_cb->handle;
+        evt_data.rfc_cong.status = BTA_JV_SUCCESS;
+        p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, p_pcb->user_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_connect
+**
+** Description  Client initiates an RFCOMM connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_connect(tBTA_JV_MSG *p_data)
+{
+    UINT16 handle = 0;
+    UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+    tPORT_STATE port_state;
+    UINT8   sec_id;
+    tBTA_JV_RFC_CB  *p_cb = NULL;
+    tBTA_JV_PCB     *p_pcb;
+    tBTA_JV_API_RFCOMM_CONNECT *cc = &(p_data->rfcomm_connect);
+    tBTA_JV_RFCOMM_CL_INIT      evt_data;
+
+    /* TODO DM role manager
+    L2CA_SetDesireRole(cc->role);
+    */
+
+    sec_id = bta_jv_alloc_sec_id();
+    evt_data.sec_id = sec_id;
+    evt_data.status = BTA_JV_SUCCESS;
+    if (0 == sec_id ||
+        BTM_SetSecurityLevel(TRUE, "", sec_id,  cc->sec_mask, BT_PSM_RFCOMM,
+                BTM_SEC_PROTO_RFCOMM, cc->remote_scn) == FALSE)
+    {
+        evt_data.status = BTA_JV_FAILURE;
+        error("sec_id:%d is zero or BTM_SetSecurityLevel failed, remote_scn:%d", sec_id, cc->remote_scn);
+    }
+
+    if (evt_data.status == BTA_JV_SUCCESS &&
+        RFCOMM_CreateConnection(UUID_SERVCLASS_SERIAL_PORT, cc->remote_scn, FALSE,
+        BTA_JV_DEF_RFC_MTU, cc->peer_bd_addr, &handle, bta_jv_port_mgmt_cl_cback) != PORT_SUCCESS)
+    {
+        evt_data.status = BTA_JV_FAILURE;
+    }
+    if (evt_data.status == BTA_JV_SUCCESS)
+    {
+        p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
+        if(p_cb)
+        {
+            p_cb->p_cback = cc->p_cback;
+            p_cb->sec_id = sec_id;
+            p_cb->scn = 0;
+            p_pcb->state = BTA_JV_ST_CL_OPENING;
+            p_pcb->user_data = cc->user_data;
+            evt_data.use_co = TRUE;
+
+            PORT_SetEventCallback(handle, bta_jv_port_event_cl_cback);
+            PORT_SetEventMask(handle, event_mask);
+            PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
+
+            PORT_GetState(handle, &port_state);
+
+            port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+            /* coverity[uninit_use_in_call]
+               FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+            PORT_SetState(handle, &port_state);
+
+            evt_data.handle = p_cb->handle;
+        }
+        else
+        {
+            evt_data.status = BTA_JV_FAILURE;
+            APPL_TRACE_ERROR0("run out of rfc control block");
+        }
+    }
+    cc->p_cback(BTA_JV_RFCOMM_CL_INIT_EVT, (tBTA_JV *)&evt_data, cc->user_data);
+ }
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_close
+**
+** Description  Close an RFCOMM connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_close(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_RFCOMM_CLOSE     evt_data;
+    tBTA_JV_API_RFCOMM_CLOSE *cc = &(p_data->rfcomm_close);
+    tBTA_JV_RFC_CB           *p_cb = cc->p_cb;
+    tBTA_JV_PCB              *p_pcb = cc->p_pcb;
+    tBTA_JV_RFCOMM_CBACK     *p_cback = p_cb->p_cback;
+
+    evt_data.handle = p_cb->handle;
+    evt_data.status = BTA_JV_FAILURE;
+
+    void* user_data = p_pcb->user_data;
+    p_pcb->cong = FALSE;
+    if(p_pcb->state <= BTA_JV_ST_CL_MAX)
+    {
+        if(p_pcb->state == BTA_JV_ST_CL_OPEN)
+        {
+            if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle))
+            {
+                p_pcb->state = BTA_JV_ST_CL_CLOSING;
+                return;
+            }
+        }
+        evt_data.status = bta_jv_free_rfc_cb(p_cb);
+    }
+    else if(BTA_JV_ST_SR_OPEN == p_pcb->state)
+    {
+        /* server is connected */
+        if(PORT_SUCCESS == RFCOMM_RemoveConnection(p_pcb->port_handle))
+        {
+            p_pcb->state = BTA_JV_ST_SR_CLOSING;
+            return;
+        }
+    }
+
+    evt_data.async = FALSE;
+
+    if (p_cback)
+        p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+    else
+        error("### NO CALLBACK SET !!! ###");
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_get_num_rfc_listen
+**
+** Description  when a RFCOMM connection goes down, make sure that there's only
+**              one port stays listening on this scn.
+**
+** Returns
+**
+*******************************************************************************/
+static UINT8 bta_jv_get_num_rfc_listen(tBTA_JV_RFC_CB *p_cb)
+{
+    UINT8   i, listen=1;
+    tBTA_JV_PCB *p_pcb;
+
+    if (p_cb->max_sess > 1)
+    {
+        listen = 0;
+        for (i=0; i<p_cb->max_sess; i++)
+        {
+            if (p_cb->rfc_hdl[i] != 0)
+            {
+                p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+                if (BTA_JV_ST_SR_LISTEN == p_pcb->state)
+                {
+                    listen++;
+                }
+            }
+        }
+    }
+    return listen;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_port_mgmt_sr_cback
+**
+** Description  callback for port mamangement function of rfcomm
+**              server connections
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_port_mgmt_sr_cback(UINT32 code, UINT16 port_handle)
+{
+    tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+    tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+    tBTA_JV evt_data;
+    BD_ADDR rem_bda;
+    UINT16 lcid;
+    UINT8  num;
+    tBTA_JV_RFCOMM_CBACK    *p_cback;
+    UINT32  si;
+
+    if(NULL == p_cb || NULL == p_cb->p_cback)
+        return;
+    void *user_data = p_pcb->user_data;
+    APPL_TRACE_DEBUG4( "bta_jv_port_mgmt_sr_cback code=%d port_handle:%d handle:%d/0x%x",
+        code, port_handle, p_cb->handle, p_pcb->handle);
+
+    PORT_CheckConnection(port_handle, rem_bda, &lcid);
+    int failed = TRUE;
+    if(code == PORT_SUCCESS)
+    {
+        evt_data.rfc_srv_open.handle = p_pcb->handle;
+        evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
+        bdcpy(evt_data.rfc_srv_open.rem_bda, rem_bda);
+        p_pcb->state = BTA_JV_ST_SR_OPEN;
+        tBTA_JV_PCB *p_pcb_new_listen  = bta_jv_add_rfc_port(p_cb);
+        if(p_pcb_new_listen)
+        {
+            evt_data.rfc_srv_open.new_listen_handle = p_pcb_new_listen->handle;
+            p_pcb_new_listen->user_data = p_cb->p_cback(BTA_JV_RFCOMM_SRV_OPEN_EVT, &evt_data, user_data);
+            failed = FALSE;
+        }
+        else error("bta_jv_add_rfc_port failed to create new listen port");
+    }
+    if(failed)
+    {
+        evt_data.rfc_close.handle = p_cb->handle;
+        evt_data.rfc_close.status = BTA_JV_SUCCESS;
+        evt_data.rfc_close.async = TRUE;
+        if(BTA_JV_ST_SR_CLOSING == p_pcb->state)
+        {
+            evt_data.rfc_close.async = FALSE;
+        }
+        p_pcb->cong = FALSE;
+        p_cback = p_cb->p_cback;
+        APPL_TRACE_DEBUG1( "removing rfc handle:0x%x", p_pcb->handle);
+        si = BTA_JV_RFC_HDL_TO_SIDX(p_pcb->handle);
+        p_cb->rfc_hdl[si] = 0;
+        p_pcb->state = BTA_JV_ST_NONE;
+        p_pcb->handle = 0;
+        RFCOMM_RemoveServer(port_handle);
+        evt_data.rfc_close.port_status = code;
+        p_cback(BTA_JV_RFCOMM_CLOSE_EVT, &evt_data, user_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_port_event_sr_cback
+**
+** Description  Callback for RFCOMM server port events
+**
+** Returns      void
+**
+*******************************************************************************/
+static void bta_jv_port_event_sr_cback(UINT32 code, UINT16 port_handle)
+{
+    tBTA_JV_PCB     *p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
+    tBTA_JV_RFC_CB  *p_cb = bta_jv_rfc_port_to_cb(port_handle);
+    tBTA_JV evt_data;
+
+    if(NULL == p_cb || NULL == p_cb->p_cback)
+        return;
+
+    APPL_TRACE_DEBUG3( "bta_jv_port_event_sr_cback code=x%x port_handle:%d handle:%d",
+        code, port_handle, p_cb->handle);
+
+    void *user_data = p_pcb->user_data;
+    if (code & PORT_EV_RXCHAR)
+    {
+        evt_data.data_ind.handle = p_cb->handle;
+        p_cb->p_cback(BTA_JV_RFCOMM_DATA_IND_EVT, &evt_data, user_data);
+    }
+
+    if (code & PORT_EV_FC)
+    {
+        p_pcb->cong = (code & PORT_EV_FCS) ? FALSE : TRUE;
+        evt_data.rfc_cong.cong = p_pcb->cong;
+        evt_data.rfc_cong.handle = p_cb->handle;
+        evt_data.rfc_cong.status = BTA_JV_SUCCESS;
+        p_cb->p_cback(BTA_JV_RFCOMM_CONG_EVT, &evt_data, user_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_add_rfc_port
+**
+** Description  add a port for server when the existing posts is open
+**
+** Returns   return a pointer to tBTA_JV_PCB just added
+**
+*******************************************************************************/
+static tBTA_JV_PCB * bta_jv_add_rfc_port(tBTA_JV_RFC_CB *p_cb)
+{
+    UINT8   used = 0, i, listen=0;
+    UINT32  si = 0;
+    tBTA_JV_PCB *p_pcb = NULL;
+    tPORT_STATE port_state;
+    UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+
+    if (p_cb->max_sess > 1)
+    {
+        for (i=0; i<p_cb->max_sess; i++)
+        {
+            if (p_cb->rfc_hdl[i] != 0)
+            {
+                p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[i] - 1];
+                if (p_pcb->state == BTA_JV_ST_SR_LISTEN)
+                    listen++;
+                used++;
+            }
+            else if (si==0)
+            {
+                si = (UINT32)(i + 1);
+            }
+        }
+
+        debug("bta_jv_add_rfc_port max_sess=%d used:%d listen:%d si:%d",
+                    p_cb->max_sess, used, listen, si);
+        if (used <p_cb->max_sess && listen==0 && si)
+        {
+            si--;
+            if (RFCOMM_CreateConnection(p_cb->sec_id, p_cb->scn, TRUE,
+                BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &(p_cb->rfc_hdl[si]), bta_jv_port_mgmt_sr_cback) == PORT_SUCCESS)
+            {
+                p_pcb = &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1];
+                p_pcb->state = BTA_JV_ST_SR_LISTEN;
+                p_pcb->port_handle = p_cb->rfc_hdl[si];
+                PORT_SetEventCallback(p_pcb->port_handle, bta_jv_port_event_sr_cback);
+                PORT_SetDataCOCallback (p_pcb->port_handle, bta_jv_port_data_co_cback);
+                PORT_SetEventMask(p_pcb->port_handle, event_mask);
+                PORT_GetState(p_pcb->port_handle, &port_state);
+
+                port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+/* coverity[uninit_use_in_call]
+FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+                PORT_SetState(p_pcb->port_handle, &port_state);
+                p_pcb->handle = BTA_JV_RFC_H_S_TO_HDL(p_cb->handle, si);
+                APPL_TRACE_DEBUG1( "new rfc handle:0x%x", p_pcb->handle);
+            }
+        }
+    }
+    return p_pcb;
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_start_server
+**
+** Description  waits for an RFCOMM client to connect
+**
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_start_server(tBTA_JV_MSG *p_data)
+{
+    UINT16 handle = 0;
+    UINT32 event_mask = (PORT_EV_RXCHAR | PORT_EV_FC | PORT_EV_FCS);
+    tPORT_STATE port_state;
+    UINT8   sec_id;
+    tBTA_JV_RFC_CB  *p_cb = NULL;
+    tBTA_JV_PCB     *p_pcb;
+    tBTA_JV_API_RFCOMM_SERVER *rs = &(p_data->rfcomm_server);
+    tBTA_JV_RFCOMM_START        evt_data;
+
+    /* TODO DM role manager
+    L2CA_SetDesireRole(rs->role);
+    */
+    evt_data.status = BTA_JV_FAILURE;
+    do
+    {
+        sec_id = bta_jv_alloc_sec_id();
+
+        if (0 == sec_id ||
+            BTM_SetSecurityLevel(FALSE, "JV PORT", sec_id,  rs->sec_mask,
+                BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, rs->local_scn) == FALSE)
+        {
+            break;
+        }
+
+        if (RFCOMM_CreateConnection(sec_id, rs->local_scn, TRUE,
+            BTA_JV_DEF_RFC_MTU, (UINT8 *) bd_addr_any, &handle, bta_jv_port_mgmt_sr_cback) != PORT_SUCCESS)
+        {
+            break;
+        }
+
+        p_cb = bta_jv_alloc_rfc_cb(handle, &p_pcb);
+        if(!p_cb)
+        {
+            APPL_TRACE_ERROR0("run out of rfc control block");
+            break;
+        }
+
+        p_cb->max_sess = rs->max_session;
+        p_cb->p_cback = rs->p_cback;
+        p_cb->sec_id = sec_id;
+        p_cb->scn = rs->local_scn;
+        p_pcb->state = BTA_JV_ST_SR_LISTEN;
+        p_pcb->user_data = rs->user_data;
+        evt_data.status = BTA_JV_SUCCESS;
+        evt_data.handle = p_cb->handle;
+        evt_data.sec_id = sec_id;
+        evt_data.use_co = TRUE; //FALSE;
+
+        PORT_SetEventCallback(handle, bta_jv_port_event_sr_cback);
+        PORT_SetEventMask(handle, event_mask);
+        PORT_GetState(handle, &port_state);
+
+        port_state.fc_type = (PORT_FC_CTS_ON_INPUT | PORT_FC_CTS_ON_OUTPUT);
+
+/* coverity[uninit_use_in_call]
+FALSE-POSITIVE: port_state is initialized at PORT_GetState() */
+        PORT_SetState(handle, &port_state);
+    } while (0);
+
+    rs->p_cback(BTA_JV_RFCOMM_START_EVT, (tBTA_JV *)&evt_data, rs->user_data);
+    if(evt_data.status == BTA_JV_SUCCESS)
+    {
+        PORT_SetDataCOCallback (handle, bta_jv_port_data_co_cback);
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_stop_server
+**
+** Description  stops an RFCOMM server
+**
+** Returns      void
+**
+*******************************************************************************/
+
+void bta_jv_rfcomm_stop_server(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_RFCOMM_CLOSE  evt_data;
+    int i;
+    tBTA_JV_API_RFCOMM_SERVER *ls = &(p_data->rfcomm_server);
+    HDL2CB(ls->rfc_handle);
+    evt_data.status = BTA_JV_FAILURE;
+    if(p_cb && p_pcb)
+    {
+        evt_data.handle = p_cb->handle;
+        void* user_data = p_pcb->user_data;
+        evt_data.status = bta_jv_free_rfc_listen_cb(p_cb);
+        evt_data.async = FALSE;
+
+        /* occasionally when shutting down stack the callback is already
+           freed, hence make sure we check for this condition (pending investigatation
+           of rootcause) */
+        debug("send BTA_JV_RFCOMM_CLOSE_EVT");
+        if( p_cb->p_cback)
+             p_cb->p_cback(BTA_JV_RFCOMM_CLOSE_EVT, (tBTA_JV *)&evt_data, user_data);
+    }
+    else
+    {
+        debug("warning, no jv callback set");
+    }
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_read
+**
+** Description  Read data from an RFCOMM connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_read(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_API_RFCOMM_READ *rc = &(p_data->rfcomm_read);
+    tBTA_JV_RFC_CB  *p_cb = rc->p_cb;
+    tBTA_JV_PCB     *p_pcb = rc->p_pcb;
+    tBTA_JV_RFCOMM_READ    evt_data;
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = p_cb->handle;
+    evt_data.req_id = rc->req_id;
+    evt_data.p_data = rc->p_data;
+    if (PORT_ReadData(rc->p_pcb->port_handle, (char *)rc->p_data, rc->len, &evt_data.len) ==
+        PORT_SUCCESS)
+    {
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+
+    p_cb->p_cback(BTA_JV_RFCOMM_READ_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
+}
+
+/*******************************************************************************
+**
+** Function     bta_jv_rfcomm_write
+**
+** Description  write data to an RFCOMM connection
+**
+** Returns      void
+**
+*******************************************************************************/
+void bta_jv_rfcomm_write(tBTA_JV_MSG *p_data)
+{
+    tBTA_JV_API_RFCOMM_WRITE *wc = &(p_data->rfcomm_write);
+    tBTA_JV_RFC_CB  *p_cb = wc->p_cb;
+    tBTA_JV_PCB     *p_pcb = wc->p_pcb;
+    tBTA_JV_RFCOMM_WRITE    evt_data;
+
+    evt_data.status = BTA_JV_FAILURE;
+    evt_data.handle = p_cb->handle;
+    evt_data.req_id = wc->req_id;
+    evt_data.cong   = p_pcb->cong;
+    evt_data.len    = 0;
+    if (!evt_data.cong &&
+        PORT_WriteDataCO(p_pcb->port_handle, &evt_data.len) ==
+        PORT_SUCCESS)
+    {
+        evt_data.status = BTA_JV_SUCCESS;
+    }
+    //update congestion flag
+    evt_data.cong   = p_pcb->cong;
+    if (p_cb->p_cback)
+    {
+        p_cb->p_cback(BTA_JV_RFCOMM_WRITE_EVT, (tBTA_JV *)&evt_data, p_pcb->user_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("bta_jv_rfcomm_write :: WARNING ! No JV callback set");
+    }
+}
+
diff --git a/bta/jv/bta_jv_api.c b/bta/jv/bta_jv_api.c
new file mode 100644
index 0000000..8953886
--- /dev/null
+++ b/bta/jv/bta_jv_api.c
@@ -0,0 +1,1584 @@
+/******************************************************************************
+ *
+ *  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 is the implementation of the JAVA API for Bluetooth Wireless
+ *  Technology (JABWT) as specified by the JSR82 specificiation
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_sys.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+#include "gki.h"
+#include <string.h>
+#include "port_api.h"
+#include "sdp_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+static const tBTA_SYS_REG bta_jv_reg =
+{
+    bta_jv_sm_execute,
+    NULL
+};
+
+/*******************************************************************************
+**
+** Function         BTA_JvEnable
+**
+** Description      Enable the Java I/F service. When the enable
+**                  operation is complete the callback function will be
+**                  called with a BTA_JV_ENABLE_EVT. This function must
+**                  be called before other function in the JV API are
+**                  called.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvEnable(tBTA_JV_DM_CBACK *p_cback)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_ENABLE  *p_buf;
+
+    APPL_TRACE_API0( "BTA_JvEnable");
+    if(p_cback && FALSE == bta_sys_is_register(BTA_ID_JV))
+    {
+        memset(&bta_jv_cb, 0, sizeof(tBTA_JV_CB));
+
+        /* register with BTA system manager */
+        GKI_sched_lock();
+        bta_sys_register(BTA_ID_JV, &bta_jv_reg);
+        GKI_sched_unlock();
+
+        if (p_cback && (p_buf = (tBTA_JV_API_ENABLE *) GKI_getbuf(sizeof(tBTA_JV_API_ENABLE))) != NULL)
+        {
+            p_buf->hdr.event = BTA_JV_API_ENABLE_EVT;
+            p_buf->p_cback = p_cback;
+            bta_sys_sendmsg(p_buf);
+            status = BTA_JV_SUCCESS;
+        }
+    }
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvDisable
+**
+** Description      Disable the Java I/F
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_JvDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    APPL_TRACE_API0( "BTA_JvDisable");
+    bta_sys_deregister(BTA_ID_JV);
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_JV_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsEnable
+**
+** Description      Get the JV registration status.
+**
+** Returns          TRUE, if registered
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsEnable(void)
+{
+    return bta_sys_is_register(BTA_ID_JV);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetDiscoverability
+**
+** Description      This function sets the Bluetooth  discoverable modes
+**                  of the local device.  This controls whether other
+**                  Bluetooth devices can find the local device.
+**
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_SET_DISCOVER_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetDiscoverability(tBTA_JV_DISC disc_mode)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_SET_DISCOVERABILITY *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvSetDiscoverability");
+    if ((p_msg = (tBTA_JV_API_SET_DISCOVERABILITY *)GKI_getbuf(sizeof(tBTA_JV_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_SET_DISCOVERABILITY_EVT;
+        p_msg->disc_mode = disc_mode;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetDiscoverability
+**
+** Description      This function gets the Bluetooth
+**                  discoverable modes of local device
+**
+** Returns          The current Bluetooth discoverable mode.
+**
+*******************************************************************************/
+tBTA_JV_DISC BTA_JvGetDiscoverability(void)
+{
+    APPL_TRACE_API0( "BTA_JvGetDiscoverability");
+    return BTM_ReadDiscoverability(0, 0);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetLocalDeviceAddr
+**
+** Description      This function obtains the local Bluetooth device address.
+**                  The local Bluetooth device address is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_ADDR_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetLocalDeviceAddr(void)
+{
+    tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+    BT_HDR *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvGetLocalDeviceAddr");
+    if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT;
+        bta_sys_sendmsg(p_msg);
+        ret = BTA_JV_SUCCESS;
+    }
+
+    return(ret);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetLocalDeviceName
+**
+** Description      This function obtains the name of the local device
+**                  The local Bluetooth device name is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_LOCAL_NAME_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetLocalDeviceName(void)
+{
+    tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+    BT_HDR *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvGetLocalDeviceName");
+    if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT;
+        bta_sys_sendmsg(p_msg);
+        ret = BTA_JV_SUCCESS;
+    }
+
+    return(ret);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetRemoteDeviceName
+**
+** Description      This function obtains the name of the specified device.
+**                  The Bluetooth device name is reported by the
+**                  tBTA_JV_DM_CBACK callback with a BTA_JV_REMOTE_NAME_EVT.
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetRemoteDeviceName(BD_ADDR bd_addr)
+{
+    tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+    tBTA_JV_API_GET_REMOTE_NAME *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvGetRemoteDeviceName");
+    if ((p_msg = (tBTA_JV_API_GET_REMOTE_NAME *)GKI_getbuf(sizeof(tBTA_JV_API_GET_REMOTE_NAME))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+        ret = BTA_JV_SUCCESS;
+    }
+
+    return(ret);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetPreknownDevice
+**
+** Description      This function obtains the Bluetooth address in the inquiry
+**                  database collected via the previous call to BTA_DmSearch().
+**
+** Returns          The number of preknown devices if p_bd_addr is NULL
+**                  BTA_JV_SUCCESS if successful.
+**                  BTA_JV_INTERNAL_ERR(-1) if internal failure.
+**
+*******************************************************************************/
+INT32 BTA_JvGetPreknownDevice(UINT8 * p_bd_addr, UINT32 index)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTM_INQ_INFO *p_info;
+    UINT32  count = 0;
+    INT32   ret = BTA_JV_INTERNAL_ERR;
+
+    APPL_TRACE_API0( "BTA_JvGetPreknownDevice");
+    p_info = BTM_InqFirstResult();
+    if(p_info)
+    {
+        status = BTA_JV_SUCCESS;
+        /* the database is valid */
+        if(NULL == p_bd_addr)
+        {
+            /* p_bd_addr is NULL: count the number of preknown devices */
+            /* set the index to an invalid size (too big) */
+            index = BTM_INQ_DB_SIZE;
+        }
+        else if(index >= BTM_INQ_DB_SIZE)
+        {
+            /* invalid index - error */
+            status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR;
+        }
+
+        if(BTA_JV_SUCCESS == status)
+        {
+            while(p_info && index > count)
+            {
+                count++;
+                p_info = BTM_InqNextResult(p_info);
+            }
+
+            if(p_bd_addr)
+            {
+                if(index == count && p_info)
+                {
+                    count = BTA_JV_SUCCESS;
+                    bdcpy(p_bd_addr, p_info->results.remote_bd_addr);
+                }
+                else
+                    status = (tBTA_JV_STATUS)BTA_JV_INTERNAL_ERR;
+            }
+            /*
+            else report the count
+            */
+        }
+        /*
+        else error had happened.
+        */
+    }
+
+    if(BTA_JV_SUCCESS == status)
+    {
+        ret = count;
+    }
+    return ret;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetDeviceClass
+**
+** Description      This function obtains the local Class of Device. This
+**                  function executes in place. The result is returned right away.
+**
+** Returns          DEV_CLASS, A three-byte array of UINT8 that contains the
+**                  Class of Device information. The definitions are in the
+**                  "Bluetooth Assigned Numbers".
+**
+*******************************************************************************/
+UINT8 * BTA_JvGetDeviceClass(void)
+{
+    APPL_TRACE_API0( "BTA_JvGetDeviceClass");
+    return BTM_ReadDeviceClass();
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetServiceClass
+**
+** Description      This function sets the service class of local Class of Device
+**
+** Returns          BTA_JV_SUCCESS if successful.
+**                  BTA_JV_FAIL if internal failure.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetServiceClass(UINT32 service)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_SET_SERVICE_CLASS *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvSetServiceClass");
+    if ((p_msg = (tBTA_JV_API_SET_SERVICE_CLASS *)GKI_getbuf(sizeof(tBTA_JV_API_SET_SERVICE_CLASS))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_SET_SERVICE_CLASS_EVT;
+        p_msg->service = service;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvSetEncryption
+**
+** Description      This function ensures that the connection to the given device
+**                  is encrypted.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_SET_ENCRYPTION_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvSetEncryption(BD_ADDR bd_addr)
+{
+    tBTA_JV_STATUS ret = BTA_JV_FAILURE;
+    tBTA_JV_API_SET_ENCRYPTION *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvSetEncryption");
+    if ((p_msg = (tBTA_JV_API_SET_ENCRYPTION *)GKI_getbuf(sizeof(tBTA_JV_API_SET_ENCRYPTION))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_SET_ENCRYPTION_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_msg);
+        ret = BTA_JV_SUCCESS;
+    }
+
+    return(ret);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsAuthenticated
+**
+** Description      This function checks if the peer device is authenticated
+**
+** Returns          TRUE if authenticated.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsAuthenticated(BD_ADDR bd_addr)
+{
+    BOOLEAN is_authenticated = FALSE;
+    UINT8 sec_flags;
+
+    if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+    {
+        if(sec_flags&BTM_SEC_FLAG_AUTHENTICATED)
+            is_authenticated = TRUE;
+    }
+    return is_authenticated;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsTrusted
+**
+** Description      This function checks if the peer device is trusted
+**                  (previously paired)
+**
+** Returns          TRUE if trusted.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsTrusted(BD_ADDR bd_addr)
+{
+    BOOLEAN is_trusted = FALSE;
+    UINT8 sec_flags;
+
+    if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+    {
+        if ((sec_flags&BTM_SEC_FLAG_AUTHENTICATED) ||
+            (sec_flags&BTM_SEC_FLAG_LKEY_KNOWN))
+        {
+            is_trusted = TRUE;
+        }
+    }
+    return is_trusted;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsAuthorized
+**
+** Description      This function checks if the peer device is authorized
+**
+** Returns          TRUE if authorized.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsAuthorized(BD_ADDR bd_addr)
+{
+    BOOLEAN is_authorized = FALSE;
+    UINT8 sec_flags;
+
+    if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+    {
+        if(sec_flags&BTM_SEC_FLAG_AUTHORIZED)
+            is_authorized = TRUE;
+    }
+    return is_authorized;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvIsEncrypted
+**
+** Description      This function checks if the link to peer device is encrypted
+**
+** Returns          TRUE if encrypted.
+**                  FALSE if not.
+**
+*******************************************************************************/
+BOOLEAN BTA_JvIsEncrypted(BD_ADDR bd_addr)
+{
+    BOOLEAN is_encrypted = FALSE;
+    UINT8 sec_flags;
+
+    if(BTM_GetSecurityFlags(bd_addr, &sec_flags))
+    {
+        if(sec_flags&BTM_SEC_FLAG_ENCRYPTED)
+            is_encrypted = TRUE;
+    }
+    return is_encrypted;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetSecurityMode
+**
+** Description      This function returns the current Bluetooth security mode
+**                  of the local device
+**
+** Returns          The current Bluetooth security mode.
+**
+*******************************************************************************/
+tBTA_JV_SEC_MODE BTA_JvGetSecurityMode(void)
+{
+   return BTM_GetSecurityMode();
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetSCN
+**
+** Description      This function reserves a SCN (server channel number) for
+**                  applications running over RFCOMM. It is primarily called by
+**                  server profiles/applications to register their SCN into the
+**                  SDP database. The SCN is reported by the tBTA_JV_DM_CBACK
+**                  callback with a BTA_JV_GET_SCN_EVT.
+**                  If the SCN reported is 0, that means all SCN resources are
+**                  exhausted.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetSCN(void)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    BT_HDR *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvGetSCN");
+    if ((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_msg->event = BTA_JV_API_GET_SCN_EVT;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvFreeSCN
+**
+** Description      This function frees a server channel number that was used
+**                  by an application running over RFCOMM.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvFreeSCN(UINT8 scn)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_FREE_SCN *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvFreeSCN");
+    if ((p_msg = (tBTA_JV_API_FREE_SCN *)GKI_getbuf(sizeof(tBTA_JV_API_FREE_SCN))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_FREE_SCN_EVT;
+        p_msg->scn       = scn;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetPSM
+**
+** Description      This function reserves a PSM (Protocol Service Multiplexer)
+**                  applications running over L2CAP. It is primarily called by
+**                  server profiles/applications to register their PSM into the
+**                  SDP database.
+**
+** Returns          The next free PSM
+**
+*******************************************************************************/
+UINT16 BTA_JvGetPSM(void)
+{
+#if 0
+    APPL_TRACE_API0( "BTA_JvGetPSM");
+
+    return (L2CA_AllocatePSM());
+#endif
+    return 0;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvStartDiscovery
+**
+** Description      This function performs service discovery for the services
+**                  provided by the given peer device. When the operation is
+**                  complete the tBTA_JV_DM_CBACK callback function will be
+**                  called with a BTA_JV_DISCOVERY_COMP_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvStartDiscovery(BD_ADDR bd_addr, UINT16 num_uuid,
+            tSDP_UUID *p_uuid_list, void * user_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_START_DISCOVERY *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvStartDiscovery");
+    if ((p_msg = (tBTA_JV_API_START_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_START_DISCOVERY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_START_DISCOVERY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->num_uuid = num_uuid;
+        memcpy(p_msg->uuid_list, p_uuid_list, num_uuid * sizeof(tSDP_UUID));
+        p_msg->num_attr = 0;
+        p_msg->user_data = user_data;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvCancelDiscovery
+**
+** Description      This function cancels an active service discovery.
+**                  When the operation is
+**                  complete the tBTA_JV_DM_CBACK callback function will be
+**                  called with a BTA_JV_CANCEL_DISCVRY_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvCancelDiscovery(void * user_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_CANCEL_DISCOVERY *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvCancelDiscovery");
+    if ((p_msg = (tBTA_JV_API_CANCEL_DISCOVERY *)GKI_getbuf(sizeof(tBTA_JV_API_CANCEL_DISCOVERY))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_CANCEL_DISCOVERY_EVT;
+        p_msg->user_data = user_data;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvGetServicesLength
+**
+** Description      This function obtains the number of services and the length
+**                  of each service found in the SDP database (result of last
+**                  BTA_JvStartDiscovery().When the operation is complete the
+**                  tBTA_JV_DM_CBACK callback function will be called with a
+**                  BTA_JV_SERVICES_LEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvGetServicesLength(BOOLEAN inc_hdr, UINT16 *p_services_len)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_GET_SERVICES_LENGTH *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvGetServicesLength");
+    if ((p_msg = (tBTA_JV_API_GET_SERVICES_LENGTH *)GKI_getbuf(sizeof(tBTA_JV_API_GET_SERVICES_LENGTH))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_GET_SERVICES_LENGTH_EVT;
+        p_msg->p_services_len = p_services_len;
+        p_msg->inc_hdr = inc_hdr;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+/*******************************************************************************
+**
+** Function         BTA_JvGetServicesResult
+**
+** Description      This function returns a number of service records found
+**                  during current service search, equals to the number returned
+**                  by previous call to BTA_JvGetServicesLength.
+**                  The contents of each SDP record will be returned under a
+**                  TLV (type, len, value) representation in the data buffer
+**                  provided by the caller.
+**
+** Returns          -1, if error. Otherwise, the number of services
+**
+*******************************************************************************/
+INT32 BTA_JvGetServicesResult(BOOLEAN inc_hdr, UINT8 **TLVs)
+{
+#if 0
+    INT32 num_services = -1;
+    UINT8   *p, *np, *op, type;
+    UINT32  raw_used, raw_cur;
+    UINT32  len;
+    UINT32  hdr_len;
+
+    APPL_TRACE_API0( "BTA_JvGetServicesResult");
+    if(p_bta_jv_cfg->p_sdp_db->p_first_rec)
+    {
+        /* the database is valid */
+        num_services = 0;
+        p = p_bta_jv_cfg->p_sdp_db->raw_data;
+        raw_used = p_bta_jv_cfg->p_sdp_db->raw_used;
+        while(raw_used && p)
+        {
+            op = p;
+            type = *p++;
+            np = sdpu_get_len_from_type(p, type, &len);
+            p = np + len;
+            raw_cur = p - op;
+            if(raw_used >= raw_cur)
+            {
+                raw_used -= raw_cur;
+            }
+            else
+            {
+                /* error. can not continue */
+                break;
+            }
+            if(inc_hdr)
+            {
+                hdr_len = np - op;
+                memcpy(TLVs[num_services++], op, len+hdr_len);
+            }
+            else
+            {
+                memcpy(TLVs[num_services++], np, len);
+            }
+        } /* end of while */
+    }
+    return(num_services);
+#endif
+    return 0;
+}
+/*******************************************************************************
+**
+** Function         BTA_JvServiceSelect
+**
+** Description      This function checks if the SDP database contains the given
+**                  service UUID. When the operation is complete the
+**                  tBTA_JV_DM_CBACK callback function will be called with a
+**                  BTA_JV_SERVICE_SEL_EVT with the length of the service record.
+**                  If the service is not found or error, -1 is reported.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvServiceSelect(UINT16 uuid)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_SERVICE_SELECT *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvServiceSelect");
+    if ((p_msg = (tBTA_JV_API_SERVICE_SELECT *)GKI_getbuf(sizeof(tBTA_JV_API_SERVICE_SELECT))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_SERVICE_SELECT_EVT;
+        p_msg->uuid = uuid;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvServiceResult
+**
+** Description      This function returns the contents of the SDP record from
+**                  last BTA_JvServiceSelect. The contents will be returned under
+**                  a TLV (type, len, value) representation in the data buffer
+**                  provided by the caller.
+**
+** Returns          -1, if error. Otherwise, the length of service record.
+**
+*******************************************************************************/
+INT32 BTA_JvServiceResult(UINT8 *TLV)
+{
+    INT32   serv_sel = -1;
+
+    APPL_TRACE_API0( "BTA_JvServiceResult");
+    if(bta_jv_cb.p_sel_raw_data)
+    {
+        serv_sel = bta_jv_cb.sel_len;
+        memcpy(TLV, bta_jv_cb.p_sel_raw_data, serv_sel);
+    }
+
+    return serv_sel;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvCreateRecord
+**
+** Description      Create a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_CREATE_RECORD_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvCreateRecordByUser(void *user_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_CREATE_RECORD *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvCreateRecordByUser");
+    if ((p_msg = (tBTA_JV_API_CREATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_CREATE_RECORD))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_CREATE_RECORD_EVT;
+        p_msg->user_data = user_data;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvUpdateRecord
+**
+** Description      Update a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_UPDATE_RECORD_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvUpdateRecord(UINT32 handle, UINT16 *p_ids,
+    UINT8 **p_values, INT32 *p_value_sizes, INT32 array_len)
+{
+#if 0
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_UPDATE_RECORD *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvUpdateRecord");
+    if ((p_msg = (tBTA_JV_API_UPDATE_RECORD *)GKI_getbuf(sizeof(tBTA_JV_API_UPDATE_RECORD))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_UPDATE_RECORD_EVT;
+        p_msg->handle = handle;
+        p_msg->p_ids = p_ids;
+        p_msg->p_values = p_values;
+        p_msg->p_value_sizes = p_value_sizes;
+        p_msg->array_len = array_len;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return(status);
+#endif
+    return -1;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvAddAttribute
+**
+** Description      Add an attribute to a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_ADD_ATTR_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvAddAttribute(UINT32 handle, UINT16 attr_id,
+    UINT8 *p_value, INT32 value_size)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvAddAttribute");
+    if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_ADD_ATTRIBUTE_EVT;
+        p_msg->handle = handle;
+        p_msg->attr_id = attr_id;
+        p_msg->p_value = p_value;
+        p_msg->value_size = value_size;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvDeleteAttribute
+**
+** Description      Delete an attribute from a service record in the local SDP database.
+**                  When the operation is complete the tBTA_JV_DM_CBACK callback
+**                  function will be called with a BTA_JV_DELETE_ATTR_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvDeleteAttribute(UINT32 handle, UINT16 attr_id)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvDeleteAttribute");
+    if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_DELETE_ATTRIBUTE_EVT;
+        p_msg->handle = handle;
+        p_msg->attr_id = attr_id;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvDeleteRecord
+**
+** Description      Delete a service record in the local SDP database.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvDeleteRecord(UINT32 handle)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_ADD_ATTRIBUTE *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvDeleteRecord");
+    if ((p_msg = (tBTA_JV_API_ADD_ATTRIBUTE *)GKI_getbuf(sizeof(tBTA_JV_API_ADD_ATTRIBUTE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_DELETE_RECORD_EVT;
+        p_msg->handle = handle;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvReadRecord
+**
+** Description      Read a service record in the local SDP database.
+**
+** Returns          -1, if the record is not found.
+**                  Otherwise, the offset (0 or 1) to start of data in p_data.
+**
+**                  The size of data copied into p_data is in *p_data_len.
+**
+*******************************************************************************/
+INT32 BTA_JvReadRecord(UINT32 handle, UINT8 *p_data, INT32 *p_data_len)
+{
+    UINT32 sdp_handle;
+
+    sdp_handle = bta_jv_get_sdp_handle(handle);
+
+    if(sdp_handle)
+    {
+        return SDP_ReadRecord(sdp_handle, p_data, p_data_len);
+    }
+
+    return -1;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capConnect
+**
+** Description      Initiate a connection as a L2CAP client to the given BD
+**                  Address.
+**                  When the connection is initiated or failed to initiate,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_CL_INIT_EVT
+**                  When the connection is established or failed,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capConnect(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role, UINT16 remote_psm, UINT16 rx_mtu,
+                           BD_ADDR peer_bd_addr, tBTA_JV_L2CAP_CBACK *p_cback)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_L2CAP_CONNECT *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvL2capConnect");
+    if (p_cback &&
+        (p_msg = (tBTA_JV_API_L2CAP_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CONNECT))) != NULL)
+    {
+        p_msg->hdr.event    = BTA_JV_API_L2CAP_CONNECT_EVT;
+        p_msg->sec_mask     = sec_mask;
+        p_msg->role         = role;
+        p_msg->remote_psm   = remote_psm;
+        p_msg->rx_mtu       = rx_mtu;
+        memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR));
+        p_msg->p_cback      = p_cback;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capClose
+**
+** Description      This function closes an L2CAP client connection
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capClose(UINT32 handle)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_L2CAP_CLOSE *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvL2capClose");
+    if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback &&
+        (p_msg = (tBTA_JV_API_L2CAP_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_CLOSE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_L2CAP_CLOSE_EVT;
+        p_msg->handle = handle;
+        p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capStartServer
+**
+** Description      This function starts an L2CAP server and listens for an L2CAP
+**                  connection from a remote Bluetooth device.  When the server
+**                  is started successfully, tBTA_JV_L2CAP_CBACK is called with
+**                  BTA_JV_L2CAP_START_EVT.  When the connection is established,
+**                  tBTA_JV_L2CAP_CBACK is called with BTA_JV_L2CAP_OPEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capStartServer(tBTA_SEC sec_mask, tBTA_JV_ROLE role,
+                           UINT16 local_psm, UINT16 rx_mtu,
+                           tBTA_JV_L2CAP_CBACK *p_cback)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_L2CAP_SERVER *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvL2capStartServer");
+    if (p_cback &&
+        (p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_L2CAP_START_SERVER_EVT;
+        p_msg->sec_mask = sec_mask;
+        p_msg->role = role;
+        p_msg->local_psm = local_psm;
+        p_msg->rx_mtu = rx_mtu;
+        p_msg->p_cback = p_cback;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capStopServer
+**
+** Description      This function stops the L2CAP server. If the server has an
+**                  active connection, it would be closed.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capStopServer(UINT16 local_psm)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_L2CAP_SERVER *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvL2capStopServer");
+    if ((p_msg = (tBTA_JV_API_L2CAP_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_SERVER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_L2CAP_STOP_SERVER_EVT;
+        p_msg->local_psm = local_psm;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capRead
+**
+** Description      This function reads data from an L2CAP connecti;
+    tBTA_JV_RFC_CB  *p_cb = rc->p_cb;
+on
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_READ_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+#if 0
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+#if SDP_FOR_JV_INCLUDED == TRUE
+    tBTA_JV_API_L2CAP_READ *p_msg;
+#endif
+    tBTA_JV_L2CAP_READ evt_data;
+
+    APPL_TRACE_API0( "BTA_JvL2capRead");
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+    if(BTA_JV_L2C_FOR_SDP_HDL == handle)
+    {
+        if (bta_jv_cb.l2c_cb[handle].p_cback &&
+            (p_msg = (tBTA_JV_API_L2CAP_READ *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_READ))) != NULL)
+        {
+            p_msg->hdr.event = BTA_JV_API_L2CAP_READ_EVT;
+            p_msg->handle = handle;
+            p_msg->req_id = req_id;
+            p_msg->p_data = p_data;
+            p_msg->len = len;
+            p_msg->p_cback = bta_jv_cb.l2c_cb[handle].p_cback;
+            bta_sys_sendmsg(p_msg);
+            status = BTA_JV_SUCCESS;
+        }
+    }
+    else
+#endif
+    if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+    {
+        status = BTA_JV_SUCCESS;
+        evt_data.status = BTA_JV_FAILURE;
+        evt_data.handle = handle;
+        evt_data.req_id = req_id;
+        evt_data.p_data = p_data;
+        evt_data.len    = 0;
+
+        if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len))
+        {
+            evt_data.status = BTA_JV_SUCCESS;
+        }
+        bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_READ_EVT, (tBTA_JV *)&evt_data);
+    }
+
+    return(status);
+#endif
+    return -1;
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capReceive
+**
+** Description      This function reads data from an L2CAP connection
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_RECEIVE_EVT.
+**                  If there are more data queued in L2CAP than len, the extra data will be discarded.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capReceive(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+#if 0
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_L2CAP_RECEIVE evt_data;
+    UINT32  left_over = 0;
+    UINT16  max_len, read_len;
+
+    APPL_TRACE_API0( "BTA_JvL2capReceive");
+
+    if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+    {
+        status = BTA_JV_SUCCESS;
+        evt_data.status = BTA_JV_FAILURE;
+        evt_data.handle = handle;
+        evt_data.req_id = req_id;
+        evt_data.p_data = p_data;
+        evt_data.len    = 0;
+
+        if (BT_PASS == GAP_ConnReadData((UINT16)handle, p_data, len, &evt_data.len))
+        {
+            evt_data.status = BTA_JV_SUCCESS;
+            GAP_GetRxQueueCnt ((UINT16)handle, &left_over);
+            while (left_over)
+            {
+                max_len = (left_over > 0xFFFF)?0xFFFF:left_over;
+                GAP_ConnReadData ((UINT16)handle, NULL, max_len, &read_len);
+                left_over -= read_len;
+            }
+        }
+        bta_jv_cb.l2c_cb[handle].p_cback(BTA_JV_L2CAP_RECEIVE_EVT, (tBTA_JV *)&evt_data);
+    }
+
+    return(status);
+#endif
+    return -1;
+}
+/*******************************************************************************
+**
+** Function         BTA_JvL2capReady
+**
+** Description      This function determined if there is data to read from
+**                    an L2CAP connection
+**
+** Returns          BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+**                  BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capReady(UINT32 handle, UINT32 *p_data_size)
+{
+#if 0
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+
+    APPL_TRACE_API1( "BTA_JvL2capReady: %d", handle);
+    if (p_data_size && handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback)
+    {
+        *p_data_size = 0;
+#if SDP_FOR_JV_INCLUDED == TRUE
+        if(BTA_JV_L2C_FOR_SDP_HDL == handle)
+        {
+            *p_data_size = bta_jv_cb.sdp_data_size;
+            status = BTA_JV_SUCCESS;
+        }
+        else
+#endif
+        if(BT_PASS == GAP_GetRxQueueCnt((UINT16)handle, p_data_size) )
+        {
+            status = BTA_JV_SUCCESS;
+        }
+    }
+
+    return(status);
+#endif
+    return -1;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvL2capWrite
+**
+** Description      This function writes data to an L2CAP connection
+**                  When the operation is complete, tBTA_JV_L2CAP_CBACK is
+**                  called with BTA_JV_L2CAP_WRITE_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvL2capWrite(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_L2CAP_WRITE *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvL2capWrite");
+    if (handle < BTA_JV_MAX_L2C_CONN && bta_jv_cb.l2c_cb[handle].p_cback &&
+        (p_msg = (tBTA_JV_API_L2CAP_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_L2CAP_WRITE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_L2CAP_WRITE_EVT;
+        p_msg->handle = handle;
+        p_msg->req_id = req_id;
+        p_msg->p_data = p_data;
+        p_msg->p_cb = &bta_jv_cb.l2c_cb[handle];
+        p_msg->len = len;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommConnect
+**
+** Description      This function makes an RFCOMM conection to a remote BD
+**                  Address.
+**                  When the connection is initiated or failed to initiate,
+**                  tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_CL_INIT_EVT
+**                  When the connection is established or failed,
+**                  tBTA_JV_RFCOMM_CBACK is called with BTA_JV_RFCOMM_OPEN_EVT
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommConnect(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role, UINT8 remote_scn, BD_ADDR peer_bd_addr,
+                           tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_CONNECT *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvRfcommConnect");
+    if (p_cback &&
+        (p_msg = (tBTA_JV_API_RFCOMM_CONNECT *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CONNECT))) != NULL)
+    {
+        p_msg->hdr.event    = BTA_JV_API_RFCOMM_CONNECT_EVT;
+        p_msg->sec_mask     = sec_mask;
+        p_msg->role         = role;
+        p_msg->remote_scn   = remote_scn;
+        memcpy(p_msg->peer_bd_addr, peer_bd_addr, sizeof(BD_ADDR));
+        p_msg->p_cback      = p_cback;
+        p_msg->user_data    = user_data;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommClose
+**
+** Description      This function closes an RFCOMM connection
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommClose(UINT32 handle)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_CLOSE *p_msg;
+    UINT32  hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    APPL_TRACE_API0( "BTA_JvRfcommClose");
+    if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+        si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+        (p_msg = (tBTA_JV_API_RFCOMM_CLOSE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_CLOSE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_CLOSE_EVT;
+        p_msg->handle = handle;
+        p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+        p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommStartServer
+**
+** Description      This function starts listening for an RFCOMM connection
+**                  request from a remote Bluetooth device.  When the server is
+**                  started successfully, tBTA_JV_RFCOMM_CBACK is called
+**                  with BTA_JV_RFCOMM_START_EVT.
+**                  When the connection is established, tBTA_JV_RFCOMM_CBACK
+**                  is called with BTA_JV_RFCOMM_OPEN_EVT.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommStartServer(tBTA_SEC sec_mask,
+                           tBTA_JV_ROLE role, UINT8 local_scn, UINT8 max_session,
+                           tBTA_JV_RFCOMM_CBACK *p_cback, void* user_data)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_SERVER *p_msg;
+
+    APPL_TRACE_API0( "BTA_JvRfcommStartServer");
+    if (p_cback &&
+        (p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL)
+    {
+        if (max_session == 0)
+            max_session = 1;
+        if (max_session > BTA_JV_MAX_RFC_SR_SESSION)
+        {
+            APPL_TRACE_DEBUG2( "max_session is too big. use max (%d)", max_session, BTA_JV_MAX_RFC_SR_SESSION);
+            max_session = BTA_JV_MAX_RFC_SR_SESSION;
+        }
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_START_SERVER_EVT;
+        p_msg->sec_mask = sec_mask;
+        p_msg->role = role;
+        p_msg->local_scn = local_scn;
+        p_msg->max_session = max_session;
+        p_msg->p_cback = p_cback;
+        p_msg->user_data = user_data; //caller's private data
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommStopServer
+**
+** Description      This function stops the RFCOMM server. If the server has an
+**                  active connection, it would be closed.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommStopServer(UINT32 handle)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_SERVER *p_msg;
+    APPL_TRACE_API0( "BTA_JvRfcommStopServer");
+    if ((p_msg = (tBTA_JV_API_RFCOMM_SERVER *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_SERVER))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_STOP_SERVER_EVT;
+        p_msg->rfc_handle = handle;
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommRead
+**
+** Description      This function reads data from an RFCOMM connection
+**                  The actual size of data read is returned in p_len.
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommRead(UINT32 handle, UINT32 req_id, UINT8 *p_data, UINT16 len)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_READ *p_msg;
+    UINT32  hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    APPL_TRACE_API0( "BTA_JvRfcommRead");
+    if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+        si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+        (p_msg = (tBTA_JV_API_RFCOMM_READ *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_READ))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_READ_EVT;
+        p_msg->handle = handle;
+        p_msg->req_id = req_id;
+        p_msg->p_data = p_data;
+        p_msg->len = len;
+        p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+        p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommGetPortHdl
+**
+** Description    This function fetches the rfcomm port handle
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+UINT16 BTA_JvRfcommGetPortHdl(UINT32 handle)
+{
+    UINT32  hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    if (hi < BTA_JV_MAX_RFC_CONN &&
+        si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
+        return bta_jv_cb.port_cb[bta_jv_cb.rfc_cb[hi].rfc_hdl[si] - 1].port_handle;
+    else
+        return 0xffff;
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommReady
+**
+** Description      This function determined if there is data to read from
+**                  an RFCOMM connection
+**
+** Returns          BTA_JV_SUCCESS, if data queue size is in *p_data_size.
+**                  BTA_JV_FAILURE, if error.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommReady(UINT32 handle, UINT32 *p_data_size)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    UINT16          size = 0;
+    UINT32  hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    APPL_TRACE_API0( "BTA_JvRfcommReady");
+    if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+        si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
+    {
+        if(PORT_GetRxQueueCnt(bta_jv_cb.rfc_cb[hi].rfc_hdl[si], &size) == PORT_SUCCESS)
+        {
+            status = BTA_JV_SUCCESS;
+        }
+    }
+    *p_data_size = size;
+    return(status);
+}
+
+/*******************************************************************************
+**
+** Function         BTA_JvRfcommWrite
+**
+** Description      This function writes data to an RFCOMM connection
+**
+** Returns          BTA_JV_SUCCESS, if the request is being processed.
+**                  BTA_JV_FAILURE, otherwise.
+**
+*******************************************************************************/
+tBTA_JV_STATUS BTA_JvRfcommWrite(UINT32 handle, UINT32 req_id)
+{
+    tBTA_JV_STATUS status = BTA_JV_FAILURE;
+    tBTA_JV_API_RFCOMM_WRITE *p_msg;
+    UINT32  hi = (handle & BTA_JV_RFC_HDL_MASK) - 1;
+    UINT32  si = BTA_JV_RFC_HDL_TO_SIDX(handle);
+
+    APPL_TRACE_API0( "BTA_JvRfcommWrite");
+    APPL_TRACE_DEBUG3( "handle:0x%x, hi:%d, si:%d", handle, hi, si);
+    if (hi < BTA_JV_MAX_RFC_CONN && bta_jv_cb.rfc_cb[hi].p_cback &&
+        si < BTA_JV_MAX_RFC_SR_SESSION && bta_jv_cb.rfc_cb[hi].rfc_hdl[si] &&
+        (p_msg = (tBTA_JV_API_RFCOMM_WRITE *)GKI_getbuf(sizeof(tBTA_JV_API_RFCOMM_WRITE))) != NULL)
+    {
+        p_msg->hdr.event = BTA_JV_API_RFCOMM_WRITE_EVT;
+        p_msg->handle = handle;
+        p_msg->req_id = req_id;
+        p_msg->p_cb = &bta_jv_cb.rfc_cb[hi];
+        p_msg->p_pcb = &bta_jv_cb.port_cb[p_msg->p_cb->rfc_hdl[si] - 1];
+        APPL_TRACE_API0( "write ok");
+        bta_sys_sendmsg(p_msg);
+        status = BTA_JV_SUCCESS;
+    }
+
+    return(status);
+}
+
diff --git a/bta/jv/bta_jv_cfg.c b/bta/jv/bta_jv_cfg.c
new file mode 100644
index 0000000..675801f
--- /dev/null
+++ b/bta/jv/bta_jv_cfg.c
@@ -0,0 +1,58 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 compile-time configurable constants for advanced
+ *  audio
+ *
+ ******************************************************************************/
+
+#include "gki.h"
+#include "bta_api.h"
+#include "bd.h"
+#include "bta_jv_api.h"
+
+#ifndef BTA_JV_SDP_DB_SIZE
+#define BTA_JV_SDP_DB_SIZE          4500
+#endif
+
+#ifndef BTA_JV_SDP_RAW_DATA_SIZE
+#define BTA_JV_SDP_RAW_DATA_SIZE    1800
+#endif
+
+/* The platform may choose to use dynamic memory for these data buffers.
+ * p_bta_jv_cfg->p_sdp_db must be allocated/stay allocated
+ * between BTA_JvEnable and BTA_JvDisable
+ * p_bta_jv_cfg->p_sdp_raw_data can be allocated before calling BTA_JvStartDiscovery
+ * it can be de-allocated after the last call to access the database */
+static UINT8 bta_jv_sdp_raw_data[BTA_JV_SDP_RAW_DATA_SIZE];
+static UINT8 bta_jv_sdp_db_data[BTA_JV_SDP_DB_SIZE];
+
+/* JV configuration structure */
+const tBTA_JV_CFG bta_jv_cfg =
+{
+    BTA_JV_SDP_RAW_DATA_SIZE,   /* The size of p_sdp_raw_data */
+    BTA_JV_SDP_DB_SIZE,         /* The size of p_sdp_db_data */
+    bta_jv_sdp_raw_data,        /* The data buffer to keep raw data */
+    (tSDP_DISCOVERY_DB *)bta_jv_sdp_db_data /* The data buffer to keep SDP database */
+};
+
+tBTA_JV_CFG *p_bta_jv_cfg = (tBTA_JV_CFG *) &bta_jv_cfg;
+
+
diff --git a/bta/jv/bta_jv_int.h b/bta/jv/bta_jv_int.h
new file mode 100644
index 0000000..5a0aaed
--- /dev/null
+++ b/bta/jv/bta_jv_int.h
@@ -0,0 +1,461 @@
+/******************************************************************************
+ *
+ *  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 is the private interface file for the BTA Java I/F
+ *
+ ******************************************************************************/
+#ifndef BTA_JV_INT_H
+#define BTA_JV_INT_H
+
+#include "bta_sys.h"
+#include "bta_api.h"
+#include "bta_jv_api.h"
+#include "rfcdefs.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+enum
+{
+    /* these events are handled by the state machine */
+    BTA_JV_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_JV),
+    BTA_JV_API_DISABLE_EVT,
+    BTA_JV_API_SET_DISCOVERABILITY_EVT,
+    BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT,
+    BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT,
+    BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT,
+    BTA_JV_API_SET_SERVICE_CLASS_EVT,
+    BTA_JV_API_SET_ENCRYPTION_EVT,
+    BTA_JV_API_GET_SCN_EVT,
+    BTA_JV_API_FREE_SCN_EVT,
+    BTA_JV_API_START_DISCOVERY_EVT,
+    BTA_JV_API_CANCEL_DISCOVERY_EVT,
+    BTA_JV_API_GET_SERVICES_LENGTH_EVT,
+    BTA_JV_API_SERVICE_SELECT_EVT,
+    BTA_JV_API_CREATE_RECORD_EVT,
+    BTA_JV_API_UPDATE_RECORD_EVT,
+    BTA_JV_API_ADD_ATTRIBUTE_EVT,
+    BTA_JV_API_DELETE_ATTRIBUTE_EVT,
+    BTA_JV_API_DELETE_RECORD_EVT,
+    BTA_JV_API_L2CAP_CONNECT_EVT,
+    BTA_JV_API_L2CAP_CLOSE_EVT,
+    BTA_JV_API_L2CAP_START_SERVER_EVT,
+    BTA_JV_API_L2CAP_STOP_SERVER_EVT,
+    BTA_JV_API_L2CAP_READ_EVT,
+    BTA_JV_API_L2CAP_WRITE_EVT,
+    BTA_JV_API_RFCOMM_CONNECT_EVT,
+    BTA_JV_API_RFCOMM_CLOSE_EVT,
+    BTA_JV_API_RFCOMM_START_SERVER_EVT,
+    BTA_JV_API_RFCOMM_STOP_SERVER_EVT,
+    BTA_JV_API_RFCOMM_READ_EVT,
+    BTA_JV_API_RFCOMM_WRITE_EVT,
+    BTA_JV_MAX_INT_EVT
+};
+
+/* data type for BTA_JV_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTA_JV_DM_CBACK   *p_cback;
+} tBTA_JV_API_ENABLE;
+
+/* data type for BTA_JV_API_SET_DISCOVERABILITY_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_JV_DISC    disc_mode;
+} tBTA_JV_API_SET_DISCOVERABILITY;
+
+
+/* data type for BTA_JV_API_SET_SERVICE_CLASS_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT32      service;
+} tBTA_JV_API_SET_SERVICE_CLASS;
+
+/* data type for BTA_JV_API_SET_ENCRYPTION_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+} tBTA_JV_API_SET_ENCRYPTION;
+
+/* data type for BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+} tBTA_JV_API_GET_REMOTE_NAME;
+
+/* data type for BTA_JV_API_START_DISCOVERY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR bd_addr;
+    UINT16 num_uuid;
+    tSDP_UUID uuid_list[BTA_JV_MAX_UUIDS];
+    UINT16 num_attr;
+    UINT16 attr_list[BTA_JV_MAX_ATTRS];
+    void            *user_data;      /* piggyback caller's private data*/
+} tBTA_JV_API_START_DISCOVERY;
+
+/* data type for BTA_JV_API_CANCEL_DISCOVERY_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    void            *user_data;      /* piggyback caller's private data*/
+} tBTA_JV_API_CANCEL_DISCOVERY;
+
+
+/* data type for BTA_JV_API_GET_SERVICES_LENGTH_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT16      *p_services_len;
+    BOOLEAN     inc_hdr;
+} tBTA_JV_API_GET_SERVICES_LENGTH;
+
+/* data type for BTA_JV_API_GET_SERVICE_RESULT_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT8        **TLVs;
+} tBTA_JV_API_GET_SERVICE_RESULT;
+
+/* data type for BTA_JV_API_SERVICE_SELECT_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT16        uuid;
+} tBTA_JV_API_SERVICE_SELECT;
+
+enum
+{
+    BTA_JV_ST_NONE = 0,
+    BTA_JV_ST_CL_OPENING,
+    BTA_JV_ST_CL_OPEN,
+    BTA_JV_ST_CL_CLOSING,
+    BTA_JV_ST_SR_LISTEN,
+    BTA_JV_ST_SR_OPEN,
+    BTA_JV_ST_SR_CLOSING
+} ;
+typedef UINT8  tBTA_JV_STATE;
+#define BTA_JV_ST_CL_MAX    BTA_JV_ST_CL_CLOSING
+
+/* JV L2CAP control block */
+typedef struct
+{
+    tBTA_JV_L2CAP_CBACK *p_cback;   /* the callback function */
+    UINT16              psm;        /* the psm used for this server connection */
+    tBTA_JV_STATE       state;      /* the state of this control block */
+    tBTA_SERVICE_ID     sec_id;     /* service id */
+    UINT16              handle;     /* the handle reported to java app (same as gap handle) */
+    BOOLEAN             cong;       /* TRUE, if congested */
+} tBTA_JV_L2C_CB;
+
+#define BTA_JV_RFC_HDL_MASK         0xFF
+#define BTA_JV_RFC_HDL_TO_SIDX(r)   (((r)&0xFF00) >> 8)
+#define BTA_JV_RFC_H_S_TO_HDL(h, s) ((h)|(s<<8))
+
+/* port control block */
+typedef struct
+{
+    UINT32              handle;     /* the rfcomm session handle at jv */
+    UINT16              port_handle; /* port handle */
+    tBTA_JV_STATE       state;      /* the state of this control block */
+    UINT8               max_sess;   /* max sessions */
+    void                *user_data; /* piggyback caller's private data*/
+    BOOLEAN             cong;       /* TRUE, if congested */
+} tBTA_JV_PCB;
+
+/* JV RFCOMM control block */
+typedef struct
+{
+    tBTA_JV_RFCOMM_CBACK *p_cback;  /* the callback function */
+    UINT16              rfc_hdl[BTA_JV_MAX_RFC_SR_SESSION];
+    tBTA_SERVICE_ID     sec_id;     /* service id */
+    UINT8               handle;     /* index: the handle reported to java app */
+    UINT8               scn;        /* the scn of the server */
+    UINT8               max_sess;   /* max sessions */
+} tBTA_JV_RFC_CB;
+
+/* data type for BTA_JV_API_L2CAP_CONNECT_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTA_SEC        sec_mask;
+    tBTA_JV_ROLE    role;
+    UINT16          remote_psm;
+    UINT16          rx_mtu;
+    BD_ADDR         peer_bd_addr;
+    tBTA_JV_L2CAP_CBACK *p_cback;
+} tBTA_JV_API_L2CAP_CONNECT;
+
+/* data type for BTA_JV_API_L2CAP_SERVER_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    tBTA_SEC            sec_mask;
+    tBTA_JV_ROLE        role;
+    UINT16              local_psm;
+    UINT16              rx_mtu;
+    tBTA_JV_L2CAP_CBACK *p_cback;
+} tBTA_JV_API_L2CAP_SERVER;
+
+/* data type for BTA_JV_API_L2CAP_CLOSE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          handle;
+    tBTA_JV_L2C_CB  *p_cb;
+} tBTA_JV_API_L2CAP_CLOSE;
+
+/* data type for BTA_JV_API_L2CAP_READ_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              handle;
+    UINT32              req_id;
+    tBTA_JV_L2CAP_CBACK *p_cback;
+    UINT8*              p_data;
+    UINT16              len;
+} tBTA_JV_API_L2CAP_READ;
+
+/* data type for BTA_JV_API_L2CAP_WRITE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;
+    UINT16              handle;
+    UINT32              req_id;
+    tBTA_JV_L2C_CB      *p_cb;
+    UINT8               *p_data;
+    UINT16              len;
+} tBTA_JV_API_L2CAP_WRITE;
+
+/* data type for BTA_JV_API_RFCOMM_CONNECT_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTA_SEC        sec_mask;
+    tBTA_JV_ROLE    role;
+    UINT8           remote_scn;
+    BD_ADDR         peer_bd_addr;
+    tBTA_JV_RFCOMM_CBACK *p_cback;
+    void            *user_data;
+} tBTA_JV_API_RFCOMM_CONNECT;
+
+/* data type for BTA_JV_API_RFCOMM_SERVER_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    tBTA_SEC        sec_mask;
+    tBTA_JV_ROLE    role;
+    UINT8           local_scn;
+    UINT8           max_session;
+    int             rfc_handle;
+    tBTA_JV_RFCOMM_CBACK *p_cback;
+    void            *user_data;
+} tBTA_JV_API_RFCOMM_SERVER;
+
+/* data type for BTA_JV_API_RFCOMM_READ_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          handle;
+    UINT32          req_id;
+    UINT8           *p_data;
+    UINT16          len;
+    tBTA_JV_RFC_CB  *p_cb;
+    tBTA_JV_PCB     *p_pcb;
+} tBTA_JV_API_RFCOMM_READ;
+
+/* data type for BTA_JV_API_RFCOMM_WRITE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          handle;
+    UINT32          req_id;
+    UINT8           *p_data;
+    int          len;
+    tBTA_JV_RFC_CB  *p_cb;
+    tBTA_JV_PCB     *p_pcb;
+} tBTA_JV_API_RFCOMM_WRITE;
+
+/* data type for BTA_JV_API_RFCOMM_CLOSE_EVT */
+typedef struct
+{
+    BT_HDR          hdr;
+    UINT16          handle;
+    tBTA_JV_RFC_CB  *p_cb;
+    tBTA_JV_PCB     *p_pcb;
+} tBTA_JV_API_RFCOMM_CLOSE;
+
+/* data type for BTA_JV_API_CREATE_RECORD_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    void        *user_data;
+} tBTA_JV_API_CREATE_RECORD;
+
+/* data type for BTA_JV_API_UPDATE_RECORD_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT32      handle;
+    UINT16      *p_ids;
+    UINT8       **p_values;
+    INT32       *p_value_sizes;
+    INT32       array_len;
+} tBTA_JV_API_UPDATE_RECORD;
+
+/* data type for BTA_JV_API_ADD_ATTRIBUTE_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT32      handle;
+    UINT16      attr_id;
+    UINT8       *p_value;
+    INT32       value_size;
+} tBTA_JV_API_ADD_ATTRIBUTE;
+
+/* data type for BTA_JV_API_FREE_SCN_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    UINT8       scn;
+} tBTA_JV_API_FREE_SCN;
+/* union of all data types */
+typedef union
+{
+    /* GKI event buffer header */
+    BT_HDR                          hdr;
+    tBTA_JV_API_ENABLE              enable;
+    tBTA_JV_API_SET_DISCOVERABILITY set_discoverability;
+    tBTA_JV_API_GET_REMOTE_NAME     get_rmt_name;
+    tBTA_JV_API_SET_SERVICE_CLASS   set_service;
+    tBTA_JV_API_SET_ENCRYPTION      set_encrypt;
+    tBTA_JV_API_START_DISCOVERY     start_discovery;
+    tBTA_JV_API_CANCEL_DISCOVERY    cancel_discovery;
+    tBTA_JV_API_GET_SERVICES_LENGTH get_services_length;
+    tBTA_JV_API_GET_SERVICE_RESULT  get_service_result;
+    tBTA_JV_API_SERVICE_SELECT      service_select;
+    tBTA_JV_API_FREE_SCN            free_scn;
+    tBTA_JV_API_CREATE_RECORD       create_record;
+    tBTA_JV_API_UPDATE_RECORD       update_record;
+    tBTA_JV_API_ADD_ATTRIBUTE       add_attr;
+    tBTA_JV_API_L2CAP_CONNECT       l2cap_connect;
+    tBTA_JV_API_L2CAP_READ          l2cap_read;
+    tBTA_JV_API_L2CAP_WRITE         l2cap_write;
+    tBTA_JV_API_L2CAP_CLOSE         l2cap_close;
+    tBTA_JV_API_L2CAP_SERVER        l2cap_server;
+    tBTA_JV_API_RFCOMM_CONNECT      rfcomm_connect;
+    tBTA_JV_API_RFCOMM_READ         rfcomm_read;
+    tBTA_JV_API_RFCOMM_WRITE        rfcomm_write;
+    tBTA_JV_API_RFCOMM_CLOSE        rfcomm_close;
+    tBTA_JV_API_RFCOMM_SERVER       rfcomm_server;
+} tBTA_JV_MSG;
+
+#if SDP_FOR_JV_INCLUDED == TRUE
+#define BTA_JV_L2C_FOR_SDP_HDL     GAP_MAX_CONNECTIONS
+#endif
+
+/* JV control block */
+typedef struct
+{
+#if SDP_FOR_JV_INCLUDED == TRUE
+    UINT32                  sdp_for_jv;     /* The SDP client connection handle */
+    UINT32                  sdp_data_size;  /* the data len */
+#endif
+    /* the SDP handle reported to JV user is the (index + 1) to sdp_handle[].
+     * if sdp_handle[i]==0, it's not used.
+     * otherwise sdp_handle[i] is the stack SDP handle. */
+    UINT32                  sdp_handle[BTA_JV_MAX_SDP_REC]; /* SDP records created */
+    UINT8                   *p_sel_raw_data;/* the raw data of last service select */
+    INT32                   sel_len;        /* the SDP record size of last service select */
+    tBTA_JV_DM_CBACK        *p_dm_cback;
+    tBTA_JV_L2C_CB          l2c_cb[BTA_JV_MAX_L2C_CONN];    /* index is GAP handle (index) */
+    tBTA_JV_RFC_CB          rfc_cb[BTA_JV_MAX_RFC_CONN];
+    tBTA_JV_PCB             port_cb[MAX_RFC_PORTS];         /* index of this array is the port_handle, */
+    UINT8                   sec_id[BTA_JV_NUM_SERVICE_ID];  /* service ID */
+    BOOLEAN                 scn[BTA_JV_MAX_SCN];            /* SCN allocated by java */
+    UINT8                   sdp_active;                     /* see BTA_JV_SDP_ACT_* */
+    tSDP_UUID               uuid;                           /* current uuid of sdp discovery*/
+    void                    *user_data;                     /* piggyback user data*/
+} tBTA_JV_CB;
+
+enum
+{
+    BTA_JV_SDP_ACT_NONE = 0,
+    BTA_JV_SDP_ACT_YES,     /* waiting for SDP result */
+    BTA_JV_SDP_ACT_CANCEL   /* waiting for cancel complete */
+};
+
+/* JV control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_JV_CB bta_jv_cb;
+#else
+extern tBTA_JV_CB *bta_jv_cb_ptr;
+#define bta_jv_cb (*bta_jv_cb_ptr)
+#endif
+
+/* config struct */
+extern tBTA_JV_CFG *p_bta_jv_cfg;
+
+/* this is defined in stack/sdp. used by bta jv */
+extern UINT8 *sdpu_get_len_from_type (UINT8 *p, UINT8 type, UINT32 *p_len);
+
+extern BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg);
+
+extern UINT32 bta_jv_get_sdp_handle(UINT32 sdp_id);
+extern void bta_jv_enable (tBTA_JV_MSG *p_data);
+extern void bta_jv_disable (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_discoverability (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_local_device_addr (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_local_device_name (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_remote_device_name (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_service_class (tBTA_JV_MSG *p_data);
+extern void bta_jv_set_encryption (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_scn (tBTA_JV_MSG *p_data);
+extern void bta_jv_free_scn (tBTA_JV_MSG *p_data);
+extern void bta_jv_start_discovery (tBTA_JV_MSG *p_data);
+extern void bta_jv_cancel_discovery (tBTA_JV_MSG *p_data);
+extern void bta_jv_get_services_length (tBTA_JV_MSG *p_data);
+extern void bta_jv_service_select (tBTA_JV_MSG *p_data);
+extern void bta_jv_create_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_update_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_add_attribute (tBTA_JV_MSG *p_data);
+extern void bta_jv_delete_attribute (tBTA_JV_MSG *p_data);
+extern void bta_jv_delete_record (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_connect (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_close (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_start_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_stop_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_read (tBTA_JV_MSG *p_data);
+extern void bta_jv_l2cap_write (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_connect (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_close (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_start_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_stop_server (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_read (tBTA_JV_MSG *p_data);
+extern void bta_jv_rfcomm_write (tBTA_JV_MSG *p_data);
+
+#endif /* BTA_JV_INT_H */
diff --git a/bta/jv/bta_jv_main.c b/bta/jv/bta_jv_main.c
new file mode 100644
index 0000000..0cba56b
--- /dev/null
+++ b/bta/jv/bta_jv_main.c
@@ -0,0 +1,103 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 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 is the main implementation file for the BTA Java I/F
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_jv_api.h"
+#include "bta_jv_int.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_JV_CB bta_jv_cb;
+#endif
+
+/* state machine action enumeration list */
+#define BTA_JV_NUM_ACTIONS  (BTA_JV_MAX_INT_EVT & 0x00ff)
+
+/* type for action functions */
+typedef void (*tBTA_JV_ACTION)(tBTA_JV_MSG *p_data);
+
+/* action function list */
+const tBTA_JV_ACTION bta_jv_action[] =
+{
+    bta_jv_enable,                  /* BTA_JV_API_ENABLE_EVT */
+    bta_jv_disable,                 /* BTA_JV_API_DISABLE_EVT */
+    bta_jv_set_discoverability,     /* BTA_JV_API_SET_DISCOVERABILITY_EVT */
+    bta_jv_get_local_device_addr,   /* BTA_JV_API_GET_LOCAL_DEVICE_ADDR_EVT */
+    bta_jv_get_local_device_name,   /* BTA_JV_API_GET_LOCAL_DEVICE_NAME_EVT */
+    bta_jv_get_remote_device_name,  /* BTA_JV_API_GET_REMOTE_DEVICE_NAME_EVT */
+    bta_jv_set_service_class,       /* BTA_JV_API_SET_SERVICE_CLASS_EVT */
+    bta_jv_set_encryption,          /* BTA_JV_API_SET_ENCRYPTION_EVT */
+    bta_jv_get_scn,                 /* BTA_JV_API_GET_SCN_EVT */
+    bta_jv_free_scn,                /* BTA_JV_API_FREE_SCN_EVT */
+    bta_jv_start_discovery,         /* BTA_JV_API_START_DISCOVERY_EVT */
+    bta_jv_cancel_discovery,        /* BTA_JV_API_CANCEL_DISCOVERY_EVT */
+    bta_jv_get_services_length,     /* BTA_JV_API_GET_SERVICES_LENGTH_EVT */
+    bta_jv_service_select,          /* BTA_JV_API_SERVICE_SELECT_EVT */
+    bta_jv_create_record,           /* BTA_JV_API_CREATE_RECORD_EVT */
+    bta_jv_update_record,           /* BTA_JV_API_UPDATE_RECORD_EVT */
+    bta_jv_add_attribute,           /* BTA_JV_API_ADD_ATTRIBUTE_EVT */
+    bta_jv_delete_attribute,        /* BTA_JV_API_DELETE_ATTRIBUTE_EVT */
+    bta_jv_delete_record,           /* BTA_JV_API_DELETE_RECORD_EVT */
+    bta_jv_l2cap_connect,           /* BTA_JV_API_L2CAP_CONNECT_EVT */
+    bta_jv_l2cap_close,             /* BTA_JV_API_L2CAP_CLOSE_EVT */
+    bta_jv_l2cap_start_server,      /* BTA_JV_API_L2CAP_START_SERVER_EVT */
+    bta_jv_l2cap_stop_server,       /* BTA_JV_API_L2CAP_STOP_SERVER_EVT */
+    bta_jv_l2cap_read,              /* BTA_JV_API_L2CAP_READ_EVT */
+    bta_jv_l2cap_write,             /* BTA_JV_API_L2CAP_WRITE_EVT */
+    bta_jv_rfcomm_connect,          /* BTA_JV_API_RFCOMM_CONNECT_EVT */
+    bta_jv_rfcomm_close,            /* BTA_JV_API_RFCOMM_CLOSE_EVT */
+    bta_jv_rfcomm_start_server,     /* BTA_JV_API_RFCOMM_START_SERVER_EVT */
+    bta_jv_rfcomm_stop_server,      /* BTA_JV_API_RFCOMM_STOP_SERVER_EVT */
+    bta_jv_rfcomm_read,             /* BTA_JV_API_RFCOMM_READ_EVT */
+    bta_jv_rfcomm_write             /* BTA_JV_API_RFCOMM_WRITE_EVT */
+};
+
+/*******************************************************************************
+**
+** Function         bta_jv_sm_execute
+**
+** Description      State machine event handling function for JV
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_jv_sm_execute(BT_HDR *p_msg)
+{
+    BOOLEAN ret = FALSE;
+    UINT16 action = (p_msg->event & 0x00ff);
+    /* execute action functions */
+
+    if(action < BTA_JV_NUM_ACTIONS)
+    {
+        (*bta_jv_action[action])((tBTA_JV_MSG*)p_msg);
+        ret = TRUE;
+    }
+
+    return(ret);
+}
diff --git a/bta/pan/bta_pan_act.c b/bta/pan/bta_pan_act.c
new file mode 100644
index 0000000..b29920f
--- /dev/null
+++ b/bta/pan/bta_pan_act.c
@@ -0,0 +1,728 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 the pan action functions for the state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(PAN_INCLUDED) && (PAN_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bd.h"
+#include "gki.h"
+#include "pan_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bta_pan_co.h"
+#include <string.h>
+
+
+/* RX and TX data flow mask */
+#define BTA_PAN_RX_MASK              0x0F
+#define BTA_PAN_TX_MASK              0xF0
+
+/*******************************************************************************
+**
+** Function         bta_pan_conn_state_cback
+**
+** Description      Connection state callback from Pan profile
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_conn_state_cback(UINT16 handle, BD_ADDR bd_addr, tPAN_RESULT state,
+                                     BOOLEAN is_role_change, UINT8 src_role, UINT8 dst_role)
+{
+
+    tBTA_PAN_CONN * p_buf;
+    tBTA_PAN_SCB     *p_scb;
+
+
+    if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
+    {
+        if((state == PAN_SUCCESS) && !is_role_change)
+        {
+            p_buf->hdr.event = BTA_PAN_CONN_OPEN_EVT;
+            if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+            {
+                /* allocate an scb */
+                p_scb = bta_pan_scb_alloc();
+
+            }
+            /* we have exceeded maximum number of connections */
+            if(!p_scb)
+            {
+                PAN_Disconnect (handle);
+                return;
+            }
+
+            p_scb->handle = handle;
+            p_scb->local_role = src_role;
+            p_scb->peer_role = dst_role;
+            p_scb->pan_flow_enable = TRUE;
+            bdcpy(p_scb->bd_addr, bd_addr);
+            GKI_init_q(&p_scb->data_queue);
+
+            if(src_role == PAN_ROLE_CLIENT)
+                p_scb->app_id = bta_pan_cb.app_id[0];
+            else if (src_role == PAN_ROLE_GN_SERVER)
+                p_scb->app_id = bta_pan_cb.app_id[1];
+            else if (src_role == PAN_ROLE_NAP_SERVER)
+                p_scb->app_id = bta_pan_cb.app_id[2];
+
+        }
+        else if((state != PAN_SUCCESS) && !is_role_change)
+        {
+            p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
+
+        }
+        else
+        {
+            return;
+        }
+
+        p_buf->result = state;
+        p_buf->hdr.layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+
+    }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_data_flow_cb
+**
+** Description      Data flow status callback from PAN
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_data_flow_cb(UINT16 handle, tPAN_RESULT result)
+{
+    BT_HDR  *p_buf;
+    tBTA_PAN_SCB *p_scb;
+
+    if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+        return;
+
+    if(result == PAN_TX_FLOW_ON)
+    {
+        if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+        {
+            p_buf->layer_specific = handle;
+            p_buf->event = BTA_PAN_BNEP_FLOW_ENABLE_EVT;
+            bta_sys_sendmsg(p_buf);
+        }
+        bta_pan_co_rx_flow(handle, p_scb->app_id, TRUE);
+
+    }
+    else if(result == PAN_TX_FLOW_OFF)
+    {
+
+        p_scb->pan_flow_enable = FALSE;
+        bta_pan_co_rx_flow(handle, p_scb->app_id, FALSE);
+
+    }
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_data_buf_ind_cback
+**
+** Description      data indication callback from pan profile
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_data_buf_ind_cback(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16 protocol, BT_HDR *p_buf,
+                                   BOOLEAN ext, BOOLEAN forward)
+{
+    tBTA_PAN_SCB *p_scb;
+    BT_HDR * p_event;
+    BT_HDR *p_new_buf;
+
+    if ( sizeof(tBTA_PAN_DATA_PARAMS) > p_buf->offset )
+    {
+        /* offset smaller than data structure in front of actual data */
+        p_new_buf = (BT_HDR *)GKI_getpoolbuf( PAN_POOL_ID );
+        if(!p_new_buf)
+        {
+            APPL_TRACE_WARNING0("Cannot get a PAN GKI buffer");
+            GKI_freebuf( p_buf );
+            return;
+        }
+        else
+        {
+            memcpy( (UINT8 *)(p_new_buf+1)+sizeof(tBTA_PAN_DATA_PARAMS), (UINT8 *)(p_buf+1)+p_buf->offset, p_buf->len );
+            p_new_buf->len    = p_buf->len;
+            p_new_buf->offset = sizeof(tBTA_PAN_DATA_PARAMS);
+            GKI_freebuf( p_buf );
+        }
+    }
+    else
+    {
+        p_new_buf = p_buf;
+    }
+    /* copy params into the space before the data */
+    bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->src, src);
+    bdcpy(((tBTA_PAN_DATA_PARAMS *)p_new_buf)->dst, dst);
+    ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->protocol = protocol;
+    ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->ext = ext;
+    ((tBTA_PAN_DATA_PARAMS *)p_new_buf)->forward = forward;
+
+
+    if((p_scb = bta_pan_scb_by_handle(handle)) == NULL)
+    {
+
+        GKI_freebuf( p_new_buf );
+        return;
+    }
+
+    GKI_enqueue(&p_scb->data_queue, p_new_buf);
+    if ((p_event = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_event->layer_specific = handle;
+        p_event->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
+        bta_sys_sendmsg(p_event);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_pfilt_ind_cback
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_pfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
+                                    UINT16 num_filters, UINT8 *p_filters)
+{
+
+    bta_pan_co_pfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
+                                    num_filters, p_filters);
+
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_mfilt_ind_cback
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_mfilt_ind_cback(UINT16 handle, BOOLEAN indication,tBNEP_RESULT result,
+                                    UINT16 num_mfilters, UINT8 *p_mfilters)
+{
+
+    bta_pan_co_mfilt_ind(handle, indication, (tBTA_PAN_STATUS)((result == BNEP_SUCCESS) ? BTA_PAN_SUCCESS : BTA_PAN_FAIL),
+                                    num_mfilters, p_mfilters);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_enable
+**
+** Description
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_enable(tBTA_PAN_DATA *p_data)
+{
+    tPAN_REGISTER reg_data;
+    UINT16  initial_discoverability;
+    UINT16  initial_connectability;
+    UINT16  d_window;
+    UINT16  d_interval;
+    UINT16  c_window;
+    UINT16  c_interval;
+
+    bta_pan_cb.p_cback = p_data->api_enable.p_cback;
+
+    reg_data.pan_conn_state_cb  = bta_pan_conn_state_cback;
+    reg_data.pan_bridge_req_cb  = NULL;
+    reg_data.pan_data_buf_ind_cb = bta_pan_data_buf_ind_cback;
+    reg_data.pan_data_ind_cb = NULL;
+    reg_data.pan_pfilt_ind_cb = bta_pan_pfilt_ind_cback;
+    reg_data.pan_mfilt_ind_cb = bta_pan_mfilt_ind_cback;
+    reg_data.pan_tx_data_flow_cb = bta_pan_data_flow_cb;
+
+    /* read connectability and discoverability settings.
+    Pan profile changes the settings. We have to change it back to
+    be consistent with other bta subsystems */
+    initial_connectability = BTM_ReadConnectability(&c_window, &c_interval);
+    initial_discoverability = BTM_ReadDiscoverability(&d_window, &d_interval);
+
+
+    PAN_Register (&reg_data);
+
+
+    /* set it back to original value */
+    BTM_SetDiscoverability(initial_discoverability, d_window, d_interval);
+    BTM_SetConnectability(initial_connectability, c_window, c_interval);
+
+    bta_pan_cb.flow_mask = bta_pan_co_init(&bta_pan_cb.q_level);
+    bta_pan_cb.p_cback(BTA_PAN_ENABLE_EVT, NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_set_role
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_set_role(tBTA_PAN_DATA *p_data)
+{
+    tPAN_RESULT status;
+    tBTA_PAN_SET_ROLE set_role;
+    UINT8  sec[3];
+
+
+    bta_pan_cb.app_id[0] = p_data->api_set_role.user_app_id;
+    bta_pan_cb.app_id[1] = p_data->api_set_role.gn_app_id;
+    bta_pan_cb.app_id[2] = p_data->api_set_role.nap_app_id;
+
+    sec[0] = p_data->api_set_role.user_sec_mask;
+    sec[1] = p_data->api_set_role.gn_sec_mask;
+    sec[2] = p_data->api_set_role.nap_sec_mask;
+
+    /* set security correctly in api and here */
+    status = PAN_SetRole(p_data->api_set_role.role, sec,
+                                     p_data->api_set_role.user_name,
+                                     p_data->api_set_role.gn_name,
+                                     p_data->api_set_role.nap_name);
+
+    set_role.role = p_data->api_set_role.role;
+    if(status == PAN_SUCCESS)
+    {
+        if(p_data->api_set_role.role & PAN_ROLE_NAP_SERVER )
+            bta_sys_add_uuid(UUID_SERVCLASS_NAP);
+        else
+            bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+
+        if(p_data->api_set_role.role & PAN_ROLE_GN_SERVER )
+            bta_sys_add_uuid(UUID_SERVCLASS_GN);
+        else
+            bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+
+        if(p_data->api_set_role.role & PAN_ROLE_CLIENT )
+            bta_sys_add_uuid(UUID_SERVCLASS_PANU);
+        else
+            bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+
+        set_role.status = BTA_PAN_SUCCESS;
+    }
+    /* if status is not success clear everything */
+    else
+    {
+        PAN_SetRole(0, 0, NULL, NULL, NULL);
+        bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+        bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+        bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+        set_role.status = BTA_PAN_FAIL;
+    }
+    bta_pan_cb.p_cback(BTA_PAN_SET_ROLE_EVT, (tBTA_PAN *)&set_role);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_disable
+**
+** Description
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_disable(void)
+{
+
+    BT_HDR *p_buf;
+    tBTA_PAN_SCB *p_scb = &bta_pan_cb.scb[0];
+    UINT8 i;
+
+
+    /* close all connections */
+    PAN_SetRole (0, NULL, NULL, NULL, NULL);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+    bta_sys_remove_uuid(UUID_SERVCLASS_NAP);
+    bta_sys_remove_uuid(UUID_SERVCLASS_GN);
+    bta_sys_remove_uuid(UUID_SERVCLASS_PANU);
+#endif
+    /* free all queued up data buffers */
+    for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+    {
+        if (p_scb->in_use)
+        {
+            while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+                GKI_freebuf(p_buf);
+
+            bta_pan_co_close(p_scb->handle, p_scb->app_id);
+
+        }
+    }
+
+
+
+    PAN_Deregister();
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_open
+**
+** Description
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+    tPAN_RESULT status;
+    tBTA_PAN_OPEN data;
+    tBTA_PAN_OPENING    opening;
+
+
+    status = PAN_Connect (p_data->api_open.bd_addr, p_data->api_open.local_role, p_data->api_open.peer_role,
+                        &p_scb->handle);
+
+
+    if(status == PAN_SUCCESS)
+    {
+
+        bdcpy(p_scb->bd_addr, p_data->api_open.bd_addr);
+        p_scb->local_role = p_data->api_open.local_role;
+        p_scb->peer_role = p_data->api_open.peer_role;
+        bdcpy(opening.bd_addr, p_data->api_open.bd_addr);
+        opening.handle = p_scb->handle;
+        bta_pan_cb.p_cback(BTA_PAN_OPENING_EVT, (tBTA_PAN *)&opening);
+
+
+    }
+    else
+    {
+        bta_pan_scb_dealloc(p_scb);
+        bdcpy(data.bd_addr, p_data->api_open.bd_addr);
+        data.status = BTA_PAN_FAIL;
+        bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_close
+**
+** Description
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_api_close (tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+    tBTA_PAN_CONN * p_buf;
+
+    PAN_Disconnect (p_scb->handle);
+
+
+    /* send an event to BTA so that application will get the connection
+       close event */
+    if ((p_buf = (tBTA_PAN_CONN *) GKI_getbuf(sizeof(tBTA_PAN_CONN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_PAN_CONN_CLOSE_EVT;
+
+        p_buf->hdr.layer_specific = p_scb->handle;
+        bta_sys_sendmsg(p_buf);
+
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_conn_open
+**
+** Description      process connection open event
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+    tBTA_PAN_OPEN data;
+
+    bdcpy(data.bd_addr, p_scb->bd_addr);
+    data.handle = p_scb->handle;
+    data.local_role = p_scb->local_role;
+    data.peer_role = p_scb->peer_role;
+
+    if(p_data->conn.result == PAN_SUCCESS)
+    {
+        data.status = BTA_PAN_SUCCESS;
+        bta_pan_co_open(p_scb->handle, p_scb->app_id, p_scb->local_role, p_scb->peer_role, p_scb->bd_addr);
+
+    }
+    else
+    {
+        bta_pan_scb_dealloc(p_scb);
+        data.status = BTA_PAN_FAIL;
+    }
+
+    p_scb->pan_flow_enable = TRUE;
+    p_scb->app_flow_enable = TRUE;
+
+    bta_sys_conn_open( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
+
+    bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_conn_close
+**
+** Description      process connection close event
+**
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+    tBTA_PAN_CLOSE data;
+    BT_HDR *p_buf;
+
+    data.handle = p_data->hdr.layer_specific;
+
+
+    bta_sys_conn_close( BTA_ID_PAN ,p_scb->app_id, p_scb->bd_addr);
+
+    /* free all queued up data buffers */
+    while((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+        GKI_freebuf(p_buf);
+
+    GKI_init_q(&p_scb->data_queue);
+
+    bta_pan_co_close(p_scb->handle, p_scb->app_id);
+
+    bta_pan_scb_dealloc(p_scb);
+
+    bta_pan_cb.p_cback(BTA_PAN_CLOSE_EVT, (tBTA_PAN *)&data);
+
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_rx_path
+**
+** Description      Handle data on the RX path (data sent from the phone to
+**                  BTA).
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+    /* if data path configured for rx pull */
+    if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PULL)
+    {
+        /* if we can accept data */
+        if (p_scb->pan_flow_enable == TRUE)
+        {
+            /* call application callout function for rx path */
+            bta_pan_co_rx_path(p_scb->handle, p_scb->app_id);
+        }
+    }
+    /* else data path configured for rx push */
+    else
+    {
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_tx_path
+**
+** Description      Handle the TX data path (data sent from BTA to the phone).
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+    BT_HDR * p_buf;
+    /* if data path configured for tx pull */
+    if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PULL)
+    {
+        /* call application callout function for tx path */
+        bta_pan_co_tx_path(p_scb->handle, p_scb->app_id);
+
+        /* free data that exceeds queue level */
+        while(p_scb->data_queue.count > bta_pan_cb.q_level)
+            GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
+    }
+    /* if configured for zero copy push */
+    else if ((bta_pan_cb.flow_mask & BTA_PAN_TX_MASK) == BTA_PAN_TX_PUSH_BUF)
+    {
+        /* if app can accept data */
+        if (p_scb->app_flow_enable == TRUE)
+        {
+            /* read data from the queue */
+            if ((p_buf = (BT_HDR *)GKI_dequeue(&p_scb->data_queue)) != NULL)
+            {
+                /* send data to application */
+                bta_pan_co_tx_writebuf(p_scb->handle,
+                                        p_scb->app_id,
+                                        ((tBTA_PAN_DATA_PARAMS *)p_buf)->src,
+                                        ((tBTA_PAN_DATA_PARAMS *)p_buf)->dst,
+                                        ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol,
+                                        p_buf,
+                                        ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext,
+                                        ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward);
+
+            }
+            /* free data that exceeds queue level  */
+            while(p_scb->data_queue.count > bta_pan_cb.q_level)
+                GKI_freebuf(GKI_dequeue(&p_scb->data_queue));
+
+            /* if there is more data to be passed to
+            upper layer */
+            if(p_scb->data_queue.count)
+            {
+                if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+                {
+                    p_buf->layer_specific = p_scb->handle;
+                    p_buf->event = BTA_PAN_RX_FROM_BNEP_READY_EVT;
+                    bta_sys_sendmsg(p_buf);
+                }
+
+            }
+
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_tx_flow
+**
+** Description      Set the application flow control state.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+    p_scb->app_flow_enable = p_data->ci_tx_flow.enable;
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_write_buf
+**
+** Description      Handle a bta_pan_ci_rx_writebuf() and send data to PAN.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+    if ((bta_pan_cb.flow_mask & BTA_PAN_RX_MASK) == BTA_PAN_RX_PUSH_BUF)
+    {
+
+        PAN_WriteBuf (p_scb->handle,
+                      ((tBTA_PAN_DATA_PARAMS *)p_data)->dst,
+                      ((tBTA_PAN_DATA_PARAMS *)p_data)->src,
+                      ((tBTA_PAN_DATA_PARAMS *)p_data)->protocol,
+                      (BT_HDR *)p_data,
+                      ((tBTA_PAN_DATA_PARAMS *)p_data)->ext);
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_free_buf
+**
+** Description      Frees the data buffer during closing state
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data)
+{
+
+    GKI_freebuf(p_data);
+
+}
+
+#endif /* PAN_INCLUDED */
diff --git a/bta/pan/bta_pan_api.c b/bta/pan/bta_pan_api.c
new file mode 100644
index 0000000..6588230
--- /dev/null
+++ b/bta/pan/bta_pan_api.c
@@ -0,0 +1,214 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the implementation of the API for PAN subsystem of BTA,
+ *  Broadcom's Bluetooth application layer for mobile phones.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "pan_api.h"
+#include "gki.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bd.h"
+#include <string.h>
+
+static const tBTA_SYS_REG bta_pan_reg =
+{
+    bta_pan_hdl_event,
+    BTA_PanDisable
+};
+
+/*******************************************************************************
+**
+** Function         BTA_PanEnable
+**
+** Description      Enable PAN service.  This function must be
+**                  called before any other functions in the PAN API are called.
+**                  When the enable operation is complete the callback function
+**                  will be called with a BTA_PAN_ENABLE_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_PanEnable(tBTA_PAN_CBACK p_cback)
+{
+    tBTA_PAN_API_ENABLE  *p_buf;
+
+    /* register with BTA system manager */
+    GKI_sched_lock();
+    bta_sys_register(BTA_ID_PAN, &bta_pan_reg);
+    GKI_sched_unlock();
+
+    if ((p_buf = (tBTA_PAN_API_ENABLE *) GKI_getbuf(sizeof(tBTA_PAN_API_ENABLE))) != NULL)
+    {
+        p_buf->hdr.event = BTA_PAN_API_ENABLE_EVT;
+        p_buf->p_cback = p_cback;
+
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         BTA_PanDisable
+**
+** Description      Disables PAN service.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_PanDisable(void)
+{
+    BT_HDR  *p_buf;
+
+    bta_sys_deregister(BTA_ID_PAN);
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_PAN_API_DISABLE_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_PanSetRole
+**
+** Description      Sets PAN roles. When the enable operation is complete
+**                  the callback function will be called with a BTA_PAN_SET_ROLE_EVT.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_PanSetRole(tBTA_PAN_ROLE role, tBTA_PAN_ROLE_INFO *p_user_info, tBTA_PAN_ROLE_INFO *p_gn_info,
+                                        tBTA_PAN_ROLE_INFO *p_nap_info)
+{
+
+    tBTA_PAN_API_SET_ROLE  *p_buf;
+
+    if ((p_buf = (tBTA_PAN_API_SET_ROLE *) GKI_getbuf(sizeof(tBTA_PAN_API_SET_ROLE))) != NULL)
+    {
+        p_buf->hdr.event = BTA_PAN_API_SET_ROLE_EVT;
+        p_buf->role = role;
+
+        if(p_user_info && (role & BTA_PAN_ROLE_PANU))
+        {
+            if(p_user_info->p_srv_name)
+                BCM_STRNCPY_S(p_buf->user_name, sizeof(p_buf->user_name), p_user_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+            else
+                p_buf->user_name[0] = 0;
+
+            p_buf->user_name[BTA_SERVICE_NAME_LEN] = 0;
+            p_buf->user_app_id = p_user_info->app_id;
+            p_buf->user_sec_mask = p_user_info->sec_mask;
+        }
+
+        if(p_gn_info && (role & BTA_PAN_ROLE_GN))
+        {
+            if(p_gn_info->p_srv_name)
+                BCM_STRNCPY_S(p_buf->gn_name, sizeof(p_buf->gn_name), p_gn_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+            else
+                p_buf->gn_name[0] = 0;
+
+            p_buf->gn_name[BTA_SERVICE_NAME_LEN] = 0;
+            p_buf->gn_app_id = p_gn_info->app_id;
+            p_buf->gn_sec_mask = p_gn_info->sec_mask;
+
+        }
+
+        if(p_nap_info && (role & BTA_PAN_ROLE_NAP))
+        {
+            if(p_nap_info->p_srv_name)
+                BCM_STRNCPY_S(p_buf->nap_name, sizeof(p_buf->nap_name), p_nap_info->p_srv_name, BTA_SERVICE_NAME_LEN);
+            else
+                p_buf->nap_name[0] = 0;
+
+            p_buf->nap_name[BTA_SERVICE_NAME_LEN] = 0;
+            p_buf->nap_app_id = p_nap_info->app_id;
+            p_buf->nap_sec_mask = p_nap_info->sec_mask;
+
+        }
+
+        bta_sys_sendmsg(p_buf);
+    }
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_PanOpen
+**
+** Description      Opens a connection to a peer device.
+**                  When connection is open callback function is called
+**                  with a BTA_PAN_OPEN_EVT.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_PanOpen(BD_ADDR bd_addr, tBTA_PAN_ROLE    local_role, tBTA_PAN_ROLE    peer_role)
+{
+
+    tBTA_PAN_API_OPEN  *p_buf;
+
+    if ((p_buf = (tBTA_PAN_API_OPEN *) GKI_getbuf(sizeof(tBTA_PAN_API_OPEN))) != NULL)
+    {
+        p_buf->hdr.event = BTA_PAN_API_OPEN_EVT;
+        p_buf->local_role = local_role;
+        p_buf->peer_role = peer_role;
+        bdcpy(p_buf->bd_addr, bd_addr);
+        bta_sys_sendmsg(p_buf);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         BTA_PanClose
+**
+** Description      Close a PAN  connection to a peer device.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void BTA_PanClose(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->event = BTA_PAN_API_CLOSE_EVT;
+        p_buf->layer_specific = handle;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+#endif /* BTA_PAN_INCLUDED */
diff --git a/bta/pan/bta_pan_ci.c b/bta/pan/bta_pan_ci.c
new file mode 100644
index 0000000..f8e5832
--- /dev/null
+++ b/bta/pan/bta_pan_ci.c
@@ -0,0 +1,260 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the implementation file for data gateway call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include <string.h>
+
+#include "gki.h"
+#include "pan_api.h"
+#include "bd.h"
+#include "bta_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_ci.h"
+#include "bta_pan_int.h"
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_tx_ready
+**
+** Description      This function sends an event to PAN indicating the phone is
+**                  ready for more data and PAN should call bta_pan_co_tx_path().
+**                  This function is used when the TX data path is configured
+**                  to use a pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_tx_ready(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->layer_specific = handle;
+        p_buf->event = BTA_PAN_CI_TX_READY_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_rx_ready
+**
+** Description      This function sends an event to PAN indicating the phone
+**                  has data available to send to PAN and PAN should call
+**                  bta_pan_co_rx_path().  This function is used when the RX
+**                  data path is configured to use a pull interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_ready(UINT16 handle)
+{
+    BT_HDR  *p_buf;
+
+    if ((p_buf = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+    {
+        p_buf->layer_specific = handle;
+        p_buf->event = BTA_PAN_CI_RX_READY_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_tx_flow
+**
+** Description      This function is called to enable or disable data flow on
+**                  the TX path.  The phone should call this function to
+**                  disable data flow when it is congested and cannot handle
+**                  any more data sent by bta_pan_co_tx_write() or
+**                  bta_pan_co_tx_writebuf().  This function is used when the
+**                  TX data path is configured to use a push interface.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_tx_flow(UINT16 handle, BOOLEAN enable)
+{
+    tBTA_PAN_CI_TX_FLOW  *p_buf;
+
+    if ((p_buf = (tBTA_PAN_CI_TX_FLOW *) GKI_getbuf(sizeof(tBTA_PAN_CI_TX_FLOW))) != NULL)
+    {
+        p_buf->hdr.layer_specific = handle;
+        p_buf->hdr.event = BTA_PAN_CI_TX_FLOW_EVT;
+        p_buf->enable = enable;
+        bta_sys_sendmsg(p_buf);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_rx_write
+**
+** Description      This function is called to send data to PAN when the RX path
+**                  is configured to use a push interface.  The function copies
+**                  data to an event buffer and sends it to PAN.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_write(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
+                            UINT8 *p_data, UINT16 len, BOOLEAN ext)
+{
+    BT_HDR * p_buf;
+
+    if((p_buf = (BT_HDR *) GKI_getpoolbuf(PAN_POOL_ID)) != NULL)
+    {
+
+
+        p_buf->offset = PAN_MINIMUM_OFFSET;
+
+        /* copy all other params before the data */
+        bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src);
+        bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst);
+        ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol;
+        ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext;
+        p_buf->len=len;
+
+        /* copy data */
+        memcpy((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, len);
+
+        p_buf->layer_specific = handle;
+        p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT;
+        bta_sys_sendmsg(p_buf);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_rx_writebuf
+**
+** Description      This function is called to send data to the phone when
+**                  the RX path is configured to use a push interface with
+**                  zero copy.  The function sends an event to PAN containing
+**                  the data buffer.  The buffer must be allocated using
+**                  functions GKI_getbuf() or GKI_getpoolbuf().  The buffer
+**                  will be freed by BTA; the phone must not free the buffer.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_rx_writebuf(UINT16 handle, BD_ADDR dst, BD_ADDR src, UINT16 protocol,
+                            BT_HDR *p_buf, BOOLEAN ext)
+{
+
+    /* copy all other params before the data */
+    bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->src, src);
+    bdcpy(((tBTA_PAN_DATA_PARAMS *)p_buf)->dst, dst);
+    ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol = protocol;
+    ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext = ext;
+
+    p_buf->layer_specific = handle;
+    p_buf->event = BTA_PAN_CI_RX_WRITEBUF_EVT;
+    bta_sys_sendmsg(p_buf);
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_readbuf
+**
+** Description
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BT_HDR * bta_pan_ci_readbuf(UINT16 handle, BD_ADDR src, BD_ADDR dst, UINT16* p_protocol,
+                                 BOOLEAN* p_ext, BOOLEAN* p_forward)
+{
+    tBTA_PAN_SCB * p_scb;
+    BT_HDR * p_buf;
+
+    p_scb = bta_pan_scb_by_handle(handle);
+
+    p_buf =  (BT_HDR *)GKI_dequeue(&p_scb->data_queue);
+
+    if(p_buf)
+    {
+        bdcpy(src,((tBTA_PAN_DATA_PARAMS *)p_buf)->src);
+        bdcpy(dst,((tBTA_PAN_DATA_PARAMS *)p_buf)->dst);
+        *p_protocol = ((tBTA_PAN_DATA_PARAMS *)p_buf)->protocol;
+        *p_ext = ((tBTA_PAN_DATA_PARAMS *)p_buf)->ext;
+        *p_forward = ((tBTA_PAN_DATA_PARAMS *)p_buf)->forward;
+    }
+
+    return p_buf;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_set_mfilters
+**
+** Description      This function is called to set multicast filters
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_set_mfilters(UINT16 handle, UINT16 num_mcast_filters, UINT8 *p_start_array,
+                                                    UINT8 *p_end_array)
+{
+
+    PAN_SetMulticastFilters(handle, num_mcast_filters, p_start_array, p_end_array);
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_ci_set_mfilters
+**
+** Description      This function is called to set protocol filters
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_ci_set_pfilters(UINT16 handle, UINT16 num_filters, UINT16 *p_start_array, UINT16 *p_end_array)
+{
+
+    PAN_SetProtocolFilters(handle, num_filters, p_start_array, p_end_array );
+
+}
+
+#endif /* BTA_PAN_API */
diff --git a/bta/pan/bta_pan_int.h b/bta/pan/bta_pan_int.h
new file mode 100644
index 0000000..1667e57
--- /dev/null
+++ b/bta/pan/bta_pan_int.h
@@ -0,0 +1,212 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 is the private interface file for the BTA data gateway.
+ *
+ ******************************************************************************/
+#ifndef BTA_PAN_INT_H
+#define BTA_PAN_INT_H
+
+#include "bta_sys.h"
+#include "bta_pan_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+
+
+
+/* PAN events */
+enum
+{
+    /* these events are handled by the state machine */
+    BTA_PAN_API_CLOSE_EVT = BTA_SYS_EVT_START(BTA_ID_PAN),
+    BTA_PAN_CI_TX_READY_EVT,
+    BTA_PAN_CI_RX_READY_EVT,
+    BTA_PAN_CI_TX_FLOW_EVT,
+    BTA_PAN_CI_RX_WRITE_EVT,
+    BTA_PAN_CI_RX_WRITEBUF_EVT,
+    BTA_PAN_CONN_OPEN_EVT,
+    BTA_PAN_CONN_CLOSE_EVT,
+    BTA_PAN_BNEP_FLOW_ENABLE_EVT,
+    BTA_PAN_RX_FROM_BNEP_READY_EVT,
+
+    /* these events are handled outside of the state machine */
+    BTA_PAN_API_ENABLE_EVT,
+    BTA_PAN_API_DISABLE_EVT,
+    BTA_PAN_API_SET_ROLE_EVT,
+    BTA_PAN_API_OPEN_EVT
+};
+
+
+
+
+/*****************************************************************************
+**  Data types
+*****************************************************************************/
+
+/* data type for BTA_PAN_API_ENABLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;                        /* Event header */
+    tBTA_PAN_CBACK     *p_cback;                    /* PAN callback function */
+} tBTA_PAN_API_ENABLE;
+
+/* data type for BTA_PAN_API_REG_ROLE_EVT */
+typedef struct
+{
+    BT_HDR              hdr;                             /* Event header */
+    char                user_name[BTA_SERVICE_NAME_LEN+1];   /* Service name */
+    char                gn_name[BTA_SERVICE_NAME_LEN+1];     /* Service name */
+    char                nap_name[BTA_SERVICE_NAME_LEN+1];    /* Service name */
+    tBTA_PAN_ROLE       role;
+    UINT8               user_app_id;
+    UINT8               gn_app_id;
+    UINT8               nap_app_id;
+    tBTA_SEC            user_sec_mask;                   /* Security mask */
+    tBTA_SEC            gn_sec_mask;                     /* Security mask */
+    tBTA_SEC            nap_sec_mask;                    /* Security mask */
+
+
+} tBTA_PAN_API_SET_ROLE;
+
+/* data type for BTA_PAN_API_OPEN_EVT */
+typedef struct
+{
+    BT_HDR              hdr;                        /* Event header */
+    tBTA_PAN_ROLE        local_role;                 /* local role */
+    tBTA_PAN_ROLE        peer_role;                  /* peer role */
+    BD_ADDR             bd_addr;                    /* peer bdaddr */
+} tBTA_PAN_API_OPEN;
+
+/* data type for BTA_PAN_CI_TX_FLOW_EVT */
+typedef struct
+{
+    BT_HDR          hdr;                    /* Event header */
+    BOOLEAN         enable;                 /* Flow control setting */
+} tBTA_PAN_CI_TX_FLOW;
+
+/* data type for BTA_PAN_CONN_OPEN_EVT */
+typedef struct
+{
+    BT_HDR          hdr;        /* Event header */
+    tPAN_RESULT     result;
+
+} tBTA_PAN_CONN;
+
+
+
+
+/* union of all data types */
+typedef union
+{
+    BT_HDR                   hdr;
+    tBTA_PAN_API_ENABLE      api_enable;
+    tBTA_PAN_API_SET_ROLE    api_set_role;
+    tBTA_PAN_API_OPEN        api_open;
+    tBTA_PAN_CI_TX_FLOW      ci_tx_flow;
+    tBTA_PAN_CONN            conn;
+} tBTA_PAN_DATA;
+
+/* state machine control block */
+typedef struct
+{
+    BD_ADDR                 bd_addr;        /* peer bdaddr */
+    BUFFER_Q                data_queue;     /* Queue of buffers waiting to be passed to application */
+    UINT16                  handle;         /* BTA PAN/BNEP handle */
+    BOOLEAN                 in_use;         /* scb in use */
+    tBTA_SEC                sec_mask;       /* Security mask */
+    BOOLEAN                 pan_flow_enable;/* BNEP flow control state */
+    BOOLEAN                 app_flow_enable;/* Application flow control state */
+    UINT8                   state;          /* State machine state */
+    tBTA_PAN_ROLE            local_role;     /* local role */
+    tBTA_PAN_ROLE            peer_role;      /* peer role */
+    UINT8                    app_id;         /* application id for the connection */
+
+} tBTA_PAN_SCB;
+
+
+
+/* main control block */
+typedef struct
+{
+    tBTA_PAN_SCB    scb[BTA_PAN_NUM_CONN];          /* state machine control blocks */
+    tBTA_PAN_CBACK *p_cback;                        /* PAN callback function */
+    UINT8            app_id[3];                      /* application id for PAN roles */
+    UINT8           flow_mask;                      /* Data flow mask */
+    UINT8           q_level;                        /* queue level set by application for TX data */
+
+} tBTA_PAN_CB;
+
+
+/* pan data param */
+typedef struct
+{
+    BT_HDR  hdr;
+    BD_ADDR src;
+    BD_ADDR dst;
+    UINT16  protocol;
+    BOOLEAN ext;
+    BOOLEAN forward;
+
+} tBTA_PAN_DATA_PARAMS;
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* PAN control block */
+
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_PAN_CB  bta_pan_cb;
+#else
+extern tBTA_PAN_CB *bta_pan_cb_ptr;
+#define bta_pan_cb (*bta_pan_cb_ptr)
+#endif
+
+/*****************************************************************************
+**  Function prototypes
+*****************************************************************************/
+extern tBTA_PAN_SCB *bta_pan_scb_alloc(void);
+extern void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb);
+extern UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb);
+extern tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle);
+extern BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg);
+
+/* action functions */
+extern void bta_pan_enable(tBTA_PAN_DATA *p_data);
+extern void bta_pan_disable(void);
+extern void bta_pan_set_role(tBTA_PAN_DATA *p_data);
+extern void bta_pan_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_api_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_set_shutdown(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_rx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_tx_path(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_tx_flow(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_conn_open(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_conn_close(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_writebuf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_write_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+extern void bta_pan_free_buf(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+
+
+#endif /* BTA_PAN_INT_H */
diff --git a/bta/pan/bta_pan_main.c b/bta/pan/bta_pan_main.c
new file mode 100644
index 0000000..add1c7c
--- /dev/null
+++ b/bta/pan/bta_pan_main.c
@@ -0,0 +1,421 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2004-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 the PAN main functions and state machine.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PAN_INCLUDED) && (BTA_PAN_INCLUDED == TRUE)
+
+#include <string.h>
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "gki.h"
+#include "pan_api.h"
+#include "bta_pan_api.h"
+#include "bta_pan_int.h"
+#include "bd.h"
+
+/*****************************************************************************
+** Constants and types
+*****************************************************************************/
+
+
+
+/* state machine action enumeration list */
+enum
+{
+    BTA_PAN_API_CLOSE,
+    BTA_PAN_TX_PATH,
+    BTA_PAN_RX_PATH,
+    BTA_PAN_TX_FLOW,
+    BTA_PAN_WRITE_BUF,
+    BTA_PAN_CONN_OPEN,
+    BTA_PAN_CONN_CLOSE,
+    BTA_PAN_FREE_BUF,
+    BTA_PAN_IGNORE
+};
+
+
+
+/* type for action functions */
+typedef void (*tBTA_PAN_ACTION)(tBTA_PAN_SCB *p_scb, tBTA_PAN_DATA *p_data);
+
+
+
+
+/* action function list */
+const tBTA_PAN_ACTION bta_pan_action[] =
+{
+    bta_pan_api_close,
+    bta_pan_tx_path,
+    bta_pan_rx_path,
+    bta_pan_tx_flow,
+    bta_pan_write_buf,
+    bta_pan_conn_open,
+    bta_pan_conn_close,
+    bta_pan_free_buf,
+
+};
+
+/* state table information */
+#define BTA_PAN_ACTIONS              1       /* number of actions */
+#define BTA_PAN_NEXT_STATE           1       /* position of next state */
+#define BTA_PAN_NUM_COLS             2       /* number of columns in state tables */
+
+
+/* state machine states */
+enum
+{
+    BTA_PAN_IDLE_ST,
+    BTA_PAN_OPEN_ST,
+    BTA_PAN_CLOSING_ST
+};
+
+
+/* state table for listen state */
+const UINT8 bta_pan_st_idle[][BTA_PAN_NUM_COLS] =
+{
+   /* API_CLOSE */          {BTA_PAN_API_CLOSE,              BTA_PAN_IDLE_ST},
+   /* CI_TX_READY */        {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* CI_RX_READY */        {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* CI_TX_FLOW */         {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* CI_RX_WRITE */        {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* CI_RX_WRITEBUF */     {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* PAN_CONN_OPEN */      {BTA_PAN_CONN_OPEN,              BTA_PAN_OPEN_ST},
+   /* PAN_CONN_CLOSE */     {BTA_PAN_CONN_OPEN,              BTA_PAN_IDLE_ST},
+   /* FLOW_ENABLE */        {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST},
+   /* BNEP_DATA */          {BTA_PAN_IGNORE,                 BTA_PAN_IDLE_ST}
+
+};
+
+
+
+/* state table for open state */
+const UINT8 bta_pan_st_open[][BTA_PAN_NUM_COLS] =
+{
+   /* API_CLOSE */          {BTA_PAN_API_CLOSE,               BTA_PAN_OPEN_ST},
+   /* CI_TX_READY */        {BTA_PAN_TX_PATH,                 BTA_PAN_OPEN_ST},
+   /* CI_RX_READY */        {BTA_PAN_RX_PATH,                 BTA_PAN_OPEN_ST},
+   /* CI_TX_FLOW */         {BTA_PAN_TX_FLOW,                 BTA_PAN_OPEN_ST},
+   /* CI_RX_WRITE */        {BTA_PAN_IGNORE,                  BTA_PAN_OPEN_ST},
+   /* CI_RX_WRITEBUF */     {BTA_PAN_WRITE_BUF,               BTA_PAN_OPEN_ST},
+   /* PAN_CONN_OPEN */      {BTA_PAN_IGNORE,                  BTA_PAN_OPEN_ST},
+   /* PAN_CONN_CLOSE */     {BTA_PAN_CONN_CLOSE,              BTA_PAN_IDLE_ST},
+   /* FLOW_ENABLE */        {BTA_PAN_RX_PATH,                 BTA_PAN_OPEN_ST},
+   /* BNEP_DATA */          {BTA_PAN_TX_PATH,                 BTA_PAN_OPEN_ST}
+};
+
+/* state table for closing state */
+const UINT8 bta_pan_st_closing[][BTA_PAN_NUM_COLS] =
+{
+   /* API_CLOSE */          {BTA_PAN_IGNORE,                   BTA_PAN_CLOSING_ST},
+   /* CI_TX_READY */        {BTA_PAN_TX_PATH,                  BTA_PAN_CLOSING_ST},
+   /* CI_RX_READY */        {BTA_PAN_RX_PATH,                  BTA_PAN_CLOSING_ST},
+   /* CI_TX_FLOW */         {BTA_PAN_TX_FLOW,                  BTA_PAN_CLOSING_ST},
+   /* CI_RX_WRITE */        {BTA_PAN_IGNORE,                   BTA_PAN_CLOSING_ST},
+   /* CI_RX_WRITEBUF */     {BTA_PAN_FREE_BUF,                 BTA_PAN_CLOSING_ST},
+   /* PAN_CONN_OPEN */      {BTA_PAN_IGNORE,                   BTA_PAN_CLOSING_ST},
+   /* PAN_CONN_CLOSE */     {BTA_PAN_CONN_CLOSE,               BTA_PAN_IDLE_ST},
+   /* FLOW_ENABLE */        {BTA_PAN_RX_PATH,                  BTA_PAN_CLOSING_ST},
+   /* BNEP_DATA */          {BTA_PAN_TX_PATH,                  BTA_PAN_CLOSING_ST}
+};
+
+/* type for state table */
+typedef const UINT8 (*tBTA_PAN_ST_TBL)[BTA_PAN_NUM_COLS];
+
+/* state table */
+const tBTA_PAN_ST_TBL bta_pan_st_tbl[] = {
+    bta_pan_st_idle,
+    bta_pan_st_open,
+    bta_pan_st_closing
+};
+
+/*****************************************************************************
+** Global data
+*****************************************************************************/
+
+/* PAN control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_PAN_CB  bta_pan_cb;
+#endif
+
+/*******************************************************************************
+**
+** Function         bta_pan_scb_alloc
+**
+** Description      Allocate a PAN server control block.
+**
+**
+** Returns          pointer to the scb, or NULL if none could be allocated.
+**
+*******************************************************************************/
+tBTA_PAN_SCB *bta_pan_scb_alloc(void)
+{
+    tBTA_PAN_SCB     *p_scb = &bta_pan_cb.scb[0];
+    int             i;
+
+    for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+    {
+        if (!p_scb->in_use)
+        {
+            p_scb->in_use = TRUE;
+            APPL_TRACE_DEBUG1("bta_pan_scb_alloc %d", i);
+            break;
+        }
+    }
+
+    if (i == BTA_PAN_NUM_CONN)
+    {
+        /* out of scbs */
+        p_scb = NULL;
+        APPL_TRACE_WARNING0("Out of scbs");
+    }
+    return p_scb;
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_sm_execute
+**
+** Description      State machine event handling function for PAN
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_sm_execute(tBTA_PAN_SCB *p_scb, UINT16 event, tBTA_PAN_DATA *p_data)
+{
+    tBTA_PAN_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+    APPL_TRACE_EVENT3("PAN scb=%d event=0x%x state=%d", bta_pan_scb_to_idx(p_scb), event, p_scb->state);
+
+    /* look up the state table for the current state */
+    state_table = bta_pan_st_tbl[p_scb->state];
+
+    event &= 0x00FF;
+
+    /* set next state */
+    p_scb->state = state_table[event][BTA_PAN_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_PAN_ACTIONS; i++)
+    {
+        if ((action = state_table[event][i]) != BTA_PAN_IGNORE)
+        {
+            (*bta_pan_action[action])(p_scb, p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_api_enable
+**
+** Description      Handle an API enable event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_api_enable(tBTA_PAN_DATA *p_data)
+{
+    /* initialize control block */
+    memset(&bta_pan_cb, 0, sizeof(bta_pan_cb));
+
+    /* store callback function */
+    bta_pan_cb.p_cback = p_data->api_enable.p_cback;
+    bta_pan_enable(p_data);
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_api_disable
+**
+** Description      Handle an API disable event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_api_disable(tBTA_PAN_DATA *p_data)
+{
+    bta_pan_disable();
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_api_open
+**
+** Description      Handle an API listen event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_pan_api_open(tBTA_PAN_DATA *p_data)
+{
+    tBTA_PAN_SCB     *p_scb;
+    tBTA_PAN_OPEN data;
+
+    /* allocate an scb */
+    if ((p_scb = bta_pan_scb_alloc()) != NULL)
+    {
+        bta_pan_open(p_scb, p_data);
+    }
+    else
+    {
+        bdcpy(data.bd_addr, p_data->api_open.bd_addr);
+        data.status = BTA_PAN_FAIL;
+        bta_pan_cb.p_cback(BTA_PAN_OPEN_EVT, (tBTA_PAN *)&data);
+
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_pan_scb_dealloc
+**
+** Description      Deallocate a link control block.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_pan_scb_dealloc(tBTA_PAN_SCB *p_scb)
+{
+    APPL_TRACE_DEBUG1("bta_pan_scb_dealloc %d", bta_pan_scb_to_idx(p_scb));
+    memset(p_scb, 0, sizeof(tBTA_PAN_SCB));
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_scb_to_idx
+**
+** Description      Given a pointer to an scb, return its index.
+**
+**
+** Returns          Index of scb.
+**
+*******************************************************************************/
+UINT8 bta_pan_scb_to_idx(tBTA_PAN_SCB *p_scb)
+{
+
+    return ((UINT8) (p_scb - bta_pan_cb.scb)) + 1;
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_pan_scb_by_handle
+**
+** Description      Find scb associated with handle.
+**
+**
+** Returns          Pointer to scb or NULL if not found.
+**
+*******************************************************************************/
+tBTA_PAN_SCB *bta_pan_scb_by_handle(UINT16 handle)
+{
+    tBTA_PAN_SCB     *p_scb = &bta_pan_cb.scb[0];
+    UINT8 i;
+
+    for (i = 0; i < BTA_PAN_NUM_CONN; i++, p_scb++)
+    {
+        if (p_scb->handle == handle)
+        {
+            return p_scb;;
+        }
+    }
+
+
+    APPL_TRACE_WARNING1("No scb for handle %d", handle);
+
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_pan_hdl_event
+**
+** Description      Data gateway main event handling function.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_pan_hdl_event(BT_HDR *p_msg)
+{
+    tBTA_PAN_SCB *p_scb;
+    BOOLEAN     freebuf = TRUE;
+
+    switch (p_msg->event)
+    {
+        /* handle enable event */
+        case BTA_PAN_API_ENABLE_EVT:
+            bta_pan_api_enable((tBTA_PAN_DATA *) p_msg);
+            break;
+
+        /* handle disable event */
+        case BTA_PAN_API_DISABLE_EVT:
+            bta_pan_api_disable((tBTA_PAN_DATA *) p_msg);
+            break;
+
+        /* handle set role event */
+        case BTA_PAN_API_SET_ROLE_EVT:
+            bta_pan_set_role((tBTA_PAN_DATA *) p_msg);
+            break;
+
+        /* handle open event */
+        case BTA_PAN_API_OPEN_EVT:
+            bta_pan_api_open((tBTA_PAN_DATA *) p_msg);
+            break;
+
+
+        /* events that require buffer not be released */
+        case BTA_PAN_CI_RX_WRITEBUF_EVT:
+            freebuf = FALSE;
+            if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL)
+            {
+                bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg);
+            }
+            break;
+
+        /* all other events */
+        default:
+            if ((p_scb = bta_pan_scb_by_handle(p_msg->layer_specific)) != NULL)
+            {
+                bta_pan_sm_execute(p_scb, p_msg->event, (tBTA_PAN_DATA *) p_msg);
+            }
+            break;
+
+    }
+    return freebuf;
+}
+#endif /* BTA_PAN_INCLUDED */
diff --git a/bta/pb/bta_pbs_cfg.c b/bta/pb/bta_pbs_cfg.c
new file mode 100644
index 0000000..b2782fb
--- /dev/null
+++ b/bta/pb/bta_pbs_cfg.c
@@ -0,0 +1,51 @@
+/******************************************************************************
+ *
+ *  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 compile-time configurable constants for the BTA Phone
+ *  Book Access Server.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+
+#if defined(BTA_PBS_INCLUDED) && (BTA_PBS_INCLUDED == TRUE)
+
+#include "bta_pbs_int.h"
+
+/* Realm Character Set */
+#ifndef BTA_PBS_REALM_CHARSET
+#define BTA_PBS_REALM_CHARSET   0       /* ASCII */
+#endif
+
+/* Specifies whether or not client's user id is required during obex authentication */
+#ifndef BTA_PBS_USERID_REQ
+#define BTA_PBS_USERID_REQ      FALSE
+#endif
+
+const tBTA_PBS_CFG bta_pbs_cfg =
+{
+    BTA_PBS_REALM_CHARSET,      /* Server only */
+    BTA_PBS_USERID_REQ,         /* Server only */
+    (BTA_PBS_SUPF_DOWNLOAD | BTA_PBS_SURF_BROWSE),
+    BTA_PBS_REPOSIT_LOCAL,
+};
+
+tBTA_PBS_CFG *p_bta_pbs_cfg = (tBTA_PBS_CFG *)&bta_pbs_cfg;
+#endif /* BTA_PBS_INCLUDED */
diff --git a/bta/pb/bta_pbs_int.h b/bta/pb/bta_pbs_int.h
new file mode 100644
index 0000000..a4fce2b
--- /dev/null
+++ b/bta/pb/bta_pbs_int.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ *  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 is the private file for the phone book access server (PBS).
+ *
+ ******************************************************************************/
+#ifndef BTA_PBS_INT_H
+#define BTA_PBS_INT_H
+
+#include "bt_target.h"
+#include "bta_pbs_api.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+#define BTA_PBS_TARGET_UUID "\x79\x61\x35\xf0\xf0\xc5\x11\xd8\x09\x66\x08\x00\x20\x0c\x9a\x66"
+#define BTA_PBS_UUID_LENGTH                 16
+#define BTA_PBS_MAX_AUTH_KEY_SIZE           16  /* Must not be greater than OBX_MAX_AUTH_KEY_SIZE */
+
+#define BTA_PBS_DEFAULT_VERSION             0x0101  /* for PBAP PSE version 1.1 */
+
+
+/* Configuration structure */
+typedef struct
+{
+    UINT8       realm_charset;          /* Server only */
+    BOOLEAN     userid_req;             /* TRUE if user id is required during obex authentication (Server only) */
+    UINT8       supported_features;     /* Server supported features */
+    UINT8       supported_repositories; /* Server supported repositories */
+
+} tBTA_PBS_CFG;
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+
+#endif /* BTA_PBS_INT_H */
diff --git a/bta/sys/bd.c b/bta/sys/bd.c
new file mode 100644
index 0000000..052f9b9
--- /dev/null
+++ b/bta/sys/bd.c
@@ -0,0 +1,112 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  BD address services.
+ *
+ ******************************************************************************/
+
+#include "data_types.h"
+#include "bd.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/* global constant for "any" bd addr */
+const BD_ADDR bd_addr_any = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
+const BD_ADDR bd_addr_null= {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/*****************************************************************************
+**  Functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** Function         bdcpy
+**
+** Description      Copy bd addr b to a.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bdcpy(BD_ADDR a, const BD_ADDR b)
+{
+    int i;
+
+    for (i = BD_ADDR_LEN; i != 0; i--)
+    {
+        *a++ = *b++;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bdcmp
+**
+** Description      Compare bd addr b to a.
+**
+**
+** Returns          Zero if b==a, nonzero otherwise (like memcmp).
+**
+*******************************************************************************/
+int bdcmp(const BD_ADDR a, const BD_ADDR b)
+{
+    int i;
+
+    for (i = BD_ADDR_LEN; i != 0; i--)
+    {
+        if (*a++ != *b++)
+        {
+            return -1;
+        }
+    }
+    return 0;
+}
+
+/*******************************************************************************
+**
+** Function         bdcmpany
+**
+** Description      Compare bd addr to "any" bd addr.
+**
+**
+** Returns          Zero if a equals bd_addr_any.
+**
+*******************************************************************************/
+int bdcmpany(const BD_ADDR a)
+{
+    return bdcmp(a, bd_addr_any);
+}
+
+/*******************************************************************************
+**
+** Function         bdsetany
+**
+** Description      Set bd addr to "any" bd addr.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bdsetany(BD_ADDR a)
+{
+    bdcpy(a, bd_addr_any);
+}
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
new file mode 100644
index 0000000..5d724e5
--- /dev/null
+++ b/bta/sys/bta_sys.h
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ *  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 is the public interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_H
+#define BTA_SYS_H
+
+#include "bt_target.h"
+#include "gki.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/* event handler function type */
+typedef BOOLEAN (tBTA_SYS_EVT_HDLR)(BT_HDR *p_msg);
+
+/* disable function type */
+typedef void (tBTA_SYS_DISABLE)(void);
+
+
+/* HW modules */
+enum
+{
+    BTA_SYS_HW_BLUETOOTH,
+    BTA_SYS_HW_FMRX,
+    BTA_SYS_HW_FMTX,
+    BTA_SYS_HW_GPS,
+    BTA_SYS_HW_SENSOR,
+    BTA_SYS_HW_NFC,
+    BTA_SYS_HW_RT,
+
+    BTA_SYS_MAX_HW_MODULES
+};
+
+typedef UINT16 tBTA_SYS_HW_MODULE;
+
+#ifndef BTA_DM_NUM_JV_ID
+#define BTA_DM_NUM_JV_ID    2
+#endif
+
+/* SW sub-systems */
+#define BTA_ID_SYS          0            /* system manager */
+/* BLUETOOTH PART - from 0 to BTA_ID_BLUETOOTH_MAX */
+#define BTA_ID_DM           1            /* device manager */
+#define BTA_ID_DM_SEARCH    2            /* device manager search */
+#define BTA_ID_DM_SEC       3            /* device manager security */
+#define BTA_ID_DG           4            /* data gateway */
+#define BTA_ID_AG           5            /* audio gateway */
+#define BTA_ID_OPC          6            /* object push client */
+#define BTA_ID_OPS          7            /* object push server */
+#define BTA_ID_FTS          8            /* file transfer server */
+#define BTA_ID_CT           9            /* cordless telephony terminal */
+#define BTA_ID_FTC          10           /* file transfer client */
+#define BTA_ID_SS           11           /* synchronization server */
+#define BTA_ID_PR           12           /* Printer client */
+#define BTA_ID_BIC          13           /* Basic Imaging Client */
+#define BTA_ID_PAN          14           /* Personal Area Networking */
+#define BTA_ID_BIS          15           /* Basic Imaging Server */
+#define BTA_ID_ACC          16           /* Advanced Camera Client */
+#define BTA_ID_SC           17           /* SIM Card Access server */
+#define BTA_ID_AV           18           /* Advanced audio/video */
+#define BTA_ID_AVK          19           /* Audio/video sink */
+#define BTA_ID_HD           20           /* HID Device */
+#define BTA_ID_CG           21           /* Cordless Gateway */
+#define BTA_ID_BP           22           /* Basic Printing Client */
+#define BTA_ID_HH           23           /* Human Interface Device Host */
+#define BTA_ID_PBS          24           /* Phone Book Access Server */
+#define BTA_ID_PBC          25           /* Phone Book Access Client */
+#define BTA_ID_JV           26           /* Java */
+#define BTA_ID_HS           27           /* Headset */
+#define BTA_ID_MSE          28           /* Message Server Equipment */
+#define BTA_ID_MCE          29           /* Message Client Equipment */
+#define BTA_ID_HL           30           /* Health Device Profile*/
+#define BTA_ID_GATTC        31           /* GATT Client */
+#define BTA_ID_GATTS        32           /* GATT Client */
+#define BTA_ID_BLUETOOTH_MAX   33        /* last BT profile */
+
+/* FM */
+#define BTA_ID_FM           34           /* FM  */
+#define BTA_ID_FMTX         35           /* FM TX */
+
+/* SENSOR */
+#define BTA_ID_SSR          36           /* Sensor  */
+
+/* GPS */
+#define BTA_ID_GPS          37           /* GPS  */
+
+/* GENERIC */
+#define BTA_ID_PRM          38
+#define BTA_ID_SYSTEM       39           /* platform-specific */
+#define BTA_ID_SWRAP        40           /* Insight script wrapper */
+#define BTA_ID_MIP          41           /* Multicase Individual Polling */
+#define BTA_ID_RT           42           /* Audio Routing module: This module is always on. */
+
+
+/* JV */
+#define BTA_ID_JV1          43           /* JV1 */
+#define BTA_ID_JV2          44           /* JV2 */
+
+#define BTA_ID_MAX          (43 + BTA_DM_NUM_JV_ID)
+
+typedef UINT8 tBTA_SYS_ID;
+
+
+#define BTA_SYS_CONN_OPEN           0x00
+#define BTA_SYS_CONN_CLOSE          0x01
+#define BTA_SYS_APP_OPEN            0x02
+#define BTA_SYS_APP_CLOSE           0x03
+#define BTA_SYS_SCO_OPEN            0x04
+#define BTA_SYS_SCO_CLOSE           0x05
+#define BTA_SYS_CONN_IDLE           0x06
+#define BTA_SYS_CONN_BUSY           0x07
+
+/* for link policy */
+#define BTA_SYS_PLCY_SET            0x10 /* set the link policy to the given addr */
+#define BTA_SYS_PLCY_CLR            0x11 /* clear the link policy to the given addr */
+#define BTA_SYS_PLCY_DEF_SET        0x12 /* set the default link policy */
+#define BTA_SYS_PLCY_DEF_CLR        0x13 /* clear the default link policy */
+#define BTA_SYS_ROLE_CHANGE         0x14 /* role change */
+
+typedef UINT8 tBTA_SYS_CONN_STATUS;
+
+/* Bitmask of sys features */
+#define BTA_SYS_FEAT_PCM2           0x0001
+#define BTA_SYS_FEAT_PCM2_MASTER    0x0002
+
+/* tBTA_PREF_ROLES */
+typedef UINT8 tBTA_SYS_PREF_ROLES;
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_CONN_CBACK)(tBTA_SYS_CONN_STATUS status,UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+/* conn callback for role / low power manager*/
+typedef void (tBTA_SYS_SSR_CFG_CBACK)(UINT8 id, UINT8 app_id, UINT16 latency, UINT16 tout);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/* eir callback for adding/removeing UUID */
+typedef void (tBTA_SYS_EIR_CBACK)(UINT16 uuid16, BOOLEAN adding);
+#endif
+
+/* registration structure */
+typedef struct
+{
+    tBTA_SYS_EVT_HDLR   *evt_hdlr;
+    tBTA_SYS_DISABLE    *disable;
+} tBTA_SYS_REG;
+
+/* system manager configuration structure */
+typedef struct
+{
+    UINT16          mbox_evt;                       /* GKI mailbox event */
+    UINT8           mbox;                           /* GKI mailbox id */
+    UINT8           timer;                          /* GKI timer id */
+    UINT8           trace_level;                    /* initial trace level */
+} tBTA_SYS_CFG;
+
+/* data type to send events to BTA SYS HW manager */
+typedef struct
+{
+    BT_HDR                hdr;
+    tBTA_SYS_HW_MODULE   hw_module;
+} tBTA_SYS_HW_MSG;
+
+
+
+/*****************************************************************************
+**  Global data
+*****************************************************************************/
+
+/* trace level */
+extern UINT8 appl_trace_level;
+
+/*****************************************************************************
+**  Macros
+*****************************************************************************/
+
+/* Calculate start of event enumeration; id is top 8 bits of event */
+#define BTA_SYS_EVT_START(id)       ((id) << 8)
+
+/*****************************************************************************
+**  events for BTA SYS HW manager
+*****************************************************************************/
+
+/* events sent to SYS HW manager - must be kept synchronized with tables in bta_sys_main.c */
+enum
+{
+    /* device manager local device API events */
+    BTA_SYS_API_ENABLE_EVT = BTA_SYS_EVT_START(BTA_ID_SYS),
+    BTA_SYS_EVT_ENABLED_EVT,
+    BTA_SYS_EVT_STACK_ENABLED_EVT,
+    BTA_SYS_API_DISABLE_EVT,
+    BTA_SYS_EVT_DISABLED_EVT,
+    BTA_SYS_ERROR_EVT,
+
+    BTA_SYS_MAX_EVT
+};
+
+
+
+/* SYS HW status events - returned by SYS HW manager to other modules. */
+enum
+{
+    BTA_SYS_HW_OFF_EVT,
+    BTA_SYS_HW_ON_EVT,
+    BTA_SYS_HW_STARTING_EVT,
+    BTA_SYS_HW_STOPPING_EVT,
+    BTA_SYS_HW_ERROR_EVT
+
+};
+typedef UINT8 tBTA_SYS_HW_EVT;
+
+/* HW enable callback type */
+typedef void (tBTA_SYS_HW_CBACK)(tBTA_SYS_HW_EVT status);
+
+/*****************************************************************************
+**  Function declarations
+*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+BTA_API extern void bta_sys_init(void);
+BTA_API extern void bta_sys_event(BT_HDR *p_msg);
+BTA_API extern void bta_sys_timer_update(void);
+BTA_API extern void bta_sys_disable_timers(void);
+BTA_API extern void bta_sys_set_trace_level(UINT8 level);
+extern void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg);
+extern void bta_sys_deregister(UINT8 id);
+extern BOOLEAN bta_sys_is_register(UINT8 id);
+extern UINT16 bta_sys_get_sys_features(void);
+extern void bta_sys_sendmsg(void *p_msg);
+extern void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout);
+extern void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle);
+extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
+
+extern void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback);
+extern void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module );
+
+
+extern void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+extern void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback);
+
+
+extern void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+extern void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr);
+
+#if (BTM_SSR_INCLUDED == TRUE)
+extern void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback);
+extern void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout);
+#endif
+
+extern void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback);
+extern void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status);
+extern void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback);
+extern void bta_sys_notify_collision (BD_ADDR_PTR p_bda);
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+extern void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback);
+extern void bta_sys_add_uuid(UINT16 uuid16);
+extern void bta_sys_remove_uuid(UINT16 uuid16);
+#else
+#define bta_sys_eir_register(ut)
+#define bta_sys_add_uuid(ut)
+#define bta_sys_remove_uuid(ut)
+#endif
+
+extern void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr);
+extern void bta_sys_set_default_policy (UINT8 id, UINT8 policy);
+extern void bta_sys_clear_default_policy (UINT8 id, UINT8 policy);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BTA_SYS_H */
diff --git a/bta/sys/bta_sys_cfg.c b/bta/sys/bta_sys_cfg.c
new file mode 100644
index 0000000..bcc7e40
--- /dev/null
+++ b/bta/sys/bta_sys_cfg.c
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ *  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 compile-time configurable constants for the BTA
+ *  system manager.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "bta_sys.h"
+
+/* GKI task mailbox event for BTA. */
+#ifndef BTA_MBOX_EVT
+#define BTA_MBOX_EVT                TASK_MBOX_2_EVT_MASK
+#endif
+
+/* GKI task mailbox for BTA. */
+#ifndef BTA_MBOX
+#define BTA_MBOX                    TASK_MBOX_2
+#endif
+
+/* GKI timer id used for protocol timer for BTA. */
+#ifndef BTA_TIMER
+#define BTA_TIMER                   TIMER_1
+#endif
+
+const tBTA_SYS_CFG bta_sys_cfg =
+{
+    BTA_MBOX_EVT,               /* GKI mailbox event */
+    BTA_MBOX,                   /* GKI mailbox id */
+    BTA_TIMER,                  /* GKI timer id */
+    APPL_INITIAL_TRACE_LEVEL    /* initial trace level */
+};
+
+tBTA_SYS_CFG *p_bta_sys_cfg = (tBTA_SYS_CFG *)&bta_sys_cfg;
+
+
diff --git a/bta/sys/bta_sys_ci.c b/bta/sys/bta_sys_ci.c
new file mode 100644
index 0000000..d191077
--- /dev/null
+++ b/bta/sys/bta_sys_ci.c
@@ -0,0 +1,77 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2010-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 is the implementation file for BTA system call-in functions.
+ *
+ ******************************************************************************/
+
+#include "bta_sys.h"
+#include "bta_sys_ci.h"
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_ci_enabled
+**
+** Description      This function must be called in response to function
+**                  bta_sys_hw_enable_co(), when HW is indeed enabled
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+  void bta_sys_hw_ci_enabled(tBTA_SYS_HW_MODULE module )
+
+{
+    tBTA_SYS_HW_MSG *p_msg;
+
+    if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_SYS_EVT_ENABLED_EVT;
+        p_msg->hw_module = module;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_ci_disabled
+**
+** Description      This function must be called in response to function
+**                  bta_sys_hw_disable_co() when HW is really OFF
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_hw_ci_disabled( tBTA_SYS_HW_MODULE module  )
+{
+    tBTA_SYS_HW_MSG *p_msg;
+
+    if ((p_msg = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        p_msg->hdr.event = BTA_SYS_EVT_DISABLED_EVT;
+        p_msg->hw_module = module;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
diff --git a/bta/sys/bta_sys_conn.c b/bta/sys/bta_sys_conn.c
new file mode 100644
index 0000000..b495085
--- /dev/null
+++ b/bta/sys/bta_sys_conn.c
@@ -0,0 +1,577 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Routes connection status callbacks from various sub systems to DM
+ *
+ ******************************************************************************/
+
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+#include "gki.h"
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_rm_register
+**
+** Description      Called by BTA DM to register role management callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_rm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.prm_cb = p_cback;
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_policy_register
+**
+** Description      Called by BTA DM to register link policy change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_policy_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_policy_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_role_chg_register
+**
+** Description      Called by BTA AV to register role change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_role_chg_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_role_cb = p_cback;
+}
+/*******************************************************************************
+**
+** Function         bta_sys_ssr_cfg_register
+**
+** Description      Called by BTA DM to register SSR configuration callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_ssr_cfg_register(tBTA_SYS_SSR_CFG_CBACK * p_cback)
+{
+    bta_sys_cb.p_ssr_cb = p_cback;
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_sys_role_chg_register
+**
+** Description      Called by BTA AV to register role change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_notify_role_chg(BD_ADDR_PTR p_bda, UINT8 new_role, UINT8 hci_status)
+{
+    if (bta_sys_cb.p_role_cb)
+    {
+        bta_sys_cb.p_role_cb(BTA_SYS_ROLE_CHANGE, new_role, hci_status, p_bda);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_collision_register
+**
+** Description      Called by any BTA module to register for collision event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_collision_register(UINT8 bta_id, tBTA_SYS_CONN_CBACK *p_cback)
+{
+    UINT8 index;
+
+    for (index = 0; index < MAX_COLLISION_REG; index++)
+    {
+        if ((bta_sys_cb.colli_reg.id[index] == bta_id) ||
+            (bta_sys_cb.colli_reg.id[index] == 0))
+        {
+            bta_sys_cb.colli_reg.id[index] = bta_id;
+            bta_sys_cb.colli_reg.p_coll_cback[index] = p_cback;
+            return;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_notify_collision
+**
+** Description      Called by BTA DM to notify collision event.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_notify_collision (BD_ADDR_PTR p_bda)
+{
+    UINT8 index;
+
+    for (index = 0; index < MAX_COLLISION_REG; index++)
+    {
+        if ((bta_sys_cb.colli_reg.id[index] != 0) &&
+            (bta_sys_cb.colli_reg.p_coll_cback[index] != NULL))
+        {
+            bta_sys_cb.colli_reg.p_coll_cback[index] (0, BTA_ID_SYS, 0, p_bda);
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_register
+**
+** Description      Called by BTA AV to register sco connection change callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.p_sco_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_pm_register
+**
+** Description      Called by BTA DM to register power management callbacks
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_pm_register(tBTA_SYS_CONN_CBACK * p_cback)
+{
+    bta_sys_cb.ppm_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_conn_open
+**
+** Description      Called by BTA subsystems when a connection is made to
+**                  the service
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_conn_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_OPEN, id, app_id, peer_addr);
+
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_conn_close
+**
+** Description      Called by BTA subsystems when a connection to the service
+**                  is closed
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_conn_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_CLOSE, id, app_id, peer_addr);
+
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_app_open
+**
+** Description      Called by BTA subsystems when application initiates connection
+**                  to a peer device
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_app_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_APP_OPEN, id, app_id, peer_addr);
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_app_close
+**
+** Description      Called by BTA subsystems when application initiates close
+**                  of connection to peer device
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_app_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_APP_CLOSE, id, app_id, peer_addr);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_open
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is open
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_open(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    /* AG triggers p_sco_cb by bta_sys_sco_use. */
+    if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+    {
+        /* without querying BTM_GetNumScoLinks() */
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_SCO_OPEN, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_close
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is closed
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_close(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT8 num_sco_links;
+
+    if((id != BTA_ID_AG) && (bta_sys_cb.p_sco_cb))
+    {
+        num_sco_links = BTM_GetNumScoLinks();
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+        bta_sys_cb.ppm_cb(BTA_SYS_SCO_CLOSE, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_use
+**
+** Description      Called by BTA subsystems when that service needs to use sco.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_use(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    /* AV streaming need to be suspended before SCO is connected. */
+    if(bta_sys_cb.p_sco_cb)
+    {
+        /* without querying BTM_GetNumScoLinks() */
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_OPEN, 1, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sco_unuse
+**
+** Description      Called by BTA subsystems when sco connection for that service
+**                  is no longer needed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sco_unuse(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    UINT8 num_sco_links;
+
+    if((bta_sys_cb.p_sco_cb))
+    {
+        num_sco_links = BTM_GetNumScoLinks();
+        bta_sys_cb.p_sco_cb(BTA_SYS_SCO_CLOSE, num_sco_links, app_id, peer_addr);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_sys_chg_ssr_config
+**
+** Description      Called by BTA subsystems to indicate that the given app SSR setting
+**                  need to be changed.
+**
+** Returns          void
+**
+*******************************************************************************/
+#if (BTM_SSR_INCLUDED == TRUE)
+void bta_sys_chg_ssr_config (UINT8 id, UINT8 app_id, UINT16 max_latency, UINT16 min_tout)
+{
+    if(bta_sys_cb.p_ssr_cb)
+    {
+        bta_sys_cb.p_ssr_cb(id, app_id, max_latency, min_tout);
+    }
+}
+#endif
+/*******************************************************************************
+**
+** Function         bta_sys_set_policy
+**
+** Description      Called by BTA subsystems to indicate that the given link
+**                  policy to peer device should be set
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_SET, id, policy, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_clear_policy
+**
+** Description      Called by BTA subsystems to indicate that the given link
+**                  policy to peer device should be clear
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_clear_policy (UINT8 id, UINT8 policy, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_CLR, id, policy, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_set_default_policy
+**
+** Description      Called by BTA subsystems to indicate that the given default
+**                  link policy should be set
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_default_policy (UINT8 id, UINT8 policy)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_SET, id, policy, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_clear_default_policy
+**
+** Description      Called by BTA subsystems to indicate that the given default
+**                  link policy should be clear
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_clear_default_policy (UINT8 id, UINT8 policy)
+{
+    if(bta_sys_cb.p_policy_cb)
+    {
+        bta_sys_cb.p_policy_cb(BTA_SYS_PLCY_DEF_CLR, id, policy, NULL);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_idle
+**
+** Description      Called by BTA subsystems to indicate that the connection to
+**                  peer device is idle
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_idle(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_IDLE, id, app_id, peer_addr);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_busy
+**
+** Description      Called by BTA subsystems to indicate that the connection to
+**                  peer device is busy
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_busy(UINT8 id, UINT8 app_id, BD_ADDR peer_addr)
+{
+    if(bta_sys_cb.prm_cb)
+    {
+
+        bta_sys_cb.prm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+    }
+
+    if(bta_sys_cb.ppm_cb)
+    {
+
+        bta_sys_cb.ppm_cb(BTA_SYS_CONN_BUSY, id, app_id, peer_addr);
+
+    }
+}
+
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+/*******************************************************************************
+**
+** Function         bta_sys_eir_register
+**
+** Description      Called by BTA DM to register EIR utility function that can be
+**                  used by the other BTA modules to add/remove UUID.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_eir_register(tBTA_SYS_EIR_CBACK * p_cback)
+{
+    bta_sys_cb.eir_cb = p_cback;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_add_uuid
+**
+** Description      Called by BTA subsystems to indicate to DM that new service
+**                  class UUID is added.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_add_uuid(UINT16 uuid16)
+{
+    if(bta_sys_cb.eir_cb)
+    {
+        bta_sys_cb.eir_cb(uuid16, TRUE );
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_remove_uuid
+**
+** Description      Called by BTA subsystems to indicate to DM that the service
+**                  class UUID is removed.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_remove_uuid(UINT16 uuid16)
+{
+    if(bta_sys_cb.eir_cb)
+    {
+        bta_sys_cb.eir_cb(uuid16, FALSE);
+    }
+}
+#endif
+
diff --git a/bta/sys/bta_sys_int.h b/bta/sys/bta_sys_int.h
new file mode 100644
index 0000000..d187b29
--- /dev/null
+++ b/bta/sys/bta_sys_int.h
@@ -0,0 +1,119 @@
+/******************************************************************************
+ *
+ *  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 is the private interface file for the BTA system manager.
+ *
+ ******************************************************************************/
+#ifndef BTA_SYS_INT_H
+#define BTA_SYS_INT_H
+
+#include "ptim.h"
+
+/*****************************************************************************
+**  Constants and data types
+*****************************************************************************/
+
+/*****************************************************************************
+**  state table
+*****************************************************************************/
+
+/* SYS HW state */
+enum
+{
+    BTA_SYS_HW_OFF,
+    BTA_SYS_HW_STARTING,
+    BTA_SYS_HW_ON,
+    BTA_SYS_HW_STOPPING
+};
+typedef UINT8 tBTA_SYS_HW_STATE;
+
+/* Collision callback */
+#define MAX_COLLISION_REG   5
+
+typedef struct
+{
+    UINT8                   id[MAX_COLLISION_REG];
+    tBTA_SYS_CONN_CBACK     *p_coll_cback[MAX_COLLISION_REG];
+} tBTA_SYS_COLLISION;
+
+/* system manager control block */
+typedef struct
+{
+    tBTA_SYS_REG            *reg[BTA_ID_MAX];       /* registration structures */
+    BOOLEAN                 is_reg[BTA_ID_MAX];     /* registration structures */
+    tPTIM_CB                ptim_cb;                /* protocol timer list */
+    BOOLEAN                 timers_disabled;        /* TRUE if sys timers disabled */
+    UINT8                   task_id;                /* GKI task id */
+    tBTA_SYS_HW_STATE state;
+    tBTA_SYS_HW_CBACK *sys_hw_cback[BTA_SYS_MAX_HW_MODULES];    /* enable callback for each HW modules */
+    UINT32                  sys_hw_module_active;   /* bitmask of all active modules */
+    UINT16                  sys_features;           /* Bitmask of sys features */
+
+    tBTA_SYS_CONN_CBACK     *prm_cb;                 /* role management callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *ppm_cb;                 /* low power management callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *p_policy_cb;            /* link policy change callback registered by DM */
+    tBTA_SYS_CONN_CBACK     *p_sco_cb;               /* SCO connection change callback registered by AV */
+    tBTA_SYS_CONN_CBACK     *p_role_cb;              /* role change callback registered by AV */
+    tBTA_SYS_COLLISION      colli_reg;               /* collision handling module */
+#if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&(BTA_EIR_CANNED_UUID_LIST != TRUE)
+    tBTA_SYS_EIR_CBACK      *eir_cb;                /* add/remove UUID into EIR */
+#endif
+#if (BTM_SSR_INCLUDED == TRUE)
+    tBTA_SYS_SSR_CFG_CBACK      *p_ssr_cb;
+#endif
+} tBTA_SYS_CB;
+
+
+
+
+/*****************************************************************************
+**  Global variables
+*****************************************************************************/
+
+/* system manager control block */
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_SYS_CB bta_sys_cb;
+#else
+extern tBTA_SYS_CB *bta_sys_cb_ptr;
+#define bta_sys_cb (*bta_sys_cb_ptr)
+#endif
+
+
+/* system manager configuration structure */
+extern tBTA_SYS_CFG *p_bta_sys_cfg;
+
+
+
+/* functions used for BTA SYS HW state machine */
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status );
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg );
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg);
+
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg);
+
+
+
+
+
+#endif /* BTA_SYS_INT_H */
diff --git a/bta/sys/bta_sys_main.c b/bta/sys/bta_sys_main.c
new file mode 100644
index 0000000..c1554bb
--- /dev/null
+++ b/bta/sys/bta_sys_main.c
@@ -0,0 +1,722 @@
+/******************************************************************************
+ *
+ *  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 is the main implementation file for the BTA system manager.
+ *
+ ******************************************************************************/
+
+#include "btm_api.h"
+#include "bta_api.h"
+#include "bta_sys.h"
+#include "bta_sys_int.h"
+#include "bta_sys_ci.h"
+#include "bta_sys_co.h"
+#if BTA_FM_INCLUDED == TRUE
+#include "bta_fm_api.h"
+#endif
+#if BTA_FMTX_INCLUDED == TRUE
+#include "bta_fmtx_api.h"
+#endif
+#if GPS_INCLUDED == TRUE
+#include "bta_gps_api.h"
+#endif
+
+#include "gki.h"
+#include "ptim.h"
+#include <string.h>
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+#include "bta_ar_api.h"
+#endif
+
+/* protocol timer update period, in milliseconds */
+#ifndef BTA_SYS_TIMER_PERIOD
+#define BTA_SYS_TIMER_PERIOD            1000
+#endif
+
+/* system manager control block definition */
+#if BTA_DYNAMIC_MEMORY == FALSE
+tBTA_SYS_CB bta_sys_cb;
+#endif
+
+/* trace level */
+/* TODO Bluedroid - Hard-coded trace levels -  Needs to be configurable */
+UINT8 appl_trace_level = BT_TRACE_LEVEL_DEBUG; //APPL_INITIAL_TRACE_LEVEL;
+UINT8 btif_trace_level = BT_TRACE_LEVEL_DEBUG;
+
+static const tBTA_SYS_REG bta_sys_hw_reg =
+{
+    bta_sys_sm_execute,
+    NULL
+};
+
+
+/* type for action functions */
+typedef void (*tBTA_SYS_ACTION)(tBTA_SYS_HW_MSG *p_data);
+
+/* action function list */
+const tBTA_SYS_ACTION bta_sys_action[] =
+{
+    /* device manager local device API events - cf bta_sys.h for events */
+    bta_sys_hw_api_enable,             /* 0  BTA_SYS_HW_API_ENABLE_EVT    */
+    bta_sys_hw_evt_enabled,           /* 1  BTA_SYS_HW_EVT_ENABLED_EVT */
+    bta_sys_hw_evt_stack_enabled,       /* 2  BTA_SYS_HW_EVT_STACK_ENABLED_EVT */
+    bta_sys_hw_api_disable,             /* 3  BTA_SYS_HW_API_DISABLE_EVT     */
+    bta_sys_hw_evt_disabled,           /* 4  BTA_SYS_HW_EVT_DISABLED_EVT  */
+    bta_sys_hw_error                        /* 5   BTA_SYS_HW_ERROR_EVT  */
+};
+
+/* state machine action enumeration list */
+enum
+{
+    /* device manager local device API events */
+    BTA_SYS_HW_API_ENABLE,
+    BTA_SYS_HW_EVT_ENABLED,
+    BTA_SYS_HW_EVT_STACK_ENABLED,
+    BTA_SYS_HW_API_DISABLE,
+    BTA_SYS_HW_EVT_DISABLED,
+    BTA_SYS_HW_ERROR
+};
+
+#define BTA_SYS_NUM_ACTIONS  (BTA_SYS_MAX_EVT & 0x00ff)
+#define BTA_SYS_IGNORE       BTA_SYS_NUM_ACTIONS
+
+/* state table information */
+#define BTA_SYS_ACTIONS              2       /* number of actions */
+#define BTA_SYS_NEXT_STATE           2       /* position of next state */
+#define BTA_SYS_NUM_COLS             3       /* number of columns in state tables */
+
+
+/* state table for OFF state */
+const UINT8 bta_sys_hw_off[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1               Action 2             Next State */
+/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,    BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
+/* EVT_ENABLED   */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_HW_EVT_DISABLED,  BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
+/* EVT_DISABLED  */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF},
+/* EVT_ERROR     */  {BTA_SYS_IGNORE,           BTA_SYS_IGNORE,     BTA_SYS_HW_OFF}
+};
+
+const UINT8 bta_sys_hw_starting[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* wait for completion event */
+/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING},
+/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive disable/enable: change state wait for completion to disable */
+/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_HW_API_ENABLE,  BTA_SYS_HW_STARTING}, /* successive enable/disable: notify, then restart HW */
+/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_on[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_HW_API_ENABLE,        BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* EVT_ENABLED   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* STACK_ENABLED */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* API_DISABLE   */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_ON}, /* don't change the state here, as some other modules might be active */
+/* EVT_DISABLED */   {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON},
+/* EVT_ERROR */      {BTA_SYS_HW_ERROR,             BTA_SYS_IGNORE,         BTA_SYS_HW_ON}
+};
+
+const UINT8 bta_sys_hw_stopping[][BTA_SYS_NUM_COLS] =
+{
+/* Event                    Action 1                   Action 2               Next State */
+/* API_ENABLE    */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STARTING}, /* change state, and wait for completion event to enable */
+/* EVT_ENABLED   */  {BTA_SYS_HW_EVT_ENABLED,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* successive enable/disable: finish the enable before disabling */
+/* STACK_ENABLED */  {BTA_SYS_HW_EVT_STACK_ENABLED, BTA_SYS_HW_API_DISABLE, BTA_SYS_HW_STOPPING}, /* successive enable/disable: notify, then stop */
+/* API_DISABLE   */  {BTA_SYS_IGNORE,               BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}, /* wait for completion event */
+/* EVT_DISABLED  */  {BTA_SYS_HW_EVT_DISABLED,      BTA_SYS_IGNORE,         BTA_SYS_HW_OFF},
+/* EVT_ERROR     */  {BTA_SYS_HW_API_DISABLE,       BTA_SYS_IGNORE,         BTA_SYS_HW_STOPPING}
+};
+
+typedef const UINT8 (*tBTA_SYS_ST_TBL)[BTA_SYS_NUM_COLS];
+
+/* state table */
+const tBTA_SYS_ST_TBL bta_sys_st_tbl[] = {
+    bta_sys_hw_off,
+    bta_sys_hw_starting,
+    bta_sys_hw_on,
+    bta_sys_hw_stopping
+};
+
+/*******************************************************************************
+**
+** Function         bta_sys_init
+**
+** Description      BTA initialization; called from task initialization.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_init(void)
+{
+    memset(&bta_sys_cb, 0, sizeof(tBTA_SYS_CB));
+    ptim_init(&bta_sys_cb.ptim_cb, BTA_SYS_TIMER_PERIOD, p_bta_sys_cfg->timer);
+    bta_sys_cb.task_id = GKI_get_taskid();
+    appl_trace_level = p_bta_sys_cfg->trace_level;
+
+    /* register BTA SYS message handler */
+    bta_sys_register( BTA_ID_SYS,  &bta_sys_hw_reg);
+
+    /* register for BTM notifications */
+    BTM_RegisterForDeviceStatusNotif ((tBTM_DEV_STATUS_CB*)&bta_sys_hw_btm_cback );
+
+#if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
+    bta_ar_init();
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_dm_sm_execute
+**
+** Description      State machine event handling function for DM
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_sm_execute(BT_HDR *p_msg)
+{
+    BOOLEAN freebuf = TRUE;
+    tBTA_SYS_ST_TBL      state_table;
+    UINT8               action;
+    int                 i;
+
+    APPL_TRACE_EVENT2("bta_sys_sm_execute state:%d, event:0x%x",  bta_sys_cb.state, p_msg->event);
+
+    /* look up the state table for the current state */
+    state_table = bta_sys_st_tbl[bta_sys_cb.state];
+    /* update state */
+    bta_sys_cb.state = state_table[p_msg->event & 0x00ff][BTA_SYS_NEXT_STATE];
+
+    /* execute action functions */
+    for (i = 0; i < BTA_SYS_ACTIONS; i++)
+    {
+        if ((action = state_table[p_msg->event & 0x00ff][i]) != BTA_SYS_IGNORE)
+        {
+            (*bta_sys_action[action])( (tBTA_SYS_HW_MSG*) p_msg);
+        }
+        else
+        {
+            break;
+        }
+    }
+    return freebuf;
+
+}
+
+
+void bta_sys_hw_register( tBTA_SYS_HW_MODULE module, tBTA_SYS_HW_CBACK *cback)
+{
+    bta_sys_cb.sys_hw_cback[module]=cback;
+}
+
+
+void bta_sys_hw_unregister( tBTA_SYS_HW_MODULE module )
+{
+    bta_sys_cb.sys_hw_cback[module]=NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_btm_cback
+**
+** Description     This function is registered by BTA SYS to BTM in order to get status notifications
+**
+**
+** Returns
+**
+*******************************************************************************/
+void bta_sys_hw_btm_cback( tBTM_DEV_STATUS status )
+{
+
+    tBTA_SYS_HW_MSG *sys_event;
+
+    APPL_TRACE_DEBUG1(" bta_sys_hw_btm_cback was called with parameter: %i" , status );
+
+    /* send a message to BTA SYS */
+    if ((sys_event = (tBTA_SYS_HW_MSG *) GKI_getbuf(sizeof(tBTA_SYS_HW_MSG))) != NULL)
+    {
+        if (status == BTM_DEV_STATUS_UP)
+            sys_event->hdr.event = BTA_SYS_EVT_STACK_ENABLED_EVT;
+        else if (status == BTM_DEV_STATUS_DOWN)
+            sys_event->hdr.event = BTA_SYS_ERROR_EVT;
+        else
+        {
+            /* BTM_DEV_STATUS_CMD_TOUT is ignored for now. */
+            GKI_freebuf (sys_event);
+            sys_event = NULL;
+        }
+
+        if (sys_event)
+        {
+            bta_sys_sendmsg(sys_event);
+        }
+    }
+    else
+    {
+        APPL_TRACE_DEBUG0("ERROR bta_sys_hw_btm_cback couldn't send msg" );
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_error
+**
+** Description     In case the HW device stops answering... Try to turn it off, then re-enable all
+**                      previously active SW modules.
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_error(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+
+    UINT8 module_index;
+
+    APPL_TRACE_DEBUG1("%s", __FUNCTION__);
+
+    for (module_index = 0; module_index < BTA_SYS_MAX_HW_MODULES; module_index++)
+    {
+        if( bta_sys_cb.sys_hw_module_active &  ((UINT32)1 << module_index )) {
+            switch( module_index)
+                {
+                case BTA_SYS_HW_BLUETOOTH:
+                   /* Send BTA_SYS_HW_ERROR_EVT to DM */
+                   if (bta_sys_cb.sys_hw_cback[module_index] != NULL)
+                       bta_sys_cb.sys_hw_cback[module_index] (BTA_SYS_HW_ERROR_EVT);
+                    break;
+                default:
+                    /* not yet supported */
+                    break;
+                }
+        }
+    }
+}
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_enable
+**
+** Description     this function is called after API enable and HW has been turned on
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+
+void bta_sys_hw_api_enable( tBTA_SYS_HW_MSG *p_sys_hw_msg )
+{
+    if ((!bta_sys_cb.sys_hw_module_active) && (bta_sys_cb.state != BTA_SYS_HW_ON))
+    {
+        /* register which HW module was turned on */
+        bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+        /* use call-out to power-up HW */
+        bta_sys_hw_co_enable(p_sys_hw_msg->hw_module);
+    }
+    else
+    {
+        /* register which HW module was turned on */
+        bta_sys_cb.sys_hw_module_active |=  ((UINT32)1 << p_sys_hw_msg->hw_module );
+
+        /* HW already in use, so directly notify the caller */
+        if (bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+            bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_ON_EVT   );
+    }
+
+    APPL_TRACE_EVENT2 ("bta_sys_hw_api_enable for %d, active modules 0x%04X",
+                    p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active);
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_disable
+**
+** Description     if no other module is using the HW, this function will call ( if defined ) a user-macro to turn off the HW
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_api_disable(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    APPL_TRACE_DEBUG2("bta_sys_hw_api_disable for %d, active modules: 0x%04X",
+        p_sys_hw_msg->hw_module, bta_sys_cb.sys_hw_module_active );
+
+    /* make sure the related SW blocks were stopped */
+    bta_sys_disable( p_sys_hw_msg->hw_module );
+
+
+    /* register which module we turn off */
+    bta_sys_cb.sys_hw_module_active &=  ~((UINT32)1 << p_sys_hw_msg->hw_module );
+
+
+    /* if there are still some SW modules using the HW, just provide an answer to the calling */
+    if( bta_sys_cb.sys_hw_module_active != 0  )
+    {
+        /*  if there are still some SW modules using the HW,  directly notify the caller */
+        if( bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ]!= NULL )
+            bta_sys_cb.sys_hw_cback[p_sys_hw_msg->hw_module ](  BTA_SYS_HW_OFF_EVT   );
+    }
+    else
+    {
+        /* manually update the state of our system */
+        bta_sys_cb.state = BTA_SYS_HW_STOPPING;
+        /* and use the call-out to disable HW */
+        bta_sys_hw_co_disable(p_sys_hw_msg->hw_module);
+    }
+
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_enabled
+**
+** Description
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    APPL_TRACE_EVENT1("bta_sys_hw_evt_enabled for %i", p_sys_hw_msg->hw_module);
+
+#if ( defined BTM_AUTOMATIC_HCI_RESET && BTM_AUTOMATIC_HCI_RESET == TRUE )
+    /* If device is already up, send a fake "BTM DEVICE UP" using BTA SYS state machine */
+    /* If we are in the middle device initialization, BTM_DEVICE_UP will be issued      */
+    /* by BTM once initialization is done.                                              */
+    if (BTA_DmIsDeviceUp())
+    {
+        bta_sys_hw_btm_cback (BTM_DEV_STATUS_UP);
+    }
+#else
+
+    /* if HCI reset was not sent during stack start-up */
+    BTM_DeviceReset( NULL );
+
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_disabled
+**
+** Description
+**
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_disabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    UINT8 hw_module_index;
+
+    APPL_TRACE_DEBUG1("bta_sys_hw_evt_disabled - module 0x%X", p_sys_hw_msg->hw_module);
+
+    for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++)
+    {
+        if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+            bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_OFF_EVT);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_hw_event_stack_enabled
+**
+** Description     we receive this event from once the SW side is ready ( stack, FW download,... ),
+**                       i.e. we can really start using the device. So notify the app.
+**
+** Returns          success or failure
+**
+*******************************************************************************/
+void bta_sys_hw_evt_stack_enabled(tBTA_SYS_HW_MSG *p_sys_hw_msg)
+{
+    UINT8 hw_module_index;
+
+    APPL_TRACE_DEBUG0(" bta_sys_hw_evt_stack_enabled!notify the callers");
+
+    for (hw_module_index = 0; hw_module_index < BTA_SYS_MAX_HW_MODULES; hw_module_index++ )
+    {
+        if (bta_sys_cb.sys_hw_cback[hw_module_index] != NULL)
+            bta_sys_cb.sys_hw_cback[hw_module_index] (BTA_SYS_HW_ON_EVT);
+    }
+}
+
+
+
+
+/*******************************************************************************
+**
+** Function         bta_sys_event
+**
+** Description      BTA event handler; called from task event handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_event(BT_HDR *p_msg)
+{
+    UINT8       id;
+    BOOLEAN     freebuf = TRUE;
+
+    APPL_TRACE_EVENT1("BTA got event 0x%x", p_msg->event);
+
+    /* get subsystem id from event */
+    id = (UINT8) (p_msg->event >> 8);
+
+    /* verify id and call subsystem event handler */
+    if ((id < BTA_ID_MAX) && (bta_sys_cb.reg[id] != NULL))
+    {
+        freebuf = (*bta_sys_cb.reg[id]->evt_hdlr)(p_msg);
+    }
+    else
+    {
+        APPL_TRACE_WARNING1("BTA got unregistered event id %d", id);
+    }
+
+    if (freebuf)
+    {
+        GKI_freebuf(p_msg);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_timer_update
+**
+** Description      Update the BTA timer list and handle expired timers.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API void bta_sys_timer_update(void)
+{
+    if (!bta_sys_cb.timers_disabled)
+    {
+        ptim_timer_update(&bta_sys_cb.ptim_cb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_register
+**
+** Description      Called by other BTA subsystems to register their event
+**                  handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_register(UINT8 id, const tBTA_SYS_REG *p_reg)
+{
+    bta_sys_cb.reg[id] = (tBTA_SYS_REG *) p_reg;
+    bta_sys_cb.is_reg[id] = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_deregister
+**
+** Description      Called by other BTA subsystems to de-register
+**                  handler.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_deregister(UINT8 id)
+{
+    bta_sys_cb.is_reg[id] = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_is_register
+**
+** Description      Called by other BTA subsystems to get registeration
+**                  status.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN bta_sys_is_register(UINT8 id)
+{
+    return bta_sys_cb.is_reg[id];
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_sendmsg
+**
+** Description      Send a GKI message to BTA.  This function is designed to
+**                  optimize sending of messages to BTA.  It is called by BTA
+**                  API functions and call-in functions.
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_sendmsg(void *p_msg)
+{
+    GKI_send_msg(bta_sys_cb.task_id, p_bta_sys_cfg->mbox, p_msg);
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_start_timer
+**
+** Description      Start a protocol timer for the specified amount
+**                  of time in milliseconds.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
+{
+    ptim_start_timer(&bta_sys_cb.ptim_cb, p_tle, type, timeout);
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_stop_timer
+**
+** Description      Stop a BTA timer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle)
+{
+    ptim_stop_timer(&bta_sys_cb.ptim_cb, p_tle);
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_disable
+**
+** Description      For each registered subsystem execute its disable function.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_disable(tBTA_SYS_HW_MODULE module)
+{
+    int bta_id = 0;
+    int bta_id_max = 0;
+
+    APPL_TRACE_DEBUG1("bta_sys_disable: module %i", module);
+
+    switch( module )
+    {
+        case BTA_SYS_HW_BLUETOOTH:
+            bta_id = BTA_ID_DM;
+            bta_id_max = BTA_ID_BLUETOOTH_MAX;
+            break;
+        case BTA_SYS_HW_FMRX:
+            bta_id = BTA_ID_FM;
+            bta_id_max = BTA_ID_FM;
+            break;
+        case BTA_SYS_HW_FMTX:
+            bta_id = BTA_ID_FMTX;
+            bta_id_max = BTA_ID_FMTX;
+            break;
+        case BTA_SYS_HW_GPS:
+            bta_id = BTA_ID_GPS;
+            bta_id_max = BTA_ID_GPS;
+            break;
+        default:
+            APPL_TRACE_WARNING0("bta_sys_disable: unkown module");
+            return;
+    }
+
+    for ( ; bta_id <= bta_id_max; bta_id++)
+    {
+        if (bta_sys_cb.reg[bta_id] != NULL)
+        {
+            if (bta_sys_cb.is_reg[bta_id] == TRUE  &&  bta_sys_cb.reg[bta_id]->disable != NULL)
+            {
+                (*bta_sys_cb.reg[bta_id]->disable)();
+            }
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_disable_timers
+**
+** Description      Disable sys timer event handling
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_disable_timers(void)
+{
+    bta_sys_cb.timers_disabled = TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_set_trace_level
+**
+** Description      Set trace level for BTA
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_sys_set_trace_level(UINT8 level)
+{
+    appl_trace_level = level;
+}
+
+/*******************************************************************************
+**
+** Function         bta_sys_get_sys_features
+**
+** Description      Returns sys_features to other BTA modules.
+**
+** Returns          sys_features
+**
+*******************************************************************************/
+UINT16 bta_sys_get_sys_features (void)
+{
+    return bta_sys_cb.sys_features;
+}
+
+
diff --git a/bta/sys/ptim.c b/bta/sys/ptim.c
new file mode 100644
index 0000000..9dffc66
--- /dev/null
+++ b/bta/sys/ptim.c
@@ -0,0 +1,162 @@
+/******************************************************************************
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  Protocol timer services.
+ *
+ ******************************************************************************/
+
+#include "bt_target.h"
+#include "gki.h"
+#include "ptim.h"
+#include "bta_sys.h"
+
+/*******************************************************************************
+**
+** Function         ptim_init
+**
+** Description      Initialize a protocol timer control block.  Parameter
+**                  period is the GKI timer period in milliseconds.  Parameter
+**                  timer_id is the GKI timer id.
+**
+** Returns          void
+**
+*******************************************************************************/
+void ptim_init(tPTIM_CB *p_cb, UINT16 period, UINT8 timer_id)
+{
+    GKI_init_timer_list(&p_cb->timer_queue);
+    p_cb->period = period;
+    p_cb->timer_id = timer_id;
+}
+
+/*******************************************************************************
+**
+** Function         ptim_timer_update
+**
+** Description      Update the protocol timer list and handle expired timers.
+**                  This function is called from the task running the protocol
+**                  timers when the periodic GKI timer expires.
+**
+** Returns          void
+**
+*******************************************************************************/
+void ptim_timer_update(tPTIM_CB *p_cb)
+{
+    TIMER_LIST_ENT *p_tle;
+    BT_HDR *p_msg;
+    UINT32 new_ticks_count;
+    INT32  period_in_ticks;
+
+    /* To handle the case when the function is called less frequently than the period
+       we must convert determine the number of ticks since the last update, then
+       convert back to milliseconds before updating timer list */
+    new_ticks_count = GKI_get_tick_count();
+
+    /* Check for wrapped condition */
+    if (new_ticks_count >= p_cb->last_gki_ticks)
+    {
+        period_in_ticks = (INT32)(new_ticks_count - p_cb->last_gki_ticks);
+    }
+    else
+    {
+        period_in_ticks = (INT32)(((UINT32)0xffffffff - p_cb->last_gki_ticks)
+                            + new_ticks_count + 1);
+    }
+
+    /* update timer list */
+    GKI_update_timer_list(&p_cb->timer_queue, GKI_TICKS_TO_MS(period_in_ticks));
+
+    p_cb->last_gki_ticks = new_ticks_count;
+
+    /* while there are expired timers */
+    while((p_cb->timer_queue.p_first) && (p_cb->timer_queue.p_first->ticks <= 0))
+    {
+        /* removed expired timer from list */
+        p_tle = p_cb->timer_queue.p_first;
+        GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
+
+        /* call timer callback */
+        if(p_tle->p_cback)
+        {
+            (*p_tle->p_cback)(p_tle);
+        }
+        else if(p_tle->event)
+        {
+            if ((p_msg = (BT_HDR *) GKI_getbuf(sizeof(BT_HDR))) != NULL)
+            {
+                p_msg->event = p_tle->event;
+                p_msg->layer_specific = 0;
+                bta_sys_sendmsg(p_msg);
+            }
+        }
+    }
+
+    /* if timer list is empty stop periodic GKI timer */
+    if (p_cb->timer_queue.p_first == NULL)
+    {
+        GKI_stop_timer(p_cb->timer_id);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         ptim_start_timer
+**
+** Description      Start a protocol timer for the specified amount
+**                  of time in seconds.
+**
+** Returns          void
+**
+*******************************************************************************/
+void ptim_start_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout)
+{
+    /* if timer list is currently empty, start periodic GKI timer */
+    if (p_cb->timer_queue.p_first == NULL)
+    {
+        p_cb->last_gki_ticks = GKI_get_tick_count();
+        GKI_start_timer(p_cb->timer_id, GKI_MS_TO_TICKS(p_cb->period), TRUE);
+    }
+
+    GKI_remove_from_timer_list(&p_cb->timer_queue, p_tle);
+
+    p_tle->event = type;
+    p_tle->ticks = timeout;
+
+    GKI_add_to_timer_list(&p_cb->timer_queue, p_tle);
+}
+
+/*******************************************************************************
+**
+** Function         ptim_stop_timer
+**
+** Description      Stop a protocol timer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void ptim_stop_timer(tPTIM_CB *p_cb, TIMER_LIST_ENT *p_tle)
+{
+    GKI_remove_from_timer_list (&p_cb->timer_queue, p_tle);
+
+    /* if timer list is empty stop periodic GKI timer */
+    if (p_cb->timer_queue.p_first == NULL)
+    {
+        GKI_stop_timer(p_cb->timer_id);
+    }
+}
diff --git a/bta/sys/utl.c b/bta/sys/utl.c
new file mode 100644
index 0000000..4bb1d95
--- /dev/null
+++ b/bta/sys/utl.c
@@ -0,0 +1,296 @@
+/******************************************************************************
+ *
+ *  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 utility functions.
+ *
+ ******************************************************************************/
+#include "utl.h"
+#include "gki.h"
+#include "btm_api.h"
+
+/*******************************************************************************
+**
+** Function         utl_str2int
+**
+** Description      This utility function converts a character string to an
+**                  integer.  Acceptable values in string are 0-9.  If invalid
+**                  string or string value too large, -1 is returned.  Leading
+**                  spaces are skipped.
+**
+**
+** Returns          Integer value or -1 on error.
+**
+*******************************************************************************/
+INT16 utl_str2int(const char *p_s)
+{
+    INT32   val = 0;
+
+    for (;*p_s == ' ' && *p_s != 0; p_s++);
+
+    if (*p_s == 0) return -1;
+
+    for (;;)
+    {
+        if ((*p_s < '0') || (*p_s > '9')) return -1;
+
+        val += (INT32) (*p_s++ - '0');
+
+        if (val > 32767) return -1;
+
+        if (*p_s == 0)
+        {
+            return (INT16) val;
+        }
+        else
+        {
+            val *= 10;
+        }
+    }
+}
+
+/*******************************************************************************
+**
+** Function         utl_strucmp
+**
+** Description      This utility function compares two strings in uppercase.
+**                  String p_s must be uppercase.  String p_t is converted to
+**                  uppercase if lowercase.  If p_s ends first, the substring
+**                  match is counted as a match.
+**
+**
+** Returns          0 if strings match, nonzero otherwise.
+**
+*******************************************************************************/
+int utl_strucmp(const char *p_s, const char *p_t)
+{
+    char c;
+
+    while (*p_s && *p_t)
+    {
+        c = *p_t++;
+        if (c >= 'a' && c <= 'z')
+        {
+            c -= 0x20;
+        }
+        if (*p_s++ != c)
+        {
+            return -1;
+        }
+    }
+    /* if p_t hit null first, no match */
+    if (*p_t == 0 && *p_s != 0)
+    {
+        return 1;
+    }
+    /* else p_s hit null first, count as match */
+    else
+    {
+        return 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         utl_itoa
+**
+** Description      This utility function converts a UINT16 to a string.  The
+**                  string is NULL-terminated.  The length of the string is
+**                  returned;
+**
+**
+** Returns          Length of string.
+**
+*******************************************************************************/
+UINT8 utl_itoa(UINT16 i, char *p_s)
+{
+    UINT16  j, k;
+    char    *p = p_s;
+    BOOLEAN fill = FALSE;
+
+    if (i == 0)
+    {
+        /* take care of zero case */
+        *p++ = '0';
+    }
+    else
+    {
+        for(j = 10000; j > 0; j /= 10)
+        {
+            k = i / j;
+            i %= j;
+            if (k > 0 || fill)
+            {
+              *p++ = k + '0';
+              fill = TRUE;
+            }
+        }
+    }
+    *p = 0;
+    return (UINT8) (p - p_s);
+}
+
+/*******************************************************************************
+**
+** Function         utl_freebuf
+**
+** Description      This function calls GKI_freebuf to free the buffer passed
+**                  in, if buffer pointer is not NULL, and also initializes
+**                  buffer pointer to NULL.
+**
+**
+** Returns          Nothing.
+**
+*******************************************************************************/
+void utl_freebuf(void **p)
+{
+    if (*p != NULL)
+    {
+        GKI_freebuf(*p);
+        *p = NULL;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         utl_set_device_class
+**
+** Description      This function updates the local Device Class.
+**
+** Parameters:
+**                  p_cod   - Pointer to the device class to set to
+**
+**                  cmd     - the fields of the device class to update.
+**                            BTA_UTL_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+**                            BTA_UTL_SET_COD_SERVICE_CLASS - set the bits in the input
+**                            BTA_UTL_CLR_COD_SERVICE_CLASS - clear the bits in the input
+**                            BTA_UTL_SET_COD_ALL - overwrite major, minor, set the bits in service class
+**                            BTA_UTL_INIT_COD - overwrite major, minor, and service class
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_set_device_class(tBTA_UTL_COD *p_cod, UINT8 cmd)
+{
+    UINT8 *dev;
+    UINT16 service;
+    UINT8  minor, major;
+    DEV_CLASS dev_class;
+
+    dev = BTM_ReadDeviceClass();
+    BTM_COD_SERVICE_CLASS( service, dev );
+    BTM_COD_MINOR_CLASS(minor, dev );
+    BTM_COD_MAJOR_CLASS(major, dev );
+
+    switch(cmd)
+    {
+    case BTA_UTL_SET_COD_MAJOR_MINOR:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        break;
+
+    case BTA_UTL_SET_COD_SERVICE_CLASS:
+        /* clear out the bits that is not SERVICE_CLASS bits */
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service | p_cod->service;
+        break;
+
+    case BTA_UTL_CLR_COD_SERVICE_CLASS:
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service & (~p_cod->service);
+        break;
+
+    case BTA_UTL_SET_COD_ALL:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service | p_cod->service;
+        break;
+
+    case BTA_UTL_INIT_COD:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        service = p_cod->service & BTM_COD_SERVICE_CLASS_MASK;
+        break;
+
+    default:
+        return FALSE;
+    }
+
+    /* convert the fields into the device class type */
+    FIELDS_TO_COD(dev_class, minor, major, service);
+
+    if (BTM_SetDeviceClass(dev_class) == BTM_SUCCESS)
+        return TRUE;
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         utl_isintstr
+**
+** Description      This utility function checks if the given string is an
+**                  integer string or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isintstr(const char *p_s)
+{
+    UINT16 i = 0;
+
+    for(i=0; p_s[i] != 0; i++)
+    {
+        if(((p_s[i] < '0') || (p_s[i] > '9')) && (p_s[i] != ';'))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         utl_isdialstr
+**
+** Description      This utility function checks if the given string contains
+**                  only dial digits or not
+**
+**
+** Returns          TRUE if successful, Otherwise FALSE
+**
+*******************************************************************************/
+BOOLEAN utl_isdialstr(const char *p_s)
+{
+    UINT16 i = 0;
+
+    for(i=0; p_s[i] != 0; i++)
+    {
+        if(!(((p_s[i] >= '0') && (p_s[i] <= '9'))
+            || (p_s[i] == '*') || (p_s[i] == '+') || (p_s[i] == '#') || (p_s[i] == ';')
+            || ((p_s[i] >= 'A') && (p_s[i] <= 'C'))))
+            return FALSE;
+    }
+
+    return TRUE;
+}
+
+