Initial version of BLE support for Bluedroid

Change-Id: I9825a5cef9be2559c34c2a529b211b7d471147cf
diff --git a/bta/av/bta_av_aact.c b/bta/av/bta_av_aact.c
index 741a5a0..6a407e0 100644
--- a/bta/av/bta_av_aact.c
+++ b/bta/av/bta_av_aact.c
@@ -394,6 +394,16 @@
             /* copy config params to event message buffer */
             switch (event)
             {
+            case AVDT_RECONFIG_CFM_EVT:
+            APPL_TRACE_DEBUG4("reconfig cfm event codec info = 0x%06x-%06x-%06x-%02x",
+                (p_msg->msg.reconfig_cfm.p_cfg->codec_info[0]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[1]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[2],
+                (p_msg->msg.reconfig_cfm.p_cfg->codec_info[3]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[4]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[5],
+                (p_msg->msg.reconfig_cfm.p_cfg->codec_info[6]<<16)+(p_msg->msg.reconfig_cfm.p_cfg->codec_info[7]<<8)+p_msg->msg.reconfig_cfm.p_cfg->codec_info[8],
+                p_msg->msg.reconfig_cfm.p_cfg->codec_info[9]);
+            break;
+
+
+
             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
@@ -461,17 +471,16 @@
         if (event == AVDT_SUSPEND_CFM_EVT)
             p_msg->initiator = TRUE;
 
-        APPL_TRACE_EVENT1("hndl:x%x", p_scb->hndl);
+        APPL_TRACE_VERBOSE1("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
- */
+/* coverity[var_deref_model] */
+/* 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);
 }
 
@@ -486,7 +495,7 @@
 *******************************************************************************/
 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);
+    APPL_TRACE_VERBOSE2("bta_av_stream0_cback avdt_handle: %d event=0x%x", handle, event);
     bta_av_proc_stream_evt(handle, bd_addr, event, p_data, 0);
 }
 
@@ -1570,11 +1579,48 @@
 *******************************************************************************/
 void bta_av_open_failed (tBTA_AV_SCB *p_scb, tBTA_AV_DATA *p_data)
 {
+
+    BOOLEAN is_av_opened = FALSE;
+    tBTA_AV_SCB * p_opened_scb = NULL;
+    UINT8 idx;
+    tBTA_AV_OPEN    open;
+
+    APPL_TRACE_DEBUG0("bta_av_open_failed");
     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]);
+
+    /* check whether there is already an opened audio or video connection with the same device */
+    for (idx = 0; (idx < BTA_AV_NUM_STRS) && (is_av_opened == FALSE); idx++ )
+    {
+        p_opened_scb = bta_av_cb.p_scb[idx];
+        if (p_opened_scb && (p_opened_scb->state == BTA_AV_OPEN_SST) && (!bdcmp(p_opened_scb->peer_addr,p_scb->peer_addr )) )
+            is_av_opened = TRUE;
+
+    }
+
+    /* if there is already an active AV connnection with the same bd_addr,
+       don't send disconnect req, just report the open event with BTA_AV_FAIL_GET_CAP status */
+    if (is_av_opened == TRUE)
+    {
+        bdcpy(open.bd_addr, p_scb->peer_addr);
+        open.chnl   = p_scb->chnl;
+        open.hndl   = p_scb->hndl;
+        open.status = BTA_AV_FAIL_GET_CAP;
+        open.starting = bta_av_chk_start(p_scb);
+        open.edr    = 0;
+        /* set the state back to initial state */
+        bta_av_set_scb_sst_init(p_scb);
+
+        (*bta_av_cb.p_cback)(BTA_AV_OPEN_EVT, (tBTA_AV *) &open);
+
+    }
+    else
+    {
+        AVDT_DisconnectReq(p_scb->peer_addr, bta_av_dt_cback[p_scb->hdi]);
+    }
 }
 
+
 /*******************************************************************************
 **
 ** Function         bta_av_getcap_results
@@ -1798,7 +1844,8 @@
             AVDT_SuspendReq(&p_scb->avdt_handle, 1);
         }
 
-        if(sus_evt)
+        /* send SUSPEND_EVT event only if not in reconfiguring state and sus_evt is TRUE*/
+        if ((sus_evt)&&(p_scb->state != BTA_AV_RCFG_SST))
         {
             suspend_rsp.status = BTA_AV_SUCCESS;
             suspend_rsp.initiator = TRUE;
@@ -1811,7 +1858,11 @@
         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);
+        /* send STOP_EVT event only if not in reconfiguring state */
+        if (p_scb->state != BTA_AV_RCFG_SST)
+        {
+            (*bta_av_cb.p_cback)(BTA_AV_STOP_EVT, (tBTA_AV *) &suspend_rsp);
+        }
     }
 }
 
@@ -1916,6 +1967,7 @@
     UINT32  timestamp;
     BOOLEAN new_buf = FALSE;
     UINT8   m_pt = 0x60 | p_scb->codec_type;
+    tAVDT_DATA_OPT_MASK     opt;
 
     if (!p_scb->cong)
     {
@@ -1958,7 +2010,15 @@
                 /*
                 APPL_TRACE_ERROR1("qw: %d", p_scb->l2c_bufs);
                 */
-                AVDT_WriteReq(p_scb->avdt_handle, p_buf, timestamp, m_pt);
+
+                /* opt is a bit mask, it could have several options set */
+                opt = AVDT_DATA_OPT_NONE;
+                if (p_scb->no_rtp_hdr)
+                {
+                    opt |= AVDT_DATA_OPT_NO_RTP;
+                }
+
+                AVDT_WriteReqOpt(p_scb->avdt_handle, p_buf, timestamp, m_pt, opt);
                 p_scb->cong = TRUE;
             }
             else
@@ -2008,6 +2068,8 @@
     UINT16          flush_to;
     UINT8           new_role = p_scb->role;
     BT_HDR          hdr;
+    UINT8           policy = HCI_ENABLE_SNIFF_MODE;
+    UINT8           cur_role;
 
     APPL_TRACE_DEBUG2("bta_av_start_ok wait:x%x, role:x%x", p_scb->wait, p_scb->role);
 
@@ -2111,11 +2173,27 @@
     }
 
     {
+        /* If sink starts stream, disable sniff mode here */
+        if (!initiator)
+        {
+             /* If souce is the master role, disable role switch during streaming.
+             * Otherwise allow role switch, if source is slave.
+             * Because it would not hurt source, if the peer device wants source 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);
+        }
+
         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->no_rtp_hdr = FALSE;
+        p_scb->p_cos->start(p_scb->hndl, p_scb->codec_type, p_scb->cfg.codec_info, &p_scb->no_rtp_hdr);
         p_scb->co_started = TRUE;
 
         APPL_TRACE_DEBUG3("bta_av_start_ok suspending: %d, role:x%x, init %d",
@@ -2269,9 +2347,13 @@
         bta_av_cb.audio_open_cnt, err_code);
 
     suspend_rsp.status = BTA_AV_SUCCESS;
-    if(err_code)
+    if (err_code)
     {
-        p_scb->suspend_sup = FALSE;
+         /* Disable suspend feature only with explicit rejection(not with timeout) */
+        if (err_code != AVDT_ERR_TIMEOUT)
+        {
+            p_scb->suspend_sup = FALSE;
+        }
         suspend_rsp.status = BTA_AV_FAIL;
 
         APPL_TRACE_ERROR0 ("bta_av_suspend_cfm: suspend failed, closing connection");
@@ -2285,7 +2367,7 @@
         p_scb->started = FALSE;
     }
 
-    if(p_scb->role & BTA_AV_ROLE_SUSPEND)
+    if (p_scb->role & BTA_AV_ROLE_SUSPEND)
     {
         p_scb->role &= ~BTA_AV_ROLE_SUSPEND;
         p_scb->cong = FALSE;
@@ -2460,9 +2542,9 @@
 
     p_scb->started = FALSE;
     p_scb->cong    = FALSE;
-    if(err_code)
+    if (err_code)
     {
-        if(AVDT_ERR_CONNECT == err_code)
+        if (AVDT_ERR_CONNECT == err_code)
         {
             /* report failure */
             evt.status = BTA_AV_FAIL;
@@ -2472,8 +2554,11 @@
         else
         {
             APPL_TRACE_ERROR0("suspend rejected, try close");
-            p_scb->suspend_sup = FALSE;
-
+             /* Disable suspend feature only with explicit rejection(not with timeout) */
+            if (err_code != AVDT_ERR_TIMEOUT)
+            {
+                p_scb->suspend_sup = FALSE;
+            }
             /* drop the buffers queued in L2CAP */
             L2CA_FlushChannel (p_scb->l2c_cid, L2CAP_FLUSH_CHANS_ALL);
 
@@ -2507,10 +2592,14 @@
     /*
     APPL_TRACE_DEBUG0("bta_av_rcfg_cfm");
     */
-    if(err_code)
+    if (err_code)
     {
         APPL_TRACE_ERROR0("reconfig rejected, try close");
-        p_scb->recfg_sup = FALSE;
+         /* Disable reconfiguration feature only with explicit rejection(not with timeout) */
+        if (err_code != AVDT_ERR_TIMEOUT)
+        {
+            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);
@@ -2518,6 +2607,8 @@
     }
     else
     {
+        /* update the codec info after rcfg cfm */
+        memcpy(p_scb->cfg.codec_info,p_data->str_msg.msg.reconfig_cfm.p_cfg->codec_info,AVDT_CODEC_SIZE);
         /* take the SSM back to OPEN state */
         bta_av_ssm_execute(p_scb, BTA_AV_STR_OPEN_OK_EVT, NULL);
     }
diff --git a/bta/av/bta_av_act.c b/bta/av/bta_av_act.c
index a47921a..edf8b7f 100644
--- a/bta/av/bta_av_act.c
+++ b/bta/av/bta_av_act.c
@@ -363,7 +363,7 @@
 ** 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)
+static tBTA_AV_CODE bta_av_group_navi_supported(UINT8 len, UINT8 *p_data, BOOLEAN is_inquiry)
 {
     tBTA_AV_CODE ret=BTA_AV_RSP_NOT_IMPL;
     UINT8 *p_ptr = p_data;
@@ -377,10 +377,18 @@
 
         if (u32 == AVRC_CO_METADATA)
         {
-            if (u16 <= AVRC_PDU_PREV_GROUP)
-                ret = BTA_AV_RSP_ACCEPT;
+            if (is_inquiry)
+            {
+                if (u16 <= AVRC_PDU_PREV_GROUP)
+                    ret = BTA_AV_RSP_IMPL_STBL;
+            }
             else
-                ret = BTA_AV_RSP_REJ;
+            {
+                if (u16 <= AVRC_PDU_PREV_GROUP)
+                    ret = BTA_AV_RSP_ACCEPT;
+                else
+                    ret = BTA_AV_RSP_REJ;
+            }
         }
     }
 
@@ -396,23 +404,34 @@
 ** 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)
+static tBTA_AV_CODE bta_av_op_supported(tBTA_AV_RC rc_id, BOOLEAN is_inquiry)
 {
     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)))
+        if (is_inquiry)
         {
-            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)))
+            if (p_bta_av_rc_id[rc_id >> 4] & (1 << (rc_id & 0x0F)))
             {
-                ret_code = BTA_AV_RSP_INTERIM;
+                ret_code = BTA_AV_RSP_IMPL_STBL;
             }
         }
+        else
+        {
+            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;
 }
@@ -824,11 +843,15 @@
     tBTA_AV     av;
     BT_HDR      *p_pkt = NULL;
     tAVRC_MSG_VENDOR    *p_vendor = &p_data->rc_msg.msg.vendor;
+    BOOLEAN is_inquiry = ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) || p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ);
 
     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)
+        if ((p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_CTRL) ||
+            (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_SPEC_INQ) ||
+            (p_data->rc_msg.msg.hdr.ctype == AVRC_CMD_GEN_INQ)
+            )
         {
         /* check if operation is supported */
             if (p_data->rc_msg.msg.pass.op_id == AVRC_ID_VENDOR)
@@ -837,9 +860,11 @@
             }
             else
             {
-                p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id);
+                p_data->rc_msg.msg.hdr.ctype = bta_av_op_supported(p_data->rc_msg.msg.pass.op_id, is_inquiry);
             }
 
+            APPL_TRACE_DEBUG1("ctype %d",p_data->rc_msg.msg.hdr.ctype)
+
             /* 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);
@@ -1335,17 +1360,10 @@
             {
                 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;
-                    }
 
+                /* look for a p_lcb with its p_scb registered */
+                if((!(mask & p_cb->conn_lcb)) && (p_cb->p_scb[xx] != NULL))
+                {
                     p_lcb = &p_cb->lcb[xx];
                     p_lcb->lidx = xx + 1;
                     bdcpy(p_lcb->addr, p_data->str_msg.bd_addr);
@@ -1382,6 +1400,16 @@
                     break;
                 }
             }
+
+            /* check if we found something */
+            if (xx == BTA_AV_NUM_LINKS)
+            {
+                /* 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;
+            }
         }
     }
 #if( defined BTA_AR_INCLUDED ) && (BTA_AR_INCLUDED == TRUE)
@@ -1516,9 +1544,10 @@
 **
 ** Function         bta_av_check_peer_features
 **
-** Description      checks
+** Description      check supported features on the peer device from the SDP record
+**                  and return the feature mask
 **
-** Returns          void
+** Returns          tBTA_AV_FEAT peer device feature mask
 **
 *******************************************************************************/
 tBTA_AV_FEAT bta_av_check_peer_features (UINT16 service_uuid)
@@ -1624,13 +1653,9 @@
     }
 
     APPL_TRACE_DEBUG1("rc_handle %d", rc_handle);
+    /* check peer version and whether support CT and TG role */
     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);
-    }
+    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);
diff --git a/bta/av/bta_av_cfg.c b/bta/av/bta_av_cfg.c
index 793c772..f589a88 100644
--- a/bta/av/bta_av_cfg.c
+++ b/bta/av/bta_av_cfg.c
@@ -78,39 +78,6 @@
 #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 */
diff --git a/bta/av/bta_av_int.h b/bta/av/bta_av_int.h
index 9ce7b2a..cd22bcb 100644
--- a/bta/av/bta_av_int.h
+++ b/bta/av/bta_av_int.h
@@ -170,7 +170,7 @@
                                  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_START) (tBTA_AV_HNDL hndl, tBTA_AV_CODEC codec_type,UINT8 *p_codec_info, BOOLEAN *p_no_rtp_hdr);
 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);
@@ -504,6 +504,7 @@
     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 */
+    BOOLEAN             no_rtp_hdr;     /* TRUE if add no RTP header*/
 } tBTA_AV_SCB;
 
 #define BTA_AV_RC_ROLE_MASK     0x10
diff --git a/bta/av/bta_av_main.c b/bta/av/bta_av_main.c
index 085362d..749756d 100644
--- a/bta/av/bta_av_main.c
+++ b/bta/av/bta_av_main.c
@@ -1191,9 +1191,9 @@
     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));
+        APPL_TRACE_VERBOSE2("AV nsm event=0x%x(%s)", event, bta_av_evt_code(event));
 #else
-        APPL_TRACE_EVENT1("AV nsm event=0x%x", event);
+        APPL_TRACE_VERBOSE1("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);
@@ -1201,16 +1201,16 @@
     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));
+        APPL_TRACE_VERBOSE2("AV sm event=0x%x(%s)", event, bta_av_evt_code(event));
 #else
-        APPL_TRACE_EVENT1("AV sm event=0x%x", event);
+        APPL_TRACE_VERBOSE1("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);
+        APPL_TRACE_VERBOSE1("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);
diff --git a/bta/av/bta_av_ssm.c b/bta/av/bta_av_ssm.c
index a35a4b0..407146e 100644
--- a/bta/av/bta_av_ssm.c
+++ b/bta/av/bta_av_ssm.c
@@ -436,10 +436,10 @@
     }
 
 #if (defined(BTA_AV_DEBUG) && BTA_AV_DEBUG == TRUE)
-    APPL_TRACE_EVENT5("AV Sevent(0x%x)=0x%x(%s) state=%d(%s)",
+    APPL_TRACE_VERBOSE5("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);
+    APPL_TRACE_VERBOSE2("AV Sevent=0x%x state=%d", event, p_scb->state);
 #endif
 
     /* look up the state table for the current state */
diff --git a/bta/dm/bta_dm_act.c b/bta/dm/bta_dm_act.c
index 29b4ec2..0ade1cc 100644
--- a/bta/dm/bta_dm_act.c
+++ b/bta/dm/bta_dm_act.c
@@ -92,7 +92,10 @@
 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);
 
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr);
 
+
+static void bta_dm_disable_search_and_disc(void);
 #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);
@@ -103,8 +106,13 @@
 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
+static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir);
+static void bta_dm_observe_cmpl_cb (void * p_result);
 
+#ifndef BTA_DM_BLE_ADV_CHNL_MAP
+#define BTA_DM_BLE_ADV_CHNL_MAP (BTM_BLE_ADV_CHNL_37|BTM_BLE_ADV_CHNL_38|BTM_BLE_ADV_CHNL_39)
+#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] =
@@ -454,10 +462,9 @@
     BTM_SetConnectability(BTM_NON_CONNECTABLE, 0, 0);
 
     bta_dm_disable_pm();
-
+    bta_dm_disable_search_and_disc();
     bta_dm_cb.disabling = TRUE;
 
-    bta_dm_search_cancel(NULL);
 
     if(BTM_GetNumAclLinks()==0)
     {
@@ -750,6 +757,58 @@
 
 /*******************************************************************************
 **
+** Function         bta_dm_close_acl
+**
+** Description      This function forces to close the connection to a remote device
+**                  and optionaly remove the device from security database if
+**                  required.
+****
+*******************************************************************************/
+void bta_dm_close_acl(tBTA_DM_MSG *p_data)
+{
+    tBTA_DM_API_REMOVE_ACL *p_remove_acl = &p_data->remove_acl;
+    UINT8   index;
+
+    APPL_TRACE_DEBUG0("bta_dm_close_acl");
+
+    if (BTM_IsAclConnectionUp(p_remove_acl->bd_addr))
+    {
+        for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+        {
+            if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, p_remove_acl->bd_addr))
+                break;
+        }
+        if (index != bta_dm_cb.device_list.count)
+        {
+            if (p_remove_acl->remove_dev)
+                bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("unknown device, remove ACL failed");
+        }
+        /* Disconnect the ACL link */
+        btm_remove_acl(p_remove_acl->bd_addr);
+    }
+    /* if to remove the device from security database ? do it now */
+    else if (p_remove_acl->remove_dev)
+    {
+        if (!BTM_SecDeleteDevice(p_remove_acl->bd_addr))
+        {
+            APPL_TRACE_ERROR0("delete device from security database failed.");
+        }
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+        /* need to remove all pending background connection if any */
+        BTA_GATTC_CancelOpen(0, p_remove_acl->bd_addr, FALSE);
+        /* remove all cached GATT information */
+        BTA_GATTC_Refresh(p_remove_acl->bd_addr);
+#endif
+    }
+    /* otherwise, no action needed */
+
+}
+/*******************************************************************************
+**
 ** Function         bta_dm_bond
 **
 ** Description      Bonds with peer device
@@ -784,8 +843,14 @@
 */
         sec_event.auth_cmpl.fail_reason = HCI_ERR_ILLEGAL_COMMAND;
         if (status == BTM_SUCCESS)
+        {
             sec_event.auth_cmpl.success = TRUE;
-
+        }
+        else
+        {
+            /* delete this device entry from Sec Dev DB */
+            bta_dm_remove_sec_dev_entry(p_data->bond.bd_addr);
+        }
         bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
     }
 
@@ -1148,11 +1213,6 @@
 //        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,
@@ -1200,7 +1260,7 @@
     {
         BTM_CancelRemoteDeviceName();
     }
-#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+#if BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE
     if (bta_dm_search_cb.gatt_disc_active)
     {
         bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
@@ -1311,6 +1371,65 @@
 
 /*******************************************************************************
 **
+** Function         bta_dm_disable_search_and_disc
+**
+** Description      Cancels an ongoing search or discovery for devices in case of
+**                  a Bluetooth disable
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_disable_search_and_disc (void)
+{
+    tBTA_DM_DI_DISC_CMPL    di_disc;
+    tBTA_DM_MSG * p_msg;
+
+    if(BTM_IsInquiryActive()||(bta_dm_search_cb.state != BTA_DM_SEARCH_IDLE))
+    {
+        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 ((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);
+        }
+    }
+    else if(bta_dm_di_cb.p_di_db != NULL)
+    {
+        memset(&di_disc, 0, sizeof(tBTA_DM_DI_DISC_CMPL));
+        bdcpy(di_disc.bd_addr, bta_dm_search_cb.peer_bdaddr);
+        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, NULL);
+    }
+
+#if (BLE_INCLUDED == TRUE) && (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_di_disc
 **
 ** Description      This function queries a remote device for DI information.
@@ -1561,7 +1680,8 @@
                         {
                             /* 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));
+                            BCM_STRNCPY_S((char*)result.disc_ble_res.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+                            result.disc_ble_res.bd_name[BD_NAME_LEN] = 0;
                             result.disc_ble_res.service.len = service_uuid.len;
                             result.disc_ble_res.service.uu.uuid16 = service_uuid.uu.uuid16;
 
@@ -2022,7 +2142,7 @@
     {
         BTM_CancelRemoteDeviceName();
     }
-#if ((BLE_INCLUDED == TRUE) && (defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
+#if (BLE_INCLUDED == TRUE) && (BTA_GATT_INCLUDED == TRUE)
     if (bta_dm_search_cb.gatt_disc_active)
     {
         bta_dm_cancel_gatt_discovery(bta_dm_search_cb.peer_bdaddr);
@@ -2535,22 +2655,25 @@
 {
     tBTA_DM_REM_NAME * p_msg;
 
-    APPL_TRACE_DEBUG1("bta_dm_remname_cback name=<%s>", p_remote_name->remote_bd_name);
+    APPL_TRACE_DEBUG2("bta_dm_remname_cback len = %d name=<%s>", p_remote_name->length,
+                      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;
+    BCM_STRNCPY_S((char*)bta_dm_search_cb.peer_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
+    bta_dm_search_cb.peer_name[BD_NAME_LEN]=0;
 
     BTM_SecDeleteRmtNameNotifyCallback(&bta_dm_service_search_remname_cback);
-
+#if BLE_INCLUDED == TRUE
+    GAP_BleReadPeerPrefConnParams (bta_dm_search_cb.peer_bdaddr);
+#endif
     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));
+        BCM_STRNCPY_S((char*)p_msg->result.disc_res.bd_name, sizeof(BD_NAME), (char*)p_remote_name->remote_bd_name, (BD_NAME_LEN));
 
         /* make sure the string is null terminated */
-        p_msg->result.disc_res.bd_name[BD_NAME_LEN-1] = 0;
+        p_msg->result.disc_res.bd_name[BD_NAME_LEN] = 0;
 
         p_msg->hdr.event = BTA_DM_REMT_NAME_EVT;
         bta_sys_sendmsg(p_msg);
@@ -2825,6 +2948,8 @@
         {
             bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
         }
+        /* delete this device entry from Sec Dev DB */
+        bta_dm_remove_sec_dev_entry(bd_addr);
     }
 
     return BTM_SUCCESS;
@@ -3074,6 +3199,7 @@
             break;
         case BTM_BL_UPDATE_EVT:
             p_msg->busy_level = p_data->update.busy_level;
+            p_msg->busy_level_flags = p_data->update.busy_level_flags;
             break;
         case BTM_BL_ROLE_CHG_EVT:
             p_msg->new_role = p_data->role_chg.new_role;
@@ -3219,6 +3345,7 @@
         if( bta_dm_cb.p_sec_cback )
         {
             conn.busy_level.level = p_data->acl_change.busy_level;
+            conn.busy_level.level_flags = p_data->acl_change.busy_level_flags;
             bta_dm_cb.p_sec_cback(BTA_DM_BUSY_LEVEL_EVT, &conn);
         }
         return;
@@ -3319,6 +3446,8 @@
                 issue_unpair_cb = TRUE;
             }
 
+            conn.link_down.is_removed = bta_dm_cb.device_list.peer_device[i].remove_dev_pending;
+
             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]));
@@ -3351,6 +3480,16 @@
                 bta_sys_start_timer(&bta_dm_cb.disable_timer, 0, 1000);
             }
         }
+        if (conn.link_down.is_removed)
+        {
+            BTM_SecDeleteDevice(p_bda);
+#if (BLE_INCLUDED == TRUE && BTA_GATT_INCLUDED == TRUE)
+            /* need to remove all pending background connection */
+            BTA_GATTC_CancelOpen(0, p_bda, FALSE);
+            /* remove all cached GATT information */
+            BTA_GATTC_Refresh(p_bda);
+#endif
+         }
 
         bdcpy(conn.link_down.bd_addr, p_bda);
         conn.link_down.status = (UINT8) btm_get_acl_disc_reason_code();
@@ -3379,6 +3518,9 @@
 {
     tBTA_SYS_HW_MSG *sys_enable_event;
 
+    /* disable the power managment module */
+    bta_dm_disable_pm();
+
     /* register our callback to SYS HW manager */
     bta_sys_hw_register( BTA_SYS_HW_BLUETOOTH, bta_dm_sys_hw_cback );
 
@@ -3573,6 +3715,44 @@
 
 /*******************************************************************************
 **
+** Function         bta_dm_remove_sec_dev_entry
+**
+** Description      Removes device entry from Security device DB if ACL connection with
+**                  remtoe device does not exist, else schedule for dev entry removal upon
+                     ACL close
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_remove_sec_dev_entry(BD_ADDR remote_bd_addr)
+{
+    UINT16 index = 0;
+    if (BTM_IsAclConnectionUp(remote_bd_addr))
+    {
+         APPL_TRACE_DEBUG1("%s ACL is not down. Schedule for  Dev Removal when ACL closes",
+                            __FUNCTION__);
+        for (index = 0; index < bta_dm_cb.device_list.count; index ++)
+        {
+            if (!bdcmp( bta_dm_cb.device_list.peer_device[index].peer_bdaddr, remote_bd_addr))
+                break;
+        }
+        if (index != bta_dm_cb.device_list.count)
+        {
+            bta_dm_cb.device_list.peer_device[index].remove_dev_pending = TRUE;
+        }
+        else
+        {
+            APPL_TRACE_ERROR1(" %s Device does not exist in DB", __FUNCTION__);
+        }
+    }
+    else
+    {
+        BTM_SecDeleteDevice (remote_bd_addr);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         bta_dm_adjust_roles
 **
 ** Description      Adjust roles
@@ -3668,7 +3848,7 @@
 *******************************************************************************/
 static char *bta_dm_get_remname(void)
 {
-    char *p_name = bta_dm_search_cb.peer_name;
+    char *p_name = (char *)bta_dm_search_cb.peer_name;
     char *p_temp;
 
     /* If the name isn't already stored, try retrieving from BTM */
@@ -4048,16 +4228,6 @@
         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 )
@@ -4078,6 +4248,16 @@
         p_length = NULL;
     }
 
+    /* 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( free_eir_length )
         UINT8_TO_STREAM(p, 0); /* terminator of significant part */
 
@@ -4352,6 +4532,74 @@
 }
 
 #if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         bta_dm_observe_results_cb
+**
+** Description      Callback for BLE Observe result
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_observe_results_cb (tBTM_INQ_RESULTS *p_inq, UINT8 *p_eir)
+{
+;
+    tBTA_DM_SEARCH     result;
+    tBTM_INQ_INFO      *p_inq_info;
+    UINT16             service_class;
+    APPL_TRACE_DEBUG0("bta_dm_observe_results_cb")
+
+    bdcpy(result.inq_res.bd_addr, p_inq->remote_bd_addr);
+    result.inq_res.rssi = p_inq->rssi;
+    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;
+
+    /* 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_scan_cback)
+        bta_dm_search_cb.p_scan_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_observe_cmpl_cb
+**
+** Description      Callback for BLE Observe complete
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+static void bta_dm_observe_cmpl_cb (void * p_result)
+{
+    tBTA_DM_SEARCH  data;
+
+    APPL_TRACE_DEBUG0("bta_dm_observe_cmpl_cb");
+
+    data.inq_cmpl.num_resps = ((tBTM_INQUIRY_CMPL *)p_result)->num_resp;
+    if (bta_dm_search_cb.p_scan_cback)
+    {
+        bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+    }
+}
+
 #if (SMP_INCLUDED == TRUE)
 /*******************************************************************************
 **
@@ -4367,6 +4615,9 @@
 {
     tBTM_STATUS status = BTM_SUCCESS;
     tBTA_DM_SEC sec_event;
+    UINT8 i;
+
+    APPL_TRACE_DEBUG0("bta_dm_ble_smp_cback");
 
     if (!bta_dm_cb.p_sec_cback)
         return BTM_NOT_AUTHORIZED;
@@ -4394,13 +4645,15 @@
 
         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));
+            BCM_STRNCPY_S((char*)sec_event.ble_req.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
             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));
+            BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
             sec_event.key_notif.passkey = p_data->key_notif;
             bta_dm_cb.p_sec_cback(BTA_DM_BLE_PASSKEY_NOTIF_EVT, &sec_event);
             break;
@@ -4418,17 +4671,41 @@
         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));
+
+            if (p_data->key.key_type == BTM_LE_KEY_PID)
+            {
+                for (i=0; i<BT_OCTET16_LEN; i++ )
+                {
+                    sec_event.ble_key.key_value.pid_key.irk[i] = p_data->key.p_key_value->pid_key.irk[i];
+                }
+                sec_event.ble_key.key_value.pid_key.addr_type = p_data->key.p_key_value->pid_key.addr_type;
+                memcpy( &(sec_event.ble_key.key_value.pid_key.static_addr),
+                        &(p_data->key.p_key_value->pid_key.static_addr),
+                        sizeof (BD_ADDR));
+            }
+            else
+            {
+                memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
+            }
+            // memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); todo will crash
             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;
+            BCM_STRNCPY_S((char*)sec_event.auth_cmpl.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
 
+            if (p_data->complt.reason != 0)
+            {
+                sec_event.auth_cmpl.fail_reason = BTA_DM_AUTH_CONVERT_SMP_CODE(((UINT8)p_data->complt.reason));
+                /* delete this device entry from Sec Dev DB */
+                bta_dm_remove_sec_dev_entry (bda);
+            }
+            else
+            {
+                sec_event.auth_cmpl.success = TRUE;
+            }
+            sec_event.auth_cmpl.privacy_enabled = p_data->complt.privacy_supported;
             if (bta_dm_cb.p_sec_cback)
             {
                 //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
@@ -4618,6 +4895,43 @@
                              p_data->ble_set_scan_params.scan_window);
 }
 
+
+/*******************************************************************************
+**
+** Function         bta_dm_ble_observe
+**
+** Description      This function set the preferred connection scan parameters.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_observe (tBTA_DM_MSG *p_data)
+{
+
+    tBTM_STATUS status;
+    if (p_data->ble_observe.start)
+    {
+        /*Save the  callback to be called when a scan results are available */
+        bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback;
+        if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration,
+                                bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb))!= BTM_SUCCESS)
+        {
+            tBTA_DM_SEARCH  data;
+            APPL_TRACE_WARNING2(" %s BTM_BleObserve  failed. status %d",__FUNCTION__,status);
+            data.inq_cmpl.num_resps = 0;
+            if (bta_dm_search_cb.p_scan_cback)
+            {
+                bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data);
+            }
+        }
+    }
+    else
+    {
+        bta_dm_search_cb.p_scan_cback = NULL;
+        BTM_BleObserve(FALSE, 0, NULL,NULL );
+    }
+}
+
 #if ((defined BTA_GATT_INCLUDED) &&  (BTA_GATT_INCLUDED == TRUE))
 
 /*******************************************************************************
@@ -4682,6 +4996,7 @@
         /* 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.bd_name[BD_NAME_LEN] = 0;
         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);
@@ -4719,6 +5034,8 @@
             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;
+            p_msg->disc_result.result.disc_res.num_uuids = 0;
+            p_msg->disc_result.result.disc_res.p_uuid_list = NULL;
             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));
@@ -4882,5 +5199,4 @@
 }
 
 #endif /* BTA_GATT_INCLUDED */
-
 #endif  /* BLE_INCLUDED */
diff --git a/bta/dm/bta_dm_api.c b/bta/dm/bta_dm_api.c
index 06e3b93..aedbe81 100644
--- a/bta/dm/bta_dm_api.c
+++ b/bta/dm/bta_dm_api.c
@@ -1572,6 +1572,42 @@
 #endif
 }
 
+/*******************************************************************************
+**
+** Function         BTA_DmBleEnableRemotePrivacy
+**
+** Description      Enable/disable privacy on a remote device
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privacy_enable)
+{
+#if BLE_INCLUDED == TRUE
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfigLocalPrivacy
+**
+** Description      Enable/disable privacy on the local device
+**
+** Parameters:      privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable)
+{
+#if BLE_INCLUDED == TRUE
+#endif
+}
+
 
 /*******************************************************************************
 **
@@ -1614,3 +1650,74 @@
     }
 }
 
+/*******************************************************************************
+**
+** Function         BTA_DmCloseACL
+**
+** Description      This function force to close an ACL connection and remove the
+**                  device from the security database list of known devices.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  remove_dev    - remove device or not after link down
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev)
+{
+    tBTA_DM_API_REMOVE_ACL   *p_msg;
+
+    APPL_TRACE_API0("BTA_DmCloseACL");
+
+    if ((p_msg = (tBTA_DM_API_REMOVE_ACL *) GKI_getbuf(sizeof(tBTA_DM_API_REMOVE_ACL))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_REMOVE_ACL));
+
+        p_msg->hdr.event = BTA_DM_API_REMOVE_ACL_EVT;
+
+        memcpy(p_msg->bd_addr, bd_addr, BD_ADDR_LEN);
+        p_msg->remove_dev      = remove_dev;
+
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleObserve
+**
+** Description      This procedure keep the device listening for advertising
+**                  events from a broadcast device.
+**
+** Parameters       start: start or stop observe.
+**
+** Returns          void
+
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+                                     tBTA_DM_SEARCH_CBACK *p_results_cb)
+{
+#if BLE_INCLUDED == TRUE
+
+    tBTA_DM_API_BLE_OBSERVE   *p_msg;
+
+    APPL_TRACE_API1("BTA_DmBleObserve:start = %d ", start);
+
+    if ((p_msg = (tBTA_DM_API_BLE_OBSERVE *) GKI_getbuf(sizeof(tBTA_DM_API_BLE_OBSERVE))) != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_BLE_OBSERVE));
+
+        p_msg->hdr.event = BTA_DM_API_BLE_OBSERVE_EVT;
+        p_msg->start = start;
+        p_msg->duration = duration;
+        p_msg->p_cback = p_results_cb;
+
+        bta_sys_sendmsg(p_msg);
+    }
+#endif
+}
+
+
diff --git a/bta/dm/bta_dm_cfg.c b/bta/dm/bta_dm_cfg.c
index 5e26909..a7c3cc4 100644
--- a/bta/dm/bta_dm_cfg.c
+++ b/bta/dm/bta_dm_cfg.c
@@ -240,14 +240,14 @@
   (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_SNIFF2, 30000},   {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_SNIFF2, 30000},   {BTA_DM_PM_NO_ACTION, 0}},    /* idle */
+      {{BTA_DM_PM_SNIFF2, 30000},   {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
       {{BTA_DM_PM_NO_ACTION, 0},   {BTA_DM_PM_NO_ACTION, 0}}     /* mode change retry */
   }
  },
@@ -358,7 +358,9 @@
 {
     /*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 */
+    {0,      0, 2},     /* BTA_DM_PM_SSR1 - HH, can NOT share entry with any other profile,
+                           seting default max latency and min remote timeout as 0,
+                           and always read individual device preference from HH module */
     {1200,   2, 2},     /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
     {360,  160, 2}      /* BTA_DM_PM_SSR3 - HD */
 };
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 35b369d..245c871 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -60,6 +60,7 @@
     BTA_DM_API_TX_INQPWR_EVT,
     BTA_DM_ACL_CHANGE_EVT,
     BTA_DM_API_ADD_DEVICE_EVT,
+    BTA_DM_API_REMOVE_ACL_EVT,
 
     /* security API events */
     BTA_DM_API_BOND_EVT,
@@ -77,6 +78,7 @@
 
     BTA_DM_API_SET_ENCRYPTION_EVT,
 
+
 #if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
     BTA_DM_API_PASKY_CANCEL_EVT,
 #endif
@@ -96,6 +98,7 @@
     BTA_DM_API_BLE_SET_BG_CONN_TYPE,
     BTA_DM_API_BLE_CONN_PARAM_EVT,
     BTA_DM_API_BLE_SCAN_PARAM_EVT,
+    BTA_DM_API_BLE_OBSERVE_EVT,
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -140,7 +143,7 @@
 typedef struct
 {
     BT_HDR              hdr;
-    char    name[BD_NAME_LEN];
+    BD_NAME             name; /* max 248 bytes name, plus must be Null terminated */
 } tBTA_DM_API_SET_NAME;
 
 /* data type for BTA_DM_API_SET_VISIBILITY_EVT */
@@ -353,6 +356,7 @@
     BT_HDR          hdr;
     tBTM_BL_EVENT   event;
     UINT8           busy_level;
+    UINT8           busy_level_flags;
     BOOLEAN         is_new;
     UINT8           new_role;
     BD_ADDR         bd_addr;
@@ -475,6 +479,20 @@
 
 }tBTA_DM_API_BLE_CONN_PARAMS;
 
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR                 peer_bda;
+    BOOLEAN                 privacy_enable;
+
+}tBTA_DM_API_ENABLE_PRIVACY;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 privacy_enable;
+}tBTA_DM_API_LOCAL_PRIVACY;
+
 /* set scan parameter for BLE connections */
 typedef struct
 {
@@ -483,7 +501,14 @@
     UINT16                  scan_window;
 }tBTA_DM_API_BLE_SCAN_PARAMS;
 
-#endif
+/* Data type for start/stop observe */
+typedef struct
+{
+    BT_HDR                  hdr;
+    BOOLEAN                 start;
+    UINT16                  duration;
+    tBTA_DM_SEARCH_CBACK * p_cback;
+}tBTA_DM_API_BLE_OBSERVE;
 
 typedef struct
 {
@@ -491,6 +516,25 @@
     BOOLEAN                 enable_or_disable;
 }tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT;
 
+
+/* set adv parameter for BLE advertising */
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  adv_int_min;
+    UINT16                  adv_int_max;
+    tBLE_BD_ADDR            *p_dir_bda;
+}tBTA_DM_API_BLE_ADV_PARAMS;
+
+typedef struct
+{
+    BT_HDR                  hdr;
+    UINT16                  data_mask;
+    tBTA_BLE_ADV_DATA       *p_adv_cfg;
+}tBTA_DM_API_SET_ADV_CONFIG;
+
+#endif
+
 #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
@@ -510,6 +554,14 @@
 }tBTA_DM_API_SET_EIR_CONFIG;
 #endif
 
+/* data type for BTA_DM_API_REMOVE_ACL_EVT */
+typedef struct
+{
+    BT_HDR      hdr;
+    BD_ADDR     bd_addr;
+    BOOLEAN     remove_dev;
+}tBTA_DM_API_REMOVE_ACL;
+
 /* union of all data types */
 typedef union
 {
@@ -580,6 +632,11 @@
     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;
+    tBTA_DM_API_BLE_OBSERVE             ble_observe;
+    tBTA_DM_API_ENABLE_PRIVACY          ble_remote_privacy;
+    tBTA_DM_API_LOCAL_PRIVACY           ble_local_privacy;
+    tBTA_DM_API_BLE_ADV_PARAMS          ble_set_adv_params;
+    tBTA_DM_API_SET_ADV_CONFIG          ble_set_adv_data;
 #endif
 
     tBTA_DM_API_SET_AFH_CHANNEL_ASSESSMENT set_afh_channel_assessment;
@@ -590,6 +647,7 @@
 #if (BTM_EIR_SERVER_INCLUDED == TRUE)
     tBTA_DM_API_SET_EIR_CONFIG          set_eir_cfg;
 #endif
+    tBTA_DM_API_REMOVE_ACL              remove_acl;
 
 } tBTA_DM_MSG;
 
@@ -623,6 +681,7 @@
 #endif
     tBTA_DM_PM_ACTTION          pm_mode_attempted;
     tBTA_DM_PM_ACTTION          pm_mode_failed;
+    BOOLEAN                     remove_dev_pending;
 
 } tBTA_DM_PEER_DEVICE;
 
@@ -738,7 +797,7 @@
     UINT16                 state;
     BD_ADDR                peer_bdaddr;
     BOOLEAN                name_discover_done;
-    char                   peer_name[BD_NAME_LEN];
+    BD_NAME                peer_name;
     TIMER_LIST_ENT         search_timer;
     UINT8                  service_index;
     tBTA_DM_MSG          * p_search_queue;   /* search or discover commands during search cancel stored here */
@@ -749,6 +808,7 @@
     BOOLEAN                sdp_search;
 
 #if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    tBTA_DM_SEARCH_CBACK * p_scan_cback;
 #if ((defined BTA_GATT_INCLUDED) && (BTA_GATT_INCLUDED == TRUE))
     tBTA_GATTC_IF          client_if;
     UINT8                  num_uuid;
@@ -917,6 +977,7 @@
 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_close_acl(tBTA_DM_MSG *p_data);
 
 
 extern void bta_dm_pm_btm_status(tBTA_DM_MSG *p_data);
@@ -931,6 +992,7 @@
 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);
+extern void bta_dm_ble_observe (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);
diff --git a/bta/dm/bta_dm_main.c b/bta/dm/bta_dm_main.c
index a2fec04..dc94c6c 100644
--- a/bta/dm/bta_dm_main.c
+++ b/bta/dm/bta_dm_main.c
@@ -58,6 +58,7 @@
     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 */
+    bta_dm_close_acl,         /* 10 BTA_DM_API_ADD_DEVICE_EVT */
 
     /* security API events */
     bta_dm_bond,              /* 10  BTA_DM_API_BOND_EVT */
@@ -94,6 +95,7 @@
     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 */
+    bta_dm_ble_observe,
 #endif
 
 #if ( BTM_EIR_SERVER_INCLUDED == TRUE )&&( BTA_EIR_CANNED_UUID_LIST != TRUE )&&(BTA_EIR_SERVER_NUM_CUSTOM_UUID > 0)
@@ -211,8 +213,8 @@
 /* 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},
+/* SEARCH_CMPL_EVT */       {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
+/* DISCV_RES_EVT */         {BTA_DM_SEARCH_CANCEL_TRANSAC_CMPL, BTA_DM_SEARCH_CANCEL_CMPL,     BTA_DM_SEARCH_IDLE},
 /* API_DI_DISCOVER_EVT */   {BTA_DM_SEARCH_IGNORE,              BTA_DM_SEARCH_IGNORE,          BTA_DM_SEARCH_CANCELLING}
 
 
diff --git a/bta/dm/bta_dm_pm.c b/bta/dm/bta_dm_pm.c
index 8a993de..cb5da6f 100644
--- a/bta/dm/bta_dm_pm.c
+++ b/bta/dm/bta_dm_pm.c
@@ -42,9 +42,14 @@
 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)
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+#include "../hh/bta_hh_int.h"
+/* BTA_DM_PM_SSR1 will be dedicated for HH SSR setting entry, no other profile can use it */
+#define BTA_DM_PM_SSR_HH      BTA_DM_PM_SSR1
+#endif
 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;
@@ -70,9 +75,6 @@
     {
         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);
     }
@@ -165,13 +167,16 @@
     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) &&
+    /* Disable/Enable sniff policy on the SCO link if sco Up/Down. Will be removed in 2.2*/
+    if ((p_dev) &&
         ((status == BTA_SYS_SCO_OPEN) || (status == BTA_SYS_SCO_CLOSE)) )
+    {
+        if ((btm_status == BTM_SUCCESS) &&
+            (vers.manufacturer ==  LMP_COMPID_BROADCOM) &&
+            (vers.hci_version < HCI_PROTO_VERSION_2_0))
         {
-        bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+            bta_dm_pm_set_sniff_policy(p_dev, (status == BTA_SYS_SCO_OPEN));
+        }
     }
 
     /* find if there is an power mode entry for the service */
@@ -272,7 +277,11 @@
     }
 
 #if (BTM_SSR_INCLUDED == TRUE)
-    if(p_bta_dm_ssr_spec[index].max_lat)
+    if(p_bta_dm_ssr_spec[index].max_lat
+#if (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+       || index == BTA_DM_PM_SSR_HH
+#endif
+       )
     {
         bta_dm_pm_ssr(peer_addr);
     }
@@ -559,7 +568,6 @@
     return TRUE;
 
 }
-
 /*******************************************************************************
 **
 ** Function         bta_dm_pm_ssr
@@ -599,6 +607,14 @@
             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 (defined BTA_HH_INCLUDED && BTA_HH_INCLUDED == TRUE)
+            /* HH has the per connection SSR preference, already read the SSR params from BTA HH */
+            if (p_bta_dm_pm_spec[p_bta_dm_pm_cfg[j].spec_idx].ssr == BTA_DM_PM_SSR_HH)
+            {
+                if (bta_hh_read_ssr_param(peer_addr, &p_spec_cur->max_lat, &p_spec_cur->min_rmt_to) == BTA_HH_ERR)
+                    continue;
+            }
+#endif
             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))
             {
@@ -617,44 +633,6 @@
             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
 /*******************************************************************************
 **
diff --git a/bta/gatt/bta_gattc_act.c b/bta/gatt/bta_gattc_act.c
index 5cacf03..25260f9 100644
--- a/bta/gatt/bta_gattc_act.c
+++ b/bta/gatt/bta_gattc_act.c
@@ -146,7 +146,6 @@
         (*p_data->api_reg.p_cback)(BTA_GATTC_REG_EVT,  (tBTA_GATTC *)&cb_data);
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_start_if
@@ -167,8 +166,6 @@
         APPL_TRACE_ERROR1("Unable to start app.: Unknown interface =%d",p_msg->int_start_if.client_if );
     }
 }
-
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_deregister_cmpl
@@ -225,7 +222,6 @@
     }
 
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_deregister
@@ -263,8 +259,6 @@
         APPL_TRACE_ERROR1("bta_gattc_int_deregister Deregister Failed, unknown client_if: %d", p_data->int_dereg.client_if);
     }
 }
-
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_deregister
@@ -364,7 +358,7 @@
     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;
+    tBTA_GATTC cb_data;
 
     if (p_msg->api_cancel_conn.is_direct)
     {
@@ -381,7 +375,8 @@
 
             if (p_clreg && p_clreg->p_cback)
             {
-                (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+                cb_data.status = BTA_GATT_ERROR;
+                (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
             }
         }
     }
@@ -391,7 +386,6 @@
 
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_cancel_open_error
@@ -403,10 +397,11 @@
 *******************************************************************************/
 void bta_gattc_cancel_open_error(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+    tBTA_GATTC cb_data;
+    cb_data.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);
+    if ( p_clcb && p_clcb->p_rcb && p_clcb->p_rcb->p_cback )
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
 }
 
 /*******************************************************************************
@@ -493,7 +488,7 @@
     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))
+    if (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, TRUE, FALSE))
     {
         /* alwaya call open to hold a connection */
         if (!GATT_Connect(p_data->client_if, p_data->remote_bda, FALSE))
@@ -540,14 +535,15 @@
 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;
+    tBTA_GATTC          cb_data;
+    cb_data.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 (bta_gattc_mark_bg_conn(p_data->client_if, p_data->remote_bda, FALSE, FALSE))
     {
         if (GATT_CancelConnect(p_data->client_if, p_data->remote_bda, FALSE))
         {
-            status = BTA_GATT_OK;
+            cb_data.status = BTA_GATT_OK;
         }
         else
         {
@@ -558,7 +554,7 @@
 
     if (p_clreg && p_clreg->p_cback)
     {
-        (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+        (*p_clreg->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
     }
 
 }
@@ -573,16 +569,16 @@
 *******************************************************************************/
 void bta_gattc_cancel_open_ok(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    tBTA_GATT_STATUS status = BTA_GATT_OK;
+    tBTA_GATTC          cb_data;
 
     if ( p_clcb->p_rcb->p_cback )
     {
-        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+        cb_data.status = BTA_GATT_OK;
+        (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
     }
 
     bta_gattc_clcb_dealloc(p_clcb);
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_cancel_open
@@ -594,7 +590,7 @@
 *******************************************************************************/
 void bta_gattc_cancel_open(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
 {
-    tBTA_GATT_STATUS status=BTA_GATT_ERROR;
+    tBTA_GATTC          cb_data;
 
     if (GATT_CancelConnect(p_clcb->p_rcb->client_if, p_data->api_cancel_conn.remote_bda, TRUE))
     {
@@ -604,7 +600,8 @@
     {
         if ( p_clcb->p_rcb->p_cback )
         {
-            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, (tBTA_GATTC *)&status);
+            cb_data.status = BTA_GATT_ERROR;
+            (*p_clcb->p_rcb->p_cback)(BTA_GATTC_CANCEL_OPEN_EVT, &cb_data);
         }
     }
 }
@@ -631,7 +628,8 @@
         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->p_srvc_cache == NULL ||
+            p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE)
         {
             if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
             {
@@ -662,7 +660,6 @@
         }
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_close_fail
@@ -717,26 +714,16 @@
 
     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)
+    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
@@ -746,7 +733,7 @@
 ** Returns          None.
 **
 *******************************************************************************/
-void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb)
+void bta_gattc_reset_discover_st(tBTA_GATTC_SERV *p_srcb, tBTA_GATT_STATUS status)
 {
     tBTA_GATTC_CB   *p_cb = &bta_gattc_cb;
     UINT8 i;
@@ -755,12 +742,29 @@
     {
         if (p_cb->clcb[i].p_srcb == p_srcb)
         {
+            p_cb->clcb[i].status = status;
             bta_gattc_sm_execute(&p_cb->clcb[i], BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
         }
     }
 }
 /*******************************************************************************
 **
+** Function         bta_gattc_disc_close
+**
+** Description      close a GATTC connection while in discovery state.
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_gattc_disc_close(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    APPL_TRACE_DEBUG1("Discovery cancel conn_id=%d",p_clcb->bta_conn_id);
+
+    bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_ERROR);
+    bta_gattc_sm_execute(p_clcb, BTA_GATTC_API_CLOSE_EVT, p_data);
+}
+/*******************************************************************************
+**
 ** Function         bta_gattc_set_discover_st
 **
 ** Description      when a SRCB start discovery, tell all related clcb and set
@@ -781,12 +785,29 @@
     {
         if (p_cb->clcb[i].p_srcb == p_srcb)
         {
+            p_cb->clcb[i].status = BTA_GATT_OK;
             p_cb->clcb[i].state = BTA_GATTC_DISCOVER_ST;
         }
     }
 }
 /*******************************************************************************
 **
+** Function         bta_gattc_restart_discover
+**
+** Description      process service change in discovery state, mark up the auto
+**                  update flag and set status to be discovery cancel for current
+**                  discovery.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA *p_data)
+{
+    p_clcb->status      = BTA_GATT_CANCEL;
+    p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+}
+/*******************************************************************************
+**
 ** Function         bta_gattc_start_discover
 **
 ** Description      Start a discovery on server.
@@ -796,16 +817,14 @@
 *******************************************************************************/
 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 */
+    APPL_TRACE_DEBUG2("bta_gattc_start_discover conn_id=%d p_clcb->p_srcb->state = %d ",
+        p_clcb->bta_conn_id, p_clcb->p_srcb->state);
+
+    if (((p_clcb->p_q_cmd == NULL || p_clcb->auto_update == BTA_GATTC_REQ_WAITING) &&
+        p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) ||
+        p_clcb->p_srcb->state == BTA_GATTC_SERV_DISC)
+    /* no pending operation, start discovery right away */
     {
         p_clcb->auto_update = BTA_GATTC_NO_SCHEDULE;
 
@@ -814,15 +833,19 @@
             /* clear the service change mask */
             p_clcb->p_srcb->srvc_hdl_chg = FALSE;
             p_clcb->p_srcb->update_count = 0;
+            p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC_ACT;
 
             /* 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)
+            if ((p_clcb->status = bta_gattc_init_cache(p_clcb->p_srcb)) == BTA_GATT_OK)
+            {
+                p_clcb->status = bta_gattc_discover_pri_service(p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
+            }
+            if (p_clcb->status != BTA_GATT_OK)
             {
                 APPL_TRACE_ERROR0("discovery on server failed");
-                bta_gattc_reset_discover_st(p_clcb->p_srcb);
+                bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
             }
         }
         else
@@ -830,6 +853,15 @@
             APPL_TRACE_ERROR0("unknown device, can not start discovery");
         }
     }
+    /* pending operation, wait until it finishes */
+    else
+    {
+        p_clcb->auto_update = BTA_GATTC_DISC_WAITING;
+
+        if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE)
+            p_clcb->state = BTA_GATTC_CONN_ST; /* set clcb state */
+    }
+
 }
 /*******************************************************************************
 **
@@ -850,11 +882,31 @@
 #endif
     p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
 
+    if (p_clcb->status != GATT_SUCCESS)
+    {
+        /* clean up cache */
+        if(p_clcb->p_srcb && p_clcb->p_srcb->p_srvc_cache)
+        {
+            while (p_clcb->p_srcb->cache_buffer.p_first)
+            {
+                GKI_freebuf (GKI_dequeue (&p_clcb->p_srcb->cache_buffer));
+            }
+            p_clcb->p_srcb->p_srvc_cache = NULL;
+        }
+
+        /* used to reset cache in application */
+        bta_gattc_co_cache_reset(p_clcb->p_srcb->server_bda);
+    }
     /* release pending attribute list buffer */
     utl_freebuf((void **)&p_clcb->p_srcb->p_srvc_list);
 
+    if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING)
+    {
+        /* start discovery again */
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+    }
     /* get any queued command to proceed */
-    if (p_q_cmd != NULL)
+    else if (p_q_cmd != NULL)
     {
         p_clcb->p_q_cmd = NULL;
 
@@ -1063,7 +1115,6 @@
         }
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_confirm
@@ -1220,8 +1271,6 @@
     ( *p_clcb->p_rcb->p_cback)(BTA_GATTC_EXEC_EVT,  &cb_data);
 
 }
-
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_op_cmpl
@@ -1384,6 +1433,7 @@
         }
         else
         {
+            p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
             /* cache open failure, start discovery */
             bta_gattc_start_discover(p_clcb, NULL);
         }
@@ -1401,7 +1451,7 @@
         {
             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);
+            bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
 
         }
     }
@@ -1431,7 +1481,7 @@
         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);
+            bta_gattc_reset_discover_st(p_clcb->p_srcb, BTA_GATT_OK);
 
         }
         else /* load more */
@@ -1446,6 +1496,7 @@
     }
     else
     {
+        p_clcb->p_srcb->state = BTA_GATTC_SERV_DISC;
         p_clcb->p_srcb->attr_index = 0;
         /* cache open failure, start discovery */
         bta_gattc_start_discover(p_clcb, NULL);
@@ -1469,10 +1520,9 @@
     {
         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);
+        bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_fail
@@ -1504,20 +1554,28 @@
 {
     BT_HDR          *p_buf;
     tBTA_GATTC_CLCB *p_clcb = NULL;
-
+#if BLE_INCLUDED == TRUE
+    UINT8           role ;
+#endif
     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)
     {
+#if BLE_INCLUDED == TRUE
+        role = L2CA_GetBleConnRole(bda);
+
+        if (role == HCI_ROLE_SLAVE)
+            bta_gattc_conn_find_alloc(bda);
+#endif
+
         /* 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))
+            /* for a background connection or listening connection */
+            if (/* L2CA_GetBleConnRole(bda)== HCI_ROLE_MASTER && */
+                bta_gattc_check_bg_conn(gattc_if, bda, role))
             {
                 /* allocate a new channel */
                 p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
@@ -1539,10 +1597,13 @@
     }
     else
     {
+#if BLE_INCLUDED == TRUE
+        bta_gattc_conn_dealloc(bda);
+#endif
         /* connection attempt timeout, send connection callback event */
         if (reason == GATT_CONN_CANCEL )
         {
-            p_clcb = bta_gattc_clcb_alloc(gattc_if, bda);
+            p_clcb = bta_gattc_find_alloc_clcb(gattc_if, bda);
             p_clcb->bta_conn_id = conn_id;
         }
         if ((p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id)) != NULL)
@@ -1564,6 +1625,55 @@
 }
 /*******************************************************************************
 **
+** Function         bta_gattc_process_api_refresh
+**
+** Description      process refresh API to delete cache and start a new discovery
+**                  if currently connected.
+**
+** Returns          None.
+**
+*******************************************************************************/
+void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg)
+{
+    tBTA_GATTC_SERV *p_srvc_cb = bta_gattc_find_srvr_cache(p_msg->api_conn.remote_bda);
+    tBTA_GATTC_CLCB      *p_clcb = &bta_gattc_cb.clcb[0];
+    BOOLEAN         found = FALSE;
+    UINT8           i;
+
+    if (p_srvc_cb != NULL)
+    {
+        /* try to find a CLCB */
+        if (p_srvc_cb->connected && p_srvc_cb->num_clcb != 0)
+        {
+            for (i = 0; i < BTA_GATTC_CLCB_MAX; i ++, p_clcb ++)
+            {
+                if (p_clcb->in_use && p_clcb->p_srcb == p_srvc_cb)
+                {
+                    found = TRUE;
+                    break;
+                }
+            }
+            if (found)
+            {
+                bta_gattc_sm_execute(p_clcb, BTA_GATTC_INT_DISCOVER_EVT, NULL);
+                return;
+            }
+        }
+        /* in all other cases, mark it and delete the cache */
+        if (p_srvc_cb->p_srvc_cache != NULL)
+        {
+            while (p_srvc_cb->cache_buffer.p_first)
+                GKI_freebuf (GKI_dequeue (&p_srvc_cb->cache_buffer));
+
+            p_srvc_cb->p_srvc_cache = NULL;
+        }
+    }
+    /* used to reset cache in application */
+    bta_gattc_co_cache_reset(p_msg->api_conn.remote_bda);
+
+}
+/*******************************************************************************
+**
 ** Function         bta_gattc_process_srvc_chg_ind
 **
 ** Description      process service change indication.
@@ -1624,7 +1734,6 @@
         /* 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);
         }
 
@@ -1746,7 +1855,6 @@
         APPL_TRACE_ERROR1("Indi/Notif for Unknown handle[0x%04x], can not find in local cache.", handle);
     }
 }
-
 /*******************************************************************************
 **
 ** Function         bta_gattc_cmpl_cback
@@ -1799,4 +1907,45 @@
 
     return;
 }
+#if BLE_INCLUDED == TRUE
+/*******************************************************************************
+**
+** Function         bta_gattc_init_clcb_conn
+**
+** Description      Initaite a BTA CLCB connection
+**
+** Returns          void
+**
+********************************************************************************/
+void bta_gattc_init_clcb_conn(UINT8 cif, BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CLCB     *p_clcb = NULL;
+    tBTA_GATTC_DATA     gattc_data;
+    UINT16              conn_id;
+
+    /* should always get the connection ID */
+    if (GATT_GetConnIdIfConnected(cif, remote_bda,&conn_id) == FALSE)
+    {
+        APPL_TRACE_ERROR0("bta_gattc_init_clcb_conn ERROR: not a connected device");
+        return;
+    }
+
+    /* initaite a new connection here */
+    if ((p_clcb = bta_gattc_clcb_alloc(cif, remote_bda)) != NULL)
+    {
+        gattc_data.hdr.layer_specific = p_clcb->bta_conn_id = conn_id;
+
+        gattc_data.api_conn.client_if = cif;
+        memcpy(gattc_data.api_conn.remote_bda, remote_bda, BD_ADDR_LEN);
+        gattc_data.api_conn.is_direct = TRUE;
+
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_API_OPEN_EVT, &gattc_data);
+    }
+    else
+    {
+        APPL_TRACE_ERROR0("No resources");
+    }
+}
+
+#endif /* #if BLE_INCLUDED == TRUE */
 #endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gattc_api.c b/bta/gatt/bta_gattc_api.c
index 1cace7d..59a9544 100644
--- a/bta/gatt/bta_gattc_api.c
+++ b/bta/gatt/bta_gattc_api.c
@@ -32,6 +32,14 @@
 #include "bta_gatt_api.h"
 #include "bta_gattc_int.h"
 
+
+/*****************************************************************************
+**  Externs
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTC_CB  bta_gattc_cb;
+#endif
+
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
@@ -44,6 +52,22 @@
 
 /*******************************************************************************
 **
+** Function         BTA_GATTC_Init
+**
+** Description     This function is called to initalize GATTC module
+**
+** Parameters       None
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTC_Init()
+{
+    memset(&bta_gattc_cb, 0, sizeof(tBTA_GATTC_CB));
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_GATTC_AppRegister
 **
 ** Description      This function is called to register application callbacks
@@ -232,7 +256,7 @@
 **
 ** Function         BTA_GATTC_GetFirstChar
 **
-** Description      This function is called to find the first charatceristic of the
+** Description      This function is called to find the first characteristic of the
 **                  service on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
@@ -270,7 +294,7 @@
 **
 ** Function         BTA_GATTC_GetNextChar
 **
-** Description      This function is called to find the next charatceristic of the
+** Description      This function is called to find the next characteristic of the
 **                  service on the given server.
 **
 ** Parameters       conn_id: connection ID which identify the server.
@@ -314,8 +338,8 @@
 **
 ** Function         BTA_GATTC_GetFirstCharDescr
 **
-** Description      This function is called to find the first charatceristic descriptor of the
-**                  charatceristic on the given server.
+** Description      This function is called to find the first characteristic descriptor of the
+**                  characteristic 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.
@@ -358,8 +382,8 @@
 **
 ** Function         BTA_GATTC_GetNextCharDescr
 **
-** Description      This function is called to find the next charatceristic of the
-**                  service on the given server.
+** Description      This function is called to find the next characteristic descriptor
+**                  of the characterisctic.
 **
 ** Parameters       conn_id: connection ID which identify the server.
 **                  p_start_descr_id: start the characteristic search from the next record
@@ -667,7 +691,10 @@
                                tBTA_GATT_AUTH_REQ auth_req)
 {
     tBTA_GATTC_API_WRITE  *p_buf;
-    UINT16  len = sizeof(tBTA_GATTC_API_WRITE) + p_data->len;
+    UINT16  len = sizeof(tBTA_GATTC_API_WRITE);
+
+    if (p_data != NULL)
+        len += p_data->len;
 
     if ((p_buf = (tBTA_GATTC_API_WRITE *) GKI_getbuf(len)) != NULL)
     {
@@ -789,7 +816,7 @@
     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
+                    conn_id, p_char_id->srvc_id.id.uuid.uu.uuid16, p_char_id->char_id.uuid.uu.uuid16);
 
     if ((p_buf = (tBTA_GATTC_API_CONFIRM *) GKI_getbuf(sizeof(tBTA_GATTC_API_CONFIRM))) != NULL)
     {
@@ -841,22 +868,39 @@
     {
         for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
         {
-            if (!p_clreg->notif_reg[i].in_use)
+            if ( p_clreg->notif_reg[i].in_use &&
+                 !memcmp(p_clreg->notif_reg[i].remote_bda, bda, BD_ADDR_LEN) &&
+                  bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
             {
-                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));
-
+                APPL_TRACE_WARNING0("notification already registered");
                 status = BTA_GATT_OK;
                 break;
             }
         }
-        if (i == BTA_GATTC_NOTIF_REG_MAX)
+        if (status != BTA_GATT_OK)
         {
-            status = BTA_GATT_NO_RESOURCES;
-            APPL_TRACE_ERROR0("Max Notification Reached, registration failed.");
+            for (i = 0; i < BTA_GATTC_NOTIF_REG_MAX; i ++)
+            {
+                if (!p_clreg->notif_reg[i].in_use)
+                {
+                    memset((void *)&p_clreg->notif_reg[i], 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);
+
+                    p_clreg->notif_reg[i].char_id.srvc_id.is_primary = p_char_id->srvc_id.is_primary;
+                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.srvc_id.id, &p_char_id->srvc_id.id);
+                    bta_gattc_cpygattid(&p_clreg->notif_reg[i].char_id.char_id, &p_char_id->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
@@ -905,10 +949,9 @@
         {
             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)))
+                bta_gattc_charid_compare(&p_clreg->notif_reg[i].char_id, p_char_id))
             {
                 APPL_TRACE_DEBUG0("Deregistered.");
-
                 memset(&p_clreg->notif_reg[i], 0, sizeof(tBTA_GATTC_NOTIF_REG));
                 status = BTA_GATT_OK;
                 break;
@@ -931,4 +974,31 @@
     return status;
 }
 
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Refresh
+**
+** Description      Refresh the server cache of the remote device
+**
+** Parameters       remote_bda: remote device BD address.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_GATTC_Refresh(BD_ADDR remote_bda)
+{
+    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_REFRESH_EVT;
+
+        memcpy(p_buf->remote_bda, remote_bda, BD_ADDR_LEN);
+
+
+        bta_sys_sendmsg(p_buf);
+    }
+    return;
+}
 #endif /* BTA_GATT_INCLUDED */
+
diff --git a/bta/gatt/bta_gattc_cache.c b/bta/gatt/bta_gattc_cache.c
index 3774df4..7b87afe 100644
--- a/bta/gatt/bta_gattc_cache.c
+++ b/bta/gatt/bta_gattc_cache.c
@@ -303,10 +303,6 @@
     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;
 }
 /*******************************************************************************
@@ -335,6 +331,12 @@
     APPL_TRACE_DEBUG2("free byte = %d,  req %d bytes.", p_srvc_cb->free_byte, len);
 #endif
 
+    if (p_srvc_cb->p_cur_srvc == NULL)
+    {
+        APPL_TRACE_ERROR0("Illegal action to add char/descr/incl srvc before adding a service!");
+        return GATT_WRONG_STATE;
+    }
+
     if (p_srvc_cb->free_byte < len)
     {
         if (bta_gattc_alloc_cache_buf(p_srvc_cb) == NULL)
@@ -381,10 +383,6 @@
 
     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;
 }
 
@@ -578,7 +576,6 @@
     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);
 }
 /*******************************************************************************
 **
@@ -935,8 +932,8 @@
             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,
+                                           p_data->value.group_value.e_handle,
+                                           p_data->value.group_value.service_type,
                                            TRUE);
                 break;
 
@@ -980,7 +977,14 @@
 void bta_gattc_disc_cmpl_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_STATUS status)
 {
     tBTA_GATTC_SERV * p_srvc_cb;
+    tBTA_GATTC_CLCB *p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
+    if ( p_clcb && (status != GATT_SUCCESS || p_clcb->status != GATT_SUCCESS) )
+    {
+        p_clcb->status = status;
+        bta_gattc_sm_execute(p_clcb, BTA_GATTC_DISCOVER_CMPL_EVT, NULL);
+        return;
+    }
     p_srvc_cb = bta_gattc_find_scb_by_cid(conn_id);
 
     if (p_srvc_cb != NULL)
@@ -988,6 +992,7 @@
         switch (disc_type)
         {
             case GATT_DISC_SRVC_ALL:
+            case GATT_DISC_SRVC_BY_UUID:
 #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
@@ -1031,7 +1036,7 @@
     tBT_UUID    attr_uuid;
     BOOLEAN     char_map = FALSE, done = FALSE;
 
-    while (p_cache && !done)
+    while (p_service_id && p_cache && !done)
     {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
         APPL_TRACE_DEBUG3("Service: handle[%d] uuid[0x%04x] inst[%d]",
@@ -1040,9 +1045,7 @@
 #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)
+        if (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
         {
             for (j = 0; p_attr; j ++)
             {
@@ -1210,12 +1213,12 @@
     {
         if (bta_gattc_uuid_compare(uuid, p_cache->service_uuid.id.uuid, FALSE))
         {
-//#if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
+#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
+#endif
             if (p_clcb->p_rcb->p_cback)
             {
                 memset(&cb_data, 0, sizeof(tBTA_GATTC));
@@ -1224,7 +1227,6 @@
                 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;
@@ -1260,11 +1262,9 @@
     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 ++)
+    for (i = 0; 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 (bta_gattc_srvcid_compare(p_service_id, &p_cache->service_uuid))
         {
 #if (defined BTA_GATT_DEBUG && BTA_GATT_DEBUG == TRUE)
             APPL_TRACE_DEBUG2("found matching service [0x%04x], inst[%d]",
@@ -1399,8 +1399,6 @@
     /* 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)
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 407e5d8..118b906 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -51,6 +51,7 @@
     BTA_GATTC_API_SEARCH_EVT,
     BTA_GATTC_API_CONFIRM_EVT,
     BTA_GATTC_API_READ_MULTI_EVT,
+    BTA_GATTC_API_REFRESH_EVT,
 
     BTA_GATTC_INT_CONN_EVT,
     BTA_GATTC_INT_DISCOVER_EVT,
@@ -74,14 +75,16 @@
 
 /* max client application GATTC can support */
 #ifndef     BTA_GATTC_CL_MAX
-#define     BTA_GATTC_CL_MAX    4
+#define     BTA_GATTC_CL_MAX    10
 #endif
 
 /* max known devices GATTC can support */
 #ifndef     BTA_GATTC_KNOWN_SR_MAX
-#define     BTA_GATTC_KNOWN_SR_MAX    4
+#define     BTA_GATTC_KNOWN_SR_MAX    10
 #endif
 
+#define BTA_GATTC_CONN_MAX      GATT_MAX_PHY_CHANNEL
+
 #ifndef BTA_GATTC_CLCB_MAX
     #define BTA_GATTC_CLCB_MAX      GATT_CL_MAX_LCB
 #endif
@@ -268,6 +271,8 @@
 #define BTA_GATTC_SERV_IDLE     0
 #define BTA_GATTC_SERV_LOAD     1
 #define BTA_GATTC_SERV_SAVE     2
+#define BTA_GATTC_SERV_DISC     3
+#define BTA_GATTC_SERV_DISC_ACT 4
 
     UINT8               state;
 
@@ -348,11 +353,19 @@
     BOOLEAN                 in_use;
     BD_ADDR                 remote_bda;
     tBTA_GATTC_CIF_MASK     cif_mask;
+    tBTA_GATTC_CIF_MASK     cif_adv_mask;
 
 }tBTA_GATTC_BG_TCK;
 
 typedef struct
 {
+    BOOLEAN             in_use;
+    BD_ADDR             remote_bda;
+}tBTA_GATTC_CONN;
+
+typedef struct
+{
+    tBTA_GATTC_CONN     conn_track[BTA_GATTC_CONN_MAX];
     tBTA_GATTC_BG_TCK   bg_track[BTA_GATTC_KNOWN_SR_MAX];
     tBTA_GATTC_RCB      cl_rcb[BTA_GATTC_CL_MAX];
 
@@ -402,6 +415,7 @@
 
 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_disc_close(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);
@@ -420,13 +434,15 @@
 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_restart_discover(tBTA_GATTC_CLCB *p_clcb, tBTA_GATTC_DATA * p_msg);
 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);
+extern void bta_gattc_process_api_refresh(tBTA_GATTC_CB *p_cb, tBTA_GATTC_DATA * p_msg);
 
 /* 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_cif (UINT8 client_if, BD_ADDR remote_bda);
 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);
@@ -443,10 +459,14 @@
 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 BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda, BOOLEAN add, BOOLEAN is_listen);
+extern BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role);
 extern UINT8 bta_gattc_num_reg_app(void);
 extern void bta_gattc_clear_notif_registration(UINT16 conn_id);
+extern tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(BD_ADDR bda);
+extern BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar);
+extern BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar);
+extern void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src);
 
 /* discovery functions */
 extern void bta_gattc_disc_res_cback (UINT16 conn_id, tGATT_DISC_TYPE disc_type, tGATT_DISC_RES *p_data);
@@ -461,4 +481,10 @@
 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);
 
+
+extern tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda);
+extern tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda);
+extern BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda);
+
 #endif /* BTA_GATTC_INT_H */
diff --git a/bta/gatt/bta_gattc_main.c b/bta/gatt/bta_gattc_main.c
index a1fb536..01a0224 100644
--- a/bta/gatt/bta_gattc_main.c
+++ b/bta/gatt/bta_gattc_main.c
@@ -42,7 +42,6 @@
 {
     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,
@@ -68,6 +67,8 @@
     BTA_GATTC_CI_SAVE,
     BTA_GATTC_CACHE_OPEN,
     BTA_GATTC_IGNORE_OP_CMPL,
+    BTA_GATTC_DISC_CLOSE,
+    BTA_GATTC_RESTART_DISCOVER,
 
     BTA_GATTC_IGNORE
 };
@@ -79,7 +80,6 @@
 {
     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,
@@ -104,7 +104,9 @@
     bta_gattc_ci_load,
     bta_gattc_ci_save,
     bta_gattc_cache_open,
-    bta_gattc_ignore_op_cmpl
+    bta_gattc_ignore_op_cmpl,
+    bta_gattc_disc_close,
+    bta_gattc_restart_discover
 };
 
 
@@ -131,6 +133,8 @@
 /* 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_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,            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},
@@ -163,6 +167,7 @@
 /* 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_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             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},
@@ -190,11 +195,13 @@
 /* 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_CLOSE_EVT          */   {BTA_GATTC_CLOSE,              BTA_GATTC_IDLE_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_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             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},
@@ -222,13 +229,15 @@
 /* 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_CLOSE_EVT          */   {BTA_GATTC_DISC_CLOSE,         BTA_GATTC_DISCOVER_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_API_REFRESH_EVT        */   {BTA_GATTC_IGNORE,             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_INT_DISCOVER_EVT       */   {BTA_GATTC_RESTART_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},
@@ -367,6 +376,10 @@
             bta_gattc_process_api_open_cancel(p_cb, (tBTA_GATTC_DATA *) p_msg);
             break;
 
+        case BTA_GATTC_API_REFRESH_EVT:
+            bta_gattc_process_api_refresh(p_cb, (tBTA_GATTC_DATA *) p_msg);
+            break;
+
         default:
             if ((p_clcb = bta_gattc_find_clcb_by_conn_id(p_msg->layer_specific))
                 != NULL)
@@ -450,7 +463,8 @@
             return "BTA_GATTC_API_REG_EVT";
         case BTA_GATTC_API_DEREG_EVT:
             return "BTA_GATTC_API_DEREG_EVT";
-
+        case BTA_GATTC_API_REFRESH_EVT:
+            return "BTA_GATTC_API_REFRESH_EVT";
         default:
             return "unknown GATTC event code";
     }
diff --git a/bta/gatt/bta_gattc_utils.c b/bta/gatt/bta_gattc_utils.c
index a36e26c..4749f21 100644
--- a/bta/gatt/bta_gattc_utils.c
+++ b/bta/gatt/bta_gattc_utils.c
@@ -221,6 +221,7 @@
 #endif
             p_clcb                  = &bta_gattc_cb.clcb[i_clcb];
             p_clcb->in_use          = TRUE;
+            p_clcb->status          = BTA_GATT_OK;
             bdcpy(p_clcb->bda, remote_bda);
 
             p_clcb->p_rcb = bta_gattc_cl_get_regcb(client_if);
@@ -275,18 +276,23 @@
 *******************************************************************************/
 void bta_gattc_clcb_dealloc(tBTA_GATTC_CLCB *p_clcb)
 {
+    tBTA_GATTC_SERV     *p_srcb = p_clcb->p_srcb;
 
     if (p_clcb)
     {
-        if (p_clcb->p_srcb->num_clcb)
-            p_clcb->p_srcb->num_clcb --;
+        if (p_srcb->num_clcb)
+            p_srcb->num_clcb --;
 
         if (p_clcb->p_rcb->num_clcb)
             p_clcb->p_rcb->num_clcb --;
+        if ( p_srcb->num_clcb == 0)
+        {
+            p_srcb->connected = FALSE;
+            p_srcb->state = BTA_GATTC_SERV_IDLE;
+        }
 
         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
@@ -299,7 +305,7 @@
 **
 ** Function         bta_gattc_find_srcb
 **
-** Description      find server cache by remote bd address
+** Description      find server cache by remote bd address currently in use
 **
 ** Returns          pointer to the server cache.
 **
@@ -316,6 +322,28 @@
     }
     return NULL;
 }
+
+/*******************************************************************************
+**
+** Function         bta_gattc_find_srvr_cache
+**
+** Description      find server cache by remote bd address
+**
+** Returns          pointer to the server cache.
+**
+*******************************************************************************/
+tBTA_GATTC_SERV * bta_gattc_find_srvr_cache(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 (bdcmp(p_srcb->server_bda, bda) == 0)
+            return p_srcb;
+    }
+    return NULL;
+}
 /*******************************************************************************
 **
 ** Function         bta_gattc_find_scb_by_cid
@@ -441,6 +469,85 @@
 }
 /*******************************************************************************
 **
+** Function         bta_gattc_cpygattid
+**
+** Description      copy two tBTA_GATT_ID value
+**
+** Returns
+**
+*******************************************************************************/
+void bta_gattc_cpygattid(tBTA_GATT_ID *p_des, tBTA_GATT_ID *p_src)
+{
+    memset ((void *)p_des, 0, sizeof(tBTA_GATT_ID));
+
+    p_des->inst_id = p_src->inst_id;
+
+    p_des->uuid.len = p_src->uuid.len;
+
+    if (p_des->uuid.len == LEN_UUID_16)
+    {
+        p_des->uuid.uu.uuid16 = p_src->uuid.uu.uuid16;
+    }
+    else if (p_des->uuid.len == LEN_UUID_128)
+    {
+        memcpy(p_des->uuid.uu.uuid128, p_src->uuid.uu.uuid128, LEN_UUID_128);
+    }
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_gattid_compare
+**
+** Description      compare two tBTA_GATT_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_gattid_compare(tBTA_GATT_ID *p_src, tBTA_GATT_ID *p_tar)
+{
+    if (p_src->inst_id == p_tar->inst_id &&
+        bta_gattc_uuid_compare (p_src->uuid, p_tar->uuid, TRUE ))
+        return TRUE;
+    else
+        return FALSE;
+
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_srvcid_compare
+**
+** Description      compare two tBTA_GATT_SRVC_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_srvcid_compare(tBTA_GATT_SRVC_ID *p_src, tBTA_GATT_SRVC_ID *p_tar)
+{
+    if (p_src->is_primary == p_tar->is_primary &&
+        bta_gattc_gattid_compare (&p_src->id, &p_tar->id))
+        return TRUE;
+    else
+        return FALSE;
+}
+/*******************************************************************************
+**
+** Function         bta_gattc_charid_compare
+**
+** Description      compare two tBTA_GATTC_CHAR_ID type of pointer
+**
+** Returns
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_charid_compare(tBTA_GATTC_CHAR_ID *p_src, tBTA_GATTC_CHAR_ID *p_tar)
+{
+    if (bta_gattc_gattid_compare (&p_src->char_id, &p_tar->char_id) &&
+        bta_gattc_srvcid_compare (&p_src->srvc_id, &p_tar->srvc_id))
+        return TRUE;
+    else
+        return FALSE;
+}
+
+/*******************************************************************************
+**
 ** Function         bta_gattc_check_notif_registry
 **
 ** Description      check if the service notificaition has been registered.
@@ -457,12 +564,7 @@
     {
         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)
-           )
+            bta_gattc_charid_compare (&p_clreg->notif_reg[i].char_id, &p_notify->char_id))
         {
             APPL_TRACE_DEBUG0("Notification registered!");
             return TRUE;
@@ -562,22 +664,36 @@
 ** Returns          TRUE if success; FALSE otherwise.
 **
 *******************************************************************************/
-BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, BOOLEAN add)
+BOOLEAN bta_gattc_mark_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR_PTR remote_bda_ptr,
+                                BOOLEAN add, BOOLEAN is_listen)
 {
     tBTA_GATTC_BG_TCK   *p_bg_tck = &bta_gattc_cb.bg_track[0];
     UINT8   i = 0;
+    tBTA_GATTC_CIF_MASK  *p_cif_mask;
 
     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)
+            ((remote_bda_ptr != NULL && bdcmp(p_bg_tck->remote_bda, remote_bda_ptr) == 0) ||
+            (remote_bda_ptr == NULL && bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0)))
         {
+             p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
             if (add)
                 /* mask on the cif bit */
-                p_bg_tck->cif_mask |= (1 <<(client_if - 1));
+                *p_cif_mask |= (1 <<(client_if - 1));
             else
-                p_bg_tck->cif_mask &= (~(1 <<(client_if - 1)));
-
+            {
+                if (client_if != 0)
+                    *p_cif_mask &= (~(1 <<(client_if - 1)));
+                else
+                    *p_cif_mask = 0;
+            }
+            /* no BG connection for this device, make it available */
+            if (p_bg_tck->cif_mask == 0 && p_bg_tck->cif_adv_mask == 0)
+            {
+                memset(p_bg_tck, 0, sizeof(tBTA_GATTC_BG_TCK));
+            }
             return TRUE;
         }
     }
@@ -594,8 +710,14 @@
             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));
+                if (remote_bda_ptr)
+                    bdcpy(p_bg_tck->remote_bda, remote_bda_ptr);
+                else
+                    bdcpy(p_bg_tck->remote_bda, bd_addr_null);
+
+                p_cif_mask = is_listen ? &p_bg_tck->cif_adv_mask : &p_bg_tck->cif_mask;
+
+                *p_cif_mask = (1 <<(client_if - 1));
                 return TRUE;
             }
         }
@@ -612,20 +734,25 @@
 ** Returns          TRUE if success; FALSE otherwise.
 **
 *******************************************************************************/
-BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda)
+BOOLEAN bta_gattc_check_bg_conn (tBTA_GATTC_IF client_if,  BD_ADDR remote_bda, UINT8 role)
 {
     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 ++)
+    for (i = 0; i < BTA_GATTC_KNOWN_SR_MAX && !is_bg_conn; i ++, p_bg_tck ++)
     {
         if (p_bg_tck->in_use &&
-            bdcmp(p_bg_tck->remote_bda, remote_bda) == 0)
+            (bdcmp(p_bg_tck->remote_bda, remote_bda) == 0 ||
+             bdcmp(p_bg_tck->remote_bda, bd_addr_null) == 0))
         {
-            if ((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0)
+            if (((p_bg_tck->cif_mask &(1 <<(client_if - 1))) != 0) &&
+                role == HCI_ROLE_MASTER)
                 is_bg_conn = TRUE;
-            break;
+
+            if (((p_bg_tck->cif_adv_mask &(1 <<(client_if - 1))) != 0) &&
+                role == HCI_ROLE_SLAVE)
+                is_bg_conn = TRUE;
         }
     }
     return is_bg_conn;
@@ -656,9 +783,103 @@
         (*p_clreg->p_cback)(BTA_GATTC_OPEN_EVT, &cb_data);
     }
 }
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_alloc
+**
+** Description      allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_alloc(BD_ADDR remote_bda)
+{
+    UINT8               i_conn = 0;
+    tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
+
+    for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+    {
+        if (!p_conn->in_use)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG1("bta_gattc_conn_alloc: found conn_track[%d] available",i_conn);
+#endif
+            p_conn->in_use          = TRUE;
+            bdcpy(p_conn->remote_bda, remote_bda);
+            return p_conn;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_find
+**
+** Description      allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find(BD_ADDR remote_bda)
+{
+    UINT8               i_conn = 0;
+    tBTA_GATTC_CONN     *p_conn = &bta_gattc_cb.conn_track[0];
+
+    for (i_conn = 0; i_conn < BTA_GATTC_CONN_MAX; i_conn++, p_conn ++)
+    {
+        if (p_conn->in_use && bdcmp(remote_bda, p_conn->remote_bda) == 0)
+        {
+#if BTA_GATT_DEBUG == TRUE
+            APPL_TRACE_DEBUG1("bta_gattc_conn_find: found conn_track[%d] matched",i_conn);
+#endif
+            return p_conn;
+        }
+    }
+    return NULL;
+}
 
 
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_find_alloc
+**
+** Description      find or allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+tBTA_GATTC_CONN * bta_gattc_conn_find_alloc(BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
 
+    if (p_conn == NULL)
+    {
+        p_conn = bta_gattc_conn_alloc(remote_bda);
+    }
+    return p_conn;
+}
 
+/*******************************************************************************
+**
+** Function         bta_gattc_conn_dealloc
+**
+** Description      de-allocate connection tracking spot
+**
+** Returns          pointer to the clcb
+**
+*******************************************************************************/
+BOOLEAN bta_gattc_conn_dealloc(BD_ADDR remote_bda)
+{
+    tBTA_GATTC_CONN     *p_conn = bta_gattc_conn_find (remote_bda);
+
+    if (p_conn != NULL)
+    {
+        p_conn->in_use = FALSE;
+        memset(p_conn->remote_bda, 0, BD_ADDR_LEN);
+        return TRUE;
+    }
+    return FALSE;
+}
 
 #endif /* BTA_GATT_INCLUDED */
diff --git a/bta/gatt/bta_gatts_act.c b/bta/gatt/bta_gatts_act.c
index 1b47598..5504df0 100644
--- a/bta/gatt/bta_gatts_act.c
+++ b/bta/gatt/bta_gatts_act.c
@@ -292,7 +292,6 @@
     tBTA_GATTS          cb_data;
     UINT8               srvc_idx;
     UINT16              service_id = 0;
-    //tBTA_GATTS_HNDL_RANGE   handle_range;
 
     cb_data.create.status = BTA_GATT_ERROR;
 
@@ -714,7 +713,6 @@
 
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_gatts_request_cback
diff --git a/bta/gatt/bta_gatts_api.c b/bta/gatt/bta_gatts_api.c
index 65df0a6..d30878e 100644
--- a/bta/gatt/bta_gatts_api.c
+++ b/bta/gatt/bta_gatts_api.c
@@ -33,6 +33,13 @@
 #include "bta_gatts_int.h"
 
 /*****************************************************************************
+**  Externs
+*****************************************************************************/
+#if BTA_DYNAMIC_MEMORY == FALSE
+extern tBTA_GATTS_CB  bta_gatts_cb;
+#endif
+
+/*****************************************************************************
 **  Constants
 *****************************************************************************/
 
@@ -44,6 +51,22 @@
 
 /*******************************************************************************
 **
+** Function         BTA_GATTS_Init
+**
+** Description     This function is called to initalize GATTS module
+**
+** Parameters       None
+**
+** Returns          None
+**
+*******************************************************************************/
+void BTA_GATTS_Init()
+{
+    memset(&bta_gatts_cb, 0, sizeof(tBTA_GATTS_CB));
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_GATTS_AppRegister
 **
 ** Description      This function is called to register application callbacks
diff --git a/bta/gatt/bta_gatts_int.h b/bta/gatt/bta_gatts_int.h
index 4810c05..9f0ec7e 100644
--- a/bta/gatt/bta_gatts_int.h
+++ b/bta/gatt/bta_gatts_int.h
@@ -28,7 +28,6 @@
 #include "bta_sys.h"
 #include "bta_gatt_api.h"
 #include "gatt_api.h"
-//#include "bta_gatts_co.h"
 
 #include "gki.h"
 
@@ -52,7 +51,8 @@
     BTA_GATTS_API_RSP_EVT,
     BTA_GATTS_API_OPEN_EVT,
     BTA_GATTS_API_CANCEL_OPEN_EVT,
-    BTA_GATTS_API_CLOSE_EVT
+    BTA_GATTS_API_CLOSE_EVT,
+    BTA_GATTS_API_LISTEN_EVT
 
 };
 typedef UINT16 tBTA_GATTS_INT_EVT;
@@ -116,7 +116,6 @@
 typedef struct
 {
     BT_HDR  hdr;
-    //todo BD_ADDR bd_addr;
     UINT16  attr_id;
     UINT16  len;
     BOOLEAN need_confirm;
@@ -148,6 +147,14 @@
 
 typedef tBTA_GATTS_API_OPEN tBTA_GATTS_API_CANCEL_OPEN;
 
+typedef struct
+{
+    BT_HDR                  hdr;
+    BD_ADDR_PTR             remote_bda;
+    tBTA_GATTS_IF           server_if;
+    BOOLEAN                 start;
+} tBTA_GATTS_API_LISTEN;
+
 typedef union
 {
     BT_HDR                          hdr;
@@ -164,6 +171,8 @@
     tBTA_GATTS_API_CANCEL_OPEN      api_cancel_open;
 
     tBTA_GATTS_INT_START_IF         int_start_if;
+    /* if peripheral role is supported */
+    tBTA_GATTS_API_LISTEN           api_listen;
 } tBTA_GATTS_DATA;
 
 /* application registration control block */
@@ -172,7 +181,7 @@
     BOOLEAN             in_use;
     tBT_UUID            app_uuid;
     tBTA_GATTS_CBACK    *p_cback;
-    tBTA_GATTS_IF        gatt_if;  //todo cahneg to server_if
+    tBTA_GATTS_IF        gatt_if;
 }tBTA_GATTS_RCB;
 
 /* service registration control block */
@@ -233,6 +242,7 @@
 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 void bta_gatts_listen(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);
diff --git a/bta/hh/bta_hh_act.c b/bta/hh/bta_hh_act.c
index de08096..f2b91e0 100644
--- a/bta/hh/bta_hh_act.c
+++ b/bta/hh/bta_hh_act.c
@@ -84,18 +84,20 @@
 
         status = BTA_HH_OK;
         /* initialize device CB */
-        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+        for (xx = 0; xx < BTA_HH_MAX_DEVICE; 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;
         }
+
+        /* initialize control block map */
+        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+            bta_hh_cb.cb_index[xx]          = BTA_HH_IDX_INVALID;
     }
 
-    /* signal BTA call back event */
-    (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
+        /* signal BTA call back event */
+        (* bta_hh_cb.p_cback)(BTA_HH_ENABLE_EVT, (tBTA_HH *)&status);
 }
 /*******************************************************************************
 **
@@ -124,7 +126,7 @@
     {
         bta_hh_cb.w4_disable = TRUE;
 
-        for(xx = 0; xx < BTA_HH_MAX_KNOWN; xx ++)
+        for(xx = 0; xx < BTA_HH_MAX_DEVICE; xx ++)
         {
             /* send API_CLOSE event to every connected device */
             if ( bta_hh_cb.kdev[xx].state == BTA_HH_CONN_ST )
@@ -152,24 +154,15 @@
 *******************************************************************************/
 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));
+    bta_hh_cleanup_disable(status);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hh_sdp_cback
@@ -186,7 +179,8 @@
     UINT8              hdl;
     tBTA_HH_STATUS    status = BTA_HH_ERR_SDP;
 
-    if (result == SDP_SUCCESS)
+    /* make sure sdp succeeded and hh has not been disabled */
+    if ((result == SDP_SUCCESS) && (p_cb != NULL))
     {
         /* security is required for the connection, add attr_mask bit*/
         if (p_cb->sec_mask)
@@ -269,20 +263,20 @@
          * 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) || (result == SDP_NO_RECS_MATCH)) && (p_cb != NULL))
     {
         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);
+                bta_hh_update_di_info(p_cb, di_rec.rec.vendor, di_rec.rec.product, di_rec.rec.version, 0);
             }
 
         }
         else /* no DI recrod available */
         {
-            bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0);
+            bta_hh_update_di_info(p_cb, BTA_HH_VENDOR_ID_INVALID, 0, 0, 0);
         }
 
         if ((ret = HID_HostGetSDPRecord(p_cb->addr,
@@ -332,6 +326,7 @@
 
     p_cb->sec_mask  = p_data->api_conn.sec_mask;
     p_cb->mode      = p_data->api_conn.mode;
+    bta_hh_cb.p_cur = p_cb;
 
     /* if previously virtually cabled device, skip SDP */
     if (p_cb->app_id)
@@ -355,9 +350,7 @@
                 bta_hh_cb.cb_index[hdl] = p_cb->index;
             }
             else
-            {
-                status = BTA_HH_ERR_SDP;
-            }
+                status = BTA_HH_ERR_NO_RES;
         }
         bta_hh_sm_execute(p_cb, BTA_HH_SDP_CMPL_EVT, (tBTA_HH_DATA *)&status);
 
@@ -531,12 +524,7 @@
 
     /* 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);
+                       p_cb->attr_mask,  p_cb->app_id);
 
     /* set protocol mode when not default report mode */
     if (p_cb->mode != BTA_HH_PROTO_RPT_MODE)
@@ -895,7 +883,8 @@
                 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);
+                                      p_dev_info->dscp_info.version,
+                                      0);
 
                 /* add to BTA device list */
                 bta_hh_add_device_to_list(p_cb, dev_handle,
@@ -917,13 +906,12 @@
 #if BTA_HH_DEBUG
         bta_hh_trace_dev_db();
 #endif
-        break;
 
+        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)
             {
@@ -1087,7 +1075,7 @@
         utl_freebuf((void **)&pdata);
         break;
     case HID_HDEV_EVT_VC_UNPLUG:
-        for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+        for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
         {
             if (bta_hh_cb.kdev[xx].hid_handle == dev_handle)
             {
diff --git a/bta/hh/bta_hh_api.c b/bta/hh/bta_hh_api.c
index 300fc6f..2a7965e 100644
--- a/bta/hh/bta_hh_api.c
+++ b/bta/hh/bta_hh_api.c
@@ -57,7 +57,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback)
+void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback)
 {
     tBTA_HH_API_ENABLE *p_buf;
 
@@ -291,12 +291,21 @@
 **
 ** Description      This function send DATA transaction to HID device.
 **
+** Parameter        dev_handle: device handle
+**                  dev_bda: remote device address
+**                  p_data: data to be sent in the DATA transaction; or
+**                          the data to be write into the Output Report of a LE HID
+**                          device. The report is identified the report ID which is
+**                          the value of the byte (UINT8 *)(p_buf + 1) + p_buf->offset.
+**                          p_data->layer_specific needs to be set to the report type,
+**                          it can be OUTPUT report, or FEATURE report.
+**
 ** 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);
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, (UINT8)p_data->layer_specific, 0, 0, p_data);
 }
 
 /*******************************************************************************
diff --git a/bta/hh/bta_hh_cfg.c b/bta/hh/bta_hh_cfg.c
index 5b7335a..e3ffefe 100644
--- a/bta/hh/bta_hh_cfg.c
+++ b/bta/hh/bta_hh_cfg.c
@@ -34,13 +34,6 @@
 #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
-#define BTA_HH_APP_ID_JOY           5
-#define BTA_HH_APP_ID_GPAD          6
 
 
 /* The type of devices supported by BTA HH and corresponding application ID */
diff --git a/bta/hh/bta_hh_int.h b/bta/hh/bta_hh_int.h
index f3a8e54..7630a3a 100644
--- a/bta/hh/bta_hh_int.h
+++ b/bta/hh/bta_hh_int.h
@@ -174,7 +174,7 @@
                                                        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          kdev[BTA_HH_MAX_DEVICE]; /* 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
@@ -232,13 +232,17 @@
                                       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);
+                           UINT16 version, UINT8 flag);
+extern void bta_hh_cleanup_disable(tBTA_HH_STATUS status);
+
+extern UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle);
 
 /* 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);
 
+extern tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout);
 
 #if BTA_HH_DEBUG
 extern void bta_hh_trace_dev_db(void);
diff --git a/bta/hh/bta_hh_main.c b/bta/hh/bta_hh_main.c
index a1d0ad2..1c03469 100644
--- a/bta/hh/bta_hh_main.c
+++ b/bta/hh/bta_hh_main.c
@@ -96,8 +96,7 @@
 /* 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    }
-
+/* BTA_HH_OPEN_CMPL_EVT        */  {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
 };
 
 
@@ -115,7 +114,7 @@
 /* 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    }
+/* BTA_HH_OPEN_CMPL_EVT     */    {BTA_HH_OPEN_CMPL_ACT, BTA_HH_CONN_ST    }
 };
 
 
@@ -233,6 +232,14 @@
                     cback_data.hs_data.status = BTA_HH_ERR_HDL;
                     /* hs_data.rsp_data will be all zero, which is not valid value */
                 }
+                else if (p_data->api_sndcmd.t_type == HID_TRANS_CONTROL &&
+                         p_data->api_sndcmd.param == BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG)
+                {
+                    cback_data.status = BTA_HH_ERR_HDL;
+                    cback_event = BTA_HH_VC_UNPLUG_EVT;
+                }
+                else
+                    cback_event = 0;
                 break;
 
             case BTA_HH_API_CLOSE_EVT:
@@ -297,7 +304,7 @@
 *******************************************************************************/
 BOOLEAN bta_hh_hdl_event(BT_HDR *p_msg)
 {
-    UINT8           index = BTA_HH_MAX_KNOWN;
+    UINT8           index = BTA_HH_IDX_INVALID;
     tBTA_HH_DEV_CB *p_cb = NULL;
 
     switch (p_msg->event)
@@ -330,24 +337,24 @@
                 }
                 else /* else remove device by handle */
                 {
-                    index = bta_hh_cb.cb_index[p_msg->layer_specific];
+                    index = bta_hh_dev_handle_to_cb_idx((UINT8)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
+                      * force the index to be IDX_INVALID
                       */
                     if (bta_hh_cb.kdev[index].in_use == FALSE) {
-                           index = BTA_HH_MAX_KNOWN;
+                           index = BTA_HH_IDX_INVALID;
                     }
 // btla-specific --
                 }
             }
-            else if (p_msg->layer_specific < BTA_HH_MAX_KNOWN )
-                index = bta_hh_cb.cb_index[p_msg->layer_specific];
+            else
+                index = bta_hh_dev_handle_to_cb_idx((UINT8)p_msg->layer_specific);
 
-            if (index != BTA_HH_MAX_KNOWN)
+            if (index != BTA_HH_IDX_INVALID)
                 p_cb = &bta_hh_cb.kdev[index];
 
 #if BTA_HH_DEBUG
diff --git a/bta/hh/bta_hh_utils.c b/bta/hh/bta_hh_utils.c
index 4349282..bea0f2b 100644
--- a/bta/hh/bta_hh_utils.c
+++ b/bta/hh/bta_hh_utils.c
@@ -23,6 +23,10 @@
 
 #include "bta_hh_int.h"
 
+/* if SSR max latency is not defined by remote device, set the default value
+   as half of the link supervision timeout */
+#define BTA_HH_GET_DEF_SSR_MAX_LAT(x)   ((x)>> 1)
+
 /*****************************************************************************
 **  Constants
 *****************************************************************************/
@@ -61,7 +65,7 @@
     UINT8 xx;
 
     /* See how many active devices there are. */
-    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
     {
         /* check if any active/known devices is a match */
         if ((!bdcmp (bda, bta_hh_cb.kdev[xx].addr) &&
@@ -83,7 +87,7 @@
     }
 
     /* if no active device match, find a spot for it */
-    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; xx++)
     {
         if (!bta_hh_cb.kdev[xx].in_use)
         {
@@ -91,12 +95,15 @@
             break;
         }
     }
-    /* If device list full, report BTA_HH_MAX_KNOWN */
+    /* If device list full, report BTA_HH_IDX_INVALID */
 #if BTA_HH_DEBUG
     APPL_TRACE_DEBUG2("bta_hh_find_cb:: index = %d while max = %d",
-                        xx, BTA_HH_MAX_KNOWN);
+                        xx, BTA_HH_MAX_DEVICE);
 #endif
 
+    if (xx == BTA_HH_MAX_DEVICE)
+        xx = BTA_HH_IDX_INVALID;
+
     return xx;
 }
 
@@ -115,7 +122,9 @@
     UINT8 index;
 
     if (p_cb->hid_handle != BTA_HH_INVALID_HANDLE )
-        bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_MAX_KNOWN;
+    {
+            bta_hh_cb.cb_index[p_cb->hid_handle] = BTA_HH_IDX_INVALID;
+    }
 
     /* reset device control block */
     index = p_cb->index;                        /* Preserve index for this control block */
@@ -140,7 +149,7 @@
 **
 *******************************************************************************/
 void bta_hh_update_di_info(tBTA_HH_DEV_CB *p_cb, UINT16 vendor_id, UINT16 product_id,
-                           UINT16 version)
+                           UINT16 version, UINT8 flag)
 {
 #if BTA_HH_DEBUG
     APPL_TRACE_DEBUG3("vendor_id = 0x%2x product_id = 0x%2x version = 0x%2x",
@@ -178,15 +187,8 @@
     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;
+    p_cb->dscp_info.ssr_max_latency = ssr_max_latency;
+    p_cb->dscp_info.ssr_min_tout    = ssr_min_tout;
 
     /* store report descriptor info */
     if ( p_dscp_info)
@@ -386,6 +388,108 @@
 
 }
 
+/*******************************************************************************
+**
+** Function         bta_hh_read_ssr_param
+**
+** Description      Read the SSR Parameter for the remote device
+**
+** Returns          tBTA_HH_STATUS  operation status
+**
+*******************************************************************************/
+tBTA_HH_STATUS bta_hh_read_ssr_param(BD_ADDR bd_addr, UINT16 *p_max_ssr_lat, UINT16 *p_min_ssr_tout)
+{
+    tBTA_HH_STATUS  status = BTA_HH_ERR;
+    tBTA_HH_CB  *p_cb = &bta_hh_cb;
+    UINT8       i;
+    UINT16      ssr_max_latency;
+    /* lock other GKI task */
+    GKI_sched_lock();
+    for (i = 0; i < BTA_HH_MAX_KNOWN; i ++)
+    {
+        if (memcmp(p_cb->kdev[i].addr, bd_addr, BD_ADDR_LEN) == 0)
+        {
+
+            /* if remote device does not have HIDSSRHostMaxLatency attribute in SDP,
+            set SSR max latency default value here.  */
+            if (p_cb->kdev[i].dscp_info.ssr_max_latency == HID_SSR_PARAM_INVALID)
+            {
+                /* The default is calculated as half of link supervision timeout.*/
+
+                BTM_GetLinkSuperTout(p_cb->kdev[i].addr, &ssr_max_latency) ;
+                ssr_max_latency = BTA_HH_GET_DEF_SSR_MAX_LAT(ssr_max_latency);
+
+                /* per 1.1 spec, if the newly calculated max latency is greater than
+                BTA_HH_SSR_MAX_LATENCY_DEF which is 500ms, use BTA_HH_SSR_MAX_LATENCY_DEF */
+                if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
+                    ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
+
+                * p_max_ssr_lat  = ssr_max_latency;
+            }
+            else
+                * p_max_ssr_lat  = p_cb->kdev[i].dscp_info.ssr_max_latency;
+
+            if (p_cb->kdev[i].dscp_info.ssr_min_tout == HID_SSR_PARAM_INVALID)
+                * p_min_ssr_tout = BTA_HH_SSR_MIN_TOUT_DEF;
+            else
+                * p_min_ssr_tout = p_cb->kdev[i].dscp_info.ssr_min_tout;
+
+            status           = BTA_HH_OK;
+
+            break;
+        }
+    }
+    GKI_sched_unlock();
+
+    return status;
+}
+
+/*******************************************************************************
+**
+** Function         bta_hh_cleanup_disable
+**
+** Description      when disable finished, cleanup control block and send callback
+**
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hh_cleanup_disable(tBTA_HH_STATUS status)
+{
+    UINT8   xx;
+    /* free buffer in CB holding report descriptors */
+    for(xx = 0; xx < BTA_HH_MAX_DEVICE; 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_dev_handle_to_cb_idx
+**
+** Description      convert a HID device handle to the device control block index.
+**
+**
+** Returns          UINT8: index of the device control block.
+**
+*******************************************************************************/
+UINT8 bta_hh_dev_handle_to_cb_idx(UINT8 dev_handle)
+{
+    UINT8 index = BTA_HH_IDX_INVALID;
+
+        /* regular HID device checking */
+        if (dev_handle < BTA_HH_MAX_KNOWN )
+        index = bta_hh_cb.cb_index[dev_handle];
+
+    return index;
+
+}
 #if BTA_HH_DEBUG
 /*******************************************************************************
 **
@@ -402,7 +506,7 @@
 
     APPL_TRACE_DEBUG0("bta_hh_trace_dev_db:: Device DB list********************");
 
-    for (xx = 0; xx < BTA_HH_MAX_KNOWN; xx++)
+    for (xx = 0; xx < BTA_HH_MAX_DEVICE; 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);
diff --git a/bta/hl/bta_hl_act.c b/bta/hl/bta_hl_act.c
index 0f46e5e..ab12222 100644
--- a/bta/hl/bta_hl_act.c
+++ b/bta/hl/bta_hl_act.c
@@ -59,7 +59,8 @@
 static void bta_hl_sdp_cback6(UINT16 status);
 
 
-static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] = {
+static tSDP_DISC_CMPL_CB * const bta_hl_sdp_cback_arr[] =
+{
     bta_hl_sdp_cback0,
     bta_hl_sdp_cback1,
     bta_hl_sdp_cback2,
@@ -544,7 +545,7 @@
     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;
+    tBTA_HL_EVT         event = 0;
     BOOLEAN             send_evt=TRUE;
     tBTA_HL_STATUS      status;
 
@@ -880,7 +881,7 @@
     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;
+    UINT8               old_dch_oper = BTA_HL_DCH_OP_NONE;
     BOOLEAN             send_event = FALSE;
 
 
@@ -987,8 +988,8 @@
     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;
+    UINT8               old_dch_oper = BTA_HL_DCH_OP_NONE;
+    tBTA_HL_DCH_MODE    dch_mode = BTA_HL_DCH_MODE_STREAMING;
     BOOLEAN             send_event = FALSE;
 
 
@@ -1006,10 +1007,6 @@
         {
             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)
         {
@@ -1034,6 +1031,11 @@
         old_dch_oper = p_dcb->dch_oper;
         p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
     }
+    else
+    {
+        APPL_TRACE_ERROR1("Error dch oper =%d",  p_dcb->dch_oper);
+        return;
+    }
 
     switch (old_dch_oper)
     {
@@ -2209,7 +2211,6 @@
 
             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))
@@ -2324,22 +2325,30 @@
 *******************************************************************************/
 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");
+    APPL_TRACE_DEBUG1("bta_hl_cch_mca_close mcl_handle=%d", p_mcb->mcl_handle);
 #endif
     if (p_mcb->sdp_oper != BTA_HL_SDP_OP_CCH_INIT)
     {
-        if ( MCA_DisconnectReq((tMCA_HANDLE) p_acb->app_handle) != MCA_SUCCESS)
+        if(p_mcb->mcl_handle)
         {
-            bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
+            if ( MCA_DisconnectReq((tMCA_HANDLE) p_mcb->mcl_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;
+            APPL_TRACE_DEBUG0("No valid mcl_handle to stop the CCH setup now so wait until CCH is up then close it" );
         }
     }
     else
     {
         p_mcb->close_pending = TRUE;
+        APPL_TRACE_DEBUG0("can not stop the CCH setup becasue SDP is in progress so wait until it is done" );
     }
 }
 
@@ -2365,6 +2374,12 @@
 #endif
     bta_sys_conn_close(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
 
+    if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE && p_mcb->force_close_local_cch_opening)
+    {
+       p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_OPEN;
+       APPL_TRACE_DEBUG0("change cch_oper from BTA_HL_CCH_OP_LOCAL_CLOSE to BTA_HL_CCH_OP_LOCAL_OPEN");
+    }
+
     switch (p_mcb->cch_oper)
     {
         case BTA_HL_CCH_OP_LOCAL_OPEN:
@@ -2445,6 +2460,28 @@
 
 /*******************************************************************************
 **
+** Function         bta_hl_cch_mca_disc_open
+**
+** Description      Action routine for disconnect the just opened Control channel
+**
+** Returns          void
+**
+*******************************************************************************/
+void bta_hl_cch_mca_disc_open(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_DEBUG2("bta_hl_cch_mca_disc_open mcl_handle=0x%x close_pending=%d", p_data->mca_evt.mcl_handle, p_mcb->close_pending );
+#endif
+
+    p_mcb->close_pending = FALSE;
+    p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
+    bta_hl_cch_mca_close(app_idx, mcl_idx, p_data);
+}
+
+/*******************************************************************************
+**
 ** Function         bta_hl_cch_mca_rsp_tout
 **
 ** Description      Action routine for processing the MCAP response timeout
@@ -2464,6 +2501,7 @@
 
     bta_hl_check_cch_close(app_idx,mcl_idx,p_data,TRUE);
 }
+
 /*******************************************************************************
 **
 ** Function         bta_hl_cch_mca_connect
@@ -2482,7 +2520,7 @@
     BOOLEAN             send_event=TRUE;
 
 #if BTA_HL_DEBUG == TRUE
-    APPL_TRACE_DEBUG0("bta_hl_cch_mca_connect");
+    APPL_TRACE_DEBUG1("bta_hl_cch_mca_connect mcl_handle=%d ", p_data->mca_evt.mcl_handle);
 #endif
 
     p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
@@ -2596,7 +2634,7 @@
             break;
     }
 
-    if ((p_msg = (tBTA_HL_MCA_EVT *)GKI_getbuf(sizeof(tBTA_HL_MCA_EVT))) != NULL)
+    if (send_event && ((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;
@@ -2606,7 +2644,6 @@
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         bta_hl_mcap_data_cback
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
index 648eb2c..30a3f94 100644
--- a/bta/hl/bta_hl_int.h
+++ b/bta/hl/bta_hl_int.h
@@ -485,6 +485,7 @@
     UINT8                   sdp_mdl_idx;
     tBTA_HL_SDP             sdp;
     UINT8                   cch_oper;
+    UINT8                   force_close_local_cch_opening;
     BOOLEAN                 intentional_close;
     BOOLEAN                 rsp_tout;
     UINT8                   timer_oper;
@@ -667,6 +668,7 @@
     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_disc_open(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);
 
diff --git a/bta/hl/bta_hl_main.c b/bta/hl/bta_hl_main.c
index afac4c3..cbc83ef 100644
--- a/bta/hl/bta_hl_main.c
+++ b/bta/hl/bta_hl_main.c
@@ -300,6 +300,7 @@
     BTA_HL_CCH_MCA_CONNECT,
     BTA_HL_CCH_MCA_DISCONNECT,
     BTA_HL_CCH_MCA_RSP_TOUT,
+    BTA_HL_CCH_MCA_DISC_OPEN,
     BTA_HL_CCH_IGNORE
 };
 
@@ -315,7 +316,8 @@
     bta_hl_cch_close_cmpl,
     bta_hl_cch_mca_connect,
     bta_hl_cch_mca_disconnect,
-    bta_hl_cch_mca_rsp_tout
+    bta_hl_cch_mca_rsp_tout,
+    bta_hl_cch_mca_disc_open
 };
 
 
@@ -374,7 +376,7 @@
 /* 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_CONNECT_IND_EVT    */ {BTA_HL_CCH_MCA_DISC_OPEN,  BTA_HL_CCH_CLOSING_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},
@@ -601,9 +603,10 @@
 {
     tBTA_HL         evt_data;
     UINT8           app_idx;
-    tBTA_HL_APP_CB  *p_acb;
+    tBTA_HL_APP_CB  *p_acb = NULL;
     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))
@@ -641,7 +644,8 @@
         if ((status != BTA_HL_STATUS_DUPLICATE_APP_ID) &&
             (status != BTA_HL_STATUS_NO_RESOURCE))
         {
-            memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
+            if (p_acb)
+                memset(p_acb, 0, sizeof(tBTA_HL_APP_CB));
         }
     }
 #if BTA_HL_DEBUG == TRUE
@@ -651,9 +655,11 @@
     }
 #endif
 
+    memset(&evt_data, 0, sizeof(tBTA_HL));
     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 (status == BTA_HL_STATUS_OK)
+        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);
@@ -697,7 +703,7 @@
     }
     else
     {
-        APPL_TRACE_ERROR1("Inavlide app_handle=%d", p_data->api_dereg.app_handle);
+        APPL_TRACE_ERROR1("Invalid app_handle=%d", p_data->api_dereg.app_handle);
     }
 }
 
@@ -760,12 +766,20 @@
             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 );
+            if (p_acb->p_cback)
+            {
+                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->p_cback(BTA_HL_CCH_OPEN_CFM_EVT,(tBTA_HL *) &evt_data );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_cch_open Null Callback");
+            }
             break;
         default:
             APPL_TRACE_ERROR1("status code=%d", status);
@@ -811,13 +825,20 @@
             bta_hl_check_cch_close(app_idx, mcl_idx, p_data, TRUE);
             break;
 
-        case BTA_HL_STATUS_FAIL:
+        case BTA_HL_STATUS_INVALID_MCL_HANDLE:
             p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-            bta_hl_build_cch_close_cfm(&evt_data,
+            if (p_acb->p_cback)
+            {
+                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 );
+                p_acb->p_cback(BTA_HL_CCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_cch_close Null Callback");
+            }
             break;
 
         default:
@@ -958,12 +979,20 @@
         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 );
+            if (p_acb->p_cback)
+            {
+                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 );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_dch_open Null Callback");
+            }
+
             break;
         default:
             APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1018,14 +1047,21 @@
             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);
+            if (p_acb->p_cback)
+            {
+                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 );
+                p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT,(tBTA_HL *) &evt_data );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_dch_close Null Callback");
+            }
             break;
         default:
             APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1053,8 +1089,9 @@
     tBTA_HL_MDL_CB  *p_dcb;
     UINT8           mdep_cfg_idx;
     UINT8           mdl_cfg_idx;
+    tBTA_HL_MDEP_CFG            *p_mdep_cfg;
 
-    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_open.mcl_handle, &app_idx, &mcl_idx))
+    if (bta_hl_find_mcl_idx_using_handle(p_data->api_dch_reconnect.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);
@@ -1085,6 +1122,20 @@
                             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;
+
+                           p_mdep_cfg = BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx);
+
+                            if (p_mdep_cfg->mdep_role == BTA_HL_MDEP_ROLE_SINK)
+                            {
+                                p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SOURCE;
+                                  APPL_TRACE_DEBUG0("peer mdep role = SOURCE ");
+							}
+                            else
+                            {
+                                p_dcb->peer_mdep_role = BTA_HL_MDEP_ROLE_SINK;
+                                APPL_TRACE_DEBUG0("peer mdep role = SINK ");
+                            }
+
                             bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
                                                        &p_dcb->max_rx_apdu_size,
                                                        &p_dcb->max_tx_apdu_size);
@@ -1139,12 +1190,19 @@
         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 );
+            if (p_acb->p_cback)
+            {
+                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 );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_dch_reconnect Null Callback");
+            }
             break;
         default:
             APPL_TRACE_ERROR1("Status code=%d", status);
@@ -1260,15 +1318,22 @@
                 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 );
+            p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
+            if (p_acb->p_cback)
+            {
+                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 );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_dch_echo_test Null Callback");
+            }
             break;
 
         default:
@@ -1350,13 +1415,20 @@
         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 );
+            if (p_acb->p_cback)
+            {
+                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->p_cback(BTA_HL_SDP_QUERY_CFM_EVT,(tBTA_HL *) &evt_data );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_sdp_query Null Callback");
+            }
             break;
         case BTA_HL_STATUS_OK:
             break;
@@ -1515,15 +1587,20 @@
         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 );
+            if (p_acb->p_cback)
+            {
+                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 );
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_delete_mdl Null Callback");
+            }
             break;
-        case BTA_HL_STATUS_INVALID_APP_HANDLE:
         default:
             APPL_TRACE_ERROR1("status code =%d", status);
             break;
@@ -1591,13 +1668,21 @@
     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);
+        if (p_acb->p_cback)
+        {
+            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 );
+            p_acb->p_cback(BTA_HL_DELETE_MDL_CFM_EVT,(tBTA_HL *) &evt_data );
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("bta_hl_mca_delete_mdl_cfm Null Callback");
+
+        }
     }
 }
 
@@ -1647,10 +1732,17 @@
     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 );
+        if (p_acb->p_cback)
+        {
+            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 );
+        }
+        else
+        {
+            APPL_TRACE_ERROR0("bta_hl_mca_delete_mdl_ind Null Callback");
+        }
     }
 }
 
@@ -1718,16 +1810,24 @@
         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 );
+            if (p_acb->p_cback)
+            {
+                p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_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);
+            }
+            else
+            {
+                APPL_TRACE_ERROR0("bta_hl_api_dch_abort Null Callback");
+            }
             break;
-        case BTA_HL_STATUS_INVALID_BD_ADDR:
-        case BTA_HL_STATUS_INVALID_APP_HANDLE:
         default:
             APPL_TRACE_ERROR1("Status code=%d", status);
             break;
diff --git a/bta/hl/bta_hl_sdp.c b/bta/hl/bta_hl_sdp.c
index 15620e8..45af7be 100644
--- a/bta/hl/bta_hl_sdp.c
+++ b/bta/hl/bta_hl_sdp.c
@@ -310,7 +310,7 @@
                 }
 
                 cnt++;
-                if (cnt>BTA_HL_NUM_SUP_FEATURE_ELEMS)
+                if (cnt==BTA_HL_NUM_SUP_FEATURE_ELEMS)
                 {
                     result = FALSE;
                     break;
diff --git a/bta/hl/bta_hl_utils.c b/bta/hl/bta_hl_utils.c
index 7f94a9c..5fab7fd 100644
--- a/bta/hl/bta_hl_utils.c
+++ b/bta/hl/bta_hl_utils.c
@@ -520,7 +520,7 @@
 {
     BOOLEAN found = FALSE;
     tBTA_HL_MCL_CB      *p_mcb;
-    UINT8               app_idx, mcl_idx;
+    UINT8               app_idx = 0, mcl_idx = 0;
 
     switch (p_msg->hdr.event)
     {
@@ -567,7 +567,7 @@
             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)
+                if ((p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE) && (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN) )
                 {
                     p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_CLOSE;
                 }
@@ -584,7 +584,7 @@
             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)
+                if ((p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE) && (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN))
                 {
                     p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
                 }
@@ -629,7 +629,7 @@
 {
     BOOLEAN         found = FALSE;
     tBTA_HL_MCL_CB  *p_mcb;
-    UINT8           app_idx, mcl_idx, mdl_idx;
+    UINT8           app_idx = 0, mcl_idx = 0, mdl_idx = 0;
 
     switch (p_msg->hdr.event)
     {
@@ -1124,7 +1124,7 @@
 {
     tBTA_HL_APP_CB  *p_acb;
     BOOLEAN         found=FALSE;
-    UINT8 i,j;
+    UINT8 i = 0,j = 0;
 
     for (i=0; i<BTA_HL_NUM_APPS; i++)
     {
@@ -1959,7 +1959,7 @@
     BOOLEAN local_mdep_id_found =FALSE;
     BOOLEAN mdl_cfg_found =FALSE;
     BOOLEAN            status=FALSE;
-    UINT8 i, in_use_mdl_idx;
+    UINT8 i, in_use_mdl_idx = 0;
 
 #if BTA_HL_DEBUG == TRUE
     APPL_TRACE_DEBUG1("bta_hl_validate_reconnect_params  mdl_id=%d", p_reconnect->mdl_id);
@@ -2358,7 +2358,7 @@
     tBTA_HL_MDL_CFG mdl_cfg;
     tBTA_HL_MDEP *p_mdep_cfg;
     tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
-    UINT8 time_val;
+    UINT8 time_val = 0;
     mdl_id = p_dcb->mdl_id;
     if (!bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx))
     {
@@ -2581,12 +2581,14 @@
     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;
+    UINT8 mdl_cfg_idx = 0;
     tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
+    BOOLEAN get_l2cap_result, get_mdl_result;
 
+    get_l2cap_result = bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
+    get_mdl_result = bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx);
 
-    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 (get_l2cap_result && get_mdl_result)
     {
         if ((p_acb->mdl_cfg[mdl_cfg_idx].mtu <= l2cap_cfg.mtu) &&
             (p_acb->mdl_cfg[mdl_cfg_idx].fcs == l2cap_cfg.fcs) &&
@@ -2632,7 +2634,7 @@
 
 {
     tBTA_HL_MDL_CB      *p_dcb;
-    UINT8   app_idx, mcl_idx, mdl_idx;
+    UINT8   app_idx = 0, mcl_idx, mdl_idx;
     BOOLEAN cong_status = TRUE;
 
     if (bta_hl_find_app_idx(app_id, &app_idx))
@@ -2766,7 +2768,10 @@
             p_mcb  = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
             if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE)
             {
+                if (p_mcb->cch_state == BTA_HL_CCH_OPENING_ST)
+                    p_mcb->force_close_local_cch_opening = TRUE;
                 p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
+                APPL_TRACE_DEBUG1("p_mcb->force_close_local_cch_opening=%d", p_mcb->force_close_local_cch_opening  );
                 bta_hl_check_cch_close(app_idx,mcl_idx,p_data, TRUE);
             }
         }
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 81dff39..042e487 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -182,14 +182,20 @@
 #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 --
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_DISCOVERABLE        BTM_BLE_NON_DISCOVERABLE        /* Device is not LE discoverable */
+#define BTA_DM_BLE_GENERAL_DISCOVERABLE    BTM_BLE_GENERAL_DISCOVERABLE    /* Device is LE General discoverable */
+#define BTA_DM_BLE_LIMITED_DISCOVERABLE    BTM_BLE_LIMITED_DISCOVERABLE    /* Device is LE Limited discoverable */
+#endif
+typedef UINT16 tBTA_DM_DISC;        /* this discoverability mode is a bit mask among BR mode and LE mode */
 
 /* Connectable Modes */
 #define BTA_DM_NON_CONN         BTM_NON_CONNECTABLE         /* Device is not connectable. */
 #define BTA_DM_CONN             BTM_CONNECTABLE             /* Device is connectable. */
+#if ((defined BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+#define BTA_DM_BLE_NON_CONNECTABLE      BTM_BLE_NON_CONNECTABLE     /* Device is LE non-connectable. */
+#define BTA_DM_BLE_CONNECTABLE          BTM_BLE_CONNECTABLE         /* Device is LE connectable. */
+#endif
 
 // btla-specific ++
 typedef UINT16 tBTA_DM_CONN;
@@ -204,6 +210,7 @@
 #define BTA_DM_CONN_PAIRED      1
 
 /* Inquiry Modes */
+#define BTA_DM_INQUIRY_NONE		BTM_INQUIRY_NONE            /*No BR inquiry. */
 #define BTA_DM_GENERAL_INQUIRY  BTM_GENERAL_INQUIRY         /* Perform general inquiry. */
 #define BTA_DM_LIMITED_INQUIRY  BTM_LIMITED_INQUIRY         /* Perform limited inquiry. */
 
@@ -291,6 +298,8 @@
     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 */
+    UINT8   bta_dm_eir_additional_len;      /* length of additional data in bytes */
+    UINT8  *bta_dm_eir_additional;          /* additional data */
 } tBTA_DM_EIR_CONF;
 
 #if BLE_INCLUDED == TRUE
@@ -302,16 +311,22 @@
 #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
+/* ADV data bit 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_INT_RANGE       BTM_BLE_AD_BIT_INT_RANGE
+#define BTA_BLE_AD_BIT_SERVICE         BTM_BLE_AD_BIT_SERVICE
+#define BTA_BLE_AD_BIT_APPEARANCE      BTM_BLE_AD_BIT_APPEARANCE
+#define BTA_BLE_AD_BIT_PROPRIETARY     BTM_BLE_AD_BIT_PROPRIETARY
+#define BTA_DM_BLE_AD_BIT_SERVICE_SOL     BTM_BLE_AD_BIT_SERVICE_SOL
+#define BTA_DM_BLE_AD_BIT_SERVICE_DATA    BTM_BLE_AD_BIT_SERVICE_DATA
+#define BTA_DM_BLE_AD_BIT_SIGN_DATA       BTM_BLE_AD_BIT_SIGN_DATA
+#define BTA_DM_BLE_AD_BIT_SERVICE_128SOL  BTM_BLE_AD_BIT_SERVICE_128SOL
+#define BTA_DM_BLE_AD_BIT_PUBLIC_ADDR     BTM_BLE_AD_BIT_PUBLIC_ADDR
+#define BTA_DM_BLE_AD_BIT_RANDOM_ADDR     BTM_BLE_AD_BIT_RANDOM_ADDR
+
 typedef  UINT16  tBTA_BLE_AD_MASK;
 
 /* slave preferred connection interval range */
@@ -330,22 +345,6 @@
     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
 {
@@ -355,11 +354,27 @@
 
 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;
+    UINT8       adv_type;
+    UINT8       len;
+    UINT8       *p_val;     /* number of len byte */
+}tBTA_BLE_PROP_ELEM;
+
+/* vendor proprietary adv type */
+typedef struct
+{
+    UINT8                   num_elem;
+    tBTA_BLE_PROP_ELEM      *p_elem;
+}tBTA_BLE_PROPRIETARY;
+
+typedef struct
+{
+    tBTA_BLE_MANU			manu;			/* manufactuer data */
+    tBTA_BLE_INT_RANGE		int_range;      /* slave prefered conn interval range */
+    tBTA_BLE_SERVICE		services;       /* services */
+	UINT16					appearance;		/* appearance data */
+    UINT8					flag;
+    tBTA_BLE_PROPRIETARY    *p_proprietary;
+
 }tBTA_BLE_ADV_DATA;
 
 /* These are the fields returned in each device adv packet.  It
@@ -373,11 +388,84 @@
     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
 
+/* BLE customer specific feature function type definitions */
+/* data type used on customer specific feature for RSSI monitoring */
+#define BTA_BLE_RSSI_ALERT_HI        0
+#define BTA_BLE_RSSI_ALERT_RANGE     1
+#define BTA_BLE_RSSI_ALERT_LO        2
+typedef UINT8 tBTA_DM_BLE_RSSI_ALERT_TYPE;
+
+#define BTA_BLE_RSSI_ALERT_NONE		    BTM_BLE_RSSI_ALERT_NONE		/*	(0) */
+#define BTA_BLE_RSSI_ALERT_HI_BIT		BTM_BLE_RSSI_ALERT_HI_BIT		/*	(1) */
+#define BTA_BLE_RSSI_ALERT_RANGE_BIT	BTM_BLE_RSSI_ALERT_RANGE_BIT	/*	(1 << 1) */
+#define BTA_BLE_RSSI_ALERT_LO_BIT		BTM_BLE_RSSI_ALERT_LO_BIT		/*	(1 << 2) */
+typedef UINT8     tBTA_DM_BLE_RSSI_ALERT_MASK;
+
+
+typedef void (tBTA_DM_BLE_RSSI_CBACK) (BD_ADDR bd_addr, tBTA_DM_BLE_RSSI_ALERT_TYPE alert_type, INT8 rssi);
+
+/* max number of filter spot for different filter type */
+#define BTA_DM_BLE_MAX_UUID_FILTER     BTM_BLE_MAX_UUID_FILTER    /* 8 */
+#define BTA_DM_BLE_MAX_ADDR_FILTER     BTM_BLE_MAX_ADDR_FILTER    /* 8 */
+#define BTA_DM_BLE_PF_STR_COND_MAX     BTM_BLE_PF_STR_COND_MAX    /* 4    apply to manu data , or local name */
+#define BTA_DM_BLE_PF_STR_LEN_MAX      BTM_BLE_PF_STR_LEN_MAX  /* match for first 20 bytes */
+
+#define BTA_DM_BLE_PF_LOGIC_OR              0
+#define BTA_DM_BLE_PF_LOGIC_AND             1
+typedef UINT8 tBTA_DM_BLE_PF_LOGIC_TYPE;
+
+enum
+{
+    BTA_DM_BLE_SCAN_COND_ADD,
+    BTA_DM_BLE_SCAN_COND_DELETE,
+    BTA_DM_BLE_SCAN_COND_CLEAR = 2
+};
+typedef UINT8 tBTA_DM_BLE_SCAN_COND_OP;
+
+/* filter selection bit index  */
+#define BTA_DM_BLE_PF_ADDR_FILTER          BTM_BLE_PF_ADDR_FILTER
+#define BTA_DM_BLE_PF_SRVC_UUID            BTM_BLE_PF_SRVC_UUID
+#define BTA_DM_BLE_PF_SRVC_SOL_UUID        BTM_BLE_PF_SRVC_SOL_UUID
+#define BTA_DM_BLE_PF_LOCAL_NAME           BTM_BLE_PF_LOCAL_NAME
+#define BTA_DM_BLE_PF_MANU_DATA            BTM_BLE_PF_MANU_DATA
+#define BTA_DM_BLE_PF_SRVC_DATA            BTM_BLE_PF_SRVC_DATA
+#define BTA_DM_BLE_PF_TYPE_MAX             BTM_BLE_PF_TYPE_MAX
+typedef UINT8   tBTA_DM_BLE_PF_COND_TYPE;
+
+typedef struct
+{
+    tBLE_BD_ADDR                *p_target_addr;     /* target address, if NULL, generic UUID filter */
+    tBT_UUID                    uuid;           /* UUID condition */
+    tBTA_DM_BLE_PF_LOGIC_TYPE   cond_logic;    /* AND/OR */
+}tBTA_DM_BLE_PF_UUID_COND;
+
+typedef struct
+{
+    UINT8                   data_len;       /* <= 20 bytes */
+    UINT8                   *p_data;
+}tBTA_DM_BLE_PF_LOCAL_NAME_COND;
+
+typedef struct
+{
+    UINT16                  company_id;     /* company ID */
+    UINT8                   data_len;       /* <= 20 bytes */
+    UINT8                   *p_pattern;
+}tBTA_DM_BLE_PF_MANU_COND;
+
+typedef union
+{
+    tBLE_BD_ADDR                            target_addr;
+    tBTA_DM_BLE_PF_LOCAL_NAME_COND             local_name; /* lcoal name filtering */
+    tBTA_DM_BLE_PF_MANU_COND                   manu_data;  /* manufactuer data filtering */
+    tBTA_DM_BLE_PF_UUID_COND                   srvc_uuid;  /* service UUID filtering */
+    tBTA_DM_BLE_PF_UUID_COND                   solicitate_uuid;   /* solicitated service UUID filtering */
+}tBTA_DM_BLE_PF_COND_PARAM;
+
+
 typedef INT8 tBTA_DM_RSSI_VALUE;
 typedef UINT8 tBTA_DM_LINK_QUALITY_VALUE;
 
@@ -430,8 +518,8 @@
 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 */
+    BD_NAME         bd_name;            /* Name of peer device. */
 } tBTA_DM_PIN_REQ;
 
 /* BLE related definition */
@@ -481,12 +569,13 @@
 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 tBTM_LE_PID_KEYS   tBTA_LE_PID_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_PID_KEYS    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;
@@ -538,6 +627,9 @@
     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. */
+#if BLE_INCLUDED == TRUE
+    BOOLEAN         privacy_enabled;    /* used for BLE device only */
+#endif
     UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
 
 } tBTA_DM_AUTH_CMPL;
@@ -565,6 +657,7 @@
 {
     BD_ADDR         bd_addr;            /* BD address peer device. */
     UINT8           status;             /* connection open/closed */
+    BOOLEAN         is_removed;         /* TRUE if device is removed when link is down */
 } tBTA_DM_LINK_DOWN;
 
 /* Structure associated with BTA_DM_ROLE_CHG_EVT */
@@ -589,6 +682,7 @@
 {
     UINT8           level;     /* when paging or inquiring, level is 10.
                                     Otherwise, the number of ACL links */
+    UINT8           level_flags; /* indicates individual flags */
 } tBTA_DM_BUSY_LEVEL;
 
 #define BTA_IO_CAP_OUT      BTM_IO_CAP_OUT      /* DisplayOnly */
@@ -630,6 +724,7 @@
 /* Structure associated with BTA_DM_SP_CFM_REQ_EVT */
 typedef struct
 {
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
     BD_ADDR         bd_addr;        /* peer address */
     DEV_CLASS       dev_class;      /* peer CoD */
     BD_NAME         bd_name;        /* peer device name */
@@ -661,6 +756,7 @@
 /* Structure associated with BTA_DM_SP_KEY_NOTIF_EVT */
 typedef struct
 {
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
     BD_ADDR         bd_addr;        /* peer address */
     DEV_CLASS       dev_class;      /* peer CoD */
     BD_NAME         bd_name;        /* peer device name */
@@ -670,6 +766,7 @@
 /* Structure associated with BTA_DM_SP_RMT_OOB_EVT */
 typedef struct
 {
+    /* Note: First 3 data members must be, bd_addr, dev_class, and bd_name in order */
     BD_ADDR         bd_addr;        /* peer address */
     DEV_CLASS       dev_class;      /* peer CoD */
     BD_NAME         bd_name;        /* peer device name */
@@ -845,7 +942,8 @@
 
 /* index to bta_dm_ssr_spec */
 #define BTA_DM_PM_SSR0          0
-#define BTA_DM_PM_SSR1          1
+#define BTA_DM_PM_SSR1          1       /* BTA_DM_PM_SSR1 will be dedicated for
+                                        HH SSR setting entry, no other profile can use it */
 #define BTA_DM_PM_SSR2          2
 #define BTA_DM_PM_SSR3          3
 #define BTA_DM_PM_SSR4          4
@@ -1458,6 +1556,22 @@
 
 /*******************************************************************************
 **
+**
+** Function         BTA_DmCloseACL
+**
+** Description      This function force to close an ACL connection and remove the
+**                  device from the security database list of known devices.
+**
+** Parameters:      bd_addr       - Address of the peer device
+**                  remove_dev    - remove device or not after link down
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev);
+
+/*******************************************************************************
+**
 ** Function         BTA_SysFeatures
 **
 ** Description      This function is called to set system features.
@@ -1707,6 +1821,25 @@
 BTA_API extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_DM_ENCRYPT_CBACK *p_callback,
                             tBTA_DM_BLE_SEC_ACT sec_act);
 
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleObserve
+**
+** Description      This procedure keep the device listening for advertising
+**                  events from a broadcast device.
+**
+** Parameters       start: start or stop observe.
+**                  duration : Duration of the scan. Continuous scan if 0 is passed
+**                  p_results_cb: Callback to be called with scan results
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration,
+                                           tBTA_DM_SEARCH_CBACK *p_results_cb);
+
+
 #endif
 
 // btla-specific ++
@@ -1721,6 +1854,47 @@
 *******************************************************************************/
 BTA_API extern void BTA_DmSetAfhChannelAssessment (BOOLEAN enable_or_disable);
 // btla-specific --
+/*******************************************************************************
+**
+** Function         BTA_DmBleConfigLocalPrivacy
+**
+** Description      Enable/disable privacy on the local device
+**
+** Parameters:      privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleConfigLocalPrivacy(BOOLEAN privacy_enable);
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleEnableRemotePrivacy
+**
+** Description      Enable/disable privacy on a remote device
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  privacy_enable   - enable/disabe privacy on remote device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleEnableRemotePrivacy(BD_ADDR bd_addr, BOOLEAN privacy_enable);
+
+
+/*******************************************************************************
+**
+** Function         BTA_DmBleSetAdvConfig
+**
+** Description      This function is called to override the BTA default ADV parameters.
+**
+** Parameters       Pointer to User defined ADV data structure
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_DmBleSetAdvConfig (tBTA_BLE_AD_MASK data_mask,
+                                           tBTA_BLE_ADV_DATA *p_adv_cfg);
 
 #ifdef __cplusplus
 }
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index eb77279..1ea570c 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -47,6 +47,7 @@
 #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 */
+#define BTA_AV_FAIL_GET_CAP     6       /* get capability failed due to no SEP availale on the peer  */
 
 typedef UINT8 tBTA_AV_STATUS;
 
@@ -492,6 +493,8 @@
     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 */
+    char              avrc_controller_name[BTA_SERVICE_NAME_LEN]; /* Default AVRCP controller name */
+    char              avrc_target_name[BTA_SERVICE_NAME_LEN];     /* Default AVRCP target name*/
 } tBTA_AV_CFG;
 
 #ifdef __cplusplus
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 0404847..78bdf13 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2003-2012 Broadcom Corporation
+ *  Copyright (C) 2003-2013 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
  *  This is the public interface file for BTA GATT.
  *
  ******************************************************************************/
+
 #ifndef BTA_GATT_API_H
 #define BTA_GATT_API_H
 
@@ -53,7 +54,7 @@
 {
     tBT_UUID    uuid;           /* uuid of the attribute */
     UINT8       inst_id;        /* instance ID */
-} tBTA_GATT_ID;
+} __attribute__((packed)) tBTA_GATT_ID;
 
 /* Success code and error codes */
 #define  BTA_GATT_OK                        GATT_SUCCESS
@@ -90,6 +91,7 @@
 #define  BTA_GATT_INVALID_CFG               GATT_INVALID_CFG                   /* 0x008b */
 #define  BTA_GATT_DUP_REG                   0x008c
 #define  BTA_GATT_ALREADY_OPEN              0x008d                              /* 0x008d */
+#define  BTA_GATT_CANCEL                    0x008e                              /* 0x008e */
 typedef UINT8 tBTA_GATT_STATUS;
 
 #define BTA_GATT_INVALID_CONN_ID   GATT_INVALID_CONN_ID
@@ -110,8 +112,9 @@
 #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_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;
@@ -562,6 +565,19 @@
 
 /*******************************************************************************
 **
+** Function         BTA_GATTC_Init
+**
+** Description      This function is called to initalize GATTC module
+**
+** Parameters       None
+**
+** Returns          None
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Init();
+
+/*******************************************************************************
+**
 ** Function         BTA_GATTC_AppRegister
 **
 ** Description      This function is called to register application callbacks
@@ -968,11 +984,37 @@
                                            tBTA_GATT_AUTH_REQ auth_req);
 
 
+/*******************************************************************************
+**
+** Function         BTA_GATTC_Refresh
+**
+** Description      Refresh the server cache of the remote device
+**
+** Parameters       remote_bda: remote device BD address.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_GATTC_Refresh(BD_ADDR remote_bda);
 
 
 /*******************************************************************************
 **  BTA GATT Server API
 ********************************************************************************/
+
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Init
+**
+** Description      This function is called to initalize GATTS module
+**
+** Parameters       None
+**
+** Returns          None
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_Init();
+
 /*******************************************************************************
 **
 ** Function         BTA_GATTS_AppRegister
@@ -1208,6 +1250,24 @@
 *******************************************************************************/
     BTA_API extern void BTA_GATTS_Close(UINT16 conn_id);
 
+/*******************************************************************************
+**
+** Function         BTA_GATTS_Listen
+**
+** Description      Start advertisement to listen for connection request for a
+**                  GATT server
+**
+** Parameters       server_if: server interface.
+**                  start: to start or stop listening for connection
+**                  remote_bda: remote device BD address, if listen to all device
+**                              use NULL.
+**
+** Returns          void
+**
+*******************************************************************************/
+    BTA_API extern void BTA_GATTS_Listen(tBTA_GATTS_IF server_if, BOOLEAN start,
+                                        BD_ADDR_PTR target_bda);
+
 
 #ifdef __cplusplus
 
diff --git a/bta/include/bta_gattc_co.h b/bta/include/bta_gattc_co.h
index d2392b8..fa882ec 100644
--- a/bta/include/bta_gattc_co.h
+++ b/bta/include/bta_gattc_co.h
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2010-2012 Broadcom Corporation
+ *  Copyright (C) 2009-2013 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -97,5 +97,19 @@
 BTA_API extern void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt,
                                             UINT16 start_index, UINT16 conn_id);
 
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_reset
+**
+** Description      This callout function is executed by GATTC to reset cache in
+**                  application
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**
+** Returns          void.
+**
+*******************************************************************************/
+BTA_API extern void bta_gattc_co_cache_reset(BD_ADDR server_bda);
+
 #endif /* BTA_GATT_CO_H */
 
diff --git a/bta/include/bta_hh_api.h b/bta/include/bta_hh_api.h
index f613d30..2cd29f4 100644
--- a/bta/include/bta_hh_api.h
+++ b/bta/include/bta_hh_api.h
@@ -29,7 +29,7 @@
 #endif
 
 #ifndef BTA_HH_SSR_MAX_LATENCY_DEF
-#define BTA_HH_SSR_MAX_LATENCY_DEF  1600
+#define BTA_HH_SSR_MAX_LATENCY_DEF  800 /* 500 ms*/
 #endif
 
 #ifndef BTA_HH_SSR_MIN_TOUT_DEF
@@ -51,15 +51,28 @@
 #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 */
+#define BTA_HH_DATA_EVT         15
+#define BTA_HH_API_ERR_EVT      16      /* API error is caught */
 
 typedef UINT16 tBTA_HH_EVT;
 
+/* 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
+#define BTA_HH_APP_ID_JOY           5
+#define BTA_HH_APP_ID_GPAD          6
+#define BTA_HH_APP_ID_LE            0xff
+
 /* defined the minimum offset */
 #define BTA_HH_MIN_OFFSET       L2CAP_MIN_OFFSET+1
 
+/* HID_HOST_MAX_DEVICES can not exceed 15 for th design of BTA HH */
+#define BTA_HH_IDX_INVALID      0xff
 #define BTA_HH_MAX_KNOWN        HID_HOST_MAX_DEVICES
+#define BTA_HH_MAX_DEVICE       HID_HOST_MAX_DEVICES
+
 /* invalid device handle */
 #define BTA_HH_INVALID_HANDLE   0xff
 
@@ -107,7 +120,8 @@
     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
+    BTA_HH_ERR_HDL,
+    BTA_HH_ERR_SEC
 };
 typedef UINT8 tBTA_HH_STATUS;
 
@@ -162,6 +176,8 @@
 
 typedef tHID_DEV_DSCP_INFO tBTA_HH_DEV_DESCR;
 
+#define BTA_HH_SSR_PARAM_INVALID       HID_SSR_PARAM_INVALID
+
 /* 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
 
@@ -172,8 +188,8 @@
     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 */
+    UINT16              ssr_max_latency;    /* SSR max latency, BTA_HH_SSR_PARAM_INVALID if unknown */
+    UINT16              ssr_min_tout;       /* SSR min timeout, BTA_HH_SSR_PARAM_INVALID if unknown */
     UINT8               ctry_code;      /*Country Code.*/
     tBTA_HH_DEV_DESCR   descriptor;
 }tBTA_HH_DEV_DSCP_INFO;
@@ -291,7 +307,7 @@
 ** Returns          void
 **
 *******************************************************************************/
-BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, BOOLEAN ucd_enabled, tBTA_HH_CBACK *p_cback);
+BTA_API extern void BTA_HhEnable(tBTA_SEC sec_mask, tBTA_HH_CBACK *p_cback);
 
 /*******************************************************************************
 **
@@ -375,6 +391,28 @@
                                     UINT8 rpt_id, UINT16 buf_size);
 /*******************************************************************************
 **
+** 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 to HID device.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTA_API extern void BTA_HhGetIdle(UINT8 dev_handle);
+
+/*******************************************************************************
+**
 ** Function         BTA_HhSendCtrl
 **
 ** Description      Send HID_CONTROL request to a HID device.
@@ -455,6 +493,7 @@
 **
 *******************************************************************************/
 BTA_API extern void BTA_HhRemoveDev(UINT8 dev_handle );
+
 /*******************************************************************************
 **
 **              Parsing Utility Functions
@@ -472,6 +511,11 @@
 BTA_API extern void BTA_HhParseBootRpt(tBTA_HH_BOOT_RPT *p_data, UINT8 *p_report,
                                        UINT16 report_len);
 
+/* test commands */
+BTA_API extern void bta_hh_le_hid_read_rpt_clt_cfg(BD_ADDR bd_addr, UINT8 rpt_id);
+
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/btif/co/bta_dm_co.c b/btif/co/bta_dm_co.c
index 611af2d..a310a00 100644
--- a/btif/co/bta_dm_co.c
+++ b/btif/co/bta_dm_co.c
@@ -25,6 +25,12 @@
 #if (BTM_OOB_INCLUDED == TRUE)
 #include "btif_dm.h"
 #endif
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+#include "bte_appl.h"
+#endif
+
+tBTE_APPL_CFG bte_appl_cfg = { 0x5, 0x4, 0x7, 0x7, 0x10 };
+
 /*******************************************************************************
 **
 ** Function         bta_dm_co_get_compress_memory
@@ -352,9 +358,10 @@
 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)
 {
-    BTIF_TRACE_ERROR0("##################################");
-    BTIF_TRACE_ERROR0("bta_dm_co_ble_load_local_keys: TBD Load local keys if any are persisted");
-    BTIF_TRACE_ERROR0("##################################");
+    BTIF_TRACE_DEBUG0("##################################");
+    BTIF_TRACE_DEBUG0("bta_dm_co_ble_load_local_keys:  Load local keys if any are persisted");
+    BTIF_TRACE_DEBUG0("##################################");
+    btif_dm_get_ble_local_keys( p_key_mask, er, p_id_keys);
 }
 
 /*******************************************************************************
@@ -387,14 +394,10 @@
      * If the answer can not be obtained right away,
      * set *p_oob_data to BTA_OOB_UNKNOWN and call bta_dm_ci_io_req() when the answer is available */
 
-    /* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
-    BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_auth_req=%d ble_authereq=%d", *p_auth_req, bte_appl_cfg.ble_auth_req);
-    BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_io_cap=%d ble_io_cap=%d", *p_io_cap, bte_appl_cfg.ble_io_cap);
-    BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_init_key=%d ble_init_key=%d", *p_init_key, bte_appl_cfg.ble_init_key);
-    BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_resp_key=%d ble_resp_key=%d", *p_resp_key, bte_appl_cfg.ble_resp_key );
-    BTIF_TRACE_ERROR2("bta_dm_co_ble_io_req. p_max_key_size=%d ble_max_key_size=%d", *p_max_key_size, bte_appl_cfg.ble_max_key_size );
-
     *p_oob_data = FALSE;
+
+    /* *p_auth_req by default is FALSE for devices with NoInputNoOutput; TRUE for other devices. */
+
     if (bte_appl_cfg.ble_auth_req)
         *p_auth_req = bte_appl_cfg.ble_auth_req | (bte_appl_cfg.ble_auth_req & 0x04) | ((*p_auth_req) & 0x04);
 
@@ -407,9 +410,8 @@
     if (bte_appl_cfg.ble_resp_key<=7)
         *p_resp_key = bte_appl_cfg.ble_resp_key;
 
-    if (bte_appl_cfg.ble_max_key_size<=16)
+    if (bte_appl_cfg.ble_max_key_size > 7 && bte_appl_cfg.ble_max_key_size <= 16)
         *p_max_key_size = bte_appl_cfg.ble_max_key_size;
-
 }
 
 
diff --git a/btif/co/bta_gattc_co.c b/btif/co/bta_gattc_co.c
new file mode 100644
index 0000000..1a71d69
--- /dev/null
+++ b/btif/co/bta_gattc_co.c
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 "gki.h"
+#include "bta_gattc_co.h"
+#include "bta_gattc_ci.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+
+/*****************************************************************************
+**  Function Declarations
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_open(BD_ADDR server_bda, UINT16 evt, UINT16 conn_id, BOOLEAN to_save)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    /* open NV cache and send call in */
+    bta_gattc_ci_cache_open(server_bda, evt, status, 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
+**
+*******************************************************************************/
+void bta_gattc_co_cache_load(BD_ADDR server_bda, UINT16 evt, UINT16 start_index, UINT16 conn_id)
+{
+    UINT16              num_attr = 0;
+    tBTA_GATTC_NV_ATTR  attr[BTA_GATTC_NV_LOAD_MAX];
+    tBTA_GATT_STATUS    status = BTA_GATT_MORE;
+
+    bta_gattc_ci_cache_load(server_bda, evt, num_attr, attr, status, 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
+**
+*******************************************************************************/
+void bta_gattc_co_cache_save (BD_ADDR server_bda, UINT16 evt, UINT16 num_attr,
+                              tBTA_GATTC_NV_ATTR *p_attr_list, UINT16 attr_index, UINT16 conn_id)
+{
+    tBTA_GATT_STATUS    status = BTA_GATT_OK;
+
+    bta_gattc_ci_cache_save(server_bda, evt, status, conn_id);
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_close(BD_ADDR server_bda, UINT16 conn_id)
+{
+    /* close NV when server cache is done saving or loading,
+       does not need to do anything for now on Insight */
+}
+
+/*******************************************************************************
+**
+** Function         bta_gattc_co_cache_reset
+**
+** Description      This callout function is executed by GATTC to reset cache in
+**                  application
+**
+** Parameter        server_bda: server bd address of this cache belongs to
+**
+** Returns          void.
+**
+*******************************************************************************/
+void bta_gattc_co_cache_reset(BD_ADDR server_bda)
+{
+}
+
+#endif
+#endif
+
diff --git a/btif/co/bta_gatts_co.c b/btif/co/bta_gatts_co.c
new file mode 100644
index 0000000..725d145
--- /dev/null
+++ b/btif/co/bta_gatts_co.c
@@ -0,0 +1,243 @@
+/*****************************************************************************
+**
+**  Name:           bta_gattc_co.c
+**
+**  Description:    This file contains the GATT client call-out
+**                  function implementation for Insight.
+**
+**  Copyright (c) 2010, Broadcom Corp., All Rights Reserved.
+**  Broadcom Bluetooth Core. Proprietary and confidential.
+**
+*****************************************************************************/
+
+#include "bta_api.h"
+
+#if( defined BLE_INCLUDED ) && (BLE_INCLUDED == TRUE)
+#if( defined BTA_GATT_INCLUDED ) && (BTA_GATT_INCLUDED == TRUE)
+
+#include <stdlib.h>
+#include "gki.h"
+#include "bd.h"
+#include "bta_gatts_co.h"
+
+/*****************************************************************************
+**  Local type definitions
+*****************************************************************************/
+
+#define BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE 50
+
+typedef struct
+{
+    BOOLEAN             enable;
+    UINT8               num_clients;
+    tBTA_GATTS_SRV_CHG  srv_chg[BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE];
+} __attribute__((packed)) btif_gatts_srv_chg_cb_t;
+
+/*****************************************************************************
+**  Static variables
+*****************************************************************************/
+
+static btif_gatts_srv_chg_cb_t btif_gatts_srv_chg_cb;
+
+/*****************************************************************************
+**  Static functions
+*****************************************************************************/
+
+static void btif_gatts_check_init(void)
+{
+    btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+
+    if (!p_cb->enable)
+    {
+       memset(p_cb, 0, sizeof(btif_gatts_srv_chg_cb_t));
+       p_cb->enable = TRUE;
+    }
+}
+
+static BOOLEAN btif_gatts_srv_chg(tBTA_GATTS_SRV_CHG_CMD cmd,
+                                  tBTA_GATTS_SRV_CHG_REQ *p_req,
+                                  tBTA_GATTS_SRV_CHG_RSP *p_rsp)
+{
+    BOOLEAN status = TRUE;
+    BOOLEAN found = FALSE;
+    UINT8   i, j, idx, last_idx;
+    btif_gatts_srv_chg_cb_t *p_cb = &btif_gatts_srv_chg_cb;
+
+    btif_gatts_check_init();
+
+    switch (cmd)
+    {
+        case BTA_GATTS_SRV_CHG_CMD_ADD_CLIENT:
+
+            if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE)
+            {
+                memcpy(&p_cb->srv_chg[p_cb->num_clients], &p_req->srv_chg, sizeof(tBTA_GATTS_SRV_CHG));
+                p_cb->num_clients++;
+            } else {
+                status = FALSE;
+            }
+            break;
+
+        case BTA_GATTS_SRV_CHG_CMD_UPDATE_CLIENT:
+
+            for (i=0; i != p_cb->num_clients; ++i)
+            {
+                if (!memcmp(p_cb->srv_chg[i].bda, p_req->srv_chg.bda, sizeof(BD_ADDR)))
+                {
+                    found = TRUE;
+                    memcpy(&p_cb->srv_chg[i], &p_req->srv_chg, sizeof(tBTA_GATTS_SRV_CHG));
+                    break;
+                }
+            }
+
+            if (!found)
+                status = FALSE;
+            break;
+
+        case BTA_GATTS_SRV_CHG_CMD_REMOVE_CLIENT:
+
+            for (i=0; i != p_cb->num_clients; ++i)
+            {
+                if (!memcmp(p_cb->srv_chg[i].bda, p_req->srv_chg.bda, sizeof(BD_ADDR)))
+                {
+                    found = TRUE;
+                    last_idx = p_cb->num_clients - 1;
+
+                    if (i != last_idx )
+                    {
+                        /* Update the array so there is no gap */
+                        for (j=i; j != last_idx; ++j )
+                        {
+                            memcpy(&p_cb->srv_chg[j], &p_cb->srv_chg[j+1], sizeof(tBTA_GATTS_SRV_CHG));
+                        }
+
+                    }
+
+                    /* Reset the last client and update num_clients */
+                    memset(&p_cb->srv_chg[last_idx], 0, sizeof(tBTA_GATTS_SRV_CHG));
+                    p_cb->num_clients--;
+                    break;
+                }
+            }
+
+            if (!found)
+                status = FALSE;
+            break;
+
+        case BTA_GATTS_SRV_CHG_CMD_READ_NUM_CLENTS:
+            p_rsp->num_clients = p_cb->num_clients;
+            break;
+
+        case BTA_GATTS_SRV_CHG_CMD_READ_CLENT:
+            idx = p_req->client_read_index - 1;
+
+            if (idx < p_cb->num_clients )
+                memcpy(&p_rsp->srv_chg, &p_cb->srv_chg[idx], sizeof(tBTA_GATTS_SRV_CHG));
+            else
+                status = FALSE;
+            break;
+
+        default:
+            status = FALSE;
+            break;
+    }
+
+    return status;
+}
+
+/*****************************************************************************
+**  Externally called functions
+*****************************************************************************/
+
+void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda)
+{
+    btif_gatts_srv_chg_cb_t *p_cb= &btif_gatts_srv_chg_cb;
+    BOOLEAN                 found = FALSE;
+    UINT8                   i;
+
+    btif_gatts_check_init();
+
+    for (i=0; i != p_cb->num_clients; ++i)
+    {
+        if (!memcmp(p_cb->srv_chg[i].bda,  bda, sizeof(BD_ADDR)))
+        {
+            found = TRUE;
+            break;
+        }
+    }
+
+    if (!found)
+    {
+        if (p_cb->num_clients < BTIF_GATTS_MAX_SRV_CHG_CLT_SIZE)
+        {
+            bdcpy(p_cb->srv_chg[p_cb->num_clients].bda, bda);
+            p_cb->srv_chg[p_cb->num_clients].srv_changed = FALSE;
+            p_cb->num_clients++;
+        }
+    }
+}
+
+/*****************************************************************************
+**  Call-out functions
+*****************************************************************************/
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+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
+**
+*******************************************************************************/
+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)
+{
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** 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.
+**
+*******************************************************************************/
+BOOLEAN bta_gatts_co_load_handle_range(UINT8 index,
+                                       tBTA_GATTS_HNDL_RANGE *p_handle_range)
+{
+   return FALSE;
+}
+#endif
+#endif
diff --git a/btif/co/bta_hh_co.c b/btif/co/bta_hh_co.c
index b4ea4c2..e7f9be2 100644
--- a/btif/co/bta_hh_co.c
+++ b/btif/co/bta_hh_co.c
@@ -61,7 +61,10 @@
     ssize_t ret;
     memset(&ev, 0, sizeof(ev));
     if(!p_dev)
+    {
         APPL_TRACE_ERROR1("%s: Device not found",__FUNCTION__)
+        return -1;
+    }
     ret = read(p_dev->fd, &ev, sizeof(ev));
     if (ret == 0) {
         APPL_TRACE_ERROR2("%s: Read HUP on uhid-cdev %s", __FUNCTION__,
@@ -91,7 +94,6 @@
         APPL_TRACE_DEBUG0("UHID_CLOSE from uhid-dev\n");
         break;
     case UHID_OUTPUT:
-        APPL_TRACE_DEBUG0("UHID_OUTPUT from uhid-dev\n");
         APPL_TRACE_DEBUG2("UHID_OUTPUT: Report type = %d, report_size = %d"
                             ,ev.u.output.rtype, ev.u.output.size);
         //Send SET_REPORT with feature report if the report type in output event is FEATURE
@@ -331,8 +333,9 @@
         p_dev = &btif_hh_cb.devices[i];
         if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN && p_dev->dev_handle == dev_handle) {
             APPL_TRACE_WARNING3("%s: Found an existing device with the same handle "
-                                                                "dev_status = %d, dev_handle =%d",__FUNCTION__,
-                                                                p_dev->dev_status,p_dev->dev_handle);
+                                                        "dev_status = %d, dev_handle =%d"
+                                                        ,__FUNCTION__,p_dev->dev_status
+                                                        ,p_dev->dev_handle);
             btif_hh_close_poll_thread(p_dev);
             break;
         }
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index c787bec..19af505 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -325,4 +325,14 @@
 *******************************************************************************/
 bt_status_t btif_dut_mode_send(uint16_t opcode, uint8_t *buf, uint8_t len);
 
+/*******************************************************************************
+**
+** Function         btif_le_test_mode
+**
+** Description     Sends a HCI BLE Test command to the Controller
+**
+** Returns          BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_le_test_mode(uint16_t opcode, uint8_t *buf, uint8_t len);
 #endif /* BTIF_API_H */
diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h
index 6bf885f..f11b629 100644
--- a/btif/include/btif_common.h
+++ b/btif/include/btif_common.h
@@ -107,6 +107,9 @@
     BTIF_DM_CB_REMOVE_BOND,   /*Remove bond */
     BTIF_DM_CB_HID_REMOTE_NAME,   /* Remote name callback for HID device */
     BTIF_DM_CB_BOND_STATE_BONDING,
+    BTIF_DM_CB_LE_TX_TEST,    /* BLE Tx Test command complete callback */
+    BTIF_DM_CB_LE_RX_TEST,    /* BLE Rx Test command complete callback */
+    BTIF_DM_CB_LE_TEST_END,   /* BLE Test mode end callback */
 
     BTIF_HFP_CB_START  = BTIF_SIG_CB_START(BTIF_HFP),
     BTIF_HFP_CB_AUDIO_CONNECTING, /* HF AUDIO connect has been sent to BTA successfully */
diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h
index 2d73c45..ed03e34 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -19,7 +19,8 @@
 #ifndef BTIF_DM_H
 #define BTIF_DM_H
 
-/*******************************************************************************
+#include "bta_api.h"
+/************************************************************************************
 **  Functions
 ********************************************************************************/
 
@@ -45,5 +46,75 @@
 BOOLEAN btif_dm_proc_rmt_oob(BD_ADDR bd_addr,  BT_OCTET16 p_c, BT_OCTET16 p_r);
 #endif /* BTIF_DM_OOB_TEST */
 #endif /* BTM_OOB_INCLUDED */
+#if (BLE_INCLUDED == TRUE)
+
+typedef struct
+{
+    UINT8       ltk[BT_OCTET16_LEN];
+    UINT8       rand[BT_OCTET8_LEN];
+    UINT16      ediv;
+    UINT8       sec_level;
+    UINT8       key_size;
+}btif_dm_ble_penc_keys_t;
+
+typedef struct
+{
+    UINT32          counter;
+    UINT8           csrk[BT_OCTET16_LEN];
+    UINT8           sec_level;
+}btif_dm_ble_pcsrk_keys_t;
+
+typedef struct
+{
+    UINT16      div;
+    UINT8       key_size;
+    UINT8       sec_level;
+}btif_dm_ble_lenc_keys_t;
+
+typedef struct
+{
+    UINT32          counter;
+    UINT16          div;
+    UINT8           sec_level;
+
+}btif_dm_ble_lcsrk_keys_t;
+
+typedef struct
+{
+    BOOLEAN                   is_penc_key_rcvd;
+    btif_dm_ble_penc_keys_t   penc_key;       /* received peer encryption key */
+    BOOLEAN                   is_pcsrk_key_rcvd;
+    btif_dm_ble_pcsrk_keys_t  pcsrk_key;       /* received peer device SRK */
+    BOOLEAN                   is_pid_key_rcvd;
+    UINT8                     pid_key[BT_OCTET16_LEN];        /* peer device ID key */
+    BOOLEAN                   is_lenc_key_rcvd;
+    btif_dm_ble_lenc_keys_t   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
+    BOOLEAN                   is_lcsrk_key_rcvd;
+    btif_dm_ble_lcsrk_keys_t  lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
+} btif_dm_ble_cb_t;
+
+#define BTIF_DM_LE_KEY_PENC        BTA_LE_KEY_PENC
+#define BTIF_DM_LE_KEY_PID         BTA_LE_KEY_PID
+#define BTIF_DM_LE_KEY_PCSRK       BTA_LE_KEY_PCSRK
+#define BTIF_DM_LE_KEY_LENC        BTA_LE_KEY_LENC
+#define BTIF_DM_LE_KEY_LID         BTA_LE_KEY_LID
+#define BTIF_DM_LE_KEY_LCSRK       BTA_LE_KEY_LCSRK
+
+#define BTIF_DM_LE_LOCAL_KEY_IR       (1<<0)
+#define BTIF_DM_LE_LOCAL_KEY_IRK      (1<<1)
+#define BTIF_DM_LE_LOCAL_KEY_DHK      (1<<2)
+#define BTIF_DM_LE_LOCAL_KEY_ER       (1<<3)
+
+void btif_dm_load_ble_local_keys(void);
+void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+                                   tBTA_BLE_LOCAL_ID_KEYS *p_id_keys);
+void btif_dm_save_ble_bonding_keys(void);
+void btif_dm_remove_ble_bonding_keys(void);
+void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ *p_ble_req);
+
+void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
+                                           tBT_DEVICE_TYPE dev_type);
+
+#endif /* BLE_INCLUDED */
 
 #endif
diff --git a/btif/include/btif_gatt.h b/btif/include/btif_gatt.h
new file mode 100644
index 0000000..e71ba1e
--- /dev/null
+++ b/btif/include/btif_gatt.h
@@ -0,0 +1,34 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+
+/*****************************************************************************
+**
+**  Name:          btif_gatt.h
+**
+**  Description:
+**
+******************************************************************************/
+
+#ifndef BTIF_GATT_H
+#define BTIF_GATT_H
+
+
+
+#endif
+
diff --git a/btif/include/btif_gatt_util.h b/btif/include/btif_gatt_util.h
new file mode 100644
index 0000000..37fe501
--- /dev/null
+++ b/btif/include/btif_gatt_util.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 BTIF_GATT_UTIL_H
+#define BTIF_GATT_UTIL_H
+
+void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src);
+void btif_to_bta_char_id(tBTA_GATT_ID *p_dest, btgatt_char_id_t *p_src);
+void btif_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, btgatt_srvc_id_t *p_src);
+void btif_to_bta_response(tBTA_GATTS_RSP *p_dest, btgatt_response_t* p_src);
+
+void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src);
+void bta_to_btif_srvc_id(btgatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src);
+void bta_to_btif_char_id(btgatt_char_id_t *p_dest, tBTA_GATT_ID *p_src);
+
+uint16_t set_read_value(btgatt_read_params_t *p_dest, tBTA_GATTC_READ *p_src);
+
+void btif_gatt_check_encrypted_link(BD_ADDR bd_addr);
+void btif_gatt_remove_encrypted_link(BD_ADDR bd_addr);
+
+
+#endif
+
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index 25063eb..c77d597 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -96,6 +96,7 @@
 
 extern btif_hh_device_t *btif_hh_find_connected_dev_by_handle(UINT8 handle);
 extern void btif_hh_remove_device(bt_bdaddr_t bd_addr);
+BOOLEAN btif_hh_add_added_dev(bt_bdaddr_t bda, tBTA_HH_ATTR_MASK attr_mask);
 extern bt_status_t btif_hh_virtual_unplug(bt_bdaddr_t *bd_addr);
 extern void btif_hh_disconnect(bt_bdaddr_t *bd_addr);
 extern void btif_hh_setreport(btif_hh_device_t *p_dev, bthh_report_type_t r_type,
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 87dec3b..41507fb 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -105,7 +105,7 @@
 **                  BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
-bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr,
+bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bd_addr,
                                            uint32_t num_properties,
                                            bt_property_t *properties);
 
@@ -231,19 +231,19 @@
 **                  BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
+
 bt_status_t btif_storage_add_hid_device_info(bt_bdaddr_t *remote_bd_addr,
                                                     UINT16 attr_mask, UINT8 sub_class,
                                                     UINT8 app_id, UINT16 vendor_id,
                                                     UINT16 product_id, UINT16 version,
-                                                    UINT8 ctry_code, UINT16 dl_len,
-                                                    UINT8 *dsc_list);
+                                                    UINT8 ctry_code, UINT16 dl_len, UINT8 *dsc_list);
 
 /*******************************************************************************
 **
 ** Function         btif_storage_load_bonded_hid_info
 **
-** Description      BTIF storage API - Loads hid info for all the bonded devices
-**                  from NVRAM and adds those devices  to the BTA_HH.
+** Description      BTIF storage API - Loads hid info for all the bonded devices from NVRAM
+**                  and adds those devices  to the BTA_HH.
 **
 ** Returns          BT_STATUS_SUCCESS if successful, BT_STATUS_FAIL otherwise
 **
@@ -284,7 +284,8 @@
 **                  FALSE otherwise
 **
 *******************************************************************************/
-BOOLEAN  btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_addr);
+
+BOOLEAN  btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_bd_addr);
 
 /*******************************************************************************
 **
@@ -296,7 +297,8 @@
 **                  BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
-bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_dev_addr);
+
+bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_bd_addr);
 
 /*******************************************************************************
 **
@@ -308,6 +310,45 @@
 **                  FALSE otherwise
 **
 *******************************************************************************/
-BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_dev_addr);
+BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_bd_addr);
 
+#if (BLE_INCLUDED == TRUE)
+bt_status_t btif_storage_add_ble_bonding_key( bt_bdaddr_t *remote_bd_addr,
+                                              char *key,
+                                              uint8_t key_type,
+                                              uint8_t key_length);
+bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+                                             UINT8 key_type,
+                                             char *key_value,
+                                             int key_length);
+
+bt_status_t btif_storage_add_ble_local_key(char *key,
+                                           uint8_t key_type,
+                                           uint8_t key_length);
+bt_status_t btif_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr);
+bt_status_t btif_storage_remove_ble_local_keys(void);
+bt_status_t btif_storage_get_ble_local_key(UINT8 key_type,
+                                           char *key_value,
+                                           int key_len);
+
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+                                              int *addr_type);
+
+bt_status_t btif_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+                                              UINT8 addr_type);
+
+#endif
+/*******************************************************************************
+**
+** Function         btif_storage_get_remote_version
+**
+** Description      Fetch remote version info on cached remote device
+**
+** Returns          BT_STATUS_SUCCESS if found
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+
+bt_status_t btif_storage_get_remote_version(const bt_bdaddr_t *remote_bd_addr,
+                                  bt_remote_version_t *p_ver);
 #endif /* BTIF_STORAGE_H */
diff --git a/btif/include/btif_util.h b/btif/include/btif_util.h
index 09dae6e..ddb4699 100644
--- a/btif/include/btif_util.h
+++ b/btif/include/btif_util.h
@@ -22,6 +22,7 @@
 #include <hardware/bluetooth.h>
 #include <hardware/bt_hf.h>
 #include <utils/Log.h>
+#include <sys/time.h>
 
 #include "data_types.h"
 #include "bt_types.h"
@@ -60,7 +61,7 @@
 const char* dump_av_audio_state(UINT16 event);
 
 int str2bd(char *str, bt_bdaddr_t *addr);
-char *bd2str(bt_bdaddr_t *addr, bdstr_t *bdstr);
+char *bd2str(const bt_bdaddr_t *addr, bdstr_t *bdstr);
 
 UINT32 devclass2uint(DEV_CLASS dev_class);
 void uint2devclass(UINT32 dev, DEV_CLASS dev_class);
diff --git a/btif/include/uinput.h b/btif/include/uinput.h
index 5925703..9a25e4b 100644
--- a/btif/include/uinput.h
+++ b/btif/include/uinput.h
@@ -262,6 +262,7 @@
 #define KEY_SUSPEND     205
 #define KEY_CLOSE       206
 #define KEY_PLAY        207
+#define KEY_FAST_FORWARD  208
 
 #define KEY_UNKNOWN     220
 
diff --git a/btif/src/bluetooth.c b/btif/src/bluetooth.c
index 20d6a07..ffeaaaf 100644
--- a/btif/src/bluetooth.c
+++ b/btif/src/bluetooth.c
@@ -35,6 +35,7 @@
 #include <hardware/bt_hh.h>
 #include <hardware/bt_hl.h>
 #include <hardware/bt_pan.h>
+#include <hardware/bt_gatt.h>
 
 #define LOG_NDDEBUG 0
 #define LOG_TAG "bluedroid"
@@ -80,6 +81,8 @@
 extern bthl_interface_t *btif_hl_get_interface();
 /*pan*/
 extern btpan_interface_t *btif_pan_get_interface();
+/* gatt */
+extern btgatt_interface_t *btif_gatt_get_interface();
 
 /************************************************************************************
 **  Functions
@@ -319,6 +322,8 @@
 
     if (is_profile(profile_id, BT_PROFILE_HEALTH_ID))
         return btif_hl_get_interface();
+    if (is_profile(profile_id, BT_PROFILE_GATT_ID))
+        return btif_gatt_get_interface();
     return NULL;
 }
 
@@ -343,8 +348,20 @@
 
     return btif_dut_mode_send(opcode, buf, len);
 }
+int le_test_mode(uint16_t opcode, uint8_t* buf, uint8_t len)
+{
+    ALOGI("le_test_mode");
+
+    /* sanity check */
+    if (interface_ready() == FALSE)
+        return BT_STATUS_NOT_READY;
+
+    return btif_le_test_mode(opcode, buf, len);
+}
+
+
 static const bt_interface_t bluetoothInterface = {
-    sizeof(bt_interface_t),
+    sizeof(bluetoothInterface),
     init,
     enable,
     disable,
@@ -366,7 +383,8 @@
     ssp_reply,
     get_profile_interface,
     dut_mode_configure,
-    dut_mode_send
+    dut_mode_send,
+    le_test_mode
 };
 
 const bt_interface_t* bluetooth__get_bluetooth_interface ()
diff --git a/btif/src/btif_core.c b/btif/src/btif_core.c
old mode 100755
new mode 100644
index 62339a9..ca39cc8
--- a/btif/src/btif_core.c
+++ b/btif/src/btif_core.c
@@ -290,6 +290,9 @@
         if (event == BT_EVT_TRIGGER_STACK_INIT)
         {
             BTIF_TRACE_DEBUG0("btif_task: received trigger stack init event");
+            #if (BLE_INCLUDED == TRUE)
+            btif_dm_load_ble_local_keys();
+            #endif
             BTA_EnableBluetooth(bte_dm_evt);
         }
 
@@ -830,6 +833,7 @@
     BTM_VendorSpecificCommand(opcode, len, buf, btif_dut_mode_cback);
     return BT_STATUS_SUCCESS;
 }
+
 /*****************************************************************************
 **
 **   btif api adapter property functions
diff --git a/btif/src/btif_dm.c b/btif/src/btif_dm.c
index cb09719..767cd0f 100644
--- a/btif/src/btif_dm.c
+++ b/btif/src/btif_dm.c
@@ -38,10 +38,12 @@
 #include "bta_api.h"
 #include "btif_api.h"
 #include "btif_util.h"
+#include "btif_dm.h"
 #include "btif_storage.h"
 #include "btif_hh.h"
 #include "btif_config.h"
 
+#include "bta_gatt_api.h"
 /******************************************************************************
 **  Constants & Macros
 ******************************************************************************/
@@ -61,7 +63,10 @@
 #define BTIF_DM_DEFAULT_INQ_MAX_RESULTS     0
 #define BTIF_DM_DEFAULT_INQ_MAX_DURATION    10
 
-typedef struct {
+
+
+typedef struct
+{
     bt_bond_state_t state;
     BD_ADDR bd_addr;
     UINT8   is_temp;
@@ -70,9 +75,31 @@
     UINT8   autopair_attempts;
     UINT8   is_local_initiated;
     UINT8   bonded_pending_sdp;
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    BOOLEAN          is_le_only;
+    btif_dm_ble_cb_t ble;
+#endif
 } btif_dm_pairing_cb_t;
 
-typedef struct {
+
+typedef struct
+{
+    UINT8       ir[BT_OCTET16_LEN];
+    UINT8       irk[BT_OCTET16_LEN];
+    UINT8       dhk[BT_OCTET16_LEN];
+}btif_dm_local_key_id_t;
+
+typedef struct
+{
+    BOOLEAN                 is_er_rcvd;
+    UINT8                   er[BT_OCTET16_LEN];
+    BOOLEAN                 is_id_keys_rcvd;
+    btif_dm_local_key_id_t  id_keys;  /* ID kyes */
+
+}btif_dm_local_key_cb_t;
+
+typedef struct
+{
     BD_ADDR bd_addr;
     BD_NAME bd_name;
 } btif_dm_remote_name_t;
@@ -98,7 +125,12 @@
 static void btif_dm_cb_hid_remote_name(tBTM_REMOTE_DEV_NAME *p_remote_name);
 static void btif_update_remote_properties(BD_ADDR bd_addr, BD_NAME bd_name,
                                           DEV_CLASS dev_class, tBT_DEVICE_TYPE dev_type);
-
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+static btif_dm_local_key_cb_t ble_local_key_cb;
+static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif);
+static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl);
+static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req);
+#endif
 /******************************************************************************
 **  Externs
 ******************************************************************************/
@@ -283,6 +315,40 @@
 
 }
 
+/* store remote version in bt config to always have access
+   to it post pairing*/
+static void btif_update_remote_version_property(bt_bdaddr_t *p_bd)
+{
+    bt_property_t property;
+    UINT8 lmp_ver = 0;
+    UINT16 lmp_subver = 0;
+    UINT16 mfct_set = 0;
+    tBTM_STATUS btm_status;
+    bt_remote_version_t info;
+    bt_status_t status;
+    bdstr_t bdstr;
+
+    btm_status = BTM_ReadRemoteVersion(*(BD_ADDR*)p_bd, &lmp_ver,
+                          &mfct_set, &lmp_subver);
+
+    ALOGD("remote version info [%s]: %x, %x, %x", bd2str(p_bd, &bdstr),
+               lmp_ver, mfct_set, lmp_subver);
+
+    if (btm_status == BTM_SUCCESS)
+    {
+        /* always update cache to ensure we have availability whenever BTM API
+           is not populated */
+        info.manufacturer = mfct_set;
+        info.sub_ver = lmp_subver;
+        info.version = lmp_ver;
+        BTIF_STORAGE_FILL_PROPERTY(&property,
+                            BT_PROPERTY_REMOTE_VERSION_INFO, sizeof(bt_remote_version_t),
+                            &info);
+        status = btif_storage_set_remote_device_property(p_bd, &property);
+        ASSERTC(status == BT_STATUS_SUCCESS, "failed to save remote version", status);
+    }
+}
+
 
 static void btif_update_remote_properties(BD_ADDR bd_addr, BD_NAME bd_name,
                                           DEV_CLASS dev_class, tBT_DEVICE_TYPE device_type)
@@ -379,12 +445,13 @@
 
 int remove_hid_bond(bt_bdaddr_t *bd_addr)
 {
-        /* For HID device, inorder to avoid the HID device from re-connecting again after unpairing,
-             * we need to do virtual unplug
-             */
-        bdstr_t bdstr;
-        BTIF_TRACE_DEBUG2("%s---Removing HID bond--%s", __FUNCTION__,bd2str((bt_bdaddr_t *)bd_addr, &bdstr));
-        return btif_hh_virtual_unplug(bd_addr);
+    /* For HID device, inorder to avoid the HID device from re-connecting again after unpairing,
+         * we need to do virtual unplug
+         */
+    bdstr_t bdstr;
+    BTIF_TRACE_DEBUG2("%s---Removing HID bond--%s", __FUNCTION__,bd2str((bt_bdaddr_t *)bd_addr, &bdstr));
+    return btif_hh_virtual_unplug(bd_addr);
+
 }
 /*******************************************************************************
 **
@@ -398,18 +465,34 @@
 *******************************************************************************/
 static void btif_dm_cb_create_bond(bt_bdaddr_t *bd_addr)
 {
+    BOOLEAN is_hid = check_cod(bd_addr, COD_HID_POINTING);
+
+
     bond_state_changed(BT_STATUS_SUCCESS, bd_addr, BT_BOND_STATE_BONDING);
-    if (check_cod(bd_addr, COD_HID_POINTING)){
+
+    if (is_hid){
+
             int status;
             status = btif_hh_connect(bd_addr);
             if(status != BT_STATUS_SUCCESS)
                 bond_state_changed(status, bd_addr, BT_BOND_STATE_NONE);
     }
     else
+    {
+        int device_type;
+        int addr_type;
+        bdstr_t bdstr;
+        bd2str(bd_addr, &bdstr);
+        if(btif_config_get_int("Remote", (char const *)&bdstr,"DevType", &device_type) &&
+           (btif_storage_get_remote_addr_type(bd_addr, &addr_type) == BT_STATUS_SUCCESS) &&
+           (device_type == BT_DEVICE_TYPE_BLE))
+        {
+            BTA_DmAddBleDevice(bd_addr->address, addr_type, BT_DEVICE_TYPE_BLE);
+        }
         BTA_DmBond ((UINT8 *)bd_addr->address);
-
-        /*  Track  originator of bond creation  */
-        pairing_cb.is_local_initiated = TRUE;
+    }
+    /*  Track  originator of bond creation  */
+    pairing_cb.is_local_initiated = TRUE;
 
 }
 
@@ -629,7 +712,8 @@
 
     /* if just_works and bonding bit is not set treat this as temporary */
     if (p_ssp_cfm_req->just_works && !(p_ssp_cfm_req->loc_auth_req & BTM_AUTH_BONDS) &&
-        !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS))
+        !(p_ssp_cfm_req->rmt_auth_req & BTM_AUTH_BONDS) &&
+        !(check_cod((bt_bdaddr_t*)&p_ssp_cfm_req->bd_addr, COD_HID_POINTING)))
         pairing_cb.is_temp = TRUE;
     else
         pairing_cb.is_temp = FALSE;
@@ -1214,23 +1298,22 @@
 
         case BTA_DM_BUSY_LEVEL_EVT:
         {
-            UINT8 busy_level;
-            busy_level = p_data->busy_level.level;
-            if (busy_level & BTM_BL_INQUIRY_PAGING_MASK)
+
+            if (p_data->busy_level.level_flags & BTM_BL_INQUIRY_PAGING_MASK)
             {
-                if (busy_level == BTM_BL_INQUIRY_STARTED)
+                if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_STARTED)
                 {
                        HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                 BT_DISCOVERY_STARTED);
                        btif_dm_inquiry_in_progress = TRUE;
                 }
-                else if (busy_level == BTM_BL_INQUIRY_CANCELLED)
+                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_CANCELLED)
                 {
                        HAL_CBACK(bt_hal_cbacks, discovery_state_changed_cb,
                                                 BT_DISCOVERY_STOPPED);
                        btif_dm_inquiry_in_progress = FALSE;
                 }
-                else if (busy_level == BTM_BL_INQUIRY_COMPLETE)
+                else if (p_data->busy_level.level_flags == BTM_BL_INQUIRY_COMPLETE)
                 {
                        btif_dm_inquiry_in_progress = FALSE;
                 }
@@ -1240,6 +1323,9 @@
         case BTA_DM_LINK_UP_EVT:
             bdcpy(bd_addr.address, p_data->link_up.bd_addr);
             BTIF_TRACE_DEBUG0("BTA_DM_LINK_UP_EVT. Sending BT_ACL_STATE_CONNECTED");
+
+            btif_update_remote_version_property(&bd_addr);
+
             HAL_CBACK(bt_hal_cbacks, acl_state_changed_cb, BT_STATUS_SUCCESS,
                       &bd_addr, BT_ACL_STATE_CONNECTED);
             break;
@@ -1265,19 +1351,158 @@
             kill(getpid(), SIGKILL);
             break;
 
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+        case BTA_DM_BLE_KEY_EVT:
+            BTIF_TRACE_DEBUG1("BTA_DM_BLE_KEY_EVT key_type=0x%02x ", p_data->ble_key.key_type);
+
+            /* If this pairing is by-product of local initiated GATT client Read or Write,
+            BTA would not have sent BTA_DM_BLE_SEC_REQ_EVT event and Bond state would not
+            have setup properly. Setup pairing_cb and notify App about Bonding state now*/
+            if (pairing_cb.state != BT_BOND_STATE_BONDING)
+            {
+                BTIF_TRACE_DEBUG0("Bond state not sent to App so far.Notify the app now");
+                bond_state_changed(BT_STATUS_SUCCESS, (bt_bdaddr_t*)p_data->ble_key.bd_addr,
+                                   BT_BOND_STATE_BONDING);
+            }
+            else if (memcmp (pairing_cb.bd_addr, p_data->ble_key.bd_addr, BD_ADDR_LEN)!=0)
+            {
+                BTIF_TRACE_ERROR1("BD mismatch discard BLE key_type=%d ",p_data->ble_key.key_type);
+                break;
+            }
+
+            switch (p_data->ble_key.key_type)
+            {
+                case BTA_LE_KEY_PENC:
+                    BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PENC");
+                    pairing_cb.ble.is_penc_key_rcvd = TRUE;
+                    memcpy(pairing_cb.ble.penc_key.ltk,p_data->ble_key.key_value.penc_key.ltk, 16);
+                    memcpy(pairing_cb.ble.penc_key.rand, p_data->ble_key.key_value.penc_key.rand,8);
+                    pairing_cb.ble.penc_key.ediv = p_data->ble_key.key_value.penc_key.ediv;
+                    pairing_cb.ble.penc_key.sec_level = p_data->ble_key.key_value.penc_key.sec_level;
+
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",i,pairing_cb.ble.penc_key.ltk[i]);
+                    }
+                    for (i=0; i<8; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("pairing_cb.ble.penc_key.rand[%d]=0x%02x",i,pairing_cb.ble.penc_key.rand[i]);
+                    }
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.ediv=0x%04x",pairing_cb.ble.penc_key.ediv);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.sec_level=0x%02x",pairing_cb.ble.penc_key.sec_level);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.penc_key.key_size=0x%02x",pairing_cb.ble.penc_key.key_size);
+                    break;
+
+                case BTA_LE_KEY_PID:
+                    BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PID");
+                    pairing_cb.ble.is_pid_key_rcvd = TRUE;
+                    memcpy(pairing_cb.ble.pid_key, p_data->ble_key.key_value.pid_key.irk, 16);
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("pairing_cb.ble.pid_key[%d]=0x%02x",i,pairing_cb.ble.pid_key[i]);
+                    }
+                    break;
+
+                case BTA_LE_KEY_PCSRK:
+                    BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_PCSRK");
+                    pairing_cb.ble.is_pcsrk_key_rcvd = TRUE;
+                    pairing_cb.ble.pcsrk_key.counter = p_data->ble_key.key_value.pcsrk_key.counter;
+                    pairing_cb.ble.pcsrk_key.sec_level = p_data->ble_key.key_value.pcsrk_key.sec_level;
+                    memcpy(pairing_cb.ble.pcsrk_key.csrk,p_data->ble_key.key_value.pcsrk_key.csrk,16);
+
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",i,pairing_cb.ble.pcsrk_key.csrk[i]);
+                    }
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.pcsrk_key.counter=0x%08x",pairing_cb.ble.pcsrk_key.counter);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",pairing_cb.ble.pcsrk_key.sec_level);
+                    break;
+
+                case BTA_LE_KEY_LENC:
+                    BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_LENC");
+                    pairing_cb.ble.is_lenc_key_rcvd = TRUE;
+                    pairing_cb.ble.lenc_key.div = p_data->ble_key.key_value.lenc_key.div;
+                    pairing_cb.ble.lenc_key.key_size = p_data->ble_key.key_value.lenc_key.key_size;
+                    pairing_cb.ble.lenc_key.sec_level = p_data->ble_key.key_value.lenc_key.sec_level;
+
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.div=0x%04x",pairing_cb.ble.lenc_key.div);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.key_size=0x%02x",pairing_cb.ble.lenc_key.key_size);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lenc_key.sec_level=0x%02x",pairing_cb.ble.lenc_key.sec_level);
+                    break;
+
+
+
+                case BTA_LE_KEY_LCSRK:
+                    BTIF_TRACE_DEBUG0("Rcv BTA_LE_KEY_LCSRK");
+                    pairing_cb.ble.is_lcsrk_key_rcvd = TRUE;
+                    pairing_cb.ble.lcsrk_key.counter = p_data->ble_key.key_value.lcsrk_key.counter;
+                    pairing_cb.ble.lcsrk_key.div = p_data->ble_key.key_value.lcsrk_key.div;
+                    pairing_cb.ble.lcsrk_key.sec_level = p_data->ble_key.key_value.lcsrk_key.sec_level;
+
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.div=0x%04x",pairing_cb.ble.lcsrk_key.div);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.counter=0x%08x",pairing_cb.ble.lcsrk_key.counter);
+                    BTIF_TRACE_DEBUG1("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",pairing_cb.ble.lcsrk_key.sec_level);
+
+                    break;
+
+                default:
+                    BTIF_TRACE_ERROR1("unknown BLE key type (0x%02x)", p_data->ble_key.key_type);
+                    break;
+            }
+
+            break;
+        case BTA_DM_BLE_SEC_REQ_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_SEC_REQ_EVT. ");
+            btif_dm_ble_sec_req_evt(&p_data->ble_req);
+            break;
+        case BTA_DM_BLE_PASSKEY_NOTIF_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_PASSKEY_NOTIF_EVT. ");
+            btif_dm_ble_key_notif_evt(&p_data->key_notif);
+            break;
+        case BTA_DM_BLE_PASSKEY_REQ_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
+            btif_dm_ble_passkey_req_evt(&p_data->pin_req);
+            break;
+        case BTA_DM_BLE_OOB_REQ_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_OOB_REQ_EVT. ");
+            break;
+        case BTA_DM_BLE_LOCAL_IR_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_LOCAL_IR_EVT. ");
+            ble_local_key_cb.is_id_keys_rcvd = TRUE;
+            memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
+            memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
+            memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
+            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0],
+                                            BTIF_DM_LE_LOCAL_KEY_IR,
+                                            BT_OCTET16_LEN);
+            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.ir[0],
+                                            BTIF_DM_LE_LOCAL_KEY_IRK,
+                                            BT_OCTET16_LEN);
+            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.dhk[0],
+                                            BTIF_DM_LE_LOCAL_KEY_DHK,
+                                            BT_OCTET16_LEN);
+            break;
+        case BTA_DM_BLE_LOCAL_ER_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_LOCAL_ER_EVT. ");
+            ble_local_key_cb.is_er_rcvd = TRUE;
+            memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16));
+            btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.er[0],
+                                            BTIF_DM_LE_LOCAL_KEY_ER,
+                                            BT_OCTET16_LEN);
+            break;
+
+        case BTA_DM_BLE_AUTH_CMPL_EVT:
+            BTIF_TRACE_DEBUG0("BTA_DM_BLE_KEY_EVT. ");
+            btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
+            break;
+#endif
+
         case BTA_DM_AUTHORIZE_EVT:
         case BTA_DM_SIG_STRENGTH_EVT:
         case BTA_DM_SP_RMT_OOB_EVT:
         case BTA_DM_SP_KEYPRESS_EVT:
         case BTA_DM_ROLE_CHG_EVT:
-        case BTA_DM_BLE_KEY_EVT:
-        case BTA_DM_BLE_SEC_REQ_EVT:
-        case BTA_DM_BLE_PASSKEY_NOTIF_EVT:
-        case BTA_DM_BLE_PASSKEY_REQ_EVT:
-        case BTA_DM_BLE_OOB_REQ_EVT:
-        case BTA_DM_BLE_LOCAL_IR_EVT:
-        case BTA_DM_BLE_LOCAL_ER_EVT:
-        case BTA_DM_BLE_AUTH_CMPL_EVT:
+
         default:
             BTIF_TRACE_WARNING1( "btif_dm_cback : unhandled event (%d)", event );
             break;
@@ -1328,6 +1553,26 @@
                 bond_state_changed(BT_STATUS_SUCCESS, (bt_bdaddr_t *)p_param, BT_BOND_STATE_BONDING);
             }
             break;
+        case BTIF_DM_CB_LE_TX_TEST:
+        case BTIF_DM_CB_LE_RX_TEST:
+            {
+                uint8_t status;
+                STREAM_TO_UINT8(status, p_param);
+                HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
+                      (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, 0);
+            }
+            break;
+        case BTIF_DM_CB_LE_TEST_END:
+            {
+                uint8_t status;
+                uint16_t count = 0;
+                STREAM_TO_UINT8(status, p_param);
+                if (status == 0)
+                    STREAM_TO_UINT16(count, p_param);
+                HAL_CBACK(bt_hal_cbacks, le_test_mode_cb,
+                      (status == 0) ? BT_STATUS_SUCCESS : BT_STATUS_FAIL, count);
+            }
+            break;
         default:
         {
             BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event);
@@ -1469,7 +1714,7 @@
     /* TODO: Do we need to handle multiple inquiries at the same time? */
 
     /* Set inquiry params and call API */
-#if (BLE_INCLUDED == TRUE)
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
     inq_params.mode = BTA_DM_GENERAL_INQUIRY|BTA_BLE_GENERAL_INQUIRY;
 #else
     inq_params.mode = BTA_DM_GENERAL_INQUIRY;
@@ -1551,6 +1796,33 @@
     */
     if (pairing_cb.state == BT_BOND_STATE_BONDING)
     {
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+        if (pairing_cb.is_ssp)
+        {
+            if (pairing_cb.is_le_only)
+            {
+                BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_PAIR_NOT_SPT);
+            }
+            else
+                BTA_DmConfirm( (UINT8 *)bd_addr->address, FALSE);
+        }
+        else
+        {
+            if (pairing_cb.is_le_only)
+            {
+                BTA_DmBondCancel ((UINT8 *)bd_addr->address);
+            }
+            else
+            {
+                BTA_DmPinReply( (UINT8 *)bd_addr->address, FALSE, 0, NULL);
+            }
+        /* Cancel bonding, in case it is in ACL connection setup state */
+        BTA_DmBondCancel ((UINT8 *)bd_addr->address);
+        }
+
+#else
         if (pairing_cb.is_ssp)
         {
             BTA_DmConfirm( (UINT8 *)bd_addr->address, FALSE);
@@ -1562,6 +1834,7 @@
         /* Cancel bonding, in case it is in ACL connection setup state */
         BTA_DmBondCancel ((UINT8 *)bd_addr->address);
         btif_storage_remove_bonded_device((bt_bdaddr_t *)bd_addr);
+#endif
     }
 
     return BT_STATUS_SUCCESS;
@@ -1602,12 +1875,35 @@
                                uint8_t pin_len, bt_pin_code_t *pin_code)
 {
     BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept);
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
 
+    if (pairing_cb.is_le_only)
+    {
+        int i;
+        UINT32 passkey = 0;
+        int multi[] = {100000, 10000, 1000, 100, 10,1};
+        BD_ADDR remote_bd_addr;
+        bdcpy(remote_bd_addr, bd_addr->address);
+        for (i = 0; i < 6; i++)
+        {
+            passkey += (multi[i] * (pin_code->pin[i] - '0'));
+        }
+        BTIF_TRACE_DEBUG1("btif_dm_pin_reply: passkey: %d", passkey);
+        BTA_DmBlePasskeyReply(remote_bd_addr, accept, passkey);
+
+    }
+    else
+    {
+        BTA_DmPinReply( (UINT8 *)bd_addr->address, accept, pin_len, pin_code->pin);
+        if (accept)
+            pairing_cb.pin_code_len = pin_len;
+    }
+#else
     BTA_DmPinReply( (UINT8 *)bd_addr->address, accept, pin_len, pin_code->pin);
 
     if (accept)
         pairing_cb.pin_code_len = pin_len;
-
+#endif
     return BT_STATUS_SUCCESS;
 }
 
@@ -1635,8 +1931,20 @@
     }
     /* BT_SSP_VARIANT_CONSENT & BT_SSP_VARIANT_PASSKEY_CONFIRMATION supported */
     BTIF_TRACE_EVENT2("%s: accept=%d", __FUNCTION__, accept);
-    BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+    if (pairing_cb.is_le_only)
+    {
+        if (accept)
+            BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_GRANTED);
+        else
+            BTA_DmBleSecurityGrant((UINT8 *)bd_addr->address,BTA_DM_SEC_PAIR_NOT_SPT);
+    }
+    else
+        BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
 
+#else
+    BTA_DmConfirm( (UINT8 *)bd_addr->address, accept);
+#endif
     return BT_STATUS_SUCCESS;
 }
 
@@ -1888,6 +2196,314 @@
     return result;
 }
 #endif /*  BTIF_DM_OOB_TEST */
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif)
+{
+    bt_bdaddr_t bd_addr;
+    bt_bdname_t bd_name;
+    UINT32 cod;
+
+    BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+
+    /* Remote name update */
+    btif_update_remote_properties(p_ssp_key_notif->bd_addr , p_ssp_key_notif->bd_name,
+                                          NULL, BT_DEVICE_TYPE_BLE);
+    bdcpy(bd_addr.address, p_ssp_key_notif->bd_addr);
+    memcpy(bd_name.name, p_ssp_key_notif->bd_name, BD_NAME_LEN);
+
+    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+    pairing_cb.is_ssp = FALSE;
+    cod = COD_UNCLASSIFIED;
+
+    HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name,
+              cod, BT_SSP_VARIANT_PASSKEY_NOTIFICATION,
+              p_ssp_key_notif->passkey);
+}
+
+/*******************************************************************************
+**
+** Function         btif_dm_ble_auth_cmpl_evt
+**
+** Description      Executes authentication complete event in btif context
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl)
+{
+    /* Save link key, if not temporary */
+    bt_bdaddr_t bd_addr;
+    bt_status_t status = BT_STATUS_FAIL;
+    bt_bond_state_t state = BT_BOND_STATE_NONE;
+
+    bdcpy(bd_addr.address, p_auth_cmpl->bd_addr);
+    if ( (p_auth_cmpl->success == TRUE) && (p_auth_cmpl->key_present) )
+    {
+        /* store keys */
+    }
+    if (p_auth_cmpl->success)
+    {
+        status = BT_STATUS_SUCCESS;
+        state = BT_BOND_STATE_BONDED;
+
+        btif_dm_save_ble_bonding_keys();
+        BTA_GATTC_Refresh(bd_addr.address);
+        btif_dm_get_remote_services(&bd_addr);
+    }
+    else
+    {
+        /*Map the HCI fail reason  to  bt status  */
+        switch (p_auth_cmpl->fail_reason)
+        {
+
+            btif_dm_remove_ble_bonding_keys();
+            default:
+                status =  BT_STATUS_FAIL;
+                break;
+        }
+    }
+    bond_state_changed(status, &bd_addr, state);
+}
+
+
+
+void    btif_dm_load_ble_local_keys(void)
+{
+    bt_status_t bt_status;
+
+    memset(&ble_local_key_cb, 0, sizeof(btif_dm_local_key_cb_t));
+
+    if (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_ER,(char*)&ble_local_key_cb.er[0],
+                                       BT_OCTET16_LEN)== BT_STATUS_SUCCESS)
+    {
+        ble_local_key_cb.is_er_rcvd = TRUE;
+        BTIF_TRACE_DEBUG1("%s BLE ER key loaded",__FUNCTION__ );
+    }
+
+    if ((btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IR,(char*)&ble_local_key_cb.id_keys.ir[0],
+                                        BT_OCTET16_LEN)== BT_STATUS_SUCCESS )&&
+        (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IRK, (char*)&ble_local_key_cb.id_keys.irk[0],
+                                        BT_OCTET16_LEN)== BT_STATUS_SUCCESS)&&
+        (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_DHK,(char*)&ble_local_key_cb.id_keys.dhk[0],
+                                        BT_OCTET16_LEN)== BT_STATUS_SUCCESS))
+    {
+        ble_local_key_cb.is_id_keys_rcvd = TRUE;
+        BTIF_TRACE_DEBUG1("%s BLE ID keys loaded",__FUNCTION__ );
+    }
+
+}
+void    btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK *p_key_mask, BT_OCTET16 er,
+                                   tBTA_BLE_LOCAL_ID_KEYS *p_id_keys)
+{
+    if (ble_local_key_cb.is_er_rcvd )
+    {
+        memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16));
+        *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER;
+    }
+
+    if (ble_local_key_cb.is_id_keys_rcvd)
+    {
+        memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0], sizeof(BT_OCTET16));
+        memcpy(&p_id_keys->irk[0],  &ble_local_key_cb.id_keys.irk[0], sizeof(BT_OCTET16));
+        memcpy(&p_id_keys->dhk[0],  &ble_local_key_cb.id_keys.dhk[0], sizeof(BT_OCTET16));
+        *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID;
+    }
+    BTIF_TRACE_DEBUG2("%s  *p_key_mask=0x%02x",__FUNCTION__,   *p_key_mask);
+}
+
+void btif_dm_save_ble_bonding_keys(void)
+{
+
+    bt_bdaddr_t bd_addr;
+
+    BTIF_TRACE_DEBUG1("%s",__FUNCTION__ );
+
+    bdcpy(bd_addr.address, pairing_cb.bd_addr);
+
+    if (pairing_cb.ble.is_penc_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         (char *) &pairing_cb.ble.penc_key,
+                                         BTIF_DM_LE_KEY_PENC,
+                                         sizeof(btif_dm_ble_penc_keys_t));
+    }
+
+    if (pairing_cb.ble.is_pid_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         (char *) &pairing_cb.ble.pid_key[0],
+                                         BTIF_DM_LE_KEY_PID,
+                                         BT_OCTET16_LEN);
+    }
+
+
+    if (pairing_cb.ble.is_pcsrk_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         (char *) &pairing_cb.ble.pcsrk_key,
+                                         BTIF_DM_LE_KEY_PCSRK,
+                                         sizeof(btif_dm_ble_pcsrk_keys_t));
+    }
+
+
+    if (pairing_cb.ble.is_lenc_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         (char *) &pairing_cb.ble.lenc_key,
+                                         BTIF_DM_LE_KEY_LENC,
+                                         sizeof(btif_dm_ble_lenc_keys_t));
+    }
+
+    if (pairing_cb.ble.is_lcsrk_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         (char *) &pairing_cb.ble.lcsrk_key,
+                                         BTIF_DM_LE_KEY_LCSRK,
+                                         sizeof(btif_dm_ble_lcsrk_keys_t));
+    }
+
+}
+
+
+void btif_dm_remove_ble_bonding_keys(void)
+{
+    bt_bdaddr_t bd_addr;
+
+    BTIF_TRACE_DEBUG1("%s",__FUNCTION__ );
+
+    bdcpy(bd_addr.address, pairing_cb.bd_addr);
+    btif_storage_remove_ble_bonding_keys(&bd_addr);
+}
+
+
+/*******************************************************************************
+**
+** Function         btif_dm_ble_sec_req_evt
+**
+** Description      Eprocess security request event in btif context
+**
+** Returns          void
+**
+*******************************************************************************/
+void btif_dm_ble_sec_req_evt(tBTA_DM_BLE_SEC_REQ *p_ble_req)
+{
+    bt_bdaddr_t bd_addr;
+    bt_bdname_t bd_name;
+    UINT32 cod;
+    BTIF_TRACE_DEBUG1("%s", __FUNCTION__);
+
+    if (pairing_cb.state == BT_BOND_STATE_BONDING)
+    {
+        BTIF_TRACE_DEBUG1("%s Discard security request", __FUNCTION__);
+        return;
+    }
+
+    /* Remote name update */
+    btif_update_remote_properties(p_ble_req->bd_addr,p_ble_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+
+    bdcpy(bd_addr.address, p_ble_req->bd_addr);
+    memcpy(bd_name.name, p_ble_req->bd_name, BD_NAME_LEN);
+
+    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+
+    pairing_cb.is_temp = FALSE;
+    pairing_cb.is_le_only = TRUE;
+    pairing_cb.is_ssp = TRUE;
+
+    cod = COD_UNCLASSIFIED;
+
+    HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name, cod,
+              BT_SSP_VARIANT_CONSENT, 0);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         btif_dm_ble_passkey_req_evt
+**
+** Description      Executes pin request event in btif context
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req)
+{
+    bt_bdaddr_t bd_addr;
+    bt_bdname_t bd_name;
+    UINT32 cod;
+
+    /* Remote name update */
+    btif_update_remote_properties(p_pin_req->bd_addr,p_pin_req->bd_name,NULL,BT_DEVICE_TYPE_BLE);
+
+    bdcpy(bd_addr.address, p_pin_req->bd_addr);
+    memcpy(bd_name.name, p_pin_req->bd_name, BD_NAME_LEN);
+
+    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+    pairing_cb.is_le_only = TRUE;
+
+    cod = COD_UNCLASSIFIED;
+
+    HAL_CBACK(bt_hal_cbacks, pin_request_cb,
+              &bd_addr, &bd_name, cod);
+}
+
+
+void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
+                                           tBT_DEVICE_TYPE dev_type)
+{
+   btif_update_remote_properties(bd_addr,bd_name,NULL,dev_type);
+}
+
+static void btif_dm_ble_tx_test_cback(void *p)
+{
+    btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_TX_TEST,
+                          (char *)p, 1, NULL);
+}
+
+static void btif_dm_ble_rx_test_cback(void *p)
+{
+    btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_RX_TEST,
+                          (char *)p, 1, NULL);
+}
+
+static void btif_dm_ble_test_end_cback(void *p)
+{
+    btif_transfer_context(btif_dm_generic_evt, BTIF_DM_CB_LE_TEST_END,
+                          (char *)p, 3, NULL);
+}
+/*******************************************************************************
+**
+** Function         btif_le_test_mode
+**
+** Description     Sends a HCI BLE Test command to the Controller
+**
+** Returns          BT_STATUS_SUCCESS on success
+**
+*******************************************************************************/
+bt_status_t btif_le_test_mode(uint16_t opcode, uint8_t *buf, uint8_t len)
+{
+     switch (opcode) {
+         case HCI_BLE_TRANSMITTER_TEST:
+             if (len != 3) return BT_STATUS_PARM_INVALID;
+             BTM_BleTransmitterTest(buf[0],buf[1],buf[2], btif_dm_ble_tx_test_cback);
+             break;
+         case HCI_BLE_RECEIVER_TEST:
+             if (len != 1) return BT_STATUS_PARM_INVALID;
+             BTM_BleReceiverTest(buf[0], btif_dm_ble_rx_test_cback);
+             break;
+         case HCI_BLE_TEST_END:
+             BTM_BleTestEnd((tBTM_CMPL_CB*) btif_dm_ble_test_end_cback);
+             break;
+         default:
+             BTIF_TRACE_ERROR2("%s: Unknown LE Test Mode Command 0x%x", __FUNCTION__, opcode);
+             return BT_STATUS_UNSUPPORTED;
+     }
+     return BT_STATUS_SUCCESS;
+}
+
+#endif
 
 void btif_dm_on_disable()
 {
diff --git a/btif/src/btif_gatt.c b/btif/src/btif_gatt.c
new file mode 100644
index 0000000..bc01c2e
--- /dev/null
+++ b/btif/src/btif_gatt.c
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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.
+ *
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ *
+ *  Filename:      btif_gatt.c
+ *
+ *  Description:   GATT Profile Bluetooth Interface
+ *
+ *******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+const btgatt_callbacks_t *bt_gatt_callbacks = NULL;
+
+extern btgatt_client_interface_t btgattClientInterface;
+extern btgatt_server_interface_t btgattServerInterface;
+
+/*******************************************************************************
+**
+** Function         btif_gatt_init
+**
+** Description      Initializes the GATT interface
+**
+** Returns    s      bt_status_t
+**
+*******************************************************************************/
+static bt_status_t btif_gatt_init( const btgatt_callbacks_t* callbacks )
+{
+    bt_gatt_callbacks = callbacks;
+
+    BTA_GATTC_Init();
+    BTA_GATTS_Init();
+
+    return BT_STATUS_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function         btif_gatt_cleanup
+**
+** Description      Closes the GATT interface
+**
+** Returns          void
+**
+*******************************************************************************/
+static void  btif_gatt_cleanup( void )
+{
+    if (bt_gatt_callbacks)
+        bt_gatt_callbacks = NULL;
+}
+
+static const btgatt_interface_t btgattInterface = {
+    sizeof(btgattInterface),
+
+    btif_gatt_init,
+    btif_gatt_cleanup,
+
+    &btgattClientInterface,
+    &btgattServerInterface,
+};
+
+/*******************************************************************************
+**
+** Function         btif_gatt_get_interface
+**
+** Description      Get the gatt callback interface
+**
+** Returns          btgatt_interface_t
+**
+*******************************************************************************/
+const btgatt_interface_t *btif_gatt_get_interface()
+{
+    return &btgattInterface;
+}
+
+#endif
diff --git a/btif/src/btif_gatt_client.c b/btif/src/btif_gatt_client.c
new file mode 100644
index 0000000..ac3df52
--- /dev/null
+++ b/btif/src/btif_gatt_client.c
@@ -0,0 +1,998 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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.
+ *
+ ******************************************************************************/
+
+
+/*******************************************************************************
+ *
+ *  Filename:      btif_gatt_client.c
+ *
+ *  Description:   GATT client implementation
+ *
+ *******************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+#include "btif_config.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+#include "btif_dm.h"
+#include "btif_storage.h"
+
+/*******************************************************************************
+**  Constants & Macros
+********************************************************************************/
+
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+    {\
+        ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
+        return BT_STATUS_NOT_READY;\
+    } else {\
+        ALOGD("%s", __FUNCTION__);\
+    }
+
+
+typedef enum {
+    BTIF_GATTC_REGISTER_APP = 1000,
+    BTIF_GATTC_UNREGISTER_APP,
+    BTIF_GATTC_SCAN_START,
+    BTIF_GATTC_SCAN_STOP,
+    BTIF_GATTC_OPEN,
+    BTIF_GATTC_CLOSE,
+    BTIF_GATTC_SEARCH_SERVICE,
+    BTIF_GATTC_GET_FIRST_CHAR,
+    BTIF_GATTC_GET_NEXT_CHAR,
+    BTIF_GATTC_GET_FIRST_CHAR_DESCR,
+    BTIF_GATTC_GET_NEXT_CHAR_DESCR,
+    BTIF_GATTC_GET_FIRST_INCL_SERVICE,
+    BTIF_GATTC_GET_NEXT_INCL_SERVICE,
+    BTIF_GATTC_READ_CHAR,
+    BTIF_GATTC_READ_CHAR_DESCR,
+    BTIF_GATTC_WRITE_CHAR,
+    BTIF_GATTC_WRITE_CHAR_DESCR,
+    BTIF_GATTC_EXECUTE_WRITE,
+    BTIF_GATTC_REG_FOR_NOTIFICATION,
+    BTIF_GATTC_DEREG_FOR_NOTIFICATION,
+    BTIF_GATTC_REFRESH,
+    BTIF_GATTC_READ_RSSI
+} btif_gattc_event_t;
+
+#define BTIF_GATT_MAX_OBSERVED_DEV 40
+
+#define BTIF_GATT_OBSERVE_EVT   0x1000
+#define BTIF_GATTC_RSSI_EVT     0x1001
+
+/*******************************************************************************
+**  Local type definitions
+********************************************************************************/
+
+typedef struct
+{
+    uint8_t     value[BTGATT_MAX_ATTR_LEN];
+    bt_bdaddr_t bd_addr;
+    btgatt_srvc_id_t srvc_id;
+    btgatt_srvc_id_t incl_srvc_id;
+    btgatt_char_id_t char_id;
+    bt_uuid_t   uuid;
+    uint16_t    conn_id;
+    uint16_t    len;
+    uint8_t     client_if;
+    uint8_t     action;
+    uint8_t     is_direct;
+    uint8_t     search_all;
+    uint8_t     auth_req;
+    uint8_t     write_type;
+    uint8_t     status;
+    uint8_t     addr_type;
+    int8_t      rssi;
+    tBT_DEVICE_TYPE device_type;
+} __attribute__((packed)) btif_gattc_cb_t;
+
+typedef struct
+{
+    bt_bdaddr_t bd_addr;
+    BOOLEAN     in_use;
+}__attribute__((packed)) btif_gattc_dev_t;
+
+typedef struct
+{
+    btif_gattc_dev_t remote_dev[BTIF_GATT_MAX_OBSERVED_DEV];
+    uint8_t        addr_type;
+    uint8_t        next_storage_idx;
+}__attribute__((packed)) btif_gattc_dev_cb_t;
+
+/*******************************************************************************
+**  Static variables
+********************************************************************************/
+
+extern const btgatt_callbacks_t *bt_gatt_callbacks;
+static btif_gattc_dev_cb_t  btif_gattc_dev_cb;
+static btif_gattc_dev_cb_t  *p_dev_cb = &btif_gattc_dev_cb;
+static uint8_t rssi_request_client_if;
+
+/*******************************************************************************
+**  Static functions
+********************************************************************************/
+
+static void btif_gattc_init_dev_cb(void)
+{
+    memset(p_dev_cb, 0, sizeof(btif_gattc_dev_cb_t));
+}
+
+static void btif_gattc_add_remote_bdaddr (BD_ADDR p_bda, uint8_t addr_type)
+{
+    BOOLEAN found=FALSE;
+    uint8_t i;
+    for (i = 0; i < BTIF_GATT_MAX_OBSERVED_DEV; i++)
+    {
+        if (!p_dev_cb->remote_dev[i].in_use )
+        {
+            memcpy(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN);
+            p_dev_cb->addr_type = addr_type;
+            p_dev_cb->remote_dev[i].in_use = TRUE;
+            ALOGD("%s device added idx=%d", __FUNCTION__, i  );
+            break;
+        }
+    }
+
+    if ( i == BTIF_GATT_MAX_OBSERVED_DEV)
+    {
+        i= p_dev_cb->next_storage_idx;
+        memcpy(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN);
+        p_dev_cb->addr_type = addr_type;
+        p_dev_cb->remote_dev[i].in_use = TRUE;
+        ALOGD("%s device overwrite idx=%d", __FUNCTION__, i  );
+        p_dev_cb->next_storage_idx++;
+        if(p_dev_cb->next_storage_idx >= BTIF_GATT_MAX_OBSERVED_DEV)
+               p_dev_cb->next_storage_idx = 0;
+    }
+}
+
+static BOOLEAN btif_gattc_find_bdaddr (BD_ADDR p_bda)
+{
+    uint8_t i;
+    for (i = 0; i < BTIF_GATT_MAX_OBSERVED_DEV; i++)
+    {
+        if (p_dev_cb->remote_dev[i].in_use &&
+            !memcmp(p_dev_cb->remote_dev[i].bd_addr.address, p_bda, BD_ADDR_LEN))
+        {
+            return TRUE;
+        }
+    }
+    return FALSE;
+}
+
+static void btif_gattc_update_properties ( btif_gattc_cb_t *p_btif_cb )
+{
+    uint8_t remote_name_len;
+    uint8_t *p_eir_remote_name=NULL;
+    bt_bdname_t bdname;
+
+    p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+                                         BTM_EIR_COMPLETE_LOCAL_NAME_TYPE, &remote_name_len);
+
+    if(p_eir_remote_name == NULL)
+    {
+        p_eir_remote_name = BTA_CheckEirData(p_btif_cb->value,
+                                BT_EIR_SHORTENED_LOCAL_NAME_TYPE, &remote_name_len);
+    }
+
+    if(p_eir_remote_name)
+    {
+         memcpy(bdname.name, p_eir_remote_name, remote_name_len);
+         bdname.name[remote_name_len]='\0';
+
+        ALOGD("%s BLE device name=%s len=%d dev_type=%d", __FUNCTION__, bdname.name,
+              remote_name_len, p_btif_cb->device_type  );
+        btif_dm_update_ble_remote_properties( p_btif_cb->bd_addr.address,   bdname.name,
+                                               p_btif_cb->device_type);
+    }
+
+    btif_storage_set_remote_addr_type( &p_btif_cb->bd_addr, p_btif_cb->addr_type);
+}
+
+static void btif_gattc_upstreams_evt(uint16_t event, char* p_param)
+{
+    ALOGD("%s: Event %d", __FUNCTION__, event);
+
+    tBTA_GATTC *p_data = (tBTA_GATTC*)p_param;
+    switch (event)
+    {
+        case BTA_GATTC_REG_EVT:
+        {
+            bt_uuid_t app_uuid;
+            bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.app_uuid);
+            HAL_CBACK(bt_gatt_callbacks, client->register_client_cb
+                , p_data->reg_oper.status
+                , p_data->reg_oper.client_if
+                , &app_uuid
+            );
+            break;
+        }
+
+        case BTA_GATTC_DEREG_EVT:
+            break;
+
+        case BTA_GATTC_READ_CHAR_EVT:
+        {
+            btgatt_read_params_t data;
+            set_read_value(&data, &p_data->read);
+
+            HAL_CBACK(bt_gatt_callbacks, client->read_characteristic_cb
+                , p_data->read.conn_id, p_data->read.status, &data);
+            break;
+        }
+
+        case BTA_GATTC_WRITE_CHAR_EVT:
+        case BTA_GATTC_PREP_WRITE_EVT:
+        {
+            btgatt_write_params_t data;
+            bta_to_btif_srvc_id(&data.srvc_id, &p_data->write.srvc_id);
+            bta_to_btif_char_id(&data.char_id, &p_data->write.char_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->write_characteristic_cb
+                , p_data->write.conn_id, p_data->write.status, &data
+            );
+            break;
+        }
+
+        case BTA_GATTC_EXEC_EVT:
+        {
+            HAL_CBACK(bt_gatt_callbacks, client->execute_write_cb
+                , p_data->exec_cmpl.conn_id, p_data->exec_cmpl.status
+            );
+            break;
+        }
+
+        case BTA_GATTC_SEARCH_CMPL_EVT:
+        {
+            HAL_CBACK(bt_gatt_callbacks, client->search_complete_cb
+                , p_data->search_cmpl.conn_id, p_data->search_cmpl.status);
+            break;
+        }
+
+        case BTA_GATTC_SEARCH_RES_EVT:
+        {
+            btgatt_srvc_id_t data;
+            bta_to_btif_srvc_id(&data, &(p_data->srvc_res.service_uuid));
+            HAL_CBACK(bt_gatt_callbacks, client->search_result_cb
+                , p_data->srvc_res.conn_id, &data);
+            break;
+        }
+
+        case BTA_GATTC_READ_DESCR_EVT:
+        {
+            btgatt_read_params_t data;
+            set_read_value(&data, &p_data->read);
+
+            HAL_CBACK(bt_gatt_callbacks, client->read_descriptor_cb
+                , p_data->read.conn_id, p_data->read.status, &data);
+            break;
+        }
+
+        case BTA_GATTC_WRITE_DESCR_EVT:
+        {
+            btgatt_write_params_t data;
+            bta_to_btif_srvc_id(&data.srvc_id, &p_data->write.srvc_id);
+            bta_to_btif_char_id(&data.char_id, &p_data->write.char_id);
+            bta_to_btif_uuid(&data.descr_id, &p_data->write.descr_type);
+
+            HAL_CBACK(bt_gatt_callbacks, client->write_descriptor_cb
+                , p_data->write.conn_id, p_data->write.status, &data);
+            break;
+        }
+
+        case BTA_GATTC_NOTIF_EVT:
+        {
+            btgatt_notify_params_t data;
+
+            bdcpy(data.bda.address, p_data->notify.bda);
+
+            bta_to_btif_srvc_id(&data.srvc_id, &p_data->notify.char_id.srvc_id);
+            bta_to_btif_char_id(&data.char_id, &p_data->notify.char_id.char_id);
+            memcpy(data.value, p_data->notify.value, p_data->notify.len);
+
+            data.is_notify = p_data->notify.is_notify;
+            data.len = p_data->notify.len;
+
+            HAL_CBACK(bt_gatt_callbacks, client->notify_cb
+                , p_data->notify.conn_id, &data);
+
+            if (p_data->notify.is_notify == FALSE)
+            {
+                BTA_GATTC_SendIndConfirm(p_data->notify.conn_id,
+                                         &p_data->notify.char_id);
+            }
+            break;
+        }
+
+        case BTA_GATTC_OPEN_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->open.remote_bda);
+
+            if (p_data->open.status == BTA_GATT_OK)
+                btif_gatt_check_encrypted_link(p_data->open.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, client->open_cb, p_data->open.conn_id
+                , p_data->open.status, p_data->open.client_if, &bda);
+            break;
+        }
+
+        case BTA_GATTC_CLOSE_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->close.remote_bda);
+            HAL_CBACK(bt_gatt_callbacks, client->close_cb, p_data->close.conn_id
+                , p_data->status, p_data->close.client_if, &bda);
+
+            if(p_data->status == BTA_GATT_OK)
+                btif_gatt_remove_encrypted_link(p_data->close.remote_bda);
+            break;
+        }
+
+        case BTA_GATTC_ACL_EVT:
+            ALOGD("BTA_GATTC_ACL_EVT: status = %d", p_data->status);
+            /* Ignore for now */
+            break;
+
+        case BTA_GATTC_CANCEL_OPEN_EVT:
+            break;
+
+        case BTIF_GATT_OBSERVE_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            if (!btif_gattc_find_bdaddr(p_btif_cb->bd_addr.address))
+            {
+                btif_gattc_add_remote_bdaddr(p_btif_cb->bd_addr.address, p_btif_cb->addr_type);
+                btif_gattc_update_properties(p_btif_cb);
+            }
+            HAL_CBACK(bt_gatt_callbacks, client->scan_result_cb,
+                      &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->value);
+            break;
+        }
+
+        case BTIF_GATTC_RSSI_EVT:
+        {
+            btif_gattc_cb_t *p_btif_cb = (btif_gattc_cb_t*)p_param;
+            HAL_CBACK(bt_gatt_callbacks, client->read_remote_rssi_cb, p_btif_cb->client_if,
+                      &p_btif_cb->bd_addr, p_btif_cb->rssi, p_btif_cb->status);
+            break;
+        }
+
+        default:
+            ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
+            break;
+    }
+}
+
+static void bte_gattc_cback(tBTA_GATTC_EVT event, tBTA_GATTC *p_data)
+{
+    bt_status_t status = btif_transfer_context(btif_gattc_upstreams_evt,
+                    (uint16_t) event, (void*)p_data, sizeof(tBTA_GATTC), NULL);
+    ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void bte_scan_results_cb (tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data)
+{
+    btif_gattc_cb_t btif_cb;
+    uint8_t len;
+
+    switch (event)
+    {
+        case BTA_DM_INQ_RES_EVT:
+        {
+            bdcpy(btif_cb.bd_addr.address, p_data->inq_res.bd_addr);
+            btif_cb.device_type = p_data->inq_res.device_type;
+            btif_cb.rssi = p_data->inq_res.rssi;
+            btif_cb.addr_type = p_data->inq_res.ble_addr_type;
+            if (p_data->inq_res.p_eir)
+            {
+                memcpy(btif_cb.value, p_data->inq_res.p_eir, 62);
+                if (BTA_CheckEirData(p_data->inq_res.p_eir, BTM_EIR_COMPLETE_LOCAL_NAME_TYPE,
+                                      &len))
+                {
+                    p_data->inq_res.remt_name_not_required  = TRUE;
+                }
+            }
+        }
+        break;
+
+        case BTA_DM_INQ_CMPL_EVT:
+        {
+            BTIF_TRACE_DEBUG2("%s  BLE observe complete. Num Resp %d",
+                              __FUNCTION__,p_data->inq_cmpl.num_resps);
+            return;
+        }
+
+        default:
+        BTIF_TRACE_WARNING2("%s : Unknown event 0x%x", __FUNCTION__, event);
+        return;
+    }
+    btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATT_OBSERVE_EVT,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static void btm_read_rssi_cb (tBTM_RSSI_RESULTS *p_result)
+{
+    btif_gattc_cb_t btif_cb;
+
+    bdcpy(btif_cb.bd_addr.address, p_result->rem_bda);
+    btif_cb.rssi = p_result->rssi;
+    btif_cb.status = p_result->status;
+    btif_cb.client_if = rssi_request_client_if;
+    btif_transfer_context(btif_gattc_upstreams_evt, BTIF_GATTC_RSSI_EVT,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+
+static void btgattc_handle_event(uint16_t event, char* p_param)
+{
+    tBTA_GATT_STATUS           status;
+    tBT_UUID                   uuid;
+    tBTA_GATT_SRVC_ID          srvc_id;
+    tGATT_CHAR_PROP            out_char_prop;
+    tBTA_GATTC_CHAR_ID         in_char_id;
+    tBTA_GATTC_CHAR_ID         out_char_id;
+    tBTA_GATTC_CHAR_DESCR_ID   in_char_descr_id;
+    tBTA_GATTC_CHAR_DESCR_ID   out_char_descr_id;
+    tBTA_GATTC_INCL_SVC_ID     in_incl_svc_id;
+    tBTA_GATTC_INCL_SVC_ID     out_incl_svc_id;
+    tBTA_GATT_UNFMT            descr_val;
+
+    btif_gattc_cb_t* p_cb = (btif_gattc_cb_t*)p_param;
+    if (!p_cb) return;
+
+    ALOGD("%s: Event %d", __FUNCTION__, event);
+
+    switch (event)
+    {
+        case BTIF_GATTC_REGISTER_APP:
+            btif_to_bta_uuid(&uuid, &p_cb->uuid);
+            BTA_GATTC_AppRegister(&uuid, bte_gattc_cback);
+            break;
+
+        case BTIF_GATTC_UNREGISTER_APP:
+            BTA_GATTC_AppDeregister(p_cb->client_if);
+            break;
+
+        case BTIF_GATTC_SCAN_START:
+            btif_gattc_init_dev_cb();
+            BTA_DmBleObserve(TRUE, 0, bte_scan_results_cb);
+            break;
+
+        case BTIF_GATTC_SCAN_STOP:
+            BTA_DmBleObserve(FALSE, 0, 0);
+            break;
+
+        case BTIF_GATTC_OPEN:
+            if (!p_cb->is_direct)
+                BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+
+            BTA_GATTC_Open(p_cb->client_if, p_cb->bd_addr.address, p_cb->is_direct);
+            break;
+
+        case BTIF_GATTC_CLOSE:
+            // Disconnect establiched connections
+            if (p_cb->conn_id != 0)
+                BTA_GATTC_Close(p_cb->conn_id);
+            else
+                BTA_GATTC_CancelOpen(p_cb->client_if, p_cb->bd_addr.address, TRUE);
+
+            // Cancel pending background connections (remove from whitelist)
+            BTA_GATTC_CancelOpen(p_cb->client_if, p_cb->bd_addr.address, FALSE);
+            break;
+
+        case BTIF_GATTC_SEARCH_SERVICE:
+        {
+            if (p_cb->search_all)
+            {
+                BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, NULL);
+            } else {
+                btif_to_bta_uuid(&uuid, &p_cb->uuid);
+                BTA_GATTC_ServiceSearchRequest(p_cb->conn_id, &uuid);
+            }
+            break;
+        }
+
+        case BTIF_GATTC_GET_FIRST_CHAR:
+        {
+            btgatt_char_id_t char_id;
+            btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+            status = BTA_GATTC_GetFirstChar(p_cb->conn_id, &srvc_id, NULL,
+                                            &out_char_id, &out_char_prop);
+
+            if (status == 0)
+                bta_to_btif_char_id(&char_id, &out_char_id.char_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_characteristic_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &char_id, out_char_prop);
+            break;
+        }
+
+        case BTIF_GATTC_GET_NEXT_CHAR:
+        {
+            btgatt_char_id_t char_id;
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            status = BTA_GATTC_GetNextChar(p_cb->conn_id, &in_char_id, NULL,
+                                            &out_char_id, &out_char_prop);
+
+            if (status == 0)
+                bta_to_btif_char_id(&char_id, &out_char_id.char_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_characteristic_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &char_id, out_char_prop);
+            break;
+        }
+
+        case BTIF_GATTC_GET_FIRST_CHAR_DESCR:
+        {
+            bt_uuid_t descr_id;
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            status = BTA_GATTC_GetFirstCharDescr(p_cb->conn_id, &in_char_id, NULL,
+                                                    &out_char_descr_id);
+
+            if (status == 0)
+                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &p_cb->char_id, &descr_id);
+            break;
+        }
+
+        case BTIF_GATTC_GET_NEXT_CHAR_DESCR:
+        {
+            bt_uuid_t descr_id;
+            btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+            status = BTA_GATTC_GetNextCharDescr(p_cb->conn_id, &in_char_descr_id
+                                        , NULL, &out_char_descr_id);
+
+            if (status == 0)
+                bta_to_btif_uuid(&descr_id, &out_char_descr_id.descr_type);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_descriptor_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &p_cb->char_id, &descr_id);
+            break;
+        }
+
+        case BTIF_GATTC_GET_FIRST_INCL_SERVICE:
+        {
+            btgatt_srvc_id_t incl_srvc_id;
+            btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+
+            status = BTA_GATTC_GetFirstIncludedService(p_cb->conn_id,
+                        &srvc_id, NULL, &out_incl_svc_id);
+
+            bta_to_btif_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_included_service_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &incl_srvc_id);
+            break;
+        }
+
+        case BTIF_GATTC_GET_NEXT_INCL_SERVICE:
+        {
+            btgatt_srvc_id_t incl_srvc_id;
+            btif_to_bta_srvc_id(&in_incl_svc_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_srvc_id(&in_incl_svc_id.incl_svc_id, &p_cb->incl_srvc_id);
+
+            status = BTA_GATTC_GetNextIncludedService(p_cb->conn_id,
+                        &in_incl_svc_id, NULL, &out_incl_svc_id);
+
+            bta_to_btif_srvc_id(&incl_srvc_id, &out_incl_svc_id.incl_svc_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->get_included_service_cb,
+                p_cb->conn_id, status, &p_cb->srvc_id,
+                &incl_srvc_id);
+            break;
+        }
+
+        case BTIF_GATTC_READ_CHAR:
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            BTA_GATTC_ReadCharacteristic(p_cb->conn_id, &in_char_id, p_cb->auth_req);
+            break;
+
+        case BTIF_GATTC_READ_CHAR_DESCR:
+            btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+            BTA_GATTC_ReadCharDescr(p_cb->conn_id, &in_char_descr_id, p_cb->auth_req);
+            break;
+
+        case BTIF_GATTC_WRITE_CHAR:
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            BTA_GATTC_WriteCharValue(p_cb->conn_id, &in_char_id,
+                                     p_cb->write_type,
+                                     p_cb->len,
+                                     p_cb->value,
+                                     p_cb->auth_req);
+            break;
+
+        case BTIF_GATTC_WRITE_CHAR_DESCR:
+            btif_to_bta_srvc_id(&in_char_descr_id.char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_descr_id.char_id.char_id, &p_cb->char_id);
+            btif_to_bta_uuid(&in_char_descr_id.descr_type, &p_cb->uuid);
+
+            descr_val.len = p_cb->len;
+            descr_val.p_value = p_cb->value;
+
+            BTA_GATTC_WriteCharDescr(p_cb->conn_id, &in_char_descr_id,
+                                     p_cb->write_type, &descr_val,
+                                     p_cb->auth_req);
+            break;
+
+        case BTIF_GATTC_EXECUTE_WRITE:
+            BTA_GATTC_ExecuteWrite(p_cb->conn_id, p_cb->action);
+            break;
+
+        case BTIF_GATTC_REG_FOR_NOTIFICATION:
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            status = BTA_GATTC_RegisterForNotifications(p_cb->client_if,
+                                    p_cb->bd_addr.address, &in_char_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
+                p_cb->conn_id, 1, status, &p_cb->srvc_id,
+                &p_cb->char_id);
+            break;
+
+        case BTIF_GATTC_DEREG_FOR_NOTIFICATION:
+            btif_to_bta_srvc_id(&in_char_id.srvc_id, &p_cb->srvc_id);
+            btif_to_bta_char_id(&in_char_id.char_id, &p_cb->char_id);
+
+            status = BTA_GATTC_DeregisterForNotifications(p_cb->client_if,
+                                        p_cb->bd_addr.address, &in_char_id);
+
+            HAL_CBACK(bt_gatt_callbacks, client->register_for_notification_cb,
+                p_cb->conn_id, 0, status, &p_cb->srvc_id,
+                &p_cb->char_id);
+            break;
+
+        case BTIF_GATTC_REFRESH:
+            BTA_GATTC_Refresh(p_cb->bd_addr.address);
+            break;
+
+        case BTIF_GATTC_READ_RSSI:
+            rssi_request_client_if = p_cb->client_if;
+            BTM_ReadRSSI (p_cb->bd_addr.address, (tBTM_CMPL_CB *)btm_read_rssi_cb);
+            break;
+
+        default:
+            ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
+            break;
+    }
+}
+
+/*******************************************************************************
+**  Client API Functions
+********************************************************************************/
+
+static bt_status_t btif_gattc_register_app(bt_uuid_t *uuid)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REGISTER_APP,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_unregister_app(int client_if )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_UNREGISTER_APP,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_scan( int client_if, bool start )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    return btif_transfer_context(btgattc_handle_event, start ? BTIF_GATTC_SCAN_START : BTIF_GATTC_SCAN_STOP,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_open(int client_if, const bt_bdaddr_t *bd_addr, bool is_direct )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    btif_cb.is_direct = is_direct ? 1 : 0;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_OPEN,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_close( int client_if, const bt_bdaddr_t *bd_addr, int conn_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_CLOSE,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_refresh( int client_if, const bt_bdaddr_t *bd_addr )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REFRESH,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_search_service(int conn_id, bt_uuid_t *filter_uuid )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.search_all = filter_uuid ? 0 : 1;
+    if (filter_uuid)
+        memcpy(&btif_cb.uuid, filter_uuid, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_SEARCH_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_characteristic( int conn_id
+        , btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *start_char_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    if (start_char_id)
+    {
+        memcpy(&btif_cb.char_id, start_char_id, sizeof(btgatt_char_id_t));
+        return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_CHAR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+    }
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_CHAR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_descriptor( int conn_id
+        , btgatt_srvc_id_t *srvc_id, btgatt_char_id_t *char_id
+        , bt_uuid_t *start_descr_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    if (start_descr_id)
+    {
+        memcpy(&btif_cb.uuid, start_descr_id, sizeof(bt_uuid_t));
+        return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_CHAR_DESCR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+    }
+
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_CHAR_DESCR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_get_included_service(int conn_id, btgatt_srvc_id_t *srvc_id,
+                                                   btgatt_srvc_id_t *start_incl_srvc_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    if (start_incl_srvc_id)
+    {
+        memcpy(&btif_cb.incl_srvc_id, start_incl_srvc_id, sizeof(btgatt_srvc_id_t));
+        return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_NEXT_INCL_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+    }
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_GET_FIRST_INCL_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_char(int conn_id, btgatt_srvc_id_t* srvc_id,
+                                        btgatt_char_id_t* char_id, int auth_req )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.auth_req = (uint8_t) auth_req;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_CHAR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_char_descr(int conn_id, btgatt_srvc_id_t* srvc_id,
+                                              btgatt_char_id_t* char_id, bt_uuid_t* descr_id,
+                                              int auth_req )
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.auth_req = (uint8_t) auth_req;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    memcpy(&btif_cb.uuid, descr_id, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_CHAR_DESCR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_write_char(int conn_id, btgatt_srvc_id_t* srvc_id,
+                                         btgatt_char_id_t* char_id, int write_type,
+                                         int len, int auth_req, char* p_value)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.auth_req = (uint8_t) auth_req;
+    btif_cb.write_type = (uint8_t) write_type;
+    btif_cb.len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    memcpy(btif_cb.value, p_value, btif_cb.len);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_WRITE_CHAR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_write_char_descr(int conn_id, btgatt_srvc_id_t* srvc_id,
+                                               btgatt_char_id_t* char_id, bt_uuid_t* descr_id,
+                                               int write_type, int len, int auth_req,
+                                               char* p_value)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.auth_req = (uint8_t) auth_req;
+    btif_cb.write_type = (uint8_t) write_type;
+    btif_cb.len = len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    memcpy(&btif_cb.uuid, descr_id, sizeof(bt_uuid_t));
+    memcpy(btif_cb.value, p_value, btif_cb.len);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_WRITE_CHAR_DESCR,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_execute_write(int conn_id, int execute)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.action = (uint8_t) execute;
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_EXECUTE_WRITE,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_reg_for_notification(int client_if, const bt_bdaddr_t *bd_addr,
+                                                   btgatt_srvc_id_t* srvc_id,
+                                                   btgatt_char_id_t* char_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_REG_FOR_NOTIFICATION,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_dereg_for_notification(int client_if, const bt_bdaddr_t *bd_addr,
+                                                     btgatt_srvc_id_t* srvc_id,
+                                                     btgatt_char_id_t* char_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    memcpy(&btif_cb.char_id, char_id, sizeof(btgatt_char_id_t));
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_DEREG_FOR_NOTIFICATION,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static bt_status_t btif_gattc_read_remote_rssi(int client_if, const bt_bdaddr_t *bd_addr)
+{
+    CHECK_BTGATT_INIT();
+    btif_gattc_cb_t btif_cb;
+    btif_cb.client_if = (uint8_t) client_if;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgattc_handle_event, BTIF_GATTC_READ_RSSI,
+                                 (char*) &btif_cb, sizeof(btif_gattc_cb_t), NULL);
+}
+
+static int btif_gattc_get_device_type( const bt_bdaddr_t *bd_addr )
+{
+    int device_type = 0;
+    char bd_addr_str[18] = {0};
+
+    bd2str(bd_addr, &bd_addr_str);
+    if (btif_config_get_int("Remote", bd_addr_str, "DevType", &device_type))
+        return device_type;
+    return 0;
+}
+
+extern bt_status_t btif_gattc_test_command_impl(int command, btgatt_test_params_t* params);
+
+static bt_status_t btif_gattc_test_command(int command, btgatt_test_params_t* params)
+{
+    return btif_gattc_test_command_impl(command, params);
+}
+
+
+const btgatt_client_interface_t btgattClientInterface = {
+    btif_gattc_register_app,
+    btif_gattc_unregister_app,
+    btif_gattc_scan,
+    btif_gattc_open,
+    btif_gattc_close,
+    btif_gattc_refresh,
+    btif_gattc_search_service,
+    btif_gattc_get_included_service,
+    btif_gattc_get_characteristic,
+    btif_gattc_get_descriptor,
+    btif_gattc_read_char,
+    btif_gattc_write_char,
+    btif_gattc_read_char_descr,
+    btif_gattc_write_char_descr,
+    btif_gattc_execute_write,
+    btif_gattc_reg_for_notification,
+    btif_gattc_dereg_for_notification,
+    btif_gattc_read_remote_rssi,
+    btif_gattc_get_device_type,
+    btif_gattc_test_command
+};
+
+#endif
diff --git a/btif/src/btif_gatt_server.c b/btif/src/btif_gatt_server.c
new file mode 100644
index 0000000..9de36f9
--- /dev/null
+++ b/btif/src/btif_gatt_server.c
@@ -0,0 +1,579 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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.
+ *
+ ******************************************************************************/
+
+
+/************************************************************************************
+ *
+ *  Filename:      btif_gatt_server.c
+ *
+ *  Description:   GATT server implementation
+ *
+ ***********************************************************************************/
+
+#include <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_dm.h"
+#include "btif_storage.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+/************************************************************************************
+**  Constants & Macros
+************************************************************************************/
+
+#define CHECK_BTGATT_INIT() if (bt_gatt_callbacks == NULL)\
+    {\
+        ALOGW("%s: BTGATT not initialized", __FUNCTION__);\
+        return BT_STATUS_NOT_READY;\
+    } else {\
+        ALOGD("%s", __FUNCTION__);\
+    }
+
+
+typedef enum {
+    BTIF_GATTS_REGISTER_APP = 2000,
+    BTIF_GATTS_UNREGISTER_APP,
+    BTIF_GATTS_OPEN,
+    BTIF_GATTS_CLOSE,
+    BTIF_GATTS_CREATE_SERVICE,
+    BTIF_GATTS_ADD_INCLUDED_SERVICE,
+    BTIF_GATTS_ADD_CHARACTERISTIC,
+    BTIF_GATTS_ADD_DESCRIPTOR,
+    BTIF_GATTS_START_SERVICE,
+    BTIF_GATTS_STOP_SERVICE,
+    BTIF_GATTS_DELETE_SERVICE,
+    BTIF_GATTS_SEND_INDICATION,
+    BTIF_GATTS_SEND_RESPONSE
+} btif_gatts_event_t;
+
+/************************************************************************************
+**  Local type definitions
+************************************************************************************/
+
+typedef struct
+{
+    uint8_t             value[BTGATT_MAX_ATTR_LEN];
+    btgatt_response_t   response;
+    btgatt_srvc_id_t    srvc_id;
+    bt_bdaddr_t         bd_addr;
+    bt_uuid_t           uuid;
+    uint32_t            trans_id;
+    uint16_t            conn_id;
+    uint16_t            srvc_handle;
+    uint16_t            incl_handle;
+    uint16_t            attr_handle;
+    uint16_t            permissions;
+    uint16_t            len;
+    uint8_t             server_if;
+    uint8_t             is_direct;
+    uint8_t             num_handles;
+    uint8_t             properties;
+    uint8_t             transport;
+    uint8_t             confirm;
+    uint8_t             status;
+} __attribute__((packed)) btif_gatts_cb_t;
+
+
+/************************************************************************************
+**  Static variables
+************************************************************************************/
+
+extern const btgatt_callbacks_t *bt_gatt_callbacks;
+
+
+/************************************************************************************
+**  Static functions
+************************************************************************************/
+
+static void btapp_gatts_handle_cback(uint16_t event, char* p_param)
+{
+    ALOGD("%s: Event %d", __FUNCTION__, event);
+
+    tBTA_GATTS *p_data = (tBTA_GATTS*)p_param;
+    switch (event)
+    {
+        case BTA_GATTS_REG_EVT:
+        {
+            bt_uuid_t app_uuid;
+            bta_to_btif_uuid(&app_uuid, &p_data->reg_oper.uuid);
+            HAL_CBACK(bt_gatt_callbacks, server->register_server_cb
+                , p_data->reg_oper.status
+                , p_data->reg_oper.server_if
+                , &app_uuid
+            );
+            break;
+        }
+
+        case BTA_GATTS_DEREG_EVT:
+            break;
+
+        case BTA_GATTS_CONNECT_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->conn.remote_bda);
+
+            btif_gatt_check_encrypted_link(p_data->conn.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
+                      p_data->conn.conn_id, TRUE, &bda);
+            break;
+        }
+
+        case BTA_GATTS_DISCONNECT_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->conn.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->connection_cb,
+                      p_data->conn.conn_id, FALSE, &bda);
+
+            btif_gatt_remove_encrypted_link(p_data->conn.remote_bda);
+            break;
+        }
+
+        case BTA_GATTS_CREATE_EVT:
+        {
+            btgatt_srvc_id_t srvc_id;
+            srvc_id.is_primary = p_data->create.is_primary;
+            srvc_id.id.inst_id = p_data->create.svc_instance;
+            bta_to_btif_uuid(&srvc_id.id.uuid, &p_data->create.uuid);
+
+            HAL_CBACK(bt_gatt_callbacks, server->service_added_cb,
+                      p_data->create.status, p_data->create.server_if, &srvc_id,
+                      p_data->create.service_id
+            );
+        }
+        break;
+
+        case BTA_GATTS_ADD_INCL_SRVC_EVT:
+            HAL_CBACK(bt_gatt_callbacks, server->included_service_added_cb,
+                      p_data->add_result.status,
+                      p_data->add_result.server_if,
+                      p_data->add_result.service_id,
+                      p_data->add_result.attr_id);
+            break;
+
+        case BTA_GATTS_ADD_CHAR_EVT:
+        {
+            bt_uuid_t uuid;
+            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
+
+            HAL_CBACK(bt_gatt_callbacks, server->characteristic_added_cb,
+                      p_data->add_result.status,
+                      p_data->add_result.server_if,
+                      &uuid,
+                      p_data->add_result.service_id,
+                      p_data->add_result.attr_id);
+            break;
+        }
+
+        case BTA_GATTS_ADD_CHAR_DESCR_EVT:
+        {
+            bt_uuid_t uuid;
+            bta_to_btif_uuid(&uuid, &p_data->add_result.char_uuid);
+
+            HAL_CBACK(bt_gatt_callbacks, server->descriptor_added_cb,
+                      p_data->add_result.status,
+                      p_data->add_result.server_if,
+                      &uuid,
+                      p_data->add_result.service_id,
+                      p_data->add_result.attr_id);
+            break;
+        }
+
+        case BTA_GATTS_START_EVT:
+            HAL_CBACK(bt_gatt_callbacks, server->service_started_cb,
+                      p_data->srvc_oper.status,
+                      p_data->srvc_oper.server_if,
+                      p_data->srvc_oper.service_id);
+            break;
+
+        case BTA_GATTS_STOP_EVT:
+            HAL_CBACK(bt_gatt_callbacks, server->service_stopped_cb,
+                      p_data->srvc_oper.status,
+                      p_data->srvc_oper.server_if,
+                      p_data->srvc_oper.service_id);
+            break;
+
+        case BTA_GATTS_DELELTE_EVT:
+            HAL_CBACK(bt_gatt_callbacks, server->service_deleted_cb,
+                      p_data->srvc_oper.status,
+                      p_data->srvc_oper.server_if,
+                      p_data->srvc_oper.service_id);
+            break;
+
+        case BTA_GATTS_READ_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->req_data.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->request_read_cb,
+                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+                      p_data->req_data.p_data->read_req.handle,
+                      p_data->req_data.p_data->read_req.offset,
+                      p_data->req_data.p_data->read_req.is_long);
+            break;
+        }
+
+        case BTA_GATTS_WRITE_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->req_data.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->request_write_cb,
+                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+                      p_data->req_data.p_data->write_req.handle,
+                      p_data->req_data.p_data->write_req.offset,
+                      p_data->req_data.p_data->write_req.len,
+                      p_data->req_data.p_data->write_req.need_rsp,
+                      p_data->req_data.p_data->write_req.is_prep,
+                      p_data->req_data.p_data->write_req.value);
+            break;
+        }
+
+        case BTA_GATTS_EXEC_WRITE_EVT:
+        {
+            bt_bdaddr_t bda;
+            bdcpy(bda.address, p_data->req_data.remote_bda);
+
+            HAL_CBACK(bt_gatt_callbacks, server->request_exec_write_cb,
+                      p_data->req_data.conn_id,p_data->req_data.trans_id, &bda,
+                      p_data->req_data.p_data->exec_write);
+            break;
+        }
+
+        case BTA_GATTS_MTU_EVT:
+        case BTA_GATTS_OPEN_EVT:
+        case BTA_GATTS_CANCEL_OPEN_EVT:
+        case BTA_GATTS_CLOSE_EVT:
+            ALOGD("%s: Empty event (%d)!", __FUNCTION__, event);
+            break;
+
+        default:
+            ALOGE("%s: Unhandled event (%d)!", __FUNCTION__, event);
+            break;
+    }
+}
+
+static void btapp_gatts_cback(tBTA_GATTS_EVT event, tBTA_GATTS *p_data)
+{
+    bt_status_t status;
+    status = btif_transfer_context(btapp_gatts_handle_cback, (uint16_t) event,
+        (void*)p_data, sizeof(tBTA_GATTS), NULL);
+    ASSERTC(status == BT_STATUS_SUCCESS, "Context transfer failed!", status);
+}
+
+static void btgatts_handle_event(uint16_t event, char* p_param)
+{
+    btif_gatts_cb_t* p_cb = (btif_gatts_cb_t*)p_param;
+    if (!p_cb) return;
+
+    ALOGD("%s: Event %d", __FUNCTION__, event);
+
+    switch (event)
+    {
+        case BTIF_GATTS_REGISTER_APP:
+        {
+            tBT_UUID uuid;
+            btif_to_bta_uuid(&uuid, &p_cb->uuid);
+            BTA_GATTS_AppRegister(&uuid, btapp_gatts_cback);
+            break;
+        }
+
+        case BTIF_GATTS_UNREGISTER_APP:
+            BTA_GATTS_AppDeregister(p_cb->server_if);
+            break;
+
+        case BTIF_GATTS_OPEN:
+            if (!p_cb->is_direct)
+                BTA_DmBleSetBgConnType(BTM_BLE_CONN_AUTO, NULL);
+            BTA_GATTS_Open(p_cb->server_if, p_cb->bd_addr.address,
+                           p_cb->is_direct);
+            break;
+
+        case BTIF_GATTS_CLOSE:
+            // Cancel pending foreground/background connections
+            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, TRUE);
+            BTA_GATTS_CancelOpen(p_cb->server_if, p_cb->bd_addr.address, FALSE);
+
+            // Close active connection
+            if (p_cb->conn_id != 0)
+                BTA_GATTS_Close(p_cb->conn_id);
+            break;
+
+        case BTIF_GATTS_CREATE_SERVICE:
+        {
+            tBTA_GATT_SRVC_ID srvc_id;
+            btif_to_bta_srvc_id(&srvc_id, &p_cb->srvc_id);
+            BTA_GATTS_CreateService(p_cb->server_if, &srvc_id.id.uuid,
+                                    srvc_id.id.inst_id, p_cb->num_handles,
+                                    srvc_id.is_primary);
+            break;
+        }
+
+        case BTIF_GATTS_ADD_INCLUDED_SERVICE:
+            BTA_GATTS_AddIncludeService(p_cb->srvc_handle, p_cb->incl_handle);
+            break;
+
+        case BTIF_GATTS_ADD_CHARACTERISTIC:
+        {
+            tBT_UUID uuid;
+            btif_to_bta_uuid(&uuid, &p_cb->uuid);
+
+            BTA_GATTS_AddCharacteristic(p_cb->srvc_handle, &uuid,
+                                        p_cb->permissions, p_cb->properties);
+            break;
+        }
+
+        case BTIF_GATTS_ADD_DESCRIPTOR:
+        {
+            tBT_UUID uuid;
+            btif_to_bta_uuid(&uuid, &p_cb->uuid);
+
+            BTA_GATTS_AddCharDescriptor(p_cb->srvc_handle, p_cb->permissions,
+                                         &uuid);
+            break;
+        }
+
+        case BTIF_GATTS_START_SERVICE:
+            BTA_GATTS_StartService(p_cb->srvc_handle, p_cb->transport);
+            break;
+
+        case BTIF_GATTS_STOP_SERVICE:
+            BTA_GATTS_StopService(p_cb->srvc_handle);
+            break;
+
+        case BTIF_GATTS_DELETE_SERVICE:
+            BTA_GATTS_DeleteService(p_cb->srvc_handle);
+            break;
+
+        case BTIF_GATTS_SEND_INDICATION:
+            BTA_GATTS_HandleValueIndication(p_cb->conn_id, p_cb->attr_handle,
+                                        p_cb->len, p_cb->value, p_cb->confirm);
+            // TODO: Might need to send an ACK if handle value indication is
+            //       invoked without need for confirmation.
+            break;
+
+        case BTIF_GATTS_SEND_RESPONSE:
+        {
+            tBTA_GATTS_RSP rsp_struct;
+            btgatt_response_t *p_rsp = &p_cb->response;
+            btif_to_bta_response(&rsp_struct, p_rsp);
+
+            BTA_GATTS_SendRsp(p_cb->conn_id, p_cb->trans_id,
+                              p_cb->status, &rsp_struct);
+
+            HAL_CBACK(bt_gatt_callbacks, server->response_confirmation_cb,
+                      0, rsp_struct.attr_value.handle);
+            break;
+        }
+
+        default:
+            ALOGE("%s: Unknown event (%d)!", __FUNCTION__, event);
+            break;
+    }
+}
+
+/************************************************************************************
+**  Server API Functions
+************************************************************************************/
+
+static bt_status_t btif_gatts_register_app(bt_uuid_t *uuid)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_REGISTER_APP,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_unregister_app( int server_if )
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_UNREGISTER_APP,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_open( int server_if, const bt_bdaddr_t *bd_addr, bool is_direct )
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.is_direct = is_direct ? 1 : 0;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_OPEN,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_close(int server_if, const bt_bdaddr_t *bd_addr, int conn_id)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    bdcpy(btif_cb.bd_addr.address, bd_addr->address);
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CLOSE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_service(int server_if, btgatt_srvc_id_t *srvc_id,
+                                          int num_handles)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.num_handles = (uint8_t) num_handles;
+    memcpy(&btif_cb.srvc_id, srvc_id, sizeof(btgatt_srvc_id_t));
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_CREATE_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_included_service(int server_if, int service_handle,
+                                                   int included_handle)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    btif_cb.incl_handle = (uint16_t) included_handle;
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_INCLUDED_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_characteristic(int server_if, int service_handle,
+                                                 bt_uuid_t *uuid, int properties,
+                                                 int permissions)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    btif_cb.properties = (uint8_t) properties;
+    btif_cb.permissions = (uint16_t) permissions;
+    memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_CHARACTERISTIC,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_add_descriptor(int server_if, int service_handle, bt_uuid_t *uuid,
+                                             int permissions)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    btif_cb.permissions = (uint16_t) permissions;
+    memcpy(&btif_cb.uuid, uuid, sizeof(bt_uuid_t));
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_ADD_DESCRIPTOR,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_start_service(int server_if, int service_handle, int transport)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    btif_cb.transport = (uint8_t) transport;
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_START_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_stop_service(int server_if, int service_handle)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_STOP_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_delete_service(int server_if, int service_handle)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.srvc_handle = (uint16_t) service_handle;
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_DELETE_SERVICE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_send_indication(int server_if, int attribute_handle, int conn_id,
+                                              int len, int confirm, char* p_value)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.server_if = (uint8_t) server_if;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.attr_handle = attribute_handle;
+    btif_cb.confirm = confirm;
+    btif_cb.len = len;
+    memcpy(btif_cb.value, p_value, len > BTGATT_MAX_ATTR_LEN ? BTGATT_MAX_ATTR_LEN : len);
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_INDICATION,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+static bt_status_t btif_gatts_send_response(int conn_id, int trans_id,
+                                            int status, btgatt_response_t *response)
+{
+    CHECK_BTGATT_INIT();
+    btif_gatts_cb_t btif_cb;
+    btif_cb.conn_id = (uint16_t) conn_id;
+    btif_cb.trans_id = (uint32_t) trans_id;
+    btif_cb.status = (uint8_t) status;
+    memcpy(&btif_cb.response, response, sizeof(btgatt_response_t));
+    return btif_transfer_context(btgatts_handle_event, BTIF_GATTS_SEND_RESPONSE,
+                                 (char*) &btif_cb, sizeof(btif_gatts_cb_t), NULL);
+}
+
+const btgatt_server_interface_t btgattServerInterface = {
+    btif_gatts_register_app,
+    btif_gatts_unregister_app,
+    btif_gatts_open,
+    btif_gatts_close,
+    btif_gatts_add_service,
+    btif_gatts_add_included_service,
+    btif_gatts_add_characteristic,
+    btif_gatts_add_descriptor,
+    btif_gatts_start_service,
+    btif_gatts_stop_service,
+    btif_gatts_delete_service,
+    btif_gatts_send_indication,
+    btif_gatts_send_response
+};
+
+#endif
diff --git a/btif/src/btif_gatt_test.c b/btif/src/btif_gatt_test.c
new file mode 100644
index 0000000..8c23d56
--- /dev/null
+++ b/btif/src/btif_gatt_test.c
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif_test"
+
+#include "btif_common.h"
+#include "btif_util.h"
+
+#if (defined(BLE_INCLUDED) && (BLE_INCLUDED == TRUE))
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+#include "bte_appl.h"
+
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+#include "btif_dm.h"
+
+#include "gatt_api.h"
+
+/*******************************************************************************
+ * Typedefs & Macros
+ *******************************************************************************/
+
+typedef struct
+{
+    tGATT_IF    gatt_if;
+    UINT16      conn_id;
+} btif_test_cb_t;
+
+/*******************************************************************************
+ * Static variables
+ *******************************************************************************/
+
+static const char * disc_name[GATT_DISC_MAX] =
+{
+    "Unknown",
+    "GATT_DISC_SRVC_ALL",
+    "GATT_DISC_SRVC_BY_UUID",
+    "GATT_DISC_INC_SRVC",
+    "GATT_DISC_CHAR",
+    "GATT_DISC_CHAR_DSCPT"
+};
+
+static btif_test_cb_t test_cb;
+
+/*******************************************************************************
+ * Callback functions
+ *******************************************************************************/
+
+static char * format_uuid(tBT_UUID bt_uuid, char *str_buf)
+{
+    int x = 0;
+
+    if (bt_uuid.len == LEN_UUID_16)
+    {
+        sprintf(str_buf, "0x%04x", bt_uuid.uu.uuid16);
+    }
+    else if (bt_uuid.len == LEN_UUID_128)
+    {
+        x += sprintf(&str_buf[x], "%02x%02x%02x%02x-%02x%02x-%02x%02x",
+                bt_uuid.uu.uuid128[15], bt_uuid.uu.uuid128[14],
+                bt_uuid.uu.uuid128[13], bt_uuid.uu.uuid128[12],
+                bt_uuid.uu.uuid128[11], bt_uuid.uu.uuid128[10],
+                bt_uuid.uu.uuid128[9], bt_uuid.uu.uuid128[8]);
+        sprintf(&str_buf[x], "%02x%02x-%02x%02x%02x%02x%02x%02x",
+                bt_uuid.uu.uuid128[7], bt_uuid.uu.uuid128[6],
+                bt_uuid.uu.uuid128[5], bt_uuid.uu.uuid128[4],
+                bt_uuid.uu.uuid128[3], bt_uuid.uu.uuid128[2],
+                bt_uuid.uu.uuid128[1], bt_uuid.uu.uuid128[0]);
+    }
+    else
+        sprintf(str_buf, "Unknown (len=%d)", bt_uuid.len);
+
+    return str_buf;
+}
+
+static void btif_test_connect_cback(tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+                                    BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+    ALOGD("%s: conn_id=%d, connected=%d", __FUNCTION__, conn_id, connected);
+    test_cb.conn_id = connected ? conn_id : 0;
+}
+
+static void btif_test_command_complete_cback(UINT16 conn_id, tGATTC_OPTYPE op,
+                                tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+{
+    ALOGD ("%s: op_code=0x%02x, conn_id=0x%x. status=0x%x",
+            __FUNCTION__, op, conn_id, status);
+
+    switch (op)
+    {
+        case GATTC_OPTYPE_READ:
+        case GATTC_OPTYPE_WRITE:
+        case GATTC_OPTYPE_CONFIG:
+        case GATTC_OPTYPE_EXE_WRITE:
+        case GATTC_OPTYPE_NOTIFICATION:
+            break;
+
+        case GATTC_OPTYPE_INDICATION:
+            GATTC_SendHandleValueConfirm(conn_id, p_data->handle);
+            break;
+
+        default:
+            ALOGD ("%s: Unknown op_code (0x%02x)", __FUNCTION__, op);
+            break;
+    }
+}
+
+
+static void btif_test_discovery_result_cback(UINT16 conn_id, tGATT_DISC_TYPE disc_type,
+                                           tGATT_DISC_RES *p_data)
+{
+    char    str_buf[50];
+
+    ALOGD("------ GATT Discovery result %-22s -------", disc_name[disc_type]);
+    ALOGD("      Attribute handle: 0x%04x (%d)", p_data->handle, p_data->handle);
+
+    if (disc_type != GATT_DISC_CHAR_DSCPT) {
+        ALOGD("        Attribute type: %s", format_uuid(p_data->type, str_buf));
+    }
+
+    switch (disc_type)
+    {
+        case GATT_DISC_SRVC_ALL:
+            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+                  p_data->handle, p_data->value.group_value.e_handle,
+                  p_data->handle, p_data->value.group_value.e_handle);
+            ALOGD("          Service UUID: %s",
+                    format_uuid(p_data->value.group_value.service_type, str_buf));
+            break;
+
+        case GATT_DISC_SRVC_BY_UUID:
+            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+                  p_data->handle, p_data->value.handle,
+                  p_data->handle, p_data->value.handle);
+            break;
+
+        case GATT_DISC_INC_SRVC:
+            ALOGD("          Handle range: 0x%04x ~ 0x%04x (%d ~ %d)",
+                  p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle,
+                  p_data->value.incl_service.s_handle, p_data->value.incl_service.e_handle);
+            ALOGD("          Service UUID: %s",
+                  format_uuid(p_data->value.incl_service.service_type, str_buf));
+            break;
+
+        case GATT_DISC_CHAR:
+            ALOGD("            Properties: 0x%02x",
+                  p_data->value.dclr_value.char_prop);
+            ALOGD("   Characteristic UUID: %s",
+                  format_uuid(p_data->value.dclr_value.char_uuid, str_buf));
+            break;
+
+        case GATT_DISC_CHAR_DSCPT:
+            ALOGD("       Descriptor UUID: %s", format_uuid(p_data->type, str_buf));
+            break;
+    }
+
+    ALOGD("-----------------------------------------------------------");
+}
+
+static void btif_test_discovery_complete_cback(UINT16 conn_id,
+                                               tGATT_DISC_TYPE disc_type,
+                                               tGATT_STATUS status)
+{
+    ALOGD("%s: status=%d", __FUNCTION__, status);
+}
+
+static tGATT_CBACK btif_test_callbacks =
+{
+    btif_test_connect_cback ,
+    btif_test_command_complete_cback,
+    btif_test_discovery_result_cback,
+    btif_test_discovery_complete_cback,
+    NULL
+};
+
+/*******************************************************************************
+ * Implementation
+ *******************************************************************************/
+
+bt_status_t btif_gattc_test_command_impl(uint16_t command, btgatt_test_params_t* params)
+{
+    switch(command) {
+        case 0x01: /* Enable */
+        {
+            ALOGD("%s: ENABLE - enable=%d", __FUNCTION__, params->u1);
+            if (params->u1)
+            {
+                tBT_UUID app_uuid = {LEN_UUID_128,{0xAE}};
+                test_cb.gatt_if = GATT_Register(&app_uuid, &btif_test_callbacks);
+                GATT_StartIf(test_cb.gatt_if);
+            } else {
+                GATT_Deregister(test_cb.gatt_if);
+                test_cb.gatt_if = 0;
+            }
+            break;
+        }
+
+        case 0x02: /* Connect */
+        {
+            ALOGD("%s: CONNECT - device=%02x:%02x:%02x:%02x:%02x:%02x (dev_type=%d)",
+                __FUNCTION__,
+                params->bda1->address[0], params->bda1->address[1],
+                params->bda1->address[2], params->bda1->address[3],
+                params->bda1->address[4], params->bda1->address[5],
+                params->u1);
+
+            if (params->u1 == BT_DEVICE_TYPE_BLE)
+                BTM_SecAddBleDevice(params->bda1->address, NULL, BT_DEVICE_TYPE_BLE, 0);
+
+            if ( !GATT_Connect(test_cb.gatt_if, params->bda1->address, TRUE) )
+            {
+                ALOGE("%s: GATT_Connect failed!", __FUNCTION__);
+            }
+            break;
+        }
+
+        case 0x03: /* Disconnect */
+        {
+            ALOGD("%s: DISCONNECT - conn_id=%d", __FUNCTION__, test_cb.conn_id);
+            GATT_Disconnect(test_cb.conn_id);
+            break;
+        }
+
+        case 0x04: /* Discover */
+        {
+            char buf[50] = {0};
+            tGATT_DISC_PARAM        param;
+            memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+            if (params->u1 >= GATT_DISC_MAX)
+            {
+                ALOGE("%s: DISCOVER - Invalid type (%d)!", __FUNCTION__, params->u1);
+                return 0;
+            }
+
+            param.s_handle = params->u2;
+            param.e_handle = params->u3;
+            btif_to_bta_uuid(&param.service, params->uuid1);
+
+            ALOGD("%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
+                  __FUNCTION__, disc_name[params->u1], test_cb.conn_id,
+                  format_uuid(param.service, buf), params->u2, params->u3);
+            GATTC_Discover(test_cb.conn_id, params->u1, &param);
+            break;
+        }
+
+        case 0xF0: /* Pairing configuration */
+            ALOGD("%s: Setting pairing config auth=%d, iocaps=%d, keys=%d/%d/%d",
+                  __FUNCTION__, params->u1, params->u2, params->u3, params->u4,
+                  params->u5);
+
+            bte_appl_cfg.ble_auth_req = params->u1;
+            bte_appl_cfg.ble_io_cap = params->u2;
+            bte_appl_cfg.ble_init_key = params->u3;
+            bte_appl_cfg.ble_resp_key = params->u4;
+            bte_appl_cfg.ble_max_key_size = params->u5;
+            break;
+
+        default:
+            ALOGE("%s: UNKNOWN TEST COMMAND 0x%02x", __FUNCTION__, command);
+            break;
+    }
+    return 0;
+}
+
+#endif
diff --git a/btif/src/btif_gatt_util.c b/btif/src/btif_gatt_util.c
new file mode 100644
index 0000000..a3cbc3d
--- /dev/null
+++ b/btif/src/btif_gatt_util.c
@@ -0,0 +1,351 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 <hardware/bluetooth.h>
+#include <hardware/bt_gatt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#define LOG_TAG "BtGatt.btif"
+
+#include "bta_api.h"
+#include "bta_gatt_api.h"
+#include "bd.h"
+#include "btif_storage.h"
+
+#include "btif_common.h"
+#include "btif_dm.h"
+#include "btif_util.h"
+#include "btif_gatt.h"
+#include "btif_gatt_util.h"
+
+#define GATTC_READ_VALUE_TYPE_VALUE          0x0000  /* Attribute value itself */
+#define GATTC_READ_VALUE_TYPE_AGG_FORMAT     0x2905  /* Characteristic Aggregate Format*/
+
+#define BTIF_GATT_MAX_ENC_LINK_RECORDS       10
+
+typedef struct
+{
+    BD_ADDR         bd_addr;
+    BOOLEAN         in_use;
+}__attribute__((packed)) btif_gatt_encrypted_link_t;
+
+static char BASE_UUID[16] = {
+    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
+    0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static btif_gatt_encrypted_link_t encrypted_links[BTIF_GATT_MAX_ENC_LINK_RECORDS];
+
+int uuidType(unsigned char* p_uuid)
+{
+    int i = 0;
+    int match = 0;
+    int all_zero = 1;
+
+    for(i = 0; i != 16; ++i)
+    {
+        if (i == 12 || i == 13)
+            continue;
+
+        if (p_uuid[i] == BASE_UUID[i])
+            ++match;
+
+        if (p_uuid[i] != 0)
+            all_zero = 0;
+    }
+    if (all_zero)
+        return 0;
+    if (match == 12)
+        return LEN_UUID_32;
+    if (match == 14)
+        return LEN_UUID_16;
+    return LEN_UUID_128;
+}
+
+/*******************************************************************************
+ * BTIF -> BTA conversion functions
+ *******************************************************************************/
+
+void btif_to_bta_uuid(tBT_UUID *p_dest, bt_uuid_t *p_src)
+{
+    char *p_byte = (char*)p_src;
+    int i = 0;
+
+    p_dest->len = uuidType(p_src->uu);
+
+    switch (p_dest->len)
+    {
+        case LEN_UUID_16:
+            p_dest->uu.uuid16 = (p_src->uu[13] << 8) + p_src->uu[12];
+            break;
+
+        case LEN_UUID_32:
+            p_dest->uu.uuid32  = (p_src->uu[13] <<  8) + p_src->uu[12];
+            p_dest->uu.uuid32 += (p_src->uu[15] << 24) + (p_src->uu[14] << 16);
+            break;
+
+        case LEN_UUID_128:
+            for(i = 0; i != 16; ++i)
+                p_dest->uu.uuid128[i] = p_byte[i];
+            break;
+
+        default:
+            ALOGE("%s: Unknown UUID length %d!", __FUNCTION__, p_dest->len);
+            break;
+    }
+}
+
+void btif_to_bta_char_id(tBTA_GATT_ID *p_dest, btgatt_char_id_t *p_src)
+{
+    p_dest->inst_id = p_src->inst_id;
+    btif_to_bta_uuid(&p_dest->uuid, &p_src->uuid);
+}
+
+void btif_to_bta_srvc_id(tBTA_GATT_SRVC_ID *p_dest, btgatt_srvc_id_t *p_src)
+{
+    p_dest->id.inst_id = p_src->id.inst_id;
+    btif_to_bta_uuid(&p_dest->id.uuid, &p_src->id.uuid);
+    p_dest->is_primary = p_src->is_primary;
+}
+
+void btif_to_bta_response(tBTA_GATTS_RSP *p_dest, btgatt_response_t* p_src)
+{
+    p_dest->attr_value.auth_req = p_src->attr_value.auth_req;
+    p_dest->attr_value.handle   = p_src->attr_value.handle;
+    p_dest->attr_value.len      = p_src->attr_value.len;
+    p_dest->attr_value.offset   = p_src->attr_value.offset;
+    memcpy(p_dest->attr_value.value, p_src->attr_value.value, GATT_MAX_ATTR_LEN);
+}
+
+/*******************************************************************************
+ * BTA -> BTIF conversion functions
+ *******************************************************************************/
+
+void bta_to_btif_uuid(bt_uuid_t *p_dest, tBT_UUID *p_src)
+{
+    int i = 0;
+
+    if (p_src->len == LEN_UUID_16 || p_src->len == LEN_UUID_32)
+    {
+        for(i=0; i != 16; ++i)
+            p_dest->uu[i] = BASE_UUID[i];
+    }
+
+    switch (p_src->len)
+    {
+        case 0:
+            break;
+
+        case LEN_UUID_16:
+            p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+            p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+            break;
+
+        case LEN_UUID_32:
+            p_dest->uu[12] = p_src->uu.uuid16 & 0xff;
+            p_dest->uu[13] = (p_src->uu.uuid16 >> 8) & 0xff;
+            p_dest->uu[14] = (p_src->uu.uuid32 >> 16) & 0xff;
+            p_dest->uu[15] = (p_src->uu.uuid32 >> 24) & 0xff;
+            break;
+
+        case LEN_UUID_128:
+            for(i=0; i != 16; ++i)
+                p_dest->uu[i] = p_src->uu.uuid128[i];
+            break;
+
+        default:
+            ALOGE("%s: Unknown UUID length %d!", __FUNCTION__, p_src->len);
+            break;
+    }
+}
+
+
+void bta_to_btif_char_id(btgatt_char_id_t *p_dest, tBTA_GATT_ID *p_src)
+{
+    p_dest->inst_id = p_src->inst_id;
+    bta_to_btif_uuid(&p_dest->uuid, &p_src->uuid);
+}
+
+void bta_to_btif_srvc_id(btgatt_srvc_id_t *p_dest, tBTA_GATT_SRVC_ID *p_src)
+{
+    p_dest->id.inst_id = p_src->id.inst_id;
+    bta_to_btif_uuid(&p_dest->id.uuid, &p_src->id.uuid);
+    p_dest->is_primary = p_src->is_primary;
+}
+
+
+/*******************************************************************************
+ * Utility functions
+ *******************************************************************************/
+
+uint16_t get_uuid16(tBT_UUID *p_uuid)
+{
+    if (p_uuid->len == LEN_UUID_16)
+    {
+        return p_uuid->uu.uuid16;
+    }
+    else if (p_uuid->len == LEN_UUID_128)
+    {
+        UINT16 u16;
+        UINT8 *p = &p_uuid->uu.uuid128[LEN_UUID_128 - 4];
+        STREAM_TO_UINT16(u16, p);
+        return u16;
+    }
+    else  /* p_uuid->len == LEN_UUID_32 */
+    {
+        return(UINT16) p_uuid->uu.uuid32;
+    }
+}
+
+uint16_t set_read_value(btgatt_read_params_t *p_dest, tBTA_GATTC_READ *p_src)
+{
+    int i = 0;
+    uint16_t descr_type = 0;
+    uint16_t len = 0;
+
+    p_dest->status = p_src->status;
+    bta_to_btif_srvc_id(&p_dest->srvc_id, &p_src->srvc_id);
+    bta_to_btif_char_id(&p_dest->char_id, &p_src->char_id);
+    bta_to_btif_uuid(&p_dest->descr_id, &p_src->descr_type);
+
+    descr_type = get_uuid16(&p_src->descr_type);
+
+    switch (descr_type)
+    {
+        case GATT_UUID_CHAR_AGG_FORMAT:
+            /* not supported */
+            p_dest->value_type = GATTC_READ_VALUE_TYPE_AGG_FORMAT;
+            break;
+
+        default:
+            if ( p_src->status == BTA_GATT_OK )
+            {
+                ALOGI("%s unformat.len = %d ", __FUNCTION__, p_src->p_value->unformat.len);
+                p_dest->value.len = p_src->p_value->unformat.len;
+                if ( p_src->p_value->unformat.len > 0  && p_src->p_value->unformat.p_value != NULL )
+                {
+                    memcpy(p_dest->value.value, p_src->p_value->unformat.p_value,
+                           p_src->p_value->unformat.len);
+                }
+                len += p_src->p_value->unformat.len;
+            }
+            else
+            {
+                p_dest->value.len = 0;
+            }
+
+            p_dest->value_type = GATTC_READ_VALUE_TYPE_VALUE;
+            break;
+    }
+
+    return len;
+}
+
+/*******************************************************************************
+ * Encrypted link map handling
+ *******************************************************************************/
+
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result);
+
+static BOOLEAN btif_gatt_is_link_encrypted (BD_ADDR bd_addr)
+{
+    btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+    int i;
+
+    if (bd_addr == NULL)
+        return FALSE;
+
+    for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+    {
+        if (p_link->in_use && (!memcmp(p_link->bd_addr, bd_addr, BD_ADDR_LEN)))
+            return TRUE;
+    }
+    return FALSE;
+}
+
+static BOOLEAN btif_gatt_add_encrypted_link (BD_ADDR bd_addr)
+{
+    btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+    int i;
+
+    if (bd_addr == NULL)
+        return FALSE;
+
+    if (btif_gatt_is_link_encrypted(bd_addr))
+        return TRUE;
+
+    for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+    {
+        if (!p_link->in_use)
+        {
+            p_link->in_use = TRUE;
+            memcpy( p_link->bd_addr, bd_addr, sizeof(BD_ADDR) );
+            return  TRUE;
+        }
+    }
+
+    return FALSE;
+}
+
+void btif_gatt_remove_encrypted_link (BD_ADDR bd_addr)
+{
+    btif_gatt_encrypted_link_t *p_link = &encrypted_links[0];
+    int i;
+
+    if (bd_addr == NULL)
+        return;
+
+    for (i = 0; i != BTIF_GATT_MAX_ENC_LINK_RECORDS; ++i, ++p_link)
+    {
+        if (p_link->in_use && (!memcmp (p_link->bd_addr, bd_addr, BD_ADDR_LEN)))
+        {
+            p_link->in_use = FALSE;
+            break;
+        }
+    }
+}
+
+static void btif_gatt_set_encryption_cb (BD_ADDR bd_addr, tBTA_STATUS result)
+{
+    if (result == BTA_SUCCESS)
+    {
+        btif_gatt_add_encrypted_link(bd_addr);
+    } else {
+        btif_gatt_remove_encrypted_link(bd_addr);
+    }
+}
+
+void btif_gatt_check_encrypted_link (BD_ADDR bd_addr)
+{
+    char buf[100];
+
+    bt_bdaddr_t bda;
+    bdcpy(bda.address, bd_addr);
+
+    if ((btif_storage_get_ble_bonding_key(&bda, BTIF_DM_LE_KEY_PENC,
+                    buf, sizeof(btif_dm_ble_penc_keys_t)) == BT_STATUS_SUCCESS)
+        && !btif_gatt_is_link_encrypted(bd_addr))
+    {
+        BTA_DmSetEncryption(bd_addr,
+                            &btif_gatt_set_encryption_cb, BTM_BLE_SEC_ENCRYPT);
+    }
+}
\ No newline at end of file
diff --git a/btif/src/btif_hf.c b/btif/src/btif_hf.c
old mode 100755
new mode 100644
index 7ce22b1..7688e68
--- a/btif/src/btif_hf.c
+++ b/btif/src/btif_hf.c
@@ -1137,7 +1137,7 @@
 }
 
 static const bthf_interface_t bthfInterface = {
-    sizeof(bt_interface_t),
+    sizeof(bthfInterface),
     init,
     connect,
     disconnect,
diff --git a/btif/src/btif_hh.c b/btif/src/btif_hh.c
index e937a71..61dd894 100644
--- a/btif/src/btif_hh.c
+++ b/btif/src/btif_hh.c
@@ -266,6 +266,7 @@
     if (p_dev->p_buf != NULL) {
         p_dev->p_buf->len = len;
         p_dev->p_buf->offset = BTA_HH_MIN_OFFSET;
+        p_dev->p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
 
         /* LED status updated by data event */
         UINT8 *pbuf_data  = (UINT8 *)(p_dev->p_buf + 1)
@@ -1571,6 +1572,7 @@
             UINT8* pbuf_data;
             pbuf_data = (UINT8*) (p_dev->p_buf + 1) + p_dev->p_buf->offset;
             memcpy(pbuf_data, hexbuf, hex_bytes_filled);
+            p_dev->p_buf->layer_specific = BTA_HH_RPTT_OUTPUT;
             BTA_HhSendData(p_dev->dev_handle, *bda, p_dev->p_buf);
             return BT_STATUS_SUCCESS;
         }
@@ -1619,7 +1621,7 @@
 }
 
 static const bthh_interface_t bthhInterface = {
-    sizeof(bt_interface_t),
+    sizeof(bthhInterface),
     init,
     connect,
     disconnect,
@@ -1649,7 +1651,7 @@
      if (b_enable)
      {
           /* Enable and register with BTA-HH */
-          BTA_HhEnable(BTA_SEC_NONE, FALSE, bte_hh_evt);
+          BTA_HhEnable(BTA_SEC_NONE, bte_hh_evt);
      }
      else {
          /* Disable HH */
diff --git a/btif/src/btif_hl.c b/btif/src/btif_hl.c
index e6c3fb7..e22ca8a 100644
--- a/btif/src/btif_hl.c
+++ b/btif/src/btif_hl.c
@@ -4542,7 +4542,7 @@
 }
 
 static const bthl_interface_t bthlInterface = {
-    sizeof(bthl_interface_t),
+    sizeof(bthlInterface),
     init,
     register_application,
     unregister_application,
diff --git a/btif/src/btif_storage.c b/btif/src/btif_storage.c
old mode 100755
new mode 100644
index 2190b1c..0553874
--- a/btif/src/btif_storage.c
+++ b/btif/src/btif_storage.c
@@ -59,6 +59,10 @@
 #define BTIF_STORAGE_PATH_REMOTE_DEVCLASS "DevClass"
 #define BTIF_STORAGE_PATH_REMOTE_DEVTYPE "DevType"
 #define BTIF_STORAGE_PATH_REMOTE_NAME "Name"
+#define BTIF_STORAGE_PATH_REMOTE_VER_MFCT "Manufacturer"
+#define BTIF_STORAGE_PATH_REMOTE_VER_VER "LmpVer"
+#define BTIF_STORAGE_PATH_REMOTE_VER_SUBVER "LmpSubVer"
+
 //#define BTIF_STORAGE_PATH_REMOTE_LINKKEYS "remote_linkkeys"
 #define BTIF_STORAGE_PATH_REMOTE_ALIASE "Aliase"
 #define BTIF_STORAGE_PATH_REMOTE_SERVICE "Service"
@@ -155,17 +159,30 @@
 } btif_bonded_devices_t;
 
 /************************************************************************************
-**  Extern variables
+**  External variables
 ************************************************************************************/
 extern UINT16 bta_service_id_to_uuid_lkup_tbl [BTA_MAX_SERVICE_ID];
 extern bt_bdaddr_t btif_local_bd_addr;
+
 /************************************************************************************
-**  Static variables
+**  External functions
 ************************************************************************************/
 
+extern void btif_gatts_add_bonded_dev_from_nv(BD_ADDR bda);
+
+/************************************************************************************
+**  Internal Functions
+************************************************************************************/
+
+bt_status_t btif_in_fetch_bonded_ble_device(char *remote_bd_addr,int add,
+                                              btif_bonded_devices_t *p_bonded_devices);
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+                                              int *addr_type);
+
 /************************************************************************************
 **  Static functions
 ************************************************************************************/
+
 /*******************************************************************************
 **
 ** Function         btif_in_make_filename
@@ -292,6 +309,22 @@
             btif_config_save();
             break;
         }
+        case BT_PROPERTY_REMOTE_VERSION_INFO:
+        {
+            bt_remote_version_t *info = (bt_remote_version_t *)prop->val;
+
+            if (!info)
+                return FALSE;
+
+            btif_config_set_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_MFCT, info->manufacturer);
+            btif_config_set_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_VER, info->version);
+            btif_config_set_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_SUBVER, info->sub_ver);
+            btif_config_save();
+         } break;
+
         default:
              BTIF_TRACE_ERROR1("Unknow prop type:%d", prop->type);
              return FALSE;
@@ -381,8 +414,32 @@
                 prop->len = num_uuids * sizeof(bt_uuid_t);
                 ret = TRUE;
             }
-            break;
-        }
+            else
+            {
+                prop->val = NULL;
+                prop->len = 0;
+            }
+        } break;
+
+        case BT_PROPERTY_REMOTE_VERSION_INFO:
+        {
+            bt_remote_version_t *info = (bt_remote_version_t *)prop->val;
+
+            if(prop->len >= (int)sizeof(bt_remote_version_t))
+            {
+                ret = btif_config_get_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_MFCT, &info->manufacturer);
+
+                if (ret == TRUE)
+                    ret = btif_config_get_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_VER, &info->version);
+
+                if (ret == TRUE)
+                    ret = btif_config_get_int("Remote", bdstr,
+                                BTIF_STORAGE_PATH_REMOTE_VER_SUBVER, &info->sub_ver);
+            }
+         } break;
+
         default:
             BTIF_TRACE_ERROR1("Unknow prop type:%d", prop->type);
             return FALSE;
@@ -412,6 +469,9 @@
     kname_size = sizeof(kname);
     kname[0] = 0;
     kpos = 0;
+    BOOLEAN bt_linkkey_file_found=FALSE;
+    int device_type;
+
     do
     {
         kpos = btif_config_next_key(kpos, "Remote", kname, &kname_size);
@@ -435,15 +495,38 @@
                     if(btif_config_get_int("Remote", kname, "DevClass", &cod))
                         uint2devclass((UINT32)cod, dev_class);
                     BTA_DmAddDevice(bd_addr.address, dev_class, link_key, 0, 0, (UINT8)linkkey_type, 0);
+
+                    if (btif_config_get_int("Remote", kname, "DevType", &device_type) &&
+                       (device_type == BT_DEVICE_TYPE_DUMO) )
+                    {
+                        btif_gatts_add_bonded_dev_from_nv(bd_addr.address);
+                    }
                 }
+                bt_linkkey_file_found = TRUE;
                 memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
             }
-            else BTIF_TRACE_ERROR1("bounded device:%s, LinkKeyType or PinLength is invalid", kname);
+            else
+            {
+#if (BLE_INCLUDED == TRUE)
+                bt_linkkey_file_found = FALSE;
+#else
+                BTIF_TRACE_ERROR1("bounded device:%s, LinkKeyType or PinLength is invalid", kname);
+#endif
+            }
         }
-        else BTIF_TRACE_DEBUG1("Remote device:%s, no link key", kname);
+#if (BLE_INCLUDED == TRUE)
+            if(!(btif_in_fetch_bonded_ble_device(kname,add, p_bonded_devices)) && (!bt_linkkey_file_found))
+            {
+                BTIF_TRACE_DEBUG1("Remote device:%s, no link key or ble key found", kname);
+            }
+#else
+            if(!bt_linkkey_file_found)
+                BTIF_TRACE_DEBUG1("Remote device:%s, no link key", kname);
+#endif
         kname_size = sizeof(kname);
         kname[0] = 0;
     } while(kpos != -1);
+    BTIF_TRACE_DEBUG0("out");
     return BT_STATUS_SUCCESS;
 }
 
@@ -640,7 +723,7 @@
 **                  BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
-bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bdaddr,
+bt_status_t btif_storage_add_remote_device(bt_bdaddr_t *remote_bd_addr,
                                            uint32_t num_properties,
                                            bt_property_t *properties)
 {
@@ -659,12 +742,12 @@
             bt_property_t addr_prop;
             memcpy(&addr_prop, &properties[i], sizeof(bt_property_t));
             addr_prop.type = BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP;
-            btif_storage_set_remote_device_property(remote_bdaddr,
+            btif_storage_set_remote_device_property(remote_bd_addr,
                                                     &addr_prop);
         }
         else
         {
-            btif_storage_set_remote_device_property(remote_bdaddr,
+            btif_storage_set_remote_device_property(remote_bd_addr,
                                                     &properties[i]);
         }
     }
@@ -846,6 +929,413 @@
     return BT_STATUS_SUCCESS;
 }
 
+#if (BLE_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function         btif_storage_add_ble_bonding_key
+**
+** Description      BTIF storage API - Adds the newly bonded device to NVRAM
+**                  along with the ble-key, Key type and Pin key length
+**
+** Returns          BT_STATUS_SUCCESS if the store was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+
+bt_status_t btif_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+                                           char *key,
+                                           UINT8 key_type,
+                                           UINT8 key_length)
+{
+    bdstr_t bdstr;
+    bd2str(remote_bd_addr, &bdstr);
+    const char* name;
+    switch(key_type)
+    {
+        case BTIF_DM_LE_KEY_PENC:
+            name = "LE_KEY_PENC";
+            break;
+        case BTIF_DM_LE_KEY_PID:
+            name = "LE_KEY_PID";
+            break;
+        case BTIF_DM_LE_KEY_PCSRK:
+            name = "LE_KEY_PCSRK";
+            break;
+        case BTIF_DM_LE_KEY_LENC:
+            name = "LE_KEY_LENC";
+            break;
+        case BTIF_DM_LE_KEY_LCSRK:
+            name = "LE_KEY_LCSRK";
+            break;
+        default:
+            return BT_STATUS_FAIL;
+    }
+    int ret = btif_config_set("Remote", bdstr, name, (const char*)key, (int)key_length, BTIF_CFG_TYPE_BIN);
+    btif_config_save();
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_get_ble_bonding_key
+**
+** Description
+**
+** Returns          BT_STATUS_SUCCESS if the fetch was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
+                                             UINT8 key_type,
+                                             char *key_value,
+                                             int key_length)
+{
+    bdstr_t bdstr;
+    bd2str(remote_bd_addr, &bdstr);
+    const char* name;
+    int type = BTIF_CFG_TYPE_BIN;
+    switch(key_type)
+    {
+        case BTIF_DM_LE_KEY_PENC:
+            name = "LE_KEY_PENC";
+            break;
+        case BTIF_DM_LE_KEY_PID:
+            name = "LE_KEY_PID";
+            break;
+        case BTIF_DM_LE_KEY_PCSRK:
+            name = "LE_KEY_PCSRK";
+            break;
+        case BTIF_DM_LE_KEY_LENC:
+            name = "LE_KEY_LENC";
+            break;
+        case BTIF_DM_LE_KEY_LCSRK:
+            name = "LE_KEY_LCSRK";
+            break;
+        default:
+            return BT_STATUS_FAIL;
+    }
+    int ret = btif_config_get("Remote", bdstr, name, key_value, &key_length, &type);
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_remove_ble_keys
+**
+** Description      BTIF storage API - Deletes the bonded device from NVRAM
+**
+** Returns          BT_STATUS_SUCCESS if the deletion was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_remove_ble_bonding_keys(bt_bdaddr_t *remote_bd_addr)
+{
+    bdstr_t bdstr;
+    bd2str(remote_bd_addr, &bdstr);
+    BTIF_TRACE_DEBUG2(" %s in bd addr:%s",__FUNCTION__, bdstr);
+    int ret = 1;
+    if(btif_config_exist("Remote", bdstr, "LE_KEY_PENC"))
+        ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PENC");
+    if(btif_config_exist("Remote", bdstr, "LE_KEY_PID"))
+        ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PID");
+    if(btif_config_exist("Remote", bdstr, "LE_KEY_PCSRK"))
+        ret &= btif_config_remove("Remote", bdstr, "LE_KEY_PCSRK");
+    if(btif_config_exist("Remote", bdstr, "LE_KEY_LENC"))
+        ret &= btif_config_remove("Remote", bdstr, "LE_KEY_LENC");
+    if(btif_config_exist("Remote", bdstr, "LE_KEY_LCSRK"))
+        ret &= btif_config_remove("Remote", bdstr, "LE_KEY_LCSRK");
+    btif_config_save();
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_add_ble_local_key
+**
+** Description      BTIF storage API - Adds the ble key to NVRAM
+**
+** Returns          BT_STATUS_SUCCESS if the store was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_add_ble_local_key(char *key,
+                                           uint8_t key_type,
+                                           uint8_t key_length)
+{
+    const char* name;
+    switch(key_type)
+    {
+        case BTIF_DM_LE_LOCAL_KEY_IR:
+            name = "LE_LOCAL_KEY_IR";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_IRK:
+            name = "LE_LOCAL_KEY_IRK";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_DHK:
+            name = "LE_LOCAL_KEY_DHK";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_ER:
+            name = "LE_LOCAL_KEY_ER";
+            break;
+        default:
+            return BT_STATUS_FAIL;
+    }
+    int ret = btif_config_set("Local", "Adapter", name, (const char*)key, key_length, BTIF_CFG_TYPE_BIN);
+    btif_config_save();
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_get_ble_local_key
+**
+** Description
+**
+** Returns          BT_STATUS_SUCCESS if the fetch was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_ble_local_key(UINT8 key_type,
+                                           char *key_value,
+                                           int key_length)
+{
+    const char* name;
+    int type = BTIF_CFG_TYPE_BIN;
+    switch(key_type)
+    {
+        case BTIF_DM_LE_LOCAL_KEY_IR:
+            name = "LE_LOCAL_KEY_IR";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_IRK:
+            name = "LE_LOCAL_KEY_IRK";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_DHK:
+            name = "LE_LOCAL_KEY_DHK";
+            break;
+        case BTIF_DM_LE_LOCAL_KEY_ER:
+            name = "LE_LOCAL_KEY_ER";
+            break;
+        default:
+            return BT_STATUS_FAIL;
+    }
+    int ret = btif_config_get("Local", "Adapter", name, key_value, &key_length, &type);
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_remove_ble_local_keys
+**
+** Description      BTIF storage API - Deletes the bonded device from NVRAM
+**
+** Returns          BT_STATUS_SUCCESS if the deletion was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_remove_ble_local_keys(void)
+{
+    int ret = 1;
+    if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_IR"))
+        ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_IR");
+    if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_IRK"))
+        ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_IRK");
+    if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_DHK"))
+        ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_DHK");
+    if(btif_config_exist("Local", "Adapter", "LE_LOCAL_KEY_ER"))
+        ret &= btif_config_remove("Local", "Adapter", "LE_LOCAL_KEY_ER");
+    btif_config_save();
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+bt_status_t btif_in_fetch_bonded_ble_device(char *remote_bd_addr,int add, btif_bonded_devices_t *p_bonded_devices)
+{
+    int device_type;
+    int addr_type;
+    char buf[100];
+    UINT32 i;
+    bt_bdaddr_t bd_addr;
+    BD_ADDR bta_bd_addr;
+    BOOLEAN is_device_added =FALSE;
+    tBTA_LE_KEY_VALUE *p;
+
+    if(!btif_config_get_int("Remote", remote_bd_addr,"DevType", &device_type))
+        return BT_STATUS_FAIL;
+    if(device_type == BT_DEVICE_TYPE_BLE)
+    {
+            BTIF_TRACE_DEBUG2("%s %s found a BLE device", __FUNCTION__,remote_bd_addr);
+            str2bd(remote_bd_addr, &bd_addr);
+            bdcpy(bta_bd_addr, bd_addr.address);
+            if (btif_storage_get_remote_addr_type(&bd_addr, &addr_type) != BT_STATUS_SUCCESS)
+            {
+                return BT_STATUS_FAIL;
+            }
+
+            memset(buf, 0, sizeof(buf));
+            if (btif_storage_get_ble_bonding_key(&bd_addr,
+                                                 BTIF_DM_LE_KEY_PENC,
+                                                 buf,
+                                                 sizeof(btif_dm_ble_penc_keys_t)) == BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("penc_key.ltk[%d]=0x%02x",i,p->penc_key.ltk[i]);
+                    }
+                    for (i=0; i<8; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("penc_key.rand[%d]=0x%02x",i,p->penc_key.rand[i]);
+                    }
+                    BTIF_TRACE_DEBUG1("p->penc_key.ediv=0x%04x",p->penc_key.ediv);
+                    BTIF_TRACE_DEBUG1("p->penc_key.sec_level=0x%02x",p->penc_key.sec_level);
+                    BTIF_TRACE_DEBUG1("p->penc_key.key_size=0x%02x",p->penc_key.key_size);
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PENC);
+                }
+            }
+
+            memset(buf, 0, sizeof(buf));
+            if (btif_storage_get_ble_bonding_key(&bd_addr,
+                                                 BTIF_DM_LE_KEY_PID,
+                                                 buf,
+                                                 sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("p->pid_key[%d]=0x%02x",i,p->pid_key.irk[i]);
+                    }
+
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PID);
+                }
+            }
+
+            memset(buf, 0, sizeof(buf));
+            if (btif_storage_get_ble_bonding_key(&bd_addr,
+                                                 BTIF_DM_LE_KEY_PCSRK,
+                                                 buf,
+                                                 sizeof(btif_dm_ble_pcsrk_keys_t)) == BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    for (i=0; i<16; i++)
+                    {
+                        BTIF_TRACE_DEBUG2("p->pcsrk_key.csrk[%d]=0x%02x",i, p->psrk_key.csrk[i]);
+                    }
+                    BTIF_TRACE_DEBUG1("p->pcsrk_key.counter=0x%08x",p->psrk_key.counter);
+                    BTIF_TRACE_DEBUG1("p->pcsrk_key.sec_level=0x%02x",p->psrk_key.sec_level);
+
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_PCSRK);
+                }
+            }
+
+            memset(buf, 0, sizeof(buf));
+            if (btif_storage_get_ble_bonding_key(&bd_addr,
+                                                 BTIF_DM_LE_KEY_LENC,
+                                                 buf,
+                                                 sizeof(btif_dm_ble_lenc_keys_t)) == BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    BTIF_TRACE_DEBUG1("p->lenc_key.div=0x%04x",p->lenc_key.div);
+                    BTIF_TRACE_DEBUG1("p->lenc_key.key_size=0x%02x",p->lenc_key.key_size);
+                    BTIF_TRACE_DEBUG1("p->lenc_key.sec_level=0x%02x",p->lenc_key.sec_level);
+
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LENC);
+                }
+            }
+
+            memset(buf, 0, sizeof(buf));
+            if (btif_storage_get_ble_bonding_key(&bd_addr,
+                                                 BTIF_DM_LE_KEY_LCSRK,
+                                                 buf,
+                                                 sizeof(btif_dm_ble_lcsrk_keys_t)) == BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    BTIF_TRACE_DEBUG1("p->lcsrk_key.div=0x%04x",p->lcsrk_key.div);
+                    BTIF_TRACE_DEBUG1("p->lcsrk_key.counter=0x%08x",p->lcsrk_key.counter);
+                    BTIF_TRACE_DEBUG1("p->lcsrk_key.sec_level=0x%02x",p->lcsrk_key.sec_level);
+
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LCSRK);
+                }
+            }
+
+            /* Fill in the bonded devices */
+            if (is_device_added)
+            {
+                memcpy(&p_bonded_devices->devices[p_bonded_devices->num_devices++], &bd_addr, sizeof(bt_bdaddr_t));
+                btif_gatts_add_bonded_dev_from_nv(bta_bd_addr);
+            }
+
+            return BT_STATUS_SUCCESS;
+    }
+    return BT_STATUS_FAIL;
+}
+
+bt_status_t btif_storage_set_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+                                              UINT8 addr_type)
+{
+    bdstr_t bdstr;
+    bd2str(remote_bd_addr, &bdstr);
+    int ret = btif_config_set_int("Remote", bdstr, "AddrType", (int)addr_type);
+    btif_config_save();
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+
+/*******************************************************************************
+**
+** Function         btif_storage_get_remote_addr_type
+**
+** Description      BTIF storage API - Fetches the remote addr type
+**
+** Returns          BT_STATUS_SUCCESS if the fetch was successful,
+**                  BT_STATUS_FAIL otherwise
+**
+*******************************************************************************/
+bt_status_t btif_storage_get_remote_addr_type(bt_bdaddr_t *remote_bd_addr,
+                                              int*addr_type)
+{
+    bdstr_t bdstr;
+    bd2str(remote_bd_addr, &bdstr);
+    int ret = btif_config_get_int("Remote", bdstr, "AddrType", addr_type);
+    return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
+}
+#endif
 /*******************************************************************************
 **
 ** Function         btif_storage_add_hid_device_info
@@ -1273,7 +1763,7 @@
 **                  FALSE otherwise
 **
 *******************************************************************************/
-BOOLEAN  btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_dev_addr)
+BOOLEAN  btif_storage_is_device_autopair_blacklisted(bt_bdaddr_t *remote_bd_addr)
 {
     char *token;
     int ret;
@@ -1283,7 +1773,7 @@
     char value[BTIF_STORAGE_MAX_LINE_SZ];
     int value_size = sizeof(value);
 
-    bd2str(remote_dev_addr, &bdstr);
+    bd2str(remote_bd_addr, &bdstr);
 
     /* Consider only  Lower Address Part from BD Address */
     bdstr[8] = '\0';
@@ -1295,7 +1785,7 @@
             return TRUE;
     }
 
-    dev_name_str = BTM_SecReadDevName((remote_dev_addr->address));
+    dev_name_str = BTM_SecReadDevName((remote_bd_addr->address));
 
     if (dev_name_str != NULL)
     {
@@ -1339,14 +1829,14 @@
 **                  BT_STATUS_FAIL otherwise
 **
 *******************************************************************************/
-bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_dev_addr)
+bt_status_t btif_storage_add_device_to_autopair_blacklist(bt_bdaddr_t *remote_bd_addr)
 {
     int ret;
     bdstr_t bdstr;
     char linebuf[BTIF_STORAGE_MAX_LINE_SZ+20];
     char input_value [20];
 
-    bd2str(remote_dev_addr, &bdstr);
+    bd2str(remote_bd_addr, &bdstr);
     strncpy(input_value, (char*)bdstr, 20);
     strncat(input_value,BTIF_AUTO_PAIR_CONF_VALUE_SEPARATOR, 20);
     int line_size = sizeof(linebuf);
@@ -1378,7 +1868,7 @@
 **                  FALSE otherwise
 **
 *******************************************************************************/
-BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_dev_addr)
+BOOLEAN btif_storage_is_fixed_pin_zeros_keyboard(bt_bdaddr_t *remote_bd_addr)
 {
     int ret;
     bdstr_t bdstr;
@@ -1386,7 +1876,7 @@
     uint8_t i = 0;
     char linebuf[BTIF_STORAGE_MAX_LINE_SZ];
 
-    bd2str(remote_dev_addr, &bdstr);
+    bd2str(remote_bd_addr, &bdstr);
 
 	/*consider on LAP part of BDA string*/
 	bdstr[8] = '\0';
diff --git a/btif/src/btif_util.c b/btif/src/btif_util.c
index 5539c11..0096eff 100644
--- a/btif/src/btif_util.c
+++ b/btif/src/btif_util.c
@@ -89,7 +89,7 @@
     return 0;
 }
 
-char *bd2str(bt_bdaddr_t *bdaddr, bdstr_t *bdstr)
+char *bd2str(const bt_bdaddr_t *bdaddr, bdstr_t *bdstr)
 {
     char *addr = (char *) bdaddr->address;
 
@@ -103,9 +103,11 @@
 {
     UINT32 cod = 0;
 
-    /* if COD is 0, irrespective of the device type set it to Unclassified device */
-    cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16);
-
+    if(dev_class != NULL)
+    {
+        /* if COD is 0, irrespective of the device type set it to Unclassified device */
+        cod = (dev_class[2]) | (dev_class[1] << 8) | (dev_class[0] << 16);
+    }
     return cod;
 }
 void uint2devclass(UINT32 cod, DEV_CLASS dev_class)
@@ -459,4 +461,3 @@
 }
 
 
-
diff --git a/conf/bt_stack.conf b/conf/bt_stack.conf
index 2cd2f62..2ca20ea 100644
--- a/conf/bt_stack.conf
+++ b/conf/bt_stack.conf
@@ -16,6 +16,7 @@
 #   BT_TRACE_LEVEL_API     3    ( API traces )
 #   BT_TRACE_LEVEL_EVENT   4    ( Debug messages for events )
 #   BT_TRACE_LEVEL_DEBUG   5    ( Full debug messages )
+#   BT_TRACE_LEVEL_VERBOSE 6    ( Verbose messages ) - Currently supported for TRC_BTAPP only.
 TRC_BTM=2
 TRC_HCI=2
 TRC_L2CAP=2
diff --git a/gki/common/gki_buffer.c b/gki/common/gki_buffer.c
index f474bab..bcf6f06 100644
--- a/gki/common/gki_buffer.c
+++ b/gki/common/gki_buffer.c
@@ -434,6 +434,7 @@
 
     GKI_enable();
 
+    GKI_exception (GKI_ERROR_OUT_OF_BUFFERS, "getbuf: out of buffers");
     return (NULL);
 }
 
@@ -460,7 +461,10 @@
     tGKI_COM_CB *p_cb = &gki_cb.com;
 
     if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+    {
+        GKI_exception(GKI_ERROR_GETPOOLBUF_BAD_QID, "getpoolbuf bad pool");
         return (NULL);
+    }
 
     /* Make sure the buffers aren't disturbed til finished with allocation */
     GKI_disable();
diff --git a/gki/common/gki_common.h b/gki/common/gki_common.h
index 9bc5005..ff5a675 100644
--- a/gki/common/gki_common.h
+++ b/gki/common/gki_common.h
@@ -43,6 +43,8 @@
 #define GKI_ERROR_BUF_SIZE_TOOBIG       0xFFF7
 #define GKI_ERROR_BUF_SIZE_ZERO         0xFFF6
 #define GKI_ERROR_ADDR_NOT_IN_BUF       0xFFF5
+#define GKI_ERROR_OUT_OF_BUFFERS        0xFFF4
+#define GKI_ERROR_GETPOOLBUF_BAD_QID    0xFFF3
 
 
 /********************************************************************
diff --git a/hci/src/userial.c b/hci/src/userial.c
index afd3010..d87bea1 100644
--- a/hci/src/userial.c
+++ b/hci/src/userial.c
@@ -52,6 +52,10 @@
 #define USERIALDBG(param, ...) {}
 #endif
 
+#ifndef ENABLE_USERIAL_TIMING_LOGS
+#define ENABLE_USERIAL_TIMING_LOGS FALSE
+#endif
+
 #define MAX_SERIAL_PORT (USERIAL_PORT_3 + 1)
 #define READ_LIMIT (BTHC_USERIAL_READ_MEM_SIZE - BT_HC_HDR_SIZE)
 
@@ -91,6 +95,29 @@
 **  Static functions
 ******************************************************************************/
 
+#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
+
+static void log_userial_tx_timing(int len)
+{
+    #define USEC_PER_SEC 1000000L
+    static struct timespec prev = {0, 0};
+    struct timespec now, diff;
+    unsigned int diff_us = 0;
+    unsigned int now_us = 0;
+
+    clock_gettime(CLOCK_MONOTONIC, &now);
+    now_us = now.tv_sec*USEC_PER_SEC + now.tv_nsec/1000;
+    diff_us = (now.tv_sec - prev.tv_sec) * USEC_PER_SEC + (now.tv_nsec - prev.tv_nsec)/1000;
+
+    ALOGW("[userial] ts %08d diff : %08d len %d", now_us, diff_us,
+                len);
+
+    prev = now;
+}
+
+#endif
+
+
 /*****************************************************************************
 **   Socket signal functions to wake up userial_read_thread for termination
 **
@@ -125,6 +152,7 @@
     return FD_ISSET(signal_fds[0], set);
 }
 
+
 /*******************************************************************************
 **
 ** Function        select_read
@@ -454,6 +482,9 @@
 
     while(len != 0)
     {
+#if defined(ENABLE_USERIAL_TIMING_LOGS) && (ENABLE_USERIAL_TIMING_LOGS==TRUE)
+        log_userial_tx_timing(len);
+#endif
         ret = write(userial_cb.fd, p_data+total, len);
         total += ret;
         len -= ret;
diff --git a/include/bt_target.h b/include/bt_target.h
old mode 100755
new mode 100644
index 836868e..98968f5
--- a/include/bt_target.h
+++ b/include/bt_target.h
@@ -260,7 +260,7 @@
 #endif
 
 #ifndef BTA_GATT_INCLUDED
-#define BTA_GATT_INCLUDED FALSE
+#define BTA_GATT_INCLUDED TRUE
 #endif
 
 #ifndef BTA_DISABLE_DELAY
@@ -555,11 +555,6 @@
 #define BTM_CMD_POOL_ID             GKI_POOL_ID_2
 #endif
 
-/* Sends TCS messages. */
-#ifndef TCS_MSG_POOL_ID
-#define TCS_MSG_POOL_ID             GKI_POOL_ID_2
-#endif
-
 #ifndef OBX_CMD_POOL_SIZE
 #define OBX_CMD_POOL_SIZE           GKI_BUF2_SIZE
 #endif
@@ -577,11 +572,6 @@
 #define CTP_SDP_DB_POOL_ID          GKI_POOL_ID_3
 #endif
 
-/* Used for CTP data exchange feature. */
-#ifndef CTP_DATA_EXCHG_POOL_ID
-#define CTP_DATA_EXCHG_POOL_ID      GKI_POOL_ID_2
-#endif
-
 /* Used to send data to L2CAP. */
 #ifndef GAP_DATA_POOL_ID
 #define GAP_DATA_POOL_ID            GKI_POOL_ID_3
@@ -596,24 +586,6 @@
 #define SPP_DB_SIZE                 GKI_BUF3_SIZE
 #endif
 
-/* HCRP protocol and internal commands. */
-#ifndef HCRP_CMD_POOL_ID
-#define HCRP_CMD_POOL_ID            GKI_POOL_ID_2
-#endif
-
-#ifndef HCRP_CMD_POOL_SIZE
-#define HCRP_CMD_POOL_SIZE          GKI_BUF2_SIZE
-#endif
-
-#ifndef BIP_EVT_POOL_SIZE
-#define BIP_EVT_POOL_SIZE           GKI_BUF3_SIZE
-#endif
-
-#ifndef BIP_DB_SIZE
-#define BIP_DB_SIZE                 GKI_BUF3_SIZE
-#endif
-
-
 /* BNEP data and protocol messages. */
 #ifndef BNEP_POOL_ID
 #define BNEP_POOL_ID                GKI_POOL_ID_3
@@ -1245,7 +1217,7 @@
 
 /* The maximum number of simultaneous channels that L2CAP can support. */
 #ifndef MAX_L2CAP_CHANNELS
-#define MAX_L2CAP_CHANNELS          10
+#define MAX_L2CAP_CHANNELS          16
 #endif
 
 /* The maximum number of simultaneous applications that can register with L2CAP. */
@@ -1417,8 +1389,8 @@
 **
 ******************************************************************************/
 
-#ifndef BLE_INCLUDED
-#define BLE_INCLUDED            FALSE
+#ifndef _cac
+#define BLE_INCLUDED            TRUE
 #endif
 
 #ifndef LOCAL_BLE_CONTROLLER_ID
@@ -1431,19 +1403,19 @@
 **
 ******************************************************************************/
 #ifndef ATT_INCLUDED
-#define ATT_INCLUDED         FALSE
+#define ATT_INCLUDED         TRUE
 #endif
 
 #ifndef ATT_DEBUG
-#define ATT_DEBUG           FALSE
+#define ATT_DEBUG           TRUE
 #endif
 
 #ifndef GATT_SERVER_ENABLED
-#define GATT_SERVER_ENABLED          FALSE
+#define GATT_SERVER_ENABLED          TRUE
 #endif
 
 #ifndef GATT_CLIENT_ENABLED
-#define GATT_CLIENT_ENABLED          FALSE
+#define GATT_CLIENT_ENABLED          TRUE
 #endif
 
 #ifndef GATT_MAX_SR_PROFILES
@@ -1479,11 +1451,11 @@
 **
 ******************************************************************************/
 #ifndef SMP_INCLUDED
-#define SMP_INCLUDED         FALSE
+#define SMP_INCLUDED         TRUE
 #endif
 
 #ifndef SMP_DEBUG
-#define SMP_DEBUG            FALSE
+#define SMP_DEBUG            TRUE
 #endif
 
 #ifndef SMP_DEFAULT_AUTH_REQ
@@ -2189,7 +2161,7 @@
 ******************************************************************************/
 
 #ifndef GAP_INCLUDED
-#define GAP_INCLUDED                FALSE
+#define GAP_INCLUDED                TRUE
 #endif
 
 /* This is set to enable use of GAP L2CAP connections. */
@@ -3749,9 +3721,6 @@
 #define L2CAP_FEATURE_RSP_ID     173
 
 
-#define L2CAP_ENHANCED_FEATURES   0
-
-
 /******************************************************************************
 **
 ** BTA
diff --git a/include/bt_trace.h b/include/bt_trace.h
index 6c3e7b1..e6a0b71 100644
--- a/include/bt_trace.h
+++ b/include/bt_trace.h
@@ -4668,6 +4668,28 @@
                                                         (m), (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5));}
 #define APPL_TRACE_DEBUG6(m,p1,p2,p3,p4,p5,p6)  {if (appl_trace_level >= BT_TRACE_LEVEL_DEBUG) LogMsg_6(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, \
                                                         (m), (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5), (UINT32)(p6));}
+
+#define APPL_TRACE_VERBOSE0(m)                    {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_0(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m));}
+#define APPL_TRACE_VERBOSE1(m,p1)                 {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_1(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1));}
+#define APPL_TRACE_VERBOSE2(m,p1,p2)              {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_2(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1), (UINT32)(p2));}
+#define APPL_TRACE_VERBOSE3(m,p1,p2,p3)           {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_3(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1), (UINT32)(p2), (UINT32)(p3));}
+#define APPL_TRACE_VERBOSE4(m,p1,p2,p3,p4)        {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_4(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4));}
+#define APPL_TRACE_VERBOSE5(m,p1,p2,p3,p4,p5)     {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_5(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5));}
+#define APPL_TRACE_VERBOSE6(m,p1,p2,p3,p4,p5,p6)  {if (appl_trace_level >= BT_TRACE_LEVEL_VERBOSE)\
+    LogMsg_6(TRACE_CTRL_GENERAL | TRACE_LAYER_NONE | TRACE_ORG_APPL | TRACE_TYPE_DEBUG, (m), \
+    (UINT32)(p1), (UINT32)(p2), (UINT32)(p3), (UINT32)(p4), (UINT32)(p5), (UINT32)(p6));}
+
 #else
 /* define traces for Application */
 
@@ -4711,6 +4733,14 @@
 #define APPL_TRACE_DEBUG5(m,p1,p2,p3,p4,p5)
 #define APPL_TRACE_DEBUG6(m,p1,p2,p3,p4,p5,p6)
 
+#define APPL_TRACE_VERBOSE0(m)
+#define APPL_TRACE_VERBOSE1(m,p1)
+#define APPL_TRACE_VERBOSE2(m,p1,p2)
+#define APPL_TRACE_VERBOSE3(m,p1,p2,p3)
+#define APPL_TRACE_VERBOSE4(m,p1,p2,p3,p4)
+#define APPL_TRACE_VERBOSE5(m,p1,p2,p3,p4,p5)
+#define APPL_TRACE_VERBOSE6(m,p1,p2,p3,p4,p5,p6)
+
 #endif
 
 #if ((MMI_INCLUDED == TRUE) && (!defined(HID_MSKB_INCLUDED) || (HID_MSKB_INCLUDED == FALSE)))
diff --git a/include/bte.h b/include/bte.h
index 103b660..968b68a 100644
--- a/include/bte.h
+++ b/include/bte.h
@@ -100,9 +100,12 @@
 /* Protocol trace mask */
 extern UINT32 bte_proto_trace_mask;
 
-/* Version string */
+/* BTE version string */
 extern const UINT8 bte_version_string[];
 
+/* BTIF version string */
+extern const UINT8 btif_version_string[];
+
 typedef struct tBAUD_REG_tag {
     UINT8 DHBR;
     UINT8 DLBR;
diff --git a/include/bte_appl.h b/include/bte_appl.h
index 63689da..cf0baed 100644
--- a/include/bte_appl.h
+++ b/include/bte_appl.h
@@ -70,25 +70,12 @@
 #define BTE_APPL_CONTACTS_DB_PATH       256
 
 typedef struct {
-    char    patchram_path[BTE_APPL_PATCHRAM_PATH_MAXLEN+1];
-    UINT32  patchram_addr;
-    UINT32  reconfig_baud;
-    UINT32  clock_rate;             /* clock rate (for uart baud calculation) */
-    BD_ADDR local_addr;             /* local bd addr */
-    BD_ADDR rem_addr;
-    UINT8   lpm_enabled;
-    UINT8   bt_wake_polarity;
-    UINT8   host_wake_polarity;
-    BOOLEAN ag_enable_3way_conf;
-    UINT16  ag_voice_settings;
-    UINT8   ag_vsc_pcm_config[5];
-    UINT8   ag_vsc_sco_pcm[5];
-    /*tBTM_CMPL_CB*/ tBTM_DEV_STATUS_CB *p_reset_cplt_cb;  /* Current reset_cplt_cb */
-    char    contacts_db[BTE_APPL_CONTACTS_DB_PATH+1];
-    UINT32  bta_module_state[BTAPP_NUM_ID_BLOCKS]; /* state of enabled bta modules */
-#if (BTAPP_AHF_API_SUPPORT==TRUE)
-    UINT8   afh_first;
-    UINT8   afh_last;
+#if ((BLE_INCLUDED == TRUE) && (SMP_INCLUDED == TRUE))
+    UINT8   ble_auth_req;
+    UINT8   ble_io_cap;
+    UINT8   ble_init_key;
+    UINT8   ble_resp_key;
+    UINT8   ble_max_key_size;
 #endif
 } tBTE_APPL_CFG;
 
diff --git a/main/Android.mk b/main/Android.mk
index 8ecb3c3..3e311d4 100644
--- a/main/Android.mk
+++ b/main/Android.mk
@@ -37,6 +37,11 @@
     ../btif/src/btif_sock_sdp.c \
     ../btif/src/btif_sock_util.c \
     ../btif/src/btif_pan.c \
+    ../btif/src/btif_gatt.c \
+    ../btif/src/btif_gatt_client.c \
+    ../btif/src/btif_gatt_server.c \
+    ../btif/src/btif_gatt_util.c \
+    ../btif/src/btif_gatt_test.c \
     ../btif/src/btif_config.c \
     ../btif/src/btif_config_util.cpp \
     ../btif/src/btif_profile_queue.c
@@ -50,7 +55,9 @@
     ../btif/co/bta_av_co.c \
     ../btif/co/bta_hh_co.c \
     ../btif/co/bta_hl_co.c \
-    ../btif/co/bta_pan_co.c
+    ../btif/co/bta_pan_co.c \
+    ../btif/co/bta_gattc_co.c \
+    ../btif/co/bta_gatts_co.c \
 
 # sbc encoder
 LOCAL_SRC_FILES+= \
diff --git a/main/bte_logmsg.c b/main/bte_logmsg.c
index 7035a57..6c9a5eb 100644
--- a/main/bte_logmsg.c
+++ b/main/bte_logmsg.c
@@ -91,6 +91,7 @@
 
 #if (BLE_INCLUDED==TRUE)
 #include "gatt_api.h"
+#include "smp_api.h"
 #endif
 
     /* LayerIDs for BTA, currently everything maps onto appl_trace_level */
@@ -282,7 +283,6 @@
     int trace_layer = TRACE_GET_LAYER(trace_set_mask);
     if (trace_layer >= TRACE_LAYER_MAX_NUM)
         trace_layer = 0;
-
 	gettimeofday(&tv, &tz);
 	time(&t);
 	tm = localtime(&t);
@@ -467,8 +467,6 @@
     {BTTRC_ID_STK_SDP, BTTRC_ID_STK_SDP, SDP_SetTraceLevel, "TRC_SDP", DEFAULT_CONF_TRACE_LEVEL},
 #if (BLE_INCLUDED==TRUE)
     {BTTRC_ID_STK_GATT, BTTRC_ID_STK_GATT, GATT_SetTraceLevel, "TRC_GATT", DEFAULT_CONF_TRACE_LEVEL},
-#endif
-#if (BLE_INCLUDED==TRUE)
     {BTTRC_ID_STK_SMP, BTTRC_ID_STK_SMP, SMP_SetTraceLevel, "TRC_SMP", DEFAULT_CONF_TRACE_LEVEL},
 #endif
 
diff --git a/main/bte_version.c b/main/bte_version.c
index 0751e1d..826f31b 100644
--- a/main/bte_version.c
+++ b/main/bte_version.c
@@ -18,5 +18,6 @@
 
 #include "bt_types.h"
 
-const UINT8 bte_version_string[] = "BCM1200_PI_10.3.20.33";
+const UINT8 bte_version_string[] = "BCM1200_PI_10.3.20.52";
+const UINT8 btif_version_string[] = "BDROID-PLUS-420-10_00.10";
 
diff --git a/stack/Android.mk b/stack/Android.mk
index dcbe961..e17f4c8 100644
--- a/stack/Android.mk
+++ b/stack/Android.mk
@@ -80,6 +80,10 @@
     ./mcap/mca_csm.c \
     ./mcap/mca_cact.c \
     ./mcap/mca_api.c \
+     ./gap/gap_ble.c \
+    ./gap/gap_api.c \
+    ./gap/gap_utils.c \
+    ./gap/gap_conn.c \
     ./gatt/gatt_sr.c \
     ./gatt/gatt_cl.c \
     ./gatt/gatt_api.c \
@@ -96,6 +100,7 @@
     ./avct/avct_lcb_act.c \
     ./smp/smp_main.c \
     ./smp/smp_l2c.c \
+    ./smp/aes.c \
     ./smp/smp_cmac.c \
     ./smp/smp_utils.c \
     ./smp/smp_act.c \
diff --git a/stack/avdt/avdt_api.c b/stack/avdt/avdt_api.c
index 67fe452..855f17e 100644
--- a/stack/avdt/avdt_api.c
+++ b/stack/avdt/avdt_api.c
@@ -883,6 +883,70 @@
 
 /*******************************************************************************
 **
+** Function         AVDT_WriteReqOpt
+**
+** Description      Send a media packet to the peer device.  The stream must
+**                  be started before this function is called.  Also, this
+**                  function can only be called if the stream is a SRC.
+**
+**                  When AVDTP has sent the media packet and is ready for the
+**                  next packet, an AVDT_WRITE_CFM_EVT is sent to the
+**                  application via the control callback.  The application must
+**                  wait for the AVDT_WRITE_CFM_EVT before it makes the next
+**                  call to AVDT_WriteReq().  If the applications calls
+**                  AVDT_WriteReq() before it receives the event the packet
+**                  will not be sent.  The application may make its first call
+**                  to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+**                  or AVDT_START_IND_EVT.
+**
+**                  The application passes the packet using the BT_HDR structure.
+**                  This structure is described in section 2.1.  The offset
+**                  field must be equal to or greater than AVDT_MEDIA_OFFSET
+**                  (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used).
+**                  This allows enough space in the buffer for the L2CAP and
+**                  AVDTP headers.
+**
+**                  The memory pointed to by p_pkt must be a GKI buffer
+**                  allocated by the application.  This buffer will be freed
+**                  by the protocol stack; the application must not free
+**                  this buffer.
+**
+**                  The opt parameter allows passing specific options like:
+**                  - NO_RTP : do not add the RTP header to buffer
+**
+** Returns          AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt, tAVDT_DATA_OPT_MASK opt)
+{
+    tAVDT_SCB       *p_scb;
+    tAVDT_SCB_EVT   evt;
+    UINT16          result = AVDT_SUCCESS;
+
+    BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
+
+    /* map handle to scb */
+    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
+    {
+        result = AVDT_BAD_HANDLE;
+    }
+    else
+    {
+        evt.apiwrite.p_buf = p_pkt;
+        evt.apiwrite.time_stamp = time_stamp;
+        evt.apiwrite.m_pt = m_pt;
+        evt.apiwrite.opt = opt;
+#if AVDT_MULTIPLEXING == TRUE
+        GKI_init_q (&evt.apiwrite.frag_q);
+#endif
+        avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
+    }
+
+    return result;
+}
+
+/*******************************************************************************
+**
 ** Function         AVDT_WriteReq
 **
 ** Description      Send a media packet to the peer device.  The stream must
@@ -916,29 +980,7 @@
 *******************************************************************************/
 UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp, UINT8 m_pt)
 {
-    tAVDT_SCB       *p_scb;
-    tAVDT_SCB_EVT   evt;
-    UINT16          result = AVDT_SUCCESS;
-
-    BTTRC_AVDT_API0(AVDT_TRACE_API_WRITE_REQ);
-
-    /* map handle to scb */
-    if ((p_scb = avdt_scb_by_hdl(handle)) == NULL)
-    {
-        result = AVDT_BAD_HANDLE;
-    }
-    else
-    {
-        evt.apiwrite.p_buf = p_pkt;
-        evt.apiwrite.time_stamp = time_stamp;
-        evt.apiwrite.m_pt = m_pt;
-#if AVDT_MULTIPLEXING == TRUE
-        GKI_init_q (&evt.apiwrite.frag_q);
-#endif
-        avdt_scb_event(p_scb, AVDT_SCB_API_WRITE_REQ_EVT, &evt);
-    }
-
-    return result;
+    return AVDT_WriteReqOpt(handle, p_pkt, time_stamp, m_pt, AVDT_DATA_OPT_NONE);
 }
 
 /*******************************************************************************
@@ -1248,7 +1290,7 @@
     tAVDT_TC_TBL    *p_tbl;
     UINT8           *p, *plen, *pm1, *p_end;
 #if AVDT_MULTIPLEXING == TRUE
-    UINT8           *p_al, u;
+    UINT8           *p_al=NULL, u;
 #endif
     UINT32  ssrc;
     UINT16  len;
diff --git a/stack/avdt/avdt_ccb_act.c b/stack/avdt/avdt_ccb_act.c
index 5719be9..12c11b4 100644
--- a/stack/avdt/avdt_ccb_act.c
+++ b/stack/avdt/avdt_ccb_act.c
@@ -167,10 +167,10 @@
         if (p_scb->allocated)
         {
             /* copy sep info */
-            sep_info[i].in_use = p_scb->in_use;
-            sep_info[i].seid = i + 1;
-            sep_info[i].media_type = p_scb->cs.media_type;
-            sep_info[i].tsep = p_scb->cs.tsep;
+            sep_info[p_data->msg.discover_rsp.num_seps].in_use = p_scb->in_use;
+            sep_info[p_data->msg.discover_rsp.num_seps].seid = i + 1;
+            sep_info[p_data->msg.discover_rsp.num_seps].media_type = p_scb->cs.media_type;
+            sep_info[p_data->msg.discover_rsp.num_seps].tsep = p_scb->cs.tsep;
 
             p_data->msg.discover_rsp.num_seps++;
         }
diff --git a/stack/avdt/avdt_int.h b/stack/avdt/avdt_int.h
index 9b101fc..04968a6 100644
--- a/stack/avdt/avdt_int.h
+++ b/stack/avdt/avdt_int.h
@@ -459,6 +459,7 @@
     UINT32      data_len;
 #endif
     UINT8       m_pt;
+    tAVDT_DATA_OPT_MASK     opt;
 } tAVDT_SCB_APIWRITE;
 
 /* type for AVDT_SCB_TC_CLOSE_EVT */
diff --git a/stack/avdt/avdt_scb_act.c b/stack/avdt/avdt_scb_act.c
index c2ced74..66f9b7d 100644
--- a/stack/avdt/avdt_scb_act.c
+++ b/stack/avdt/avdt_scb_act.c
@@ -1213,19 +1213,22 @@
     }
 
     /* build a media packet */
+    /* Add RTP header if required */
+    if ( !(p_data->apiwrite.opt & AVDT_DATA_OPT_NO_RTP) )
+    {
+        ssrc = avdt_scb_gen_ssrc(p_scb);
 
-    ssrc = avdt_scb_gen_ssrc(p_scb);
+        p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
+        p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
 
-    p_data->apiwrite.p_buf->len += AVDT_MEDIA_HDR_SIZE;
-    p_data->apiwrite.p_buf->offset -= AVDT_MEDIA_HDR_SIZE;
+        p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
 
-    p = (UINT8 *)(p_data->apiwrite.p_buf + 1) + p_data->apiwrite.p_buf->offset;
-
-    UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
-    UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
-    UINT16_TO_BE_STREAM(p, p_scb->media_seq);
-    UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
-    UINT32_TO_BE_STREAM(p, ssrc);
+        UINT8_TO_BE_STREAM(p, AVDT_MEDIA_OCTET1);
+        UINT8_TO_BE_STREAM(p, p_data->apiwrite.m_pt);
+        UINT16_TO_BE_STREAM(p, p_scb->media_seq);
+        UINT32_TO_BE_STREAM(p, p_data->apiwrite.time_stamp);
+        UINT32_TO_BE_STREAM(p, ssrc);
+    }
 
     p_scb->media_seq++;
 
diff --git a/stack/btm/btm_acl.c b/stack/btm/btm_acl.c
index e3ac11b..eb847bb 100644
--- a/stack/btm/btm_acl.c
+++ b/stack/btm/btm_acl.c
@@ -127,8 +127,6 @@
     /* If here, no BD Addr found */
     return(xx);
 }
-
-
 /*******************************************************************************
 **
 ** Function         btm_acl_created
@@ -142,7 +140,7 @@
 void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
                       UINT16 hci_handle, UINT8 link_role, UINT8 is_le_link)
 {
-    tBTM_SEC_DEV_REC *p_dev_rec;
+    tBTM_SEC_DEV_REC *p_dev_rec = NULL;
     UINT8             yy;
     tACL_CONN        *p;
     UINT8             xx;
@@ -173,8 +171,16 @@
             p->hci_handle        = hci_handle;
             p->link_role         = link_role;
             p->link_up_issued    = FALSE;
+
 #if BLE_INCLUDED == TRUE
             p->is_le_link        = is_le_link;
+
+            if (is_le_link)
+            {
+                p->conn_addr_type = BLE_ADDR_PUBLIC;
+                BTM_GetLocalDeviceAddr(p->conn_addr);
+            }
+
 #endif
             p->restore_pkt_types = 0;   /* Only exists while SCO is active */
             p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
@@ -193,8 +199,12 @@
             if (bdn)
                 memcpy (p->remote_name, bdn, BTM_MAX_REM_BD_NAME_LEN);
 
-
-            /* Check if we already know features for this device */
+            /* if BR/EDR do something more */
+            if (!is_le_link)
+            {
+                btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
+                btsnd_hcic_rmt_ver_req (p->hci_handle);
+            }
             p_dev_rec = btm_find_dev_by_handle (hci_handle);
 
 #if (BLE_INCLUDED == TRUE)
@@ -204,18 +214,9 @@
             }
 #endif
 
-
-            if (p_dev_rec
-#if (BLE_INCLUDED == TRUE)
-                && p_dev_rec->device_type != BT_DEVICE_TYPE_BLE
-#endif
-               )
+            if (p_dev_rec && !is_le_link)
             {
 
-                /* if BR/EDR do something more */
-                btsnd_hcic_read_rmt_clk_offset (p->hci_handle);
-                btsnd_hcic_rmt_ver_req (p->hci_handle);
-
                 for (yy = 0; yy < BD_FEATURES_LEN; yy++)
                 {
                     if (p_dev_rec->features[yy])
@@ -238,17 +239,15 @@
                     }
                 }
             }
+
 #if (BLE_INCLUDED == TRUE)
             /* If here, features are not known yet */
-            if (p_dev_rec && p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+            if (p_dev_rec && is_le_link)
             {
                 btm_establish_continue(p);
 
                 if (link_role == HCI_ROLE_MASTER)
                 {
-                    btm_ble_update_bg_state();
-                    btm_ble_resume_bg_conn (NULL, FALSE);
-
                     btsnd_hcic_ble_read_remote_feat(p->hci_handle);
                 }
             }
@@ -282,10 +281,10 @@
     if (btm_cb.devcb.p_switch_role_cb && (bda &&
                                           (0 == memcmp(btm_cb.devcb.switch_role_ref_data.remote_bd_addr, bda, BD_ADDR_LEN))))
     {
-        memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
-        ref_data.hci_status = hci_status;
         memcpy (&ref_data, &btm_cb.devcb.switch_role_ref_data, sizeof(tBTM_ROLE_SWITCH_CMPL));
+        ref_data.hci_status = hci_status;
         (*btm_cb.devcb.p_switch_role_cb)(&ref_data);
+        memset (&btm_cb.devcb.switch_role_ref_data, 0, sizeof(tBTM_ROLE_SWITCH_CMPL));
         btm_cb.devcb.p_switch_role_cb = NULL;
     }
 }
@@ -309,7 +308,6 @@
 #endif
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
     tBTM_SEC_DEV_REC *p_dev_rec=NULL;
-    UINT16 combined_mode;
 #endif
 
     BTM_TRACE_DEBUG0 ("btm_acl_removed");
@@ -351,23 +349,6 @@
                           btm_cb.ble_ctr_cb.inq_var.connectable_mode,
                           p->link_role);
 
-
-        /* If we are LE connectable, check if we need to start advertising again */
-        if ( p->is_le_link && (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) )
-        {
-            tACL_CONN   *pa = &btm_cb.acl_db[0];
-            UINT16       xx;
-
-            for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
-            {
-                /* If any other LE link is up, we are still not connectable */
-                if (pa->in_use && pa->is_le_link)
-                    return;
-            }
-            combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
-            btm_ble_set_connectability ( combined_mode );
-        }
-
         p_dev_rec = btm_find_dev(bda);
         if ( p_dev_rec)
         {
@@ -451,7 +432,6 @@
         case BTM_BLI_ACL_UP_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_ACL_UP_EVT");
             btm_cb.num_acl++;
-            busy_level = (UINT8)btm_cb.num_acl;
             break;
         case BTM_BLI_ACL_DOWN_EVT:
             if (btm_cb.num_acl)
@@ -463,35 +443,39 @@
             {
                 BTM_TRACE_ERROR0 ("BTM_BLI_ACL_DOWN_EVT issued, but num_acl already zero !!!");
             }
-            busy_level = (UINT8)btm_cb.num_acl;
             break;
         case BTM_BLI_PAGE_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_EVT");
             btm_cb.is_paging = TRUE;
-            busy_level = BTM_BL_PAGING_STARTED;
+            evt.busy_level_flags= BTM_BL_PAGING_STARTED;
             break;
         case BTM_BLI_PAGE_DONE_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_PAGE_DONE_EVT");
             btm_cb.is_paging = FALSE;
-            busy_level = BTM_BL_PAGING_COMPLETE;
+            evt.busy_level_flags = BTM_BL_PAGING_COMPLETE;
             break;
         case BTM_BLI_INQ_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_EVT");
             btm_cb.is_inquiry = TRUE;
-            busy_level = BTM_BL_INQUIRY_STARTED;
+            evt.busy_level_flags = BTM_BL_INQUIRY_STARTED;
             break;
         case BTM_BLI_INQ_CANCEL_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_CANCEL_EVT");
             btm_cb.is_inquiry = FALSE;
-            busy_level = BTM_BL_INQUIRY_CANCELLED;
+            evt.busy_level_flags = BTM_BL_INQUIRY_CANCELLED;
             break;
         case BTM_BLI_INQ_DONE_EVT:
             BTM_TRACE_DEBUG0 ("BTM_BLI_INQ_DONE_EVT");
             btm_cb.is_inquiry = FALSE;
-            busy_level = BTM_BL_INQUIRY_COMPLETE;
+            evt.busy_level_flags = BTM_BL_INQUIRY_COMPLETE;
             break;
     }
 
+    if (btm_cb.is_paging || btm_cb.is_inquiry)
+        busy_level = 10;
+    else
+        busy_level = (UINT8)btm_cb.num_acl;
+
     if (busy_level != btm_cb.busy_level)
     {
         evt.event         = BTM_BL_UPDATE_EVT;
@@ -631,10 +615,7 @@
     /* Wake up the link if in sniff or park before attempting switch */
     if (pwr_mode == BTM_PM_MD_PARK || pwr_mode == BTM_PM_MD_SNIFF)
     {
-/* Coverity FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment.     */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
-                                the other data members of tBTM_PM_PWR_MD are ignored
-*/
+        memset( (void*)&settings, 0, sizeof(settings));
         settings.mode = BTM_PM_MD_ACTIVE;
         status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
         if (status != BTM_CMD_STARTED)
@@ -646,7 +627,8 @@
     /* some devices do not support switch while encryption is on */
     else
     {
-        if (((p_dev_rec = btm_find_dev (remote_bd_addr)) != NULL)
+        p_dev_rec = btm_find_dev (remote_bd_addr);
+        if ((p_dev_rec != NULL)
             && ((p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED) != 0)
             && !BTM_EPR_AVAILABLE(p))
         {
@@ -741,10 +723,7 @@
     /* Wake up the link if in park before attempting to change link keys */
     if (pwr_mode == BTM_PM_MD_PARK)
     {
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
-                                the other data members of tBTM_PM_PWR_MD are ignored
-*/
+        memset( (void*)&settings, 0, sizeof(settings));
         settings.mode = BTM_PM_MD_ACTIVE;
         status = BTM_SetPowerMode (BTM_PM_SET_ONLY_ID, p->remote_addr, &settings);
         if (status != BTM_CMD_STARTED)
@@ -863,12 +842,11 @@
 {
     tACL_CONN *p;
     UINT8     xx;
+    tBTM_SEC_DEV_REC  *p_dev_rec;
 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
     tBTM_BL_ROLE_CHG_DATA   evt;
 #endif
-#if BTM_DISC_DURING_RS == TRUE
-    tBTM_SEC_DEV_REC  *p_dev_rec;
-#endif
+
     BTM_TRACE_DEBUG3 ("btm_acl_encrypt_change handle=%d status=%d encr_enabl=%d", handle, status, encr_enable);
     xx = btm_handle_to_acl_index(handle);
     /* don't assume that we can never get a bad hci_handle */
@@ -1044,8 +1022,36 @@
 *******************************************************************************/
 void BTM_SetDefaultLinkPolicy (UINT16 settings)
 {
-    BTM_TRACE_DEBUG0 ("BTM_SetDefaultLinkPolicy");
+    UINT8 *localFeatures = BTM_ReadLocalFeatures();
+
+    BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy setting:0x%04x", settings);
+
+    if((settings & HCI_ENABLE_MASTER_SLAVE_SWITCH) && (!HCI_SWITCH_SUPPORTED(localFeatures)))
+    {
+        settings &= ~HCI_ENABLE_MASTER_SLAVE_SWITCH;
+        BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy switch not supported (settings: 0x%04x)", settings);
+    }
+    if ((settings & HCI_ENABLE_HOLD_MODE) && (!HCI_HOLD_MODE_SUPPORTED(localFeatures)))
+    {
+        settings &= ~HCI_ENABLE_HOLD_MODE;
+        BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy hold not supported (settings: 0x%04x)", settings);
+    }
+    if ((settings & HCI_ENABLE_SNIFF_MODE) && (!HCI_SNIFF_MODE_SUPPORTED(localFeatures)))
+    {
+        settings &= ~HCI_ENABLE_SNIFF_MODE;
+        BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy sniff not supported (settings: 0x%04x)", settings);
+    }
+    if ((settings & HCI_ENABLE_PARK_MODE) && (!HCI_PARK_MODE_SUPPORTED(localFeatures)))
+    {
+        settings &= ~HCI_ENABLE_PARK_MODE;
+        BTM_TRACE_DEBUG1("BTM_SetDefaultLinkPolicy park not supported (settings: 0x%04x)", settings);
+    }
+    BTM_TRACE_DEBUG1("Set DefaultLinkPolicy:0x%04x", settings);
+
     btm_cb.btm_def_link_policy = settings;
+
+    /* Set the default Link Policy of the controller */
+    btsnd_hcic_write_def_policy_set(settings);
 }
 
 
@@ -1361,8 +1367,6 @@
 
         if (btm_cb.btm_def_link_policy)
             BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
-
-        BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
     }
 #endif
     p_acl_cb->link_up_issued = TRUE;
@@ -1377,7 +1381,6 @@
         evt_data.conn.p_dc  = p_acl_cb->remote_dc;
         evt_data.conn.p_features = p_acl_cb->features;
 
-
         (*btm_cb.p_bl_changed_cb)(&evt_data);
     }
     btm_acl_update_busy_level (BTM_BLI_ACL_UP_EVT);
@@ -1410,6 +1413,30 @@
 
 /*******************************************************************************
 **
+** Function         BTM_GetLinkSuperTout
+**
+** Description      Read the link supervision timeout value of the connection
+**
+** Returns          status of the operation
+**
+*******************************************************************************/
+tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda, UINT16 *p_timeout)
+{
+    tACL_CONN   *p = btm_bda_to_acl(remote_bda);
+
+    BTM_TRACE_DEBUG0 ("BTM_GetLinkSuperTout");
+    if (p != (tACL_CONN *)NULL)
+    {
+        *p_timeout = p->link_super_tout;
+        return(BTM_SUCCESS);
+    }
+    /* If here, no BD Addr found */
+    return(BTM_UNKNOWN_ADDR);
+}
+
+
+/*******************************************************************************
+**
 ** Function         BTM_SetLinkSuperTout
 **
 ** Description      Create and send HCI "Write Link Supervision Timeout" command
@@ -1802,7 +1829,7 @@
 {
     tACL_CONN   *p;
 
-    BTM_TRACE_API6 ("BTM_ReadClockOffset: RemBdAddr: %02x%02x%02x%02x%02x%02x",
+    BTM_TRACE_API6 ("BTM_IsAclConnectionUp: RemBdAddr: %02x%02x%02x%02x%02x%02x",
                     remote_bda[0], remote_bda[1], remote_bda[2],
                     remote_bda[3], remote_bda[4], remote_bda[5]);
 
@@ -1967,12 +1994,11 @@
     UINT8                   *p_bda = (bd_addr) ? bd_addr : btm_cb.devcb.switch_role_ref_data.remote_bd_addr;
     tACL_CONN               *p = btm_bda_to_acl(p_bda);
     tBTM_ROLE_SWITCH_CMPL   *p_data = &btm_cb.devcb.switch_role_ref_data;
+    tBTM_SEC_DEV_REC        *p_dev_rec;
 #if (defined(BTM_BUSY_LEVEL_CHANGE_INCLUDED) && BTM_BUSY_LEVEL_CHANGE_INCLUDED == TRUE)
     tBTM_BL_ROLE_CHG_DATA   evt;
 #endif
-#if BTM_DISC_DURING_RS == TRUE
-    tBTM_SEC_DEV_REC  *p_dev_rec;
-#endif
+
     BTM_TRACE_DEBUG0 ("btm_acl_role_changed");
     /* Ignore any stray events */
     if (p == NULL)
@@ -2297,14 +2323,7 @@
             pkt_size = HCI_DM1_PACKET_SIZE;
     }
 
-#ifdef BRCM_VS
-    /* Using HCI size 1017 instead of 1021 */
-    if ((pkt_size == HCI_EDR3_DH5_PACKET_SIZE)
-        && (btu_cb.hcit_acl_data_size == 1017))
-        pkt_size = 1017;
-#endif
-
-    return(pkt_size);
+   return(pkt_size);
 }
 
 /*******************************************************************************
@@ -2830,14 +2849,15 @@
     }
     else    /* otherwise can disconnect right away */
 #endif
-
-    if (hci_handle != 0xFFFF)
     {
-        if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
-            status = BTM_NO_RESOURCES;
+        if (hci_handle != 0xFFFF)
+        {
+            if (!btsnd_hcic_disconnect (hci_handle, HCI_ERR_PEER_USER))
+                status = BTM_NO_RESOURCES;
+        }
+        else
+            status = BTM_UNKNOWN_ADDR;
     }
-    else
-        status = BTM_UNKNOWN_ADDR;
 
     return status;
 }
diff --git a/stack/btm/btm_ble.c b/stack/btm/btm_ble.c
index 74b5767..1d2cdf3 100644
--- a/stack/btm/btm_ble.c
+++ b/stack/btm/btm_ble.c
@@ -31,14 +31,15 @@
 #include "btm_int.h"
 #include "btm_ble_api.h"
 #include "smp_api.h"
+#include "l2c_int.h"
+#include "gap_api.h"
 
 #if SMP_INCLUDED == TRUE
 extern BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature);
 extern void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable);
 extern BOOLEAN smp_proc_ltk_request(BD_ADDR bda);
 #endif
-
-static void btm_ble_update_active_bgconn_scan_params(void);
+extern void gatt_notify_enc_cmpl(BD_ADDR bd_addr);
 
 /*******************************************************************************/
 /* External Function to be called by other modules                             */
@@ -114,7 +115,7 @@
     {
         p_dev_rec->sec_flags |= BTM_SEC_NAME_KNOWN;
         BCM_STRNCPY_S ((char *)p_dev_rec->sec_bd_name, sizeof (p_dev_rec->sec_bd_name),
-            (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
+                       (char *)bd_name, BTM_MAX_REM_BD_NAME_LEN);
     }
     p_dev_rec->device_type = dev_type;
     p_dev_rec->ble.ble_addr_type = addr_type;
@@ -158,9 +159,10 @@
     p_dev_rec = btm_find_dev (bd_addr);
     if (!p_dev_rec || !p_le_key ||
         (key_type != BTM_LE_KEY_PENC && key_type != BTM_LE_KEY_PID &&
-         key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC))
+         key_type != BTM_LE_KEY_PCSRK && key_type != BTM_LE_KEY_LENC &&
+         key_type != BTM_LE_KEY_LCSRK))
     {
-        BTM_TRACE_WARNING3 ("BTM_SecAddLeKey()  No BT Link Key, Wrong Type, or No Device record \
+        BTM_TRACE_WARNING3 ("BTM_SecAddBleKey()  Wrong Type, or No Device record \
                         for bdaddr: %08x%04x, Type: %d",
                             (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
                             (bd_addr[4]<<8)+bd_addr[5], key_type);
@@ -283,29 +285,54 @@
 **
 ** Function         BTM_ReadConnectionAddr
 **
-** Description      This function is called to set the local device random address
+** Description      This function is called to get the local device address information
 **                  .
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTM_ReadConnectionAddr (BD_ADDR conn_addr)
+void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr, tBLE_ADDR_TYPE *p_addr_type)
 {
 #if BLE_INCLUDED == TRUE
-    BTM_TRACE_DEBUG0 ("BTM_ReadConnectionAddr");
-    if (btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_PUBLIC)
+    tACL_CONN       *p_acl = btm_bda_to_acl(remote_bda);
+
+    if (p_acl == NULL)
     {
-        BTM_GetLocalDeviceAddr(conn_addr);
+        BTM_TRACE_ERROR0("No connection exist!");
+        return;
     }
-    else
-    {
-        memcpy (conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
-    }
+    memcpy(local_conn_addr, p_acl->conn_addr, BD_ADDR_LEN);
+    * p_addr_type = p_acl->conn_addr_type;
+
+    BTM_TRACE_DEBUG2 ("BTM_ReadConnectionAddr address type: %d addr: 0x%02x",
+                    p_acl->conn_addr_type, p_acl->conn_addr[0]);
+
 #endif
 }
 
 /*******************************************************************************
 **
+** Function         BTM_ReadRemoteConnectionAddr
+**
+** Description      This function is read the remote device address currently used
+**                  .
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr, BD_ADDR conn_addr, tBLE_ADDR_TYPE *p_addr_type)
+{
+    BOOLEAN         st = TRUE;
+#if BLE_INCLUDED == TRUE
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev(pseudo_addr);
+
+    memcpy(conn_addr, pseudo_addr, BD_ADDR_LEN);
+    *p_addr_type = p_dev_rec->ble.ble_addr_type;
+#endif
+    return st;
+}
+/*******************************************************************************
+**
 ** Function         BTM_SecurityGrant
 **
 ** Description      This function is called to grant security process.
@@ -346,6 +373,12 @@
     tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
     tSMP_STATUS      res_smp = (res == BTM_SUCCESS) ? SMP_SUCCESS : SMP_PASSKEY_ENTRY_FAIL;
 
+    if (p_dev_rec == NULL)
+    {
+        BTM_TRACE_ERROR0("Passkey reply to Unknown device");
+        return;
+    }
+
     p_dev_rec->sec_flags   |= BTM_SEC_LINK_KEY_AUTHED;
     BTM_TRACE_DEBUG0 ("BTM_BlePasskeyReply");
     SMP_PasskeyReply(bd_addr, res_smp, passkey);
@@ -371,6 +404,13 @@
     tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
 
     BTM_TRACE_DEBUG0 ("BTM_BleOobDataReply");
+
+    if (p_dev_rec == NULL)
+    {
+        BTM_TRACE_ERROR0("BTM_BleOobDataReply() to Unknown device");
+        return;
+    }
+
     p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_AUTHED;
     SMP_OobDataReply(bd_addr, res_smp, len, p_data);
 #endif
@@ -411,8 +451,10 @@
             new_param = TRUE;
         }
 
-        if (new_param)
-            btm_ble_update_active_bgconn_scan_params();
+        if (new_param && p_ble_cb->conn_state == BLE_BG_CONN)
+        {
+            btm_ble_suspend_bg_conn();
+        }
     }
     else
     {
@@ -452,7 +494,7 @@
     if (BTM_BLE_VALID_PRAM(min_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
         BTM_BLE_VALID_PRAM(max_conn_int, BTM_BLE_CONN_INT_MIN, BTM_BLE_CONN_INT_MAX) &&
         BTM_BLE_VALID_PRAM(supervision_tout, BTM_BLE_CONN_SUP_TOUT_MIN, BTM_BLE_CONN_SUP_TOUT_MAX) &&
-        slave_latency <= BTM_BLE_CONN_LATENCY_MAX)
+        (slave_latency <= BTM_BLE_CONN_LATENCY_MAX || slave_latency == BTM_BLE_CONN_PARAM_UNDEF))
     {
         if (p_dev_rec)
         {
@@ -544,41 +586,83 @@
     return;
 }
 
+/*******************************************************************************
+**
+** Function         BTM_BleReceiverTest
+**
+** Description      This function is called to start the LE Receiver test
+**
+** Parameter       rx_freq - Frequency Range
+**               p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+     btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+     if (btsnd_hcic_ble_receiver_test(rx_freq) == FALSE)
+     {
+          BTM_TRACE_ERROR1("%s: Unable to Trigger LE receiver test", __FUNCTION__);
+     }
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleTransmitterTest
+**
+** Description      This function is called to start the LE Transmitter test
+**
+** Parameter       tx_freq - Frequency Range
+**                       test_data_len - Length in bytes of payload data in each packet
+**                       packet_payload - Pattern to use in the payload
+**                       p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+                                 UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+     btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+     if (btsnd_hcic_ble_transmitter_test(tx_freq, test_data_len, packet_payload) == FALSE)
+     {
+          BTM_TRACE_ERROR1("%s: Unable to Trigger LE transmitter test", __FUNCTION__);
+     }
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleTestEnd
+**
+** Description      This function is called to stop the in-progress TX or RX test
+**
+** Parameter       p_cmd_cmpl_cback - Command complete callback
+**
+*******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback)
+{
+     btm_cb.devcb.p_le_test_cmd_cmpl_cb = p_cmd_cmpl_cback;
+
+     if (btsnd_hcic_ble_test_end() == FALSE)
+     {
+          BTM_TRACE_ERROR1("%s: Unable to End the LE TX/RX test", __FUNCTION__);
+     }
+}
 
 /*******************************************************************************
 ** Internal Functions
 *******************************************************************************/
 #if BLE_INCLUDED == TRUE
 
-/*******************************************************************************
-**
-** Function         btm_ble_update_active_bgconn_scan_params
-**
-** Description      This function is called to update the scan parameter if background
-**                  connection has been active.
-**
-*******************************************************************************/
-static void btm_ble_update_active_bgconn_scan_params(void)
+void btm_ble_test_command_complete(UINT8 *p)
 {
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    tBTM_BLE_SEL_CBACK   *p_select_cback;
+    tBTM_CMPL_CB   *p_cb = btm_cb.devcb.p_le_test_cmd_cmpl_cb;
+    UINT8           status;
 
-    /* if active , cancel and restart and apply the params */
-    if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+    btm_cb.devcb.p_le_test_cmd_cmpl_cb = NULL;
+
+    if (p_cb)
     {
-        if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
-        {
-            if (btm_ble_start_auto_conn(FALSE))
-                btm_ble_start_auto_conn(TRUE);
-        }
-        else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
-        {
-            p_select_cback = p_cb->p_select_cback;
-            if (btm_ble_start_select_conn(FALSE, NULL))
-                btm_ble_start_select_conn(TRUE, p_select_cback);
-        }
+        (*p_cb)(p);
     }
-    return;
 }
 
 /*******************************************************************************
@@ -643,7 +727,7 @@
 }
 
 
-#if (SMP_INCLUDED == TRUE)
+    #if (SMP_INCLUDED == TRUE)
 
 /*******************************************************************************
 **
@@ -744,6 +828,7 @@
 {
     tBTM_SEC_DEV_REC *p_rec;
     tBTM_LE_EVT_DATA    cb_data;
+    UINT8 i;
 
     BTM_TRACE_DEBUG2 ("btm_sec_save_le_key key_type=0x%x pass_to_application=%d",key_type, pass_to_application);
     /* Store the updated key in the device database */
@@ -776,7 +861,14 @@
                 break;
 
             case BTM_LE_KEY_PID:
-                memcpy(p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN);
+                for (i=0; i<BT_OCTET16_LEN; i++)
+                {
+                    p_rec->ble.keys.irk[i] = p_keys->pid_key.irk[i];
+                }
+
+                 //memcpy( p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN); todo will crash the system
+                memcpy(p_rec->ble.static_addr, p_keys->pid_key.static_addr, BD_ADDR_LEN);
+                p_rec->ble.static_addr_type = p_keys->pid_key.addr_type;
                 p_rec->ble.key_type |= BTM_LE_KEY_PID;
                 BTM_TRACE_DEBUG1("BTM_LE_KEY_PID key_type=0x%x save peer IRK",  p_rec->ble.key_type);
                 break;
@@ -839,7 +931,6 @@
         {
             cb_data.key.p_key_value = p_keys;
             cb_data.key.key_type = key_type;
-
             (*btm_cb.api.p_le_callback) (BTM_LE_KEY_EVT, bd_addr, &cb_data);
         }
         return;
@@ -919,7 +1010,8 @@
         return;
     }
 
-    if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
+    if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+        p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING)
     {
         /* race condition: discard the security request while master is encrypting the link */
         *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
@@ -960,12 +1052,13 @@
             }
             else
             {
-                /* To avoid re-encryption on an encrypted link for an equal condition encryption
+                /* To avoid re-encryption on an encrypted link for an equal condition encryption */
+                /* if link has been encrypted, do nothing, go straight to furhter action
                 if (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)
                     *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_DISCARD;
                 else
                 */
-                    *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
+                *p_sec_req_act = BTM_BLE_SEC_REQ_ACT_ENCRYPT;
             }
         }
         else
@@ -1000,13 +1093,14 @@
     tBTM_BLE_SEC_ACT    sec_act = *(tBTM_BLE_SEC_ACT *)p_ref_data ;
     tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bd_addr);
 
-    BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
-
     if (p_rec == NULL)
     {
+        BTM_TRACE_WARNING1 ("btm_ble_set_encryption (NULL device record!! sec_act=0x%x", sec_act);
         return(BTM_WRONG_MODE);
     }
 
+    BTM_TRACE_DEBUG2 ("btm_ble_set_encryption sec_act=0x%x role_master=%d", sec_act, p_rec->role_master);
+
     if (sec_act == BTM_BLE_SEC_ENCRYPT_MITM)
     {
         p_rec->security_required |= BTM_SEC_IN_MITM;
@@ -1018,9 +1112,11 @@
             if (link_role == BTM_ROLE_MASTER)
             {
                 /* start link layer encryption using the security info stored */
-                btm_ble_start_encrypt(bd_addr, FALSE, NULL);
-                p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
-                cmd = BTM_CMD_STARTED;
+                if (btm_ble_start_encrypt(bd_addr, FALSE, NULL))
+                {
+                    p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
+                    cmd = BTM_CMD_STARTED;
+                }
                 break;
             }
             /* if salve role then fall through to call SMP_Pair below which will send a
@@ -1123,30 +1219,36 @@
 void btm_ble_link_encrypted(BD_ADDR bd_addr, UINT8 encr_enable)
 {
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (bd_addr);
+    BOOLEAN             enc_cback;
+
+    if (!p_dev_rec)
+    {
+        BTM_TRACE_WARNING1 ("btm_ble_link_encrypted (No Device Found!) encr_enable=%d", encr_enable);
+        return;
+    }
 
     BTM_TRACE_DEBUG1 ("btm_ble_link_encrypted encr_enable=%d", encr_enable);
 
+    enc_cback = (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING);
+
     smp_link_encrypted(bd_addr, encr_enable);
 
-    if (p_dev_rec)
+    BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
+
+    if (encr_enable && p_dev_rec->enc_key_size == 0)
+        p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
+
+    p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+    if (p_dev_rec->p_callback && enc_cback)
     {
-        BTM_TRACE_DEBUG1(" p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags);
+        if (encr_enable)
+            btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
+        else if (p_dev_rec->role_master)
+            btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
 
-        if (encr_enable && p_dev_rec->enc_key_size == 0)
-            p_dev_rec->enc_key_size = p_dev_rec->ble.keys.key_size;
-
-        if (p_dev_rec->p_callback)
-        {
-            if (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING)
-            {
-                if (encr_enable)
-                    btm_sec_dev_rec_cback_event(p_dev_rec, BTM_SUCCESS);
-                else if (p_dev_rec->role_master)
-                    btm_sec_dev_rec_cback_event(p_dev_rec, BTM_ERR_PROCESSING);
-            }
-        }
-        p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
     }
+    /* to notify GATT to send data if any request is pending */
+    gatt_notify_enc_cmpl(p_dev_rec->bd_addr);
 }
 
 /*******************************************************************************
@@ -1186,7 +1288,7 @@
         p_dev_rec = btm_find_dev_by_handle (p_cb->enc_handle);
 
         if ( p_dev_rec &&
-            p_dev_rec->ble.keys.div == div )
+             p_dev_rec->ble.keys.div == div )
         {
             BTM_TRACE_DEBUG0 ("LTK request OK");
             /* calculating LTK , LTK = E er(div) */
@@ -1305,6 +1407,110 @@
     return callback_rc;
 }
 
+/*******************************************************************************
+**
+** Function         btm_ble_connected
+**
+** Description      This function is when a LE connection to the peer device is
+**                  establsihed
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role,
+                        tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched)
+{
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
+    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
+
+    BTM_TRACE_EVENT0 ("btm_ble_connected");
+
+    /* Commenting out trace due to obf/compilation problems.
+    */
+#if (BT_USE_TRACES == TRUE)
+    if (p_dev_rec)
+    {
+        BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected :  handle:%d  enc_mode:%d  bda:%x RName:%s",
+                          handle,  enc_mode,
+                          (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
+                          p_dev_rec->sec_bd_name);
+
+        BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
+    }
+    else
+    {
+        BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected:   handle:%d  enc_mode:%d  bda:%x ",
+                          handle,  enc_mode,
+                          (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
+    }
+#endif
+
+    if (!p_dev_rec)
+    {
+        /* There is no device record for new connection.  Allocate one */
+        p_dev_rec = btm_sec_alloc_dev (bda);
+    }
+    else    /* Update the timestamp for this device */
+    {
+        p_dev_rec->timestamp = btm_cb.dev_rec_count++;
+    }
+
+    /* update device information */
+    p_dev_rec->device_type |= BT_DEVICE_TYPE_BLE;
+    p_dev_rec->hci_handle = handle;
+    p_dev_rec->ble.ble_addr_type = addr_type;
+
+    if (role == HCI_ROLE_MASTER)
+        p_dev_rec->role_master = TRUE;
+
+    if (role == HCI_ROLE_SLAVE)
+        p_cb->inq_var.adv_mode  = BTM_BLE_ADV_DISABLE;
+    p_cb->inq_var.directed_conn = FALSE;
+
+    return;
+}
+
+/*****************************************************************************
+**  Function        btm_ble_conn_complete
+**
+**  Description     LE connection complete.
+**
+******************************************************************************/
+void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
+{
+    UINT8       role, status, bda_type;
+    UINT16      handle;
+    BD_ADDR     bda;
+    UINT16      conn_interval, conn_latency, conn_timeout;
+    BOOLEAN     match = FALSE;
+
+    STREAM_TO_UINT8   (status, p);
+    STREAM_TO_UINT16   (handle, p);
+    STREAM_TO_UINT8    (role, p);
+    STREAM_TO_UINT8    (bda_type, p);
+    STREAM_TO_BDADDR   (bda, p);
+
+    if (status == 0)
+    {
+        STREAM_TO_UINT16   (conn_interval, p);
+        STREAM_TO_UINT16   (conn_latency, p);
+        STREAM_TO_UINT16   (conn_timeout, p);
+        handle = HCID_GET_HANDLE (handle);
+
+        btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type, match);
+        l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
+                              conn_latency, conn_timeout);
+    }
+    else
+    {
+        role = HCI_ROLE_UNKNOWN;
+
+        if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+            btm_ble_dir_adv_tout();
+    }
+    btm_ble_update_mode_operation(role, bda, TRUE);
+}
+
 /*****************************************************************************
 **  Function        btm_proc_smp_cback
 **
@@ -1314,7 +1520,7 @@
 UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
 {
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (bd_addr);
-    UINT8 res;
+    UINT8 res = 0;
 
     BTM_TRACE_DEBUG1 ("btm_proc_smp_cback event = %d", event);
 
@@ -1336,11 +1542,7 @@
                 {
                     /* the callback function implementation may change the IO capability... */
                     BTM_TRACE_DEBUG1 ("btm_cb.api.p_le_callback=0x%x", btm_cb.api.p_le_callback );
-                    (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
-                }
-                else
-                {
-                    BTM_TRACE_ERROR0 ("btm_proc_smp_cback: btm_cb.api.p_le_callback ==NULL");
+                   (*btm_cb.api.p_le_callback) (event, bd_addr, (tBTM_LE_EVT_DATA *)p_data);
                 }
 
                 if (event == SMP_COMPLT_EVT)
@@ -1370,7 +1572,7 @@
                         else
                         {
                             BTM_TRACE_DEBUG0 ("Pairing failed - Not Removing ACL");
-	                        p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+                            p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
                         }
                     }
 #else
@@ -1406,7 +1608,7 @@
     return 0;
 }
 
-#endif  /* SMP_INCLUDED */
+    #endif  /* SMP_INCLUDED */
 #endif  /* BLE_INCLUDED */
 
 
@@ -1548,7 +1750,7 @@
 **
 *******************************************************************************/
 BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT32 counter,
-                             UINT8 *p_comp)
+                                UINT8 *p_comp)
 {
     BOOLEAN             verified = FALSE;
 #if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
@@ -1844,7 +2046,7 @@
     }
 }
 
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
+    #if BTM_BLE_CONFORMANCE_TESTING == TRUE
 /*******************************************************************************
 **
 ** Function         btm_ble_set_no_disc_if_pair_fail
@@ -1894,6 +2096,33 @@
     btm_cb.devcb.test_local_sign_cntr =  test_local_sign_cntr;
 }
 
+/*******************************************************************************
+**
+** Function         btm_set_random_address
+**
+** Description      This function set a random address to local controller.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_set_random_address(BD_ADDR random_bda)
+{
+    tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+    BOOLEAN     adv_mode = btm_cb.ble_ctr_cb.inq_var.adv_mode ;
+
+    BTM_TRACE_DEBUG0 ("btm_set_random_address");
+
+    if (adv_mode  == BTM_BLE_ADV_ENABLE)
+        btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
+
+    memcpy(p_cb->private_addr, random_bda, BD_ADDR_LEN);
+    btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+
+    if (adv_mode  == BTM_BLE_ADV_ENABLE)
+        btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE);
+
+
+}
 #endif /* BTM_BLE_CONFORMANCE_TESTING */
 
 
diff --git a/stack/btm/btm_ble_addr.c b/stack/btm/btm_ble_addr.c
index 04872f9..9ae37f9 100644
--- a/stack/btm/btm_ble_addr.c
+++ b/stack/btm/btm_ble_addr.c
@@ -28,11 +28,13 @@
 #include "hcimsgs.h"
 #include "btu.h"
 #include "btm_int.h"
-
+#include "btm_ble_int.h"
+#include "gap_api.h"
 
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
-    #include "smp_api.h"
-    #define BTM_BLE_PRIVATE_ADDR_INT    900             /* 15 minutes minimum for random address refreshing */
+#include "smp_api.h"
+#define BTM_BLE_PRIVATE_ADDR_INT    900           /* 15 minutes minimum for
+                                                   random address refreshing */
 
 /*******************************************************************************
 **
@@ -47,42 +49,24 @@
 static void btm_gen_resolve_paddr_cmpl(tSMP_ENC *p)
 {
     tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-    tBTM_BLE_INQ_CB  *p_inq_cb = &btm_cb.ble_ctr_cb.inq_var;
     BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_cmpl");
-    if (p && p->param_buf)
+
+    if (p)
     {
-        /* get the high bytes of the random address */
-        p_cb->private_addr[2] = p->param_buf[0];
-        p_cb->private_addr[1] = p->param_buf[1];
-        p_cb->private_addr[0] = p->param_buf[2];
-        /* mask off the 1st MSB */
-        p_cb->private_addr[0] &= 0xfe;
-        /* set the 2nd MSB to be 1 */
-        p_cb->private_addr[0] |= 0x02;
+        /* set hash to be LSB of rpAddress */
+        p_cb->private_addr[5] = p->param_buf[0];
+        p_cb->private_addr[4] = p->param_buf[1];
+        p_cb->private_addr[3] = p->param_buf[2];
         /* set it to controller */
         btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
 
-        p_inq_cb->own_addr_type = BLE_ADDR_RANDOM;
+        p_cb->own_addr_type = BLE_ADDR_RANDOM;
 
         /* start a periodical timer to refresh random addr */
         btu_stop_timer(&p_cb->raddr_timer_ent);
         btu_start_timer (&p_cb->raddr_timer_ent, BTU_TTYPE_BLE_RANDOM_ADDR,
                          BTM_BLE_PRIVATE_ADDR_INT);
 
-        /* if adv is active, restart adv with new private addr */
-        if (p_inq_cb->adv_mode == BTM_BLE_ADV_ENABLE)
-        {
-            btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
-
-            btsnd_hcic_ble_write_adv_params (p_inq_cb->adv_interval_min,
-                                             p_inq_cb->adv_interval_max,
-                                             p_inq_cb->evt_type,
-                                             p_inq_cb->own_addr_type,
-                                             p_inq_cb->direct_bda.type,
-                                             p_inq_cb->direct_bda.bda,
-                                             p_inq_cb->adv_chnl_map,
-                                             p_inq_cb->afp);
-        }
     }
     else
     {
@@ -107,11 +91,14 @@
     tSMP_ENC    output;
 
     BTM_TRACE_EVENT0 ("btm_gen_resolve_paddr_low");
-    if (p && p->param_buf)
+    if (p)
     {
-        p_cb->private_addr[5] = p->param_buf[0];
-        p_cb->private_addr[4] = p->param_buf[1];
-        p_cb->private_addr[3] = p->param_buf[2];
+        p->param_buf[2] &= (~BLE_RESOLVE_ADDR_MASK);
+        p->param_buf[2] |= BLE_RESOLVE_ADDR_MSB;
+
+        p_cb->private_addr[2] = p->param_buf[0];
+        p_cb->private_addr[1] = p->param_buf[1];
+        p_cb->private_addr[0] = p->param_buf[2];
 
         /* encrypt with ur IRK */
         if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, p->param_buf, 3, &output))
@@ -154,22 +141,31 @@
 static void btm_gen_non_resolve_paddr_cmpl(tBTM_RAND_ENC *p)
 {
     tBTM_LE_RANDOM_CB *p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+    tBTM_BLE_ADDR_CBACK *p_cback = p_cb->p_generate_cback;
+    void    *p_data = p_cb->p;
     UINT8   *pp;
-    BTM_TRACE_EVENT0 ("btm_gen_non_resolve_paddr_cmpl");
-    if (p && p->param_buf)
-    {
-        pp = p->param_buf;
-        STREAM_TO_BDADDR(p_cb->private_addr, pp);
-        /* mask off the 2 MSB */
-        p_cb->private_addr[0] &= 0xfc;
-        /* write to controller */
-        btsnd_hcic_ble_set_random_addr(p_cb->private_addr);
+    BD_ADDR     static_random;
 
-        btm_cb.ble_ctr_cb.inq_var.own_addr_type = BLE_ADDR_RANDOM;
+    BTM_TRACE_EVENT0 ("btm_gen_non_resolve_paddr_cmpl");
+
+    p_cb->p_generate_cback = NULL;
+    if (p)
+    {
+
+        pp = p->param_buf;
+        STREAM_TO_BDADDR(static_random, pp);
+        /* mask off the 2 MSB */
+        static_random[0] &= BLE_STATIC_PRIVATE_MSB_MASK;
+
+        /* report complete */
+        if (p_cback)
+            (* p_cback)(static_random, p_data);
     }
     else
     {
         BTM_TRACE_DEBUG0("btm_gen_non_resolvable_private_addr failed");
+        if (p_cback)
+            (* p_cback)(NULL, p_data);
     }
 }
 /*******************************************************************************
@@ -182,13 +178,22 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_gen_non_resolvable_private_addr (void)
+void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
 {
+    tBTM_LE_RANDOM_CB   *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+
     BTM_TRACE_EVENT0 ("btm_gen_non_resolvable_private_addr");
+
+    if (p_mgnt_cb->p_generate_cback != NULL)
+        return;
+
+    p_mgnt_cb->p_generate_cback = p_cback;
+    p_mgnt_cb->p                = p;
     if (!btsnd_hcic_ble_rand((void *)btm_gen_non_resolve_paddr_cmpl))
     {
         btm_gen_non_resolve_paddr_cmpl(NULL);
     }
+
 }
     #if SMP_INCLUDED == TRUE
 /*******************************************************************************
@@ -209,9 +214,12 @@
     tBTM_LE_RANDOM_CB   *p_mgnt_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
     tBTM_SEC_DEV_REC    *p_dev_rec = NULL;
 
-    BTM_TRACE_EVENT0 ("btm_ble_resolve_address_cmpl");
+    BTM_TRACE_EVENT1 ("btm_ble_resolve_address_cmpl p_mgnt_cb->index = %d", p_mgnt_cb->index);
+
     if (p_mgnt_cb->index < BTM_SEC_MAX_DEVICE_RECORDS)
+    {
         p_dev_rec = &btm_cb.sec_dev_rec[p_mgnt_cb->index];
+    }
 
     p_mgnt_cb->busy = FALSE;
 
@@ -237,7 +245,7 @@
     comp[1] = p_mgnt_cb->random_bda[4];
     comp[2] = p_mgnt_cb->random_bda[3];
 
-    if (p && p->param_buf)
+    if (p)
     {
         if (!memcmp(p->param_buf, &comp[0], 3))
         {
@@ -329,11 +337,12 @@
         /* check for next security record */
         while (TRUE)
         {
-            if (btm_ble_match_random_bda(p_mgnt_cb->index++))
+            if (btm_ble_match_random_bda(p_mgnt_cb->index))
             {
-                // match found or went through the list
+                /* atch found or went through the list */
                 break;
             }
+	        p_mgnt_cb->index ++;
         }
     }
     else
@@ -366,18 +375,7 @@
     else
         return BLE_ADDR_PUBLIC;
 }
-/*******************************************************************************
-**
-** Function         btm_ble_map_bda_to_pseudo_bda
-**
-** Description      This function map a BD address to a pseudo address when the
-**                  address given is a random address.
-**
-*******************************************************************************/
-void btm_ble_map_bda_to_pseudo_bda(BD_ADDR bd_addr)
-{
-    BTM_TRACE_EVENT0 ("btm_ble_map_bda_to_pseudo_bda");
-}
+
 #endif
 
 
diff --git a/stack/btm/btm_ble_bgconn.c b/stack/btm/btm_ble_bgconn.c
index aa002e8..3b8b1e2 100644
--- a/stack/btm/btm_ble_bgconn.c
+++ b/stack/btm/btm_ble_bgconn.c
@@ -30,11 +30,16 @@
 #include "l2c_int.h"
 #include "hcimsgs.h"
 
+
 #ifndef BTM_BLE_SCAN_PARAM_TOUT
 #define BTM_BLE_SCAN_PARAM_TOUT      50    /* 50 seconds */
 #endif
 
 #if (BLE_INCLUDED == TRUE)
+
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
+
 /*******************************************************************************
 **
 ** Function         btm_update_scanner_filter_policy
@@ -45,9 +50,11 @@
 {
     tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var;
     BTM_TRACE_EVENT0 ("btm_update_scanner_filter_policy");
-    btm_cb.ble_ctr_cb.inq_var.sfp = scan_policy;
 
-    btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+    p_inq->sfp = scan_policy;
+    p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
+
+    btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
                                     (UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
                                     (UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
                                      BLE_ADDR_PUBLIC,
@@ -55,88 +62,68 @@
 }
 /*******************************************************************************
 **
-** Function         btm_update_adv_filter_policy
-**
-** Description      This function update the filter policy of scnner or advertiser.
-*******************************************************************************/
-void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy)
-{
-    tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
-    BTM_TRACE_EVENT0 ("btm_update_adv_filter_policy");
-    p_cb->afp = adv_policy;
-}
-/*******************************************************************************
-**
 ** Function         btm_update_dev_to_white_list
 **
 ** Description      This function adds a device into white list.
 *******************************************************************************/
-BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, tBLE_ADDR_TYPE addr_type)
+BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 attr)
 {
     /* look up the sec device record, and find the address */
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    tBTM_SEC_DEV_REC    *p_dev_rec;
+    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (bd_addr);
     BD_ADDR             dummy_bda = {0};
-    BOOLEAN             started = FALSE, suspend = FALSE;
+    BOOLEAN             started = FALSE;
+    UINT8       wl_state = p_cb->wl_state;
+    tBT_DEVICE_TYPE dev_type;
+    tBLE_ADDR_TYPE  addr_type = BLE_ADDR_PUBLIC;
 
-    if (btm_cb.btm_inq_vars.inq_active)
+    if ((to_add && p_cb->num_empty_filter == 0) ||
+        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
     {
-        suspend = TRUE;
-        btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE);
+        BTM_TRACE_ERROR1("WL full or empty, unable to update to WL. num_entry available: %d", p_cb->num_empty_filter);
+        return started;
     }
 
-    if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL &&
+    btm_suspend_wl_activity(wl_state);
+
+    if (p_dev_rec != NULL &&
         p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
     {
-        BTM_TRACE_DEBUG0("btm_update_dev_to_white_list 1");
 
-        if ((to_add && p_cb->num_empty_filter == 0) ||
-            (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+        if (to_add)
         {
-            BTM_TRACE_ERROR1("num_entry available in controller: %d", p_cb->num_empty_filter);
-            return started;
-        }
-
-
-        if ( p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC)
-        {
-            if (to_add)
-                started = btsnd_hcic_ble_add_white_list (BLE_ADDR_PUBLIC, bd_addr);
-            else
-                started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_PUBLIC, bd_addr);
+            if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
+            {
+                started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+            }
+            if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
+                memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
+            {
+                 started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
+            }
         }
         else
         {
-            if (BLE_ADDR_IS_STATIC(bd_addr))
+            if (!BTM_BLE_IS_RESOLVE_BDA(bd_addr))
             {
-                if (to_add)
-                    started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, bd_addr);
-                else
-                    started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, bd_addr);
-
+                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
             }
-            if (memcmp(p_dev_rec->ble.reconn_addr, dummy_bda, BD_ADDR_LEN) != 0)
+            if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) != 0)
             {
-                if (to_add)
-                    started = btsnd_hcic_ble_add_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
-                else
-                    started = btsnd_hcic_ble_remove_from_white_list (BLE_ADDR_RANDOM, p_dev_rec->ble.reconn_addr);
+                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
             }
         }
-    }
-    /* if not a known device, shall we add it? */
+    }    /* if not a known device, shall we add it? */
     else
     {
+        BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
         if (to_add)
             started = btsnd_hcic_ble_add_white_list (addr_type, bd_addr);
         else
             started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
     }
 
-    if (suspend)
-    {
-        btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE);
-    }
+    btm_resume_wl_activity(wl_state);
 
     return started;
 }
@@ -175,12 +162,12 @@
 **
 ** Description      This function read the current white list size.
 *******************************************************************************/
-void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len)
+void btm_ble_add_2_white_list_complete(UINT8 status)
 {
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
     BTM_TRACE_EVENT0 ("btm_ble_add_2_white_list_complete");
 
-    if (*p == HCI_SUCCESS)
+    if (status == HCI_SUCCESS)
     {
         p_cb->num_empty_filter --;
     }
@@ -202,54 +189,25 @@
 }
 /*******************************************************************************
 **
-** Function         btm_ble_find_dev_in_whitelist
-**
-** Description      This function check if the device is in the white list
-*******************************************************************************/
-BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr)
-{
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    UINT8 i;
-
-    BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
-
-    /* empty wl */
-    if (p_cb->num_empty_filter == p_cb->max_filter_entries)
-    {
-        BTM_TRACE_DEBUG0("white list empty");
-        return FALSE;
-    }
-
-    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
-    {
-        if (memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
-            return TRUE;
-    }
-    return FALSE;
-}
-/*******************************************************************************
-**
 ** Function         btm_ble_count_unconn_dev_in_whitelist
 **
-** Description      This function check the number of unconnected device in white list.
+** Description      This function find the number of un-connected background device
 *******************************************************************************/
 UINT8 btm_ble_count_unconn_dev_in_whitelist(void)
 {
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    UINT8 count = 0, i;
-    BD_ADDR dummy_bda ={0};
+    UINT8 i, count = 0;
 
-    BTM_TRACE_EVENT0 ("btm_ble_find_dev_in_whitelist");
-
-    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++)
     {
-        if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) != 0 &&
-            !BTM_IsAclConnectionUp(p_cb->bg_conn_dev_list[i]))
+        if (p_cb->bg_dev_list[i].in_use &&
+            !BTM_IsAclConnectionUp(p_cb->bg_dev_list[i].bd_addr))
         {
             count ++;
         }
     }
     return count;
+
 }
 /*******************************************************************************
 **
@@ -257,59 +215,63 @@
 **
 ** Description      This function update the local background connection device list.
 *******************************************************************************/
-BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr)
+BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag)
 {
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    UINT8 i;
-    BD_ADDR dummy_bda = {0};
+    UINT8                   white_list_type = *p_attr_tag;
+    tBTM_BLE_CB             *p_cb = &btm_cb.ble_ctr_cb;
+    tBTM_LE_BG_CONN_DEV     *p_bg_dev = &p_cb->bg_dev_list[0], *p_next, *p_cur;
+    UINT8                   i, j;
+    BOOLEAN             ret = FALSE;
+
     BTM_TRACE_EVENT0 ("btm_update_bg_conn_list");
-    if ((to_add && (p_cb->bg_conn_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)) ||
-        (!to_add && p_cb->num_empty_filter == p_cb->max_filter_entries))
+
+    if ((to_add && (p_cb->bg_dev_num == BTM_BLE_MAX_BG_CONN_DEV_NUM || p_cb->num_empty_filter == 0)))
     {
         BTM_TRACE_DEBUG1("num_empty_filter = %d", p_cb->num_empty_filter);
-        return FALSE;
+        return ret;
     }
 
-    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM && i < p_cb->max_filter_entries; i ++)
+    for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
     {
-        /* to add */
-        if (memcmp(p_cb->bg_conn_dev_list[i], dummy_bda, BD_ADDR_LEN) == 0 && to_add)
+        if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
         {
-            memcpy(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN);
-            p_cb->bg_conn_dev_num ++;
-            return TRUE;
-        }
-        /* to remove */
-        if (!to_add && memcmp(p_cb->bg_conn_dev_list[i], bd_addr, BD_ADDR_LEN) == 0)
-        {
-            memset(p_cb->bg_conn_dev_list[i], 0, BD_ADDR_LEN);
-            p_cb->bg_conn_dev_num --;
-            return TRUE;
-        }
-    }
-    return FALSE;
-}
-/*******************************************************************************
-**
-** Function         btm_write_bg_conn_wl
-**
-** Description      This function write background connection device list into
-**                  controller.
-*******************************************************************************/
-void btm_write_bg_conn_wl(void)
-{
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    UINT8       i;
-    BTM_TRACE_EVENT0 ("btm_write_bg_conn_wl");
-    btm_ble_clear_white_list();
+            if (to_add)
+                p_bg_dev->attr |= white_list_type;
+            else
+                p_bg_dev->attr &=  ~white_list_type;
 
-    for (i = 0; i < p_cb->bg_conn_dev_num; i ++)
-    {
-        if (!btm_update_dev_to_white_list(TRUE, p_cb->bg_conn_dev_list[i], BLE_ADDR_PUBLIC))
+            if (p_bg_dev->attr == 0)
+            {
+                memset(p_bg_dev, 0, sizeof(tBTM_LE_BG_CONN_DEV));
+                p_cb->bg_dev_num --;
+                p_cur = p_bg_dev;
+                p_next = p_bg_dev + 1;
+                for (j = i + 1 ;j < BTM_BLE_MAX_BG_CONN_DEV_NUM && p_next->in_use ; j ++, p_cur ++, p_next ++ )
+                    memcpy(p_cur, p_next, sizeof(tBTM_LE_BG_CONN_DEV));
+            }
+            ret = TRUE;
             break;
+        }
+        else if (!p_bg_dev->in_use && to_add)
+        {
+            BTM_TRACE_DEBUG0("add new WL entry in bg_dev_list");
+
+            memcpy(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN);
+            p_bg_dev->in_use = TRUE;
+            p_bg_dev->attr |= white_list_type;
+            p_cb->bg_dev_num ++;
+
+            ret = TRUE;
+            break;
+        }
     }
-    return;
+
+    if (i != BTM_BLE_MAX_BG_CONN_DEV_NUM)
+        *p_attr_tag = p_bg_dev->attr;
+
+    return ret;
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_start_auto_conn
@@ -326,51 +288,58 @@
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
     BD_ADDR dummy_bda = {0};
     BOOLEAN exec = TRUE;
+    UINT8  own_addr_type = BLE_ADDR_PUBLIC;
     UINT16 scan_int, scan_win;
 
-    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
-    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
-
     if (start)
     {
-        if (!l2cb.is_ble_connecting &&
-            btm_ble_count_unconn_dev_in_whitelist() > 0)
+        if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
         {
-            if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE && p_cb->bg_conn_dev_num > 0)
+
+            scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_INT_1 : p_cb->scan_int;
+            scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_SLOW_WIN_1 : p_cb->scan_win;
+
+            if (!btsnd_hcic_ble_create_ll_conn (scan_int,  /* UINT16 scan_int      */
+                                                scan_win,    /* UINT16 scan_win      */
+                                                0x01,                   /* UINT8 white_list     */
+                                                BLE_ADDR_PUBLIC,        /* UINT8 addr_type_peer */
+                                                dummy_bda,              /* BD_ADDR bda_peer     */
+                                                own_addr_type,         /* UINT8 addr_type_own, not allow random address for central  */
+                                                BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
+                                                BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
+                                                BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
+                                                BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
+                                                0,                       /* UINT16 min_len       */
+                                                0))                      /* UINT16 max_len       */
             {
-                if (!btsnd_hcic_ble_create_ll_conn (scan_int,  /* UINT16 scan_int      */
-                                                    scan_win,    /* UINT16 scan_win      */
-                                                    0x01,                   /* UINT8 white_list     */
-                                                    BLE_ADDR_PUBLIC,        /* UINT8 addr_type_peer */
-                                                    dummy_bda,              /* BD_ADDR bda_peer     */
-                                                    BLE_ADDR_PUBLIC,         /* UINT8 addr_type_own  */
-                                                    BTM_BLE_CONN_INT_MIN_DEF,   /* UINT16 conn_int_min  */
-                                                    BTM_BLE_CONN_INT_MAX_DEF,   /* UINT16 conn_int_max  */
-                                                    BTM_BLE_CONN_SLAVE_LATENCY_DEF,  /* UINT16 conn_latency  */
-                                                    BTM_BLE_CONN_TIMEOUT_DEF,        /* UINT16 conn_timeout  */
-                                                    0,                       /* UINT16 min_len       */
-                                                    0))                      /* UINT16 max_len       */
-                {
-                    /* start auto connection failed */
-                    exec =  FALSE;
-                }
-                else
-                {
-                    p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-                }
+                /* start auto connection failed */
+                exec =  FALSE;
+            }
+            else
+            {
+                p_cb->conn_state = BLE_BG_CONN;
+
             }
         }
         else
+        {
             exec = FALSE;
+        }
     }
     else
     {
-        if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
+        if (p_cb->conn_state == BLE_BG_CONN)
         {
-            if (!btsnd_hcic_ble_create_conn_cancel())
-                exec = FALSE;
-            else
-                p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
+            btsnd_hcic_ble_create_conn_cancel();
+            p_cb->conn_state = BLE_CONN_IDLE;
+
+        }
+        else
+        {
+#if 0
+            BTM_TRACE_ERROR1("conn_st = %d, not in auto conn state, can not stop.", p_cb->conn_state);
+            exec = FALSE;
+#endif
         }
     }
     return exec;
@@ -396,16 +365,18 @@
 
     BTM_TRACE_EVENT0 ("btm_ble_start_select_conn");
 
-    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_INT : p_cb->scan_int;
-    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_CONN_EST_SCAN_WIND : p_cb->scan_win;
+    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
 
     if (start)
     {
-        if (!btm_cb.btm_inq_vars.inq_active)
+        if (btm_cb.btm_inq_vars.inq_active == BTM_INQUIRY_INACTIVE)
         {
-            btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
+            if (p_select_cback != NULL)
+                btm_cb.ble_ctr_cb.p_select_cback = p_select_cback;
 
             btm_update_scanner_filter_policy(SP_ADV_WL);
+            btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_PASS;
 
             if (!btsnd_hcic_ble_set_scan_params(BTM_BLE_SCAN_MODE_PASS,  /* use passive scan by default */
                                                 scan_int, /* scan interval */
@@ -415,23 +386,22 @@
                 )
                 return FALSE;
 
-            if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE)
+            if (p_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE
+                )
             {
                 BTM_TRACE_ERROR0("peripheral device cannot initiate a selective connection");
                 return FALSE;
             }
-            else if (p_cb->bg_conn_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
+            else if (p_cb->bg_dev_num > 0 && btm_ble_count_unconn_dev_in_whitelist() > 0 )
             {
 
                 if (!btsnd_hcic_ble_set_scan_enable(TRUE, TRUE)) /* duplicate filtering enabled */
                     return FALSE;
 
                 /* mark up inquiry status flag */
-                btm_cb.btm_inq_vars.inq_active = TRUE;
-                btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
-
-                p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+                btm_cb.btm_inq_vars.inq_active |= BTM_LE_SELECT_CONN_ACTIVE;
+                p_cb->inq_var.proc_mode = BTM_BLE_SELECT_SCAN;
+                p_cb->conn_state                = BLE_BG_CONN;
             }
         }
         else
@@ -442,14 +412,12 @@
     }
     else /* disable selective connection mode */
     {
-        p_cb->p_select_cback = NULL;
-        btm_cb.btm_inq_vars.inq_active = FALSE;
+        btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_SELECT_CONN_ACTIVE;
         btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
 
         btm_update_scanner_filter_policy(SP_ADV_ALL);
-
         /* stop scanning */
-        if (p_cb->bg_conn_dev_num > 0)
+        if (p_cb->bg_dev_num > 0)
         {
             if (!btsnd_hcic_ble_set_scan_enable(FALSE, TRUE)) /* duplicate filtering enabled */
                 return FALSE;
@@ -472,9 +440,7 @@
 *******************************************************************************/
 void btm_ble_initiate_select_conn(BD_ADDR bda)
 {
-    UINT8   addr_type;
     BTM_TRACE_EVENT0 ("btm_ble_initiate_select_conn");
-    addr_type = btm_ble_map_bda_to_conn_bda(bda);
 
     /* use direct connection procedure to initiate connection */
     if (!L2CA_ConnectFixedChnl(L2CAP_ATT_CID, bda))
@@ -484,29 +450,6 @@
 }
 /*******************************************************************************
 **
-** Function         btm_ble_suspend_bg_sele_conn
-**
-** Description      This function is to suspend an active background connection
-**                  procedure.
-**
-** Parameters       none.
-**
-** Returns          none.
-**
-*******************************************************************************/
-void btm_ble_suspend_bg_sele_conn(void)
-{
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    BTM_TRACE_EVENT0 ("btm_ble_suspend_bg_sele_conn");
-
-    if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
-    {
-        p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
-        btm_ble_start_select_conn(FALSE, NULL);
-    }
-}
-/*******************************************************************************
-**
 ** Function         btm_ble_suspend_bg_conn
 **
 ** Description      This function is to suspend an active background connection
@@ -524,20 +467,56 @@
 
     if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
     {
-        if (btm_ble_start_auto_conn(FALSE))
-            p_cb->bg_conn_state = BLE_BG_CONN_SUSPEND;
+        btm_ble_start_auto_conn(FALSE);
+    }
+    else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
+    {
+        btm_ble_start_select_conn(FALSE, NULL);
     }
 }
 /*******************************************************************************
 **
-** Function         btm_ble_scan_param_idle
+** Function         btm_suspend_wl_activity
 **
-** Description      This function is to process the scan parameter idle timeout
-**                  timeout.
-********************************************************************************/
-void btm_ble_scan_param_idle(void)
+** Description      This function is to suspend white list related activity
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state)
 {
-    BTM_BleSetConnScanParams(BTM_BLE_CONN_EST_SCAN_INT_LO, BTM_BLE_CONN_EST_SCAN_WIND_LO);
+    if (wl_state & BTM_BLE_WL_INIT)
+    {
+        btm_ble_start_auto_conn(FALSE);
+    }
+    if (wl_state & BTM_BLE_WL_SCAN)
+    {
+        btm_ble_start_select_conn(FALSE, NULL);
+    }
+    if (wl_state & BTM_BLE_WL_ADV)
+    {
+        btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_DISABLE);
+    }
+
+}
+/*******************************************************************************
+**
+** Function         btm_resume_wl_activity
+**
+** Description      This function is to resume white list related activity
+**
+** Returns          none.
+**
+*******************************************************************************/
+static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state)
+{
+    btm_ble_resume_bg_conn();
+
+    if (wl_state & BTM_BLE_WL_ADV)
+    {
+        btsnd_hcic_ble_set_adv_enable(BTM_BLE_ADV_ENABLE);
+    }
+
 }
 /*******************************************************************************
 **
@@ -551,66 +530,91 @@
 ** Returns          none.
 **
 *******************************************************************************/
-BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param)
+BOOLEAN btm_ble_resume_bg_conn(void)
 {
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
     BOOLEAN ret = FALSE;
 
-    if (p_cb->bg_conn_state != BLE_BG_CONN_ACTIVE )
+    if (p_cb->bg_conn_type != BTM_BLE_CONN_NONE)
     {
-        if (def_param)
-        {
-            p_cb->scan_int = BTM_BLE_CONN_PARAM_UNDEF;
-            p_cb->scan_win = BTM_BLE_CONN_PARAM_UNDEF;
-
-            /* start scan param idle timer */
-            btu_start_timer(&p_cb->scan_param_idle_timer,
-                            BTU_TTYPE_BLE_SCAN_PARAM_IDLE,
-                            BTM_BLE_SCAN_PARAM_TOUT);
-        }
-
         if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
             ret = btm_ble_start_auto_conn(TRUE);
 
         if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
-        {
-            /* terminate selective connection mode if all devices are connected */
-            if (btm_ble_count_unconn_dev_in_whitelist() == 0)
-            {
-                btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_DISABLE);
-                btm_cb.ble_ctr_cb.inq_var.proc_mode = BTM_BLE_INQUIRY_NONE;
-                btm_cb.btm_inq_vars.inq_active = FALSE;
-            }
-            else if (!btm_cb.btm_inq_vars.inq_active)
-                btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
-        }
-
-        if (ret)
-            p_cb->bg_conn_state = BLE_BG_CONN_ACTIVE;
-
+            ret = btm_ble_start_select_conn(TRUE, btm_cb.ble_ctr_cb.p_select_cback);
     }
 
     return ret;
 }
 /*******************************************************************************
 **
-** Function         btm_ble_update_bg_state
+** Function         btm_ble_get_conn_st
 **
-** Description      This function is to update the bg connection status.
+** Description      This function get BLE connection state
 **
-** Parameters       none.
-**
-** Returns          none.
+** Returns          connection state
 **
 *******************************************************************************/
-void btm_ble_update_bg_state(void)
+tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
 {
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
-    if (!l2cb.is_ble_connecting && (p_cb->bg_conn_state != BLE_BG_CONN_SUSPEND))
-        p_cb->bg_conn_state = BLE_BG_CONN_IDLE;
-
+    return btm_cb.ble_ctr_cb.conn_state;
+}
+/*******************************************************************************
+**
+** Function         btm_ble_set_conn_st
+**
+** Description      This function set BLE connection state
+**
+** Returns          None.
+**
+*******************************************************************************/
+void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
+{
+    btm_cb.ble_ctr_cb.conn_state = new_st;
 }
 
+/*******************************************************************************
+**
+** Function         btm_ble_enqueue_direct_conn_req
+**
+** Description      This function enqueue the direct connection request
+**
+** Returns          None.
+**
+*******************************************************************************/
+void btm_ble_enqueue_direct_conn_req(void *p_param)
+{
+    tBTM_BLE_CONN_REQ   *p = (tBTM_BLE_CONN_REQ *)GKI_getbuf(sizeof(tBTM_BLE_CONN_REQ));
+
+    p->p_param = p_param;
+
+    GKI_enqueue (&btm_cb.ble_ctr_cb.conn_pending_q, p);
+}
+/*******************************************************************************
+**
+** Function         btm_send_pending_direct_conn
+**
+** Description      This function send the pending direct connection request in queue
+**
+** Returns          TRUE if started, FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN btm_send_pending_direct_conn(void )
+{
+    tBTM_BLE_CONN_REQ *p_req;
+    BOOLEAN     rt = FALSE;
+
+    if ( btm_cb.ble_ctr_cb.conn_pending_q.count )
+    {
+        p_req = (tBTM_BLE_CONN_REQ*)GKI_dequeue (&btm_cb.ble_ctr_cb.conn_pending_q);
+
+        rt = l2cble_init_direct_conn((tL2C_LCB *)(p_req->p_param));
+
+        GKI_freebuf((void *)p_req);
+    }
+
+    return rt;
+}
 #endif
 
+
diff --git a/stack/btm/btm_ble_gap.c b/stack/btm/btm_ble_gap.c
index b9e17c0..d13e36b 100644
--- a/stack/btm/btm_ble_gap.c
+++ b/stack/btm/btm_ble_gap.c
@@ -33,23 +33,16 @@
 #if (GAP_INCLUDED == TRUE)
 #include "gap_api.h"
 #endif
-
 #if (BLE_INCLUDED == TRUE)
+#include "gattdefs.h"
+
 #define BTM_BLE_NAME_SHORT                  0x01
 #define BTM_BLE_NAME_CMPL                   0x02
 
 #define BTM_BLE_FILTER_TARGET_UNKNOWN       0xff
 #define BTM_BLE_POLICY_UNKNOWN              0xff
 
-#define BLE_RESOLVE_ADDR_MSB                 0x40   /*  most significant bit, bit7, bit6 is 01 to be resolvable random */
-#define BLE_RESOLVE_ADDR_MASK                0xc0   /* bit 6, and bit7 */
-#define BTM_BLE_IS_RESOLVE_BDA(x)           ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
-
 #define BTM_EXT_BLE_RMT_NAME_TIMEOUT        30
-static tBLE_BD_ADDR le_bda_any ={BLE_ADDR_PUBLIC, {0x00,0x00,0x00,0x00,0x00,0x00}};
-
-
-#define BTM_BLE_VALID_CONN_DIRECT(x) (memcmp(&le_bda_any, x, sizeof(tBLE_BD_ADDR)) != 0)
 
 /*******************************************************************************
 **  Local functions
@@ -57,11 +50,12 @@
 static void btm_ble_update_adv_flag(UINT8 flag);
 static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt_type, UINT8 *p);
 static UINT8 *btm_ble_build_adv_data(tBTM_BLE_AD_MASK *p_data_mask, UINT8 **p_dst, tBTM_BLE_ADV_DATA *p_data);
-
-
-
-
-
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+                                     BD_ADDR_PTR p_addr_ptr,
+                                     tBLE_ADDR_TYPE *p_init_addr_type,
+                                     tBLE_ADDR_TYPE *p_own_addr_type);
+static BOOLEAN btm_ble_start_adv(void);
+static tBTM_STATUS btm_ble_stop_adv(void);
 
 
 
@@ -80,9 +74,65 @@
 {
     btsnd_hcic_ble_reset();
 }
+/*******************************************************************************
+**
+** Function         BTM_BleUpdateAdvWhitelist
+**
+** Description      Add or remove device from advertising white list
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR remote_bda)
+{
+        return FALSE;
+}
 
 /*******************************************************************************
 **
+** Function         BTM_BleUpdateAdvFilterPolicy
+**
+** Description      This function update the filter policy of advertiser.
+**
+** Parameter        adv_policy: advertising filter policy
+**
+** Return           void
+*******************************************************************************/
+void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy)
+{
+    tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+    tBLE_ADDR_TYPE   init_addr_type = BLE_ADDR_PUBLIC;
+    BD_ADDR          p_addr_ptr= {0};
+    UINT8            adv_mode = p_cb->adv_mode;
+
+    BTM_TRACE_EVENT0 ("BTM_BleUpdateAdvFilterPolicy");
+
+    if (p_cb->afp != adv_policy)
+    {
+        p_cb->afp = adv_policy;
+
+        /* if adv active, stop and restart */
+        btm_ble_stop_adv ();
+
+        if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+            p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &p_cb->adv_addr_type);
+
+        btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+                                         p_cb->adv_interval_max,
+                                         p_cb->evt_type,
+                                         p_cb->adv_addr_type,
+                                         init_addr_type,
+                                         p_addr_ptr,
+                                         p_cb->adv_chnl_map,
+                                         p_cb->afp);
+
+        if (adv_mode == BTM_BLE_ADV_ENABLE)
+            btm_ble_start_adv ();
+
+    }
+}
+/*******************************************************************************
+**
 ** Function         BTM_BleObserve
 **
 ** Description      This procedure keep the device listening for advertising
@@ -104,14 +154,16 @@
 
     if (start)
     {
-        if (p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
+        /* shared inquiry database, do not allow observe if any inquiry is active */
+        if (btm_cb.btm_inq_vars.inq_active || p_inq->proc_mode != BTM_BLE_INQUIRY_NONE)
             return BTM_BUSY;
 
         btm_cb.btm_inq_vars.p_inq_results_cb = p_results_cb;
         btm_cb.btm_inq_vars.p_inq_cmpl_cb = p_cmpl_cb;
+        p_inq->scan_type = (p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type;
 
         /* allow config scanning type */
-        if (btsnd_hcic_ble_set_scan_params ((UINT8)((p_inq->scan_type == BTM_BLE_SCAN_MODE_NONE) ? BTM_BLE_SCAN_MODE_ACTI: p_inq->scan_type),
+        if (btsnd_hcic_ble_set_scan_params (p_inq->scan_type,
                                             (UINT16)(!p_inq->scan_interval ? BTM_BLE_GAP_DISC_SCAN_INT : p_inq->scan_interval),
                                             (UINT16)(!p_inq->scan_window ? BTM_BLE_GAP_DISC_SCAN_WIN : p_inq->scan_window),
                                             BLE_ADDR_PUBLIC,
@@ -122,7 +174,7 @@
             {
                 status = BTM_SUCCESS;
                 p_inq->proc_mode = BTM_BLE_OBSERVE;
-                btm_cb.btm_inq_vars.inq_active = TRUE;
+                btm_cb.btm_inq_vars.inq_active |= BTM_LE_OBSERVE_ACTIVE;
 
                 if (duration != 0)
                 {
@@ -134,6 +186,7 @@
     }
     else if (p_inq->proc_mode == BTM_BLE_OBSERVE)
     {
+        btm_cb.btm_inq_vars.inq_active &= ~BTM_LE_OBSERVE_ACTIVE;
         btm_ble_stop_scan();
     }
 
@@ -154,6 +207,7 @@
 tBTM_STATUS BTM_BleBroadcast(BOOLEAN start)
 {
     tBTM_STATUS status = BTM_NO_RESOURCES;
+    tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT8 evt_type = p_cb->scan_rsp ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
 
@@ -170,8 +224,9 @@
         if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
                                               (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
                                               evt_type,
-                                              p_cb->own_addr_type,
-                                              p_cb->direct_bda.type, p_cb->direct_bda.bda,
+                                              p_addr_cb->own_addr_type,
+                                              p_cb->direct_bda.type,
+                                              p_cb->direct_bda.bda,
                                               p_cb->adv_chnl_map,
                                               p_cb->afp))
 
@@ -179,21 +234,11 @@
         else
             p_cb->evt_type = evt_type;
 
-        if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
-        {
-            p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
-
-            status = BTM_SUCCESS;
-        }
+        status = btm_ble_start_adv ();
     }
     else if (!start && p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
     {
-        if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
-        {
-            p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
-            status = BTM_SUCCESS;
-        }
+        status = btm_ble_stop_adv();
     }
     else
     {
@@ -201,16 +246,9 @@
         BTM_TRACE_ERROR2("Can not %s Broadcast, device %s in Broadcast mode",
             (start ? "Start" : "Stop"), (start ? "alerady" :"not"));
     }
-
     return status;
 }
 
-
-
-
-
-
-
 /*******************************************************************************
 **
 ** Function         BTM_RegisterScanReqEvt
@@ -226,32 +264,14 @@
 *******************************************************************************/
 void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK   *p_scan_req_cback)
 {
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
-    if (BTM_BLE_PC_ADV_TEST_MODE)   // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+    if (BTM_BLE_PC_ADV_TEST_MODE)   /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
     {
         tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
         p_cb->p_scan_req_cback = p_scan_req_cback;
     }
 #endif
 }
-/*******************************************************************************
-**
-** Function         BTM_BleConfigPrivacy
-**
-** Description      This function is called to enable or disable the privacy in
-**                  the local device.
-**
-** Parameters       enable: TRUE to enable it; FALSE to disable it.
-**
-** Returns          void
-**
-*******************************************************************************/
-void BTM_BleConfigPrivacy(BOOLEAN enable)
-{
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    BTM_TRACE_EVENT0 (" BTM_BleConfigPrivacy");
-    p_cb->privacy = enable;
-}
 
 /*******************************************************************************
 **
@@ -331,46 +351,8 @@
 *******************************************************************************/
 BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR   remote_bda)
 {
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-    tBTM_BLE_SEL_CBACK   *p_select_cback;
     BOOLEAN ret = TRUE;
 
-    BTM_TRACE_EVENT0 (" BTM_BleUpdateBgConnDev");
-
-    /* if auto connection is active */
-    if (p_cb->bg_conn_state == BLE_BG_CONN_ACTIVE)
-    {
-        if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
-        {
-            /* terminate auto connection first */
-            ret = btm_ble_start_auto_conn(FALSE);
-        }
-        else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
-        {
-            p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
-            ret = btm_ble_start_select_conn(FALSE, NULL);
-        }
-    }
-    if (ret)
-    {
-        /* update white list */
-        ret = btm_update_bg_conn_list(add_remove, remote_bda);
-        btm_update_dev_to_white_list(add_remove, remote_bda, BLE_ADDR_PUBLIC);
-    }
-
-    if (ret && p_cb->bg_conn_state == BLE_BG_CONN_IDLE)
-    {
-        if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO)
-        {
-            /* restart auto connection */
-            btm_ble_start_auto_conn(TRUE);
-        }
-        else if (p_cb->bg_conn_type == BTM_BLE_CONN_SELECTIVE)
-        {
-            p_select_cback = btm_cb.ble_ctr_cb.p_select_cback;
-            btm_ble_start_select_conn(TRUE, p_select_cback);
-        }
-    }
     return ret;
 }
 
@@ -387,44 +369,49 @@
 ** Returns          void
 **
 *******************************************************************************/
-tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed, tBLE_BD_ADDR *p_dir_bda)
+tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
 {
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
-    tBTM_STATUS status = BTM_SUCCESS;
-    BD_ADDR     reconn_bda;
 
-    BTM_TRACE_EVENT0 ("BTM_BleSetConnMode ");
+    BTM_TRACE_EVENT1 ("BTM_BleSetConnMode is_directed = %d ", is_directed);
 
-    memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
-    p_cb->own_addr_type = BLE_ADDR_PUBLIC;
+    p_cb->directed_conn = is_directed;
+    return btm_ble_set_connectability( p_cb->connectable_mode);
 
-    if (directed)
+}
+
+/*******************************************************************************
+**
+** Function         btm_set_conn_mode_adv_init_addr
+**
+** Description      set initator address type and local address type based on adv
+**                  mode.
+**
+**
+*******************************************************************************/
+static UINT8 btm_set_conn_mode_adv_init_addr(tBTM_BLE_INQ_CB *p_cb,
+                                     BD_ADDR_PTR p_addr_ptr,
+                                     tBLE_ADDR_TYPE *p_init_addr_type,
+                                     tBLE_ADDR_TYPE *p_own_addr_type)
+{
+    UINT8 evt_type;
+
+    if ( p_cb->directed_conn)
     {
-        if (p_dir_bda)
-        {
-            memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
-
-            if (btm_cb.ble_ctr_cb.privacy /* && GAP privacy ad reconnect addr exist */)
-            {
-                /* write reconnect address to controller*/
-                btsnd_hcic_ble_set_random_addr(reconn_bda);
-            }
-            /* else use static address or publich address */
-
-        }
-        else
-            status = BTM_ILLEGAL_VALUE;
+        /*  direct adv mode does not have privacy if privacy
+            is not enabled or no reconn addr config */
+        *p_own_addr_type   = BLE_ADDR_PUBLIC;
+        *p_init_addr_type  = p_cb->direct_bda.type;
+         memcpy(p_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
+        evt_type = BTM_BLE_CONNECT_DIR_EVT;
     }
-    else /* undirected connecatable */
+    else /* undirect adv mode */
     {
-        if (btm_cb.ble_ctr_cb.privacy /* GAP privacy flag enabled */)
-        {
-            /* generate resolvable private address */
-            btm_gen_resolvable_private_addr();
-        } /* else use publich address */
-
+        evt_type = BTM_BLE_CONNECT_EVT;
     }
-    return status;
+
+    return evt_type;
+
 }
 
 /*******************************************************************************
@@ -445,8 +432,13 @@
                                 tBLE_BD_ADDR *p_dir_bda,
                                 tBTM_BLE_ADV_CHNL_MAP chnl_map)
 {
+    tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     tBTM_STATUS status = BTM_SUCCESS;
+    BD_ADDR     p_addr_ptr =  {0};
+    tBLE_ADDR_TYPE   init_addr_type = BLE_ADDR_PUBLIC;
+    tBLE_ADDR_TYPE   own_addr_type = p_addr_cb->own_addr_type;
+    UINT8            adv_mode = p_cb->adv_mode;
 
     BTM_TRACE_EVENT0 ("BTM_BleSetAdvParams");
 
@@ -464,46 +456,26 @@
     {
         memcpy(&p_cb->direct_bda, p_dir_bda, sizeof(tBLE_BD_ADDR));
     }
-    else
-        memcpy(&p_cb->direct_bda, &le_bda_any, sizeof(tBLE_BD_ADDR));
 
-    if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
-    {
-        BTM_TRACE_EVENT0 ("update params for an active adv");
+    BTM_TRACE_EVENT0 ("update params for an active adv");
 
-        if (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE)
-        {
-            if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
-                p_cb->evt_type = BTM_BLE_CONNECT_DIR_EVT;
-            else
-                p_cb->evt_type = BTM_BLE_CONNECT_EVT;
+    btm_ble_stop_adv();
 
-            BTM_TRACE_DEBUG1(" evt_type = %d", p_cb->evt_type);
-        }
+    if (p_cb->connectable_mode & BTM_BLE_CONNECTABLE)
+        p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
 
-        if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
-            status = BTM_NO_RESOURCES;
-        else
-        /* update adv params */
-        if (!btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
-                                              p_cb->adv_interval_max,
-                                              p_cb->evt_type,
-                                              p_cb->own_addr_type,
-                                              p_cb->direct_bda.type,
-                                              p_cb->direct_bda.bda,
-                                              p_cb->adv_chnl_map,
-                                              p_cb->afp))
+    /* update adv params */
+    btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
+                                     p_cb->adv_interval_max,
+                                     p_cb->evt_type,
+                                     own_addr_type,
+                                     init_addr_type,
+                                     p_addr_ptr,
+                                     p_cb->adv_chnl_map,
+                                     p_cb->afp);
 
-            status = BTM_NO_RESOURCES;
-
-        else if (!btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
-        {
-            p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-
-            status = BTM_NO_RESOURCES;
-        }
-
-    }
+    if (adv_mode == BTM_BLE_ADV_ENABLE)
+        btm_ble_start_adv();
 
     return status;
 }
@@ -539,7 +511,6 @@
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         BTM_BleSetScanParams
@@ -606,7 +577,7 @@
     {
         status = BTM_SUCCESS;
 
-        if (p_data != NULL)
+        if (data_mask != 0)
             btm_cb.ble_ctr_cb.inq_var.scan_rsp = TRUE;
         else
             btm_cb.ble_ctr_cb.inq_var.scan_rsp = FALSE;
@@ -711,7 +682,6 @@
     *p_flag = NULL;
     UINT16  len = BTM_BLE_AD_DATA_LEN, cp_len = 0;
     UINT8   i = 0;
-    tBTM_BLE_ATTR           *p_attr;
     tBTM_BLE_PROP_ELEM      *p_elem;
 
     BTM_TRACE_EVENT0 (" btm_ble_build_adv_data");
@@ -734,7 +704,18 @@
 
             data_mask &= ~BTM_BLE_AD_BIT_FLAGS;
         }
+        /* appearance data */
+        if (len > 3 && data_mask & BTM_BLE_AD_BIT_APPEARANCE)
+        {
+            *p++ = 3; /* length */
+            *p++ = BTM_BLE_AD_TYPE_APPEARANCE;
+            UINT16_TO_STREAM(p, p_data->appearance);
+            len -= 4;
+
+            data_mask &= ~BTM_BLE_AD_BIT_APPEARANCE;
+        }
         /* device name */
+#if BTM_MAX_LOC_BD_NAME_LEN > 0
         if (len > 2 && data_mask & BTM_BLE_AD_BIT_DEV_NAME)
         {
             if (strlen(btm_cb.cfg.bd_name) > (UINT16)(len - 2))
@@ -750,10 +731,10 @@
                 *p++ = BTM_BLE_AD_TYPE_NAME_CMPL;
                 ARRAY_TO_STREAM(p, btm_cb.cfg.bd_name, cp_len);
             }
-
             len -= (cp_len + 2);
             data_mask &= ~BTM_BLE_AD_BIT_DEV_NAME;
         }
+#endif
         /* manufacturer data */
         if (len > 2 && data_mask & BTM_BLE_AD_BIT_MANU &&
             p_data && p_data->manu.len != 0 && p_data->manu.p_val)
@@ -789,13 +770,13 @@
             {
                 cp_len = (len - 2)/2;
                 *p ++ = 1 + cp_len * 2;
-                *p++ = BTM_BLE_AD_TYPE_SRV_PART;
+                *p++ = BTM_BLE_AD_TYPE_16SRV_PART;
             }
             else
             {
                 cp_len = p_data->services.num_service;
                 *p++ = 1 + cp_len * 2;
-                *p++ = BTM_BLE_AD_TYPE_SRV_CMPL;
+                *p++ = BTM_BLE_AD_TYPE_16SRV_CMPL;
             }
             for (i = 0; i < cp_len; i ++)
             {
@@ -815,27 +796,6 @@
             len -= 6;
             data_mask &= ~BTM_BLE_AD_BIT_INT_RANGE;
         }
-        if (data_mask & BTM_BLE_AD_BIT_ATTR && p_data && p_data->attr.num_attr != 0)
-        {
-            for (i = 0; i < p_data->attr.num_attr ; i ++)
-            {
-                p_attr = p_data->attr.attr_list + i;
-
-                if (len >= (2 + 2 + p_attr->data_len))/* len byte(1) + ATTR type(1) + Uuid len(2) + value length */
-                {
-                    *p ++ = p_attr->data_len + 2 + 1; /* Uuid len + value length */
-                    *p ++ = BTM_BLE_AD_TYPE_ATTR;
-                    UINT16_TO_STREAM(p, p_attr->uuid);
-                    ARRAY_TO_STREAM(p, p_attr->p_data, p_attr->data_len);
-
-                    len -= (4 + p_attr->data_len);
-                }
-                else
-                    break;
-            }
-            if (i == p_data->attr.num_attr)
-                data_mask &= ~BTM_BLE_AD_BIT_ATTR;
-        }
         if (data_mask & BTM_BLE_AD_BIT_PROPRIETARY && p_data && p_data->p_proprietary)
         {
             for (i = 0; i < p_data->p_proprietary->num_elem ; i ++)
@@ -879,6 +839,7 @@
 *******************************************************************************/
 tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
 {
+    tBTM_LE_RANDOM_CB   *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
     tBTM_BLE_INQ_CB     *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT16              mode = (combined_mode &  BTM_BLE_DISCOVERABLE_MASK);
     UINT8               flag = 0;
@@ -887,6 +848,9 @@
                                    ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
                                    : BTM_BLE_CONNECT_EVT;
     tBTM_STATUS         status = BTM_SUCCESS;
+    BD_ADDR             p_addr_ptr= {0};
+    tBLE_ADDR_TYPE      init_addr_type = BLE_ADDR_PUBLIC,
+                        own_addr_type = p_addr_cb->own_addr_type;;
 
     BTM_TRACE_EVENT2 ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
 
@@ -925,55 +889,47 @@
             BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode if no scan rsp ");
             if (!p_cb->scan_rsp )
 	            new_mode = BTM_BLE_ADV_DISABLE;
+
         }
         else
         {
-            if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
-            {
-                BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
-                evt_type = BTM_BLE_CONNECT_DIR_EVT;
-            }
-            else
-            {
-                BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
-                evt_type = BTM_BLE_CONNECT_EVT;
-            }
+            p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
         }
     }
     btm_ble_update_adv_flag(flag);
 
     /* update adv params if start advertising */
     BTM_TRACE_EVENT2 ("evt_type=0x%x p-cb->evt_type=0x%x ", evt_type, p_cb->evt_type);
-    if (new_mode == BTM_BLE_ADV_ENABLE && evt_type != p_cb->evt_type)
+    if (new_mode == BTM_BLE_ADV_ENABLE &&
+        (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type))
     {
-        if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
-        {
-            BTM_TRACE_EVENT0 ("Set Adv disable");
-            p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-            btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
-        }
+        btm_ble_stop_adv();
 
         /* update adv params */
         if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
                                               (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
                                               evt_type,
-                                              p_cb->own_addr_type,
-                                              p_cb->direct_bda.type, p_cb->direct_bda.bda,
+                                              own_addr_type,
+                                              init_addr_type,
+                                              p_addr_ptr,
                                               p_cb->adv_chnl_map,
                                               p_cb->afp))
 
             status = BTM_NO_RESOURCES;
         else
+        {
             p_cb->evt_type = evt_type;
+            p_cb->adv_addr_type = own_addr_type;
+        }
 
     }
+
     if (status == BTM_SUCCESS && p_cb->adv_mode != new_mode)
     {
-        /* update advertising mode */
-        if (!btsnd_hcic_ble_set_adv_enable (new_mode))
-            status = BTM_NO_RESOURCES;
+        if (new_mode == BTM_BLE_ADV_ENABLE)
+            status = btm_ble_start_adv();
         else
-            p_cb->adv_mode = new_mode;
+            status = btm_ble_stop_adv();
     }
 
     /* set up stop advertising timer */
@@ -1000,6 +956,7 @@
 *******************************************************************************/
 tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
 {
+    tBTM_LE_RANDOM_CB       *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
     tBTM_BLE_INQ_CB         *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT16                  mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK);
     UINT8                   cur_flag = 0;
@@ -1008,9 +965,11 @@
     UINT8                   new_mode = BTM_BLE_ADV_ENABLE;
     UINT8                   evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
     tBTM_STATUS             status = BTM_SUCCESS;
+    BD_ADDR                 p_addr_ptr =  {0};
+    tBLE_ADDR_TYPE          init_addr_type = BLE_ADDR_PUBLIC,
+                            own_addr_type = p_addr_cb->own_addr_type;
 
     BTM_TRACE_EVENT2 ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
-
     /*** Check mode parameter ***/
     if (mode > BTM_BLE_MAX_CONNECTABLE)
         return(BTM_ILLEGAL_VALUE);
@@ -1035,45 +994,36 @@
             BTM_TRACE_EVENT0 ("always disable adv in non-discoverable non-connectable mode with no scan rsp");
             if(!p_cb->scan_rsp)
 	            new_mode = BTM_BLE_ADV_DISABLE;
+
         }
     }
     else /* connectable */
     {
-        BTM_TRACE_DEBUG2("btm_ble_set_connectability: mode = %04x discoverable_mode= %02x", mode, p_cb->discoverable_mode);
-
-        if (BTM_BLE_VALID_CONN_DIRECT(&p_cb->direct_bda))
-        {
-            BTM_TRACE_DEBUG0("evt_type = BTM_BLE_CONNECT_DIR_EVT");
-            evt_type = BTM_BLE_CONNECT_DIR_EVT;
-        }
-        else
-        {
-            BTM_TRACE_DEBUG0(" evt_type = BTM_BLE_CONNECT_EVT");
-            evt_type = BTM_BLE_CONNECT_EVT;
-        }
+        evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
     }
 
     /* update adv params if needed */
-    if (p_cb->evt_type != evt_type && new_mode == BTM_BLE_ADV_ENABLE)
+    if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type)
+        && new_mode == BTM_BLE_ADV_ENABLE)
     {
-        if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
-        {
-            p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
-            btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE);
-        }
+        btm_ble_stop_adv();
 
         if (!btsnd_hcic_ble_write_adv_params ((UINT16)(p_cb->adv_interval_min ? p_cb->adv_interval_min : BTM_BLE_GAP_ADV_INT),
                                               (UINT16)(p_cb->adv_interval_max ? p_cb->adv_interval_max : BTM_BLE_GAP_ADV_INT),
                                               evt_type,
-                                              p_cb->own_addr_type,
-                                              p_cb->direct_bda.type,
-                                              p_cb->direct_bda.bda,
+                                              own_addr_type,
+                                              init_addr_type,
+                                              p_addr_ptr,
                                               p_cb->adv_chnl_map,
                                               p_cb->afp))
             status = BTM_NO_RESOURCES;
         else
+        {
             p_cb->evt_type = evt_type;
+            p_cb->adv_addr_type = own_addr_type;
+        }
     }
+
     /* update advertising mode */
     if (status == BTM_SUCCESS && new_mode != p_cb->adv_mode)
     {
@@ -1082,6 +1032,13 @@
             status = BTM_SUCCESS;
 
             p_cb->adv_mode = new_mode;
+
+            if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE &&
+                p_cb->afp != AP_SCAN_CONN_ALL)
+                btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+            else
+                btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+
         }
     }
 
@@ -1103,11 +1060,8 @@
 **
 **
 ** Returns          BTM_CMD_STARTED if successfully started
-**                  BTM_ILLEGAL_VALUE if a bad parameter is detected
 **                  BTM_NO_RESOURCES if could not allocate a message buffer
-**                  BTM_SUCCESS - if cancelling the periodic inquiry
 **                  BTM_BUSY - if an inquiry is already active
-**                  BTM_WRONG_MODE if the device is not up.
 **
 *******************************************************************************/
 tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8   duration)
@@ -1128,7 +1082,7 @@
     /* start scan, already enable duplicate filtering */
     if (btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, BTM_BLE_DUPLICATE_DISABLE))
     {
-        status = BTM_SUCCESS;
+        status = BTM_CMD_STARTED;
         p_inq->proc_mode = mode;
 
         if (duration != 0)
@@ -1155,7 +1109,7 @@
     UINT8   hci_status = HCI_SUCCESS;
     BD_NAME bd_name;
 
-    memset(bd_name, 0, BD_NAME_LEN);
+    memset(bd_name, 0, (BD_NAME_LEN + 1));
     memcpy((UINT8*)bd_name, p_name, length);
 
     if ((!status) || (length==0))
@@ -1163,7 +1117,7 @@
         hci_status = HCI_ERR_HOST_TIMEOUT;
     }
 
-    btm_process_remote_name(bda, bd_name, length, hci_status);
+    btm_process_remote_name(bda, bd_name, length +1, hci_status);
     btm_sec_rmt_name_request_complete (bda, (UINT8 *)p_name, hci_status);
 }
 
@@ -1298,7 +1252,6 @@
 {
     UINT8   *p_cur = p_data;
     UINT8   ad_len, ad_type, ad_flag;
-    tBTM_BLE_ATTR   *p_attr;
 
     BTM_TRACE_EVENT0 (" btm_ble_parse_adv_data");
 
@@ -1348,35 +1301,38 @@
                 BTM_TRACE_DEBUG1("BTM_BLE_AD_TYPE_TX_PWR tx_level = %d", p_adv_data->tx_power_level);
                 break;
 
-            case BTM_BLE_AD_TYPE_ATTR:
-                p_adv_data->ad_mask |= BTM_BLE_AD_BIT_ATTR;
-                p_attr = &p_adv_data->attr_data.attr_list[p_adv_data->attr_data.num_attr];
-                p_attr->uuid = *p_cur ++;
-
-                if (ad_len > 3)
-                {
-                    p_attr->data_len = ad_len - 3;
-                    p_attr->p_data = p_buf;
-                    memcpy(p_attr->p_data, p_cur, p_attr->data_len);
-                    p_buf += p_attr->data_len;
-                }
-
-                p_adv_data->attr_data.num_attr ++;
-                BTM_TRACE_DEBUG2("BTM_BLE_AD_TYPE_ATTR[%d] uuid = 0x%04x",p_adv_data->attr_data.num_attr, p_attr->uuid);
-                break;
-
             case BTM_BLE_AD_TYPE_MANU:
 
-            case BTM_BLE_AD_TYPE_SRV_CMPL:
-            case BTM_BLE_AD_TYPE_SRV_PART:
-                p_adv_data->ad_mask |= ad_type;
+            case BTM_BLE_AD_TYPE_16SRV_PART:
+            case BTM_BLE_AD_TYPE_16SRV_CMPL:
+                p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE;
                 /* need allocate memory to store UUID list */
                 p_adv_data->service.num_service = (ad_len - 1)/2;
                 BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
-
-            default:
                 p_cur += (ad_len - 1);
                 break;
+
+            case BTM_BLE_AD_TYPE_SOL_SRV_UUID:
+                p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_SOL;
+                /* need allocate memory to store UUID list */
+                p_adv_data->service.num_service = (ad_len - 1)/2;
+                BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+                p_cur += (ad_len - 1);
+                break;
+
+            case BTM_BLE_AD_TYPE_128SOL_SRV_UUID:
+                p_adv_data->ad_mask |= BTM_BLE_AD_BIT_SERVICE_128SOL;
+                /* need allocate memory to store UUID list */
+                p_adv_data->service.num_service = (ad_len - 1)/16;
+                BTM_TRACE_DEBUG1("service UUID list, num = %d", p_adv_data->service.num_service);
+                p_cur += (ad_len - 1);
+                break;
+
+            case BTM_BLE_AD_TYPE_APPEARANCE:
+            case BTM_BLE_AD_TYPE_PUBLIC_TARGET:
+            case BTM_BLE_AD_TYPE_RANDOM_TARGET:
+            default:
+                break;
         }
         len -= (ad_len + 1);
     }
@@ -1426,6 +1382,7 @@
     /* parse service UUID from adv packet and save it in inq db eir_uuid */
     /* TODO */
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_is_discoverable
@@ -1501,6 +1458,7 @@
 
     return is_discoverable;
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_update_inq_result
@@ -1567,9 +1525,10 @@
     }
 
     /* if BR/EDR not supported is not set, assume is a DUMO device */
-    if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0)
+    if ((p_cur->flag & BTM_BLE_BREDR_NOT_SPT) == 0 &&
+         evt_type != BTM_BLE_CONNECT_DIR_EVT)
     {
-        BTM_TRACE_ERROR0("BR/EDR NOT support bit not set, treat as DUMO");
+        BTM_TRACE_DEBUG0("BR/EDR NOT support bit not set, treat as DUMO");
         p_cur->device_type |= BT_DEVICE_TYPE_DUMO;
     }
     else
@@ -1625,45 +1584,6 @@
 
 /*******************************************************************************
 **
-** Function         btm_ble_resolve_random_addr_cmpl
-**
-** Description      resolve random address complete callback.
-**
-** Returns          void
-**
-*******************************************************************************/
-static void btm_ble_resolve_random_addr_cmpl(void * p_rec, void *p)
-{
-    tBTM_SEC_DEV_REC    *match_rec = (tBTM_SEC_DEV_REC *) p_rec;
-    UINT8       addr_type = BLE_ADDR_RANDOM;
-    BD_ADDR     bda;
-    UINT8       *pp = (UINT8 *)p + 1;
-    UINT8           evt_type;
-
-    BTM_TRACE_EVENT0 ("btm_ble_resolve_random_addr_cmpl ");
-
-    STREAM_TO_UINT8    (evt_type, pp);
-    STREAM_TO_UINT8    (addr_type, pp);
-    STREAM_TO_BDADDR   (bda, pp);
-
-    if (match_rec)
-    {
-        BTM_TRACE_ERROR0("Random match");
-        memcpy(match_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
-        memcpy(bda, match_rec->bd_addr, BD_ADDR_LEN);
-    }
-    else
-    {
-        BTM_TRACE_ERROR0("Random unmatch");
-    }
-
-    btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, pp);
-
-    return;
-}
-
-/*******************************************************************************
-**
 ** Function         btm_ble_process_adv_pkt
 **
 ** Description      This function is called when adv packet report events are
@@ -1681,8 +1601,6 @@
     UINT8               evt_type = 0, *p = p_data;
     UINT8               addr_type = 0;
 
-    BTM_TRACE_EVENT0 ("btm_ble_process_adv_pkt ");
-
     /* always get one device at a time */
     p ++;
 
@@ -1691,30 +1609,24 @@
     STREAM_TO_UINT8    (addr_type, p);
     STREAM_TO_BDADDR   (bda, p);
 
-#ifdef BTM_BLE_PC_ADV_TEST_MODE // For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include
-    if (BTM_BLE_PC_ADV_TEST_MODE)   // For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode
+#ifdef BTM_BLE_PC_ADV_TEST_MODE /* For general stack code (e.g. BTInsight testing), we simply do not define it to exclude or set it to TRUE to include */
+    if (BTM_BLE_PC_ADV_TEST_MODE)   /* For stack component, it is always defined and maps to a global variable g_bDraculaAdvertisingMode */
     {
         if (btm_cb.ble_ctr_cb.p_scan_req_cback)
             (*btm_cb.ble_ctr_cb.p_scan_req_cback)(bda, addr_type, evt_type);
     }
 #endif
 
+
+
     /* Only process the results if the inquiry is still active */
-    if (!btm_cb.btm_inq_vars.inq_active &&
+    if ((btm_cb.btm_inq_vars.inq_active & BTM_LE_SCAN_ACTIVE_MASK) == 0 &&
         (btm_cb.ble_ctr_cb.bg_conn_type != BTM_BLE_CONN_SELECTIVE ||
          /* or selective auto connection is active */
          btm_cb.ble_ctr_cb.p_select_cback == NULL))
         return;
 
-
-#if SMP_INCLUDED == TRUE
-    if (addr_type == BLE_ADDR_RANDOM && BTM_BLE_IS_RESOLVE_BDA(bda))
-    {
-        btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_cmpl, p_data);
-    }
-    else
-#endif
-        btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
+    btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
 }
 
 /*******************************************************************************
@@ -1755,14 +1667,12 @@
         }
         else
         {
-            BTM_TRACE_DEBUG0("LE in le_bd_db already");
             /* if yes, skip it */
             return; /* assumption: one result per event */
         }
     }
     else /* not been processed int his round */
     {
-        BTM_TRACE_DEBUG0("new LE BD_ADDR");
         to_report = TRUE;
     }
 
@@ -1774,7 +1684,6 @@
             if ((p_i = btm_inq_db_new (bda)) != NULL)
             {
                 p_inq->inq_cmpl_info.num_resp++;
-                BTM_TRACE_DEBUG0("adv pkt process:  new record is added into inq db");
                 to_report = TRUE;
             }
             else
@@ -1809,7 +1718,9 @@
         {
             BTM_TRACE_WARNING0("INQ RES: Extra Response Received...cancelling inquiry..");
 
-            if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) )
+            /* if is non-periodic inquiry active, cancel now */
+            if ((p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK) != 0 &&
+                (p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) == 0)
                 btsnd_hcic_inq_cancel();
 
             /* stop LE scan now */
@@ -1825,14 +1736,17 @@
     /* background connection in selective connection mode */
     if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_SELECTIVE)
     {
-        btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+        if (p_i->inq_info.results.device_type == BT_DEVICE_TYPE_BLE &&
+            (evt_type == BTM_BLE_CONNECT_EVT || evt_type == BTM_BLE_CONNECT_DIR_EVT))
+            btm_send_sel_conn_callback(bda, evt_type, p, addr_type);
+        else
+        {
+            BTM_TRACE_DEBUG0("None LE device, can not initiate selective connection");
+        }
     }
     else if (p_inq_results_cb && to_report)
     {
-        BTM_TRACE_DEBUG0("BTMINQ LE: Found devices, send callback btm_inqrslt_cb");
-
-        if (p_inq->inq_active)
-            (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
+        (p_inq_results_cb)((tBTM_INQ_RESULTS *) &p_i->inq_info.results, p_le_inq_cb->adv_data_cache);
     }
 }
 
@@ -1873,6 +1787,36 @@
 
 /*******************************************************************************
 **
+** Function         btm_ble_start_adv
+**
+** Description      Stop the BLE advertising.
+**
+** Returns          void
+**
+*******************************************************************************/
+static tBTM_STATUS btm_ble_start_adv(void)
+{
+    tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+    tBTM_STATUS     rt = BTM_NO_RESOURCES;
+
+    if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_ENABLE))
+    {
+        if (p_cb->afp != AP_SCAN_CONN_ALL)
+             btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_ADV;
+
+         p_cb->adv_mode = BTM_BLE_ADV_ENABLE;
+
+         rt = BTM_SUCCESS;
+     }
+     else
+     {
+         p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+         btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+     }
+     return rt;
+}
+/*******************************************************************************
+**
 ** Function         btm_ble_stop_adv
 **
 ** Description      Stop the BLE advertising.
@@ -1880,14 +1824,23 @@
 ** Returns          void
 **
 *******************************************************************************/
-void btm_ble_stop_adv(void)
+static tBTM_STATUS btm_ble_stop_adv(void)
 {
-    BTM_TRACE_EVENT0 (" btm_ble_stop_adv");
+    tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
+    tBTM_STATUS rt = BTM_SUCCESS;
 
-    if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+    if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
     {
-        btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+        if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE))
+        {
+            p_cb->adv_mode = BTM_BLE_ADV_DISABLE;
+            btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_ADV;
+        }
+        else
+            rt = BTM_NO_RESOURCES;
     }
+    return rt;
+
 }
 
 /*******************************************************************************
@@ -1917,8 +1870,7 @@
             break;
 
         case BTU_TTYPE_BLE_RANDOM_ADDR:
-            if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_ENABLE &&
-                btm_cb.ble_ctr_cb.inq_var.own_addr_type == BLE_ADDR_RANDOM)
+            if (btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type == BLE_ADDR_RANDOM)
             {
                 /* refresh the random addr */
                 btm_gen_resolvable_private_addr();
@@ -1928,62 +1880,6 @@
     }
 }
 
-/*******************************************************************************
-**
-** Function         btm_ble_connected
-**
-** Description      This function is when a LE connection to the peer device is
-**                  establsihed
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role)
-{
-    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bda);
-    tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
-
-    BTM_TRACE_EVENT0 ("btm_ble_connected");
-
-    /* Commenting out trace due to obf/compilation problems.
-    */
-#if (BT_USE_TRACES == TRUE)
-    if (p_dev_rec)
-    {
-        BTM_TRACE_EVENT4 ("Security Manager: btm_sec_connected :  handle:%d  enc_mode:%d  bda:%x RName:%s",
-                          handle,  enc_mode,
-                          (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5],
-                          p_dev_rec->sec_bd_name);
-
-        BTM_TRACE_DEBUG1 ("btm_ble_connected sec_flags=0x%x",p_dev_rec->sec_flags);
-    }
-    else
-    {
-        BTM_TRACE_EVENT3 ("Security Manager: btm_sec_connected:   handle:%d  enc_mode:%d  bda:%x ",
-                          handle,  enc_mode,
-                          (bda[2]<<24)+(bda[3]<<16)+(bda[4]<<8)+bda[5]);
-    }
-#endif
-
-    if (!p_dev_rec)
-    {
-        /* There is no device record for new connection.  Allocate one */
-        p_dev_rec = btm_sec_alloc_dev (bda);
-    }
-    else    /* Update the timestamp for this device */
-    {
-        p_dev_rec->timestamp = btm_cb.dev_rec_count++;
-    }
-
-    p_dev_rec->device_type = BT_DEVICE_TYPE_BLE;
-    p_dev_rec->hci_handle = handle;
-    if (role == HCI_ROLE_MASTER)
-        p_dev_rec->role_master = TRUE;
-
-    p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
-
-    return;
-}
 
 /*******************************************************************************
 **
@@ -2049,7 +1945,81 @@
         /* toggle back the adv mode */
         p_cb->adv_mode = !p_cb->adv_mode;
     }
+
+
 }
+
+/*******************************************************************************
+**
+** Function         btm_ble_dir_adv_tout
+**
+** Description      when directed adv time out
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_dir_adv_tout(void)
+{
+    btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+
+    /* make device fall back into undirected adv mode by default */
+    btm_cb.ble_ctr_cb.inq_var.directed_conn = FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_update_mode_operation
+**
+** Description      This function update the GAP role operation when a link status
+**                  is updated.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, BOOLEAN conn_cancel)
+{
+    tACL_CONN   *pa = &btm_cb.acl_db[0];
+    UINT16       xx;
+    UINT8        dev_role = link_role;
+
+    BTM_TRACE_DEBUG1("btm_ble_update_mode_operation adv_mode = %d", btm_cb.ble_ctr_cb.inq_var.adv_mode );
+
+    /* update periphera role operation */
+    /* If we are LE connectable, check if we need to start advertising again */
+    if (link_role == HCI_ROLE_UNKNOWN)
+        /* && btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE) */
+    {
+        for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
+        {
+            /* If any other LE link is up, we are still not connectable */
+            if (pa->in_use && pa->is_le_link)
+            {
+                dev_role = pa->link_role;
+                break;
+            }
+        }
+    }
+
+    if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE  &&
+        (dev_role == HCI_ROLE_UNKNOWN )) /* when device has no connection, update adv here */
+        /* if already in connection, no connectable adv is allowed unless scatternet is enabled */
+    {
+        btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
+    }
+
+    /* if connection complete */
+    if (conn_cancel || link_role != HCI_ROLE_UNKNOWN)
+        btm_ble_set_conn_st(BLE_CONN_IDLE);
+
+    if (btm_ble_get_conn_st() == BLE_CONN_IDLE)
+    {
+        if (!btm_send_pending_direct_conn())
+        {
+            btm_ble_resume_bg_conn();
+        }
+    }
+}
+
 /*******************************************************************************
 **
 ** Function         btm_ble_init
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index 449de8f..878037b 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -36,15 +36,6 @@
 #include "smp_api.h"
 #endif
 
-#define BTM_BLE_CONNECT_EVT     0x00
-#define BTM_BLE_CONNECT_DIR_EVT 0x01
-#define BTM_BLE_DISCOVER_EVT    0x02
-#define BTM_BLE_NON_CONNECT_EVT 0x03
-#define BTM_BLE_SCAN_RSP_EVT    0x04
-#define BTM_BLE_SCAN_REQ_EVT    0x06
-#define BTM_BLE_UNKNOWN_EVT     0xff
-
-#define BTM_BLE_UNKNOWN_EVT     0xff
 
 /* scanning enable status */
 #define BTM_BLE_SCAN_ENABLE      0x01
@@ -79,7 +70,10 @@
 #define BTM_BLE_SEC_REQ_ACT_DISCARD        3 /* discard the sec request while encryption is started but not completed */
 typedef UINT8   tBTM_BLE_SEC_REQ_ACT;
 
-
+#define BLE_STATIC_PRIVATE_MSB_MASK          0x3f
+#define BLE_RESOLVE_ADDR_MSB                 0x40   /*  most significant bit, bit7, bit6 is 01 to be resolvable random */
+#define BLE_RESOLVE_ADDR_MASK                0xc0   /* bit 6, and bit7 */
+#define BTM_BLE_IS_RESOLVE_BDA(x)           ((x[0] & BLE_RESOLVE_ADDR_MASK) == BLE_RESOLVE_ADDR_MSB)
 
 typedef struct
 {
@@ -119,13 +113,14 @@
     UINT8            scan_type;        /* current scan type: active or passive */
     UINT16           adv_interval_min;
     UINT16           adv_interval_max;
-    tBLE_ADDR_TYPE	 own_addr_type;
     tBTM_BLE_AFP     afp;               /* advertising filter policy */
     tBTM_BLE_SFP     sfp;               /* scanning filter policy */
 
+    tBLE_ADDR_TYPE   adv_addr_type;
     UINT8            evt_type;
     UINT8            adv_mode;
     tBLE_BD_ADDR     direct_bda;
+    BOOLEAN          directed_conn;
 
     UINT8            adv_len;
     UINT8            adv_data_cache[BTM_BLE_CACHE_ADV_DATA_MAX];
@@ -134,7 +129,6 @@
     UINT8               num_bd_entries;
     UINT8               max_bd_entries;
 
-    tBLE_BD_ADDR        local_bda;
 
     tBTM_BLE_LOCAL_ADV_DATA   adv_data;
     tBTM_BLE_ADV_CHNL_MAP     adv_chnl_map;
@@ -142,21 +136,25 @@
     TIMER_LIST_ENT   inq_timer_ent;
     BOOLEAN          scan_rsp;
     UINT8            state;             /* Current state that the inquiry process is in */
-    UINT8           tx_power;
+    INT8             tx_power;
 } tBTM_BLE_INQ_CB;
 
 
 /* random address resolving complete callback */
 typedef void (tBTM_BLE_RESOLVE_CBACK) (void * match_rec, void *p);
 
+typedef void (tBTM_BLE_ADDR_CBACK) (BD_ADDR_PTR static_random, void *p);
+
 /* random address management control block */
 typedef struct
 {
+    tBLE_ADDR_TYPE	            own_addr_type;         /* local device LE address type */
     BD_ADDR			            private_addr;
     BD_ADDR                     random_bda;
     BOOLEAN                     busy;
     UINT16                       index;
     tBTM_BLE_RESOLVE_CBACK      *p_resolve_cback;
+    tBTM_BLE_ADDR_CBACK         *p_generate_cback;
     void                        *p;
     TIMER_LIST_ENT              raddr_timer_ent;
 } tBTM_LE_RANDOM_CB;
@@ -172,6 +170,32 @@
 
 }tBTM_LE_CONN_PRAMS;
 
+
+typedef struct
+{
+    BD_ADDR     bd_addr;
+    UINT8       attr;
+    BOOLEAN     is_connected;
+    BOOLEAN     in_use;
+}tBTM_LE_BG_CONN_DEV;
+
+  /* white list using state as a bit mask */
+#define BTM_BLE_WL_IDLE         0
+#define BTM_BLE_WL_INIT         1
+#define BTM_BLE_WL_SCAN         2
+#define BTM_BLE_WL_ADV          4
+typedef UINT8 tBTM_BLE_WL_STATE;
+
+/* BLE connection state */
+#define BLE_CONN_IDLE    0
+#define BLE_DIR_CONN     1
+#define BLE_BG_CONN      2
+typedef UINT8 tBTM_BLE_CONN_ST;
+
+typedef struct
+{
+    void    *p_param;
+}tBTM_BLE_CONN_REQ;
 /* Define BLE Device Management control structure
 */
 typedef struct
@@ -188,28 +212,26 @@
     tBTM_BLE_SEL_CBACK  *p_select_cback;
     TIMER_LIST_ENT      scan_param_idle_timer;
 
-    UINT8               bg_conn_dev_num;
-    BD_ADDR             bg_conn_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
+    /* white list information */
+    UINT8                   num_empty_filter;      /* Number of entries in white list */
+    UINT8                   max_filter_entries;    /* Maximum number of entries that can be stored */
+    tBTM_BLE_WL_STATE       wl_state;
+    UINT8                   bg_dev_num;
+    tBTM_LE_BG_CONN_DEV     bg_dev_list[BTM_BLE_MAX_BG_CONN_DEV_NUM];
 
-#define BLE_BG_CONN_IDLE    0
-#define BLE_BG_CONN_ACTIVE  1
-#define BLE_BG_CONN_SUSPEND 2
-
-    UINT8               bg_conn_state;
+    BUFFER_Q                conn_pending_q;
+    tBTM_BLE_CONN_ST        conn_state;
 
     /* random address management control block */
     tBTM_LE_RANDOM_CB   addr_mgnt_cb;
 
-    /* white list information */
-    UINT8            num_empty_filter;      /* Number of entries in white list */
-    UINT8            max_filter_entries;    /* Maximum number of entries that can be stored */
     BOOLEAN          enabled;
-    BOOLEAN          privacy;               /* privacy enabled or disabled */
 
 #ifdef BTM_BLE_PC_ADV_TEST_MODE
     tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
 #endif
 
+    BOOLEAN         scatternet_enable;
 } tBTM_BLE_CB;
 
 #ifdef __cplusplus
@@ -225,17 +247,21 @@
 extern tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode);
 extern tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode);
 extern tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8   duration);
+extern void btm_ble_dir_adv_tout(void);
 
 extern void btm_ble_stop_scan(void);
 extern void btm_ble_att_db_init(void);
 extern void btm_ble_init (void);
-extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role);
+extern void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role, tBLE_ADDR_TYPE addr_type, BOOLEAN addr_matched);
 extern void btm_ble_read_remote_features_complete(UINT8 *p);
-extern void btm_ble_stop_adv(void);
 extern void btm_ble_write_adv_enable_complete(UINT8 * p);
+extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern tBTM_BLE_CONN_ST btm_ble_get_conn_st(void);
+extern void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st);
+
 
 /* LE security function from btm_sec.c */
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#if SMP_INCLUDED == TRUE
 extern void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE_SEC_REQ_ACT *p_sec_req_act);
 extern void btm_ble_ltk_request_reply(BD_ADDR bda,  BOOLEAN use_stk, BT_OCTET16 stk);
 extern UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
@@ -260,35 +286,38 @@
 extern UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
 
 /* white list function */
-extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,tBLE_ADDR_TYPE addr_type);
-extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr);
+extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr,UINT8 wl_type);
+extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr, UINT8 *p_attr_tag);
 extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
 extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
 extern void btm_ble_clear_white_list (void);
-extern void btm_write_bg_conn_wl(void);
 
 /* background connection function */
 extern void btm_ble_suspend_bg_conn(void);
-extern BOOLEAN btm_ble_resume_bg_conn(tBTM_BLE_SEL_CBACK *p_sele_callback, BOOLEAN def_param);
-extern void btm_ble_update_bg_state(void);
+extern BOOLEAN btm_ble_resume_bg_conn(void);
 extern void btm_ble_initiate_select_conn(BD_ADDR bda);
 extern BOOLEAN btm_ble_start_auto_conn(BOOLEAN start);
 extern BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK   *p_select_cback);
-extern BOOLEAN btm_ble_find_dev_in_whitelist(BD_ADDR bd_addr);
 extern BOOLEAN btm_ble_renew_bg_conn_params(BOOLEAN add, BD_ADDR bd_addr);
-extern void btm_ble_scan_param_idle(void);
 extern UINT8 btm_ble_count_unconn_dev_in_whitelist(void);
+extern void btm_write_dir_conn_wl(BD_ADDR target_addr);
+extern void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bda, BOOLEAN conn_ccancel);
+
+/* direct connection utility */
+extern BOOLEAN btm_send_pending_direct_conn(void);
+extern void btm_ble_enqueue_direct_conn_req(void *p_param);
 
 /* BLE address management */
-extern tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bda);
 extern void btm_gen_resolvable_private_addr (void);
-extern void btm_gen_non_resolvable_private_addr (void);
+extern void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p);
 extern void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_cback, void *p);
+extern void btm_ble_update_reconnect_address(BD_ADDR bd_addr);
 
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
 BT_API extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
 BT_API extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
 BT_API extern void btm_ble_set_test_local_sign_cntr_value(BOOLEAN enable, UINT32 test_local_sign_cntr);
+BT_API extern void btm_set_random_address(BD_ADDR random_bda);
 #endif
 
 
diff --git a/stack/btm/btm_dev.c b/stack/btm/btm_dev.c
index 04994d1..40919fa 100644
--- a/stack/btm/btm_dev.c
+++ b/stack/btm/btm_dev.c
@@ -125,7 +125,10 @@
     }
 
 #if defined(BTIF_MIXED_MODE_INCLUDED) && (BTIF_MIXED_MODE_INCLUDED == TRUE)
-    p_dev_rec->sm4 = BTM_SM4_KNOWN;
+    if (key_type  < BTM_MAX_PRE_SM4_LKEY_TYPE)
+        p_dev_rec->sm4 = BTM_SM4_KNOWN;
+    else
+        p_dev_rec->sm4 = BTM_SM4_TRUE;
 #endif
 
     p_dev_rec->rmt_io_caps = io_cap;
@@ -245,7 +248,6 @@
     else
     {
 #if BLE_INCLUDED == TRUE
-        p_dev_rec->device_type = BT_DEVICE_TYPE_BREDR;  /* initialize it as BR/EDR device */
         /* update conn params, use default value for background connection params */
         memset(&p_dev_rec->conn_params, 0xff, sizeof(tBTM_LE_CONN_PRAMS));
 #endif
diff --git a/stack/btm/btm_devctl.c b/stack/btm/btm_devctl.c
index f0fc437..5a88a77 100644
--- a/stack/btm/btm_devctl.c
+++ b/stack/btm/btm_devctl.c
@@ -37,11 +37,6 @@
 #if BLE_INCLUDED == TRUE
 #include "gatt_int.h"
 
-#if GAP_INCLUDED == TRUE
-#include "gap_api.h"
-#include "gattdefs.h"
-#endif
-
 #endif /* BLE_INCLUDED */
 
 /* BTM_APP_DEV_INIT should be defined if additional controller initialization is
@@ -112,10 +107,6 @@
 #define BTM_SCO_HOST_BUF_SIZE       0xff
 #endif
 
-#ifndef BTM_GPS_UIPC_CH_NB
-#define BTM_GPS_UIPC_CH_NB UIPC_CH_ID_1
-#endif
-
 /********************************************************************************/
 /*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /********************************************************************************/
@@ -551,11 +542,6 @@
 
     BTM_TRACE_EVENT0 ("btm_reset_complete");
 
-#ifdef BRCM_VS
-    btm_vs_reset_complete();
-#endif
-
-
     /* Handle if btm initiated the reset */
     if (btm_cb.devcb.state == BTM_DEV_STATE_WAIT_RESET_CMPLT)
     {
@@ -587,11 +573,11 @@
 #endif
 
 #if (BLE_INCLUDED == TRUE)
-     btm_cb.ble_ctr_cb.bg_conn_state = BLE_BG_CONN_IDLE;
-     btm_cb.ble_ctr_cb.bg_conn_dev_num = 0;
+     btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
+     btm_cb.ble_ctr_cb.bg_dev_num = 0;
      btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
      btm_cb.ble_ctr_cb.p_select_cback = NULL;
-     memset(&btm_cb.ble_ctr_cb.bg_conn_dev_list, 0, (sizeof(BD_ADDR)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
+     memset(&btm_cb.ble_ctr_cb.bg_dev_list, 0, (sizeof(tBTM_LE_BG_CONN_DEV)*BTM_BLE_MAX_BG_CONN_DEV_NUM));
      gatt_reset_bgdev_list();
 #endif
     }
@@ -753,13 +739,9 @@
         btm_read_local_features_complete( buf, 9 );
     }
 #else
-#ifdef BRCM_VS
-    btm_brcm_feat_init();
-#else
     /* get local feature if BRCM specific feature is not included  */
     btm_get_local_features ();
 #endif
-#endif
 
 }
 
@@ -781,6 +763,8 @@
         STREAM_TO_UINT8(btm_cb.ble_ctr_cb.max_filter_entries, p);
         btm_cb.ble_ctr_cb.num_empty_filter = btm_cb.ble_ctr_cb.max_filter_entries;
     }
+    /* write LE host support and simultaneous LE supported */
+    btsnd_hcic_ble_write_host_supported(BTM_BLE_HOST_SUPPORT, BTM_BLE_SIMULTANEOUS_HOST);
 
     btm_get_ble_buffer_size();
 }
@@ -827,20 +811,78 @@
         btm_read_local_features_complete( buf, 9 );
     }
 #else
-#ifdef BRCM_VS
-    btm_brcm_feat_init();
-#else
     /* get local feature if BRCM specific feature is not included  */
     btm_get_local_features ();
 #endif
-#endif
 }
 
+/*******************************************************************************
+**
+** Function         btm_read_local_extended_feature
+**
+** Description      Local function called to send a read local extended feature to controller
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_local_extended_feature (void)
+{
+    btu_start_timer (&btm_cb.devcb.reset_timer, BTU_TTYPE_BTM_DEV_CTL, BTM_DEV_REPLY_TIMEOUT);
 
+    /* Send a Read Local extended feature message to the Controller. */
+    btsnd_hcic_read_local_ext_features (1);
+
+}
+/*******************************************************************************
+**
+** Function         btm_read_local_ext_features_complete
+**
+
+** Description      This function is called when local features read is complete.
+**                  This is the last step of the startup sequence.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_read_local_ext_features_complete(UINT8 *p, UINT16 evt_len)
+{
+    tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
+    tBTM_CMPL_CB   *p_cb = p_devcb->p_reset_cmpl_cb;
+    UINT8 last;
+    UINT8 first;
+
+    btu_stop_timer (&btm_cb.devcb.reset_timer);
+    /* If there was a callback address for reset complete, call it */
+    p_devcb->p_reset_cmpl_cb = NULL;
+
+    btm_sec_dev_reset ();
+
+    /* If 802.11 present might have to disable some channels */
+    if (btm_cb.last_disabled_channel != 0xff)
+    {
+        last  = btm_cb.last_disabled_channel;
+        first = btm_cb.first_disabled_channel;
+        btm_cb.last_disabled_channel  = 0xff;
+        btm_cb.first_disabled_channel = 0xff;
+        BTM_SetAfhChannels(first, last);
+    }
+
+    BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
+    BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
+
+    /* If anyone wants device status notifications, give him one */
+    btm_report_device_status (BTM_DEV_STATUS_UP);
+
+    /* Reset sequence is complete. If this was an application originated */
+    /* reset, tell him its done.                                         */
+    if (p_cb)
+        (*p_cb)((void *) NULL);
+}
 /*******************************************************************************
 **
 ** Function         btm_read_local_features_complete
 **
+
 ** Description      This function is called when local features read is complete.
 **                  This is the last step of the startup sequence.
 **
@@ -850,15 +892,8 @@
 void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len)
 {
     tBTM_DEVCB     *p_devcb = &btm_cb.devcb;
-    tBTM_CMPL_CB   *p_cb = p_devcb->p_reset_cmpl_cb;
     UINT8           status;
     UINT16          xx;
-    UINT8 last;
-    UINT8 first;
-
-    btu_stop_timer (&btm_cb.devcb.reset_timer);
-    /* If there was a callback address for reset complete, call it */
-    p_devcb->p_reset_cmpl_cb = NULL;
 
     STREAM_TO_UINT8  (status, p);
     if (status == HCI_SUCCESS)
@@ -1003,18 +1038,6 @@
         else
             btm_cb.btm_def_link_policy &= ~HCI_ENABLE_PARK_MODE;
 
-        btm_sec_dev_reset ();
-
-        /* If 802.11 present might have to disable some channels */
-        if (btm_cb.last_disabled_channel != 0xff)
-        {
-            last  = btm_cb.last_disabled_channel;
-            first = btm_cb.first_disabled_channel;
-            btm_cb.last_disabled_channel  = 0xff;
-            btm_cb.first_disabled_channel = 0xff;
-            BTM_SetAfhChannels(first, last);
-        }
-
 #if ((BTM_EIR_SERVER_INCLUDED == TRUE)||(BTM_EIR_CLIENT_INCLUDED == TRUE))
         if (HCI_LMP_INQ_RSSI_SUPPORTED(p_devcb->local_features))
         {
@@ -1033,21 +1056,8 @@
         else
             l2cu_set_non_flushable_pbf(FALSE);
 #endif
-        BTM_SetPageScanType (BTM_DEFAULT_SCAN_TYPE);
-        BTM_SetInquiryScanType (BTM_DEFAULT_SCAN_TYPE);
-
-        /* If anyone wants device status notifications, give him one */
-        btm_report_device_status (BTM_DEV_STATUS_UP);
-
-#ifdef BRCM_VS
-    btm_brcm_arc_init();
-#endif
-
-        /* Reset sequence is complete. If this was an application originated */
-        /* reset, tell him its done.                                         */
-        if (p_cb)
-            (*p_cb)((void *) NULL);
     }
+    btm_read_local_extended_feature ();
 }
 
 /*******************************************************************************
@@ -1086,9 +1096,6 @@
 tBTM_STATUS BTM_SetLocalDeviceName (char *p_name)
 {
     UINT8    *p;
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
-    tGAP_BLE_ATTR_VALUE     attr_value;
-#endif
 
     if (!p_name || !p_name[0] || (strlen ((char *)p_name) > BD_NAME_LEN))
         return (BTM_ILLEGAL_VALUE);
@@ -1109,11 +1116,6 @@
     p = (UINT8 *)p_name;
 #endif
 
-#if BLE_INCLUDED == TRUE && GAP_INCLUDED == TRUE
-    attr_value.p_dev_name = (UINT8 *)p_name;
-    GAP_BleAttrDBUpdate(GATT_UUID_GAP_DEVICE_NAME, &attr_value);
-#endif
-
     if (btsnd_hcic_change_name(p))
         return (BTM_CMD_STARTED);
     else
diff --git a/stack/btm/btm_inq.c b/stack/btm/btm_inq.c
index 5598562..a9feed7 100644
--- a/stack/btm/btm_inq.c
+++ b/stack/btm/btm_inq.c
@@ -502,8 +502,9 @@
         min_delay < BTM_PER_INQ_MIN_MIN_PERIOD         ||
         min_delay > BTM_PER_INQ_MAX_MIN_PERIOD         ||
         max_delay <= min_delay                         ||
-        max_delay < BTM_PER_INQ_MIN_MAX_PERIOD         ||
-        max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)
+        max_delay < BTM_PER_INQ_MIN_MAX_PERIOD)
+ /*       max_delay > BTM_PER_INQ_MAX_MAX_PERIOD)*/
+ /*  BTM_PER_INQ_MAX_MAX_PERIOD set to 1's in all bits. Condition resulting in false always*/
     {
         return (BTM_ILLEGAL_VALUE);
     }
@@ -618,13 +619,13 @@
     BTM_TRACE_API0 ("BTM_SetConnectability");
 
 #if (BLE_INCLUDED == TRUE && BLE_INCLUDED == TRUE)
-    if (btm_ble_set_connectability(page_mode) == BTM_SUCCESS)
+    if (btm_ble_set_connectability(page_mode) != BTM_SUCCESS)
     {
-        p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
-        p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
+        return BTM_NO_RESOURCES;
     }
+    p_inq->connectable_mode &= (~BTM_BLE_CONNECTABLE_MASK);
+    p_inq->connectable_mode |= (page_mode & BTM_BLE_CONNECTABLE_MASK);
     page_mode &= ~BTM_BLE_CONNECTABLE_MASK;
-
 #endif
 
     /*** Check mode parameter ***/
@@ -757,7 +758,7 @@
         return (BTM_WRONG_MODE);
 
     /* Only cancel if not in periodic mode, otherwise the caller should call BTM_CancelPeriodicMode */
-    if (p_inq->inq_active &&
+    if ((p_inq->inq_active &BTM_INQUIRY_ACTIVE_MASK) != 0 &&
         (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE)))
     {
         p_inq->inq_active = BTM_INQUIRY_INACTIVE;
@@ -775,8 +776,11 @@
          /* Initiate the cancel inquiry */
         else
         {
-            if (!btsnd_hcic_inq_cancel())
-                status = BTM_NO_RESOURCES;
+            if ((p_inq->inqparms.mode & BTM_BR_INQUIRY_MASK) != 0)
+            {
+                if (!btsnd_hcic_inq_cancel())
+                    status = BTM_NO_RESOURCES;
+            }
 #if BLE_INCLUDED == TRUE
             if ((p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) != 0)
                 btm_ble_stop_scan();
@@ -805,7 +809,7 @@
 ** Description      This function is called to start an inquiry.
 **
 ** Parameters:      p_inqparms - pointer to the inquiry information
-**                      mode - GENERAL or LIMITED inquiry
+**                      mode - GENERAL or LIMITED inquiry, BR/LE bit mask seperately
 **                      duration - length in 1.28 sec intervals (If '0', the inquiry is CANCELLED)
 **                      max_resps - maximum amount of devices to search for before ending the inquiry
 **                      filter_cond_type - BTM_CLR_INQUIRY_FILTER, BTM_FILTER_COND_DEVICE_CLASS, or
@@ -830,7 +834,7 @@
 tBTM_STATUS BTM_StartInquiry (tBTM_INQ_PARMS *p_inqparms, tBTM_INQ_RESULTS_CB *p_results_cb,
                               tBTM_CMPL_CB *p_cmpl_cb)
 {
-    tBTM_STATUS  status;
+    tBTM_STATUS  status = BTM_CMD_STARTED;
     tBTM_INQUIRY_VAR_ST *p_inq = &btm_cb.btm_inq_vars;
 
     BTM_TRACE_API4 ("BTM_StartInquiry: mode: %d, dur: %d, rsps: %d, flt: %d",
@@ -847,23 +851,23 @@
         return (BTM_WRONG_MODE);
 
     if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_GENERAL_INQUIRY &&
-        (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY)
+        (p_inqparms->mode & BTM_BR_INQUIRY_MASK)!= BTM_LIMITED_INQUIRY
+#if (BLE_INCLUDED == TRUE)
+        && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_GENERAL_INQUIRY
+        && (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)!= BTM_BLE_LIMITED_INQUIRY
+#endif
+        )
         return (BTM_ILLEGAL_VALUE);
 
     /* Save the inquiry parameters to be used upon the completion of setting/clearing the inquiry filter */
     p_inq->inqparms = *p_inqparms;
-#if (BLE_INCLUDED == TRUE)
-    p_inq->inqparms.mode = (UINT8)(p_inq->inqparms.mode & BTM_BLE_INQUIRY_MASK) | (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#else
-    p_inq->inqparms.mode = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
-#endif
 
     /* Initialize the inquiry variables */
     p_inq->state = BTM_INQ_ACTIVE_STATE;
     p_inq->p_inq_cmpl_cb = p_cmpl_cb;
     p_inq->p_inq_results_cb = p_results_cb;
     p_inq->inq_cmpl_info.num_resp = 0;         /* Clear the results counter */
-    p_inq->inq_active = (UINT8)(1 << (p_inqparms->mode & BTM_BR_INQUIRY_MASK));
+    p_inq->inq_active = p_inqparms->mode;
 
     BTM_TRACE_DEBUG1("BTM_StartInquiry: p_inq->inq_active = 0x%02x", p_inq->inq_active);
 
@@ -872,8 +876,8 @@
     if (p_inqparms->mode & BTM_BLE_INQUIRY_MASK)
     {
         /* BLE for now does not support filter condition for inquiry */
-        if (btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
-                        p_inq->inqparms.duration) != BTM_SUCCESS)
+        if ((status = btm_ble_start_inquiry((UINT8)(p_inqparms->mode & BTM_BLE_INQUIRY_MASK),
+                        p_inq->inqparms.duration)) != BTM_CMD_STARTED)
         {
             BTM_TRACE_ERROR0("Err Starting LE Inquiry.");
             p_inq->inqparms.mode &= ~ BTM_BLE_INQUIRY_MASK;
@@ -885,6 +889,10 @@
     }
 #endif /* end of BLE_INCLUDED */
 
+    /* we're done with this routine if BR/EDR inquiry is not desired. */
+    if ((p_inqparms->mode & BTM_BR_INQUIRY_MASK) == BTM_INQUIRY_NONE)
+        return status;
+
 #if (defined(BTM_BYPASS_EVENT_FILTERING) && BTM_BYPASS_EVENT_FILTERING == TRUE)
     BTM_TRACE_WARNING0("BTM: Bypassing event filtering...");
     p_inq->inqfilt_active = FALSE;
@@ -1954,7 +1962,7 @@
     UINT8            num_resp, xx;
     BD_ADDR          bda;
     tINQ_DB_ENT     *p_i;
-    tBTM_INQ_RESULTS *p_cur;
+    tBTM_INQ_RESULTS *p_cur=NULL;
     BOOLEAN          is_new = TRUE;
     BOOLEAN          update = FALSE;
     INT8             i_rssi;
@@ -1977,8 +1985,8 @@
     BTM_TRACE_DEBUG3 ("btm_process_inq_results inq_active:0x%x state:%d inqfilt_active:%d",
         btm_cb.btm_inq_vars.inq_active, btm_cb.btm_inq_vars.state, btm_cb.btm_inq_vars.inqfilt_active);
 #endif
-    /* Only process the results if the inquiry is still active */
-    if (!p_inq->inq_active)
+    /* Only process the results if the BR inquiry is still active */
+    if (!(p_inq->inq_active & BTM_BR_INQ_ACTIVE_MASK))
         return;
 
     STREAM_TO_UINT8 (num_resp, p);
@@ -2499,7 +2507,7 @@
 *******************************************************************************/
 void btm_process_remote_name (BD_ADDR bda, BD_NAME bdn, UINT16 evt_len, UINT8 hci_status)
 {
-    tBTM_REMOTE_DEV_NAME    rem_name = {0};
+    tBTM_REMOTE_DEV_NAME    rem_name;
     tBTM_INQUIRY_VAR_ST    *p_inq = &btm_cb.btm_inq_vars;
     tBTM_CMPL_CB           *p_cb = p_inq->p_remname_cmpl_cb;
     UINT8                  *p_n1;
@@ -2559,6 +2567,7 @@
             /*      temporary buffer.                                       */
             p_n1 = (UINT8 *)rem_name.remote_bd_name;
             rem_name.length = (evt_len < BD_NAME_LEN) ? evt_len : BD_NAME_LEN;
+            rem_name.remote_bd_name[rem_name.length] = 0;
             rem_name.status = BTM_SUCCESS;
             temp_evt_len = rem_name.length;
 
@@ -2567,6 +2576,7 @@
                 *p_n1++ = *bdn++;
                 temp_evt_len--;
             }
+            rem_name.remote_bd_name[rem_name.length] = 0;
         }
 
 
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index e5f4c15..0b83051 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -117,6 +117,11 @@
 #endif /* BTM_PWR_MGR_INCLUDED */
 #if BLE_INCLUDED == TRUE
     UINT8           is_le_link;
+    BD_ADDR         conn_addr;              /* local device address used for this connection */
+    UINT8           conn_addr_type;         /* local device address type for this connection */
+    BD_ADDR         active_remote_addr;     /* remote address used on this connection */
+    UINT8           active_remote_addr_type;         /* local device address type for this connection */
+
 #endif
 
 } tACL_CONN;
@@ -171,6 +176,10 @@
     TIMER_LIST_ENT       tx_power_timer;
     tBTM_CMPL_CB        *p_tx_power_cmpl_cb;   /* Callback function to be called       */
 
+#if BLE_INCLUDED == TRUE
+    tBTM_CMPL_CB        *p_le_test_cmd_cmpl_cb;   /* Callback function to be called when
+                                                  LE test mode command has been sent successfully */
+#endif
     BD_ADDR              local_addr;        /* BD_ADDR of the local device          */
     tBTM_VERSION_INFO    local_version;     /* Local Version Information            */
     BD_FEATURES          local_features;    /* Local features bit mask              */
@@ -464,8 +473,7 @@
 typedef struct
 {
     tBLE_ADDR_TYPE      ble_addr_type;  /* LE device type: public or random address */
-    BD_ADDR             reconn_addr;    /* reconnect address */
-    BD_ADDR             cur_rand_addr;  /* current random address */
+    tBLE_ADDR_TYPE      static_addr_type;   /* static address type */
     BD_ADDR             static_addr;    /* static address */
 
 #if SMP_INCLUDED == TRUE
@@ -491,17 +499,18 @@
     DEV_CLASS            dev_class;         /* DEV_CLASS of the device            */
     LINK_KEY             link_key;          /* Device link key                    */
 
-#define BTM_SEC_AUTHORIZED      BTM_SEC_FLAG_AUTHORIZED
-#define BTM_SEC_AUTHENTICATED   BTM_SEC_FLAG_AUTHENTICATED
-#define BTM_SEC_ENCRYPTED       BTM_SEC_FLAG_ENCRYPTED
+#define BTM_SEC_AUTHORIZED      BTM_SEC_FLAG_AUTHORIZED     /* 0x01 */
+#define BTM_SEC_AUTHENTICATED   BTM_SEC_FLAG_AUTHENTICATED  /* 0x02 */
+#define BTM_SEC_ENCRYPTED       BTM_SEC_FLAG_ENCRYPTED      /* 0x04 */
 #define BTM_SEC_NAME_KNOWN      0x08
-#define BTM_SEC_LINK_KEY_KNOWN  BTM_SEC_FLAG_LKEY_KNOWN
+#define BTM_SEC_LINK_KEY_KNOWN  BTM_SEC_FLAG_LKEY_KNOWN /* 0x10 */
 #define BTM_SEC_LINK_KEY_AUTHED 0x20
 #define BTM_SEC_ROLE_SWITCHED   0x40
 #define BTM_SEC_IN_USE          0x80
 
-    tBTM_BD_NAME    sec_bd_name;        /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
     UINT8           sec_flags;          /* Current device security state      */
+
+    tBTM_BD_NAME    sec_bd_name;        /* User friendly name of the device. (may be truncated to save space in dev_rec table) */
     BD_FEATURES     features;           /* Features suported by the device    */
 
 #define BTM_SEC_STATE_IDLE              0
@@ -525,6 +534,8 @@
     UINT8       link_key_type;          /* Type of key used in pairing   */
     BOOLEAN     link_key_changed;       /* Changed link key during current connection */
 
+#define BTM_MAX_PRE_SM4_LKEY_TYPE   BTM_LKEY_TYPE_REMOTE_UNIT /* the link key type used by legacy pairing */
+
 #define BTM_SM4_UNKNOWN     0x00
 #define BTM_SM4_KNOWN       0x10
 #define BTM_SM4_TRUE        0x11
@@ -552,6 +563,9 @@
     UINT8           rs_disc_pending;
 #endif
 // btla-specific --
+#define BTM_SEC_NO_LAST_SERVICE_ID      0
+    UINT8           last_author_service_id;         /* ID of last serviced authorized: Reset after each l2cap connection */
+
 } tBTM_SEC_DEV_REC;
 
 #define BTM_SEC_IS_SM4(sm) ((BOOLEAN)(BTM_SM4_TRUE == ((sm)&BTM_SM4_TRUE)))
@@ -676,6 +690,7 @@
 #define BTM_PAIR_FLAGS_PIN_REQD         0x08    /* set this bit when pin_callback is called     */
 #define BTM_PAIR_FLAGS_PRE_FETCH_PIN    0x10    /* set this bit when pre-fetch pin     */
 #define BTM_PAIR_FLAGS_REJECTED_CONNECT 0x20    /* set this bit when rejected incoming connection  */
+#define BTM_PAIR_FLAGS_WE_CANCEL_DD     0x40    /* set this bit when cancelling a bonding procedure */
 
 typedef struct
 {
@@ -1003,6 +1018,7 @@
 extern void btm_read_local_version_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_hci_buf_size_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_local_features_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_read_local_ext_features_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_local_name_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_local_addr_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_get_local_features (void);
@@ -1010,7 +1026,7 @@
 #if (BLE_INCLUDED == TRUE)
 extern void btm_read_ble_buf_size_complete (UINT8 *p, UINT16 evt_len);
 extern void btm_read_white_list_size_complete(UINT8 *p, UINT16 evt_len);
-extern void btm_ble_add_2_white_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_2_white_list_complete(UINT8 status);
 extern void btm_ble_remove_from_white_list_complete(UINT8 *p, UINT16 evt_len);
 extern void btm_ble_clear_white_list_complete(UINT8 *p, UINT16 evt_len);
 #endif  /* BLE_INCLUDED */
@@ -1081,6 +1097,7 @@
 extern void  btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC  *p_dev_rec);
 extern  BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_DEV_REC *p_rec);
 extern BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda);
+extern BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda);
 #endif /* BLE_INCLUDED */
 
 extern tINQ_DB_ENT *btm_inq_db_new (BD_ADDR p_bda);
@@ -1098,13 +1115,7 @@
 extern void  btm_acl_paging (BT_HDR *p, BD_ADDR dest);
 extern void  btm_acl_set_discing (BOOLEAN discing);
 extern UINT8 btm_sec_clr_service_by_psm (UINT16 psm);
-
-#ifdef BRCM_VS
-extern void btm_brcm_feat_init(void);
-extern void btm_vs_reset_complete (void);
-extern void btm_brcm_arc_init (void);
-
-#endif
+extern void  btm_sec_clr_temp_auth_service (BD_ADDR bda);
 
 #ifdef __cplusplus
 }
diff --git a/stack/btm/btm_sco.c b/stack/btm/btm_sco.c
index 5a11404..f580232 100644
--- a/stack/btm/btm_sco.c
+++ b/stack/btm/btm_sco.c
@@ -308,8 +308,6 @@
 #endif
 }
 
-
-
 /*******************************************************************************
 **
 ** Function         BTM_WriteScoData
@@ -619,10 +617,7 @@
                     {
                         if (md == BTM_PM_MD_PARK || md == BTM_PM_MD_SNIFF)
                         {
-/* Coverity: FALSE-POSITIVE error from Coverity tool. Please do NOT remove following comment. */
-/* coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
-                                the other data members of tBTM_PM_PWR_MD are ignored
-*/
+                            memset( (void*)&pm, 0, sizeof(pm));
                             pm.mode = BTM_PM_MD_ACTIVE;
                             BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, remote_bda, &pm);
                             p->state = SCO_ST_PEND_UNPARK;
@@ -1447,6 +1442,8 @@
 tBTM_STATUS BTM_ReadEScoLinkParms (UINT16 sco_inx, tBTM_ESCO_DATA *p_parms)
 {
 #if (BTM_MAX_SCO_LINKS>0)
+    UINT8 index;
+
     BTM_TRACE_API1("BTM_ReadEScoLinkParms -> sco_inx 0x%04x", sco_inx);
 
     if (sco_inx < BTM_MAX_SCO_LINKS &&
@@ -1455,8 +1452,23 @@
         *p_parms = btm_cb.sco_cb.sco_db[sco_inx].esco.data;
         return (BTM_SUCCESS);
     }
+
+    if (sco_inx == BTM_FIRST_ACTIVE_SCO_INDEX)
+    {
+        for (index = 0; index < BTM_MAX_SCO_LINKS; index++)
+        {
+            if (btm_cb.sco_cb.sco_db[index].state >= SCO_ST_CONNECTED)
+            {
+                BTM_TRACE_API1("BTM_ReadEScoLinkParms the first active SCO index is %d",index);
+                *p_parms = btm_cb.sco_cb.sco_db[index].esco.data;
+                return (BTM_SUCCESS);
+            }
+        }
+    }
+
 #endif
 
+    BTM_TRACE_API0("BTM_ReadEScoLinkParms cannot find the SCO index!");
     memset(p_parms, 0, sizeof(tBTM_ESCO_DATA));
     return (BTM_WRONG_MODE);
 }
diff --git a/stack/btm/btm_sec.c b/stack/btm/btm_sec.c
index 956364e..212b118 100644
--- a/stack/btm/btm_sec.c
+++ b/stack/btm/btm_sec.c
@@ -288,7 +288,7 @@
 {
     UINT8   old_mode = btm_cb.security_mode;
 
-    UINT8   sp_mode = HCI_SPD_MODE_ENABLED;
+    UINT8   sp_mode = HCI_SP_MODE_ENABLED;
     UINT8   sp_debug_mode = HCI_SPD_MODE_DISABLED;
 
     switch (security_mode)
@@ -777,6 +777,39 @@
 
 /*******************************************************************************
 **
+** Function         btm_sec_clr_temp_auth_service
+**
+** Description      Removes specified device record's temporary authorization
+**                  flag from the security database.
+**
+** Parameters       Device address to be cleared
+**
+** Returns          void.
+**
+*******************************************************************************/
+void btm_sec_clr_temp_auth_service (BD_ADDR bda)
+{
+    tBTM_SEC_DEV_REC   *p_dev_rec;
+
+    if ((p_dev_rec = btm_find_dev (bda)) == NULL)
+    {
+        BTM_TRACE_WARNING0 ("btm_sec_clr_temp_auth_service() - no dev CB");
+        return;
+    }
+
+    /* Reset the temporary authorized flag so that next time (untrusted) service is accessed autorization will take place */
+    if (p_dev_rec->last_author_service_id != BTM_SEC_NO_LAST_SERVICE_ID && p_dev_rec->p_cur_service)
+    {
+        BTM_TRACE_DEBUG6 ("btm_sec_clr_auth_service_by_psm [clearing device: %02x:%02x:%02x:%02x:%02x:%02x]",
+                    bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
+
+        p_dev_rec->last_author_service_id = BTM_SEC_NO_LAST_SERVICE_ID;
+    }
+}
+
+/*******************************************************************************
+**
+**
 ** Function         BTM_SecClrUCDService
 **
 ** Description
@@ -964,7 +997,18 @@
     {
         p_dev_rec->sec_flags   |= BTM_SEC_AUTHORIZED;
         if (trusted_mask)
+        {
             BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
+        }
+
+        /* Save the currently authorized service in case we are asked again
+        by another multiplexer layer */
+        if (!p_dev_rec->is_originator)
+        {
+            BTM_TRACE_DEBUG1("BTM_DeviceAuthorized: Setting last_author_service_id to %d",
+                             p_dev_rec->p_cur_service->service_id);
+            p_dev_rec->last_author_service_id = p_dev_rec->p_cur_service->service_id;
+        }
     }
 
     if (p_dev_rec->sec_state != BTM_SEC_STATE_AUTHORIZING)
@@ -1008,6 +1052,8 @@
 #if SMP_INCLUDED == TRUE
     tACL_CONN   *p=NULL;
     BOOLEAN     is_le_slave_role=FALSE;
+    tBT_DEVICE_TYPE     dev_type;
+    tBLE_ADDR_TYPE      addr_type;
 #endif
     BTM_TRACE_API6 ("BTM_SecBond BDA: %02x:%02x:%02x:%02x:%02x:%02x",
                     bd_addr[0], bd_addr[1], bd_addr[2], bd_addr[3], bd_addr[4], bd_addr[5]);
@@ -1100,10 +1146,11 @@
 
     }
 
+    BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
     /* LE device, do SMP pairing */
-    if (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE)
+    if (dev_type == BT_DEVICE_TYPE_BLE)
     {
-        if (SMP_Pair(p_dev_rec->bd_addr) == SMP_STARTED)
+        if (SMP_Pair(bd_addr) == SMP_STARTED)
         {
             p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
             return BTM_CMD_STARTED;
@@ -1275,7 +1322,12 @@
 
                 return BTM_NO_RESOURCES;
             }
-
+            if (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME)
+            {
+                BTM_CancelRemoteDeviceName();
+                btm_cb.pairing_flags |= BTM_PAIR_FLAGS_WE_CANCEL_DD;
+                return BTM_CMD_STARTED;
+            }
             return BTM_NOT_AUTHORIZED;
         }
     }
@@ -1450,7 +1502,8 @@
 *******************************************************************************/
 static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 reason)
 {
-    UINT8 old_state = p_dev_rec->sec_state;
+    UINT8       old_state = p_dev_rec->sec_state;
+    tBTM_STATUS status = BTM_CMD_STARTED;
 
     BTM_TRACE_EVENT2 ("btm_sec_send_hci_disconnect:  handle:0x%x, reason=0x%x",
                       p_dev_rec->hci_handle, reason);
@@ -1466,18 +1519,19 @@
         {
                  BTM_TRACE_ERROR0("RS in progress - Set DISC Pending flag in btm_sec_send_hci_disconnect to delay disconnect");
                  p_dev_rec->rs_disc_pending = BTM_SEC_DISC_PENDING;
-                 return BTM_SUCCESS;
+                 status = BTM_SUCCESS;
         }
+        else
 #endif
         /* Tear down the HCI link */
         if (!btsnd_hcic_disconnect (p_dev_rec->hci_handle, reason))
         {
             /* could not send disconnect. restore old state */
             p_dev_rec->sec_state = old_state;
-            return(BTM_NO_RESOURCES);
+            status = BTM_NO_RESOURCES;
         }
     }
-    return(BTM_CMD_STARTED);
+    return (status);
 }
 
 /*******************************************************************************
@@ -1916,6 +1970,45 @@
 *************************************************************************/
 /*******************************************************************************
 **
+** Function         btm_sec_is_upgrade_possible
+**
+** Description      This function returns TRUE if the existing link key
+**                  can be upgraded or if the link key does not exist.
+**
+** Returns          BOOLEAN
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN is_originator)
+{
+    UINT16              mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
+    BOOLEAN             is_possible = TRUE;
+
+    if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
+    {
+        is_possible = FALSE;
+        BTM_TRACE_DEBUG5 ("btm_sec_is_upgrade_possible id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
+                          p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
+                          mtm_check, p_dev_rec->p_cur_service->security_flags);
+        /* Already have a link key to the connected peer. Is the link key secure enough?
+        ** Is a link key upgrade even possible?
+        */
+        if ((p_dev_rec->security_required & mtm_check)                          /* needs MITM */
+            && (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) /* has unauthenticated link key */
+            && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX)                           /* a valid peer IO cap */
+            && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */
+        {
+            /* upgrade is possible: check if the application wants the upgrade.
+             * If the application is configured to use a global MITM flag,
+             * it probably would not want to upgrade the link key based on the security level database */
+            is_possible = TRUE;
+        }
+    }
+    BTM_TRACE_DEBUG2 ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags);
+    return is_possible;
+}
+
+/*******************************************************************************
+**
 ** Function         btm_sec_check_upgrade
 **
 ** Description      This function is called to check if the existing link key
@@ -1927,42 +2020,33 @@
 static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN is_originator)
 {
     tBTM_SP_UPGRADE     evt_data;
-    UINT16              mtm_check = is_originator ? BTM_SEC_OUT_MITM : BTM_SEC_IN_MITM;
 
-    if (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)
+    BTM_TRACE_DEBUG0 ("btm_sec_check_upgrade...");
+
+    /* Only check if link key already exists */
+    if (!(p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
+        return;
+    if (btm_sec_is_upgrade_possible (p_dev_rec, is_originator) == TRUE)
     {
+        BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
+        /* upgrade is possible: check if the application wants the upgrade.
+         * If the application is configured to use a global MITM flag,
+         * it probably would not want to upgrade the link key based on the security level database */
+        memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+        evt_data.upgrade = TRUE;
+        if (btm_cb.api.p_sp_callback)
+            (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
 
-        BTM_TRACE_DEBUG5 ("btm_sec_check_upgrade id:%d, link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, flags:x%x",
-                          p_dev_rec->p_cur_service->service_id, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps,
-                          mtm_check, p_dev_rec->p_cur_service->security_flags);
-        /* Already have a link key to the connected peer. Is the link key secure enough?
-        ** Is a link key upgrade even possible?
-        */
-        if ((p_dev_rec->security_required & mtm_check)                          /* needs MITM */
-            && (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB) /* has unauthenticated link key */
-            && (p_dev_rec->rmt_io_caps < BTM_IO_CAP_MAX)                           /* a valid peer IO cap */
-            && (btm_sec_io_map[p_dev_rec->rmt_io_caps][btm_cb.devcb.loc_io_caps])) /* authenticated link key is possible */
+        BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
+        if (evt_data.upgrade)
         {
-            BTM_TRACE_DEBUG1 ("need upgrade!! sec_flags:0x%x", p_dev_rec->sec_flags);
-            /* upgrade is possible: check if the application wants the upgrade.
-             * If the application is configured to use a global MITM flag,
-             * it probably would not want to upgrade the link key based on the security level database */
-            memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
-            evt_data.upgrade = TRUE;
-            if (btm_cb.api.p_sp_callback)
-                (*btm_cb.api.p_sp_callback) (BTM_SP_UPGRADE_EVT, (tBTM_SP_EVT_DATA *)&evt_data);
+            /* if the application confirms the upgrade, set the upgrade bit */
+            p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
 
-            BTM_TRACE_DEBUG1 ("evt_data.upgrade:0x%x", evt_data.upgrade);
-            if (evt_data.upgrade)
-            {
-                /* if the application confirms the upgrade, set the upgrade bit */
-                p_dev_rec->sm4 |= BTM_SM4_UPGRADE;
-
-                /* Clear the link key known to go through authentication/pairing again */
-                p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
-                p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
-                BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
-            }
+            /* Clear the link key known to go through authentication/pairing again */
+            p_dev_rec->sec_flags &= ~(BTM_SEC_LINK_KEY_KNOWN | BTM_SEC_LINK_KEY_AUTHED);
+            p_dev_rec->sec_flags &= ~BTM_SEC_AUTHENTICATED;
+            BTM_TRACE_DEBUG1 ("sec_flags:0x%x", p_dev_rec->sec_flags);
         }
     }
 }
@@ -2085,15 +2169,17 @@
     /* we will process one after another */
     if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
     {
-        BTM_TRACE_EVENT2 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed  state: %s",
-                          psm, btm_pair_state_descr(btm_cb.pairing_state));
+        BTM_TRACE_EVENT4 ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed  state: %s mode:%d, sm4:0x%x",
+                          psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4);
+        BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
         rc = BTM_CMD_STARTED;
         if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
             || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+            || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
            )
         {
-            BTM_TRACE_EVENT2 ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
-            /* legacy mode - local is legacy or local is lisbon/peer is legacy */
+            /* legacy mode - local is legacy or local is lisbon/peer is legacy
+             * or SM4 with no possibility of link key upgrade */
             if (is_originator)
             {
                 if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
@@ -2256,11 +2342,16 @@
 
     p_dev_rec->p_callback        = p_callback;
 
-    /* Although authentication and encryption are per connection */
-    /* authorization is per access request.  For example when serial connection */
-    /* is up and authorized and client requests to read file (access to other */
-    /* scn, we need to request user's permission again. */
-    p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+    if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+        || p_dev_rec->last_author_service_id != p_dev_rec->p_cur_service->service_id)
+    {
+        /* Although authentication and encryption are per connection
+        ** authorization is per access request.  For example when serial connection
+        ** is up and authorized and client requests to read file (access to other
+        ** scn), we need to request user's permission again.
+        */
+        p_dev_rec->sec_flags &= ~BTM_SEC_AUTHORIZED;
+    }
 
     if (BTM_SEC_IS_SM4(p_dev_rec->sm4))
     {
@@ -2311,6 +2402,7 @@
     tBTM_SEC_DEV_REC  *p_dev_rec;
     tBTM_SEC_SERV_REC *p_serv_rec;
     tBTM_STATUS        rc;
+    UINT16             security_required;
 
     BTM_TRACE_DEBUG1 ("btm_sec_mx_access_request is_originator:%d", is_originator);
     /* Find or get oldest record */
@@ -2337,8 +2429,41 @@
         BTM_TRACE_EVENT4 ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed  state: %s",
                           psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
 
-        btm_sec_queue_mx_request (bd_addr, psm,  is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
-        return BTM_CMD_STARTED;
+        rc = BTM_CMD_STARTED;
+        security_required = p_serv_rec->security_flags;
+        if ((BTM_SEC_MODE_SP != btm_cb.security_mode)
+            || ((BTM_SEC_MODE_SP == btm_cb.security_mode) && (BTM_SM4_KNOWN == p_dev_rec->sm4))
+            || (BTM_SEC_IS_SM4(p_dev_rec->sm4) && (btm_sec_is_upgrade_possible(p_dev_rec, is_originator) == FALSE))
+           )
+        {
+            /* legacy mode - local is legacy or local is lisbon/peer is legacy
+             * or SM4 with no possibility of link key upgrade */
+            if (is_originator)
+            {
+                if (((security_required & BTM_SEC_OUT_FLAGS) == 0) ||
+                    ((((security_required & BTM_SEC_OUT_FLAGS) == BTM_SEC_OUT_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+                    ((((security_required & BTM_SEC_OUT_FLAGS) == (BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+                    )
+                {
+                    rc = BTM_SUCCESS;
+                }
+            }
+            else
+            {
+                if (((security_required & BTM_SEC_IN_FLAGS) == 0) ||
+                    ((((security_required & BTM_SEC_IN_FLAGS) == BTM_SEC_IN_AUTHENTICATE) && (p_dev_rec->sec_flags & BTM_SEC_AUTHENTICATED))) ||
+                    ((((security_required & BTM_SEC_IN_FLAGS) == (BTM_SEC_IN_AUTHENTICATE | BTM_SEC_IN_ENCRYPT)) && (p_dev_rec->sec_flags & BTM_SEC_ENCRYPTED)))
+                    )
+                {
+                    rc = BTM_SUCCESS;
+                }
+            }
+        }
+        if (rc == BTM_CMD_STARTED)
+        {
+            btm_sec_queue_mx_request (bd_addr, psm,  is_originator, mx_proto_id, mx_chan_id, p_callback, p_ref_data);
+            return rc;
+        }
     }
 
     p_dev_rec->p_cur_service     = p_serv_rec;
@@ -2487,7 +2612,9 @@
 
     if ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_DISC_WHEN_DONE) ||
         (BTM_PAIR_STATE_WAIT_LOCAL_PIN == btm_cb.pairing_state &&
-         BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags))
+         BTM_PAIR_FLAGS_WE_STARTED_DD & btm_cb.pairing_flags) ||
+         (btm_cb.pairing_state == BTM_PAIR_STATE_GET_REM_NAME &&
+          BTM_PAIR_FLAGS_WE_CANCEL_DD & btm_cb.pairing_flags))
     {
         /* for dedicated bonding in legacy mode, authentication happens at "link level"
          * btm_sec_connected is called with failed status.
@@ -2894,6 +3021,12 @@
         if (p_bd_addr && memcmp (btm_cb.pairing_bda, p_bd_addr, BD_ADDR_LEN) == 0)
         {
             BTM_TRACE_EVENT2 ("btm_sec_rmt_name_request_complete() continue bonding sm4: 0x%04x, status:0x%x", p_dev_rec->sm4, status);
+            if(btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_CANCEL_DD)
+            {
+                btm_sec_bond_cancel_complete();
+                return;
+            }
+
             if (status != HCI_SUCCESS)
             {
                 btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
@@ -3531,6 +3664,7 @@
         memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
         memcpy (evt_data.dev_class, p_dev_rec->dev_class, DEV_CLASS_LEN);
         BCM_STRNCPY_S((char *)evt_data.bd_name, sizeof(evt_data.bd_name), (char *)p_dev_rec->sec_bd_name, BTM_MAX_REM_BD_NAME_LEN+1);
+        evt_data.bd_name[BTM_MAX_REM_BD_NAME_LEN] = 0;
 
         btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_LOCAL_OOB_RSP);
         if ((*btm_cb.api.p_sp_callback) (BTM_SP_RMT_OOB_EVT, (tBTM_SP_EVT_DATA *)&evt_data) == BTM_NOT_AUTHORIZED)
@@ -3834,10 +3968,12 @@
 void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
 {
     tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev_by_handle (handle);
-
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+    tACL_CONN         *p_acl;
+#endif
     BTM_TRACE_EVENT3 ("Security Manager: encrypt_change status:%d State:%d, encr_enable = %d",
                       status, (p_dev_rec) ? p_dev_rec->sec_state : 0, encr_enable);
-    BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+    BTM_TRACE_DEBUG1 ("before update p_dev_rec->sec_flags=0x%x", (p_dev_rec) ? p_dev_rec->sec_flags : 0 );
 
     /* For transaction collision we need to wait and repeat.  There is no need */
     /* for random timeout because only slave should receive the result */
@@ -3860,8 +3996,11 @@
         p_dev_rec->sec_flags &= ~BTM_SEC_ENCRYPTED;
 
     BTM_TRACE_DEBUG1 ("after update p_dev_rec->sec_flags=0x%x", p_dev_rec->sec_flags );
+
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
-    if (p_dev_rec->device_type  == BT_DEVICE_TYPE_BLE)
+    p_acl = btm_bda_to_acl(p_dev_rec->bd_addr);
+
+    if (p_acl && p_acl->is_le_link)
     {
         btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
         return;
@@ -4004,6 +4143,9 @@
         if (status == HCI_SUCCESS)
         {
             p_dev_rec = btm_sec_alloc_dev (bda);
+#if BLE_INCLUDED == TRUE
+            p_dev_rec->device_type |= BT_DEVICE_TYPE_BREDR;
+#endif
         }
         else
         {
@@ -4061,6 +4203,8 @@
     p_dev_rec->rs_disc_pending   = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
 #endif
 
+    p_dev_rec->rs_disc_pending   = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
+
     if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
          && (memcmp (btm_cb.pairing_bda, bda, BD_ADDR_LEN) == 0) )
     {
@@ -4208,8 +4352,6 @@
         if (btm_cb.btm_def_link_policy)
             BTM_SetLinkPolicy (p_acl_cb->remote_addr, &btm_cb.btm_def_link_policy);
 #endif
-
-        BTM_SetLinkSuperTout (p_acl_cb->remote_addr, btm_cb.btm_def_link_super_tout);
     }
     btm_acl_created (bda, p_dev_rec->dev_class, p_dev_rec->sec_bd_name, handle, HCI_ROLE_SLAVE, FALSE);
 
@@ -4338,6 +4480,8 @@
     if (!p_dev_rec)
         return;
 
+    p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
+
 #if BTM_DISC_DURING_RS == TRUE
     BTM_TRACE_ERROR0("btm_sec_disconnected - Clearing Pending flag");
     p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING;     /* reset flag */
@@ -4382,7 +4526,7 @@
 
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     p_dev_rec->enc_key_size = 0;
-    btm_ble_resume_bg_conn(NULL, TRUE);
+    btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, p_dev_rec->bd_addr, FALSE);
     /* see sec_flags processing in btm_acl_removed */
 #endif
     p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
@@ -4421,7 +4565,10 @@
         p_dev_rec->link_key_type = key_type;
 
     p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
-
+#if (BLE_INCLUDED == TRUE)
+    /* BR/EDR connection, update the encryption key size to be 16 as always */
+    p_dev_rec->enc_key_size = 16;
+#endif
     memcpy (p_dev_rec->link_key, p_link_key, LINK_KEY_LEN);
 
     if ( (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE)
@@ -5059,16 +5206,33 @@
         else
             service_id = 0;
 
-        p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
-        result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
+        /* Send authorization request if not already sent during this service connection */
+        if (p_dev_rec->last_author_service_id == BTM_SEC_NO_LAST_SERVICE_ID
+            || p_dev_rec->last_author_service_id != service_id)
+        {
+            p_dev_rec->sec_state = BTM_SEC_STATE_AUTHORIZING;
+            result = (*btm_cb.api.p_authorize_callback) (p_dev_rec->bd_addr,
                                                      p_dev_rec->dev_class,
                                                      p_dev_rec->sec_bd_name,
                                                      p_service_name,
                                                      service_id,
                                                      p_dev_rec->is_originator);
+        }
+
+        else    /* Already authorized once for this L2CAP bringup */
+        {
+            BTM_TRACE_DEBUG1 ("btm_sec_start_authorization: (Ignoring extra Authorization prompt for service %d)", service_id);
+            return (BTM_SUCCESS);
+        }
+
         if (result == BTM_SUCCESS)
         {
             p_dev_rec->sec_flags |= BTM_SEC_AUTHORIZED;
+
+            /* Save the currently authorized service in case we are asked again by another multiplexer layer */
+            if (!p_dev_rec->is_originator)
+                p_dev_rec->last_author_service_id = service_id;
+
             p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
         }
         return(result);
@@ -5088,7 +5252,7 @@
 *******************************************************************************/
 BOOLEAN btm_sec_are_all_trusted(UINT32 p_mask[])
 {
-    int trusted_inx;
+    UINT32 trusted_inx;
     for (trusted_inx = 0; trusted_inx < BTM_SEC_SERVICE_ARRAY_SIZE; trusted_inx++)
     {
         if (p_mask[trusted_inx] != BTM_SEC_TRUST_ALL)
@@ -5611,6 +5775,30 @@
 
 /*******************************************************************************
 **
+** Function         btm_sec_is_le_capable_dev
+**
+** Description       Is the specified device is dual mode or LE only device
+**
+** Returns          TRUE - dev is a dual mode
+**
+*******************************************************************************/
+BOOLEAN btm_sec_is_le_capable_dev (BD_ADDR bda)
+{
+    tBTM_SEC_DEV_REC *p_dev_rec= btm_find_dev (bda);
+    BOOLEAN le_capable = FALSE;
+
+#if (BLE_INCLUDED== TRUE)
+    if (p_dev_rec && ((p_dev_rec->device_type == BT_DEVICE_TYPE_DUMO) ||
+         (p_dev_rec->device_type == BT_DEVICE_TYPE_BLE) ) )
+    {
+        le_capable  = TRUE;
+    }
+#endif
+    return le_capable;
+}
+
+/*******************************************************************************
+**
 ** Function         btm_sec_find_bonded_dev
 **
 ** Description      Find a bonded device starting from the specified index
diff --git a/stack/btu/btu_hcif.c b/stack/btu/btu_hcif.c
index 63803bd..4aa82ef 100644
--- a/stack/btu/btu_hcif.c
+++ b/stack/btu/btu_hcif.c
@@ -150,10 +150,17 @@
 *******************************************************************************/
 static void btu_hcif_store_cmd (UINT8 controller_id, BT_HDR *p_buf)
 {
-    tHCI_CMD_CB * p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+    tHCI_CMD_CB *p_hci_cmd_cb;
     UINT16  opcode;
     BT_HDR  *p_cmd;
-    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+    UINT8   *p;
+
+    /* Validate controller ID */
+    if (controller_id >= BTU_MAX_LOCAL_CTRLS)
+        return;
+
+    p_hci_cmd_cb = &(btu_cb.hci_cmd_cb[controller_id]);
+    p = (UINT8 *)(p_buf + 1) + p_buf->offset;
 
     /* get command opcode */
     STREAM_TO_UINT16 (opcode, p);
@@ -1033,6 +1040,10 @@
             btm_read_local_features_complete (p, evt_len);
             break;
 
+        case HCI_READ_LOCAL_EXT_FEATURES:
+            btm_read_local_ext_features_complete (p, evt_len);
+            break;
+
         case HCI_READ_LOCAL_NAME:
             btm_read_local_name_complete (p, evt_len);
             break;
@@ -1075,7 +1086,7 @@
             break;
 
         case HCI_BLE_ADD_WHITE_LIST:
-            btm_ble_add_2_white_list_complete(p, evt_len);
+            btm_ble_add_2_white_list_complete(*p);
             break;
 
         case HCI_BLE_CLEAR_WHITE_LIST:
@@ -1103,6 +1114,11 @@
             btm_ble_write_adv_enable_complete(p);
             break;
 
+        case HCI_BLE_TRANSMITTER_TEST:
+        case HCI_BLE_RECEIVER_TEST:
+        case HCI_BLE_TEST_END:
+            btm_ble_test_command_complete(p);
+            break;
 #endif /* (BLE_INCLUDED == TRUE) */
 
         default:
@@ -1470,9 +1486,7 @@
     UINT8   *p;
     void    *p_cplt_cback = NULL;
     UINT16  opcode;
-// btla-specific ++
     UINT16  event;
-// btla-specific --
 
 #if (defined(BTU_CMD_CMPL_TOUT_DOUBLE_CHECK) && BTU_CMD_CMPL_TOUT_DOUBLE_CHECK == TRUE)
     if (!(p_hci_cmd_cb->checked_hcisu))
@@ -1586,10 +1600,8 @@
             }
 
             /* fake a command complete; first create a fake event */
-// btla-specific ++
             event = HCI_ERR_UNSPECIFIED;
             btu_hcif_hdl_command_complete (opcode, (UINT8 *)&event, 1, p_cplt_cback, controller_id);
-// btla-specific --
             break;
     }
 
@@ -2202,51 +2214,9 @@
     btm_ble_process_adv_pkt(p);
 }
 
-
 static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
 {
-    UINT8       role, status, bda_type;
-    UINT16      handle;
-    BD_ADDR     bda;
-    UINT16      conn_interval, conn_latency, conn_timeout;
-	UINT16      combined_mode;
-
-    STREAM_TO_UINT8   (status, p);
-    STREAM_TO_UINT16   (handle, p);
-    STREAM_TO_UINT8    (role, p);
-    STREAM_TO_UINT8    (bda_type, p);
-    STREAM_TO_BDADDR   (bda, p);
-    STREAM_TO_UINT16   (conn_interval, p);
-    STREAM_TO_UINT16   (conn_latency, p);
-    STREAM_TO_UINT16   (conn_timeout, p);
-
-    handle = HCID_GET_HANDLE (handle);
-
-    if (status == 0)
-    {
-        btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role);
-
-        l2cble_conn_comp (handle, role, bda, bda_type, conn_interval,
-                          conn_latency, conn_timeout);
-    }
-    else
-    {
-        /* If we are LE connectable, check if we need to start advertising again */
-        if (btm_cb.ble_ctr_cb.inq_var.connectable_mode != BTM_BLE_NON_CONNECTABLE)
-        {
-            tACL_CONN   *pa = &btm_cb.acl_db[0];
-            UINT16       xx;
-
-            for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
-            {
-                /* If any other LE link is up, we are still not connectable */
-                if (pa->in_use && pa->is_le_link)
-                    return;
-            }
-			combined_mode = (btm_cb.ble_ctr_cb.inq_var.connectable_mode | btm_cb.btm_inq_vars.connectable_mode);
-            btm_ble_set_connectability ( combined_mode );
-        }
-    }
+    btm_ble_conn_complete(p, evt_len);
 }
 
 static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
@@ -2267,7 +2237,7 @@
     STREAM_TO_UINT16(handle, p);
     pp = p + 8;
     STREAM_TO_UINT16(ediv, pp);
-#if SMP_INCLUDED == TRUE
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     btm_ble_ltk_request(handle, p, ediv);
 #endif
     /* This is empty until an upper layer cares about returning event */
diff --git a/stack/btu/btu_task.c b/stack/btu/btu_task.c
index 48ce489..5147518 100644
--- a/stack/btu/btu_task.c
+++ b/stack/btu/btu_task.c
@@ -169,7 +169,10 @@
 
 #if (defined(HCISU_H4_INCLUDED) && HCISU_H4_INCLUDED == TRUE)
     /* wait an event that HCISU is ready */
-    GKI_wait(0xFFFF, 0);
+    event = GKI_wait (0xFFFF, 0);
+    if (event & EVENT_MASK(GKI_SHUTDOWN_EVT))
+        /* indicates BT ENABLE abort */
+        return (0);
 #endif
     /* Initialize the mandatory core stack control blocks
        (BTU, BTM, L2CAP, and SDP)
@@ -302,6 +305,14 @@
                         GKI_freebuf (p_msg);
                         break;
 
+                    case BT_EVT_TO_STOP_TIMER:
+                        if (btu_cb.timer_queue.p_first == NULL)
+                        {
+                            GKI_stop_timer(TIMER_0);
+                        }
+                        GKI_freebuf (p_msg);
+                        break;
+
 #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
                     case BT_EVT_TO_START_QUICK_TIMER :
                         GKI_start_timer (TIMER_2, QUICK_TIMER_TICKS, TRUE);
@@ -440,10 +451,6 @@
                         btm_ble_timeout(p_tle);
                         break;
 
-                    case BTU_TTYPE_BLE_SCAN_PARAM_IDLE:
-                        btm_ble_scan_param_idle();
-                        break;
-
                     case BTU_TTYPE_ATT_WAIT_FOR_RSP:
                         gatt_rsp_timeout(p_tle);
                         break;
@@ -602,14 +609,27 @@
 *******************************************************************************/
 void btu_stop_timer (TIMER_LIST_ENT *p_tle)
 {
+    BT_HDR *p_msg;
     GKI_remove_from_timer_list (&btu_cb.timer_queue, p_tle);
 
-    /* if timer list is empty stop periodic GKI timer */
-    if (btu_cb.timer_queue.p_first == NULL)
+    /* if timer is stopped on other than BTU task */
+    if (GKI_get_taskid() != BTU_TASK)
     {
-        GKI_stop_timer(TIMER_0);
+        /* post event to stop timer in BTU task */
+        if ((p_msg = (BT_HDR *)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+        {
+            p_msg->event = BT_EVT_TO_STOP_TIMER;
+            GKI_send_msg (BTU_TASK, TASK_MBOX_0, p_msg);
+        }
     }
-
+    else
+    {
+        /* if timer list is empty stop periodic GKI timer */
+        if (btu_cb.timer_queue.p_first == NULL)
+        {
+            GKI_stop_timer(TIMER_0);
+        }
+    }
 }
 
 #if defined(QUICK_TIMER_TICKS_PER_SEC) && (QUICK_TIMER_TICKS_PER_SEC > 0)
diff --git a/stack/gap/gap_api.c b/stack/gap/gap_api.c
new file mode 100644
index 0000000..d17895d
--- /dev/null
+++ b/stack/gap/gap_api.c
@@ -0,0 +1,903 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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"
+#include "gap_int.h"
+#include "btm_int.h"
+#include "gki.h"
+#include "btu.h"
+
+/*******************************************************************************
+**
+** Function         GAP_SetDiscoverableMode
+**
+** Description      This function is called to allow or disallow a service to
+**                  discovered (Inquiry Scans).
+**
+** Parameters:      mode        - GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE,
+**                                  or GAP_GENERAL_DISCOVERABLE
+**
+**                  duration    - Amount of time for the duration of an inquiry scan.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**                                If a value of '0' is entered the default of
+**                                0x0012 (11.25 msecs) will be used.
+**                                Note: The duration must be less than or equal to
+**                                the interval.
+**
+**                  interval    - Amount of time between the start of two inquiry scans.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**                                If a value of '0' is entered the default of
+**                                0x800 (1.28 secs) will be used.
+**
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_PARM if a bad parameter is detected,
+**                  GAP_DEVICE_NOT_UP if the device is not active,
+**                  GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+    tBTM_STATUS status;
+
+    status = BTM_SetDiscoverability(mode, duration, interval);
+
+    return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ReadDiscoverableMode
+**
+** Description      This function is called to retrieve the current discoverable mode
+**                  for the local device.
+**
+** Parameters:      duration    - pointer to the amount of time of an inquiry scan.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**                  interval    - pointer to the amount of time between the start of
+**                                two inquiry scans.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns          GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+**                  GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval)
+{
+    return (BTM_ReadDiscoverability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_SetConnectableMode
+**
+** Description      This function is called to allow or disallow a
+**                  connections on the local device.
+**
+** Parameters:      mode        - GAP_NON_CONNECTABLE, GAP_CONNECTABLE,
+**
+**                  duration    - Amount of time for the duration of a page scan.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**                                If a value of '0' is entered the default of
+**                                0x0012 (11.25 msecs) will be used.
+**                                Note: The duration must be less than or equal to
+**                                the interval.
+**
+**                  interval    - Amount of time between the start of two page scans.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**                                If a value of '0' is entered the default of
+**                                0x800 (1.28 secs) will be used.
+**
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_PARM if a bad parameter is detected,
+**                  GAP_DEVICE_NOT_UP if the device is not active,
+**                  GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration, UINT16 interval)
+{
+    tBTM_STATUS status;
+
+    status = BTM_SetConnectability(mode, duration, interval);
+
+    return (gap_convert_btm_status (status));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_FindAddrByName
+**
+** Description      This function is called to retrieve a device address given
+**                  a device name.  It first looks in the current local inquiry
+**                  database for the device with the specified name.  If not found
+**                  it initiates a general inquiry.  Upon completion, it retrieves
+**                  the name for each device until a match is found or all devices
+**                  have been checked.  Note:  This process can take a while to
+**                  complete.
+**
+** Parameters:      devname -
+**
+**                  inqparms - pointer to the inquiry information
+**                      mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+**                      duration - length in 1.28 sec intervals
+**                      max_resps - maximum amount of devices to search for before ending the inquiry
+**                      filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+**                                         GAP_FILTER_COND_BD_ADDR
+**                      filter_cond - value for the filter (based on filter_cond_type)
+**
+**
+** Returns          BT_PASS if the name was immediately available.  (BD_ADDR is returned)
+**                  GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+UINT16 GAP_FindAddrByName (BD_NAME devname, tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_addr_cb,
+                           BD_ADDR bd_addr)
+{
+    UINT16           status;
+    tBTM_STATUS      btm_status;
+
+
+    /* If the remote name is retrieved automatically during an inquiry search the local db first */
+    if ((status = gap_find_local_addr_by_name (devname, bd_addr)) != BT_PASS)
+    {
+        /* If this code is used, the name wasn't in the current inquiry database */
+        /* A general inquiry must now be initiated */
+        if (gap_cb.findaddr_cb.in_use == FALSE)
+        {
+            gap_cb.findaddr_cb.p_cback = p_addr_cb;
+            gap_cb.findaddr_cb.p_cur_inq = (tBTM_INQ_INFO *) NULL;     /* Reset to the beginning of the database */
+            BCM_STRNCPY_S ((char *)gap_cb.findaddr_cb.results.devname, sizeof(gap_cb.findaddr_cb.results.devname), (char *)devname, BTM_MAX_REM_BD_NAME_LEN);
+
+            /* make sure we have an end of string char */
+            gap_cb.findaddr_cb.results.devname[BTM_MAX_REM_BD_NAME_LEN] = 0;
+
+            btm_status = BTM_StartInquiry (p_inq_parms, (tBTM_INQ_RESULTS_CB *) NULL,
+                    (tBTM_CMPL_CB *) gap_find_addr_inq_cb);
+                gap_cb.findaddr_cb.in_use = TRUE;
+
+            /* convert the error code into a GAP code and check the results for any errors */
+            if ((status = gap_convert_btm_status (btm_status)) == GAP_CMD_INITIATED)
+                gap_cb.findaddr_cb.in_use = TRUE;
+        }
+        else
+            status = GAP_ERR_BUSY;
+    }
+
+    return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ReadConnectableMode
+**
+** Description      This function is called to retrieve the current connectability
+**                  mode for the local device.
+**
+** Parameters:      duration    - pointer to the amount of time of an page scan.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**                  interval    - pointer to the amount of time between the start of
+**                                two page scans.
+**                                The step size is in 0.625 msec intervals.
+**                                Range: 0x0012 - 0x1000 (11.25 - 2560 msecs)
+**
+**
+** Returns          GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval)
+{
+    return (BTM_ReadConnectability(duration, interval));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_SetSecurityMode
+**
+** Description      Set security mode for the device
+**
+** Returns          void
+**
+*******************************************************************************/
+void GAP_SetSecurityMode (UINT8 sec_mode)
+{
+    BTM_SetSecurityMode (sec_mode);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_Bond
+**
+** Description      This function is called to perform bonding with peer device
+**
+** Parameters:      bd_addr      - Address of the device to bond
+**                  pin_len      - length in bytes of the PIN Code
+**                  p_pin        - pointer to array with the PIN Code
+**                  trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+    return ((UINT8) BTM_SecBond (bd_addr, pin_len, p_pin, trusted_mask));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_SecRegister
+**
+** Description      Application manager calls this function to register for
+**                  security services.  There can be one and only one application
+**                  saving link keys.  BTM allows only first registration.
+**
+** Returns          TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+BOOLEAN  GAP_SecRegister (tBTM_APPL_INFO *p_cb_info)
+{
+    return (BTM_SecRegister (p_cb_info));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_PinRsp
+**
+** Description      This function is called from UI after Security Manager submitted
+**                  PIN code request.
+**
+** Parameters:      bd_addr      - Address of the device for which PIN was requested
+**                  res          - result of the operation BTM_SUCCESS if success
+**                  pin_len      - length in bytes of the PIN Code
+**                  p_pin        - pointer to array with the PIN Code
+**                  trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[])
+{
+    BTM_PINCodeReply (bd_addr, res, pin_len, p_pin, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_AuthorizeRsp
+**
+** Description      This function is called from UI after Security Manager submitted
+**                  authorization request
+**
+** Parameters:      bd_addr      - Address of the device for which PIN was requested
+**                  res          - result of the operation BTM_SUCCESS if success
+**                  trusted_mask - bitwise OR of trusted services (array of UINT32)
+**
+*******************************************************************************/
+void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res, UINT32 trusted_mask[])
+{
+    BTM_DeviceAuthorized (bd_addr, res, trusted_mask);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_SetPairableMode
+**
+** Description      This function is called to allow or disallow pairing
+**                  on the local device.
+**
+** Parameters:      mode        - GAP_ALLOW_PAIRING, GAP_DISALLOW_PAIRING
+**                  connect_only_pairable - TRUE or FALSE connect only to paired devices
+**
+**                  callback    - The callback is called when a pin number is requested.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired)
+{
+    tBTM_STATUS btm_status;
+    UINT16      status = BT_PASS;
+
+    if (mode == GAP_ALLOW_PAIRING)
+    {
+        btm_status = BTM_SetConnectability(BTM_CONNECTABLE, 0, 0);
+
+        if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+            BTM_SetPairableMode (TRUE, connect_only_paired);
+    }
+    else if (mode == GAP_DISALLOW_PAIRING)
+    {
+        BTM_SetPairableMode (FALSE, connect_only_paired);
+    }
+    else
+    {
+        GAP_TRACE_ERROR1 ("GAP_SetPairableMode: illegal mode %d", mode);
+        status = GAP_ERR_ILL_MODE;
+    }
+    return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_StartInquiry
+**
+** Description      This function initiates a single inquiry.
+**
+** Parameters:      p_inqparms - pointer to the inquiry information
+**                      mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+**                      duration - length in 1.28 sec intervals
+**                      max_resps - maximum amount of devices to search for before ending the inquiry
+**                      filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+**                                         GAP_FILTER_COND_BD_ADDR
+**                      filter_cond - value for the filter (based on filter_cond_type)
+**
+**                  p_results_cb - Pointer to the callback routine which gets called
+**                                 upon receipt of an inquiry result. If this field is
+**                                 NULL, the application is not notified.
+**
+**                  p_cmpl_cb   - Pointer to the callback routine which gets called
+**                                upon completion.  If this field is NULL, the
+**                                application is not notified when completed.
+**
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_MODE if a bad mode parameter was passed
+**                  GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks
+**                  GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+**                  GAP_ERR_BUSY if the device already has an iquiry active
+**                  GAP_DEVICE_NOT_UP if the device is not initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms, tGAP_CALLBACK *p_results_cb, tGAP_CALLBACK *p_cmpl_cb)
+{
+    tGAP_INFO   *p_cb;
+    tBTM_STATUS  btm_status;
+    UINT16       retval;
+
+    /*** Make sure the parameters are valid before continuing ***/
+    if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+        return (GAP_ERR_ILL_MODE);
+
+    if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN   ||
+        p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH)
+        return (GAP_ERR_ILL_INQ_TIME);
+
+    /*** get a control block for this operation ***/
+    if ((p_cb = gap_allocate_cb()) != NULL)
+    {
+        p_cb->gap_cback = p_cmpl_cb;
+        p_cb->gap_inq_rslt_cback = p_results_cb;
+        p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* Return event expected */
+
+        btm_status = BTM_StartInquiry(p_inq_parms, gap_inq_results_cb,
+                        (tBTM_CMPL_CB *) gap_cb.btm_cback[p_cb->index]);
+
+        /* convert the error code into a GAP code and check the results for any errors */
+        if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+            gap_free_cb(p_cb);      /* Error starting the inquiry */
+    }
+    else
+        retval = GAP_ERR_NO_CTRL_BLK;
+
+    return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_StartPeriodicInquiry
+**
+** Description      This function initiates a periodic inquiry.
+**
+** Parameters:      p_inqparms - pointer to the inquiry information
+**                      mode - GAP_GENERAL_INQUIRY or GAP_LIMITED_INQUIRY inquiry
+**                      duration - length in 1.28 sec intervals
+**                      max_resps - maximum amount of devices to search for before ending the inquiry
+**                      filter_cond_type - GAP_CLR_INQUIRY_FILTER, GAP_FILTER_COND_DEVICE_CLASS, or
+**                                         GAP_FILTER_COND_BD_ADDR
+**                      filter_cond - value for the filter (based on filter_cond_type)
+**
+**                  min_time    - Minimum amount of time between consecutive inquiries.
+**                                The value is in 1.28 second intervals.
+**                                Range: 0x0002 - 0xFFFE (2.56 - 83883.52 seconds)
+**
+**                  max_time    - Maximum amount of time between consecutive inquiries.
+**                                The value is in 1.28 sec intervals.
+**                                Range: 0x0003 - 0xFFFF (3.84 - 83884.8 seconds)
+**
+**                  p_results_cb - Pointer to the callback routine which gets called
+**                                 upon receipt of an inquiry result. If this field is
+**                                 NULL, the application is not notified.
+**
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_MODE if a bad mode parameter was passed
+**                  GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks
+**                  GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+**                  GAP_ERR_BUSY if the device already has an iquiry active
+**                  GAP_DEVICE_NOT_UP if the device is not initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+
+UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms, UINT16 min_time,
+                                 UINT16 max_time, tGAP_CALLBACK *p_results_cb)
+{
+    tGAP_INFO   *p_cb;
+    tBTM_STATUS  btm_status;
+    UINT16       retval = BT_PASS;
+
+    /*** Make sure the parameters are valid before continuing ***/
+    if (p_inq_parms->mode != GAP_GENERAL_INQUIRY && p_inq_parms->mode != GAP_LIMITED_INQUIRY)
+        return (GAP_ERR_ILL_MODE);
+
+    if (p_inq_parms->duration < GAP_MIN_INQUIRY_LEN     ||
+        p_inq_parms->duration > GAP_MAX_INQUIRY_LENGTH  ||
+        min_time <= p_inq_parms->duration               ||
+        min_time < GAP_PER_INQ_MIN_MIN_PERIOD           ||
+        min_time > GAP_PER_INQ_MAX_MIN_PERIOD           ||
+        max_time <= min_time                            ||
+        max_time < GAP_PER_INQ_MIN_MAX_PERIOD)
+    {
+        return (GAP_ERR_ILL_INQ_TIME);
+    }
+
+    /*** get a control block for this operation ***/
+    if ((p_cb = gap_allocate_cb()) != NULL)
+    {
+        p_cb->gap_inq_rslt_cback = p_results_cb;
+        p_cb->event = GAP_EVT_INQUIRY_COMPLETE; /* mark the inquiry event active */
+
+        btm_status = BTM_SetPeriodicInquiryMode(p_inq_parms, max_time, min_time,
+                                                gap_inq_results_cb);
+
+        /* convert the error code into a GAP code and check the results for any errors */
+        if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+            gap_free_cb(p_cb);      /* Error starting the inquiry */
+    }
+    else
+        retval = GAP_ERR_NO_CTRL_BLK;
+
+    return (retval);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_CancelInquiry
+**
+** Description      This function cancels a single inquiry (if in progress)
+**
+** Parameters:      None
+**
+** Returns          BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelInquiry(void)
+{
+    tGAP_INFO   *p_cb = &gap_cb.blk[0];
+    UINT8        x;
+    tBTM_STATUS  btm_status;
+    UINT16       status;
+
+    btm_status = BTM_CancelInquiry();
+    if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+    {
+        /* Free the control block that is waiting for the inquiry complete event */
+        for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+        {
+            if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+            {
+                gap_free_cb(p_cb);
+                return (BT_PASS);
+            }
+        }
+
+        /* If here the control block was not found */
+        status = GAP_ERR_NO_CTRL_BLK;
+    }
+
+    return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_CancelPeriodicInquiry
+**
+** Description      This function cancels a periodic inquiry (if in progress)
+**
+** Parameters:      None
+**
+** Returns          BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+UINT16 GAP_CancelPeriodicInquiry(void)
+{
+    tGAP_INFO   *p_cb = &gap_cb.blk[0];
+    UINT8        x;
+    tBTM_STATUS  btm_status;
+    UINT16       status;
+
+    btm_status = BTM_CancelPeriodicInquiry();
+    if ((status = gap_convert_btm_status (btm_status)) == BT_PASS)
+    {
+        /* Free the control block that is waiting for the inquiry complete event */
+        for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+        {
+            if (p_cb->in_use && p_cb->event == GAP_EVT_INQUIRY_COMPLETE)
+            {
+                gap_free_cb(p_cb);
+                return (BT_PASS);
+            }
+        }
+
+        /* If here the control block was not found */
+        status = GAP_ERR_NO_CTRL_BLK;
+    }
+
+    return (status);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_GetFirstInquiryResult
+**
+** Description      This function retrieves the first valid inquiry result.
+**
+** Parameters:      p_results - pointer to the inquiry results
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**                  GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+    UINT8 *ptr;
+
+    gap_cb.cur_inqptr = BTM_InqFirstResult();
+
+    if (gap_cb.cur_inqptr != NULL)
+    {
+        memcpy(p_results, &gap_cb.cur_inqptr->results, sizeof(tBTM_INQ_RESULTS));
+
+        ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+        GAP_TRACE_EVENT6("GAP_GetFirstInqResult %02x%02x%02x%02x%02x%02x",
+                    ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+        return(BT_PASS);
+    }
+    else
+    {
+        GAP_TRACE_EVENT0("GAP_FirstInqResults:  No BD_ADDRs Found");
+        memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+        return(GAP_EOINQDB);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_GetNextInquiryResult
+**
+** Description      This function retrieves the next valid inquiry result.
+**
+** Parameters:      p_results  - pointer to the inquiry results
+**
+** Returns          BT_PASS (0) if successful, or a non-zero status code
+**                  GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results)
+{
+    UINT8 *ptr;
+
+    /*** if the current inquiry db pointer is NULL then call the first entry ***/
+    if (gap_cb.cur_inqptr)
+    {
+        gap_cb.cur_inqptr = BTM_InqNextResult(gap_cb.cur_inqptr);
+        if (gap_cb.cur_inqptr != NULL)
+        {
+            memcpy(p_results, &gap_cb.cur_inqptr->results,
+                   sizeof(tGAP_INQ_RESULTS));
+
+            ptr = (UINT8 *)gap_cb.cur_inqptr->results.remote_bd_addr;
+            GAP_TRACE_EVENT6("GAP_GetNextInqResult %02x%02x%02x%02x%02x%02x",
+                        ptr[0],ptr[1],ptr[2],ptr[3],ptr[4],ptr[5]);
+
+            return(BT_PASS);
+        }
+        else
+        {
+            GAP_TRACE_EVENT0("GAP_NextInqResults:  No BD_ADDRs Found");
+            memset(p_results, 0, sizeof(tBTM_INQ_RESULTS));
+            return(GAP_EOINQDB);
+        }
+    }
+    else
+        return (GAP_GetFirstInquiryResult(p_results));
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ReadLocalDeviceInfo
+**
+** Description      This function retrieves local device information to the caller.
+**
+** Parameters:      name        - (output) pointer to the UTF-8 encoded string representing
+**                                the device name.
+**
+**                  addr        - (output) pointer to the Bluetooth device address (BD_ADDR).
+**
+**                  verinfo     - (output) pointer to the LMP version information.
+**
+**                  features    - (output) pointer to the LMP features for the device.
+**
+**                  NOTE:  Return parameters that are set to NULL are not retrieved.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+
+UINT16 GAP_ReadLocalDeviceInfo(UINT8 *name, BD_ADDR *addr, tGAP_LMP_VERSION *verinfo,
+                               tGAP_LMP_FEATURES *features)
+{
+    return (GAP_UNSUPPORTED);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         GAP_GetRemoteDeviceName
+**
+** Description      The remote name is retrieved from the specified remote device.  If
+**                  GAP_CMD_INITIATED is returned by the function, the command was
+**                  successfully sent to the controller.  The GAP_EVT_NAME_RESP event
+**                  is passed in the callback when the remote device name has been retrieved.
+**
+** Parameters:      addr        - The Bluetooth device address (BD_ADDR) of the remote
+**                                device.
+**
+**                  callback    - pointer to the callback which is called after the
+**                                remote device has been retrieved.
+**                                p_data in the callback points to the structure containing the
+**                                status, device name length, and the UTF-8 encoded
+**                                device name. (type tBTM_REMOTE_DEV_NAME)
+**                                The event field in the callback is set to GAP_EVT_REM_NAME_COMPLETE.
+**  The callback is not called unless (GAP_CMD_INITIATED) is returned.
+**
+**
+** Returns
+**                  GAP_CMD_INITIATED if remote search successfully initiated
+**                  GAP_ERR_BUSY if a remote name request is already in progress,
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+**                  GAP_BAD_BD_ADDR if the device address is bad,
+**                  GAP_DEVICE_NOT_UP if the device has not been initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback)
+{
+    tGAP_INFO   *p_cb;
+    UINT16       retval;
+    tBTM_STATUS  btm_status;
+
+    if ((p_cb = gap_allocate_cb()) != NULL)
+    {
+        p_cb->gap_cback = callback;
+        p_cb->event = GAP_EVT_REM_NAME_COMPLETE;     /* Return event expected */
+
+        btm_status = BTM_ReadRemoteDeviceName (addr, gap_cb.btm_cback[p_cb->index]);
+
+        /* If the name was not returned immediately, or if an error occurred, release the control block */
+        if ((retval = gap_convert_btm_status (btm_status)) != GAP_CMD_INITIATED)
+            gap_free_cb (p_cb);
+    }
+    else
+        retval = GAP_ERR_NO_CTRL_BLK;
+
+    return (retval);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_SetDeviceClass
+**
+** 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.
+**                            GAP_SET_COD_MAJOR_MINOR, - overwrite major, minor class
+**                            GAP_SET_COD_SERVICE_CLASS - set the bits in the input
+**                            GAP_CLR_COD_SERVICE_CLASS - clear the bits in the input
+**                            GAP_SET_COD_ALL - overwrite major, minor, set the bits in service class
+**                            GAP_INIT_COD - overwrite major, minor, and service class
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_BUSY if a discovery is already in progress
+**                  GAP_ERR_ILL_PARM if an illegal parameter was detected
+**                  GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd)
+{
+    tBTM_STATUS btm_status;
+    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 GAP_SET_COD_MAJOR_MINOR:
+        minor = p_cod->minor & BTM_COD_MINOR_CLASS_MASK;
+        major = p_cod->major & BTM_COD_MAJOR_CLASS_MASK;
+        break;
+
+    case GAP_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 GAP_CLR_COD_SERVICE_CLASS:
+        p_cod->service &= BTM_COD_SERVICE_CLASS_MASK;
+        service = service & (~p_cod->service);
+        break;
+
+    case GAP_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 GAP_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 GAP_ERR_ILL_PARM;
+    }
+
+    /* convert the fields into the device class type */
+    FIELDS_TO_COD(dev_class, minor, major, service);
+
+    btm_status = BTM_SetDeviceClass(dev_class);
+    return (gap_convert_btm_status (btm_status));
+}
+
+/*******************************************************************************
+**
+** Function         GAP_ReadDeviceClass
+**
+** Description      This function reads the local Device Class.
+**
+** Parameters:
+**
+** Returns          PASS
+**
+*******************************************************************************/
+UINT16   GAP_ReadDeviceClass(tGAP_COD *p_cod)
+{
+    UINT8 *dev;
+
+    dev = BTM_ReadDeviceClass();
+
+    BTM_COD_SERVICE_CLASS( p_cod->service, dev );
+    BTM_COD_MINOR_CLASS( p_cod->minor, dev );
+    BTM_COD_MAJOR_CLASS( p_cod->major, dev );
+
+    return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_SetTraceLevel
+**
+** Description      This function sets the trace level for GAP.  If called with
+**                  a value of 0xFF, it simply returns the current trace level.
+**
+** Returns          The new or current trace level
+**
+*******************************************************************************/
+UINT8 GAP_SetTraceLevel (UINT8 new_level)
+{
+    if (new_level != 0xFF)
+        gap_cb.trace_level = new_level;
+
+    return (gap_cb.trace_level);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_Init
+**
+** Description      Initializes the control blocks used by GAP.
+**
+**                  This routine should not be called except once per
+**                      stack invocation.
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+void GAP_Init(void)
+{
+    memset (&gap_cb, 0, sizeof (tGAP_CB));
+
+    /*** Initialize the callbacks for BTM; Needs to be one per GAP_MAX_BLOCKS ***/
+    gap_cb.btm_cback[0] = gap_btm_cback0;
+#if GAP_MAX_BLOCKS > 1
+    gap_cb.btm_cback[1] = gap_btm_cback1;
+#endif
+#if GAP_MAX_BLOCKS > 2
+    gap_cb.btm_cback[2] = gap_btm_cback2;
+#endif
+
+#if defined(GAP_INITIAL_TRACE_LEVEL)
+    gap_cb.trace_level = GAP_INITIAL_TRACE_LEVEL;
+#else
+    gap_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
+#endif
+
+    /* Initialize the connection control block if included in build */
+#if GAP_CONN_INCLUDED == TRUE
+    gap_conn_init();
+#endif  /* GAP_CONN_INCLUDED */
+
+#if BLE_INCLUDED == TRUE
+    gap_attr_db_init();
+#endif
+}
+
diff --git a/stack/gap/gap_ble.c b/stack/gap/gap_ble.c
new file mode 100644
index 0000000..19e24a9
--- /dev/null
+++ b/stack/gap/gap_ble.c
@@ -0,0 +1,967 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 "bt_target.h"
+
+#if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
+
+#include <string.h>
+#include "gap_int.h"
+#include "gap_api.h"
+#include "gattdefs.h"
+#include "gatt_api.h"
+#include "gatt_int.h"
+#include "btm_int.h"
+#include "hcimsgs.h"
+
+#define GAP_CHAR_ICON_SIZE          2
+#define GAP_CHAR_DEV_NAME_SIZE      248
+#define GAP_BLE_PRIVACY_FLAG_SIZE    1
+
+#define GAP_MAX_NUM_INC_SVR       0
+#define GAP_MAX_ATTR_NUM          (2 * GAP_MAX_CHAR_NUM + GAP_MAX_NUM_INC_SVR + 1)
+#define GAP_MAX_CHAR_VALUE_SIZE   (30 + GAP_CHAR_DEV_NAME_SIZE)
+
+
+#ifndef GAP_ATTR_DB_SIZE
+#define GAP_ATTR_DB_SIZE      GATT_DB_MEM_SIZE(GAP_MAX_NUM_INC_SVR, GAP_MAX_CHAR_NUM, GAP_MAX_CHAR_VALUE_SIZE)
+#endif
+
+/* privacy flag readable and writable with encryption on */
+#ifndef GAP_BLE_PRIVACY_FLAG_PERM
+#define GAP_BLE_PRIVACY_FLAG_PERM       (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#define GATT_READ_GAP_PRIVACY_FLAG      1
+#define GATT_SET_GAP_PRIVACY_FLAG       2
+#define GATT_READ_GAP_REMOTE_NAME       3
+#define GATT_UPDATE_RECONN_ADDR         4
+
+#define GAP_BLE_PRIVACY_UNKNOWN         0xff
+
+static void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id, tGATTS_REQ_TYPE op_code, tGATTS_DATA *p_data);
+
+/* client connection callback */
+static void  gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id, BOOLEAN connected, tGATT_DISCONN_REASON reason);
+static void  gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data);
+
+static tGATT_CBACK gap_cback =
+{
+    gap_ble_c_connect_cback,
+    gap_ble_c_cmpl_cback,
+    NULL,
+    NULL,
+    gap_ble_s_attr_request_cback
+};
+
+
+
+/*******************************************************************************
+**
+** Function         gap_find_clcb_by_bd_addr
+**
+** Description      The function searches all LCB with macthing bd address
+**
+** Returns          total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_clcb_by_bd_addr(BD_ADDR bda)
+{
+    UINT8 i_clcb;
+    tGAP_CLCB    *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+    {
+        if (p_clcb->in_use && !memcmp(p_clcb->bda, bda, BD_ADDR_LEN))
+        {
+            return p_clcb;
+        }
+    }
+
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_find_clcb_by_conn_id
+**
+** Description      The function searches all LCB with macthing connection ID
+**
+** Returns          total number of clcb found.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id)
+{
+    UINT8 i_clcb;
+    tGAP_CLCB    *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+    {
+        if (p_clcb->in_use && p_clcb->connected && p_clcb->conn_id == conn_id)
+        {
+            return p_clcb;
+        }
+    }
+
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         gap_clcb_alloc
+**
+** Description      The function allocates a GAP  connection link control block
+**
+** Returns           NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+{
+    UINT8         i_clcb = 0;
+    tGAP_CLCB    *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+    {
+        if (!p_clcb->in_use)
+        {
+            p_clcb->in_use      = TRUE;
+            p_clcb->conn_id     = conn_id;
+            p_clcb->connected   = TRUE;
+            memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+            break;
+        }
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         gap_find_alloc_clcb
+**
+** Description      The function find or allocates a GAP  connection link control block
+**
+** Returns           NULL if not found. Otherwise pointer to the connection link block.
+**
+*******************************************************************************/
+tGAP_CLCB *gap_find_alloc_clcb (UINT16 conn_id, BD_ADDR bda)
+{
+    UINT8         i_clcb = 0;
+    tGAP_CLCB    *p_clcb = NULL;
+
+    for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+    {
+        if (!p_clcb->in_use)
+        {
+            p_clcb->in_use      = TRUE;
+            p_clcb->conn_id     = conn_id;
+            p_clcb->connected   = TRUE;
+            memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
+            break;
+        }
+    }
+    return p_clcb;
+}
+
+/*******************************************************************************
+**
+** Function         gap_get_conn_id_if_connected
+**
+** Description      This function returns a connecttion handle to a ATT server
+**                  if the server is already connected
+**
+** Parameters       client_if: client interface.
+**                  bd_addr: peer device address.
+**
+** Returns          Connection handle or invalid handle value
+**
+*******************************************************************************/
+UINT16 gap_get_conn_id_if_connected (BD_ADDR bd_addr)
+{
+    tGAP_CLCB       *p_clcb;
+    UINT16          i;
+
+    GAP_TRACE_EVENT2 ("gap_get_conn_id_if_connected() - BDA: %08x%04x ",
+                      (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+                      (bd_addr[4]<<8)+bd_addr[5]);
+
+    for (i = 0, p_clcb = gap_cb.clcb; i < GAP_MAX_CL; i++, p_clcb++)
+    {
+        if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bd_addr,  BD_ADDR_LEN) )
+        {
+            return(p_clcb->conn_id);
+        }
+    }
+
+    /* If here, failed to allocate a client control block */
+    GATT_TRACE_DEBUG0 ("gap_get_conn_id_if_connected: not connected");
+    return(GATT_INVALID_CONN_ID);
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_enqueue_op
+**
+** Description      enqueue a GAP operation when GAP client is busy
+**
+** Returns          void
+**
+*******************************************************************************/
+void gap_ble_enqueue_op( tGAP_CLCB * p_clcb, UINT8 op, BD_ADDR reconn_addr, UINT8 privacy_flag, void *p_cback)
+{
+    tGAP_BLE_PENDING_OP  *p_op = (tGAP_BLE_PENDING_OP *)GKI_getbuf(sizeof(tGAP_BLE_PENDING_OP));
+
+    if (p_op != NULL)
+    {
+        p_op->op = op;
+        p_op->p_pending_cback = p_cback;
+
+        if (op == GATT_SET_GAP_PRIVACY_FLAG)
+            p_op->pending_data.privacy_flag = privacy_flag;
+        else if (op == GATT_UPDATE_RECONN_ADDR)
+            memcpy(p_op->pending_data.reconn_addr, reconn_addr, BD_ADDR_LEN);
+
+        GKI_enqueue(&p_clcb->pending_op_q, p_op);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_process_pending_op
+**
+** Description      get next pending operation and process it
+**
+** Returns          void
+**
+*******************************************************************************/
+static BOOLEAN gap_ble_process_pending_op(tGAP_CLCB *p_clcb)
+{
+    tGAP_BLE_PENDING_OP *p_pending_op = (tGAP_BLE_PENDING_OP *)GKI_dequeue(&p_clcb->pending_op_q);
+    BOOLEAN         started = FALSE;
+
+    if (p_pending_op != NULL)
+    {
+        if (p_pending_op->op == GATT_UPDATE_RECONN_ADDR)
+        {
+            GAP_BleUpdateReconnectAddr( p_clcb->bda,
+                                        p_pending_op->pending_data.reconn_addr,
+                                        (tGAP_BLE_RECONN_ADDR_CBACK *)p_pending_op->p_pending_cback);
+            started = TRUE;
+        }
+        GKI_freebuf(p_pending_op);
+    }
+    else
+    {
+        GAP_TRACE_EVENT0("No pending operation");
+    }
+
+    return started;
+}
+
+/*******************************************************************************
+**   GAP Attributes Database Request callback
+*******************************************************************************/
+tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN is_long)
+{
+    tGAP_ATTR   *p_db_attr = gap_cb.gatt_attr;
+    UINT8       *p = p_value->value, i;
+    UINT16      offset = p_value->offset;
+    UINT8       *p_dev_name = NULL;
+
+    for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+    {
+        if (handle == p_db_attr->handle)
+        {
+            if (p_db_attr->uuid != GATT_UUID_GAP_DEVICE_NAME &&
+                is_long == TRUE)
+                return GATT_NOT_LONG;
+
+            switch (p_db_attr->uuid)
+            {
+                case GATT_UUID_GAP_DEVICE_NAME:
+                    BTM_ReadLocalDeviceName((char **)&p_dev_name);
+                    if (strlen ((char *)p_dev_name) > GATT_MAX_ATTR_LEN)
+                        p_value->len = GATT_MAX_ATTR_LEN;
+                    else
+                        p_value->len = (UINT16)strlen ((char *)p_dev_name);
+
+                    if (offset > p_value->len)
+                        return GATT_INVALID_OFFSET;
+                    else
+                    {
+                        p_value->len -= offset;
+                        p_dev_name += offset;
+                        ARRAY_TO_STREAM(p, p_dev_name, p_value->len);
+                        GAP_TRACE_EVENT1("GATT_UUID_GAP_DEVICE_NAME len=0x%04x", p_value->len);
+                    }
+                    break;
+
+                case GATT_UUID_GAP_ICON:
+                    UINT16_TO_STREAM(p, p_db_attr->attr_value.icon);
+                    p_value->len = 2;
+                    break;
+
+                case GATT_UUID_GAP_PRIVACY_FLAG:
+                    UINT8_TO_STREAM(p, p_db_attr->attr_value.privacy);
+                    p_value->len = 1;
+                    break;
+
+                case GATT_UUID_GAP_RECONN_ADDR:
+                    p_value->len = BD_ADDR_LEN;
+                    BDADDR_TO_STREAM(p, p_db_attr->attr_value.reconn_bda);
+                    break;
+
+                case GATT_UUID_GAP_PREF_CONN_PARAM:
+                    UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_min); /* int_min */
+                    UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.int_max); /* int_max */
+                    UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.latency); /* latency */
+                    UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout);  /* sp_tout */
+                    p_value->len =8;
+                    break;
+            }
+            return GATT_SUCCESS;
+        }
+    }
+    return GATT_NOT_FOUND;
+}
+
+/*******************************************************************************
+**   GAP Attributes Database Read/Read Blob Request process
+*******************************************************************************/
+tGATT_STATUS gap_proc_read (tGATTS_REQ_TYPE type, tGATT_READ_REQ *p_data, tGATTS_RSP *p_rsp)
+{
+    tGATT_STATUS    status = GATT_NO_RESOURCES;
+
+    if (p_data->is_long)
+        p_rsp->attr_value.offset = p_data->offset;
+
+    p_rsp->attr_value.handle = p_data->handle;
+
+    status = gap_read_attr_value(p_data->handle, &p_rsp->attr_value, p_data->is_long);
+
+    return status;
+}
+BOOLEAN gap_read_local_reconn_addr(BD_ADDR_PTR reconn_bda)
+{
+    BD_ADDR dummy_bda = {0};
+
+    if (memcmp(gap_cb.reconn_bda, dummy_bda, BD_ADDR_LEN) != 0)
+    {
+        memcpy(reconn_bda, gap_cb.reconn_bda, BD_ADDR_LEN);
+        return TRUE;
+    }
+    else
+        return FALSE;
+}
+
+/******************************************************************************
+**
+** Function         gap_proc_write_req
+**
+** Description      GAP ATT server process a write request.
+**
+** Returns          void.
+**
+*******************************************************************************/
+UINT8 gap_proc_write_req( tGATTS_REQ_TYPE type, tGATT_WRITE_REQ *p_data)
+{
+    tGAP_ATTR   *p_db_attr = gap_cb.gatt_attr;
+    UINT8   i;
+
+    for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+    {
+        if (p_data-> handle == p_db_attr->handle)
+        {
+            if (p_data->offset != 0) return GATT_NOT_LONG;
+            if (p_data->is_prep) return GATT_REQ_NOT_SUPPORTED;
+
+/* DO NOT SUPPORT RECONNECTION ADDRESS FOR NOW
+
+            if (p_db_attr->uuid == GATT_UUID_GAP_RECONN_ADDR)
+            {
+                if (!btm_cb.ble_ctr_cb.privacy)
+                    return GATT_WRITE_NOT_PERMIT;
+                if (p_data->len != BD_ADDR_LEN) return GATT_INVALID_ATTR_LEN;
+
+                STREAM_TO_BDADDR(p_db_attr->attr_value.reconn_bda, p);
+                // write direct connection address
+                memcpy(&gap_cb.reconn_bda, p_db_attr->attr_value.reconn_bda, BD_ADDR_LEN);
+
+                return GATT_SUCCESS;
+            }
+            else
+*/
+            return GATT_WRITE_NOT_PERMIT;
+        }
+    }
+    return GATT_NOT_FOUND;
+
+}
+
+/******************************************************************************
+**
+** Function         gap_ble_s_attr_request_cback
+**
+** Description      GAP ATT server attribute access request callback.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void gap_ble_s_attr_request_cback (UINT16 conn_id, UINT32 trans_id,
+                                   tGATTS_REQ_TYPE type, tGATTS_DATA *p_data)
+{
+    UINT8       status = GATT_INVALID_PDU;
+    tGATTS_RSP  rsp_msg;
+    BOOLEAN     ignore = FALSE;
+
+    GAP_TRACE_EVENT1("gap_ble_s_attr_request_cback : recv type (0x%02x)", type);
+
+    memset(&rsp_msg, 0, sizeof(tGATTS_RSP));
+
+    switch (type)
+    {
+        case GATTS_REQ_TYPE_READ:
+            status = gap_proc_read(type, &p_data->read_req, &rsp_msg);
+            break;
+
+        case GATTS_REQ_TYPE_WRITE:
+            if (!p_data->write_req.need_rsp)
+                ignore = TRUE;
+
+            status = gap_proc_write_req(type, &p_data->write_req);
+            break;
+
+        case GATTS_REQ_TYPE_WRITE_EXEC:
+            ignore = TRUE;
+            GAP_TRACE_EVENT0("Ignore GATTS_REQ_TYPE_WRITE_EXEC"  );
+            break;
+
+        case GATTS_REQ_TYPE_MTU:
+            GAP_TRACE_EVENT1("Get MTU exchange new mtu size: %d", p_data->mtu);
+            ignore = TRUE;
+            break;
+
+        default:
+            GAP_TRACE_EVENT1("Unknown/unexpected LE GAP ATT request: 0x%02x", type);
+            break;
+    }
+
+    if (!ignore)
+        GATTS_SendRsp (conn_id, trans_id, status, &rsp_msg);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_att_db_init
+**
+** Description      GAP ATT database initalization.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void gap_attr_db_init(void)
+{
+    tBT_UUID        app_uuid = {LEN_UUID_128,{0}};
+    tBT_UUID        uuid     = {LEN_UUID_16,{UUID_SERVCLASS_GAP_SERVER}};
+    UINT16          service_handle;
+    tGAP_ATTR       *p_db_attr = &gap_cb.gatt_attr[0];
+    tGATT_STATUS    status;
+
+    /* Fill our internal UUID with a fixed pattern 0x82 */
+    memset (&app_uuid.uu.uuid128, 0x82, LEN_UUID_128);
+    memset(gap_cb.gatt_attr, 0, sizeof(tGAP_ATTR) *GAP_MAX_CHAR_NUM);
+
+    gap_cb.gatt_if = GATT_Register(&app_uuid, &gap_cback);
+
+    GATT_StartIf(gap_cb.gatt_if);
+
+    /* Create a GAP service */
+    service_handle = GATTS_CreateService (gap_cb.gatt_if, &uuid, 0, GAP_MAX_ATTR_NUM, TRUE);
+
+    GAP_TRACE_EVENT1 ("gap_attr_db_init service_handle = %d", service_handle);
+
+    /* add Device Name Characteristic
+    */
+    uuid.len = LEN_UUID_16;
+    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_DEVICE_NAME;
+    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid, GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+    p_db_attr ++;
+
+    /* add Icon characteristic
+    */
+    uuid.uu.uuid16   = p_db_attr->uuid = GATT_UUID_GAP_ICON;
+    p_db_attr->handle = GATTS_AddCharacteristic(service_handle,
+                                                &uuid,
+                                                GATT_PERM_READ,
+                                                GATT_CHAR_PROP_BIT_READ);
+    p_db_attr ++;
+
+    /* start service now */
+    memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
+
+    status = GATTS_StartService(gap_cb.gatt_if, service_handle, GAP_TRANSPORT_SUPPORTED );
+
+    GAP_TRACE_EVENT3 ("GAP App gatt_if: %d  s_hdl = %d start_status=%d",
+                      gap_cb.gatt_if, service_handle, status);
+
+
+
+}
+
+/*******************************************************************************
+**
+** Function         GAP_BleAttrDBUpdate
+**
+** Description      GAP ATT database update.
+**
+** Returns          void.
+**
+*******************************************************************************/
+void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
+{
+    tGAP_ATTR  *p_db_attr = gap_cb.gatt_attr;
+    UINT8       i = 0;
+
+    GAP_TRACE_EVENT1("GAP_BleAttrDBUpdate attr_uuid=0x%04x", attr_uuid);
+
+    for (i = 0; i < GAP_MAX_CHAR_NUM; i ++, p_db_attr ++)
+    {
+        if (p_db_attr->uuid == attr_uuid)
+        {
+            GAP_TRACE_EVENT1("Found attr_uuid=0x%04x", attr_uuid);
+
+            switch (attr_uuid)
+            {
+            case GATT_UUID_GAP_ICON:
+                p_db_attr->attr_value.icon  =  p_value->icon;
+                break;
+
+            case GATT_UUID_GAP_PREF_CONN_PARAM:
+                memcpy((void *)&p_db_attr->attr_value.conn_param, (const void *)&p_value->conn_param, sizeof(tGAP_BLE_PREF_PARAM));
+                break;
+
+            case GATT_UUID_GAP_DEVICE_NAME:
+                BTM_SetLocalDeviceName((char *)p_value->p_dev_name);
+                break;
+
+            }
+            break;
+        }
+    }
+
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_cl_op_cmpl
+**
+** Description      GAP client operation complete callback
+**
+** Returns          void
+**
+*******************************************************************************/
+void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_name)
+{
+    tGAP_BLE_DEV_NAME_CBACK *p_dev_name_cback = (tGAP_BLE_DEV_NAME_CBACK *)(p_clcb->p_cback);
+    UINT16                  op = p_clcb->cl_op_uuid;
+
+    GAP_TRACE_EVENT1("gap_ble_cl_op_cmpl status: %d", status);
+
+    p_clcb->cl_op_uuid = 0;
+    p_clcb->p_cback=NULL;
+
+    if (!gap_ble_process_pending_op(p_clcb) && op != 0)
+        GATT_Disconnect(p_clcb->conn_id);
+
+    if (p_dev_name_cback)
+    {
+        GAP_TRACE_EVENT0("calling gap_ble_cl_op_cmpl");
+
+        if (op == GATT_UUID_GAP_DEVICE_NAME)
+            (* p_dev_name_cback)(status, p_clcb->bda, len, (char *)p_name);
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_c_connect_cback
+**
+** Description      Client connection callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_id,
+                                     BOOLEAN connected, tGATT_DISCONN_REASON reason)
+{
+    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (bda);
+    UINT16      cl_op_uuid;
+
+    GAP_TRACE_EVENT5 ("gap_ble_c_connect_cback: from %08x%04x connected:%d conn_id=%d reason = 0x%04x",
+                      (bda[0]<<24)+(bda[1]<<16)+(bda[2]<<8)+bda[3],
+                      (bda[4]<<8)+bda[5], connected, conn_id, reason);
+
+
+    if (connected)
+    {
+        if (p_clcb == NULL)
+        {
+            if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
+            {
+                GAP_TRACE_ERROR0 ("gap_ble_c_connect_cback: no_resource");
+                return;
+            }
+        }
+        p_clcb->conn_id = conn_id;
+        p_clcb->connected = TRUE;
+
+        /* Do not use reconnection address for now -->
+          check privacy enabled? set reconnect address
+        btm_ble_update_reconnect_address(bda);*/
+    }
+    else
+    {
+        if (p_clcb != NULL)
+            p_clcb->connected = FALSE;
+    }
+
+    if (p_clcb)
+    {
+        cl_op_uuid = p_clcb->cl_op_uuid;
+
+        GAP_TRACE_EVENT1 ("cl_op_uuid=0x%04x", cl_op_uuid  );
+
+        if (p_clcb->connected)
+        {
+            p_clcb->cl_op_uuid = 0;
+            if (cl_op_uuid == GATT_UUID_GAP_DEVICE_NAME)
+            {
+                GAP_BleReadPeerDevName (bda, (tGAP_BLE_DEV_NAME_CBACK *)p_clcb->p_cback);
+            }
+        }
+        /* current link disconnect */
+        else
+        {
+            gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+            memset(p_clcb, 0, sizeof(tGAP_CLCB));
+        }
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_c_cmpl_cback
+**
+** Description      Client operation complete callback.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS status, tGATT_CL_COMPLETE *p_data)
+
+{
+    tGAP_CLCB   *p_clcb = gap_ble_find_clcb_by_conn_id(conn_id);
+    UINT16      op_type;
+    UINT16      min, max, latency, tout;
+    UINT16      len;
+    UINT8       *pp;
+
+    if (p_clcb == NULL)
+        return;
+
+    op_type = p_clcb->cl_op_uuid;
+
+    GAP_TRACE_EVENT3 ("gap_ble_c_cmpl_cback() - op_code: 0x%02x  status: 0x%02x  read_type: 0x%04x", op, status, op_type);
+    /* Currently we only issue read commands */
+    if (op != GATTC_OPTYPE_READ && op != GATTC_OPTYPE_WRITE)
+        return;
+
+    if (status != GATT_SUCCESS)
+    {
+        gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+        return;
+    }
+
+    pp = p_data->att_value.value;
+
+    switch (op_type)
+    {
+        case GATT_UUID_GAP_PREF_CONN_PARAM:
+            GAP_TRACE_EVENT0 ("GATT_UUID_GAP_PREF_CONN_PARAM");
+            /* Extract the peripheral preferred connection parameters and save them */
+
+            STREAM_TO_UINT16 (min, pp);
+            STREAM_TO_UINT16 (max, pp);
+            STREAM_TO_UINT16 (latency, pp);
+            STREAM_TO_UINT16 (tout, pp);
+
+            BTM_BleSetPrefConnParams (p_clcb->bda, min, max, latency, tout);
+            /* release the connection here */
+            gap_ble_cl_op_cmpl(p_clcb, TRUE, 0, NULL);
+            break;
+
+        case GATT_UUID_GAP_DEVICE_NAME:
+            GAP_TRACE_EVENT0 ("GATT_UUID_GAP_DEVICE_NAME");
+            len = (UINT16)strlen((char *)pp);
+            if (len > GAP_CHAR_DEV_NAME_SIZE)
+                len = GAP_CHAR_DEV_NAME_SIZE;
+            gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
+            break;
+        case GATT_UUID_GAP_ICON:
+            break;
+
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_ble_cl_read_request
+**
+** Description      utility function to start a read request for a GAP charactersitic
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
+{
+    tGATT_READ_PARAM   param;
+
+    memset(&param, 0, sizeof(tGATT_READ_PARAM));
+
+    param.service.uuid.len       = LEN_UUID_16;
+    param.service.uuid.uu.uuid16 = uuid;
+    param.service.s_handle       = 1;
+    param.service.e_handle       = 0xFFFF;
+    param.service.auth_req       = 0;
+
+    if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS)
+    {
+        GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+        /* release the link here */
+        GATT_Disconnect(p_clcb->conn_id);
+        return(FALSE);
+    }
+    else
+    {
+        p_clcb->p_cback = p_cback;
+        p_clcb->cl_op_uuid = uuid;
+        return TRUE;
+    }
+
+}
+
+/*******************************************************************************
+**
+** Function         GAP_BleReadPeerPrefConnParams
+**
+** Description      Start a process to read a connected peripheral's preferred
+**                  connection parameters
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
+{
+    tGAP_CLCB   *p_clcb;
+
+
+    /* This function should only be called if there is a connection to  */
+    /* the peer. Get a client handle for that connection.               */
+    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+        !p_clcb->connected)
+    {
+        GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+        return(FALSE);
+    }
+
+    GAP_TRACE_API3 ("GAP_BleReadPeerPrefConnParams() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
+                    (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+                    (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+    /* For now we only handle one at a time */
+    if (p_clcb->cl_op_uuid != 0)
+        return(FALSE);
+
+    return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
+
+}
+
+/*******************************************************************************
+**
+** Function         GAP_BleReadPeerDevName
+**
+** Description      Start a process to read a connected peripheral's device name.
+**
+** Returns          TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
+{
+    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+    if (p_cback == NULL)
+        return(FALSE);
+
+    if (p_clcb == NULL)
+    {
+        p_clcb = gap_clcb_alloc(0, peer_bda);
+        p_clcb->connected = FALSE;
+    }
+
+    if (p_clcb == NULL)
+    {
+        GAP_TRACE_ERROR0("GAP_BleReadPeerDevName max connection reached");
+    }
+
+
+    GAP_TRACE_EVENT3 ("GAP_BleReadPeerDevName() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
+                      (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+                      (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+    /* For now we only handle one at a time */
+    if (p_clcb->cl_op_uuid != 0)
+        return(FALSE);
+
+    /* hold the link here */
+    GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+    if (p_clcb->connected)
+    {
+        return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_DEVICE_NAME, (void *)p_cback);
+    }
+
+    p_clcb->p_cback = (void *)p_cback;
+    /* Mark currently active operation */
+    p_clcb->cl_op_uuid = GATT_UUID_GAP_DEVICE_NAME;
+
+
+    return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_BleCancelReadPeerDevName
+**
+** Description      Cancel reading a peripheral's device name.
+**
+** Returns          TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
+{
+    tGAP_CLCB *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
+
+    GAP_TRACE_EVENT3 ("GAP_BleCancelReadPeerDevName() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
+                      (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+                      (peer_bda[4]<<8)+peer_bda[5], (p_clcb == NULL)? 0 : p_clcb->cl_op_uuid);
+
+    if (p_clcb == NULL || p_clcb->cl_op_uuid != GATT_UUID_GAP_DEVICE_NAME)
+    {
+        GAP_TRACE_ERROR0 ("Cannot cancel current op is not get dev name");
+        return FALSE;
+    }
+
+    if (!p_clcb->connected)
+    {
+        if (!GATT_CancelConnect(gap_cb.gatt_if, peer_bda, TRUE))
+        {
+            GAP_TRACE_ERROR0 ("Cannot cancel where No connection id");
+            return FALSE;
+        }
+    }
+
+    gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
+
+    return(TRUE);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_BleUpdateReconnectAddr
+**
+** Description      Start a process to udpate the reconnect address if remote devive
+**                  has privacy enabled.
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda, BD_ADDR reconn_addr,
+                                    tGAP_BLE_RECONN_ADDR_CBACK *p_cback)
+{
+    tGAP_CLCB         *p_clcb;
+    tGATT_DISC_PARAM   param;
+
+    if (p_cback == NULL)
+        return(FALSE);
+
+    /* This function should only be called if there is a connection to  */
+    /* the peer. Get a client handle for that connection.               */
+    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL ||
+        !p_clcb->connected)
+    {
+        GAP_TRACE_ERROR0("No connection, can not update reconnect address");
+        return(FALSE);
+    }
+
+    GAP_TRACE_API3 ("GAP_BleUpdateReconnectAddr() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
+                    (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+                    (peer_bda[4]<<8)+peer_bda[5], p_clcb->cl_op_uuid);
+
+    /* For now we only handle one at a time */
+    if (p_clcb->cl_op_uuid != 0)
+    {
+        gap_ble_enqueue_op(p_clcb, GATT_UPDATE_RECONN_ADDR, reconn_addr, 0, (void *)p_cback);
+        return(FALSE);
+    }
+
+    /* hold the link here */
+    GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE);
+
+    memset(&param, 0, sizeof(tGATT_DISC_PARAM));
+
+    param.service.len       = LEN_UUID_16;
+    param.service.uu.uuid16 = GATT_UUID_GAP_RECONN_ADDR;
+    param.s_handle          = 1;
+    param.e_handle          = 0xFFFF;
+
+    if (GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, &param) != GATT_SUCCESS)
+    {
+        GAP_TRACE_ERROR0 ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
+        /* release the link here */
+        GATT_Disconnect(p_clcb->conn_id);
+        return(FALSE);
+    }
+    else
+    {
+        p_clcb->p_cback     = (void *)p_cback;
+        memcpy(p_clcb->reconn_addr, reconn_addr, BD_ADDR_LEN);
+        p_clcb->cl_op_uuid  = GATT_UUID_GAP_RECONN_ADDR;
+    }
+
+    return TRUE;
+
+}
+
+#endif  /* BLE_INCLUDED */
+
+
+
+
+
diff --git a/stack/gap/gap_conn.c b/stack/gap/gap_conn.c
new file mode 100644
index 0000000..43765b7
--- /dev/null
+++ b/stack/gap/gap_conn.c
@@ -0,0 +1,1270 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 "bt_target.h"
+#include "btu.h"
+#include "gap_int.h"
+#include "l2cdefs.h"
+#include "l2c_int.h"
+#include <string.h>
+#if GAP_CONN_INCLUDED == TRUE
+#include "btm_int.h"
+
+/********************************************************************************/
+/*              L O C A L    F U N C T I O N     P R O T O T Y P E S            */
+/********************************************************************************/
+static void gap_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id);
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result);
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg);
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed);
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg);
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested);
+
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid);
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle);
+static tGAP_CCB *gap_allocate_ccb (void);
+static void      gap_release_ccb (tGAP_CCB *p_ccb);
+
+/*******************************************************************************
+**
+** Function         gap_conn_init
+**
+** Description      This function is called to initialize GAP connection management
+**
+** Returns          void
+**
+*******************************************************************************/
+void gap_conn_init (void)
+{
+#if AMP_INCLUDED == TRUE
+    gap_cb.conn.reg_info.pAMP_ConnectInd_Cb         = gap_connect_ind;
+    gap_cb.conn.reg_info.pAMP_ConnectCfm_Cb         = gap_connect_cfm;
+    gap_cb.conn.reg_info.pAMP_ConnectPnd_Cb         = NULL;
+    gap_cb.conn.reg_info.pAMP_ConfigInd_Cb          = gap_config_ind;
+    gap_cb.conn.reg_info.pAMP_ConfigCfm_Cb          = gap_config_cfm;
+    gap_cb.conn.reg_info.pAMP_DisconnectInd_Cb      = gap_disconnect_ind;
+    gap_cb.conn.reg_info.pAMP_DisconnectCfm_Cb      = NULL;
+    gap_cb.conn.reg_info.pAMP_QoSViolationInd_Cb    = NULL;
+    gap_cb.conn.reg_info.pAMP_DataInd_Cb            = gap_data_ind;
+    gap_cb.conn.reg_info.pAMP_CongestionStatus_Cb   = gap_congestion_ind;
+    gap_cb.conn.reg_info.pAMP_TxComplete_Cb         = NULL;
+    gap_cb.conn.reg_info.pAMP_MoveInd_Cb            = NULL;
+    gap_cb.conn.reg_info.pAMP_MoveRsp_Cb            = NULL;
+    gap_cb.conn.reg_info.pAMP_MoveCfm_Cb            = NULL; //gap_move_cfm
+    gap_cb.conn.reg_info.pAMP_MoveCfmRsp_Cb         = NULL; //gap_move_cfm_rsp
+
+#else
+    gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb       = gap_connect_ind;
+    gap_cb.conn.reg_info.pL2CA_ConnectCfm_Cb       = gap_connect_cfm;
+    gap_cb.conn.reg_info.pL2CA_ConnectPnd_Cb       = NULL;
+    gap_cb.conn.reg_info.pL2CA_ConfigInd_Cb        = gap_config_ind;
+    gap_cb.conn.reg_info.pL2CA_ConfigCfm_Cb        = gap_config_cfm;
+    gap_cb.conn.reg_info.pL2CA_DisconnectInd_Cb    = gap_disconnect_ind;
+    gap_cb.conn.reg_info.pL2CA_DisconnectCfm_Cb    = NULL;
+    gap_cb.conn.reg_info.pL2CA_QoSViolationInd_Cb  = NULL;
+    gap_cb.conn.reg_info.pL2CA_DataInd_Cb          = gap_data_ind;
+    gap_cb.conn.reg_info.pL2CA_CongestionStatus_Cb = gap_congestion_ind;
+    gap_cb.conn.reg_info.pL2CA_TxComplete_Cb       = NULL;
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnOpen
+**
+** Description      This function is called to open an L2CAP connection.
+**
+** Parameters:      is_server   - If TRUE, the connection is not created
+**                                but put into a "listen" mode waiting for
+**                                the remote side to connect.
+**
+**                  service_id  - Unique service ID from
+**                                BTM_SEC_SERVICE_FIRST_EMPTY (6)
+**                                to BTM_SEC_MAX_SERVICE_RECORDS (32)
+**
+**                  p_rem_bda   - Pointer to remote BD Address.
+**                                If a server, and we don't care about the
+**                                remote BD Address, then NULL should be passed.
+**
+**                  psm         - the PSM used for the connection
+**
+**                  p_config    - Optional pointer to configuration structure.
+**                                If NULL, the default GAP configuration will
+**                                be used.
+**
+**                  security    - security flags
+**                  chan_mode_mask - (GAP_FCR_CHAN_OPT_BASIC, GAP_FCR_CHAN_OPT_ERTM, GAP_FCR_CHAN_OPT_STREAM)
+**
+**                  p_cb        - Pointer to callback function for events.
+**
+** Returns          handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+                     BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+                     UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb)
+{
+    tGAP_CCB    *p_ccb;
+    UINT16       cid;
+    tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+    GAP_TRACE_EVENT0 ("GAP_CONN - Open Request");
+
+    /* Allocate a new CCB. Return if none available. */
+    if ((p_ccb = gap_allocate_ccb()) == NULL)
+        return (GAP_INVALID_HANDLE);
+
+    /* If caller specified a BD address, save it */
+    if (p_rem_bda)
+    {
+        /* the bd addr is not BT_BD_ANY, then a bd address was specified */
+        if (memcmp (p_rem_bda, BT_BD_ANY, BD_ADDR_LEN))
+            p_ccb->rem_addr_specified = TRUE;
+
+        memcpy (&p_ccb->rem_dev_address[0], p_rem_bda, BD_ADDR_LEN);
+    }
+    else if (!is_server)
+    {
+        /* remore addr is not specified and is not a server -> bad */
+        return (GAP_INVALID_HANDLE);
+    }
+
+    /* A client MUST have specified a bd addr to connect with */
+    if (!p_ccb->rem_addr_specified && !is_server)
+    {
+        gap_release_ccb (p_ccb);
+        GAP_TRACE_ERROR0 ("GAP ERROR: Client must specify a remote BD ADDR to connect to!");
+        return (GAP_INVALID_HANDLE);
+    }
+
+    /* Check if configuration was specified */
+    if (p_cfg)
+        p_ccb->cfg = *p_cfg;
+
+    p_ccb->p_callback     = p_cb;
+
+    /* If originator, use a dynamic PSM */
+#if AMP_INCLUDED == TRUE
+    if (!is_server)
+        gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = NULL;
+    else
+        gap_cb.conn.reg_info.pAMP_ConnectInd_Cb  = gap_connect_ind;
+#else
+    if (!is_server)
+        gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = NULL;
+    else
+        gap_cb.conn.reg_info.pL2CA_ConnectInd_Cb = gap_connect_ind;
+#endif
+
+    /* Register the PSM with L2CAP */
+    if ((p_ccb->psm = L2CA_REGISTER (psm, &gap_cb.conn.reg_info, AMP_AUTOSWITCH_ALLOWED|AMP_USE_AMP_IF_POSSIBLE)) == 0)
+    {
+        GAP_TRACE_ERROR1 ("GAP_ConnOpen: Failure registering PSM 0x%04x", psm);
+        gap_release_ccb (p_ccb);
+        return (GAP_INVALID_HANDLE);
+    }
+
+    /* Register with Security Manager for the specific security level */
+    p_ccb->service_id = service_id;
+    if (!BTM_SetSecurityLevel ((UINT8)!is_server, p_serv_name, p_ccb->service_id, security, p_ccb->psm, 0, 0))
+    {
+        GAP_TRACE_ERROR0 ("GAP_CONN - Security Error");
+        gap_release_ccb (p_ccb);
+        return (GAP_INVALID_HANDLE);
+    }
+
+    /* Fill in eL2CAP parameter data */
+    if( p_ccb->cfg.fcr_present )
+    {
+        p_ccb->ertm_info.preferred_mode = p_ccb->cfg.fcr.mode;
+        p_ccb->ertm_info.user_rx_pool_id = GAP_DATA_POOL_ID;
+        p_ccb->ertm_info.user_tx_pool_id = GAP_DATA_POOL_ID;
+        p_ccb->ertm_info.fcr_rx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+        p_ccb->ertm_info.fcr_tx_pool_id = L2CAP_DEFAULT_ERM_POOL_ID;
+    }
+
+    /* optional FCR channel modes */
+    p_ccb->ertm_info.allowed_modes = (chan_mode_mask) ? chan_mode_mask : (UINT8)L2CAP_FCR_CHAN_OPT_BASIC;
+
+    if (is_server)
+    {
+        p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE; /* assume btm/l2cap would handle it */
+        p_ccb->con_state = GAP_CCB_STATE_LISTENING;
+        return (p_ccb->gap_handle);
+    }
+    else
+    {
+        /* We are the originator of this connection */
+        p_ccb->con_flags = GAP_CCB_FLAGS_IS_ORIG;
+
+        /* Transition to the next appropriate state, waiting for connection confirm. */
+        p_ccb->con_state = GAP_CCB_STATE_CONN_SETUP;
+
+        /* mark security done flag, when security is not required */
+        if ((security & (BTM_SEC_OUT_AUTHORIZE | BTM_SEC_OUT_AUTHENTICATE | BTM_SEC_OUT_ENCRYPT) ) == 0)
+            p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+
+        /* Check if L2CAP started the connection process */
+        if (p_rem_bda && ((cid = L2CA_CONNECT_REQ (p_ccb->psm, p_rem_bda, &p_ccb->ertm_info, &bt_uuid)) != 0))
+        {
+            p_ccb->connection_id = cid;
+            return (p_ccb->gap_handle);
+        }
+        else
+        {
+            gap_release_ccb (p_ccb);
+            return (GAP_INVALID_HANDLE);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnClose
+**
+** Description      This function is called to close a connection.
+**
+** Parameters:      handle      - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns          BT_PASS             - closed OK
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnClose (UINT16 gap_handle)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+    GAP_TRACE_EVENT1 ("GAP_CONN - close  handle: 0x%x", gap_handle);
+
+    if (p_ccb)
+    {
+        /* Check if we have a connection ID */
+        if (p_ccb->con_state != GAP_CCB_STATE_LISTENING)
+            L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+
+        gap_release_ccb (p_ccb);
+
+        return (BT_PASS);
+    }
+
+    return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnReadData
+**
+** Description      Normally not GKI aware application will call this function
+**                  after receiving GAP_EVT_RXDATA event.
+**
+** Parameters:      handle      - Handle of the connection returned in the Open
+**                  p_data      - Data area
+**                  max_len     - Byte count requested
+**                  p_len       - Byte count received
+**
+** Returns          BT_PASS             - data read
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**                  GAP_NO_DATA_AVAIL   - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+    BT_HDR     *p_buf;
+    UINT16      copy_len;
+
+    if (!p_ccb)
+        return (GAP_ERR_BAD_HANDLE);
+
+    *p_len = 0;
+
+    p_buf = (BT_HDR *)GKI_getfirst (&p_ccb->rx_queue);
+    if (!p_buf)
+        return (GAP_NO_DATA_AVAIL);
+
+    GKI_disable();
+
+    while (max_len && p_buf)
+    {
+        copy_len = (p_buf->len > max_len)?max_len:p_buf->len;
+        max_len -= copy_len;
+        *p_len  += copy_len;
+        if (p_data)
+        {
+            memcpy (p_data, (UINT8 *)(p_buf + 1) + p_buf->offset, copy_len);
+            p_data += copy_len;
+        }
+
+        if (p_buf->len > copy_len)
+        {
+            p_buf->offset += copy_len;
+            p_buf->len    -= copy_len;
+            break;
+        }
+        else
+        {
+            if (max_len)
+            {
+                p_buf = (BT_HDR *)GKI_getnext (p_buf);
+            }
+            GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+        }
+    }
+
+    p_ccb->rx_queue_size -= *p_len;
+
+    GKI_enable();
+
+    GAP_TRACE_EVENT2 ("GAP_ConnReadData - rx_queue_size left=%d, *p_len=%d",
+                                       p_ccb->rx_queue_size, *p_len);
+
+    return (BT_PASS);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_GetRxQueueCnt
+**
+** Description      This function return number of bytes on the rx queue.
+**
+** Parameters:      handle     - Handle returned in the GAP_ConnOpen
+**                  p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count)
+{
+    tGAP_CCB    *p_ccb;
+    int         rc = BT_PASS;
+
+    /* Check that handle is valid */
+    if (handle < GAP_MAX_CONNECTIONS)
+    {
+        p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+        if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+        {
+            *p_rx_queue_count = p_ccb->rx_queue_size;
+        }
+        else
+            rc = GAP_INVALID_HANDLE;
+    }
+    else
+        rc = GAP_INVALID_HANDLE;
+
+    GAP_TRACE_EVENT2 ("GAP_GetRxQueueCnt - rc = 0x%04x, rx_queue_count=%d",
+                                       rc , *p_rx_queue_count);
+
+    return (rc);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_ConnBTRead
+**
+** Description      Bluetooth aware applications will call this function after receiving
+**                  GAP_EVT_RXDATA event.
+**
+** Parameters:      handle      - Handle of the connection returned in the Open
+**                  pp_buf      - pointer to address of buffer with data,
+**
+** Returns          BT_PASS             - data read
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**                  GAP_NO_DATA_AVAIL   - no data available
+**
+*******************************************************************************/
+UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+    BT_HDR      *p_buf;
+
+    if (!p_ccb)
+        return (GAP_ERR_BAD_HANDLE);
+
+    p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->rx_queue);
+
+    if (p_buf)
+    {
+        *pp_buf = p_buf;
+
+        p_ccb->rx_queue_size -= p_buf->len;
+        return (BT_PASS);
+    }
+    else
+    {
+        *pp_buf = NULL;
+        return (GAP_NO_DATA_AVAIL);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnBTWrite
+**
+** Description      Bluetooth Aware applications can call this function to write data.
+**
+** Parameters:      handle      - Handle of the connection returned in the Open
+**                  p_buf      - pointer to address of buffer with data,
+**
+** Returns          BT_PASS                 - data read
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**                  GAP_ERR_BAD_STATE       - connection not established
+**                  GAP_INVALID_BUF_OFFSET  - buffer offset is invalid
+*******************************************************************************/
+UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+    if (!p_ccb)
+    {
+        GKI_freebuf (p_buf);
+        return (GAP_ERR_BAD_HANDLE);
+    }
+
+    if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+    {
+        GKI_freebuf (p_buf);
+        return (GAP_ERR_BAD_STATE);
+    }
+
+    if (p_buf->offset < L2CAP_MIN_OFFSET)
+    {
+        GKI_freebuf (p_buf);
+        return (GAP_ERR_BUF_OFFSET);
+    }
+
+    GKI_enqueue (&p_ccb->tx_queue, p_buf);
+
+    if (p_ccb->is_congested)
+    {
+        return (BT_PASS);
+    }
+
+    /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+    gap_send_event (gap_handle);
+#else
+    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+    {
+        UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+        if (status == L2CAP_DW_CONGESTED)
+        {
+            p_ccb->is_congested = TRUE;
+            break;
+        }
+        else if (status != L2CAP_DW_SUCCESS)
+            return (GAP_ERR_BAD_STATE);
+    }
+#endif
+    return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnWriteData
+**
+** Description      Normally not GKI aware application will call this function
+**                  to send data to the connection.
+**
+** Parameters:      handle      - Handle of the connection returned in the Open
+**                  p_data      - Data area
+**                  max_len     - Byte count requested
+**                  p_len       - Byte count received
+**
+** Returns          BT_PASS                 - data read
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**                  GAP_ERR_BAD_STATE       - connection not established
+**                  GAP_CONGESTION          - system is congested
+**
+*******************************************************************************/
+UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data, UINT16 max_len, UINT16 *p_len)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+    BT_HDR     *p_buf;
+
+    *p_len = 0;
+
+    if (!p_ccb)
+        return (GAP_ERR_BAD_HANDLE);
+
+    if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+        return (GAP_ERR_BAD_STATE);
+
+    while (max_len)
+    {
+        if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+        {
+            if ((p_buf = (BT_HDR *)GKI_getpoolbuf (p_ccb->ertm_info.user_tx_pool_id)) == NULL)
+                return (GAP_ERR_CONGESTED);
+        }
+        else
+        {
+            if ((p_buf = (BT_HDR *)GKI_getpoolbuf (GAP_DATA_POOL_ID)) == NULL)
+                return (GAP_ERR_CONGESTED);
+        }
+
+        p_buf->offset = L2CAP_MIN_OFFSET;
+        p_buf->len = (p_ccb->rem_mtu_size < max_len) ? p_ccb->rem_mtu_size : max_len;
+        p_buf->event = BT_EVT_TO_BTU_SP_DATA;
+
+        memcpy ((UINT8 *)(p_buf + 1) + p_buf->offset, p_data, p_buf->len);
+
+        *p_len  += p_buf->len;
+        max_len -= p_buf->len;
+        p_data  += p_buf->len;
+
+        GAP_TRACE_EVENT1 ("GAP_WriteData %d bytes", p_buf->len);
+
+        GKI_enqueue (&p_ccb->tx_queue, p_buf);
+    }
+
+    if (p_ccb->is_congested)
+    {
+        return (BT_PASS);
+    }
+
+    /* Send the buffer through L2CAP */
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+    gap_send_event (gap_handle);
+#else
+    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+    {
+        UINT8 status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+        if (status == L2CAP_DW_CONGESTED)
+        {
+            p_ccb->is_congested = TRUE;
+            break;
+        }
+        else if (status != L2CAP_DW_SUCCESS)
+            return (GAP_ERR_BAD_STATE);
+    }
+#endif
+    return (BT_PASS);
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnReconfig
+**
+** Description      Applications can call this function to reconfigure the connection.
+**
+** Parameters:      handle      - Handle of the connection
+**                  p_cfg       - Pointer to new configuration
+**
+** Returns          BT_PASS                 - config process started
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+    if (!p_ccb)
+        return (GAP_ERR_BAD_HANDLE);
+
+    p_ccb->cfg = *p_cfg;
+
+    if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+        L2CA_CONFIG_REQ (p_ccb->connection_id, p_cfg);
+
+    return (BT_PASS);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnSetIdleTimeout
+**
+** Description      Higher layers call this function to set the idle timeout for
+**                  a connection, or for all future connections. The "idle timeout"
+**                  is the amount of time that a connection can remain up with
+**                  no L2CAP channels on it. A timeout of zero means that the
+**                  connection will be torn down immediately when the last channel
+**                  is removed. A timeout of 0xFFFF means no timeout. Values are
+**                  in seconds.
+**
+** Parameters:      handle      - Handle of the connection
+**                  timeout     - in secs
+**                                0 = immediate disconnect when last channel is removed
+**                                0xFFFF = no idle timeout
+**
+** Returns          BT_PASS                 - config process started
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**
+*******************************************************************************/
+UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout)
+{
+    tGAP_CCB    *p_ccb;
+
+    if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+        return (GAP_ERR_BAD_HANDLE);
+
+    if (L2CA_SetIdleTimeout (p_ccb->connection_id, timeout, FALSE))
+        return (BT_PASS);
+    else
+        return (GAP_ERR_BAD_HANDLE);
+}
+
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetRemoteAddr
+**
+** Description      This function is called to get the remote BD address
+**                  of a connection.
+**
+** Parameters:      handle      - Handle of the connection returned by GAP_ConnOpen
+**
+** Returns          BT_PASS             - closed OK
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**
+*******************************************************************************/
+UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle)
+{
+    tGAP_CCB    *p_ccb = gap_find_ccb_by_handle (gap_handle);
+
+    GAP_TRACE_EVENT1 ("GAP_ConnGetRemoteAddr gap_handle = %d", gap_handle);
+
+    if ((p_ccb) && (p_ccb->con_state > GAP_CCB_STATE_LISTENING))
+    {
+        GAP_TRACE_EVENT6("GAP_ConnGetRemoteAddr bda :0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n", \
+                         p_ccb->rem_dev_address[0],p_ccb->rem_dev_address[1],p_ccb->rem_dev_address[2],
+                         p_ccb->rem_dev_address[3],p_ccb->rem_dev_address[4],p_ccb->rem_dev_address[5]);
+        return (p_ccb->rem_dev_address);
+    }
+    else
+    {
+        GAP_TRACE_EVENT0 ("GAP_ConnGetRemoteAddr return Error ");
+        return (NULL);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetRemMtuSize
+**
+** Description      Returns the remote device's MTU size
+**
+** Parameters:      handle      - Handle of the connection
+**
+** Returns          UINT16      - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle)
+{
+    tGAP_CCB    *p_ccb;
+
+    if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+        return (0);
+
+    return (p_ccb->rem_mtu_size);
+}
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetL2CAPCid
+**
+** Description      Returns the L2CAP channel id
+**
+** Parameters:      handle      - Handle of the connection
+**
+** Returns          UINT16      - The L2CAP channel id
+**                  0, if error
+**
+*******************************************************************************/
+UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle)
+{
+    tGAP_CCB    *p_ccb;
+
+    if ((p_ccb = gap_find_ccb_by_handle (gap_handle)) == NULL)
+        return (0);
+
+    return (p_ccb->connection_id);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_connect_ind
+**
+** Description      This function handles an inbound connection indication
+**                  from L2CAP. This is the case where we are acting as a
+**                  server.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_connect_ind (BD_ADDR  bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id)
+{
+    UINT16       xx;
+    tGAP_CCB     *p_ccb;
+    tBT_UUID    bt_uuid = {2, {GAP_PROTOCOL_ID}};
+
+    /* See if we have a CCB listening for the connection */
+    for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+    {
+        if ((p_ccb->con_state == GAP_CCB_STATE_LISTENING)
+         && (p_ccb->psm == psm)
+         && ((p_ccb->rem_addr_specified == FALSE)
+           || (!memcmp (bd_addr, p_ccb->rem_dev_address, BD_ADDR_LEN))))
+            break;
+    }
+
+    if (xx == GAP_MAX_CONNECTIONS)
+    {
+        GAP_TRACE_WARNING0("*******");
+        GAP_TRACE_WARNING0("WARNING: GAP Conn Indication for Unexpected Bd Addr...Disconnecting");
+        GAP_TRACE_WARNING0("*******");
+
+        /* Disconnect because it is an unexpected connection */
+        L2CA_DISCONNECT_REQ (l2cap_cid);
+        return;
+    }
+
+    /* Transition to the next appropriate state, waiting for config setup. */
+    p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+    /* Save the BD Address and Channel ID. */
+    memcpy (&p_ccb->rem_dev_address[0], bd_addr, BD_ADDR_LEN);
+    p_ccb->connection_id = l2cap_cid;
+
+    /* Send response to the L2CAP layer. */
+    L2CA_CONNECT_RSP (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK, &p_ccb->ertm_info, &bt_uuid);
+
+    GAP_TRACE_EVENT1("GAP_CONN - Rcvd L2CAP conn ind, CID: 0x%x", p_ccb->connection_id);
+
+    /* Send a Configuration Request. */
+    L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+}
+
+/*******************************************************************************
+**
+** Function         gap_checks_con_flags
+**
+** Description      This function processes the L2CAP configuration indication
+**                  event.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_checks_con_flags (tGAP_CCB    *p_ccb)
+{
+    GAP_TRACE_EVENT1 ("gap_checks_con_flags conn_flags:0x%x, ", p_ccb->con_flags);
+    /* if all the required con_flags are set, report the OPEN event now */
+    if ((p_ccb->con_flags & GAP_CCB_FLAGS_CONN_DONE) == GAP_CCB_FLAGS_CONN_DONE)
+    {
+        p_ccb->con_state = GAP_CCB_STATE_CONNECTED;
+
+        p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_OPENED);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_sec_check_complete
+**
+** Description      The function called when Security Manager finishes
+**                  verification of the service side connection
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_sec_check_complete (BD_ADDR bd_addr, void *p_ref_data, UINT8 res)
+{
+    tGAP_CCB *p_ccb = (tGAP_CCB *)p_ref_data;
+
+    GAP_TRACE_EVENT3 ("gap_sec_check_complete conn_state:%d, conn_flags:0x%x, status:%d",
+        p_ccb->con_state, p_ccb->con_flags, res);
+    if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+        return;
+
+    if (res == BTM_SUCCESS)
+    {
+        p_ccb->con_flags |= GAP_CCB_FLAGS_SEC_DONE;
+        gap_checks_con_flags (p_ccb);
+    }
+    else
+    {
+        /* security failed - disconnect the channel */
+        L2CA_DISCONNECT_REQ (p_ccb->connection_id);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_connect_cfm
+**
+** Description      This function handles the connect confirm events
+**                  from L2CAP. This is the case when we are acting as a
+**                  client and have sent a connect request.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_connect_cfm (UINT16 l2cap_cid, UINT16 result)
+{
+    tGAP_CCB    *p_ccb;
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+        return;
+
+    /* initiate security process, if needed */
+    if ( (p_ccb->con_flags & GAP_CCB_FLAGS_SEC_DONE) == 0)
+    {
+        btm_sec_mx_access_request (p_ccb->rem_dev_address, p_ccb->psm, TRUE,
+                                   0, 0, &gap_sec_check_complete, p_ccb);
+    }
+
+    /* If the connection response contains success status, then */
+    /* Transition to the next state and startup the timer.      */
+    if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == GAP_CCB_STATE_CONN_SETUP))
+    {
+        p_ccb->con_state = GAP_CCB_STATE_CFG_SETUP;
+
+        /* Send a Configuration Request. */
+        L2CA_CONFIG_REQ (l2cap_cid, &p_ccb->cfg);
+    }
+    else
+    {
+        /* Tell the user if he has a callback */
+        if (p_ccb->p_callback)
+            (*p_ccb->p_callback) (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+
+        gap_release_ccb (p_ccb);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_config_ind
+**
+** Description      This function processes the L2CAP configuration indication
+**                  event.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+    tGAP_CCB    *p_ccb;
+    UINT16      local_mtu_size;
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+        return;
+
+    /* Remember the remote MTU size */
+
+    if (p_ccb->cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)
+    {
+        local_mtu_size = GKI_get_pool_bufsize (p_ccb->ertm_info.user_tx_pool_id)
+                       - sizeof(BT_HDR) - L2CAP_MIN_OFFSET;
+    }
+    else
+        local_mtu_size = L2CAP_MTU_SIZE;
+
+    if ((!p_cfg->mtu_present)||(p_cfg->mtu > local_mtu_size))
+    {
+        p_ccb->rem_mtu_size = local_mtu_size;
+    }
+    else
+        p_ccb->rem_mtu_size = p_cfg->mtu;
+
+    /* For now, always accept configuration from the other side */
+    p_cfg->flush_to_present = FALSE;
+    p_cfg->mtu_present      = FALSE;
+    p_cfg->result           = L2CAP_CFG_OK;
+    p_cfg->fcs_present      = FALSE;
+
+    L2CA_CONFIG_RSP (l2cap_cid, p_cfg);
+
+    p_ccb->con_flags |= GAP_CCB_FLAGS_HIS_CFG_DONE;
+
+    gap_checks_con_flags (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_config_cfm
+**
+** Description      This function processes the L2CAP configuration confirmation
+**                  event.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
+{
+    tGAP_CCB    *p_ccb;
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+        return;
+
+    if (p_cfg->result == L2CAP_CFG_OK)
+    {
+        p_ccb->con_flags |= GAP_CCB_FLAGS_MY_CFG_DONE;
+
+
+        if (p_ccb->cfg.fcr_present)
+            p_ccb->cfg.fcr.mode = p_cfg->fcr.mode;
+        else
+            p_ccb->cfg.fcr.mode = L2CAP_FCR_BASIC_MODE;
+
+        gap_checks_con_flags (p_ccb);
+    }
+    else
+    {
+        p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+        gap_release_ccb (p_ccb);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_disconnect_ind
+**
+** Description      This function handles a disconnect event from L2CAP. If
+**                  requested to, we ack the disconnect before dropping the CCB
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed)
+{
+    tGAP_CCB    *p_ccb;
+
+    GAP_TRACE_EVENT1 ("GAP_CONN - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid);
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+        return;
+
+    if (ack_needed)
+        L2CA_DISCONNECT_RSP (l2cap_cid);
+
+    p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_CLOSED);
+    gap_release_ccb (p_ccb);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_data_ind
+**
+** Description      This function is called when data is received from L2CAP.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg)
+{
+    tGAP_CCB    *p_ccb;
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (l2cap_cid)) == NULL)
+    {
+        GKI_freebuf (p_msg);
+        return;
+    }
+
+    if (p_ccb->con_state == GAP_CCB_STATE_CONNECTED)
+    {
+        GKI_enqueue (&p_ccb->rx_queue, p_msg);
+
+        p_ccb->rx_queue_size += p_msg->len;
+        /*
+        GAP_TRACE_EVENT2 ("gap_data_ind - rx_queue_size=%d, msg len=%d",
+                                       p_ccb->rx_queue_size, p_msg->len);
+         */
+
+        p_ccb->p_callback (p_ccb->gap_handle, GAP_EVT_CONN_DATA_AVAIL);
+    }
+    else
+    {
+        GKI_freebuf (p_msg);
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_congestion_ind
+**
+** Description      This is a callback function called by L2CAP when
+**                  data L2CAP congestion status changes
+**
+*******************************************************************************/
+static void gap_congestion_ind (UINT16 lcid, BOOLEAN is_congested)
+{
+    tGAP_CCB    *p_ccb;
+    UINT16       event;
+    BT_HDR      *p_buf;
+    UINT8        status;
+
+    GAP_TRACE_EVENT2 ("GAP_CONN - Rcvd L2CAP Is Congested (%d), CID: 0x%x",
+                      is_congested, lcid);
+
+    /* Find CCB based on CID */
+    if ((p_ccb = gap_find_ccb_by_cid (lcid)) == NULL)
+        return;
+
+    p_ccb->is_congested = is_congested;
+
+    event = (is_congested) ? GAP_EVT_CONN_CONGESTED : GAP_EVT_CONN_UNCONGESTED;
+    p_ccb->p_callback (p_ccb->gap_handle, event);
+
+    if (!is_congested)
+    {
+        while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+        {
+            status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+            if (status == L2CAP_DW_CONGESTED)
+            {
+                p_ccb->is_congested = TRUE;
+                break;
+            }
+            else if (status != L2CAP_DW_SUCCESS)
+                break;
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_find_ccb_by_cid
+**
+** Description      This function searches the CCB table for an entry with the
+**                  passed CID.
+**
+** Returns          the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_cid (UINT16 cid)
+{
+    UINT16       xx;
+    tGAP_CCB     *p_ccb;
+
+    /* Look through each connection control block */
+    for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+    {
+        if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->connection_id == cid))
+            return (p_ccb);
+    }
+
+    /* If here, not found */
+    return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_find_ccb_by_handle
+**
+** Description      This function searches the CCB table for an entry with the
+**                  passed handle.
+**
+** Returns          the CCB address, or NULL if not found.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_find_ccb_by_handle (UINT16 handle)
+{
+    tGAP_CCB     *p_ccb;
+
+    /* Check that handle is valid */
+    if (handle < GAP_MAX_CONNECTIONS)
+    {
+        p_ccb = &gap_cb.conn.ccb_pool[handle];
+
+        if (p_ccb->con_state != GAP_CCB_STATE_IDLE)
+            return (p_ccb);
+    }
+
+    /* If here, handle points to invalid connection */
+    return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_allocate_ccb
+**
+** Description      This function allocates a new CCB.
+**
+** Returns          CCB address, or NULL if none available.
+**
+*******************************************************************************/
+static tGAP_CCB *gap_allocate_ccb (void)
+{
+    UINT16       xx;
+    tGAP_CCB     *p_ccb;
+
+    /* Look through each connection control block for a free one */
+    for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+    {
+        if (p_ccb->con_state == GAP_CCB_STATE_IDLE)
+        {
+            memset (p_ccb, 0, sizeof (tGAP_CCB));
+
+            p_ccb->gap_handle   = xx;
+            p_ccb->rem_mtu_size = L2CAP_MTU_SIZE;
+
+            return (p_ccb);
+        }
+    }
+
+    /* If here, no free CCB found */
+    return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_release_ccb
+**
+** Description      This function releases a CCB.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void gap_release_ccb (tGAP_CCB *p_ccb)
+{
+    UINT16       xx;
+    UINT16      psm = p_ccb->psm;
+    UINT8       service_id = p_ccb->service_id;
+
+    /* Drop any buffers we may be holding */
+    p_ccb->rx_queue_size = 0;
+
+    while (p_ccb->rx_queue.p_first)
+        GKI_freebuf (GKI_dequeue (&p_ccb->rx_queue));
+
+    while (p_ccb->tx_queue.p_first)
+        GKI_freebuf (GKI_dequeue (&p_ccb->tx_queue));
+
+    p_ccb->con_state = GAP_CCB_STATE_IDLE;
+
+    /* If no-one else is using the PSM, deregister from L2CAP */
+    for (xx = 0, p_ccb = gap_cb.conn.ccb_pool; xx < GAP_MAX_CONNECTIONS; xx++, p_ccb++)
+    {
+        if ((p_ccb->con_state != GAP_CCB_STATE_IDLE) && (p_ccb->psm == psm))
+            return;
+    }
+
+    /* Free the security record for this PSM */
+    BTM_SecClrService(service_id);
+    L2CA_DEREGISTER (psm);
+}
+
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+
+/*******************************************************************************
+**
+** Function     gap_send_event
+**
+** Description  Send BT_EVT_TO_GAP_MSG event to BTU task
+**
+** Returns      None
+**
+*******************************************************************************/
+void gap_send_event (UINT16 gap_handle)
+{
+    BT_HDR  *p_msg;
+
+    if ((p_msg = (BT_HDR*)GKI_getbuf(BT_HDR_SIZE)) != NULL)
+    {
+        p_msg->event  = BT_EVT_TO_GAP_MSG;
+        p_msg->len    = 0;
+        p_msg->offset = 0;
+        p_msg->layer_specific = gap_handle;
+
+        GKI_send_msg(BTU_TASK, BTU_HCI_RCV_MBOX, p_msg);
+    }
+    else
+    {
+        GAP_TRACE_ERROR0("Unable to allocate message buffer for event.");
+    }
+}
+
+/*******************************************************************************
+**
+** Function     gap_proc_btu_event
+**
+** Description  Event handler for BT_EVT_TO_GAP_MSG event from BTU task
+**
+** Returns      None
+**
+*******************************************************************************/
+void gap_proc_btu_event(BT_HDR *p_msg)
+{
+    tGAP_CCB   *p_ccb = gap_find_ccb_by_handle (p_msg->layer_specific);
+    UINT8       status;
+    BT_HDR     *p_buf;
+
+    if (!p_ccb)
+    {
+        return;
+    }
+
+    if (p_ccb->con_state != GAP_CCB_STATE_CONNECTED)
+    {
+        return;
+    }
+
+    if (p_ccb->is_congested)
+    {
+        return;
+    }
+
+    /* Send the buffer through L2CAP */
+
+    while ((p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->tx_queue)) != NULL)
+    {
+        status = L2CA_DATA_WRITE (p_ccb->connection_id, p_buf);
+
+        if (status == L2CAP_DW_CONGESTED)
+        {
+            p_ccb->is_congested = TRUE;
+            break;
+        }
+        else if (status != L2CAP_DW_SUCCESS)
+            break;
+    }
+
+}
+#endif /* (GAP_CONN_POST_EVT_INCLUDED == TRUE) */
+#endif  /* GAP_CONN_INCLUDED */
diff --git a/stack/gap/gap_int.h b/stack/gap/gap_int.h
new file mode 100644
index 0000000..295ad83
--- /dev/null
+++ b/stack/gap/gap_int.h
@@ -0,0 +1,231 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 GAP_INT_H
+#define GAP_INT_H
+
+#include "bt_target.h"
+#include "gap_api.h"
+#include "btm_api.h"
+#include "gki.h"
+#include "gatt_api.h"
+#if AMP_INCLUDED == TRUE
+    #include "amp_api.h"
+#endif
+
+#if defined BLE_INCLUDED && BLE_INCLUDED == TRUE
+    #include "gatt_api.h"
+#endif
+
+#define GAP_MAX_BLOCKS 2        /* Concurrent GAP commands pending at a time*/
+/* There must be a different btm callback for*/
+/* each control block.*/
+
+
+/* Definitions of limits for inquiries */
+#define GAP_PER_INQ_MIN_MAX_PERIOD      BTM_PER_INQ_MIN_MAX_PERIOD
+#define GAP_PER_INQ_MAX_MAX_PERIOD      BTM_PER_INQ_MAX_MAX_PERIOD
+#define GAP_PER_INQ_MIN_MIN_PERIOD      BTM_PER_INQ_MIN_MIN_PERIOD
+#define GAP_PER_INQ_MAX_MIN_PERIOD      BTM_PER_INQ_MAX_MIN_PERIOD
+#define GAP_MAX_INQUIRY_LENGTH          BTM_MAX_INQUIRY_LENGTH
+#define GAP_MIN_INQUIRY_LEN             BTM_MIN_INQUIRY_LEN
+
+/* Define the Generic Access Profile control structure */
+typedef struct
+{
+    void          *p_data;      /* Pointer to any data returned in callback */
+    tGAP_CALLBACK *gap_cback;   /* Pointer to users callback function */
+    tGAP_CALLBACK *gap_inq_rslt_cback; /* Used for inquiry results */
+    UINT16         event;       /* Passed back in the callback */
+    UINT8          index;       /* Index of this control block and callback */
+    BOOLEAN        in_use;      /* True when structure is allocated */
+} tGAP_INFO;
+
+/* Define the control block for the FindAddrByName operation (Only 1 active at a time) */
+typedef struct
+{
+    tGAP_CALLBACK           *p_cback;
+    tBTM_INQ_INFO           *p_cur_inq; /* Pointer to the current inquiry database entry */
+    tGAP_FINDADDR_RESULTS    results;
+    BOOLEAN                  in_use;
+} tGAP_FINDADDR_CB;
+
+
+/* Define the GAP Connection Control Block.
+*/
+typedef struct
+{
+#define GAP_CCB_STATE_IDLE              0
+#define GAP_CCB_STATE_LISTENING         1
+#define GAP_CCB_STATE_CONN_SETUP        2
+#define GAP_CCB_STATE_CFG_SETUP         3
+#define GAP_CCB_STATE_WAIT_SEC          4
+#define GAP_CCB_STATE_CONNECTED         5
+    UINT8             con_state;
+
+#define GAP_CCB_FLAGS_IS_ORIG           0x01
+#define GAP_CCB_FLAGS_HIS_CFG_DONE      0x02
+#define GAP_CCB_FLAGS_MY_CFG_DONE       0x04
+#define GAP_CCB_FLAGS_SEC_DONE          0x08
+#define GAP_CCB_FLAGS_CONN_DONE         0x0E
+    UINT8             con_flags;
+
+    UINT8             service_id;           /* Used by BTM                          */
+    UINT16            gap_handle;           /* GAP handle                           */
+    UINT16            connection_id;        /* L2CAP CID                            */
+    BOOLEAN           rem_addr_specified;
+    UINT8             chan_mode_mask;       /* Supported channel modes (FCR)        */
+    BD_ADDR           rem_dev_address;
+    UINT16            psm;
+    UINT16            rem_mtu_size;
+
+    BOOLEAN           is_congested;
+    BUFFER_Q          tx_queue;             /* Queue of buffers waiting to be sent  */
+    BUFFER_Q          rx_queue;             /* Queue of buffers waiting to be read  */
+
+    UINT32            rx_queue_size;        /* Total data count in rx_queue         */
+
+    tGAP_CONN_CALLBACK *p_callback;         /* Users callback function              */
+
+    tL2CAP_CFG_INFO   cfg;                  /* Configuration                        */
+    tL2CAP_ERTM_INFO  ertm_info;            /* Pools and modes for ertm */
+} tGAP_CCB;
+
+typedef struct
+{
+#if AMP_INCLUDED == TRUE
+    tAMP_APPL_INFO    reg_info;
+#else
+    tL2CAP_APPL_INFO  reg_info;                     /* L2CAP Registration info */
+#endif
+    tGAP_CCB    ccb_pool[GAP_MAX_CONNECTIONS];
+} tGAP_CONN;
+
+
+#if BLE_INCLUDED == TRUE
+    #define GAP_MAX_CHAR_NUM          5
+
+typedef struct
+{
+    UINT16                  handle;
+    UINT16                  uuid;
+    tGAP_BLE_ATTR_VALUE     attr_value;
+}tGAP_ATTR;
+#endif
+/**********************************************************************
+** M A I N   C O N T R O L   B L O C K
+***********************************************************************/
+
+#define GAP_MAX_CL GATT_CL_MAX_LCB
+
+typedef struct
+{
+    union
+    {
+        BD_ADDR         reconn_addr;
+        UINT8           privacy_flag;
+    }                   pending_data;
+    UINT8               op;
+    void                *p_pending_cback;
+}tGAP_BLE_PENDING_OP;
+
+typedef struct
+{
+    BD_ADDR                 bda;
+    BD_ADDR                 reconn_addr;
+    void                    * p_cback;
+    UINT16                  conn_id;
+    UINT16                  cl_op_uuid;
+    UINT16                  disc_handle;
+    BOOLEAN                 in_use;
+    BOOLEAN                 connected;
+    UINT8                   privacy_flag;
+    BUFFER_Q                pending_op_q;
+}tGAP_CLCB;
+
+typedef struct
+{
+    tGAP_INFO        blk[GAP_MAX_BLOCKS];
+    tBTM_CMPL_CB    *btm_cback[GAP_MAX_BLOCKS];
+    UINT8            trace_level;
+    tGAP_FINDADDR_CB findaddr_cb;   /* Contains the control block for finding a device addr */
+    tBTM_INQ_INFO   *cur_inqptr;
+
+#if GAP_CONN_INCLUDED == TRUE
+    tGAP_CONN        conn;
+#endif
+
+    /* LE GAP attribute database */
+#if BLE_INCLUDED == TRUE
+    tGAP_ATTR               gatt_attr[GAP_MAX_CHAR_NUM];
+    BD_ADDR                 reconn_bda;
+    tGAP_CLCB               clcb[GAP_MAX_CL]; /* connection link*/
+
+    tGATT_IF                gatt_if;
+#endif
+} tGAP_CB;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if GAP_DYNAMIC_MEMORY == FALSE
+    GAP_API extern tGAP_CB  gap_cb;
+#else
+    GAP_API extern tGAP_CB *gap_cb_ptr;
+#define gap_cb (*gap_cb_ptr)
+#endif
+
+    extern tGAP_INFO        *gap_allocate_cb(void);
+    extern void              gap_free_cb(tGAP_INFO *p_cb);
+
+    /* GAP inquiry functions */
+    extern void              gap_inq_results_cb(tGAP_INQ_RESULTS *p_results, UINT8 *p_eir);
+    extern UINT16            gap_find_local_addr_by_name (const BD_NAME devname, BD_ADDR bd_addr);
+    extern void              gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p);
+
+    extern BOOLEAN           gap_is_service_busy (UINT16 request);
+    extern UINT16            gap_convert_btm_status (tBTM_STATUS btm_status);
+
+    extern void gap_btm_cback0(void *p1);
+#if GAP_MAX_BLOCKS > 1
+    extern void gap_btm_cback1(void *p1);
+#endif
+#if GAP_MAX_BLOCKS > 2
+    extern void gap_btm_cback2(void *p1);
+#endif
+
+#if (GAP_CONN_INCLUDED == TRUE)
+    extern void gap_conn_init(void);
+#if (GAP_CONN_POST_EVT_INCLUDED == TRUE)
+    void gap_send_event (UINT16 gap_handle);
+    void gap_proc_btu_event(BT_HDR *p_msg);
+#endif
+#endif
+
+#if (BLE_INCLUDED == TRUE)
+    extern void gap_attr_db_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/stack/gap/gap_utils.c b/stack/gap/gap_utils.c
new file mode 100644
index 0000000..d253a99
--- /dev/null
+++ b/stack/gap/gap_utils.c
@@ -0,0 +1,432 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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"
+#include "gap_int.h"
+
+/*****************************************************************************/
+/*                 G L O B A L      GAP       D A T A                        */
+/*****************************************************************************/
+#if GAP_DYNAMIC_MEMORY == FALSE
+tGAP_CB  gap_cb;
+#endif
+
+/*****************************************************************************
+** Callbacks passed to BTM -
+**      There are different callbacks based on the control block index so that
+**      more than one command can be pending at a time.
+**  NOTE:  There must be 1 callback for each control block defined
+**          GAP_MAX_BLOCKS
+**
+**          Also, the inquiry results event has its own callback; Not handled here!
+******************************************************************************/
+static void btm_cback(UINT16 index, void *p_data)
+{
+    tGAP_INFO       *p_cb;
+    tGAP_INQ_CMPL    inq_cmpl;
+
+    /* Make sure that the index is valid AND it is in use */
+    if (index < GAP_MAX_BLOCKS && gap_cb.blk[index].in_use)
+    {
+        p_cb = &gap_cb.blk[index];
+
+        /* If the callback is non-NULL, call it with the specified event */
+        switch (p_cb->event)
+        {
+        case GAP_EVT_INQUIRY_COMPLETE:
+            /* pass the number of results to caller */
+            inq_cmpl.num_results = ((tBTM_INQUIRY_CMPL *)p_data)->num_resp;
+
+            inq_cmpl.status = (((tBTM_INQUIRY_CMPL *)p_data)->status == BTM_SUCCESS) ? BT_PASS : GAP_ERR_PROCESSING;
+
+            p_data = &inq_cmpl;
+
+            GAP_TRACE_EVENT2("   GAP Inquiry Complete Event (Status 0x%04x, Result(s) %d)",
+                            inq_cmpl.status, inq_cmpl.num_results);
+            break;
+
+        case GAP_EVT_DISCOVERY_COMPLETE:
+            if (*((UINT16 *) p_data))
+            {
+                GAP_TRACE_EVENT1("   GAP Discovery Complete Event(SDP Result: 0x%04x)", *((UINT16 *) p_data));
+            }
+            else
+            {
+                GAP_TRACE_EVENT0("   GAP Discovery Successfully Completed");
+            }
+
+            break;
+
+        case GAP_EVT_REM_NAME_COMPLETE:
+            /* override the BTM error code with a GAP error code */
+            ((tGAP_REMOTE_DEV_NAME *)p_data)->status =
+                    gap_convert_btm_status ((tBTM_STATUS)((tBTM_REMOTE_DEV_NAME *)p_data)->status);
+
+            GAP_TRACE_EVENT1("   GAP Remote Name Complete Event (status 0x%04x)", ((tGAP_REMOTE_DEV_NAME *)p_data)->status);
+
+            break;
+        };
+
+        if (p_cb->gap_cback)
+            p_cb->gap_cback(p_cb->event, p_data);
+
+        /* Deallocate the control block */
+        gap_free_cb(p_cb);
+    }
+}
+
+
+/*** Callback functions for BTM_CMPL_CB ***/
+void gap_btm_cback0(void *p1)
+{
+    btm_cback(0, p1);
+}
+
+#if GAP_MAX_BLOCKS > 1
+void gap_btm_cback1(void *p1)
+{
+    btm_cback(1, p1);
+}
+#endif
+#if GAP_MAX_BLOCKS > 2
+void gap_btm_cback2(void *p1)
+{
+    btm_cback(2, p1);
+}
+#endif
+
+/* There is only one instance of this because only 1 inquiry can be active at a time */
+void gap_inq_results_cb(tBTM_INQ_RESULTS *p_results, UINT8 *p_eir)
+{
+    tGAP_INFO   *p_cb;
+    UINT8        index;
+
+    GAP_TRACE_EVENT6 ("GAP Inquiry Results Callback (bdaddr [%02x%02x%02x%02x%02x%02x])",
+                p_results->remote_bd_addr[0], p_results->remote_bd_addr[1],
+                p_results->remote_bd_addr[2], p_results->remote_bd_addr[3],
+                p_results->remote_bd_addr[4], p_results->remote_bd_addr[5]);
+    GAP_TRACE_EVENT4 ("                             (COD [%02x%02x%02x], clkoff 0x%04x)",
+                p_results->dev_class[0], p_results->dev_class[1], p_results->dev_class[2],
+                p_results->clock_offset);
+
+    /* Find the control block which has an Inquiry Active and call its results callback */
+    for (index = 0, p_cb = &gap_cb.blk[0]; index < GAP_MAX_BLOCKS; index++, p_cb++)
+    {
+        /* Look for the control block that is using inquiry */
+        if (p_cb->in_use && (p_cb->event == GAP_EVT_INQUIRY_COMPLETE))
+        {
+            /* Notify the higher layer if they care */
+            if (p_cb->gap_inq_rslt_cback)
+                p_cb->gap_inq_rslt_cback (GAP_EVT_INQUIRY_RESULTS, (tGAP_INQ_RESULTS *)p_results);
+        }
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_find_addr_name_cb
+**
+** Description      Processes the remote name request event when the Find Addr by Name
+**                  request is active.  The following procedure takes place:
+**                  1. Check the resulting name (If return status is ok)
+**                  2. If name matches requested name, we're done, call the appl's callback
+**                          with the BD ADDR.
+**                  3. Otherwise get the next BD ADDR out of the inquiry database and intiate
+**                          another remote name request.
+**                  4. If there are no more BD ADDRs, then call the appl's callback with a FAIL
+**                          status.
+**
+** Returns          void
+**
+*******************************************************************************/
+void gap_find_addr_name_cb (tBTM_REMOTE_DEV_NAME *p)
+{
+    tGAP_FINDADDR_CB        *p_cb = &gap_cb.findaddr_cb;
+    tGAP_FINDADDR_RESULTS   *p_result = &p_cb->results;
+
+    if (p_cb->in_use)
+    {
+        if (p->status == BTM_SUCCESS)
+        {
+            GAP_TRACE_EVENT2("   GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x, Name [%s])",
+                                p->status, p->remote_bd_name);
+
+            /* See if the returned name matches the desired name; if not initiate another search */
+            if (!strncmp ((char *)p_result->devname, (char *) p->remote_bd_name, strlen ((char *) p_result->devname)))
+            {
+                /* We found the device!  Copy it into the return structure */
+                memcpy (p_result->bd_addr, p_cb->p_cur_inq->results.remote_bd_addr, BD_ADDR_LEN);
+                p_result->status = BT_PASS;
+            }
+            else    /* The name doesn't match so initiate another search */
+            {
+                /* Get the device address of the next database entry */
+                if ((p_cb->p_cur_inq = BTM_InqDbNext(p_cb->p_cur_inq)) != NULL)
+                {
+                    if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+                        (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+                        return;     /* This routine will get called again with the next results */
+                    else
+                        p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+                }
+                else
+                    p_result->status = GAP_EOINQDB;     /* No inquiry results; we're done! */
+            }
+        }
+        else
+        {
+            GAP_TRACE_EVENT1("   GAP: FindAddrByName Rem Name Cmpl Evt (Status 0x%04x)", p->status);
+            p_result->status = gap_convert_btm_status ((tBTM_STATUS) p->status);
+        }
+
+        /* If this code is reached, the process has completed so call the appl's callback with results */
+        if (p_cb->p_cback)
+            p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+        /* Clear out the control block */
+        p_cb->in_use = FALSE;
+        p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_find_addr_inq_cb
+**
+** Description      Processes the inquiry complete event when the Find Addr by Name
+**                  request is active.  This callback performs one of the two following
+**                  steps:
+**                      1. If the remote name is retrieved automatically, the DB is searched
+**                          immediately, and the results are returned in the appls callback.
+**
+**                      2. If remote name is not automatic, retrieve the first BTM INQ
+**                         database entry and initiate a remote name request.
+**
+** Returns          void
+**
+*******************************************************************************/
+void gap_find_addr_inq_cb (tBTM_INQUIRY_CMPL *p)
+{
+    tGAP_FINDADDR_CB        *p_cb = &gap_cb.findaddr_cb;
+    tGAP_FINDADDR_RESULTS   *p_result = &p_cb->results;
+
+    if (p_cb->in_use)
+    {
+
+        GAP_TRACE_EVENT2("   GAP: FindAddrByName Inq Cmpl Evt (Status 0x%04x, Result(s) %d)",
+            p->status, p->num_resp);
+
+        if (p->status == BTM_SUCCESS)
+        {
+            /* Step 1: If automatically retrieving remote names then search the local database */
+            if ((p_result->status = gap_find_local_addr_by_name (p_result->devname, p_result->bd_addr)) == GAP_NO_DATA_AVAIL)
+            {
+                /* Step 2:  The name is not stored automatically, so a search of all devices needs to
+                 *          be initiated.
+                 */
+                if ((p_cb->p_cur_inq = BTM_InqDbFirst()) != NULL)
+                {
+                    if ((BTM_ReadRemoteDeviceName (p_cb->p_cur_inq->results.remote_bd_addr,
+                        (tBTM_CMPL_CB *) gap_find_addr_name_cb)) == BTM_CMD_STARTED)
+                        return;     /* Wait for the response in gap_find_addr_name_cb() */
+                    else
+                        p_result->status = gap_convert_btm_status (p->status);
+                }
+                else
+                    p_result->status = GAP_EOINQDB;     /* No inquiry results; we're done! */
+            }
+        }
+        else
+            p_result->status = gap_convert_btm_status (p->status);
+
+        /* If this code is reached, the process has completed so call the appl's callback with results */
+        if (p_cb->p_cback)
+            p_cb->p_cback (GAP_EVT_FIND_ADDR_COMPLETE, (tGAP_FINDADDR_RESULTS *) p_result);
+
+        /* Clear out the control block */
+        p_cb->in_use = FALSE;
+        p_cb->p_cback = (tGAP_CALLBACK *) NULL;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         gap_find_local_addr_by_name
+**
+** Description      Searches through the internal inquiry database for a device
+**                  that has the same name as the one passed in.  If found, the
+**                  device address is filled in.
+**
+**                  NOTE:  It only searches up to the first BTM_MAX_REM_BD_NAME_LEN
+**                          bytes because the inquiry database uses tBTM_BD_NAME.
+**
+** Returns          BT_PASS if the name was found and the device address is filled in
+**                  GAP_EOINQDB if the name was not found in the database
+**                  GAP_NO_DATA_AVAIL if the name is not saved with the inquiry
+**
+*******************************************************************************/
+UINT16 gap_find_local_addr_by_name (const tBTM_BD_NAME devname, BD_ADDR bd_addr)
+{
+
+/* If the remote name is retrieved automatically during an inquiry search the local db */
+#if (BTM_INQ_GET_REMOTE_NAME == TRUE)
+    tBTM_INQ_INFO   *p_result;
+
+    p_result = BTM_InqDbFirst();
+
+    while (p_result)
+    {
+        /* Check the entry for a device name match */
+        if (!strncmp ((char *)devname, (char *)p_result->remote_name, BTM_MAX_REM_BD_NAME_LEN))
+        {
+            memcpy (bd_addr, p_result->results.remote_bd_addr, BD_ADDR_LEN);
+            return (BT_PASS);
+        }
+        else
+            p_result = BTM_InqDbNext(p_result);
+    };
+
+    return (GAP_EOINQDB);
+#else
+    /* No data available because we are not automatically saving the data */
+    return (GAP_NO_DATA_AVAIL);
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_allocate_cb
+**
+** Description      Look through the GAP Control Blocks for a free one.
+**
+** Returns          Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+tGAP_INFO *gap_allocate_cb (void)
+{
+    tGAP_INFO     *p_cb = &gap_cb.blk[0];
+    UINT8        x;
+
+    for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+    {
+        if (!p_cb->in_use)
+        {
+            memset (p_cb, 0, sizeof (tGAP_INFO));
+
+            p_cb->in_use = TRUE;
+            p_cb->index = x;
+            p_cb->p_data = (void *)NULL;
+            return (p_cb);
+        }
+    }
+
+    /* If here, no free control blocks found */
+    return (NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_free_cb
+**
+** Description      Release GAP control block.
+**
+** Returns          Pointer to the control block or NULL if not found
+**
+*******************************************************************************/
+void gap_free_cb (tGAP_INFO *p_cb)
+{
+    if (p_cb)
+    {
+        p_cb->gap_cback = NULL;
+        p_cb->in_use = FALSE;
+    }
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_is_service_busy
+**
+** Description      Look through the GAP Control Blocks that are in use
+**                  and check to see if the event waiting for is the command
+**                  requested.
+**
+** Returns          TRUE if already in use
+**                  FALSE if not busy
+**
+*******************************************************************************/
+BOOLEAN gap_is_service_busy (UINT16 request)
+{
+    tGAP_INFO   *p_cb = &gap_cb.blk[0];
+    UINT8        x;
+
+    for (x = 0; x < GAP_MAX_BLOCKS; x++, p_cb++)
+    {
+        if (p_cb->in_use && p_cb->event == request)
+            return (TRUE);
+    }
+
+    /* If here, service is not busy */
+    return (FALSE);
+}
+
+
+/*******************************************************************************
+**
+** Function         gap_convert_btm_status
+**
+** Description      Converts a BTM error status into a GAP error status
+**
+**
+** Returns          GAP_UNKNOWN_BTM_STATUS is returned if not recognized
+**
+*******************************************************************************/
+UINT16 gap_convert_btm_status (tBTM_STATUS btm_status)
+{
+    switch (btm_status)
+    {
+    case BTM_SUCCESS:
+        return (BT_PASS);
+
+    case BTM_CMD_STARTED:
+        return (GAP_CMD_INITIATED);
+
+    case BTM_BUSY:
+        return (GAP_ERR_BUSY);
+
+    case BTM_MODE_UNSUPPORTED:
+    case BTM_ILLEGAL_VALUE:
+        return (GAP_ERR_ILL_PARM);
+
+    case BTM_WRONG_MODE:
+        return (GAP_DEVICE_NOT_UP);
+
+    case BTM_UNKNOWN_ADDR:
+        return (GAP_BAD_BD_ADDR);
+
+    case BTM_DEVICE_TIMEOUT:
+        return (GAP_ERR_TIMEOUT);
+
+    default:
+        return (GAP_ERR_PROCESSING);
+    }
+}
diff --git a/stack/gatt/att_protocol.c b/stack/gatt/att_protocol.c
index a114a33..9c715af 100644
--- a/stack/gatt/att_protocol.c
+++ b/stack/gatt/att_protocol.c
@@ -390,13 +390,13 @@
     switch (op_code)
     {
     case GATT_RSP_READ_BLOB:
-        GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB: len = %d offset = %d", p_msg->attr_value.len, p_msg->attr_value.offset);
-        offset = p_msg->attr_value.offset;
-
     case GATT_RSP_PREPARE_WRITE:
-        if (offset == 0)
-            offset = p_msg->attr_value.offset;
-
+        GATT_TRACE_EVENT2 ("ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
+                    p_msg->attr_value.len, p_msg->attr_value.offset);
+        offset = p_msg->attr_value.offset;
+/* Coverity: [FALSE-POSITIVE error] intended fall through */
+/* Missing break statement between cases in switch statement */
+        /* fall through */
     case GATT_RSP_READ_BY_TYPE:
     case GATT_RSP_READ:
     case GATT_HANDLE_VALUE_NOTIF:
@@ -503,7 +503,10 @@
                 att_ret = GATT_INTERNAL_ERROR;
         }
         else
+        {
+            att_ret = GATT_CMD_STARTED;
             gatt_cmd_enq(p_tcb, clcb_idx, TRUE, cmd_code, p_cmd);
+        }
     }
     else
         att_ret = GATT_ILLEGAL_PARAMETER;
diff --git a/stack/gatt/gatt_api.c b/stack/gatt/gatt_api.c
index 7845f3c..ef437e1 100644
--- a/stack/gatt/gatt_api.c
+++ b/stack/gatt/gatt_api.c
@@ -849,6 +849,7 @@
             (disc_type == GATT_DISC_SRVC_BY_UUID &&
              p_param->service.len == 0))
         {
+            gatt_clcb_dealloc(p_clcb);
             return GATT_ILLEGAL_PARAMETER;
         }
 
@@ -1313,7 +1314,6 @@
 {
     tGATT_REG   *p_reg;
     tGATT_TCB   *p_tcb;
-    //tGATT_CLCB   *p_clcb;
     BD_ADDR     bda;
     UINT8       start_idx, found_idx;
     UINT16      conn_id;
@@ -1326,7 +1326,7 @@
         while (gatt_find_the_connected_bda(start_idx, bda, &found_idx))
         {
             p_tcb = gatt_find_tcb_by_addr(bda);
-            if (p_reg->app_cb.p_conn_cb)
+            if (p_reg->app_cb.p_conn_cb && p_tcb)
             {
                 conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, gatt_if);
                 (*p_reg->app_cb.p_conn_cb)(gatt_if, bda, conn_id, TRUE, 0);
@@ -1341,7 +1341,8 @@
 **
 ** Function         GATT_Connect
 **
-** Description      This function initiate a connecttion to a ATT server.
+** Description      This function initiate a connecttion to a remote device on GATT
+**                  channel.
 **
 ** Parameters       gatt_if: applicaiton interface
 **                  bd_addr: peer device address.
@@ -1366,7 +1367,7 @@
     if (is_direct)
         status = gatt_act_connect (p_reg, bd_addr);
     else
-        status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr);
+        status = gatt_update_auto_connect_dev(gatt_if,TRUE, bd_addr, TRUE);
 
     return status;
 
@@ -1376,7 +1377,8 @@
 **
 ** Function         GATT_CancelConnect
 **
-** Description      This function initiate a connecttion to a ATT server.
+** Description      This function terminate the connection initaition to a remote
+**                  device on GATT channel.
 **
 ** Parameters       gatt_if: client interface. If 0 used as unconditionally disconnect,
 **                          typically used for direct connection cancellation.
@@ -1454,7 +1456,8 @@
 **
 ** Function         GATT_Disconnect
 **
-** Description      This function disconnect a logic channel.
+** Description      This function disconnect the GATT channel for this registered
+**                  application.
 **
 ** Parameters       conn_id: connection identifier.
 **
@@ -1550,6 +1553,50 @@
     return status;
 }
 
-#endif
 
+/*******************************************************************************
+**
+** Function         GATT_Listen
+**
+** Description      This function start or stop LE advertisement and listen for
+**                  connection.
+**
+** Parameters       gatt_if: applicaiton interface
+**                  p_bd_addr: listen for specific address connection, or NULL for
+**                             listen to all device connection.
+**                  start: is a direct conenection or a background auto connection
+**
+** Returns          TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr)
+{
+    tGATT_REG    *p_reg;
+    BOOLEAN status = TRUE;
+
+    GATT_TRACE_API1 ("GATT_Listen gatt_if=%d", gatt_if);
+
+    /* Make sure app is registered */
+    if ((p_reg = gatt_get_regcb(gatt_if)) == NULL)
+    {
+        GATT_TRACE_ERROR1("GATT_Listen - gatt_if =%d is not registered", gatt_if);
+        return(FALSE);
+    }
+
+    if (bd_addr != NULL)
+    {
+        status = gatt_update_auto_connect_dev(gatt_if,start, bd_addr, FALSE);
+    }
+    else
+    {
+        p_reg->listening = start ? GATT_LISTEN_TO_ALL : GATT_LISTEN_TO_NONE;
+    }
+
+    gatt_update_listen_mode();
+
+    return status;
+
+}
+
+#endif
 
diff --git a/stack/gatt/gatt_attr.c b/stack/gatt/gatt_attr.c
index b7ec2fc..459580e 100644
--- a/stack/gatt/gatt_attr.c
+++ b/stack/gatt/gatt_attr.c
@@ -183,7 +183,7 @@
             break;
 
         case GATTS_REQ_TYPE_WRITE_EXEC:
-            //case GATT_CMD_WRITE:
+        case GATT_CMD_WRITE:
             ignore = TRUE;
             GATT_TRACE_EVENT0("Ignore GATT_REQ_EXEC_WRITE/WRITE_CMD" );
             break;
@@ -269,7 +269,7 @@
 
     /* start service
     */
-    status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATT_TRANSPORT_LE_BR_EDR);
+    status = GATTS_StartService (gatt_cb.gatt_if, service_handle, GATTP_TRANSPORT_SUPPORTED );
 
     GATT_TRACE_DEBUG2 ("gatt_profile_db_init:  gatt_if=%d   start status%d",
                        gatt_cb.gatt_if,  status);
diff --git a/stack/gatt/gatt_auth.c b/stack/gatt/gatt_auth.c
index de0c14f..df42758 100644
--- a/stack/gatt/gatt_auth.c
+++ b/stack/gatt/gatt_auth.c
@@ -48,6 +48,9 @@
     BOOLEAN             status = FALSE;
     UINT8                *p_signature;
 
+    /* do not need to mark channel securoty activity for data signing */
+    gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_OK);
+
     p_data = (UINT8 *)GKI_getbuf((UINT16)(p_attr->len + 3)); /* 3 = 2 byte handle + opcode */
 
     if (p_data != NULL)
@@ -69,7 +72,7 @@
         {
             p_attr->len += BTM_BLE_AUTH_SIGN_LEN;
             gatt_set_ch_state(p_clcb->p_tcb, GATT_CH_OPEN);
-            gatt_act_write(p_clcb);
+            gatt_act_write(p_clcb, GATT_SEC_SIGN_DATA);
         }
         else
         {
@@ -126,10 +129,10 @@
 ** Returns          void.
 **
 *******************************************************************************/
-void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB   *p_clcb)
+void gatt_sec_check_complete(BOOLEAN sec_check_ok, tGATT_CLCB   *p_clcb, UINT8 sec_act)
 {
-    p_clcb->p_tcb->p_clcb = NULL;
-    gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
+    if (GKI_queue_is_empty(&p_clcb->p_tcb->pending_enc_clcb))
+        gatt_set_sec_act(p_clcb->p_tcb, GATT_SEC_NONE);
 
     if (!sec_check_ok)
     {
@@ -137,7 +140,7 @@
     }
     else if (p_clcb->operation == GATTC_OPTYPE_WRITE)
     {
-        gatt_act_write(p_clcb);
+        gatt_act_write(p_clcb, sec_act);
     }
     else if (p_clcb->operation == GATTC_OPTYPE_READ)
     {
@@ -158,28 +161,51 @@
     tGATT_TCB   *p_tcb;
     UINT8       sec_flag;
     BOOLEAN     status = FALSE;
+    tGATT_PENDING_ENC_CLCB  *p_buf;
+    UINT16       count;
 
     GATT_TRACE_DEBUG0("gatt_enc_cmpl_cback");
     if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
     {
-        gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+        if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+            return;
 
-        if (result == BTM_SUCCESS)
+        if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
         {
-            if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+            if (result == BTM_SUCCESS)
             {
-                BTM_GetSecurityFlags(bd_addr, &sec_flag);
-                if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+                if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENCRYPT_MITM )
+                {
+                    BTM_GetSecurityFlags(bd_addr, &sec_flag);
+                    if (sec_flag & sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+                    {
+                        status = TRUE;
+                    }
+                }
+                else
                 {
                     status = TRUE;
                 }
             }
-            else
+            gatt_sec_check_complete(status , p_buf->p_clcb, p_tcb->sec_act);
+            GKI_freebuf(p_buf);
+            /* start all other pending operation in queue */
+            count = p_tcb->pending_enc_clcb.count;
+            for (; count > 0; count --)
             {
-                status = TRUE;
+                if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+                {
+                    gatt_security_check_start(p_buf->p_clcb);
+                    GKI_freebuf(p_buf);
+                }
+                else
+                    break;
             }
         }
-        gatt_sec_check_complete(status , (tGATT_CLCB   *)p_tcb->p_clcb);
+        else
+        {
+            GATT_TRACE_ERROR0("Unknown operation encryption completed");
+        }
     }
     else
     {
@@ -189,6 +215,48 @@
 
 /*******************************************************************************
 **
+** Function         gatt_notify_enc_cmpl
+**
+** Description      link encryption complete notification for all encryption process
+**                  initiated outside GATT.
+**
+** Returns
+**
+*******************************************************************************/
+void gatt_notify_enc_cmpl(BD_ADDR bd_addr)
+{
+    tGATT_TCB   *p_tcb;
+    tGATT_PENDING_ENC_CLCB  *p_buf;
+    UINT16       count;
+
+    if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
+    {
+        if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING)
+        {
+            gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+
+            count = p_tcb->pending_enc_clcb.count;
+
+            for (; count > 0; count --)
+            {
+                if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_dequeue (&p_tcb->pending_enc_clcb)) != NULL)
+                {
+                    gatt_security_check_start(p_buf->p_clcb);
+                    GKI_freebuf(p_buf);
+                }
+                else
+                    break;
+            }
+        }
+    }
+    else
+    {
+        GATT_TRACE_DEBUG0("notify GATT for encryption completion of unknown device");
+    }
+    return;
+}
+/*******************************************************************************
+**
 ** Function         gatt_set_sec_act
 **
 ** Description      This function set the sec_act in clcb
@@ -243,18 +311,32 @@
     BOOLEAN             is_link_key_known=FALSE;
     BOOLEAN             is_key_mitm=FALSE;
     UINT8               key_type;
+    tBTM_BLE_SEC_REQ_ACT    sec_act = BTM_LE_SEC_NONE;
 
     if (auth_req == GATT_AUTH_REQ_NONE )
         return act;
 
     is_le_link = btm_ble_check_link_type(p_tcb->peer_bda);
     BTM_GetSecurityFlags(p_tcb->peer_bda, &sec_flag);
+    btm_ble_link_sec_check(p_tcb->peer_bda, auth_req, &sec_act);
+
+    /* if a encryption is pending, need to wait */
+    if (sec_act == BTM_BLE_SEC_REQ_ACT_DISCARD &&
+        auth_req != GATT_AUTH_REQ_NONE)
+        return GATT_SEC_ENC_PENDING;
 
     if (sec_flag & BTM_SEC_FLAG_ENCRYPTED)
     {
         is_link_encrypted = TRUE;
+        is_link_key_known = TRUE;
+
+        if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
+        {
+            is_key_mitm = TRUE;
+        }
+
     }
-    if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
+    else if (sec_flag & BTM_SEC_FLAG_LKEY_KNOWN)
     {
         is_link_key_known = TRUE;
         if (sec_flag & BTM_SEC_FLAG_LKEY_AUTHED)
@@ -397,48 +479,49 @@
     tBTM_BLE_SEC_ACT    btm_ble_sec_act;
     BOOLEAN             status = TRUE;
     tBTM_STATUS         btm_status;
+    tGATT_SEC_ACTION    sec_act_old =  gatt_get_sec_act(p_tcb);
 
-    if ( gatt_get_ch_state(p_tcb) == GATT_CH_OPEN)
-    {
-        gatt_sec_act = gatt_determine_sec_act(p_clcb);
+    gatt_sec_act = gatt_determine_sec_act(p_clcb);
+
+    if (sec_act_old == GATT_SEC_NONE)
         gatt_set_sec_act(p_tcb, gatt_sec_act);
-        switch (gatt_sec_act )
-        {
-            case GATT_SEC_SIGN_DATA:
-                GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
-                gatt_set_ch_state(p_tcb, GATT_CH_W4_DATA_SIGN_COMP);
-                gatt_sign_data(p_clcb);
-                break;
-            case GATT_SEC_ENCRYPT:
-            case GATT_SEC_ENCRYPT_NO_MITM:
-            case GATT_SEC_ENCRYPT_MITM:
+
+    switch (gatt_sec_act )
+    {
+        case GATT_SEC_SIGN_DATA:
+            GATT_TRACE_DEBUG0("gatt_security_check_start: Do data signing");
+            gatt_sign_data(p_clcb);
+            break;
+        case GATT_SEC_ENCRYPT:
+        case GATT_SEC_ENCRYPT_NO_MITM:
+        case GATT_SEC_ENCRYPT_MITM:
+            if (sec_act_old < GATT_SEC_ENCRYPT)
+            {
                 GATT_TRACE_DEBUG0("gatt_security_check_start: Encrypt now or key upgreade first");
-                gatt_convert_sec_action(p_tcb->sec_act, &btm_ble_sec_act);
-                gatt_set_ch_state(p_tcb, GATT_CH_W4_SEC_COMP);
-                p_tcb->p_clcb = p_clcb;           /* keep the clcb pointer in CCB */
+                gatt_convert_sec_action(gatt_sec_act, &btm_ble_sec_act);
                 btm_status = BTM_SetEncryption(p_tcb->peer_bda, gatt_enc_cmpl_cback, &btm_ble_sec_act);
                 if ( (btm_status != BTM_SUCCESS) && (btm_status != BTM_CMD_STARTED))
                 {
                     GATT_TRACE_ERROR1("gatt_security_check_start BTM_SetEncryption failed btm_status=%d", btm_status);
-                    p_tcb->p_clcb  = NULL;
                     status = FALSE;
                 }
-                break;
-            default:
-                gatt_sec_check_complete(TRUE, p_clcb);
-                break;
-        }
-
-        if (status == FALSE)
-        {
-            gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
-            gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
-        }
+            }
+            if (status)
+                gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+            break;
+        case GATT_SEC_ENC_PENDING:
+            gatt_add_pending_enc_channel_clcb (p_tcb, p_clcb);
+            /* wait for link encrypotion to finish */
+            break;
+        default:
+            gatt_sec_check_complete(TRUE, p_clcb, gatt_sec_act);
+            break;
     }
-    else
+
+    if (status == FALSE)
     {
-        GATT_TRACE_ERROR0("gatt_security_check_start channel not open");
-        status = FALSE;
+        gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
+        gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
     }
 
     return status;
diff --git a/stack/gatt/gatt_cl.c b/stack/gatt/gatt_cl.c
index 91fb985..e9402aa 100644
--- a/stack/gatt/gatt_cl.c
+++ b/stack/gatt/gatt_cl.c
@@ -201,7 +201,7 @@
 ** Returns          void.
 **
 *******************************************************************************/
-void gatt_act_write (tGATT_CLCB *p_clcb)
+void gatt_act_write (tGATT_CLCB *p_clcb, UINT8 sec_act)
 {
     tGATT_TCB           *p_tcb = p_clcb->p_tcb;
     UINT8               rt = GATT_SUCCESS, op_code;
@@ -213,7 +213,7 @@
         {
             case GATT_WRITE_NO_RSP:
                 p_clcb->s_handle = p_attr->handle;
-                op_code = (p_tcb->sec_act & GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
+                op_code = (sec_act == GATT_SEC_SIGN_DATA) ? GATT_SIGN_CMD_WRITE : GATT_CMD_WRITE;
                 rt = gatt_send_write_msg(p_tcb,
                                          p_clcb->clcb_idx,
                                          op_code,
@@ -379,59 +379,7 @@
     }
 }
 
-/*******************************************************************************
-**
-** Function         gatt_proc_disc_read_by_type_rsp
-**
-** Description      This function process the read by type response and send another
-**                  request if needed.
-**
-** Returns          void.
-**
-*******************************************************************************/
-void gatt_proc_disc_read_by_type_rsp(tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
-{
-    /*
-      tGATT_TCB   *p_tcb = p_clcb->p_tcb;
-      tGATT_DISCOVERY_DB  *p_db = p_clcb->p_disc_db;
-      tGATT_DISC_REC      *p_rec;
-      tGATT_STATUS         status = GATT_INTERNAL_ERROR;
 
-
-      if ((p_rec = gatt_add_record(p_clcb->p_disc_db)) != NULL)
-      {
-          p_rec->handle   = handle;
-          p_rec->type     = p_db->uuid_filter;
-          p_rec->attr_len = len;
-
-          // copy the attibute value into DB
-          p_rec->p_value  = p_db->p_free_mem;
-          memcpy(p_rec->p_value, p_value, len);
-          p_db->p_free_mem += len;
-          p_db->mem_free -= len;
-
-          if (handle < p_clcb->e_handle)
-          {
-              // send another request
-              if (gatt_act_send_browse(p_tcb, p_clcb->conn_id,
-                                       GATT_REQ_READ_BY_TYPE,
-                                       (UINT16)(handle + 1), // starting handle
-                                       p_clcb->e_handle,              // end handle
-                                       p_clcb->p_disc_db->uuid_filter) // uuid filter /
-                          == GATT_SUCCESS)
-              {
-                  status = GATT_SUCCESS;
-              }
-          }
-      }
-      else
-          status = GATT_DB_FULL;
-
-      if (status != GATT_SUCCESS) // DB full
-      {
-          gatt_end_operation(p_clcb, status, NULL);
-      }*/
-}
 /*******************************************************************************
 **
 ** Function         gatt_process_find_type_value_rsp
@@ -445,7 +393,6 @@
 void gatt_process_find_type_value_rsp (tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT16 len, UINT8 *p_data)
 {
     tGATT_DISC_RES      result;
-    tGATT_DISC_VALUE    record_value;
     UINT8               *p = p_data;
 
     GATT_TRACE_DEBUG0("gatt_process_find_type_value_rsp ");
@@ -453,7 +400,7 @@
     if (p_clcb->operation != GATTC_OPTYPE_DISCOVERY || p_clcb->op_subtype != GATT_DISC_SRVC_BY_UUID)
         return;
 
-    memset (&record_value, 0, sizeof(tGATT_DISC_VALUE));
+    memset (&result, 0, sizeof(tGATT_DISC_RES));
     result.type.len = 2;
     result.type.uu.uuid16 = GATT_UUID_PRI_SERVICE;
 
@@ -461,17 +408,17 @@
     while (len >= 4)
     {
         STREAM_TO_UINT16 (result.handle, p);
-        STREAM_TO_UINT16 (record_value.handle, p);
-        len -= 4;
+        STREAM_TO_UINT16 (result.value.group_value.e_handle, p);
+        memcpy (&result.value.group_value.service_type,  &p_clcb->uuid, sizeof(tBT_UUID));
 
-        memcpy (&result.value, &record_value, sizeof (result.value));;
+        len -= 4;
 
         if (p_clcb->p_reg->app_cb.p_disc_res_cb)
             (*p_clcb->p_reg->app_cb.p_disc_res_cb)(p_clcb->conn_id, p_clcb->op_subtype, &result);
     }
 
     /* last handle  + 1 */
-    p_clcb->s_handle = (record_value.handle == 0) ? 0 : (record_value.handle + 1);
+    p_clcb->s_handle = (result.value.group_value.e_handle == 0) ? 0 : (result.value.group_value.e_handle + 1);
     /* initiate another request */
     gatt_act_discovery(p_clcb) ;
 }
@@ -721,12 +668,12 @@
             attp_send_cl_msg(p_tcb, 0, GATT_HANDLE_VALUE_CONF, NULL);
     }
 
+    encrypt_status = gatt_get_link_encrypt_status(p_tcb);
     for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++)
     {
         if (p_reg->in_use && p_reg->app_cb.p_cmpl_cb)
         {
             conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
-            encrypt_status = gatt_get_link_encrypt_status(p_tcb);
             (*p_reg->app_cb.p_cmpl_cb) (conn_id, event, encrypt_status, (tGATT_CL_COMPLETE *)&value);
         }
     }
@@ -882,7 +829,12 @@
                 gatt_end_operation(p_clcb, GATT_INVALID_HANDLE, NULL);
                 return;
             }
-            gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p);
+            if (!gatt_parse_uuid_from_cmd(&record_value.dclr_value.char_uuid, (UINT16)(value_len - 3), &p))
+            {
+                gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+                /* invalid format, and skip the result */
+                return;
+            }
 
             /* UUID not matching */
             if (!gatt_uuid_compare(record_value.dclr_value.char_uuid, p_clcb->uuid))
@@ -1087,6 +1039,8 @@
 {
     tGATT_CMD_Q  *p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
     BOOLEAN     sent = FALSE;
+    UINT8       rsp_code;
+    tGATT_CLCB   *p_clcb = NULL;
 
     while (!sent &&
            p_tcb->pending_cl_req != p_tcb->next_slot_inq &&
@@ -1099,7 +1053,21 @@
             p_cmd->to_send = FALSE;
             p_cmd->p_cmd = NULL;
 
-            gatt_start_rsp_timer (p_tcb);
+            /* dequeue the request if is write command or sign write */
+            if (p_cmd->op_code != GATT_CMD_WRITE && p_cmd->op_code != GATT_SIGN_CMD_WRITE)
+            {
+                gatt_start_rsp_timer (p_tcb);
+            }
+            else
+            {
+                p_clcb = gatt_cmd_dequeue(p_tcb, &rsp_code);
+
+                /* if no ack needed, keep sending */
+                sent = FALSE;
+                p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
+                /* send command complete callback here */
+                gatt_end_operation(p_clcb, GATT_SUCCESS, NULL);
+            }
         }
         else
         {
@@ -1109,6 +1077,7 @@
             p_tcb->pending_cl_req ++;
             p_cmd = &p_tcb->cl_cmd_q[p_tcb->pending_cl_req];
         }
+
     }
     return sent;
 }
diff --git a/stack/gatt/gatt_db.c b/stack/gatt/gatt_db.c
index bd94e50..fa636fb 100644
--- a/stack/gatt/gatt_db.c
+++ b/stack/gatt/gatt_db.c
@@ -134,7 +134,8 @@
         return GATT_READ_NOT_PERMIT;
     }
 
-    if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
+    if ((perm & GATT_READ_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED) &&
+        !(sec_flag & BTM_SEC_FLAG_ENCRYPTED))
     {
         GATT_TRACE_ERROR0( "GATT_INSUF_AUTHENTICATION");
         return GATT_INSUF_AUTHENTICATION;
@@ -731,14 +732,21 @@
                                    p_attr->permission,
                                    min_key_size);
 
-                if ((op_code == GATT_CMD_WRITE) && (perm & GATT_WRITE_SIGNED_PERM) )
+                if ((op_code == GATT_CMD_WRITE || op_code == GATT_REQ_WRITE)
+                    && (perm & GATT_WRITE_SIGNED_PERM))
                 {
                     /* use the rules for the mixed security see section 10.2.3*/
-                    if (perm & GATT_PERM_WRITE_SIGNED)
+                    /* use security mode 1 level 2 when the following condition follows */
+                    /* LE security mode 2 level 1 and LE security mode 1 level 2 */
+                    if ((perm & GATT_PERM_WRITE_SIGNED) && (perm & GATT_PERM_WRITE_ENCRYPTED))
                     {
                         perm = GATT_PERM_WRITE_ENCRYPTED;
                     }
-                    else
+                    /* use security mode 1 level 3 when the following condition follows */
+                    /* LE security mode 2 level 2 and security mode 1 and LE */
+                    else if (((perm & GATT_PERM_WRITE_SIGNED_MITM) && (perm & GATT_PERM_WRITE_ENCRYPTED)) ||
+                              /* LE security mode 2 and security mode 1 level 3 */
+                             ((perm & GATT_WRITE_SIGNED_PERM) && (perm & GATT_PERM_WRITE_ENC_MITM)))
                     {
                         perm = GATT_PERM_WRITE_ENC_MITM;
                     }
@@ -759,6 +767,7 @@
                     status = GATT_WRITE_NOT_PERMIT;
                     GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_WRITE_NOT_PERMIT");
                 }
+                /* require authentication, but not been authenticated */
                 else if ((perm & GATT_WRITE_AUTH_REQUIRED ) && !(sec_flag & GATT_SEC_FLAG_LKEY_UNAUTHED))
                 {
                     status = GATT_INSUF_AUTHENTICATION;
@@ -779,6 +788,12 @@
                     status = GATT_INSUF_KEY_SIZE;
                     GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_KEY_SIZE");
                 }
+                /* LE security mode 2 attribute  */
+                else if (perm & GATT_WRITE_SIGNED_PERM && op_code != GATT_SIGN_CMD_WRITE && !(sec_flag & GATT_SEC_FLAG_ENCRYPTED))
+                {
+                    status = GATT_INSUF_AUTHENTICATION;
+                    GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INSUF_AUTHENTICATION: LE security mode 2 required");
+                }
                 else /* writable: must be char value declaration or char descritpors */
                 {
                     if(p_attr->uuid_type == GATT_ATTR_UUID_TYPE_16)
@@ -793,6 +808,9 @@
                             break;
 
                         case GATT_UUID_CHAR_CLIENT_CONFIG:
+/* coverity[MISSING_BREAK] */
+/* intnended fall through, ignored */
+                            /* fall through */
                         case GATT_UUID_CHAR_SRVR_CONFIG:
                             max_size = 2;
                         case GATT_UUID_CHAR_DESCRIPTION:
@@ -828,7 +846,7 @@
                         }
                         else if (len != max_size)    /* data does not match the required format */
                         {
-                            status = GATT_INVALID_PDU;
+                            status = GATT_INVALID_ATTR_LEN;
                             GATT_TRACE_ERROR0( "gatts_write_attr_perm_check - GATT_INVALID_PDU");
                         }
                         else
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 44a2bc1..48278c2 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -42,10 +42,11 @@
 /* security action for GATT write and read request */
 #define GATT_SEC_NONE              0
 #define GATT_SEC_OK                1
-#define GATT_SEC_ENCRYPT           2    /* encrypt the link with current key */
-#define GATT_SEC_ENCRYPT_NO_MITM   3    /* unauthenticated encryption or better */
-#define GATT_SEC_ENCRYPT_MITM      4    /* authenticated encryption */
-#define GATT_SEC_SIGN_DATA         5   /* compute the signature for the write cmd */
+#define GATT_SEC_SIGN_DATA         2   /* compute the signature for the write cmd */
+#define GATT_SEC_ENCRYPT           3    /* encrypt the link with current key */
+#define GATT_SEC_ENCRYPT_NO_MITM   4    /* unauthenticated encryption or better */
+#define GATT_SEC_ENCRYPT_MITM      5    /* authenticated encryption */
+#define GATT_SEC_ENC_PENDING       6   /* wait for link encryption pending */
 typedef UINT8 tGATT_SEC_ACTION;
 
 
@@ -214,7 +215,6 @@
 typedef struct
 {
     tGATT_SVC_DB    *p_db;      /* pointer to the service database */
-    //tGATT_SR_CBACK  sr_cb;      /* server callback functions */
     tBT_UUID        app_uuid;           /* applicatino UUID */
     UINT32          sdp_handle; /* primamry service SDP handle */
     UINT16          service_instance;   /* service instance number */
@@ -225,6 +225,8 @@
     BOOLEAN         in_use;
 } tGATT_SR_REG;
 
+#define GATT_LISTEN_TO_ALL  0xff
+#define GATT_LISTEN_TO_NONE 0
 
 /* Data Structure used for GATT server */
 /* An GATT registration record consists of a handle, and 1 or more attributes */
@@ -237,6 +239,7 @@
     tGATT_CBACK  app_cb;
     tGATT_IF     gatt_if; /* one based */
     BOOLEAN      in_use;
+    UINT8        listening; /* if adv for all has been enabled */
 } tGATT_REG;
 
 
@@ -332,7 +335,7 @@
 
 typedef struct
 {
-    void            *p_clcb;            /* which clcb is doing encryption */
+    BUFFER_Q        pending_enc_clcb;   /* pending encryption channel q */
     tGATT_SEC_ACTION sec_act;
     BD_ADDR         peer_bda;
     UINT32          trans_id;
@@ -366,6 +369,7 @@
     UINT8           tcb_idx;
 } tGATT_TCB;
 
+
 /* logic channel */
 typedef struct
 {
@@ -395,6 +399,12 @@
     BOOLEAN                 in_use;
 } tGATT_CLCB;
 
+typedef struct
+{
+    tGATT_CLCB  *p_clcb;
+}tGATT_PENDING_ENC_CLCB;
+
+
 #define GATT_SIGN_WRITE             1
 #define GATT_VERIFY_SIGN_DATA       2
 
@@ -429,6 +439,7 @@
 typedef struct
 {
     tGATT_IF        gatt_if[GATT_MAX_APPS];
+    tGATT_IF        listen_gif[GATT_MAX_APPS];
     BD_ADDR         remote_bda;
     BOOLEAN         in_use;
 }tGATT_BG_CONN_DEV;
@@ -468,6 +479,7 @@
     BOOLEAN             enable_err_rsp;
     UINT8               req_op_code;
     UINT8               err_status;
+    UINT16              handle;
 #endif
 
     tGATT_PROFILE_CLCB  profile_clcb[GATT_MAX_APPS];
@@ -551,6 +563,7 @@
 extern void gatt_start_ind_ack_timer(tGATT_TCB *p_tcb);
 extern tGATT_STATUS gatt_send_error_rsp(tGATT_TCB *p_tcb, UINT8 err_code, UINT8 op_code, UINT16 handle, BOOLEAN deq);
 extern void gatt_dbg_display_uuid(tBT_UUID bt_uuid);
+extern tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb );
 
 extern tGATTS_PENDING_NEW_SRV_START *gatt_sr_is_new_srv_chg(tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
 
@@ -563,6 +576,7 @@
 extern tGATT_VALUE *gatt_add_pending_ind(tGATT_TCB  *p_tcb, tGATT_VALUE *p_ind);
 extern tGATTS_PENDING_NEW_SRV_START *gatt_add_pending_new_srv_start( tGATTS_HNDL_RANGE *p_new_srv_start);
 extern void gatt_free_srvc_db_buffer_app_id(tBT_UUID *p_app_id);
+extern void gatt_update_listen_mode(void);
 
 /* reserved handle list */
 extern tGATT_HDL_LIST_ELEM *gatt_find_hdl_buffer_by_app_id (tBT_UUID *p_app_uuid128, tBT_UUID *p_svc_uuid, UINT16 svc_inst);
@@ -578,13 +592,11 @@
 extern tGATTS_SRV_CHG *gatt_add_srv_chg_clt(tGATTS_SRV_CHG *p_srv_chg);
 
 /* for background connection */
-extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr);
-extern BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
+extern BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initiator);
 extern BOOLEAN gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV *p_dev, tGATT_IF gatt_if);
 extern BOOLEAN gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, BD_ADDR bd_addr);
 extern UINT8 gatt_get_num_apps_for_bg_dev(BD_ADDR bd_addr);
 extern BOOLEAN gatt_find_app_for_bg_dev(BD_ADDR bd_addr, tGATT_IF *p_gatt_if);
-extern BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr);
 extern tGATT_BG_CONN_DEV * gatt_find_bg_dev(BD_ADDR remote_bda);
 extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if);
 extern void gatt_reset_bgdev_list(void);
@@ -634,7 +646,7 @@
 
 extern void gatt_act_discovery(tGATT_CLCB *p_clcb);
 extern void gatt_act_read(tGATT_CLCB *p_clcb, UINT16 offset);
-extern void gatt_act_write(tGATT_CLCB *p_clcb);
+extern void gatt_act_write(tGATT_CLCB *p_clcb, UINT8 sec_act);
 extern UINT8 gatt_act_send_browse(tGATT_TCB *p_tcb, UINT16 index, UINT8 op, UINT16 s_handle, UINT16 e_handle,
                                   tBT_UUID uuid);
 extern tGATT_CLCB *gatt_cmd_dequeue(tGATT_TCB *p_tcb, UINT8 *p_opcode);
@@ -666,6 +678,7 @@
 extern void gatts_update_srv_list_elem(UINT8 i_sreg, UINT16 handle, BOOLEAN is_primary);
 extern tBT_UUID * gatts_get_service_uuid (tGATT_SVC_DB *p_db);
 
+extern void gatt_reset_bgdev_list(void);
 #endif
 
 #endif /* BLE_INCLUDED */
diff --git a/stack/gatt/gatt_main.c b/stack/gatt/gatt_main.c
index 06d87bb..dcd9398 100644
--- a/stack/gatt/gatt_main.c
+++ b/stack/gatt/gatt_main.c
@@ -49,7 +49,7 @@
 static void gatt_l2cif_disconnect_ind_cback (UINT16 l2cap_cid, BOOLEAN ack_needed);
 static void gatt_l2cif_disconnect_cfm_cback (UINT16 l2cap_cid, UINT16 result);
 static void gatt_l2cif_data_ind_cback (UINT16 l2cap_cid, BT_HDR *p_msg);
-static void gatt_send_conn_cback (BOOLEAN is_bg_conn, tGATT_TCB *p_tcb);
+static void gatt_send_conn_cback (tGATT_TCB *p_tcb);
 
 static const tL2CAP_APPL_INFO dyn_info =
 {
@@ -145,7 +145,8 @@
 
     BTM_ReadDevInfo(rem_bda, &dev_type, &addr_type);
 
-    gatt_set_ch_state(p_tcb, GATT_CH_CONN);
+    if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
+        gatt_set_ch_state(p_tcb, GATT_CH_CONN);
 
     if (dev_type == BT_DEVICE_TYPE_BLE)
     {
@@ -188,8 +189,10 @@
             if (p_tcb->att_lcid == L2CAP_ATT_CID)
             {
                 if (ch_state == GATT_CH_OPEN)
+                {
                     /* only LCB exist between remote device and local */
                     ret = L2CA_RemoveFixedChnl (L2CAP_ATT_CID, rem_bda);
+                }
                 else
                 {
                     gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
@@ -315,13 +318,22 @@
 {
     BOOLEAN     ret = FALSE;
     tGATT_TCB   *p_tcb;
+    UINT8       st;
 
     GATT_TRACE_DEBUG0("gatt_act_connect");
 
     if ((p_tcb = gatt_find_tcb_by_addr(bd_addr)) != NULL)
     {
         ret = TRUE;
-        if(gatt_get_ch_state(p_tcb) == GATT_CH_CLOSING )
+        st = gatt_get_ch_state(p_tcb);
+
+        /* before link down, another app try to open a GATT connection */
+        if(st == GATT_CH_OPEN &&  gatt_num_apps_hold_link(p_tcb) == 0 )
+        {
+            if (!gatt_connect(bd_addr,  p_tcb))
+                ret = FALSE;
+        }
+        else if(st == GATT_CH_CLOSING)
         {
             /* need to complete the closing first */
             ret = FALSE;
@@ -370,8 +382,6 @@
 
     BOOLEAN                 check_srv_chg = FALSE;
     tGATTS_SRV_CHG          *p_srv_chg_clt=NULL;
-    BOOLEAN                 is_bg_conn = FALSE;
-
 
     GATT_TRACE_DEBUG3 ("GATT   ATT protocol channel with BDA: %08x%04x is %s",
                        (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
@@ -407,7 +417,7 @@
                 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
                 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
 
-                gatt_send_conn_cback(FALSE, p_tcb);
+                gatt_send_conn_cback(p_tcb);
             }
             else /* there was an exisiting link, ignore the callback */
             {
@@ -425,11 +435,8 @@
                 gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
 
                 p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
-                if (L2CA_GetBleConnRole(p_tcb->peer_bda)== HCI_ROLE_MASTER)
-                {
-                    is_bg_conn = TRUE;
-                }
-                gatt_send_conn_cback (is_bg_conn, p_tcb);
+
+                gatt_send_conn_cback (p_tcb);
                 if (check_srv_chg)
                 {
                     gatt_chk_srv_chg (p_srv_chg_clt);
@@ -630,12 +637,15 @@
                     }
                     else
                     {
-                        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+                        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+                            btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+                        {
                             gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+                        }
                     }
 
                     /* send callback */
-                    gatt_send_conn_cback(FALSE, p_tcb);
+                    gatt_send_conn_cback(p_tcb);
                 }
             }
             /* else failure */
@@ -692,12 +702,15 @@
                 }
                 else
                 {
-                    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+                    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+                        btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+                    {
                         gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+                    }
                 }
 
                 /* send callback */
-                gatt_send_conn_cback(FALSE, p_tcb);
+                gatt_send_conn_cback(p_tcb);
             }
         }
     }
@@ -726,8 +739,13 @@
             /* send L2CAP disconnect response */
             L2CA_DisconnectRsp(lcid);
         }
-        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+
+        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+            btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+        {
             gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+        }
+
         /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
         if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
             reason = GATT_CONN_TERMINATE_PEER_USER;
@@ -755,8 +773,12 @@
     /* look up clcb for this channel */
     if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL)
     {
-        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+        if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda) &&
+            btm_sec_is_le_capable_dev(p_tcb->peer_bda))
+        {
             gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+        }
+
         /* send disconnect callback */
         /* if ACL link is still up, no reason is logged, l2cap is disconnect from peer */
         if ((reason = L2CA_GetDisconnectReason(p_tcb->peer_bda)) == 0)
@@ -801,15 +823,14 @@
 ** Returns          void
 **
 *******************************************************************************/
-static void gatt_send_conn_cback(BOOLEAN is_bg_conn, tGATT_TCB *p_tcb)
+static void gatt_send_conn_cback(tGATT_TCB *p_tcb)
 {
     UINT8               i;
     tGATT_REG           *p_reg;
     tGATT_BG_CONN_DEV   *p_bg_dev=NULL;
     UINT16              conn_id;
 
-    if (is_bg_conn)
-        p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
+    p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
 
     /* notifying all applications for the connection up event */
     for (i = 0,  p_reg = gatt_cb.cl_rcb ; i < GATT_MAX_APPS; i++, p_reg++)
@@ -1015,7 +1036,7 @@
             while ((i <= num_clients) && status)
             {
                 req.client_read_index = i;
-                if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)))
+                if ((status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp)) == TRUE)
                 {
                     memcpy(&srv_chg_clt, &rsp.srv_chg ,sizeof(tGATTS_SRV_CHG));
                     if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL)
diff --git a/stack/gatt/gatt_sr.c b/stack/gatt/gatt_sr.c
index ddecdb3..71ba6a5 100644
--- a/stack/gatt/gatt_sr.c
+++ b/stack/gatt/gatt_sr.c
@@ -332,6 +332,18 @@
     tGATT_IF gatt_if;
     UINT16  conn_id;
 
+#if GATT_CONFORMANCE_TESTING == TRUE
+    if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code)
+    {
+        GATT_TRACE_DEBUG2("conf test forced err rsp for %s error status=%d",
+                           __FUNCTION__,gatt_cb.err_status);
+
+        gatt_send_error_rsp (p_tcb, gatt_cb.err_status, gatt_cb.req_op_code, 0, FALSE);
+
+        return;
+    }
+#endif
+
     STREAM_TO_UINT8(flag, p);
 
     /* mask the flag */
diff --git a/stack/gatt/gatt_utils.c b/stack/gatt/gatt_utils.c
index bd3aaf6..5470f4e 100644
--- a/stack/gatt/gatt_utils.c
+++ b/stack/gatt/gatt_utils.c
@@ -98,6 +98,23 @@
 
 /*******************************************************************************
 **
+** Function         gatt_free_pending_enc_queue
+**
+** Description       Free all buffers in pending encyption queue
+**
+** Returns       None
+**
+*******************************************************************************/
+void gatt_free_pending_enc_queue(tGATT_TCB *p_tcb)
+{
+    GATT_TRACE_DEBUG0("gatt_free_pending_enc_queue");
+    /* release all queued indications */
+    while (p_tcb->pending_enc_clcb.p_first)
+        GKI_freebuf (GKI_dequeue (&p_tcb->pending_enc_clcb));
+}
+
+/*******************************************************************************
+**
 ** Function         gatt_delete_dev_from_srv_chg_clt_list
 **
 ** Description    Delete a device from the service changed client lit
@@ -920,6 +937,8 @@
         if (allocated)
         {
             memset(p_tcb, 0, sizeof(tGATT_TCB));
+            GKI_init_q (&p_tcb->pending_enc_clcb);
+            GKI_init_q (&p_tcb->pending_ind_q);
             p_tcb->in_use = TRUE;
             p_tcb->tcb_idx = i;
         }
@@ -1258,7 +1277,6 @@
             p_sreg->type                = p_list->asgn_range.is_primary ? GATT_UUID_PRI_SERVICE: GATT_UUID_SEC_SERVICE;
             p_sreg->s_hdl               = p_list->asgn_range.s_handle;
             p_sreg->e_hdl               = p_list->asgn_range.e_handle;
-            //p_sreg->sr_cb               = *p_cback;
             p_sreg->p_db                = &p_list->svc_db;
 
             GATT_TRACE_DEBUG1 ("total GKI buffer in db [%d]",p_sreg->p_db->svc_buffer.count);
@@ -2109,6 +2127,7 @@
         btu_stop_timer (&p_tcb->ind_ack_timer_ent);
         btu_stop_timer (&p_tcb->conf_timer_ent);
         gatt_free_pending_ind(p_tcb);
+        gatt_free_pending_enc_queue(p_tcb);
 
         for (i = 0; i < GATT_MAX_APPS; i ++)
         {
@@ -2272,13 +2291,15 @@
 **
 ** Description      add/remove device from the back ground connection device list
 **
-** Returns          pointer to the device record
+** Returns          TRUE if device added to the list; FALSE failed
 **
 *******************************************************************************/
-BOOLEAN gatt_add_bg_dev_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_add_bg_dev_list(tGATT_REG *p_reg,  BD_ADDR bd_addr, BOOLEAN is_initator)
 {
+    tGATT_IF gatt_if =  p_reg->gatt_if;
     tGATT_BG_CONN_DEV   *p_dev = NULL;
-    UINT8   i;
+    UINT8       i;
+    BOOLEAN      ret = FALSE;
 
     if ((p_dev = gatt_find_bg_dev(bd_addr)) == NULL)
     {
@@ -2289,26 +2310,51 @@
     {
         for (i = 0; i < GATT_MAX_APPS; i ++)
         {
-            if (p_dev->gatt_if[i] == gatt_if)
+            if (is_initator)
             {
-                GATT_TRACE_ERROR0("device already in list");
-                return FALSE;
+                if (p_dev->gatt_if[i] == gatt_if)
+                {
+                    GATT_TRACE_ERROR0("device already in iniator white list");
+                    break;
+                }
+                else if (p_dev->gatt_if[i] == 0)
+                {
+                    p_dev->gatt_if[i] = gatt_if;
+                    if (i == 0)
+                        ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
+                    break;
+                }
             }
-            else if (p_dev->gatt_if[i] == 0)
+            else
             {
-                GATT_TRACE_DEBUG0("add device into list");
-                p_dev->gatt_if[i] = gatt_if;
-                return TRUE;
+                if (p_dev->listen_gif[i] == gatt_if)
+                {
+                    GATT_TRACE_ERROR0("device already in adv white list");
+                    return FALSE;
+                }
+                else if (p_dev->listen_gif[i] == 0)
+                {
+                    if (p_reg->listening == GATT_LISTEN_TO_ALL)
+                        p_reg->listening = GATT_LISTEN_TO_NONE;
+
+                    p_reg->listening ++;
+                    p_dev->listen_gif[i] = gatt_if;
+
+                    if (i == 0)
+                        ret = BTM_BleUpdateAdvWhitelist(TRUE, bd_addr);
+                    break;
+                }
             }
         }
     }
+    else
+    {
+        GATT_TRACE_ERROR0("no device record available");
+    }
 
-    GATT_TRACE_ERROR0("no device record available");
-
-    return FALSE;
+    return ret;
 }
 
-
 /*******************************************************************************
 **
 ** Function         gatt_remove_bg_dev_for_app
@@ -2325,7 +2371,7 @@
 
     if (p_tcb)
         gatt_update_app_use_link_flag(gatt_if, p_tcb, FALSE, FALSE);
-    status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr);
+    status = gatt_update_auto_connect_dev(gatt_if, FALSE, bd_addr, TRUE);
     return status;
 }
 
@@ -2393,13 +2439,15 @@
 **
 ** Function         gatt_remove_bg_dev_from_list
 **
-** Description      add/remove device from the back ground connection device list
+** Description      add/remove device from the back ground connection device list or
+**                  listening to advertising list.
 **
 ** Returns          pointer to the device record
 **
 *******************************************************************************/
-BOOLEAN gatt_remove_bg_dev_from_list(tGATT_IF gatt_if, BD_ADDR bd_addr)
+BOOLEAN gatt_remove_bg_dev_from_list(tGATT_REG *p_reg, BD_ADDR bd_addr, BOOLEAN is_initiator)
 {
+    tGATT_IF gatt_if = p_reg->gatt_if;
     tGATT_BG_CONN_DEV   *p_dev = NULL;
     UINT8   i, j;
     BOOLEAN ret = FALSE;
@@ -2409,25 +2457,47 @@
         return ret;
     }
 
-    for (i = 0; i < GATT_MAX_APPS && p_dev->gatt_if[i] > 0; i ++)
+    for (i = 0; i < GATT_MAX_APPS && (p_dev->gatt_if[i] > 0 || p_dev->listen_gif[i]); i ++)
     {
-        if (p_dev->gatt_if[i] == gatt_if)
+        if (is_initiator)
         {
-            p_dev->gatt_if[i] = 0;
-
-            for (j = i + 1; j < GATT_MAX_APPS; j ++)
-                p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
-
-            if (p_dev->gatt_if[0] == 0)
+            if (p_dev->gatt_if[i] == gatt_if)
             {
-                ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
-                memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
-            }
-            else
-                ret = TRUE;
+                p_dev->gatt_if[i] = 0;
+                /* move all element behind one forward */
+                for (j = i + 1; j < GATT_MAX_APPS; j ++)
+                    p_dev->gatt_if[j - 1] = p_dev->gatt_if[j];
 
-            break;
+                if (p_dev->gatt_if[0] == 0)
+                    ret = BTM_BleUpdateBgConnDev(FALSE, p_dev->remote_bda);
+                else
+                    ret = TRUE;
+
+                break;
+            }
         }
+        else
+        {
+            if (p_dev->listen_gif[i] == gatt_if)
+            {
+                p_dev->listen_gif[i] = 0;
+                p_reg->listening --;
+                /* move all element behind one forward */
+                for (j = i + 1; j < GATT_MAX_APPS; j ++)
+                    p_dev->listen_gif[j - 1] = p_dev->listen_gif[j];
+
+                if (p_dev->listen_gif[0] == 0)
+                    ret = BTM_BleUpdateAdvWhitelist(FALSE, p_dev->remote_bda);
+                else
+                    ret = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (i != GATT_MAX_APPS && p_dev->gatt_if[0] == 0 && p_dev->listen_gif[0] == 0)
+    {
+        memset(p_dev, 0, sizeof(tGATT_BG_CONN_DEV));
     }
 
     return ret;
@@ -2500,9 +2570,9 @@
 ** Returns          TRUE if connection started; FALSE if connection start failure.
 **
 *******************************************************************************/
-BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr)
+BOOLEAN gatt_update_auto_connect_dev (tGATT_IF gatt_if, BOOLEAN add, BD_ADDR bd_addr, BOOLEAN is_initator)
 {
-    BOOLEAN         ret = FALSE, exist_dev = FALSE;
+    BOOLEAN         ret = FALSE;
     tGATT_REG        *p_reg;
     tGATT_TCB       *p_tcb = gatt_find_tcb_by_addr(bd_addr);
 
@@ -2516,27 +2586,17 @@
 
     if (add)
     {
-        /* new device */
-        if (gatt_find_bg_dev(bd_addr))
-            exist_dev = TRUE;
+        ret = gatt_add_bg_dev_list(p_reg, bd_addr, is_initator);
 
-        if (gatt_add_bg_dev_list(gatt_if, bd_addr))
+        if (ret && p_tcb != NULL)
         {
-            if (!exist_dev)
-            {
-                ret = BTM_BleUpdateBgConnDev(TRUE, bd_addr);
-            }
-            else
-                ret = TRUE;
-
             /* if a connected device, update the link holding number */
-            if (p_tcb != NULL)
-                gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
+            gatt_update_app_use_link_flag(gatt_if, p_tcb, TRUE, TRUE);
         }
     }
     else
     {
-        ret = gatt_remove_bg_dev_from_list(gatt_if, bd_addr);
+        ret = gatt_remove_bg_dev_from_list(p_reg, bd_addr, is_initator);
     }
     return ret;
 }
@@ -2591,10 +2651,70 @@
     GATT_TRACE_ERROR1 ("gatt_get_conn_id: not connected- gatt_if: %u", gatt_if);
     return(GATT_INVALID_CONN_ID);
 }
+/*******************************************************************************
+**
+** Function     gatt_add_pending_new_srv_start
+**
+** Description  Add a pending new srv start to the new service start queue
+**
+** Returns    Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+tGATT_PENDING_ENC_CLCB* gatt_add_pending_enc_channel_clcb(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb )
+{
+    tGATT_PENDING_ENC_CLCB   *p_buf;
 
+    GATT_TRACE_DEBUG0 ("gatt_add_pending_new_srv_start");
+    if ((p_buf = (tGATT_PENDING_ENC_CLCB *)GKI_getbuf((UINT16)sizeof(tGATT_PENDING_ENC_CLCB))) != NULL)
+    {
+        GATT_TRACE_DEBUG0 ("enqueue a new pending encryption channel clcb");
+        p_buf->p_clcb = p_clcb;
+        GKI_enqueue (&p_tcb->pending_enc_clcb, p_buf);
+    }
+    return p_buf;
+}
+/*******************************************************************************
+**
+** Function     gatt_update_listen_mode
+**
+** Description  update peripheral role listening mode
+**
+** Returns    Pointer to the new service start buffer, NULL no buffer available
+**
+*******************************************************************************/
+void gatt_update_listen_mode(void)
+{
+    UINT8           ii = 0;
+    tGATT_REG       *p_reg = &gatt_cb.cl_rcb[0];
+    UINT8           listening = 0;
+    UINT16          connectability, window, interval;
 
+    for (; ii < GATT_MAX_APPS; ii ++, p_reg ++)
+    {
+        if ( p_reg->in_use && p_reg->listening > listening)
+        {
+            listening = p_reg->listening;
+        }
+    }
 
+    if (listening == GATT_LISTEN_TO_ALL ||
+        listening == GATT_LISTEN_TO_NONE)
+        BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_ALL);
+    else
+        BTM_BleUpdateAdvFilterPolicy (AP_SCAN_CONN_WL);
 
+    connectability = BTM_ReadConnectability (&window, &interval);
+
+    if (listening != GATT_LISTEN_TO_NONE)
+    {
+        connectability |= BTM_BLE_CONNECTABLE;
+    }
+    else
+        connectability &= ~BTM_BLE_CONNECTABLE;
+    /* turning on the adv now */
+    BTM_SetConnectability(connectability, window, interval);
+
+}
 #endif
 
 
diff --git a/stack/hcic/hciblecmds.c b/stack/hcic/hciblecmds.c
index 417297b..a4e55da 100644
--- a/stack/hcic/hciblecmds.c
+++ b/stack/hcic/hciblecmds.c
@@ -748,4 +748,112 @@
     return (TRUE);
 }
 
+BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM1)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM1;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_RECEIVER_TEST);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_PARAM1);
+
+    UINT8_TO_STREAM (pp, rx_freq);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len, UINT8 payload)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_PARAM3)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_PARAM3;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_TRANSMITTER_TEST);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_PARAM3);
+
+    UINT8_TO_STREAM (pp, tx_freq);
+    UINT8_TO_STREAM (pp, test_data_len);
+    UINT8_TO_STREAM (pp, payload);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_test_end(void)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_TEST_END);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_host_supported (void)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_READ_CMD)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_READ_CMD;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_READ_LE_HOST_SUPPORTED);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_READ_CMD);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF(HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len    = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_WRITE_LE_HOST_SUPPORTED);
+    UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED);
+	UINT8_TO_STREAM  (pp, le_host_spt);
+	UINT8_TO_STREAM  (pp, simul_le_host_spt);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
+    return (TRUE);
+}
+
 #endif
diff --git a/stack/hcic/hcicmds.c b/stack/hcic/hcicmds.c
index 71a5dc5..21222bd 100644
--- a/stack/hcic/hcicmds.c
+++ b/stack/hcic/hcicmds.c
@@ -1371,6 +1371,9 @@
     UINT16_TO_STREAM (pp, HCI_CHANGE_LOCAL_NAME);
     UINT8_TO_STREAM  (pp, HCIC_PARAM_SIZE_CHANGE_NAME);
 
+    if (len > HCIC_PARAM_SIZE_CHANGE_NAME)
+        len = HCIC_PARAM_SIZE_CHANGE_NAME;
+
     ARRAY_TO_STREAM (pp, name, len);
 
     btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
diff --git a/stack/hid/hidh_api.c b/stack/hid/hidh_api.c
index 36ee5ea..4f048fc 100644
--- a/stack/hid/hidh_api.c
+++ b/stack/hid/hidh_api.c
@@ -88,7 +88,7 @@
         else
         {
             memcpy( str, (char *) p_attr->attr_value.v.array, max_len-1 );
-            str[max_len] = '\0';
+            str[max_len-1] = '\0';
         }
     }
     else
@@ -220,7 +220,7 @@
         p_nvi->ssr_min_tout = p_attr->attr_value.v.u16;
     }
     else
-        p_nvi->ssr_max_latency = HID_SSR_PARAM_INVALID;
+        p_nvi->ssr_min_tout = HID_SSR_PARAM_INVALID;
 
     hh_cb.sdp_rec.p_sdp_layer_rec = p_rec;
     hh_cb.sdp_cback(SDP_SUCCESS, attr_mask, &hh_cb.sdp_rec);
@@ -454,7 +454,7 @@
         status = HID_ERR_INVALID_PARAM;
     }
 
-    if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
+    else if( hh_cb.devices[dev_handle].state != HID_DEV_CONNECTED )
     {
         HIDH_TRACE_ERROR1("HID_ERR_NO_CONNECTION dev_handle %d", dev_handle);
         status = HID_ERR_NO_CONNECTION;
diff --git a/stack/hid/hidh_conn.c b/stack/hid/hidh_conn.c
index 9ed3a0e..2fe1f3d 100644
--- a/stack/hid/hidh_conn.c
+++ b/stack/hid/hidh_conn.c
@@ -322,7 +322,7 @@
 #endif
     UINT32 reason;
 
-    dhandle = p_dev - &(hh_cb.devices[0]) ;
+    dhandle = ((UINT32)p_dev - (UINT32)&(hh_cb.devices[0]))/ sizeof(tHID_HOST_DEV_CTB);
     if( res == BTM_SUCCESS && p_dev->conn.conn_state == HID_CONN_STATE_SECURITY )
     {
         HIDH_TRACE_EVENT0 ("HID - Originator security pass.");
@@ -975,7 +975,6 @@
     if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq (HID_PSM_CONTROL, p_dev->addr)) == 0)
     {
         HIDH_TRACE_WARNING0 ("HID - Originate failed");
-        dhandle = (p_dev - &(hh_cb.devices[0]))/(sizeof( tHID_HOST_DEV_CTB )) ;
         hh_cb.callback( dhandle, HID_HDEV_EVT_CLOSE, HID_ERR_L2CAP_FAILED, NULL ) ;
     }
     else
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index 0a9b7f8..beaecf6 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -407,6 +407,13 @@
     UINT16              nsc_mask;       /* Nonsupported protocol command messages */
 } tAVDT_CS;
 
+/* AVDT data option mask is used in the write request */
+#define AVDT_DATA_OPT_NONE      0x00         /* No option still add RTP header */
+#define AVDT_DATA_OPT_NO_RTP   (0x01 << 0)   /* Skip adding RTP header */
+
+typedef UINT8 tAVDT_DATA_OPT_MASK;
+
+
 
 /*****************************************************************************
 **  External Function Declarations
@@ -758,6 +765,44 @@
 *******************************************************************************/
 AVDT_API extern UINT16 AVDT_WriteReq(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
                                      UINT8 m_pt);
+/*******************************************************************************
+**
+** Function         AVDT_WriteReqOpt
+**
+** Description      Send a media packet to the peer device.  The stream must
+**                  be started before this function is called.  Also, this
+**                  function can only be called if the stream is a SRC
+**
+**                  When AVDTP has sent the media packet and is ready for the
+**                  next packet, an AVDT_WRITE_CFM_EVT is sent to the
+**                  application via the control callback.  The application must
+**                  wait for the AVDT_WRITE_CFM_EVT before it makes the next
+**                  call to AVDT_WriteReq().  If the applications calls
+**                  AVDT_WriteReq() before it receives the event the packet
+**                  will not be sent.  The application may make its first call
+**                  to AVDT_WriteReq() after it receives an AVDT_START_CFM_EVT
+**                  or AVDT_START_IND_EVT.
+**
+**                  The application passes the packet using the BT_HDR structure
+**                  This structure is described in section 2.1.  The offset
+**                  field must be equal to or greater than AVDT_MEDIA_OFFSET
+**                  (if NO_RTP is specified, L2CAP_MIN_OFFSET can be used)
+**                  This allows enough space in the buffer for the L2CAP and
+**                  AVDTP headers.
+**
+**                  The memory pointed to by p_pkt must be a GKI buffer
+**                  allocated by the application.  This buffer will be freed
+**                  by the protocol stack; the application must not free
+**                  this buffer.
+**
+**                  The opt parameter allows passing specific options like:
+**                  - NO_RTP : do not add the RTP header to buffer
+**
+** Returns          AVDT_SUCCESS if successful, otherwise error.
+**
+*******************************************************************************/
+AVDT_API extern UINT16 AVDT_WriteReqOpt(UINT8 handle, BT_HDR *p_pkt, UINT32 time_stamp,
+                                     UINT8 m_pt, tAVDT_DATA_OPT_MASK opt);
 
 /*******************************************************************************
 **
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index 1f4bb7f..cc6db7f 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -563,7 +563,8 @@
 **                  Otherwise, the error code defined by AVRCP 1.4
 **
 *******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsCommand (tAVRC_MSG *p_msg, tAVRC_COMMAND *p_result,
+    UINT8 *p_buf, UINT16 buf_len);
 
 /*******************************************************************************
 **
@@ -575,7 +576,8 @@
 **                  Otherwise, the error code defined by AVRCP 1.4
 **
 *******************************************************************************/
-AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result, UINT8 *p_buf, UINT16 buf_len);
+AVRC_API extern tAVRC_STS AVRC_ParsResponse (tAVRC_MSG *p_msg, tAVRC_RESPONSE *p_result,
+    UINT8 *p_buf, UINT16 buf_len);
 
 /*******************************************************************************
 **
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 5809968..020a281 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -97,33 +97,34 @@
 #define BT_EVT_TO_OBX_SR_L2C_MSG    0x3500
 
 /* ftp events */
-#define BT_EVT_TO_FTP_SRVR_CMDS     0x3800
-#define BT_EVT_TO_FTP_CLNT_CMDS     0x3900
+#define BT_EVT_TO_FTP_SRVR_CMDS     0x3600
+#define BT_EVT_TO_FTP_CLNT_CMDS     0x3700
 
-#define BT_EVT_TO_BTU_SAP           0x3a00       /* SIM Access Profile events */
+#define BT_EVT_TO_BTU_SAP           0x3800       /* SIM Access Profile events */
 
 /* opp events */
-#define BT_EVT_TO_OPP_SRVR_CMDS     0x3b00
-#define BT_EVT_TO_OPP_CLNT_CMDS     0x3c00
+#define BT_EVT_TO_OPP_SRVR_CMDS     0x3900
+#define BT_EVT_TO_OPP_CLNT_CMDS     0x3a00
 
 /* gap events */
-#define BT_EVT_TO_GAP_MSG           0x3d00
+#define BT_EVT_TO_GAP_MSG           0x3b00
 
 /* start timer */
-#define BT_EVT_TO_START_TIMER       0x3e00
+#define BT_EVT_TO_START_TIMER       0x3c00
+
+/* stop timer */
+#define BT_EVT_TO_STOP_TIMER        0x3d00
 
 /* start quick timer */
-#define BT_EVT_TO_START_QUICK_TIMER 0x3f00
+#define BT_EVT_TO_START_QUICK_TIMER 0x3e00
 
 
 /* for NFC                          */
                                                 /************************************/
 #define BT_EVT_TO_NFC_NCI           0x4000      /* NCI Command, Notification or Data*/
 #define BT_EVT_TO_NFC_INIT          0x4100      /* Initialization message */
-#define BT_EVT_TO_LLCP_ECHO         0x4200      /* LLCP Echo Service */
-#define BT_EVT_TO_LLCP_SOCKET       0x4300      /* LLCP over TCP/IP */
-#define BT_EVT_TO_NCI_LP            0x4400      /* Low power */
-#define BT_EVT_TO_NFC_ERR           0x4500      /* Error notification to NFC Task */
+#define BT_EVT_TO_NCI_LP            0x4200      /* Low power */
+#define BT_EVT_TO_NFC_ERR           0x4300      /* Error notification to NFC Task */
 
 #define BT_EVT_TO_NFCCSIM_NCI       0x4a00      /* events to NFCC simulation (NCI packets) */
 
@@ -330,7 +331,7 @@
 typedef UINT8 *EXT_INQ_RESP_PTR;             /* Pointer to Extended Inquiry Response */
 
 #define BD_NAME_LEN     248
-typedef UINT8 BD_NAME[BD_NAME_LEN];         /* Device name */
+typedef UINT8 BD_NAME[BD_NAME_LEN + 1];         /* Device name */
 typedef UINT8 *BD_NAME_PTR;                 /* Pointer to Device name */
 
 #define BD_FEATURES_LEN 8
@@ -580,13 +581,13 @@
 #define TRACE_LAYER_SMP             0x00260000
 #define TRACE_LAYER_NFC             0x00270000
 #define TRACE_LAYER_NCI             0x00280000
-#define TRACE_LAYER_IDEP            0x00290000
-#define TRACE_LAYER_NDEP            0x002a0000
-#define TRACE_LAYER_LLCP            0x002b0000
-#define TRACE_LAYER_RW              0x002c0000
-#define TRACE_LAYER_CE              0x002d0000
+#define TRACE_LAYER_LLCP            0x00290000
+#define TRACE_LAYER_NDEF            0x002a0000
+#define TRACE_LAYER_RW              0x002b0000
+#define TRACE_LAYER_CE              0x002c0000
+#define TRACE_LAYER_P2P             0x002d0000
 #define TRACE_LAYER_SNEP            0x002e0000
-#define TRACE_LAYER_NDEF            0x002f0000
+#define TRACE_LAYER_CHO             0x002f0000
 #define TRACE_LAYER_NFA             0x00300000
 
 #define TRACE_LAYER_MAX_NUM         0x0031
@@ -667,11 +668,13 @@
 #define SCR_PROTO_TRACE_ATT         0x00001000
 #define SCR_PROTO_TRACE_SMP         0x00002000
 #define SCR_PROTO_TRACE_NCI         0x00004000
-#define SCR_PROTO_TRACE_DEP         0x00008000
-#define SCR_PROTO_TRACE_LLCP        0x00010000
-#define SCR_PROTO_TRACE_NDEF        0x00020000
-#define SCR_PROTO_TRACE_TAGS        0x00040000
-#define SCR_PROTO_TRACE_ALL         0x0007ffff
+#define SCR_PROTO_TRACE_LLCP        0x00008000
+#define SCR_PROTO_TRACE_NDEF        0x00010000
+#define SCR_PROTO_TRACE_RW          0x00020000
+#define SCR_PROTO_TRACE_CE          0x00040000
+#define SCR_PROTO_TRACE_SNEP        0x00080000
+#define SCR_PROTO_TRACE_CHO         0x00100000
+#define SCR_PROTO_TRACE_ALL         0x001fffff
 #define SCR_PROTO_TRACE_HCI_LOGGING_VSE 0x0800 /* Brcm vs event for logmsg and protocol traces */
 
 #define MAX_SCRIPT_TYPE             5
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 09bb749..a639fa6 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -172,9 +172,11 @@
 
 /* Inquiry modes
  * Note: These modes are associated with the inquiry active values (BTM_*ACTIVE) */
-#define BTM_GENERAL_INQUIRY         0
-#define BTM_LIMITED_INQUIRY         1
-#define BTM_BR_INQUIRY_MASK         0x0f
+#define BTM_INQUIRY_NONE			0
+#define BTM_GENERAL_INQUIRY         0x01
+#define BTM_LIMITED_INQUIRY         0x02
+#define BTM_BR_INQUIRY_MASK         (BTM_GENERAL_INQUIRY | BTM_LIMITED_INQUIRY)
+
 /* high byte of inquiry mode for BLE inquiry mode */
 #define BTM_BLE_INQUIRY_NONE         0x00
 #define BTM_BLE_GENERAL_INQUIRY      0x10
@@ -188,6 +190,16 @@
 #define BTM_LIMITED_INQUIRY_ACTIVE  0x2     /* a limited inquiry is in progress */
 #define BTM_PERIODIC_INQUIRY_ACTIVE 0x8     /* a periodic inquiry is active */
 #define BTM_SSP_INQUIRY_ACTIVE      0x4     /* SSP is active, so inquiry is disallowed (work around for FW bug) */
+#define BTM_LE_GENERAL_INQUIRY_ACTIVE  0x10     /* a general inquiry is in progress */
+#define BTM_LE_LIMITED_INQUIRY_ACTIVE  0x20     /* a limited inquiry is in progress */
+#define BTM_LE_SELECT_CONN_ACTIVE	   0x40     /* selection connection is in progress */
+#define BTM_LE_OBSERVE_ACTIVE		   0x80     /* selection connection is in progress */
+
+/* inquiry activity mask */
+#define BTM_BR_INQ_ACTIVE_MASK		   (BTM_GENERAL_INQUIRY_ACTIVE|BTM_LIMITED_INQUIRY_ACTIVE|BTM_PERIODIC_INQUIRY_ACTIVE) /* BR/EDR inquiry activity mask */
+#define BTM_LE_SCAN_ACTIVE_MASK		   0xF0     /* LE scan activity mask */
+#define BTM_LE_INQ_ACTIVE_MASK		   (BTM_LE_GENERAL_INQUIRY_ACTIVE|BTM_LE_LIMITED_INQUIRY_ACTIVE) /* LE inquiry activity mask*/
+#define BTM_INQUIRY_ACTIVE_MASK		   (BTM_BR_INQ_ACTIVE_MASK | BTM_LE_INQ_ACTIVE_MASK) /* inquiry activity mask */
 
 /* Define scan types */
 #define BTM_SCAN_TYPE_STANDARD      0
@@ -825,8 +837,9 @@
 typedef struct
 {
     tBTM_BL_EVENT   event;  /* The event reported. */
-    UINT8           busy_level;/* when paging or inquiring, level is as above.
+    UINT8           busy_level;/* when paging or inquiring, level is 10.
                                 * Otherwise, the number of ACL links. */
+    UINT8           busy_level_flags; /* Notifies actual inquiry/page activities */
 } tBTM_BL_UPDATE_DATA;
 
 /* the data type associated with BTM_BL_ROLE_CHG_EVT */
@@ -877,6 +890,9 @@
 /* Define an invalid SCO disconnect reason */
 #define BTM_INVALID_SCO_DISC_REASON 0xFFFF
 
+/* Define first active SCO index */
+#define BTM_FIRST_ACTIVE_SCO_INDEX  BTM_MAX_SCO_LINKS
+
 /* Define SCO packet types used in APIs */
 #define BTM_SCO_PKT_TYPES_MASK_HV1  HCI_ESCO_PKT_TYPES_MASK_HV1
 #define BTM_SCO_PKT_TYPES_MASK_HV2  HCI_ESCO_PKT_TYPES_MASK_HV2
@@ -929,6 +945,17 @@
 #define BTM_SCO_CODEC_MSBC          0x0002
 typedef UINT16 tBTM_SCO_CODEC_TYPE;
 
+
+
+/*******************
+** SCO Air Mode Types
+********************/
+#define BTM_SCO_AIR_MODE_U_LAW          0
+#define BTM_SCO_AIR_MODE_A_LAW          1
+#define BTM_SCO_AIR_MODE_CVSD           2
+#define BTM_SCO_AIR_MODE_TRANSPNT       3
+typedef UINT8 tBTM_SCO_AIR_MODE_TYPE;
+
 /*******************
 ** SCO Voice Settings
 ********************/
@@ -1198,11 +1225,11 @@
                                         (UINT32)(((UINT32)1 << (((UINT32)(service)) % BTM_SEC_ARRAY_BITS)))) ? TRUE : FALSE)
 
 /* MACRO to copy two trusted device bitmask */
-#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst)   {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_COPY_TRUSTED_DEVICE(p_src, p_dst)   {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
                                                         ((UINT32 *)(p_dst))[trst] = ((UINT32 *)(p_src))[trst];}
 
 /* MACRO to clear two trusted device bitmask */
-#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst)   {int trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
+#define BTM_SEC_CLR_TRUSTED_DEVICE(p_dst)   {UINT32 trst; for (trst = 0; trst < BTM_SEC_SERVICE_ARRAY_SIZE; trst++) \
                                                         ((UINT32 *)(p_dst))[trst] = 0;}
 
 /* Following bits can be provided by host in the trusted_mask array */
@@ -1556,8 +1583,8 @@
 
 /* LE security level */
 #define BTM_LE_SEC_NONE             SMP_SEC_NONE
-#define BTM_LE_SEC_UNAUTHENTICATE   SMP_SEC_UNAUTHENTICATE
-#define BTM_LE_SEC_AUTHENTICATED    SMP_SEC_AUTHENTICATED
+#define BTM_LE_SEC_UNAUTHENTICATE   SMP_SEC_UNAUTHENTICATE      /* 1 */
+#define BTM_LE_SEC_AUTHENTICATED    SMP_SEC_AUTHENTICATED       /* 4 */
 typedef UINT8 tBTM_LE_SEC;
 
 
@@ -1577,6 +1604,8 @@
 {
     UINT8       reason;
     UINT8       sec_level;
+    BOOLEAN     privacy_supported;
+    BOOLEAN     is_pair_cancel;
 }tBTM_LE_COMPLT;
 #endif
 
@@ -1615,12 +1644,18 @@
 
 }tBTM_LE_LCSRK_KEYS;
 
+typedef struct
+{
+    BT_OCTET16          irk;
+    tBLE_ADDR_TYPE      addr_type;
+    BD_ADDR             static_addr;
+}tBTM_LE_PID_KEYS;
 
 typedef union
 {
     tBTM_LE_PENC_KEYS   penc_key;       /* received peer encryption key */
-    tBTM_LE_PCSRK_KEYS   pcsrk_key;       /* received peer device SRK */
-    BT_OCTET16          pid_key;        /* peer device ID key */
+    tBTM_LE_PCSRK_KEYS  pcsrk_key;       /* received peer device SRK */
+    tBTM_LE_PID_KEYS    pid_key;        /* peer device ID key */
     tBTM_LE_LENC_KEYS   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
     tBTM_LE_LCSRK_KEYS   lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
 }tBTM_LE_KEY_VALUE;
@@ -2907,6 +2942,17 @@
 *******************************************************************************/
     BTM_API extern tBTM_STATUS BTM_SetLinkSuperTout (BD_ADDR remote_bda,
                                                      UINT16 timeout);
+/*******************************************************************************
+**
+** Function         BTM_GetLinkSuperTout
+**
+** Description      Read the link supervision timeout value of the connection
+**
+** Returns          status of the operation
+**
+*******************************************************************************/
+    BTM_API extern tBTM_STATUS BTM_GetLinkSuperTout (BD_ADDR remote_bda,
+                                                     UINT16 *p_timeout);
 
 /*******************************************************************************
 **
@@ -3415,6 +3461,11 @@
 **                  is active, but is typically called after receiving the SCO
 **                  opened callback.
 **
+**                  Note: If called over a 1.1 controller, only the packet types
+**                        field has meaning.
+**                  Note: If the upper layer doesn't know the current sco index,
+**                  BTM_FIRST_ACTIVE_SCO_INDEX can be used as the first parameter to
+**                  find the first active SCO index
 **
 ** Returns          BTM_SUCCESS if returned data is valid connection.
 **                  BTM_ILLEGAL_VALUE if no connection for specified sco_inx.
@@ -4450,27 +4501,6 @@
 *******************************************************************************/
     BTM_API extern void BTM_N2BtDisconnect(void);
 
-
-/*******************************************************************************
-**
-** Function         BTM_ConfigI2SPCM
-**
-** Description      This function sends VSC Write_I2SPCM_Interface_Param
-**                  as to the specified codec_type.
-**
-**
-** Parameter        codec_type: codec_type to be used for sco connection.
-**                  role: master or slave role
-**                  sample_rate: sampling rate
-**                  clock_rate:clock rate 128K to 2048K
-**
-**
-** Returns          BTM_SUCCESS if the successful.
-**                  BTM_ILLEGAL_VALUE: wrong codec type
-**
-*******************************************************************************/
-    BTM_API extern tBTM_STATUS BTM_ConfigI2SPCM (tBTM_SCO_CODEC_TYPE codec_type, UINT8 role, UINT8 sample_rate, UINT8 clock_rate);
-
 /*****************************************************************************
 **  SCO OVER HCI
 *****************************************************************************/
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index 8456b9f..b86968d 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -30,6 +30,16 @@
 #define CHNL_MAP_LEN    5
 typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN];
 
+#define BTM_BLE_CONNECT_EVT     0x00
+#define BTM_BLE_CONNECT_DIR_EVT 0x01
+#define BTM_BLE_DISCOVER_EVT    0x02
+#define BTM_BLE_NON_CONNECT_EVT 0x03
+#define BTM_BLE_SCAN_RSP_EVT    0x04
+#define BTM_BLE_SCAN_REQ_EVT    0x06
+#define BTM_BLE_UNKNOWN_EVT     0xff
+
+#define BTM_BLE_UNKNOWN_EVT     0xff
+
 #define BTM_BLE_SCAN_MODE_PASS      0
 #define BTM_BLE_SCAN_MODE_ACTI      1
 #define BTM_BLE_SCAN_MODE_NONE      0xff
@@ -72,7 +82,7 @@
 #define BTM_BLE_ADV_INT_MIN            0x0020
 #define BTM_BLE_ADV_INT_MAX            0x4000
 
-/* connection parameter boundary value */
+/* connection parameter boundary values */
 #define BTM_BLE_SCAN_INT_MIN            0x0004
 #define BTM_BLE_SCAN_INT_MAX            0x4000
 #define BTM_BLE_SCAN_WIN_MIN            0x0004
@@ -83,32 +93,41 @@
 #define BTM_BLE_CONN_SUP_TOUT_MIN       0x000A
 #define BTM_BLE_CONN_SUP_TOUT_MAX       0x0C80
 #define BTM_BLE_CONN_PARAM_UNDEF        0xffff      /* use this value when a specific value not to be overwritten */
+#define BTM_BLE_CONN_SUP_TOUT_DEF       700
 
 /* default connection parameters if not configured, use GAP recommend value for auto/selective connection */
 /* default scan interval */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT
-#define BTM_BLE_CONN_EST_SCAN_INT    96    /* 312.5 ms   = 500 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_INT
+#define BTM_BLE_SCAN_FAST_INT    96    /* 30 ~ 60 ms (use 60)  = 96 *0.625 */
 #endif
 /* default scan window for background connection, applicable for auto connection or selective conenction */
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND
-#define BTM_BLE_CONN_EST_SCAN_WIND   48      /* 187.5 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_FAST_WIN
+#define BTM_BLE_SCAN_FAST_WIN   48      /* 30 ms = 48 *0.625 */
 #endif
 
-/* default scan paramter used in reduced power cycle */
-#ifndef BTM_BLE_CONN_EST_SCAN_INT_LO
-#define BTM_BLE_CONN_EST_SCAN_INT_LO    2048    /* 1.28 s   = 500 *0.625 */
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_1
+#define BTM_BLE_SCAN_SLOW_INT_1    2048    /* 1.28 s   = 2048 *0.625 */
 #endif
-#ifndef BTM_BLE_CONN_EST_SCAN_WIND_LO
-#define BTM_BLE_CONN_EST_SCAN_WIND_LO   18      /* 11.25 ms = 400 *0.625 */
+#ifndef BTM_BLE_SCAN_SLOW_WIN_1
+#define BTM_BLE_SCAN_SLOW_WIN_1   18      /* 11.25 ms = 18 *0.625 */
+#endif
+
+/* default scan paramter used in reduced power cycle (background scanning) */
+#ifndef BTM_BLE_SCAN_SLOW_INT_2
+#define BTM_BLE_SCAN_SLOW_INT_2    4096    /* 2.56 s   = 4096 *0.625 */
+#endif
+#ifndef BTM_BLE_SCAN_SLOW_WIN_2
+#define BTM_BLE_SCAN_SLOW_WIN_2   36      /* 22.5 ms = 36 *0.625 */
 #endif
 
 /* default connection interval min */
 #ifndef BTM_BLE_CONN_INT_MIN_DEF
-#define BTM_BLE_CONN_INT_MIN_DEF     40      /* 50ms = 400 * 1.25 */
+#define BTM_BLE_CONN_INT_MIN_DEF     24      /* recommended min: 30ms  = 24 * 1.25 */
 #endif
 /* default connectino interval max */
 #ifndef BTM_BLE_CONN_INT_MAX_DEF
-#define BTM_BLE_CONN_INT_MAX_DEF     56      /* 70ms = 56 * 1.25 */
+#define BTM_BLE_CONN_INT_MAX_DEF     40      /* recommended max: 50 ms = 56 * 1.25 */
 #endif
 /* default slave latency */
 #ifndef BTM_BLE_CONN_SLAVE_LATENCY_DEF
@@ -119,10 +138,25 @@
 #define BTM_BLE_CONN_TIMEOUT_DEF    2000
 #endif
 
+#define BTM_BLE_DIR_CONN_FALLBACK_UNDIR         1
+#define BTM_BLE_DIR_CONN_FALLBACK_NO_ADV        2
+
+#ifndef BTM_BLE_DIR_CONN_FALLBACK
+#define BTM_BLE_DIR_CONN_FALLBACK   BTM_BLE_DIR_CONN_FALLBACK_UNDIR
+#endif
+
 #define BTM_CMAC_TLEN_SIZE          8                   /* 64 bits */
 #define BTM_BLE_AUTH_SIGN_LEN       12                   /* BLE data signature length 8 Bytes + 4 bytes counter*/
 typedef UINT8 BLE_SIGNATURE[BTM_BLE_AUTH_SIGN_LEN];         /* Device address */
 
+#ifndef BTM_BLE_HOST_SUPPORT
+#define BTM_BLE_HOST_SUPPORT		0x01
+#endif
+
+#ifndef BTM_BLE_SIMULTANEOUS_HOST
+#define BTM_BLE_SIMULTANEOUS_HOST	0x01
+#endif
+
 /* Structure returned with Rand/Encrypt complete callback */
 typedef struct
 {
@@ -165,27 +199,41 @@
 #define BTM_BLE_AD_BIT_FLAGS           (0x0001 << 1)
 #define BTM_BLE_AD_BIT_MANU            (0x0001 << 2)
 #define BTM_BLE_AD_BIT_TX_PWR          (0x0001 << 3)
-#define BTM_BLE_AD_BIT_ATTR            (0x0001 << 4)
 #define BTM_BLE_AD_BIT_INT_RANGE       (0x0001 << 5)
 #define BTM_BLE_AD_BIT_SERVICE         (0x0001 << 6)
 #define BTM_BLE_AD_BIT_SERVICE_SOL     (0x0001 << 7)
 #define BTM_BLE_AD_BIT_SERVICE_DATA    (0x0001 << 8)
 #define BTM_BLE_AD_BIT_SIGN_DATA       (0x0001 << 9)
+#define BTM_BLE_AD_BIT_SERVICE_128SOL  (0x0001 << 10)
+#define BTM_BLE_AD_BIT_APPEARANCE      (0x0001 << 11)
+#define BTM_BLE_AD_BIT_PUBLIC_ADDR      (0x0001 << 12)
+#define BTM_BLE_AD_BIT_RANDOM_ADDR      (0x0001 << 13)
+
 #define BTM_BLE_AD_BIT_PROPRIETARY     (0x0001 << 15)
 
 typedef  UINT16  tBTM_BLE_AD_MASK;
 
-#define BTM_BLE_AD_TYPE_FLAG            0x01
-#define BTM_BLE_AD_TYPE_SRV_PART        0x02
-#define BTM_BLE_AD_TYPE_SRV_CMPL        0x03
-#define BTM_BLE_AD_TYPE_NAME_SHORT      0x08
-#define BTM_BLE_AD_TYPE_NAME_CMPL       0x09
-#define BTM_BLE_AD_TYPE_TX_PWR          0x0A
+#define BTM_BLE_AD_TYPE_FLAG            HCI_EIR_FLAGS_TYPE                  /* 0x01 */
+#define BTM_BLE_AD_TYPE_16SRV_PART      HCI_EIR_MORE_16BITS_UUID_TYPE       /* 0x02 */
+#define BTM_BLE_AD_TYPE_16SRV_CMPL      HCI_EIR_COMPLETE_16BITS_UUID_TYPE   /* 0x03 */
+#define BTM_BLE_AD_TYPE_32SRV_PART      HCI_EIR_MORE_32BITS_UUID_TYPE       /* 0x04 */
+#define BTM_BLE_AD_TYPE_32SRV_CMPL      HCI_EIR_COMPLETE_32BITS_UUID_TYPE   /* 0x05 */
+#define BTM_BLE_AD_TYPE_128SRV_PART     HCI_EIR_MORE_128BITS_UUID_TYPE       /* 0x06 */
+#define BTM_BLE_AD_TYPE_128SRV_CMPL     HCI_EIR_COMPLETE_128BITS_UUID_TYPE   /* 0x07 */
+#define BTM_BLE_AD_TYPE_NAME_SHORT      HCI_EIR_SHORTENED_LOCAL_NAME_TYPE       /* 0x08 */
+#define BTM_BLE_AD_TYPE_NAME_CMPL       HCI_EIR_COMPLETE_LOCAL_NAME_TYPE        /* 0x09 */
+#define BTM_BLE_AD_TYPE_TX_PWR          HCI_EIR_TX_POWER_LEVEL_TYPE             /* 0x0A */
 #define BTM_BLE_AD_TYPE_DEV_CLASS       0x0D
-#define BTM_BLE_AD_TYPE_ATTR            0x10
-#define BTM_BLE_AD_TYPE_MANU            0xff
+#define BTM_BLE_AD_TYPE_SM_TK           0x10
+#define BTM_BLE_AD_TYPE_SM_OOB_FLAG     0x11
 #define BTM_BLE_AD_TYPE_INT_RANGE       0x12
 #define BTM_BLE_AD_TYPE_SOL_SRV_UUID    0x14
+#define BTM_BLE_AD_TYPE_128SOL_SRV_UUID 0x15
+#define BTM_BLE_AD_TYPE_SERVICE_DATA    0x16
+#define BTM_BLE_AD_TYPE_PUBLIC_TARGET   0x17
+#define BTM_BLE_AD_TYPE_RANDOM_TARGET   0x18
+#define BTM_BLE_AD_TYPE_APPEARANCE      0x19
+#define BTM_BLE_AD_TYPE_MANU            HCI_EIR_MANUFACTURER_SPECIFIC_TYPE      /* 0xff */
 typedef UINT8   tBTM_BLE_AD_TYPE;
 
 /* slave preferred connection interval range */
@@ -204,24 +252,6 @@
     UINT16      *p_uuid;
 }tBTM_BLE_SERVICE;
 
-/* attribute data */
-typedef struct
-{
-    UINT16       uuid;
-    UINT16       data_len;
-    UINT8       *p_data;
-}tBTM_BLE_ATTR;
-
-#ifndef BTM_BLE_NUM_AD_ATTR_MAX
-#define BTM_BLE_NUM_AD_ATTR_MAX         10
-#endif
-/* attribute list contained in adv data */
-typedef struct
-{
-    UINT8               num_attr;
-    tBTM_BLE_ATTR       attr_list[BTM_BLE_NUM_AD_ATTR_MAX];
-}tBTM_BLE_ATTR_DATA;
-
 typedef struct
 {
     UINT8       len;
@@ -243,11 +273,11 @@
 
 typedef struct
 {
-    tBTM_BLE_MANU           manu;        /* manufactuer data */
+    tBTM_BLE_MANU           manu;			/* manufactuer data */
     tBTM_BLE_INT_RANGE      int_range;      /* slave prefered conn interval range */
     tBTM_BLE_SERVICE        services;       /* services */
-    tBTM_BLE_ATTR_DATA      attr;           /* attribute data */
     UINT8                   flag;
+    UINT16                  appearance;
     tBTM_BLE_PROPRIETARY    *p_proprietary;
 }tBTM_BLE_ADV_DATA;
 
@@ -262,7 +292,6 @@
     UINT8               tx_power_level;
     UINT8               remote_name_len;
     UINT8               *p_remote_name;
-    tBTM_BLE_ATTR_DATA  attr_data;
     tBTM_BLE_SERVICE    service;
 } tBTM_BLE_INQ_DATA;
 
@@ -283,6 +312,7 @@
 typedef void (tBTM_BLE_RANDOM_SET_CBACK) (BD_ADDR random_bda);
 
 typedef void (tBTM_BLE_SCAN_REQ_CBACK)(BD_ADDR remote_bda, tBLE_ADDR_TYPE addr_type, UINT8 adv_evt);
+
 /*****************************************************************************
 **  EXTERNAL FUNCTION DECLARATIONS
 *****************************************************************************/
@@ -554,18 +584,6 @@
 
 /*******************************************************************************
 **
-** Function         BTM_SetRandomAddr
-**
-** Description      This function is called to set the local device random address
-**                  .
-**
-** Returns          void
-**
-*******************************************************************************/
-BTM_API extern void BTM_SetRandomAddr (tBTM_BLE_RANDOM_SET_CBACK *p_cback);
-
-/*******************************************************************************
-**
 ** Function         BTM_ReadConnectionAddr
 **
 ** Description      This function is called to set the local device random address
@@ -574,7 +592,24 @@
 ** Returns          void
 **
 *******************************************************************************/
-BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR conn_addr);
+BTM_API extern void BTM_ReadConnectionAddr (BD_ADDR remote_bda, BD_ADDR local_conn_addr,
+                                            tBLE_ADDR_TYPE *p_addr_type);
+
+
+
+/*******************************************************************************
+**
+** Function         BTM_ReadRemoteConnectionAddr
+**
+** Description      This function is read the remote device address currently used
+**                  .
+**
+** Returns          void
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_ReadRemoteConnectionAddr(BD_ADDR pseudo_addr,
+                                                    BD_ADDR conn_addr,
+                                                    tBLE_ADDR_TYPE *p_addr_type);
 
 /*******************************************************************************
 **
@@ -721,7 +756,113 @@
 *******************************************************************************/
 BTM_API extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback);
 
+/*******************************************************************************
+**
+** Function         BTM_BleConfigPrivacy
+**
+** Description      This function is called to enable or disable the privacy in
+**                  the local device.
+**
+** Parameters       enable: TRUE to enable it; FALSE to disable it.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleConfigPrivacy(BOOLEAN enable);
 
+/*******************************************************************************
+**
+** Function         BTM_BleSetConnMode
+**
+** Description      This function is called to set BLE connectable mode for a
+**                  peripheral device.
+**
+** Parameters       directed: is directed connectable mode, or non-directed.
+**                  p_dir_bda: connectable direct initiator's LE device address
+**
+** Returns          void
+**
+*******************************************************************************/
+BTM_API extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
+
+/*******************************************************************************
+**
+** Function         BTM_BleTurnOnPrivacyOnRemote
+**
+** Description      This function is called to enable or disable the privacy on the
+**                  remote device.
+**
+** Parameters       bd_addr: remote device address.
+**                  privacy_on: TRUE to enable it; FALSE to disable it.
+**
+** Returns          void
+**
+*******************************************************************************/
+BTM_API extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
+                                                 BOOLEAN privacy_on);
+
+
+/*******************************************************************************
+**
+** Function         BTM_BleUpdateAdvWhitelist
+**
+** Description      Add or remove device from advertising white list
+**
+** Returns          void
+**
+*******************************************************************************/
+BTM_API extern BOOLEAN BTM_BleUpdateAdvWhitelist(BOOLEAN add_remove, BD_ADDR emote_bda);
+
+/*******************************************************************************
+**
+** Function         BTM_BleUpdateAdvFilterPolicy
+**
+** Description      This function update the filter policy of advertiser.
+**
+** Parameter        adv_policy: advertising filter policy
+**
+** Return           void
+*******************************************************************************/
+BTM_API extern void BTM_BleUpdateAdvFilterPolicy(tBTM_BLE_AFP adv_policy);
+
+/*******************************************************************************
+**
+** Function         BTM_BleReceiverTest
+**
+** Description      This function is called to start the LE Receiver test
+**
+** Parameter       rx_freq - Frequency Range
+**               p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleReceiverTest(UINT8 rx_freq, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+
+/*******************************************************************************
+**
+** Function         BTM_BleTransmitterTest
+**
+** Description      This function is called to start the LE Transmitter test
+**
+** Parameter       tx_freq - Frequency Range
+**                       test_data_len - Length in bytes of payload data in each packet
+**                       packet_payload - Pattern to use in the payload
+**                       p_cmd_cmpl_cback - Command Complete callback
+**
+*******************************************************************************/
+void BTM_BleTransmitterTest(UINT8 tx_freq, UINT8 test_data_len,
+                                 UINT8 packet_payload, tBTM_CMPL_CB *p_cmd_cmpl_cback);
+
+/*******************************************************************************
+**
+** Function         BTM_BleTestEnd
+**
+** Description      This function is called to stop the in-progress TX or RX test
+**
+** Parameter       p_cmd_cmpl_cback - Command complete callback
+**
+*******************************************************************************/
+void BTM_BleTestEnd(tBTM_CMPL_CB *p_cmd_cmpl_cback);
 #ifdef __cplusplus
 }
 #endif
diff --git a/stack/include/btu.h b/stack/include/btu.h
index d33f0bb..4f0e162 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -152,7 +152,11 @@
 #define BTU_TTYPE_BLE_RANDOM_ADDR                   103
 #define BTU_TTYPE_ATT_WAIT_FOR_APP_RSP              104
 #define BTU_TTYPE_ATT_WAIT_FOR_IND_ACK              105
-#define BTU_TTYPE_BLE_SCAN_PARAM_IDLE               106
+
+#define BTU_TTYPE_UCD_TO                            106
+
+/* BTU timer event for TBFC */
+#define BTU_TTYPE_TBFC_RESUME                       107
 
 /* Define the BTU_TASK APPL events
 */
diff --git a/stack/include/gap_api.h b/stack/include/gap_api.h
new file mode 100644
index 0000000..05affed
--- /dev/null
+++ b/stack/include/gap_api.h
@@ -0,0 +1,802 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 GAP_API_H
+#define GAP_API_H
+
+#include "profiles_api.h"
+#include "btm_api.h"
+#include "l2c_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+
+/*** GAP Error and Status Codes ***/
+#define GAP_UNSUPPORTED     (GAP_ERR_GRP + 0x01)    /* Unsupported call */
+#define GAP_EOINQDB         (GAP_ERR_GRP + 0x02)    /* End of inquiry database marker */
+#define GAP_ERR_BUSY        (GAP_ERR_GRP + 0x03)    /* The requested function was busy */
+#define GAP_ERR_NO_CTRL_BLK (GAP_ERR_GRP + 0x04)    /* No control blocks available */
+#define GAP_ERR_STARTING_CMD (GAP_ERR_GRP + 0x05)   /* Error occurred while initiating the command */
+#define GAP_NO_BDADDR_REC   (GAP_ERR_GRP + 0x06)    /* No Inquiry DB record for BD_ADDR */
+#define GAP_ERR_ILL_MODE    (GAP_ERR_GRP + 0x07)    /* An illegal mode parameter was detected */
+#define GAP_ERR_ILL_INQ_TIME (GAP_ERR_GRP + 0x08)   /* An illegal time parameter was detected */
+#define GAP_ERR_ILL_PARM     (GAP_ERR_GRP + 0x09)   /* An illegal parameter was detected */
+#define GAP_ERR_REM_NAME    (GAP_ERR_GRP + 0x0a)    /* Error starting the remote device name request */
+#define GAP_CMD_INITIATED   (GAP_ERR_GRP + 0x0b)    /* The GAP command was started (result pending) */
+#define GAP_DEVICE_NOT_UP   (GAP_ERR_GRP + 0x0c)    /* The device was not up; the request was not executed */
+#define GAP_BAD_BD_ADDR     (GAP_ERR_GRP + 0x0d)    /* The bd addr passed in was not found or invalid */
+
+#define GAP_ERR_BAD_HANDLE  (GAP_ERR_GRP + 0x0e)    /* Bad GAP handle                       */
+#define GAP_ERR_BUF_OFFSET  (GAP_ERR_GRP + 0x0f)    /* Buffer offset invalid                */
+#define GAP_ERR_BAD_STATE   (GAP_ERR_GRP + 0x10)    /* Connection is in invalid state       */
+#define GAP_NO_DATA_AVAIL   (GAP_ERR_GRP + 0x11)    /* No data available                    */
+#define GAP_ERR_CONGESTED   (GAP_ERR_GRP + 0x12)    /* BT stack is congested                */
+#define GAP_ERR_SECURITY    (GAP_ERR_GRP + 0x13)    /* Security failed                      */
+
+#define GAP_ERR_PROCESSING  (GAP_ERR_GRP + 0x14)    /* General error processing BTM request */
+#define GAP_ERR_TIMEOUT     (GAP_ERR_GRP + 0x15)    /* Timeout occurred while processing cmd */
+
+/** GAP Events - definitions of GAP return events ***/
+#define GAP_EVT_INQUIRY_RESULTS     0x0001
+#define GAP_EVT_INQUIRY_COMPLETE    0x0002
+#define GAP_EVT_DISCOVERY_COMPLETE  0x0003
+#define GAP_EVT_REM_NAME_COMPLETE   0x0004
+#define GAP_EVT_FIND_ADDR_COMPLETE  0x0005
+
+#define GAP_EVT_CONN_OPENED         0x0100
+#define GAP_EVT_CONN_CLOSED         0x0101
+#define GAP_EVT_CONN_DATA_AVAIL     0x0102
+#define GAP_EVT_CONN_CONGESTED      0x0103
+#define GAP_EVT_CONN_UNCONGESTED    0x0104
+
+/* Values for 'chan_mode_mask' field */
+/* GAP_ConnOpen() - optional channels to negotiate */
+#define GAP_FCR_CHAN_OPT_BASIC      L2CAP_FCR_CHAN_OPT_BASIC
+#define GAP_FCR_CHAN_OPT_ERTM       L2CAP_FCR_CHAN_OPT_ERTM
+#define GAP_FCR_CHAN_OPT_STREAM     L2CAP_FCR_CHAN_OPT_STREAM
+
+/*** discovery of devices ***/
+#define GAP_INQUIRY_NONE            BTM_INQUIRY_NONE
+#define GAP_GENERAL_INQUIRY         BTM_GENERAL_INQUIRY
+#define GAP_LIMITED_INQUIRY         BTM_LIMITED_INQUIRY
+
+#if BLE_INCLUDED == TRUE
+#define GAP_BLE_INQUIRY_NONE        BTM_BLE_INQUIRY_NONE
+#define GAP_BLE_GENERAL_INQUIRY     BTM_BLE_GENERAL_INQUIRY
+#define GAP_BLE_LIMITED_INQUIRY     BTM_BLE_LIMITED_INQUIRY
+#endif
+
+/*** discoverable modes ***/
+#define GAP_NON_DISCOVERABLE        BTM_NON_DISCOVERABLE
+#define GAP_LIMITED_DISCOVERABLE    BTM_LIMITED_DISCOVERABLE
+#define GAP_GENERAL_DISCOVERABLE    BTM_GENERAL_DISCOVERABLE
+
+/*** Inquiry Filter Condition types  (The values are defined in btm_api.h) ***/
+#define GAP_CLR_INQUIRY_FILTER      BTM_CLR_INQUIRY_FILTER          /* Inquiry Filtering is turned off */
+#define GAP_FILTER_COND_DEVICE_CLASS BTM_FILTER_COND_DEVICE_CLASS    /* Filter on device class */
+#define GAP_FILTER_COND_BD_ADDR     BTM_FILTER_COND_BD_ADDR         /* Filter on device addr */
+
+/*** connectability ***/
+#define GAP_NON_CONNECTABLE         BTM_NON_CONNECTABLE
+#define GAP_CONNECTABLE             BTM_CONNECTABLE
+
+/*** security features ***/
+#define GAP_DISALLOW_PAIRING        0
+#define GAP_ALLOW_PAIRING           1
+
+/*** class of device settings ***/
+#define GAP_SET_COD_MAJOR_MINOR     0x01
+#define GAP_SET_COD_SERVICE_CLASS   0x02 /* only set the bits in the input */
+#define GAP_CLR_COD_SERVICE_CLASS   0x04
+#define GAP_SET_COD_ALL             0x08 /* take service class as the input (may clear some set bits!!) */
+#define GAP_INIT_COD                0x0a
+
+/*** used in connection variables and functions ***/
+#define GAP_INVALID_HANDLE      0xFFFF
+
+/* This is used to change the criteria for AMP  */
+#define GAP_PROTOCOL_ID         (UUID_PROTOCOL_UDP)
+
+/* slave preferred parameter, minimum connection interval */
+#ifndef GAP_SL_CONN_INT_MIN
+#define GAP_SL_CONN_INT_MIN     6
+#endif
+/* slave preferred parameter, maximum connection interval */
+#ifndef GAP_SL_CONN_INT_MAX
+#define GAP_SL_CONN_INT_MAX     20
+#endif
+/* slave preferred parameter */
+#ifndef GAP_SL_LATENCY
+#define GAP_SL_LATENCY     2
+#endif
+
+#ifndef GAP_BLE_PRIVACY_RECONN_ADDR_PERM
+#define GAP_BLE_PRIVACY_RECONN_ADDR_PERM        (GATT_PERM_READ|GATT_PERM_WRITE)
+#endif
+
+#ifndef  GAP_PREFER_CONN_INT_MAX
+#define  GAP_PREFER_CONN_INT_MAX         BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef  GAP_PREFER_CONN_INT_MIN
+#define  GAP_PREFER_CONN_INT_MIN         BTM_BLE_CONN_INT_MIN
+#endif
+
+#ifndef  GAP_PREFER_CONN_LATENCY
+#define  GAP_PREFER_CONN_LATENCY         0
+#endif
+
+#ifndef  GAP_PREFER_CONN_SP_TOUT
+#define  GAP_PREFER_CONN_SP_TOUT         2000
+#endif
+
+#if BLE_INCLUDED == TRUE
+#ifndef GAP_TRANSPORT_SUPPORTED
+#define GAP_TRANSPORT_SUPPORTED GATT_TRANSPORT_LE_BR_EDR
+#endif
+#endif
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+/*
+** Callback function for connection services
+*/
+typedef void (tGAP_CONN_CALLBACK) (UINT16 gap_handle, UINT16 event);
+
+/*
+** Define the callback function prototypes.  Parameters are specific
+** to each event and are described below
+*/
+typedef void (tGAP_CALLBACK) (UINT16 event, void *p_data);
+
+typedef tBTM_REMOTE_DEV_NAME    tGAP_REMOTE_DEV_NAME;   /* see btm_api.h */
+typedef tBTM_INQ_PARMS          tGAP_INQ_PARMS;         /* see btm_api.h */
+typedef tBTM_INQ_RESULTS        tGAP_INQ_RESULTS;       /* see btm_api.h */
+
+/* Inquiry results structure */
+typedef struct
+{
+    UINT16  status;
+    UINT8   num_results;
+} tGAP_INQ_CMPL;
+
+/* Definition of the GAP_FindAddrByName results structure */
+typedef struct
+{
+    UINT16       status;
+    BD_ADDR      bd_addr;
+    tBTM_BD_NAME devname;
+} tGAP_FINDADDR_RESULTS;
+
+/** for GAP_SetDeviceClass() **/
+/* Define Class of Device related values
+ *
+ * >>> changes to this type need to also be made to tHSP_COD in hsp2_int.h
+ */
+typedef struct
+{
+    UINT8       minor;
+    UINT8       major;
+    UINT16      service;
+} tGAP_COD;
+
+/*** Constants and functions for device features ***/
+typedef struct
+{
+    UINT8   lmp_version;
+    UINT16  mfc_name;
+    UINT16  lmp_subversion;
+} tGAP_LMP_VERSION;
+
+typedef struct
+{
+    UINT8   lmp_features[8];
+} tGAP_LMP_FEATURES;
+
+typedef struct
+{
+    UINT16      int_min;
+    UINT16      int_max;
+    UINT16      latency;
+    UINT16      sp_tout;
+}tGAP_BLE_PREF_PARAM;
+
+typedef union
+{
+    tGAP_BLE_PREF_PARAM     conn_param;
+    BD_ADDR                 reconn_bda;
+    UINT16                  icon;
+    UINT8                   *p_dev_name;
+    UINT8                   privacy;
+
+}tGAP_BLE_ATTR_VALUE;
+
+typedef void (tGAP_BLE_DEV_NAME_CBACK)(BOOLEAN status, BD_ADDR addr, UINT16 length, char *p_name);
+
+typedef void (tGAP_BLE_RECONN_ADDR_CBACK)(BOOLEAN status, BD_ADDR addr, BD_ADDR reconn_bda);
+
+/*****************************************************************************
+**  External Function Declarations
+*****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*******************************************************************************
+**
+** Function         GAP_SetDiscoverableMode
+**
+** Description      This function is called to allow or disallow a service to
+**                  discovered (Inquiry Scans).
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_PARM if a bad parameter is detected,
+**                  GAP_DEVICE_NOT_UP if the device is not active,
+**                  GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDiscoverableMode (UINT16 mode, UINT16 duration,
+                                               UINT16 interval);
+
+/*******************************************************************************
+**
+** Function         GAP_ReadDiscoverableMode
+**
+** Description      This function is called to retrieve the current discoverable
+**                  mode for the local device.
+**
+** Returns          GAP_NON_DISCOVERABLE, GAP_LIMITED_DISCOVERABLE, or
+**                  GAP_GENERAL_DISCOVERABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDiscoverableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function         GAP_StartInquiry
+**
+** Description      This function initiates a single inquiry.
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_MODE if a bad mode parameter was passed
+**                  GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks
+**                  GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+**                  GAP_ERR_BUSY if the device already has an iquiry active
+**                  GAP_DEVICE_NOT_UP if the device is not initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartInquiry (tGAP_INQ_PARMS *p_inq_parms,
+                                        tGAP_CALLBACK *p_results_cb,
+                                        tGAP_CALLBACK *p_cmpl_cb);
+
+/*******************************************************************************
+**
+** Function         GAP_StartPeriodicInquiry
+**
+** Description      This function initiates a periodic inquiry.
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_MODE if a bad mode parameter was passed
+**                  GAP_ERR_ILL_INQ_TIME if a bad interval or duration was passed
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks
+**                  GAP_ERR_ILL_PARM if a bad parameter was detected in BTM
+**                  GAP_ERR_BUSY if the device already has an iquiry active
+**                  GAP_DEVICE_NOT_UP if the device is not initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error was returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_StartPeriodicInquiry (tGAP_INQ_PARMS *p_inq_parms,
+                                                UINT16 min_time,
+                                                UINT16 max_time,
+                                                tGAP_CALLBACK *p_results_cb);
+
+/*******************************************************************************
+**
+** Function         GAP_CancelInquiry
+**
+** Description      This function cancels a single inquiry (if in progress)
+**
+** Returns          BOOLEAN (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelInquiry(void);
+
+/*******************************************************************************
+**
+** Function         GAP_CancelPeriodicInquiry
+**
+** Description      This function cancels a periodic inquiry (if in progress)
+**
+** Returns          BOOLEAN: (TRUE if successful, otherwise FALSE)
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_CancelPeriodicInquiry(void);
+
+/*******************************************************************************
+**
+** Function         GAP_GetFirstInquiryResult
+**
+** Description      This function retrieves the first valid inquiry result.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**                  GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetFirstInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function         GAP_GetNextInquiryResult
+**
+** Description      This function retrieves the next valid inquiry result.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero status code
+**                  GAP_EOINQDB if no more entries in the database.
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetNextInquiryResult(tGAP_INQ_RESULTS *p_results);
+
+/*******************************************************************************
+**
+** Function         GAP_FindAddrByName
+**
+** Description      This function is called to retrieve a device address given
+**                  a device name.  It first looks in the current local inquiry
+**                  database for the device with the specified name.  If not found
+**                  it initiates a general inquiry.  Upon completion, it retrieves
+**                  the name for each device until a match is found or all devices
+**                  have been checked.  Note:  This process can take a while to
+**                  complete.
+**
+** Returns          BT_PASS if the name was immediately available. (BD_ADDR is returned)
+**                  GAP_CMD_INITIATED if an inquiry has been initiated
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_FindAddrByName (BD_NAME devname,
+                                          tGAP_INQ_PARMS *p_inq_parms,
+                                          tGAP_CALLBACK *p_addr_cb,
+                                          BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         GAP_SetConnectableMode
+**
+** Description      This function is called to allow or disallow a
+**                  connections on the local device.
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_ILL_PARM if a bad parameter is detected,
+**                  GAP_DEVICE_NOT_UP if the device is not active,
+**                  GAP_ERR_PROCESSING if not enough resources to carry out request
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetConnectableMode (UINT16 mode, UINT16 duration,
+                                              UINT16 interval);
+
+/*******************************************************************************
+**
+** Function         GAP_ReadConnectableMode
+**
+** Description      This function is called to retrieve the current connectability
+**                  mode for the local device.
+**
+** Returns          GAP_NON_CONNECTABLE, GAP_CONNECTABLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadConnectableMode (UINT16 *duration, UINT16 *interval);
+
+/*******************************************************************************
+**
+** Function         GAP_SetSecurityMode
+**
+** Description      Set security mode for the device (Service or Link level)
+**
+** Returns          void
+**
+*******************************************************************************/
+GAP_API extern void GAP_SetSecurityMode (UINT8 sec_mode);
+
+/*******************************************************************************
+**
+** Function         GAP_SecRegister
+**
+** Description      Application calls this function to register for
+**                  security services.
+**
+** Returns          TRUE if registered OK, else FALSE
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_SecRegister (tBTM_APPL_INFO *p_cb_info);
+
+/*******************************************************************************
+**
+** Function         GAP_SetPairableMode
+**
+** Description      This function is called to allow or disallow pairing
+**                  on the local device.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetPairableMode (UINT16 mode, BOOLEAN connect_only_paired);
+
+/*******************************************************************************
+**
+** Function         GAP_Bond
+**
+** Description      This function is called to initiate bonding with peer device
+**
+** Returns          tBTM_STATUS - BTM_CMD_STARTED of successfully initiated
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_Bond (BD_ADDR bd_addr, UINT8 pin_len, UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function         GAP_PinRsp
+**
+** Description      This function is called from UI after Security Manager submitted
+**                  PIN code request.
+**
+** Returns          void
+**
+*******************************************************************************/
+GAP_API extern void GAP_PinRsp (BD_ADDR bd_addr, UINT8 res, UINT8 pin_len,
+                                UINT8 *p_pin, UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function         GAP_AuthorizeRsp
+**
+** Description      This function is called from UI after Security Manager submitted
+**                  an authorization request.
+**
+** Returns          void
+**
+*******************************************************************************/
+GAP_API extern void GAP_AuthorizeRsp (BD_ADDR bd_addr, UINT8 res,
+                                      UINT32 trusted_mask[]);
+
+/*******************************************************************************
+**
+** Function         GAP_SetDeviceClass
+**
+** Description      This function updates the local Device Class.
+**
+** Returns          BT_PASS (0) if successful,
+**                  GAP_ERR_BUSY if a discovery is already in progress
+**                  GAP_ERR_ILL_PARM if an illegal parameter was detected
+**                  GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_SetDeviceClass(tGAP_COD *p_cod, UINT8 cmd);
+
+/*******************************************************************************
+**
+** Function         GAP_ReadDeviceClass
+**
+** Description      This function reads the current local Device Class setting.
+**
+** Returns          BT_PASS
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadDeviceClass(tGAP_COD *p_cod);
+
+/*******************************************************************************
+**
+** Function         GAP_ReadLocalDeviceInfo
+**
+** Description      This function retrieves local device information to the caller.
+**                  NOTE:  Return parameters that are set to NULL are not retrieved.
+**
+** Returns          BT_PASS (0) if successful, or a non-zero error code
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ReadLocalDeviceInfo(  UINT8 *name, BD_ADDR *addr,
+                                                tGAP_LMP_VERSION *verinfo,
+                                                tGAP_LMP_FEATURES *features);
+
+
+/*******************************************************************************
+**
+** Function         GAP_GetRemoteDeviceName
+**
+** Description      The remote name is retrieved from the specified remote device.  If
+**                  GAP_CMD_INITIATED is returned by the function, the command was
+**                  successfully sent to the controller.  The GAP_EVT_NAME_RESP event
+**                  is passed in the callback when the remote device name has been retrieved.
+**
+** Returns
+**                  GAP_CMD_INITIATED if remote search successfully initiated
+**                  GAP_ERR_BUSY if a remote name request is already in progress,
+**                  GAP_ERR_NO_CTRL_BLK if out of control blocks (too many commands pending)
+**                  GAP_BAD_BD_ADDR if the device address is bad,
+**                  GAP_DEVICE_NOT_UP if the device has not been initialized yet
+**                  GAP_ERR_PROCESSING if any other BTM error has been returned
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_GetRemoteDeviceName (BD_ADDR addr, tGAP_CALLBACK *callback);
+
+/*** Functions for L2CAP connection interface ***/
+/*******************************************************************************
+**
+** Function         GAP_ConnOpen
+**
+** Description      This function is called to open a generic L2CAP connection.
+**
+** Returns          handle of the connection if successful, else GAP_INVALID_HANDLE
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnOpen (char *p_serv_name, UINT8 service_id, BOOLEAN is_server,
+                                    BD_ADDR p_rem_bda, UINT16 psm, tL2CAP_CFG_INFO *p_cfg,
+                                    UINT16 security, UINT8 chan_mode_mask, tGAP_CONN_CALLBACK *p_cb);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnClose
+**
+** Description      This function is called to close a connection.
+**
+** Returns          BT_PASS             - closed OK
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnClose (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnReadData
+**
+** Description      GKI buffer unaware application will call this function
+**                  after receiving GAP_EVT_RXDATA event. A data copy is made
+**                  into the receive buffer parameter.
+**
+** Returns          BT_PASS             - data read
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**                  GAP_NO_DATA_AVAIL   - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReadData (UINT16 gap_handle, UINT8 *p_data,
+                                        UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function         GAP_GetRxQueueCnt
+**
+** Description      This function return number of bytes on the rx queue.
+**
+** Parameters:      handle     - Handle returned in the GAP_ConnOpen
+**                  p_rx_queue_count - Pointer to return queue count in.
+**
+**
+*******************************************************************************/
+GAP_API extern int GAP_GetRxQueueCnt (UINT16 handle, UINT32 *p_rx_queue_count);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnBTRead
+**
+** Description      GKI buffer aware applications will call this function after
+**                  receiving an GAP_EVT_RXDATA event to process the incoming
+**                  data buffer.
+**
+** Returns          BT_PASS             - data read
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**                  GAP_NO_DATA_AVAIL   - no data available
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTRead (UINT16 gap_handle, BT_HDR **pp_buf);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnBTWrite
+**
+** Description      GKI buffer aware applications can call this function to write data
+**                  by passing a pointer to the GKI buffer of data.
+**
+** Returns          BT_PASS                 - data read
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**                  GAP_ERR_BAD_STATE       - connection not established
+**                  GAP_INVALID_BUF_OFFSET  - buffer offset is invalid
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnBTWrite (UINT16 gap_handle, BT_HDR *p_buf);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnWriteData
+**
+** Description      GKI buffer unaware application will call this function
+**                  to send data to the connection. A data copy is made into a GKI
+**                  buffer.
+**
+** Returns          BT_PASS                 - data read
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**                  GAP_ERR_BAD_STATE       - connection not established
+**                  GAP_CONGESTION          - system is congested
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnWriteData (UINT16 gap_handle, UINT8 *p_data,
+                                         UINT16 max_len, UINT16 *p_len);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnReconfig
+**
+** Description      Applications can call this function to reconfigure the connection.
+**
+** Returns          BT_PASS                 - config process started
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnReconfig (UINT16 gap_handle, tL2CAP_CFG_INFO *p_cfg);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnSetIdleTimeout
+**
+** Description      Higher layers call this function to set the idle timeout for
+**                  a connection, or for all future connections. The "idle timeout"
+**                  is the amount of time that a connection can remain up with
+**                  no L2CAP channels on it. A timeout of zero means that the
+**                  connection will be torn down immediately when the last channel
+**                  is removed. A timeout of 0xFFFF means no timeout. Values are
+**                  in seconds.
+**
+** Returns          BT_PASS                 - config process started
+**                  GAP_ERR_BAD_HANDLE      - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnSetIdleTimeout (UINT16 gap_handle, UINT16 timeout);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetRemoteAddr
+**
+** Description      This function is called to get the remote BD address
+**                  of a connection.
+**
+** Returns          BT_PASS             - closed OK
+**                  GAP_ERR_BAD_HANDLE  - invalid handle
+**
+*******************************************************************************/
+GAP_API extern UINT8 *GAP_ConnGetRemoteAddr (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetRemMtuSize
+**
+** Description      Returns the remote device's MTU size.
+**
+** Returns          UINT16 - maximum size buffer that can be transmitted to the peer
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetRemMtuSize (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function         GAP_ConnGetL2CAPCid
+**
+** Description      Returns the L2CAP channel id
+**
+** Parameters:      handle      - Handle of the connection
+**
+** Returns          UINT16      - The L2CAP channel id
+**                  0, if error
+**
+*******************************************************************************/
+GAP_API extern UINT16 GAP_ConnGetL2CAPCid (UINT16 gap_handle);
+
+/*******************************************************************************
+**
+** Function         GAP_SetTraceLevel
+**
+** Description      This function sets the trace level for GAP.  If called with
+**                  a value of 0xFF, it simply returns the current trace level.
+**
+** Returns          The new or current trace level
+**
+*******************************************************************************/
+GAP_API extern UINT8 GAP_SetTraceLevel (UINT8 new_level);
+
+/*******************************************************************************
+**
+** Function         GAP_Init
+**
+** Description      Initializes the control blocks used by GAP.
+**                  This routine should not be called except once per
+**                      stack invocation.
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_Init(void);
+
+#if (BLE_INCLUDED == TRUE)
+/*******************************************************************************
+**
+** Function         GAP_BleAttrDBUpdate
+**
+** Description      update GAP local BLE attribute database.
+**
+** Returns          Nothing
+**
+*******************************************************************************/
+GAP_API extern void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value);
+
+
+/*******************************************************************************
+**
+** Function         GAP_BleReadPeerPrefConnParams
+**
+** Description      Start a process to read a connected peripheral's preferred
+**                  connection parameters
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function         GAP_BleReadPeerDevName
+**
+** Description      Start a process to read a connected peripheral's device name.
+**
+** Returns          TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback);
+
+
+/*******************************************************************************
+**
+** Function         GAP_BleCancelReadPeerDevName
+**
+** Description      Cancel reading a peripheral's device name.
+**
+** Returns          TRUE if request accepted
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+
+/*******************************************************************************
+**
+** Function         GAP_BleUpdateReconnectAddr
+**
+** Description      Start a process to udpate the reconnect address if remote devive
+**                  has privacy enabled.
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+GAP_API extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda,
+                                                   BD_ADDR reconn_addr,
+                                                   tGAP_BLE_RECONN_ADDR_CBACK *p_cback);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* GAP_API_H */
+
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index 2d13e5a..d53a80e 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -137,6 +137,9 @@
     #define GATT_MAX_SCCB       10
 #endif
 
+#ifndef GATTP_TRANSPORT_SUPPORTED
+#define GATTP_TRANSPORT_SUPPORTED        GATT_TRANSPORT_LE_BR_EDR
+#endif
 
 
 /* GATT notification caching timer, default to be three seconds
@@ -164,7 +167,7 @@
 #define GATT_ENCRYPT_KEY_SIZE_MASK  (0xF000) /* the MS nibble of tGATT_PERM; key size 7=0; size 16=9 */
 
 #define GATT_READ_ALLOWED           (GATT_PERM_READ | GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
-#define GATT_READ_AUTH_REQUIRED     (GATT_PERM_READ_ENC_MITM)
+#define GATT_READ_AUTH_REQUIRED     (GATT_PERM_READ_ENCRYPTED)
 #define GATT_READ_MITM_REQUIRED     (GATT_PERM_READ_ENC_MITM)
 #define GATT_READ_ENCRYPTED_REQUIRED   (GATT_PERM_READ_ENCRYPTED | GATT_PERM_READ_ENC_MITM)
 
@@ -1120,6 +1123,25 @@
 *******************************************************************************/
     GATT_API extern BOOLEAN GATT_GetConnIdIfConnected(tGATT_IF gatt_if, BD_ADDR bd_addr, UINT16 *p_conn_id);
 
+
+/*******************************************************************************
+**
+** Function         GATT_Listen
+**
+** Description      This function start or stop LE advertisement and listen for
+**                  connection.
+**
+** Parameters       gatt_if: applicaiton interface
+**                  p_bd_addr: listen for specific address connection, or NULL for
+**                             listen to all device connection.
+**                  start: is a direct conenection or a background auto connection
+**
+** Returns          TRUE if advertisement is started; FALSE if adv start failure.
+**
+*******************************************************************************/
+    GATT_API extern BOOLEAN GATT_Listen (tGATT_IF gatt_if, BOOLEAN start, BD_ADDR_PTR bd_addr);
+
+
 #ifdef __cplusplus
 
 }
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index 6eac0f4..e2150f2 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -57,53 +57,4 @@
 #define GATT_UUID_GATT_SRV_CHGD         0x2A05
 /* Attribute Protocol Test */
 
-/* Link Loss Service */
-#define GATT_UUID_ALERT_LEVEL           0x2A06      /* Alert Level */
-#define GATT_UUID_TX_POWER_LEVEL        0x2A07      /* TX power level */
-
-/* Time Profile */
-/* Current Time Service */
-#define GATT_UUID_CURRENT_TIME          0x2A2B      /* Current Time */
-#define GATT_UUID_LOCAL_TIME_INFO       0x2A0F      /* Local time info */
-#define GATT_UUID_REF_TIME_INFO         0x2A14      /* reference time information */
-
-/* NwA Profile */
-#define GATT_UUID_NW_STATUS             0x2A18      /* network availability status */
-#define GATT_UUID_NW_TRIGGER            0x2A1A      /* Network availability trigger */
-
-/* phone alert */
-#define GATT_UUID_ALERT_STATUS          0x2A40     /* alert status */
-#define GATT_UUID_RINGER_CP             0x2A42     /* ringer control point */
-#define GATT_UUID_RINGER_SETTING        0x2A41     /* ringer setting */
-
-/* Glucose Service */
-#define GATT_UUID_GM_MEASUREMENT        0x2A18
-#define GATT_UUID_GM_CONTEXT            0x2A34
-#define GATT_UUID_GM_CONTROL_POINT      0x2A52
-#define GATT_UUID_GM_FEATURE            0x2A51
-
-/* device infor characteristic */
-#define GATT_UUID_SYSTEM_ID             0x2A23
-#define GATT_UUID_MODEL_NUMBER_STR      0x2A24
-#define GATT_UUID_SERIAL_NUMBER_STR     0x2A25
-#define GATT_UUID_FW_VERSION_STR        0x2A26
-#define GATT_UUID_HW_VERSION_STR        0x2A27
-#define GATT_UUID_SW_VERSION_STR        0x2A28
-#define GATT_UUID_MANU_NAME             0x2A29
-#define GATT_UUID_IEEE_DATA             0x2A2A
-#define GATT_UUID_PNP_ID                0x2A50
-
-/* HID characteristics */
-#define GATT_UUID_HID_INFORMATION       0x2A4A
-#define GATT_UUID_HID_REPORT_MAP        0x2A4B
-#define GATT_UUID_HID_CONTROL_POINT     0x2A4C
-#define GATT_UUID_HID_REPORT            0x2A4D
-#define GATT_UUID_HID_PROTO_MODE        0x2A4E
-#define GATT_UUID_HID_BT_KB_INPUT       0x2A22
-#define GATT_UUID_HID_BT_KB_OUTPUT      0x2A32
-#define GATT_UUID_HID_BT_MOUSE_INPUT    0x2A33
-
-/* Battery Service char */
-#define GATT_UUID_BATTERY_LEVEL         0x2A19
-
 #endif
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 1a0b3e8..0584f65 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -19,10 +19,6 @@
 #ifndef HCIDEFS_H
 #define HCIDEFS_H
 
-#ifdef BRCM_VS
-#include "brcm_vs_include.h"
-#endif
-
 #define HCI_PROTO_VERSION     0x01      /* Version for BT spec 1.1          */
 #define HCI_PROTO_VERSION_1_2 0x02      /* Version for BT spec 1.2          */
 #define HCI_PROTO_VERSION_2_0 0x03      /* Version for BT spec 2.0          */
@@ -100,8 +96,19 @@
 #define HCI_LOGICAL_LINK_CANCEL         (0x003B | HCI_GRP_LINK_CONTROL_CMDS)
 #define HCI_FLOW_SPEC_MODIFY            (0x003C | HCI_GRP_LINK_CONTROL_CMDS)
 
+#define HCI_ENH_SETUP_ESCO_CONNECTION   (0x003D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ENH_ACCEPT_ESCO_CONNECTION  (0x003E | HCI_GRP_LINK_CONTROL_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_TRUNCATED_PAGE              (0x003F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_TRUNCATED_PAGE_CANCEL       (0x0040 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SET_CLB                     (0x0041 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_CLB                 (0x0042 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_START_SYNC_TRAIN            (0x0043 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RECEIVE_SYNC_TRAIN          (0x0044 | HCI_GRP_LINK_CONTROL_CMDS)
+
 #define HCI_LINK_CTRL_CMDS_FIRST        HCI_INQUIRY
-#define HCI_LINK_CTRL_CMDS_LAST         HCI_FLOW_SPEC_MODIFY
+#define HCI_LINK_CTRL_CMDS_LAST         HCI_RECEIVE_SYNC_TRAIN
 
 /* Commands of HCI_GRP_LINK_POLICY_CMDS */
 #define HCI_HOLD_MODE                   (0x0001 | HCI_GRP_LINK_POLICY_CMDS)
@@ -131,6 +138,7 @@
 #define HCI_READ_PIN_TYPE               (0x0009 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_WRITE_PIN_TYPE              (0x000A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_CREATE_NEW_UNIT_KEY         (0x000B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_GET_MWS_TRANS_LAYER_CFG     (0x000C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_READ_STORED_LINK_KEY        (0x000D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_WRITE_STORED_LINK_KEY       (0x0011 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_DELETE_STORED_LINK_KEY      (0x0012 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
@@ -210,9 +218,27 @@
 #define HCI_READ_BE_FLUSH_TOUT                (0x0069 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_WRITE_BE_FLUSH_TOUT               (0x006A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_SHORT_RANGE_MODE                  (0x006B | HCI_GRP_HOST_CONT_BASEBAND_CMDS) /* 802.11 only */
+#define HCI_READ_LE_HOST_SUPPORTED              (0x006C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_LE_HOST_SUPPORTED             (0x006D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+
+/* MWS coexistence */
+#define HCI_SET_MWS_CHANNEL_PARAMETERS          (0x006E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION    (0x006F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SIGNALING                   (0x0070 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_TRANSPORT_LAYER             (0x0071 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE        (0x0072 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_MWS_PATTERN_CONFIGURATION       (0x0073 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+/* ConnectionLess Broadcast */
+#define HCI_SET_RESERVED_LT_ADDR                (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_RESERVED_LT_ADDR             (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLB_DATA                      (0x0079 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SYNC_TRAIN_PARAM              (0x007A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SYNC_TRAIN_PARAM               (0x007B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 
 #define HCI_CONT_BASEBAND_CMDS_FIRST    HCI_SET_EVENT_MASK
-#define HCI_CONT_BASEBAND_CMDS_LAST     HCI_SHORT_RANGE_MODE
+#define HCI_CONT_BASEBAND_CMDS_LAST     HCI_READ_SYNC_TRAIN_PARAM
 
 
 /* Commands of HCI_GRP_INFORMATIONAL_PARAMS group */
@@ -224,9 +250,10 @@
 #define HCI_READ_COUNTRY_CODE           (0x0007 | HCI_GRP_INFORMATIONAL_PARAMS)
 #define HCI_READ_BD_ADDR                (0x0009 | HCI_GRP_INFORMATIONAL_PARAMS)
 #define HCI_READ_DATA_BLOCK_SIZE        (0x000A | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_SUPPORTED_CODECS (0x000B | HCI_GRP_INFORMATIONAL_PARAMS)
 
 #define HCI_INFORMATIONAL_CMDS_FIRST    HCI_READ_LOCAL_VERSION_INFO
-#define HCI_INFORMATIONAL_CMDS_LAST     HCI_READ_BD_ADDR
+#define HCI_INFORMATIONAL_CMDS_LAST     HCI_READ_LOCAL_SUPPORTED_CODECS
 
 
 /* Commands of HCI_GRP_STATUS_PARAMS group */
@@ -296,6 +323,10 @@
 #define HCI_BLE_LTK_REQ_REPLY           (0x001A | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_LTK_REQ_NEG_REPLY       (0x001B | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_READ_SUPPORTED_STATES   (0x001C | HCI_GRP_BLE_CMDS)
+/* BLE TEST COMMANDS */
+#define HCI_BLE_RECEIVER_TEST           (0x001D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TRANSMITTER_TEST        (0x001E | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TEST_END                (0x001F | HCI_GRP_BLE_CMDS)
 
 #define HCI_BLE_RESET                   (0x0020 | HCI_GRP_BLE_CMDS)
 
@@ -390,8 +421,18 @@
 #define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT   0x04
 #define HCI_BLE_LTK_REQ_EVT                 0x05
 
-#define HCI_EVENT_RSP_FIRST             HCI_INQUIRY_COMP_EVT
-#define HCI_EVENT_RSP_LAST              HCI_AMP_STATUS_CHANGE_EVT
+/* ConnectionLess Broadcast events */
+#define HCI_SYNC_TRAIN_COMP_EVT             0x4F
+#define HCI_SYNC_TRAIN_RECEIVED_EVT         0x50
+#define HCI_CLB_RX_DATA_EVT                 0x51
+#define HCI_CLB_RX_TIMEOUT_EVT              0x52
+#define HCI_TRUNCATED_PAGE_COMP_EVT         0x53
+#define HCI_SLAVE_PAGE_RESP_TIMEOUT_EVT     0x54
+#define HCI_CLB_CHANNEL_CHANGE_EVT          0x55
+#define HCI_INQUIRY_RESPONSE_NOTIF          0x56
+
+#define HCI_EVENT_RSP_FIRST                 HCI_INQUIRY_COMP_EVT
+#define HCI_EVENT_RSP_LAST                  HCI_CLB_CHANNEL_CHANGE_EVT
 
 #define HCI_VENDOR_SPECIFIC_EVT         0xFF  /* Vendor specific events */
 #define HCI_NAP_TRACE_EVT               0xFF  /* was define 0xFE, 0xFD, change to 0xFF
@@ -469,7 +510,13 @@
 #define HCI_ERR_CONN_FAILED_ESTABLISHMENT               0x3E
 #define HCI_ERR_MAC_CONNECTION_FAILED                   0x3F
 
-#define HCI_ERR_MAX_ERR                                 0x40
+/* ConnectionLess Broadcast errors */
+#define HCI_ERR_LT_ADDR_ALREADY_IN_USE                  0x40
+#define HCI_ERR_LT_ADDR_NOT_ALLOCATED                   0x41
+#define HCI_ERR_CLB_NOT_ENABLED                         0x42
+#define HCI_ERR_CLB_DATA_TOO_BIG                        0x43
+
+#define HCI_ERR_MAX_ERR                                 0x43
 
 #define HCI_HINT_TO_RECREATE_AMP_PHYS_LINK              0xFF
 
@@ -965,8 +1012,15 @@
 #define HCI_CONTROLLER_TYPE_ECMA        2
 #define HCI_MAX_CONTROLLER_TYPES        3
 
+/*  ConnectionLess Broadcast */
+#define HCI_CLB_DISABLE                 0x00
+#define HCI_CLB_ENABLE                  0x01
 
-
+/* ConnectionLess Broadcast Data fragment */
+#define HCI_CLB_FRAGMENT_CONT           0x00
+#define HCI_CLB_FRAGMENT_START          0x01
+#define HCI_CLB_FRAGMENT_END            0x02
+#define HCI_CLB_FRAGMENT_SINGLE         0x03
 
 /* AMP Controller Status codes
 */
@@ -1152,7 +1206,43 @@
 #define LMP_COMPID_SOUND ID             111
 #define LMP_COMPID_MONSTER LLC          112
 #define LMP_COMPID_CONNECTBLU           113
-#define LMP_COMPID_MAX_ID               114 /* this is a place holder */
+
+#define LMP_COMPID_SHANGHAI_SSE         114
+#define LMP_COMPID_GROUP_SENSE          115
+#define LMP_COMPID_ZOMM                 116
+#define LMP_COMPID_SAMSUNG              117
+#define LMP_COMPID_CREATIVE_TECH        118
+#define LMP_COMPID_LAIRD_TECH           119
+#define LMP_COMPID_NIKE                 120
+#define LMP_COMPID_LESSWIRE             121
+#define LMP_COMPID_MSTAR_SEMI           122
+#define LMP_COMPID_HANLYNN_TECH         123
+#define LMP_COMPID_AR_CAMBRIDGE         124
+#define LMP_COMPID_SEERS_TECH           125
+#define LMP_COMPID_SPORTS_TRACKING      126
+#define LMP_COMPID_AUTONET_MOBILE       127
+#define LMP_COMPID_DELORME_PUBLISH      128
+#define LMP_COMPID_WUXI_VIMICRO         129
+#define LMP_COMPID_SENNHEISER           130
+#define LMP_COMPID_TIME_KEEPING_SYS     131
+#define LMP_COMPID_LUDUS_HELSINKI       132
+#define LMP_COMPID_BLUE_RADIOS          133
+#define LMP_COMPID_EQUINUX              134
+#define LMP_COMPID_GARMIN_INTL          135
+#define LMP_COMPID_ECOTEST              136
+#define LMP_COMPID_GN_RESOUND           137
+#define LMP_COMPID_JAWBONE              138
+#define LMP_COMPID_TOPCON_POSITIONING   139
+#define LMP_COMPID_QUALCOMM_LABS        140
+#define LMP_COMPID_ZSCAN_SOFTWARE       141
+#define LMP_COMPID_QUINTIC              142
+#define LMP_COMPID_STOLLMAN_EV          143
+#define LMP_COMPID_FUNAI_ELECTRONIC     144
+#define LMP_COMPID_ADV_PANMOBILE        145
+#define LMP_COMPID_THINK_OPTICS         146
+#define LMP_COMPID_UNIVERSAL_ELEC       147
+#define LMP_COMPID_AIROHA_TECH          148
+#define LMP_COMPID_MAX_ID               149 /* this is a place holder */
 #define LMP_COMPID_INTERNAL             65535
 
 #define MAX_LMP_COMPID                  (LMP_COMPID_MAX_ID)
@@ -1349,6 +1439,16 @@
 #define HCI_FEATURE_AFH_CLASS_SLAVE_OFF  4
 #define HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_SLAVE_OFF] & HCI_FEATURE_AFH_CLASS_SLAVE_MASK)
 
+#if 1
+#define HCI_FEATURE_BREDR_NOT_SPT_MASK     0x20
+#define HCI_FEATURE_BREDR_NOT_SPT_OFF      4
+#define HCI_BREDR_NOT_SPT_SUPPORTED(x) ((x)[HCI_FEATURE_BREDR_NOT_SPT_OFF] & HCI_FEATURE_BREDR_NOT_SPT_MASK)
+
+#define HCI_FEATURE_LE_SPT_MASK      0x40
+#define HCI_FEATURE_LE_SPT_OFF       4
+#define HCI_LE_SPT_SUPPORTED(x)  ((x)[HCI_FEATURE_LE_SPT_OFF] & HCI_FEATURE_LE_SPT_MASK)
+#else
+
 #define HCI_FEATURE_ALIAS_AUTH_MASK     0x20
 #define HCI_FEATURE_ALIAS_AUTH_OFF      4
 #define HCI_LMP_ALIAS_AUTH_SUPPORTED(x) ((x)[HCI_FEATURE_ALIAS_AUTH_OFF] & HCI_FEATURE_ALIAS_AUTH_MASK)
@@ -1356,6 +1456,7 @@
 #define HCI_FEATURE_ANON_MODE_MASK      0x40
 #define HCI_FEATURE_ANON_MODE_OFF       4
 #define HCI_LMP_ANON_MODE_SUPPORTED(x)  ((x)[HCI_FEATURE_ANON_MODE_OFF] & HCI_FEATURE_ANON_MODE_MASK)
+#endif
 
 #define HCI_FEATURE_3_SLOT_EDR_ACL_MASK 0x80
 #define HCI_FEATURE_3_SLOT_EDR_ACL_OFF  4
@@ -1397,9 +1498,16 @@
 #define HCI_FEATURE_EXT_INQ_RSP_OFF     6
 #define HCI_EXT_INQ_RSP_SUPPORTED(x)    ((x)[HCI_FEATURE_EXT_INQ_RSP_OFF] & HCI_FEATURE_EXT_INQ_RSP_MASK)
 
+#if 1 /* TOKYO spec definition */
+#define HCI_FEATURE_SIMUL_LE_BREDR_MASK 0x02
+#define HCI_FEATURE_SIMUL_LE_BREDR_OFF  6
+#define HCI_SIMUL_LE_BREDR_SUPPORTED(x) ((x)[HCI_FEATURE_SIMUL_LE_BREDR_OFF] & HCI_FEATURE_SIMUL_LE_BREDR_MASK)
+
+#else
 #define HCI_FEATURE_ANUM_PIN_AWARE_MASK 0x02
 #define HCI_FEATURE_ANUM_PIN_AWARE_OFF  6
 #define HCI_ANUM_PIN_AWARE_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_AWARE_OFF] & HCI_FEATURE_ANUM_PIN_AWARE_MASK)
+#endif
 
 #define HCI_FEATURE_ANUM_PIN_CAP_MASK   0x04
 #define HCI_FEATURE_ANUM_PIN_CAP_OFF    6
@@ -1448,6 +1556,14 @@
 #define HCI_EXT_FEATURE_SSP_HOST_OFF  0
 #define HCI_SSP_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SSP_HOST_OFF] & HCI_EXT_FEATURE_SSP_HOST_MASK)
 
+#define HCI_EXT_FEATURE_LE_HOST_MASK 0x02
+#define HCI_EXT_FEATURE_LE_HOST_OFF  0
+#define HCI_LE_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_LE_HOST_OFF] & HCI_EXT_FEATURE_LE_HOST_MASK)
+
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK 0x04
+#define HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF  0
+#define HCI_SIMUL_DUMO_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SIMUL_DUMO_HOST_OFF] & HCI_EXT_FEATURE_SIMUL_DUMO_HOST_MASK)
+
 /*
 **   Local Supported Commands encoding
 */
@@ -2136,6 +2252,99 @@
 ** Supported Commands (Byte 28)
 */
 
+/* Supported Commands (Byte 29) */
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK     0x08
+#define HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF      29
+#define HCI_READ_ENH_SETUP_SYNCH_CONN_SUPPORTED(x)      ((x)[HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_SETUP_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK    0x10
+#define HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF     29
+#define HCI_READ_ENH_ACCEPT_SYNCH_CONN_SUPPORTED(x)     ((x)[HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ENH_ACCEPT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK        0x20
+#define HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF         29
+#define HCI_READ_LOCAL_CODECS_SUPPORTED(x)              ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_CODECS_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK      0x40
+#define HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF       29
+#define HCI_SET_MWS_CHANNEL_PARAMETERS_SUPPORTED(x)     ((x)[HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_OFF] & HCI_SUPP_COMMANDS_SET_MWS_CHANN_PARAM_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK       0x80
+#define HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF        29
+#define HCI_SET_EXTERNAL_FRAME_CONFIGURATION_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_OFF] & HCI_SUPP_COMMANDS_SET_EXT_FRAME_CONF_MASK)
+
+
+/* Supported Commands (Byte 30) */
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK     0x01
+#define HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF      30
+#define HCI_SET_MWS_SIGNALING_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SIGNALING_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK   0x02
+#define HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF    30
+#define HCI_SET_MWS_TRANSPORT_LAYER_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_OFF] & HCI_SUPP_COMMANDS_SET_MWS_TRANS_LAYER_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK   0x04
+#define HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF    30
+#define HCI_SET_MWS_SCAN_FREQUENCY_TABLE_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_OFF] & HCI_SUPP_COMMANDS_SET_MWS_SCAN_FREQ_TABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK      0x08
+#define HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF    30
+#define HCI_GET_MWS_TRANS_LAYER_CFG_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_OFF] & HCI_SUPP_COMMANDS_GET_TRANS_LAYER_CONF_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK      0x10
+#define HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF       30
+#define HCI_SET_MWS_PATTERN_CONFIGURATION_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_OFF] & HCI_SUPP_COMMANDS_SET_MWS_PATTERN_CONF_MASK)
+
+/* Supported Commands (Byte 30 bit 6-7) */
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE             0x06
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF         30
+#define HCI_TRUNCATED_PAGE_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE)
+
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL             0x07
+#define HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF         30
+#define HCI_TRUNCATED_PAGE_CANCEL_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL_OFF] & HCI_SUPP_COMMANDS_TRUNCATED_PAGE_CANCEL)
+
+/* Supported Commands (Byte 31 bit 6-7) */
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST             0x00
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF         31
+#define HCI_SET_CONLESS_SLAVE_BRCST_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE             0x01
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF         31
+#define HCI_SET_CONLESS_SLAVE_BRCST_RECEIVE_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_RECEIVE)
+
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN             0x02
+#define HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF         31
+#define HCI_START_SYNC_TRAIN_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_START_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_START_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN             0x03
+#define HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF         31
+#define HCI_RECEIVE_SYNC_TRAIN_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN_OFF] & HCI_SUPP_COMMANDS_RECEIVE_SYNC_TRAIN)
+
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR             0x04
+#define HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF         31
+#define HCI_SET_RESERVED_LT_ADDR_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_SET_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR             0x05
+#define HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF         31
+#define HCI_DELETE_RESERVED_LT_ADDR_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR_OFF] & HCI_SUPP_COMMANDS_DELETE_RESERVED_LT_ADDR)
+
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA             0x06
+#define HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF         31
+#define HCI_SET_CONLESS_SLAVE_BRCST_DATA_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA_OFF] & HCI_SUPP_COMMANDS_SET_CONLESS_SLAVE_BRCST_DATA)
+
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM             0x07
+#define HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF         31
+#define HCI_READ_SYNC_TRAIN_PARAM_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_READ_SYNC_TRAIN_PARAM)
+
+/* Supported Commands (Byte 32 bit 0) */
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM             0x00
+#define HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF         32
+#define HCI_WRITE_SYNC_TRAIN_PARAM_SUPPORTED(x)   ((x)[HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM_OFF] & HCI_SUPP_COMMANDS_WRITE_SYNC_TRAIN_PARAM)
+
+
+
+
 /*
 Commands of HCI_GRP_VENDOR_SPECIFIC group for WIDCOMM SW LM Simulator
 */
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 3a23dbe..cb85cb1 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -1241,6 +1241,7 @@
 #define HCIC_PARAM_SIZE_BLE_READ_REMOTE_FEAT    2
 #define HCIC_PARAM_SIZE_BLE_ENCRYPT             32
 #define HCIC_PARAM_SIZE_BLE_RAND                0
+#define HCIC_PARAM_SIZE_WRITE_LE_HOST_SUPPORTED	2
 
 #define HCIC_BLE_RAND_DI_SIZE                   8
 #define HCIC_BLE_ENCRYT_KEY_SIZE                16
@@ -1320,6 +1321,15 @@
 
 HCI_API extern BOOLEAN btsnd_hcic_ble_read_supported_states (void);
 
+HCI_API extern BOOLEAN btsnd_hcic_ble_write_host_supported (UINT8 le_host_spt, UINT8 simul_le_host_spt);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_read_host_supported (void);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_receiver_test(UINT8 rx_freq);
+
+HCI_API extern BOOLEAN btsnd_hcic_ble_transmitter_test(UINT8 tx_freq, UINT8 test_data_len,
+                                                           UINT8 payload);
+HCI_API extern BOOLEAN btsnd_hcic_ble_test_end(void);
 
 #endif /* BLE_INCLUDED */
 
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 618ea8d..95c44e0 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -123,16 +123,6 @@
 #define L2C_INVALID_PSM(psm)    (((psm) & 0x0101) != 0x0001)
 #define L2C_IS_VALID_PSM(psm)   (((psm) & 0x0101) == 0x0001)
 
-#if (BLE_INCLUDED == TRUE)
-#define L2CAP_LE_INT_MIN            0x0006
-#define L2CAP_LE_INT_MAX            0x0C80
-#define L2CAP_LE_LATENCY_MAX        500
-#define L2CAP_LE_TIMEOUT_MIN        0x000a
-#define L2CAP_LE_TIMEOUT_MAX        0x0C80
-#define L2CAP_LE_TIMEOUT_DEFAULT    0x07D0
-#endif
-
-
 /*****************************************************************************
 **  Type Definitions
 *****************************************************************************/
diff --git a/stack/include/profiles_api.h b/stack/include/profiles_api.h
new file mode 100644
index 0000000..eee0dd8
--- /dev/null
+++ b/stack/include/profiles_api.h
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2013 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 PROFILES_API_H
+#define PROFILES_API_H
+
+#include "bt_target.h"
+#include "btm_api.h"
+
+/*****************************************************************************
+**  Constants
+*****************************************************************************/
+#define BT_PASS         0   /* Used for general successful function returns */
+
+/*** Port entity passes back 8 bit errors; will use upper byte offset ***/
+#define PORT_ERR_GRP    0x0000          /* base offset for port entity */
+#define GAP_ERR_GRP     0x0100          /* base offset for GAP profile */
+#define SPP_ERR_GRP     0x0200          /* base offset for serial port profile */
+#define HCRP_ERR_GRP    0x0300          /* base offset for HCRP */
+#define HCRPM_ERR_GRP   0x0400          /* base offset for HCRPM */
+
+/* #define HSP2_ERR_GRP 0x0F00 */
+
+/* security level definitions (tBT_SECURITY) */
+#define BT_USE_DEF_SECURITY         0
+#define BT_SEC_MODE_NONE            BTM_SEC_MODE_NONE
+#define BT_SEC_MODE_SERVICE         BTM_SEC_MODE_SERVICE
+#define BT_SEC_MODE_LINK            BTM_SEC_MODE_LINK
+
+/* security mask definitions (tBT_SECURITY) */
+/* The following definitions are OR'd together to form the security requirements */
+#define BT_SEC_IN_AUTHORIZE         BTM_SEC_IN_AUTHORIZE         /* Inbound call requires authorization */
+#define BT_SEC_IN_AUTHENTICATE      BTM_SEC_IN_AUTHENTICATE      /* Inbound call requires authentication */
+#define BT_SEC_IN_ENCRYPT           BTM_SEC_IN_ENCRYPT           /* Inbound call requires encryption */
+#define BT_SEC_OUT_AUTHORIZE        BTM_SEC_OUT_AUTHORIZE        /* Outbound call requires authorization */
+#define BT_SEC_OUT_AUTHENTICATE     BTM_SEC_OUT_AUTHENTICATE     /* Outbound call requires authentication */
+#define BT_SEC_OUT_ENCRYPT          BTM_SEC_OUT_ENCRYPT          /* Outbound call requires encryption */
+
+
+/*****************************************************************************
+**  Type Definitions
+*****************************************************************************/
+
+/*
+** Security Definitions
+**      This following definitions are used to indicate the security
+**      requirements for a service.
+*/
+typedef struct
+{
+    UINT8   level;
+    UINT8   mask;
+} tBT_SECURITY;
+
+#endif  /* PROFILES_API_H */
+
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index c290e03..fcd4a5e 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -262,10 +262,20 @@
 #define UUID_SERVCLASS_CURRENT_TIME             0x1805      /* Link Loss Alert */
 #define UUID_SERVCLASS_DST_CHG                  0x1806      /* DST Time change */
 #define UUID_SERVCLASS_REF_TIME_UPD             0x1807      /* reference time update */
+#define UUID_SERVCLASS_THERMOMETER              0x1809      /* Thermometer UUID */
 #define UUID_SERVCLASS_DEVICE_INFO              0x180A      /* device info service */
 #define UUID_SERVCLASS_NWA                      0x180B      /* Network availability */
-#define UUID_SERVCLASS_PHALERT                  0x180C      /* phone alert service */
-#define UUID_SERVCLASS_GLUCOSE                  0xC000      /* Glucose Meter Service */
+#define UUID_SERVCLASS_HEART_RATE               0x180D      /* Heart Rate service */
+#define UUID_SERVCLASS_PHALERT                  0x180E      /* phone alert service */
+#define UUID_SERVCLASS_BATTERY                  0x180F     /* battery service */
+#define UUID_SERVCLASS_BPM                      0x1810      /*  blood pressure service */
+#define UUID_SERVCLASS_ALERT_NOTIFICATION       0x1811      /* alert notification service */
+#define UUID_SERVCLASS_LE_HID                   0x1812     /*  HID over LE */
+#define UUID_SERVCLASS_SCAN_PARAM               0x1813      /* Scan Parameter service */
+#define UUID_SERVCLASS_GLUCOSE                  0x1808      /* Glucose Meter Service */
+#define UUID_SERVCLASS_RSC                      0x1814      /* RUNNERS SPEED AND CADENCE SERVICE      */
+#define UUID_SERVCLASS_CSC                      0x1816      /* Cycling SPEED AND CADENCE SERVICE      */
+
 #define UUID_SERVCLASS_TEST_SERVER              0x9000      /* Test Group UUID */
 
 #if (BTM_WBS_INCLUDED == TRUE )
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index bd7b131..68c9ebf 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -61,6 +61,7 @@
 #define SMP_RSP_TIMEOUT             0x11
 #define SMP_DIV_NOT_AVAIL           0x12
 #define SMP_FAIL                    0x13 /* unspecified failed reason */
+#define SMP_CONN_TOUT               0x14 /* unspecified failed reason */
 #define SMP_SUCCESS                 0
 
 typedef UINT8 tSMP_STATUS;
diff --git a/stack/l2cap/l2c_ble.c b/stack/l2cap/l2c_ble.c
index f464ff3..0a296c8 100644
--- a/stack/l2cap/l2c_ble.c
+++ b/stack/l2cap/l2c_ble.c
@@ -48,7 +48,7 @@
     tL2C_LCB *p_lcb;
 
     /* There can be only one BLE connection request outstanding at a time */
-    if (!l2cb.is_ble_connecting)
+    if (btm_ble_get_conn_st() == BLE_DIR_CONN)
     {
         L2CAP_TRACE_WARNING0 ("L2CA_CancelBleConnectReq - no connection pending");
         return(FALSE);
@@ -72,10 +72,8 @@
             p_lcb->disc_reason = L2CAP_CONN_CANCEL;
             l2cu_release_lcb (p_lcb);
         }
-
-        l2cb.is_ble_connecting = FALSE;
-        btm_ble_update_bg_state();
-        btm_ble_resume_bg_conn(NULL, TRUE);
+        /* update conn state to IDLE */
+        btm_ble_set_conn_st (BLE_CONN_IDLE);
 
         return(TRUE);
     }
@@ -186,10 +184,10 @@
             tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (rem_bda);
 
             btsnd_hcic_ble_upd_ll_conn_params (p_lcb->handle,
-                (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN),
-                (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MAX),
-                (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0),
-                (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX),
+                (UINT16)((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN_DEF),
+                (UINT16)((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MAX_DEF),
+                (UINT16)((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : BTM_BLE_CONN_SLAVE_LATENCY_DEF),
+                (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_TIMEOUT_DEF),
                 0, 0);
         }
         p_lcb->upd_disabled = UPD_DISABLED;
@@ -250,7 +248,8 @@
 ** Returns          void
 **
 *******************************************************************************/
-void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type, UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
+void l2cble_scanner_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE type,
+                               UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
 {
     tL2C_LCB            *p_lcb;
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (bda);
@@ -260,9 +259,6 @@
 
     l2cb.is_ble_connecting = FALSE;
 
-    p_dev_rec->device_type   = BT_DEVICE_TYPE_BLE;
-    p_dev_rec->ble.ble_addr_type = type;
-
     /* See if we have a link control block for the remote device */
     p_lcb = l2cu_find_lcb_by_bd_addr (bda);
 
@@ -302,13 +298,13 @@
     p_lcb->is_ble_link = TRUE;
 
     /* If there are any preferred connection parameters, set them now */
-    if ( (p_dev_rec->conn_params.min_conn_int     >= L2CAP_LE_INT_MIN ) &&
-         (p_dev_rec->conn_params.min_conn_int     <= L2CAP_LE_INT_MAX ) &&
-         (p_dev_rec->conn_params.max_conn_int     >= L2CAP_LE_INT_MIN ) &&
-         (p_dev_rec->conn_params.max_conn_int     <= L2CAP_LE_INT_MAX ) &&
-         (p_dev_rec->conn_params.slave_latency    <= L2CAP_LE_LATENCY_MAX ) &&
-         (p_dev_rec->conn_params.supervision_tout >= L2CAP_LE_TIMEOUT_MIN) &&
-         (p_dev_rec->conn_params.supervision_tout <= L2CAP_LE_TIMEOUT_MAX) &&
+    if ( (p_dev_rec->conn_params.min_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
+         (p_dev_rec->conn_params.min_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
+         (p_dev_rec->conn_params.max_conn_int     >= BTM_BLE_CONN_INT_MIN ) &&
+         (p_dev_rec->conn_params.max_conn_int     <= BTM_BLE_CONN_INT_MAX ) &&
+         (p_dev_rec->conn_params.slave_latency    <= BTM_BLE_CONN_LATENCY_MAX ) &&
+         (p_dev_rec->conn_params.supervision_tout >= BTM_BLE_CONN_SUP_TOUT_MIN) &&
+         (p_dev_rec->conn_params.supervision_tout <= BTM_BLE_CONN_SUP_TOUT_MAX) &&
          ((conn_interval < p_dev_rec->conn_params.min_conn_int &&
           p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ||
           (conn_interval > p_dev_rec->conn_params.max_conn_int) ||
@@ -393,9 +389,6 @@
     /* Tell BTM Acl management about the link */
     p_dev_rec = btm_find_or_alloc_dev (bda);
 
-    p_dev_rec->device_type   = BT_DEVICE_TYPE_BLE;
-    p_dev_rec->ble.ble_addr_type = type;
-
     btm_acl_created (bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role, TRUE);
 
     p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT | L2CAP_FIXED_CHNL_BLE_SIG_BIT | L2CAP_FIXED_CHNL_SMP_BIT;
@@ -476,14 +469,14 @@
             /* If we are a master, the slave wants to update the parameters */
             if (p_lcb->link_role == HCI_ROLE_MASTER)
             {
-                if (min_interval < L2CAP_LE_INT_MIN || min_interval > L2CAP_LE_INT_MAX ||
-                    max_interval < L2CAP_LE_INT_MIN || max_interval > L2CAP_LE_INT_MAX ||
-                    latency  > L2CAP_LE_LATENCY_MAX ||
+                if (min_interval < BTM_BLE_CONN_INT_MIN || min_interval > BTM_BLE_CONN_INT_MAX ||
+                    max_interval < BTM_BLE_CONN_INT_MIN || max_interval > BTM_BLE_CONN_INT_MAX ||
+                    latency  > BTM_BLE_CONN_LATENCY_MAX ||
                     /*(timeout >= max_interval && latency > (timeout * 10/(max_interval * 1.25) - 1)) ||*/
-                    timeout < L2CAP_LE_TIMEOUT_MIN || timeout > L2CAP_LE_TIMEOUT_MAX ||
+                    timeout < BTM_BLE_CONN_SUP_TOUT_MIN || timeout > BTM_BLE_CONN_SUP_TOUT_MAX ||
                     max_interval < min_interval)
                 {
-                    result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
+                    l2cu_send_peer_ble_par_rsp (p_lcb, L2CAP_CFG_UNACCEPTABLE_PARAMS, id);
                 }
                 else
                 {
@@ -526,6 +519,65 @@
 
 /*******************************************************************************
 **
+** Function         l2cble_init_direct_conn
+**
+** Description      This function is to initate a direct connection
+**
+** Returns          TRUE connection initiated, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
+{
+    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
+    tBTM_BLE_CB         *p_cb = &btm_cb.ble_ctr_cb;
+    UINT16               scan_int, scan_win;
+    BD_ADDR         init_addr;
+    UINT8           init_addr_type = BLE_ADDR_PUBLIC,
+                    own_addr_type = BLE_ADDR_PUBLIC;
+
+    /* There can be only one BLE connection request outstanding at a time */
+    if (p_dev_rec == NULL)
+    {
+        BTM_TRACE_WARNING0 ("unknown device, can not initate connection");
+        return(FALSE);
+    }
+
+    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_INT : p_cb->scan_int;
+    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? BTM_BLE_SCAN_FAST_WIN : p_cb->scan_win;
+
+    init_addr_type = p_lcb->ble_addr_type;
+    memcpy(init_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+
+    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
+                                        scan_win, /* UINT16 scan_win      */
+                                        FALSE,                   /* UINT8 white_list     */
+                                        p_lcb->ble_addr_type,          /* UINT8 addr_type_peer */
+                                        p_lcb->remote_bd_addr,         /* BD_ADDR bda_peer     */
+                                        BLE_ADDR_PUBLIC,         /* UINT8 addr_type_own  */
+                                        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_min  */
+                                        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : BTM_BLE_CONN_INT_MIN),  /* UINT16 conn_int_max  */
+                                        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency  */
+                                        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : BTM_BLE_CONN_SUP_TOUT_DEF), /* UINT16 conn_timeout  */
+                                        0,                       /* UINT16 min_len       */
+                                        0))                      /* UINT16 max_len       */
+    {
+        l2cu_release_lcb (p_lcb);
+        L2CAP_TRACE_ERROR0("initate direct connection fail, no resources");
+        return (FALSE);
+    }
+    else
+    {
+        p_lcb->link_state = LST_CONNECTING;
+        memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
+        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
+        btm_ble_set_conn_st (BLE_DIR_CONN);
+
+        return (TRUE);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         l2cble_create_conn
 **
 ** Description      This function initiates an acl connection via HCI
@@ -535,49 +587,26 @@
 *******************************************************************************/
 BOOLEAN l2cble_create_conn (tL2C_LCB *p_lcb)
 {
-    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_or_alloc_dev (p_lcb->remote_bd_addr);
-    tBTM_BLE_CB     *p_cb = &btm_cb.ble_ctr_cb;
-    UINT16          scan_int, scan_win;
+    tBTM_BLE_CONN_ST     conn_st = btm_ble_get_conn_st();
+    BOOLEAN         rt = FALSE;
 
     /* There can be only one BLE connection request outstanding at a time */
-    if (l2cb.is_ble_connecting)
+    if (conn_st == BLE_CONN_IDLE)
     {
-        L2CAP_TRACE_WARNING0 ("L2CAP - LE - cannot start new connection, already connecting");
-        return(FALSE);
-    }
-
-    p_lcb->link_state      = LST_CONNECTING;
-    l2cb.is_ble_connecting = TRUE;
-
-    memcpy (l2cb.ble_connecting_bda, p_lcb->remote_bd_addr, BD_ADDR_LEN);
-    btm_ble_suspend_bg_conn();
-
-    scan_int = (p_cb->scan_int == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_int;
-    scan_win = (p_cb->scan_win == BTM_BLE_CONN_PARAM_UNDEF) ? L2CAP_LE_INT_MIN : p_cb->scan_win;
-
-    if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
-                                        scan_win, /* UINT16 scan_win      */
-                                        FALSE,                   /* UINT8 white_list     */
-                                        p_lcb->ble_addr_type,    /* UINT8 addr_type_peer */
-                                        p_lcb->remote_bd_addr,   /* BD_ADDR bda_peer     */
-                                        BLE_ADDR_PUBLIC,         /* UINT8 addr_type_own  */
-                                        (UINT16) ((p_dev_rec->conn_params.min_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.min_conn_int : L2CAP_LE_INT_MIN),  /* UINT16 conn_int_min  */
-                                        (UINT16) ((p_dev_rec->conn_params.max_conn_int != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.max_conn_int : L2CAP_LE_INT_MIN),  /* UINT16 conn_int_max  */
-                                        (UINT16) ((p_dev_rec->conn_params.slave_latency != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.slave_latency : 0), /* UINT16 conn_latency  */
-                                        (UINT16) ((p_dev_rec->conn_params.supervision_tout != BTM_BLE_CONN_PARAM_UNDEF) ? p_dev_rec->conn_params.supervision_tout : L2CAP_LE_TIMEOUT_MAX), /* UINT16 conn_timeout  */
-                                        0,                       /* UINT16 min_len       */
-                                        0))                      /* UINT16 max_len       */
-    {
-        /* No buffer for connection request ? */
-        l2cb.is_ble_connecting = FALSE;
-        p_lcb->disc_reason = L2CAP_CONN_NO_RESOURCES;
-        l2cu_release_lcb (p_lcb);
-        return(FALSE);
+        rt = l2cble_init_direct_conn(p_lcb);
     }
     else
-        btu_start_timer (&p_lcb->timer_entry, BTU_TTYPE_L2CAP_LINK, L2CAP_BLE_LINK_CONNECT_TOUT);
+    {
+        L2CAP_TRACE_WARNING1 ("L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
 
-    return(TRUE);
+        btm_ble_enqueue_direct_conn_req(p_lcb);
+
+        if (conn_st == BLE_BG_CONN)
+            btm_ble_suspend_bg_conn();
+
+        rt = TRUE;
+    }
+    return rt;
 }
 
 /*******************************************************************************
diff --git a/stack/l2cap/l2c_fcr.c b/stack/l2cap/l2c_fcr.c
index ff018c5..9685f77 100644
--- a/stack/l2cap/l2c_fcr.c
+++ b/stack/l2cap/l2c_fcr.c
@@ -1486,8 +1486,12 @@
     else if (p_buf != NULL)
     {
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
-        if (p_ccb->local_cid < L2CAP_BASE_APPL_CID)
-            (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+        if (p_ccb->local_cid < L2CAP_BASE_APPL_CID &&
+            (p_ccb->local_cid >= L2CAP_FIRST_FIXED_CHNL && p_ccb->local_cid <= L2CAP_LAST_FIXED_CHNL))
+        {
+            if (l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)
+                (*l2cb.fixed_reg[p_ccb->local_cid - L2CAP_FIRST_FIXED_CHNL].pL2CA_FixedData_Cb)(p_ccb->p_lcb->remote_bd_addr, p_buf);
+        }
         else
 #endif
             l2c_csm_execute (p_ccb, L2CEVT_L2CAP_DATA, p_buf);
@@ -1622,7 +1626,7 @@
     BOOLEAN     first_seg    = FALSE,       /* The segment is the first part of data  */
                 mid_seg      = FALSE,       /* The segment is the middle part of data */
                 last_seg     = FALSE;       /* The segment is the last part of data   */
-    UINT16      sdu_len;
+    UINT16      sdu_len = 0;
     BT_HDR      *p_buf, *p_xmit;
     UINT8       *p;
     UINT16      max_pdu = p_ccb->tx_mps /* Needed? - L2CAP_MAX_HEADER_FCS*/;
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 609c825..f4eb008 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -761,6 +761,7 @@
 extern void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len);
 extern void l2cble_conn_comp (UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
                               UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout);
+extern BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb);
 
 #endif
 
diff --git a/stack/l2cap/l2c_link.c b/stack/l2cap/l2c_link.c
index 401084a..4bb2be7 100644
--- a/stack/l2cap/l2c_link.c
+++ b/stack/l2cap/l2c_link.c
@@ -133,7 +133,10 @@
     }
     else
     {
-        L2CAP_TRACE_ERROR0 ("L2CAP got conn_req while connected");
+        L2CAP_TRACE_ERROR1("L2CAP got conn_req while connected (state:%d). Reject it",
+                p_lcb->link_state);
+        /* Reject the connection with ACL Connection Already exist reason */
+        btsnd_hcic_reject_conn (bd_addr, HCI_ERR_CONNECTION_EXISTS);
     }
     return (FALSE);
 }
@@ -202,6 +205,8 @@
         else
             btm_acl_created (ci.bd_addr, NULL, NULL, handle, p_lcb->link_role, FALSE);
 
+        BTM_SetLinkSuperTout (ci.bd_addr, btm_cb.btm_def_link_super_tout);
+
         /* If dedicated bonding do not process any further */
         if (p_lcb->is_bonding)
         {
@@ -677,7 +682,7 @@
     UINT16      controller_xmit_quota = l2cb.num_lm_acl_bufs;
     UINT16      high_pri_link_quota = L2CAP_HIGH_PRI_MIN_XMIT_QUOTA_A;
 
-    /* If no links active, nothing to do. */
+    /* If no links active, reset buffer quotas and controller buffers */
     if (l2cb.num_links_active == 0)
     {
         l2cb.controller_xmit_window = l2cb.num_lm_acl_bufs;
@@ -1027,7 +1032,6 @@
 BOOLEAN l2c_link_check_power_mode (tL2C_LCB *p_lcb)
 {
     tBTM_PM_MODE     mode;
-    tBTM_PM_PWR_MD   pm;
     tL2C_CCB    *p_ccb;
     BOOLEAN need_to_active = FALSE;
 
@@ -1054,29 +1058,10 @@
         /* check power mode */
         if (BTM_ReadPowerMode(p_lcb->remote_bd_addr, &mode) == BTM_SUCCESS)
         {
-            /*
-            if ( mode == BTM_PM_MD_PARK )
-            {
-                L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in park mode", p_lcb->handle);
-// Coverity:
-// FALSE-POSITIVE error from Coverity test tool. Please do NOT remove following comment.
-// coverity[uninit_use_in_call] False-positive: setting the mode to BTM_PM_MD_ACTIVE only uses settings.mode
-                                the other data members of tBTM_PM_PWR_MD are ignored
-
-                memset((void*)&pm, 0, sizeof(pm));
-                pm.mode = BTM_PM_MD_ACTIVE;
-                BTM_SetPowerMode(BTM_PM_SET_ONLY_ID, p_lcb->remote_bd_addr, &pm);
-                btu_start_timer (&p_lcb->timer_entry,
-                                 BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
-                return TRUE;
-            }
-            */
             if ( mode == BTM_PM_STS_PENDING )
             {
                 L2CAP_TRACE_DEBUG1 ("LCB(0x%x) is in PM pending state", p_lcb->handle);
 
-                btu_start_timer (&p_lcb->timer_entry,
-                                 BTU_TTYPE_L2CAP_LINK, L2CAP_WAIT_UNPARK_TOUT);
                 return TRUE;
             }
         }
diff --git a/stack/l2cap/l2c_main.c b/stack/l2cap/l2c_main.c
index 6c29cff..49dd811 100644
--- a/stack/l2cap/l2c_main.c
+++ b/stack/l2cap/l2c_main.c
@@ -50,7 +50,7 @@
 /* Temporary - until l2cap implements group management */
 #if (TCS_BCST_SETUP_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
 extern void tcs_proc_bcst_msg( BD_ADDR addr, BT_HDR *p_msg ) ;
-
+#endif
 /*******************************************************************************
 **
 ** Function         l2c_bcst_msg
@@ -104,7 +104,7 @@
         HCI_ACL_DATA_TO_LOWER (p_buf);
     }
 }
-#endif
+
 
 /*******************************************************************************
 **
@@ -680,31 +680,10 @@
             break;
 
         case L2CAP_CMD_ECHO_REQ:
-
-#if (L2CAP_ENHANCED_FEATURES != 0)
-            if (!l2cu_check_feature_req (p_lcb, id, p, cmd_len))
-            {
-                if (cmd_len < (btu_cb.hcit_acl_pkt_size - L2CAP_PKT_OVERHEAD
-                                                        - L2CAP_CMD_OVERHEAD
-                                                        - L2CAP_ECHO_RSP_LEN
-                                                        - HCI_DATA_PREAMBLE_SIZE))
-                {
-                    l2cu_send_peer_echo_rsp (p_lcb, id, p, cmd_len);
-                }
-                else
-                {
-                    l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
-                }
-            }
-#else
             l2cu_send_peer_echo_rsp (p_lcb, id, NULL, 0);
-#endif
             break;
 
         case L2CAP_CMD_ECHO_RSP:
-#if (L2CAP_ENHANCED_FEATURES != 0)
-            l2cu_check_feature_rsp (p_lcb, id, p, cmd_len);
-#endif
             if (p_lcb->p_echo_rsp_cb)
             {
                 tL2CA_ECHO_RSP_CB *p_cb = p_lcb->p_echo_rsp_cb;
diff --git a/stack/l2cap/l2c_utils.c b/stack/l2cap/l2c_utils.c
index fd618ed..581930f 100644
--- a/stack/l2cap/l2c_utils.c
+++ b/stack/l2cap/l2c_utils.c
@@ -307,13 +307,6 @@
 *******************************************************************************/
 void l2cu_adj_id (tL2C_LCB *p_lcb, UINT8 adj_mask)
 {
-#if (L2CAP_ENHANCED_FEATURES != 0)
-    if ((adj_mask & L2CAP_ADJ_BRCM_ID) && p_lcb->id == L2CAP_FEATURE_REQ_ID)
-    {
-        p_lcb->id++;
-    }
-#endif
-
     if ((adj_mask & L2CAP_ADJ_ZERO_ID) && !p_lcb->id)
     {
         p_lcb->id++;
@@ -1546,6 +1539,9 @@
     {
         btm_sec_clr_service_by_psm(p_rcb->psm);
     }
+
+    btm_sec_clr_temp_auth_service (p_lcb->remote_bd_addr);
+
     /* Stop the timer */
     btu_stop_timer (&p_ccb->timer_entry);
 
@@ -2056,6 +2052,9 @@
             l2c_link_hci_disc_comp (p_lcb->handle, (UINT8) -1);
         }
     }
+#if (BLE_INCLUDED == TRUE)
+    l2cb.is_ble_connecting = FALSE;
+#endif
 }
 
 #if (TCS_WUG_MEMBER_INCLUDED == TRUE && TCS_INCLUDED == TRUE)
@@ -2391,153 +2390,6 @@
     return(TRUE);
 }
 
-#if (L2CAP_ENHANCED_FEATURES != 0)
-/*******************************************************************************
-**
-** Function         l2cu_send_feature_req
-**
-** Description      Called at connection establishment by the originator
-**                  of the connection to send an L2CAP Echo request message
-**                  to the peer to determine if he supports Widcomm proprietary
-**                  features.
-**
-** Returns          void
-**
-*******************************************************************************/
-void l2cu_send_feature_req (tL2C_CCB *p_ccb)
-{
-    UINT8     saved_id;
-    UINT8     buff[100], *p = buff;
-
-    UINT8_TO_STREAM (p, 'R');
-    UINT8_TO_STREAM (p, 'Q');
-
-    UINT8_TO_STREAM (p, 'r');
-    UINT8_TO_STREAM (p, 'q');
-
-    /* save current ID to be restored after feature request */
-    saved_id = p_ccb->p_lcb->id;
-
-    /* Set appropriate ID */
-    p_ccb->p_lcb->id               = L2CAP_FEATURE_REQ_ID - 1;
-
-    l2cu_send_peer_echo_req (p_ccb->p_lcb, buff, (UINT16)(p - buff));
-
-    /* packet has been built so we can restore the control block id */
-    p_ccb->p_lcb->id = saved_id;
-}
-
-
-
-/*******************************************************************************
-**
-** Function         l2cu_check_feature_req
-**
-** Description      Called when an echo request is received to check if the
-**                  other side is doing a proprietary feature request. If so,
-**                  extract the values and reply with a features response.
-**
-** Returns          void
-**
-*******************************************************************************/
-BOOLEAN l2cu_check_feature_req (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
-    UINT8   buff[100];
-    UINT8   *p_out           = buff;
-    UINT8   *p_end           = p_data + data_len - 2;
-    UINT8   pe_type, pe_len;
-
-    if ((data_len <= 4)
-     || (p_data[0] != 'R')
-     || (p_data[1] != 'Q')
-     || (p_data[data_len - 2] != 'r')
-     || (p_data[data_len - 1] != 'q')
-     || (id != L2CAP_FEATURE_REQ_ID))
-        return (FALSE);
-
-    /* Skip leading frame characters */
-    p_data += 2;
-
-    UINT8_TO_STREAM (p_out, 'R');
-    UINT8_TO_STREAM (p_out, 'S');
-
-    while (p_data < p_end)
-    {
-        pe_type  = *p_data++;
-        pe_len   = *p_data++;
-
-        switch (pe_type)
-        {
-        default:
-            p_data += pe_len;
-            break;
-        }
-    }
-
-    /* Sanity check - we should not overrun the input */
-    if (p_data != p_end)
-    {
-        L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature req");
-        return (FALSE);
-    }
-
-    UINT8_TO_STREAM (p_out, 'r');
-    UINT8_TO_STREAM (p_out, 's');
-
-    l2cu_send_peer_echo_rsp (p_lcb, L2CAP_FEATURE_RSP_ID, buff, (UINT16)(p_out - buff));
-
-    return (TRUE);
-}
-
-/*******************************************************************************
-**
-** Function         l2cu_check_feature_rsp
-**
-** Description      Called when an echo response is received to check if the
-**                  other side is suports proprietary feature(s). If so,
-**                  extract the values.
-**
-** Returns          void
-**
-*******************************************************************************/
-void l2cu_check_feature_rsp (tL2C_LCB *p_lcb, UINT8 id, UINT8 *p_data, UINT16 data_len)
-{
-    UINT8       *p_end = p_data + data_len - 2;
-
-     if ((data_len <= 4)
-       || (p_data[0] != 'R')
-       || (p_data[1] != 'S')
-       || (p_data[data_len - 2] != 'r')
-       || (p_data[data_len - 1] != 's')
-       || (id != L2CAP_FEATURE_RSP_ID))
-    {
-        return;
-    }
-
-    /* Skip leading frame characters */
-    p_data += 2;
-
-    while (p_data < p_end)
-    {
-        UINT8   pe_id  = *p_data++;
-        UINT8   pe_len = *p_data++;
-
-        switch (pe_id)
-        {
-        default:
-            p_data += pe_len;
-            break;
-        }
-    }
-
-    /* Sanity check - we should not overrun the input */
-    if (p_data != p_end)
-    {
-        L2CAP_TRACE_ERROR0 ("L2CAP - badly formatted feature rsp");
-    }
-}
-#endif /* L2CAP_ENHANCED_FEATURES != 0 */
-
 #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
 /******************************************************************************
 **
@@ -2697,6 +2549,8 @@
     if ((p_ccb = l2cu_allocate_ccb (NULL, 0)) == NULL)
         return (FALSE);
 
+    btu_stop_timer(&p_lcb->timer_entry);
+
     /* Set CID for the connection */
     p_ccb->local_cid  = fixed_cid;
     p_ccb->remote_cid = fixed_cid;
@@ -2836,11 +2690,15 @@
 
                 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, TRUE, reason);
             }
-            else if (p_lcb->p_fixed_ccbs[xx])
+            else
             {
                 (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(p_lcb->remote_bd_addr, FALSE, p_lcb->disc_reason);
-                l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
-                p_lcb->p_fixed_ccbs[xx] = NULL;
+
+                if (p_lcb->p_fixed_ccbs[xx])
+                {
+                    l2cu_release_ccb (p_lcb->p_fixed_ccbs[xx]);
+                    p_lcb->p_fixed_ccbs[xx] = NULL;
+                }
             }
         }
     }
@@ -3219,6 +3077,11 @@
             if (p_ccb->xmit_hold_q.count != 0)
             {
                 p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+                if(NULL == p_buf)
+                {
+                    L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send: No data to be sent");
+                    return (NULL);
+                }
                 l2cu_set_acl_hci_header (p_buf, p_ccb);
                 return (p_buf);
             }
@@ -3245,6 +3108,11 @@
     else
     {
         p_buf = (BT_HDR *)GKI_dequeue (&p_ccb->xmit_hold_q);
+        if(NULL == p_buf)
+        {
+            L2CAP_TRACE_ERROR0("l2cu_get_buffer_to_send() #2: No data to be sent");
+            return (NULL);
+        }
     }
 
     if ( p_ccb->p_rcb && p_ccb->p_rcb->api.pL2CA_TxComplete_Cb && (p_ccb->peer_cfg.fcr.mode != L2CAP_FCR_ERTM_MODE) )
diff --git a/stack/mcap/mca_int.h b/stack/mcap/mca_int.h
index 2563f7f..54ff0c0 100644
--- a/stack/mcap/mca_int.h
+++ b/stack/mcap/mca_int.h
@@ -322,9 +322,18 @@
 extern void mca_stop_timer(tMCA_CCB *p_ccb);
 
 /* l2c functions */
+extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+
+/* callback function declarations */
 extern void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
 extern void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-extern UINT16 mca_l2c_open_req(BD_ADDR bd_addr, UINT16 PSM, const tMCA_CHNL_CFG *p_chnl_cfg);
+extern void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
+extern void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
+extern void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
+extern void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
+extern void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
 
 /*****************************************************************************
 ** global data
diff --git a/stack/mcap/mca_l2c.c b/stack/mcap/mca_l2c.c
index f8a48bf..23d56f5 100644
--- a/stack/mcap/mca_l2c.c
+++ b/stack/mcap/mca_l2c.c
@@ -30,19 +30,10 @@
 #include "mca_defs.h"
 #include "mca_int.h"
 
-/* callback function declarations */
-void mca_l2c_cconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_dconn_ind_cback(BD_ADDR bd_addr, UINT16 lcid, UINT16 psm, UINT8 id);
-void mca_l2c_connect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_config_cfm_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_config_ind_cback(UINT16 lcid, tL2CAP_CFG_INFO *p_cfg);
-void mca_l2c_disconnect_ind_cback(UINT16 lcid, BOOLEAN ack_needed);
-void mca_l2c_disconnect_cfm_cback(UINT16 lcid, UINT16 result);
-void mca_l2c_congestion_ind_cback(UINT16 lcid, BOOLEAN is_congested);
-void mca_l2c_data_ind_cback(UINT16 lcid, BT_HDR *p_buf);
 
 /* L2CAP callback function structure */
-const tL2CAP_APPL_INFO mca_l2c_int_appl = {
+const tL2CAP_APPL_INFO mca_l2c_int_appl =
+{
     NULL,
     mca_l2c_connect_cfm_cback,
     NULL,
@@ -52,11 +43,13 @@
     mca_l2c_disconnect_cfm_cback,
     NULL,
     mca_l2c_data_ind_cback,
-    mca_l2c_congestion_ind_cback
+    mca_l2c_congestion_ind_cback,
+	NULL
 };
 
 /* Control channel eL2CAP default options */
-const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def = {
+const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def =
+{
     L2CAP_FCR_ERTM_MODE,            /* Mandatory for MCAP */
     MCA_FCR_OPT_TX_WINDOW_SIZE,     /* Tx window size */
     MCA_FCR_OPT_MAX_TX_B4_DISCNT,   /* Maximum transmissions before disconnecting */
diff --git a/stack/mcap/mca_main.c b/stack/mcap/mca_main.c
index 2e05d5e..d09319d 100644
--- a/stack/mcap/mca_main.c
+++ b/stack/mcap/mca_main.c
@@ -563,6 +563,7 @@
             if (done)
             {
                 memset (p_rcb, 0, sizeof(tMCA_RCB));
+                MCA_TRACE_DEBUG1("Reset MCA_RCB index=%d",handle);
             }
         }
     }
diff --git a/stack/sdp/sdp_db.c b/stack/sdp/sdp_db.c
index b5ab31a..318a8cc 100644
--- a/stack/sdp/sdp_db.c
+++ b/stack/sdp/sdp_db.c
@@ -538,11 +538,18 @@
 {
 #if SDP_SERVER_ENABLED == TRUE
     UINT16          xx;
-    UINT8           buff[SDP_MAX_ATTR_LEN * 2];
+    UINT8           *p_buff;
     UINT8           *p;
     UINT8           *p_head;
+    BOOLEAN         result;
 
-    p = buff;
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddSequence cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff;
+
     /* First, build the sequence */
     for (xx = 0; xx < num_elem; xx++)
     {
@@ -572,14 +579,15 @@
 
         ARRAY_TO_BE_STREAM (p, p_val[xx], len[xx]);
 
-        if (p - buff > SDP_MAX_ATTR_LEN)
+        if (p - p_buff > SDP_MAX_ATTR_LEN)
         {
             /* go back to before we add this element */
             p = p_head;
-            if(p_head == buff)
+            if(p_head == p_buff)
             {
                 /* the first element exceed the max length */
                 SDP_TRACE_ERROR0 ("SDP_AddSequence - too long(attribute is not added)!!");
+                GKI_freebuf(p_buff);
                 return FALSE;
             }
             else
@@ -587,9 +595,9 @@
             break;
         }
     }
-
-    return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
-            (UINT32) (p - buff), buff));
+    result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -613,9 +621,17 @@
 {
 #if SDP_SERVER_ENABLED == TRUE
     UINT16          xx;
-    UINT8           buff[SDP_MAX_ATTR_LEN * 2];
-    UINT8           *p = buff;
+    UINT8           *p_buff;
+    UINT8           *p;
     INT32           max_len = SDP_MAX_ATTR_LEN -3;
+    BOOLEAN         result;
+
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddUuidSequence cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff;
 
     /* First, build the sequence */
     for (xx = 0; xx < num_uuids ; xx++, p_uuids++)
@@ -623,15 +639,16 @@
         UINT8_TO_BE_STREAM  (p, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES);
         UINT16_TO_BE_STREAM (p, *p_uuids);
 
-        if((p - buff) > max_len)
+        if((p - p_buff) > max_len)
         {
             SDP_TRACE_WARNING2 ("SDP_AddUuidSequence - too long, add %d uuids of %d", xx, num_uuids);
             break;
         }
     }
 
-    return (SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,
-            (UINT32) (p - buff), buff));
+    result = SDP_AddAttribute (handle, attr_id, DATA_ELE_SEQ_DESC_TYPE,(UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -653,13 +670,20 @@
                              tSDP_PROTOCOL_ELEM *p_elem_list)
 {
 #if SDP_SERVER_ENABLED == TRUE
-    UINT8           buff[SDP_MAX_ATTR_LEN * 2];
-    int offset;
+    UINT8           *p_buff;
+    int             offset;
+    BOOLEAN         result;
 
-    offset = sdp_compose_proto_list(buff, num_elem, p_elem_list);
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddProtocolList cannot get a buffer!");
+        return (FALSE);
+    }
 
-    return (SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,
-            DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, buff));
+    offset = sdp_compose_proto_list(p_buff, num_elem, p_elem_list);
+    result = SDP_AddAttribute (handle, ATTR_ID_PROTOCOL_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) offset, p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -683,10 +707,18 @@
 {
 #if SDP_SERVER_ENABLED == TRUE
     UINT16          xx;
-    UINT8           buff[SDP_MAX_ATTR_LEN * 2];
-    UINT8           *p = buff;
-    UINT8            *p_len;
-    int offset;
+    UINT8           *p_buff;
+    UINT8           *p;
+    UINT8           *p_len;
+    int             offset;
+    BOOLEAN         result;
+
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddAdditionProtoLists cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff;
 
     /* for each ProtocolDescriptorList */
     for (xx = 0; xx < num_elem; xx++, p_proto_list++)
@@ -700,9 +732,11 @@
 
         *p_len  = (UINT8)(p - p_len - 1);
     }
+    result = SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,DATA_ELE_SEQ_DESC_TYPE,
+	                           (UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 
-    return (SDP_AddAttribute (handle, ATTR_ID_ADDITION_PROTO_DESC_LISTS,
-            DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -724,8 +758,16 @@
                                       UINT16 version)
 {
 #if SDP_SERVER_ENABLED == TRUE
-    UINT8           buff[SDP_MAX_ATTR_LEN];
-    UINT8           *p = &buff[2];
+    UINT8           *p_buff;
+    UINT8           *p;
+     BOOLEAN        result;
+
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddProfileDescriptorList cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff+2;
 
     /* First, build the profile descriptor list. This consists of a data element sequence. */
     /* The sequence consists of profile's UUID and version number  */
@@ -736,11 +778,13 @@
     UINT16_TO_BE_STREAM (p, version);
 
     /* Add in type and length fields */
-    buff[0] = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
-    buff[1] = (UINT8) (p - &buff[2]);
+    *p_buff = (UINT8) ((DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
+    *(p_buff+1) = (UINT8) (p - (p_buff+2));
 
-    return (SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,
-            DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+    result = SDP_AddAttribute (handle, ATTR_ID_BT_PROFILE_DESC_LIST,DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
+
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -763,8 +807,16 @@
                                        UINT16 char_enc, UINT16 base_id)
 {
 #if SDP_SERVER_ENABLED == TRUE
-    UINT8           buff[SDP_MAX_ATTR_LEN];
-    UINT8           *p = buff;
+    UINT8           *p_buff;
+    UINT8           *p;
+    BOOLEAN         result;
+
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddLanguageBaseAttrIDList cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff;
 
     /* First, build the language base descriptor list. This consists of a data */
     /* element sequence. The sequence consists of 9 bytes (3 UINt16 fields)    */
@@ -777,8 +829,10 @@
     UINT8_TO_BE_STREAM  (p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
     UINT16_TO_BE_STREAM (p, base_id);
 
-    return (SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,
-            DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+    result = SDP_AddAttribute (handle, ATTR_ID_LANGUAGE_BASE_ATTR_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+	                           (UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
@@ -802,8 +856,16 @@
 {
 #if SDP_SERVER_ENABLED == TRUE
     UINT16          xx;
-    UINT8           buff[SDP_MAX_ATTR_LEN * 2];
-    UINT8           *p = buff;
+    UINT8           *p_buff;
+    UINT8           *p;
+    BOOLEAN         result;
+
+    if ((p_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN * 2)) == NULL)
+    {
+        SDP_TRACE_ERROR0("SDP_AddServiceClassIdList cannot get a buffer!");
+        return (FALSE);
+    }
+    p = p_buff;
 
     for (xx = 0; xx < num_services; xx++, p_service_uuids++)
     {
@@ -811,8 +873,10 @@
         UINT16_TO_BE_STREAM (p, *p_service_uuids);
     }
 
-    return (SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,
-            DATA_ELE_SEQ_DESC_TYPE, (UINT32) (p - buff), buff));
+    result = SDP_AddAttribute (handle, ATTR_ID_SERVICE_CLASS_ID_LIST,DATA_ELE_SEQ_DESC_TYPE,
+	                           (UINT32) (p - p_buff), p_buff);
+    GKI_freebuf(p_buff);
+    return result;
 #else   /* SDP_SERVER_ENABLED == FALSE */
     return (FALSE);
 #endif
diff --git a/stack/sdp/sdp_server.c b/stack/sdp/sdp_server.c
index 5736b8d..342d93e 100644
--- a/stack/sdp/sdp_server.c
+++ b/stack/sdp/sdp_server.c
@@ -173,7 +173,7 @@
     tSDP_UUID_SEQ   uid_seq;
     UINT8           *p_rsp, *p_rsp_start, *p_rsp_param_len;
     UINT16          rsp_param_len, num_rsp_handles, xx;
-    UINT32          rsp_handles[SDP_MAX_RECORDS];
+    UINT32          rsp_handles[SDP_MAX_RECORDS] = {0};
     tSDP_RECORD    *p_rec = NULL;
     BT_HDR         *p_buf;
     BOOLEAN         is_cont = FALSE;
@@ -430,7 +430,7 @@
             }
             else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
             {
-                if (attr_len >= MAX_ATTR_LEN)
+                if (attr_len >= SDP_MAX_ATTR_LEN)
                 {
                     SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
                     sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
@@ -697,7 +697,7 @@
                 }
                 else if (rem_len < attr_len) /* Not enough space for attr... so add partially */
                 {
-                    if (attr_len >= MAX_ATTR_LEN)
+                    if (attr_len >= SDP_MAX_ATTR_LEN)
                     {
                         SDP_TRACE_ERROR2("SDP attr too big: max_list_len=%d,attr_len=%d", max_list_len, attr_len);
                         sdpu_build_n_send_error (p_ccb, trans_num, SDP_NO_RESOURCES, NULL);
diff --git a/stack/sdp/sdp_utils.c b/stack/sdp/sdp_utils.c
index cda0570..842e757 100644
--- a/stack/sdp/sdp_utils.c
+++ b/stack/sdp/sdp_utils.c
@@ -884,7 +884,7 @@
     UINT16 len1 = 0;
     UINT16 xx;
     BOOLEAN is_range = FALSE;
-    UINT16 start_id, end_id;
+    UINT16 start_id=0, end_id=0;
 
     for (xx = 0; xx < attr_seq->num_attr; xx++)
     {
@@ -999,21 +999,29 @@
 *******************************************************************************/
 UINT8 *sdpu_build_partial_attrib_entry (UINT8 *p_out, tSDP_ATTRIBUTE *p_attr, UINT16 len, UINT16 *offset)
 {
-    UINT8   tmp_attr[MAX_ATTR_LEN];
-    UINT8   *p_tmp_attr = &tmp_attr[0];
+    UINT8   *p_attr_buff;
+    UINT8   *p_tmp_attr;
     size_t  len_to_copy;
     UINT16  attr_len;
 
+    if ((p_attr_buff = (UINT8 *) GKI_getbuf(sizeof(UINT8) * SDP_MAX_ATTR_LEN )) == NULL)
+    {
+        SDP_TRACE_ERROR0("sdpu_build_partial_attrib_entry cannot get a buffer!");
+        return NULL;
+    }
+    p_tmp_attr = p_attr_buff;
+
     sdpu_build_attrib_entry(p_tmp_attr, p_attr);
     attr_len = sdpu_get_attrib_entry_len(p_attr);
 
     len_to_copy = ((attr_len - *offset) < len) ? (attr_len - *offset): len;
 
-    memcpy(p_out, &tmp_attr[*offset], len_to_copy);
+    memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
 
     p_out = &p_out[len_to_copy];
     *offset += len_to_copy;
 
+    GKI_freebuf(p_attr_buff);
     return p_out;
 }
 
diff --git a/stack/smp/aes.c b/stack/smp/aes.c
new file mode 100644
index 0000000..1028d5b
--- /dev/null
+++ b/stack/smp/aes.c
@@ -0,0 +1,926 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state (there are options to use 32-bit types if available).
+
+ The combination of mix columns and byte substitution used here is based on
+ that developed by Karl Malbrain. His contribution is acknowledged.
+ */
+
+/* define if you have a fast memcpy function on your system */
+#if 1
+#  define HAVE_MEMCPY
+#  include <string.h>
+#if 0
+#  if defined( _MSC_VER )
+#    include <intrin.h>
+#    pragma intrinsic( memcpy )
+#  endif
+#endif
+#endif
+
+#include <stdlib.h>
+
+/* define if you have fast 32-bit types on your system */
+#if 1
+#  define HAVE_UINT_32T
+#endif
+
+/* define if you don't want any tables */
+#if 1
+#  define USE_TABLES
+#endif
+
+/*  On Intel Core 2 duo VERSION_1 is faster */
+
+/* alternative versions (test for performance on your system) */
+#if 1
+#  define VERSION_1
+#endif
+
+#include "aes.h"
+
+#if defined( HAVE_UINT_32T )
+  typedef unsigned long uint_32t;
+#endif
+
+/* functions for finite field multiplication in the AES Galois field    */
+
+#define WPOLY   0x011b
+#define BPOLY     0x1b
+#define DPOLY   0x008d
+
+#define f1(x)   (x)
+#define f2(x)   ((x << 1) ^ (((x >> 7) & 1) * WPOLY))
+#define f4(x)   ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY))
+#define f8(x)   ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \
+                          ^ (((x >> 5) & 4) * WPOLY))
+#define d2(x)   (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0))
+
+#define f3(x)   (f2(x) ^ x)
+#define f9(x)   (f8(x) ^ x)
+#define fb(x)   (f8(x) ^ f2(x) ^ x)
+#define fd(x)   (f8(x) ^ f4(x) ^ x)
+#define fe(x)   (f8(x) ^ f4(x) ^ f2(x))
+
+#if defined( USE_TABLES )
+
+#define sb_data(w) {    /* S Box data values */                            \
+    w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
+    w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
+    w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
+    w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
+    w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
+    w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
+    w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
+    w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
+    w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
+    w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
+    w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
+    w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
+    w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
+    w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
+    w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
+    w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
+    w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
+    w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
+    w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
+    w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
+    w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
+    w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
+    w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
+    w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
+    w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
+    w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
+    w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
+    w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
+    w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
+    w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
+    w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
+    w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
+
+#define isb_data(w) {   /* inverse S Box data values */                    \
+    w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\
+    w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\
+    w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\
+    w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\
+    w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\
+    w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\
+    w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\
+    w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\
+    w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\
+    w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\
+    w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\
+    w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\
+    w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\
+    w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\
+    w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\
+    w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\
+    w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\
+    w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\
+    w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\
+    w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\
+    w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\
+    w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\
+    w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\
+    w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\
+    w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\
+    w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\
+    w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\
+    w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\
+    w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\
+    w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\
+    w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\
+    w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) }
+
+#define mm_data(w) {    /* basic data for forming finite field tables */   \
+    w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\
+    w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\
+    w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\
+    w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\
+    w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\
+    w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\
+    w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\
+    w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\
+    w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\
+    w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\
+    w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\
+    w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\
+    w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\
+    w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\
+    w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\
+    w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\
+    w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\
+    w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\
+    w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\
+    w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\
+    w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\
+    w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\
+    w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\
+    w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\
+    w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\
+    w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\
+    w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\
+    w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\
+    w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\
+    w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\
+    w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\
+    w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) }
+
+static const uint_8t sbox[256]  =  sb_data(f1);
+static const uint_8t isbox[256] = isb_data(f1);
+
+static const uint_8t gfm2_sbox[256] = sb_data(f2);
+static const uint_8t gfm3_sbox[256] = sb_data(f3);
+
+static const uint_8t gfmul_9[256] = mm_data(f9);
+static const uint_8t gfmul_b[256] = mm_data(fb);
+static const uint_8t gfmul_d[256] = mm_data(fd);
+static const uint_8t gfmul_e[256] = mm_data(fe);
+
+#define s_box(x)     sbox[(x)]
+#define is_box(x)    isbox[(x)]
+#define gfm2_sb(x)   gfm2_sbox[(x)]
+#define gfm3_sb(x)   gfm3_sbox[(x)]
+#define gfm_9(x)     gfmul_9[(x)]
+#define gfm_b(x)     gfmul_b[(x)]
+#define gfm_d(x)     gfmul_d[(x)]
+#define gfm_e(x)     gfmul_e[(x)]
+
+#else
+
+/* this is the high bit of x right shifted by 1 */
+/* position. Since the starting polynomial has  */
+/* 9 bits (0x11b), this right shift keeps the   */
+/* values of all top bits within a byte         */
+
+static uint_8t hibit(const uint_8t x)
+{   uint_8t r = (uint_8t)((x >> 1) | (x >> 2));
+
+    r |= (r >> 2);
+    r |= (r >> 4);
+    return (r + 1) >> 1;
+}
+
+/* return the inverse of the finite field element x */
+
+static uint_8t gf_inv(const uint_8t x)
+{   uint_8t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0;
+
+    if(x < 2)
+        return x;
+
+    for( ; ; )
+    {
+        if(n1)
+            while(n2 >= n1)             /* divide polynomial p2 by p1    */
+            {
+                n2 /= n1;               /* shift smaller polynomial left */
+                p2 ^= (p1 * n2) & 0xff; /* and remove from larger one    */
+                v2 ^= (v1 * n2);        /* shift accumulated value and   */
+                n2 = hibit(p2);         /* add into result               */
+            }
+        else
+            return v1;
+
+        if(n2)                          /* repeat with values swapped    */
+            while(n1 >= n2)
+            {
+                n1 /= n2;
+                p1 ^= p2 * n1;
+                v1 ^= v2 * n1;
+                n1 = hibit(p1);
+            }
+        else
+            return v2;
+    }
+}
+
+/* The forward and inverse affine transformations used in the S-box */
+uint_8t fwd_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+    uint_32t w = x;
+    w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4);
+    return 0x63 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+    return 0x63 ^ x ^ (x << 1) ^ (x << 2) ^ (x << 3) ^ (x << 4)
+                    ^ (x >> 7) ^ (x >> 6) ^ (x >> 5) ^ (x >> 4);
+#endif
+}
+
+uint_8t inv_affine(const uint_8t x)
+{
+#if defined( HAVE_UINT_32T )
+    uint_32t w = x;
+    w = (w << 1) ^ (w << 3) ^ (w << 6);
+    return 0x05 ^ ((w ^ (w >> 8)) & 0xff);
+#else
+    return 0x05 ^ (x << 1) ^ (x << 3) ^ (x << 6)
+                ^ (x >> 7) ^ (x >> 5) ^ (x >> 2);
+#endif
+}
+
+#define s_box(x)   fwd_affine(gf_inv(x))
+#define is_box(x)  gf_inv(inv_affine(x))
+#define gfm2_sb(x) f2(s_box(x))
+#define gfm3_sb(x) f3(s_box(x))
+#define gfm_9(x)   f9(x)
+#define gfm_b(x)   fb(x)
+#define gfm_d(x)   fd(x)
+#define gfm_e(x)   fe(x)
+
+#endif
+
+#if defined( HAVE_MEMCPY )
+#  define block_copy_nn(d, s, l)    memcpy(d, s, l)
+#  define block_copy(d, s)          memcpy(d, s, N_BLOCK)
+#else
+#  define block_copy_nn(d, s, l)    copy_block_nn(d, s, l)
+#  define block_copy(d, s)          copy_block(d, s)
+#endif
+
+#if !defined( HAVE_MEMCPY )
+static void copy_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0];
+    ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1];
+    ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2];
+    ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3];
+#else
+    ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0];
+    ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1];
+    ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2];
+    ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3];
+    ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4];
+    ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5];
+    ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6];
+    ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7];
+    ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8];
+    ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9];
+    ((uint_8t*)d)[10] = ((uint_8t*)s)[10];
+    ((uint_8t*)d)[11] = ((uint_8t*)s)[11];
+    ((uint_8t*)d)[12] = ((uint_8t*)s)[12];
+    ((uint_8t*)d)[13] = ((uint_8t*)s)[13];
+    ((uint_8t*)d)[14] = ((uint_8t*)s)[14];
+    ((uint_8t*)d)[15] = ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_block_nn( void * d, const void *s, uint_8t nn )
+{
+    while( nn-- )
+        *((uint_8t*)d)++ = *((uint_8t*)s)++;
+}
+#endif
+
+static void xor_block( void *d, const void *s )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint_32t*)d)[ 0] ^= ((uint_32t*)s)[ 0];
+    ((uint_32t*)d)[ 1] ^= ((uint_32t*)s)[ 1];
+    ((uint_32t*)d)[ 2] ^= ((uint_32t*)s)[ 2];
+    ((uint_32t*)d)[ 3] ^= ((uint_32t*)s)[ 3];
+#else
+    ((uint_8t*)d)[ 0] ^= ((uint_8t*)s)[ 0];
+    ((uint_8t*)d)[ 1] ^= ((uint_8t*)s)[ 1];
+    ((uint_8t*)d)[ 2] ^= ((uint_8t*)s)[ 2];
+    ((uint_8t*)d)[ 3] ^= ((uint_8t*)s)[ 3];
+    ((uint_8t*)d)[ 4] ^= ((uint_8t*)s)[ 4];
+    ((uint_8t*)d)[ 5] ^= ((uint_8t*)s)[ 5];
+    ((uint_8t*)d)[ 6] ^= ((uint_8t*)s)[ 6];
+    ((uint_8t*)d)[ 7] ^= ((uint_8t*)s)[ 7];
+    ((uint_8t*)d)[ 8] ^= ((uint_8t*)s)[ 8];
+    ((uint_8t*)d)[ 9] ^= ((uint_8t*)s)[ 9];
+    ((uint_8t*)d)[10] ^= ((uint_8t*)s)[10];
+    ((uint_8t*)d)[11] ^= ((uint_8t*)s)[11];
+    ((uint_8t*)d)[12] ^= ((uint_8t*)s)[12];
+    ((uint_8t*)d)[13] ^= ((uint_8t*)s)[13];
+    ((uint_8t*)d)[14] ^= ((uint_8t*)s)[14];
+    ((uint_8t*)d)[15] ^= ((uint_8t*)s)[15];
+#endif
+}
+
+static void copy_and_key( void *d, const void *s, const void *k )
+{
+#if defined( HAVE_UINT_32T )
+    ((uint_32t*)d)[ 0] = ((uint_32t*)s)[ 0] ^ ((uint_32t*)k)[ 0];
+    ((uint_32t*)d)[ 1] = ((uint_32t*)s)[ 1] ^ ((uint_32t*)k)[ 1];
+    ((uint_32t*)d)[ 2] = ((uint_32t*)s)[ 2] ^ ((uint_32t*)k)[ 2];
+    ((uint_32t*)d)[ 3] = ((uint_32t*)s)[ 3] ^ ((uint_32t*)k)[ 3];
+#elif 1
+    ((uint_8t*)d)[ 0] = ((uint_8t*)s)[ 0] ^ ((uint_8t*)k)[ 0];
+    ((uint_8t*)d)[ 1] = ((uint_8t*)s)[ 1] ^ ((uint_8t*)k)[ 1];
+    ((uint_8t*)d)[ 2] = ((uint_8t*)s)[ 2] ^ ((uint_8t*)k)[ 2];
+    ((uint_8t*)d)[ 3] = ((uint_8t*)s)[ 3] ^ ((uint_8t*)k)[ 3];
+    ((uint_8t*)d)[ 4] = ((uint_8t*)s)[ 4] ^ ((uint_8t*)k)[ 4];
+    ((uint_8t*)d)[ 5] = ((uint_8t*)s)[ 5] ^ ((uint_8t*)k)[ 5];
+    ((uint_8t*)d)[ 6] = ((uint_8t*)s)[ 6] ^ ((uint_8t*)k)[ 6];
+    ((uint_8t*)d)[ 7] = ((uint_8t*)s)[ 7] ^ ((uint_8t*)k)[ 7];
+    ((uint_8t*)d)[ 8] = ((uint_8t*)s)[ 8] ^ ((uint_8t*)k)[ 8];
+    ((uint_8t*)d)[ 9] = ((uint_8t*)s)[ 9] ^ ((uint_8t*)k)[ 9];
+    ((uint_8t*)d)[10] = ((uint_8t*)s)[10] ^ ((uint_8t*)k)[10];
+    ((uint_8t*)d)[11] = ((uint_8t*)s)[11] ^ ((uint_8t*)k)[11];
+    ((uint_8t*)d)[12] = ((uint_8t*)s)[12] ^ ((uint_8t*)k)[12];
+    ((uint_8t*)d)[13] = ((uint_8t*)s)[13] ^ ((uint_8t*)k)[13];
+    ((uint_8t*)d)[14] = ((uint_8t*)s)[14] ^ ((uint_8t*)k)[14];
+    ((uint_8t*)d)[15] = ((uint_8t*)s)[15] ^ ((uint_8t*)k)[15];
+#else
+    block_copy(d, s);
+    xor_block(d, k);
+#endif
+}
+
+static void add_round_key( uint_8t d[N_BLOCK], const uint_8t k[N_BLOCK] )
+{
+    xor_block(d, k);
+}
+
+static void shift_sub_rows( uint_8t st[N_BLOCK] )
+{   uint_8t tt;
+
+    st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]);
+    st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]);
+
+    tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]);
+    st[ 9] = s_box(st[13]); st[13] = s_box( tt );
+
+    tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt );
+    tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt );
+
+    tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]);
+    st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt );
+}
+
+static void inv_shift_sub_rows( uint_8t st[N_BLOCK] )
+{   uint_8t tt;
+
+    st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]);
+    st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]);
+
+    tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]);
+    st[ 5] = is_box(st[1]); st[ 1] = is_box( tt );
+
+    tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt );
+    tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt );
+
+    tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]);
+    st[11] = is_box(st[15]); st[15] = is_box( tt );
+}
+
+#if defined( VERSION_1 )
+  static void mix_sub_columns( uint_8t dt[N_BLOCK] )
+  { uint_8t st[N_BLOCK];
+    block_copy(st, dt);
+#else
+  static void mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+  {
+#endif
+    dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]);
+    dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]);
+    dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]);
+    dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]);
+
+    dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]);
+    dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]);
+    dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]);
+    dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]);
+
+    dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]);
+    dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]);
+    dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]);
+    dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]);
+
+    dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]);
+    dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]);
+    dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]);
+    dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]);
+  }
+
+#if defined( VERSION_1 )
+  static void inv_mix_sub_columns( uint_8t dt[N_BLOCK] )
+  { uint_8t st[N_BLOCK];
+    block_copy(st, dt);
+#else
+  static void inv_mix_sub_columns( uint_8t dt[N_BLOCK], uint_8t st[N_BLOCK] )
+  {
+#endif
+    dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3]));
+    dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3]));
+    dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3]));
+    dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3]));
+
+    dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7]));
+    dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7]));
+    dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7]));
+    dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7]));
+
+    dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11]));
+    dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11]));
+    dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11]));
+    dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11]));
+
+    dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15]));
+    dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15]));
+    dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15]));
+    dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15]));
+  }
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+/*  Set the cipher key for the pre-keyed version */
+
+return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
+{
+    uint_8t cc, rc, hi;
+
+    switch( keylen )
+    {
+    case 16:
+    case 128:
+        keylen = 16;
+        break;
+    case 24:
+    case 192:
+        keylen = 24;
+        break;
+    case 32:
+    case 256:
+        keylen = 32;
+        break;
+    default:
+        ctx->rnd = 0;
+        return (return_type)-1;
+    }
+    block_copy_nn(ctx->ksch, key, keylen);
+    hi = (keylen + 28) << 2;
+    ctx->rnd = (hi >> 4) - 1;
+    for( cc = keylen, rc = 1; cc < hi; cc += 4 )
+    {   uint_8t tt, t0, t1, t2, t3;
+
+        t0 = ctx->ksch[cc - 4];
+        t1 = ctx->ksch[cc - 3];
+        t2 = ctx->ksch[cc - 2];
+        t3 = ctx->ksch[cc - 1];
+        if( cc % keylen == 0 )
+        {
+            tt = t0;
+            t0 = s_box(t1) ^ rc;
+            t1 = s_box(t2);
+            t2 = s_box(t3);
+            t3 = s_box(tt);
+            rc = f2(rc);
+        }
+        else if( keylen > 24 && cc % keylen == 16 )
+        {
+            t0 = s_box(t0);
+            t1 = s_box(t1);
+            t2 = s_box(t2);
+            t3 = s_box(t3);
+        }
+        tt = cc - keylen;
+        ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0;
+        ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1;
+        ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2;
+        ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3;
+    }
+    return 0;
+}
+
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+/*  Encrypt a single block of 16 bytes */
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK], unsigned char  out[N_BLOCK], const aes_context ctx[1] )
+{
+    if( ctx->rnd )
+    {
+        uint_8t s1[N_BLOCK], r;
+        copy_and_key( s1, in, ctx->ksch );
+
+        for( r = 1 ; r < ctx->rnd ; ++r )
+#if defined( VERSION_1 )
+        {
+            mix_sub_columns( s1 );
+            add_round_key( s1, ctx->ksch + r * N_BLOCK);
+        }
+#else
+        {   uint_8t s2[N_BLOCK];
+            mix_sub_columns( s2, s1 );
+            copy_and_key( s1, s2, ctx->ksch + r * N_BLOCK);
+        }
+#endif
+        shift_sub_rows( s1 );
+        copy_and_key( out, s1, ctx->ksch + r * N_BLOCK );
+    }
+    else
+        return (return_type)-1;
+    return 0;
+}
+
+/* CBC encrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_encrypt( const unsigned char *in, unsigned char *out,
+                         int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+
+    while(n_block--)
+    {
+        xor_block(iv, in);
+        if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+        memcpy(out, iv, N_BLOCK);
+        in += N_BLOCK;
+        out += N_BLOCK;
+    }
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+/*  Decrypt a single block of 16 bytes */
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] )
+{
+    if( ctx->rnd )
+    {
+        uint_8t s1[N_BLOCK], r;
+        copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK );
+        inv_shift_sub_rows( s1 );
+
+        for( r = ctx->rnd ; --r ; )
+#if defined( VERSION_1 )
+        {
+            add_round_key( s1, ctx->ksch + r * N_BLOCK );
+            inv_mix_sub_columns( s1 );
+        }
+#else
+        {   uint_8t s2[N_BLOCK];
+            copy_and_key( s2, s1, ctx->ksch + r * N_BLOCK );
+            inv_mix_sub_columns( s1, s2 );
+        }
+#endif
+        copy_and_key( out, s1, ctx->ksch );
+    }
+    else
+        return (return_type)-1;
+    return 0;
+}
+
+/* CBC decrypt a number of blocks (input and return an IV) */
+
+return_type aes_cbc_decrypt( const unsigned char *in, unsigned char *out,
+                         int n_block, unsigned char iv[N_BLOCK], const aes_context ctx[1] )
+{
+    while(n_block--)
+    {   uint_8t tmp[N_BLOCK];
+
+        memcpy(tmp, in, N_BLOCK);
+        if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS)
+			return EXIT_FAILURE;
+        xor_block(out, iv);
+        memcpy(iv, tmp, N_BLOCK);
+        in += N_BLOCK;
+        out += N_BLOCK;
+    }
+    return EXIT_SUCCESS;
+}
+
+#endif
+
+#if defined( AES_ENC_128_OTFK )
+
+/*  The 'on the fly' encryption key update for for 128 bit keys */
+
+static void update_encrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{   uint_8t cc;
+
+    k[0] ^= s_box(k[13]) ^ *rc;
+    k[1] ^= s_box(k[14]);
+    k[2] ^= s_box(k[15]);
+    k[3] ^= s_box(k[12]);
+    *rc = f2( *rc );
+
+    for(cc = 4; cc < 16; cc += 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+}
+
+/*  Encrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_encrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+                     const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{   uint_8t s1[N_BLOCK], r, rc = 1;
+
+    if(o_key != key)
+        block_copy( o_key, key );
+    copy_and_key( s1, in, o_key );
+
+    for( r = 1 ; r < 10 ; ++r )
+#if defined( VERSION_1 )
+    {
+        mix_sub_columns( s1 );
+        update_encrypt_key_128( o_key, &rc );
+        add_round_key( s1, o_key );
+    }
+#else
+    {   uint_8t s2[N_BLOCK];
+        mix_sub_columns( s2, s1 );
+        update_encrypt_key_128( o_key, &rc );
+        copy_and_key( s1, s2, o_key );
+    }
+#endif
+
+    shift_sub_rows( s1 );
+    update_encrypt_key_128( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+
+/*  The 'on the fly' decryption key update for for 128 bit keys */
+
+static void update_decrypt_key_128( uint_8t k[N_BLOCK], uint_8t *rc )
+{   uint_8t cc;
+
+    for( cc = 12; cc > 0; cc -= 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+    *rc = d2(*rc);
+    k[0] ^= s_box(k[13]) ^ *rc;
+    k[1] ^= s_box(k[14]);
+    k[2] ^= s_box(k[15]);
+    k[3] ^= s_box(k[12]);
+}
+
+/*  Decrypt a single block of 16 bytes with 'on the fly' 128 bit keying */
+
+void aes_decrypt_128( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+                      const unsigned char key[N_BLOCK], unsigned char o_key[N_BLOCK] )
+{
+    uint_8t s1[N_BLOCK], r, rc = 0x6c;
+    if(o_key != key)
+        block_copy( o_key, key );
+
+    copy_and_key( s1, in, o_key );
+    inv_shift_sub_rows( s1 );
+
+    for( r = 10 ; --r ; )
+#if defined( VERSION_1 )
+    {
+        update_decrypt_key_128( o_key, &rc );
+        add_round_key( s1, o_key );
+        inv_mix_sub_columns( s1 );
+    }
+#else
+    {   uint_8t s2[N_BLOCK];
+        update_decrypt_key_128( o_key, &rc );
+        copy_and_key( s2, s1, o_key );
+        inv_mix_sub_columns( s1, s2 );
+    }
+#endif
+    update_decrypt_key_128( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+
+/*  The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_encrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{   uint_8t cc;
+
+    k[0] ^= s_box(k[29]) ^ *rc;
+    k[1] ^= s_box(k[30]);
+    k[2] ^= s_box(k[31]);
+    k[3] ^= s_box(k[28]);
+    *rc = f2( *rc );
+
+    for(cc = 4; cc < 16; cc += 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    k[16] ^= s_box(k[12]);
+    k[17] ^= s_box(k[13]);
+    k[18] ^= s_box(k[14]);
+    k[19] ^= s_box(k[15]);
+
+    for( cc = 20; cc < 32; cc += 4 )
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+}
+
+/*  Encrypt a single block of 16 bytes with 'on the fly' 256 bit keying */
+
+void aes_encrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+    uint_8t s1[N_BLOCK], r, rc = 1;
+    if(o_key != key)
+    {
+        block_copy( o_key, key );
+        block_copy( o_key + 16, key + 16 );
+    }
+    copy_and_key( s1, in, o_key );
+
+    for( r = 1 ; r < 14 ; ++r )
+#if defined( VERSION_1 )
+    {
+        mix_sub_columns(s1);
+        if( r & 1 )
+            add_round_key( s1, o_key + 16 );
+        else
+        {
+            update_encrypt_key_256( o_key, &rc );
+            add_round_key( s1, o_key );
+        }
+    }
+#else
+    {   uint_8t s2[N_BLOCK];
+        mix_sub_columns( s2, s1 );
+        if( r & 1 )
+            copy_and_key( s1, s2, o_key + 16 );
+        else
+        {
+            update_encrypt_key_256( o_key, &rc );
+            copy_and_key( s1, s2, o_key );
+        }
+    }
+#endif
+
+    shift_sub_rows( s1 );
+    update_encrypt_key_256( o_key, &rc );
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+
+/*  The 'on the fly' encryption key update for for 256 bit keys */
+
+static void update_decrypt_key_256( uint_8t k[2 * N_BLOCK], uint_8t *rc )
+{   uint_8t cc;
+
+    for(cc = 28; cc > 16; cc -= 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    k[16] ^= s_box(k[12]);
+    k[17] ^= s_box(k[13]);
+    k[18] ^= s_box(k[14]);
+    k[19] ^= s_box(k[15]);
+
+    for(cc = 12; cc > 0; cc -= 4)
+    {
+        k[cc + 0] ^= k[cc - 4];
+        k[cc + 1] ^= k[cc - 3];
+        k[cc + 2] ^= k[cc - 2];
+        k[cc + 3] ^= k[cc - 1];
+    }
+
+    *rc = d2(*rc);
+    k[0] ^= s_box(k[29]) ^ *rc;
+    k[1] ^= s_box(k[30]);
+    k[2] ^= s_box(k[31]);
+    k[3] ^= s_box(k[28]);
+}
+
+/*  Decrypt a single block of 16 bytes with 'on the fly'
+    256 bit keying
+*/
+void aes_decrypt_256( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK], unsigned char o_key[2 * N_BLOCK] )
+{
+    uint_8t s1[N_BLOCK], r, rc = 0x80;
+
+    if(o_key != key)
+    {
+        block_copy( o_key, key );
+        block_copy( o_key + 16, key + 16 );
+    }
+
+    copy_and_key( s1, in, o_key );
+    inv_shift_sub_rows( s1 );
+
+    for( r = 14 ; --r ; )
+#if defined( VERSION_1 )
+    {
+        if( ( r & 1 ) )
+        {
+            update_decrypt_key_256( o_key, &rc );
+            add_round_key( s1, o_key + 16 );
+        }
+        else
+            add_round_key( s1, o_key );
+        inv_mix_sub_columns( s1 );
+    }
+#else
+    {   uint_8t s2[N_BLOCK];
+        if( ( r & 1 ) )
+        {
+            update_decrypt_key_256( o_key, &rc );
+            copy_and_key( s2, s1, o_key + 16 );
+        }
+        else
+            copy_and_key( s2, s1, o_key );
+        inv_mix_sub_columns( s1, s2 );
+    }
+#endif
+    copy_and_key( out, s1, o_key );
+}
+
+#endif
diff --git a/stack/smp/aes.h b/stack/smp/aes.h
new file mode 100644
index 0000000..dcfde93
--- /dev/null
+++ b/stack/smp/aes.h
@@ -0,0 +1,162 @@
+/*
+ ---------------------------------------------------------------------------
+ Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
+
+ LICENSE TERMS
+
+ The redistribution and use of this software (with or without changes)
+ is allowed without the payment of fees or royalties provided that:
+
+  1. source code distributions include the above copyright notice, this
+     list of conditions and the following disclaimer;
+
+  2. binary distributions include the above copyright notice, this list
+     of conditions and the following disclaimer in their documentation;
+
+  3. the name of the copyright holder is not used to endorse products
+     built using this software without specific written permission.
+
+ DISCLAIMER
+
+ This software is provided 'as is' with no explicit or implied warranties
+ in respect of its properties, including, but not limited to, correctness
+ and/or fitness for purpose.
+ ---------------------------------------------------------------------------
+ Issue 09/09/2006
+
+ This is an AES implementation that uses only 8-bit byte operations on the
+ cipher state.
+ */
+
+#ifndef AES_H
+#define AES_H
+
+#if 1
+#  define AES_ENC_PREKEYED  /* AES encryption with a precomputed key schedule  */
+#endif
+#if 1
+#  define AES_DEC_PREKEYED  /* AES decryption with a precomputed key schedule  */
+#endif
+#if 1
+#  define AES_ENC_128_OTFK  /* AES encryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+#  define AES_DEC_128_OTFK  /* AES decryption with 'on the fly' 128 bit keying */
+#endif
+#if 1
+#  define AES_ENC_256_OTFK  /* AES encryption with 'on the fly' 256 bit keying */
+#endif
+#if 1
+#  define AES_DEC_256_OTFK  /* AES decryption with 'on the fly' 256 bit keying */
+#endif
+
+#define N_ROW                   4
+#define N_COL                   4
+#define N_BLOCK   (N_ROW * N_COL)
+#define N_MAX_ROUNDS           14
+
+typedef unsigned char uint_8t;
+
+typedef uint_8t return_type;
+
+/*  Warning: The key length for 256 bit keys overflows a byte
+    (see comment below)
+*/
+
+typedef uint_8t length_type;
+
+typedef struct
+{   uint_8t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK];
+    uint_8t rnd;
+} aes_context;
+
+/*  The following calls are for a precomputed key schedule
+
+    NOTE: If the length_type used for the key length is an
+    unsigned 8-bit character, a key length of 256 bits must
+    be entered as a length in bytes (valid inputs are hence
+    128, 192, 16, 24 and 32).
+*/
+
+#if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
+
+return_type aes_set_key( const unsigned char key[],
+                         length_type keylen,
+                         aes_context ctx[1] );
+#endif
+
+#if defined( AES_ENC_PREKEYED )
+
+return_type aes_encrypt( const unsigned char in[N_BLOCK],
+                         unsigned char out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_encrypt( const unsigned char *in,
+                         unsigned char *out,
+                         int n_block,
+                         unsigned char iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+#if defined( AES_DEC_PREKEYED )
+
+return_type aes_decrypt( const unsigned char in[N_BLOCK],
+                         unsigned char out[N_BLOCK],
+                         const aes_context ctx[1] );
+
+return_type aes_cbc_decrypt( const unsigned char *in,
+                         unsigned char *out,
+                         int n_block,
+                         unsigned char iv[N_BLOCK],
+                         const aes_context ctx[1] );
+#endif
+
+/*  The following calls are for 'on the fly' keying.  In this case the
+    encryption and decryption keys are different.
+
+    The encryption subroutines take a key in an array of bytes in
+    key[L] where L is 16, 24 or 32 bytes for key lengths of 128,
+    192, and 256 bits respectively.  They then encrypts the input
+    data, in[] with this key and put the reult in the output array
+    out[].  In addition, the second key array, o_key[L], is used
+    to output the key that is needed by the decryption subroutine
+    to reverse the encryption operation.  The two key arrays can
+    be the same array but in this case the original key will be
+    overwritten.
+
+    In the same way, the decryption subroutines output keys that
+    can be used to reverse their effect when used for encryption.
+
+    Only 128 and 256 bit keys are supported in these 'on the fly'
+    modes.
+*/
+
+#if defined( AES_ENC_128_OTFK )
+void aes_encrypt_128( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[N_BLOCK],
+                      uint_8t o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_128_OTFK )
+void aes_decrypt_128( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[N_BLOCK],
+                      unsigned char o_key[N_BLOCK] );
+#endif
+
+#if defined( AES_ENC_256_OTFK )
+void aes_encrypt_256( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK],
+                      unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#if defined( AES_DEC_256_OTFK )
+void aes_decrypt_256( const unsigned char in[N_BLOCK],
+                      unsigned char out[N_BLOCK],
+                      const unsigned char key[2 * N_BLOCK],
+                      unsigned char o_key[2 * N_BLOCK] );
+#endif
+
+#endif
diff --git a/stack/smp/smp_act.c b/stack/smp/smp_act.c
index ca24225..73f4811 100644
--- a/stack/smp/smp_act.c
+++ b/stack/smp/smp_act.c
@@ -36,7 +36,7 @@
         {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
     /* responder */
     {{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY,   SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}, /* Display Only */
-        {SMP_MODEL_ENC_ONLY,  SMP_MODEL_ENC_ONLY,   SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+        {SMP_MODEL_ENC_ONLY,  SMP_MODEL_ENC_ONLY,   SMP_MODEL_KEY_NOTIF,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
         {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_PASSKEY}, /* keyboard only */
         {SMP_MODEL_ENC_ONLY,  SMP_MODEL_ENC_ONLY,   SMP_MODEL_ENC_ONLY,  SMP_MODEL_ENC_ONLY,    SMP_MODEL_ENC_ONLY},/* No Input No Output */
         {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENC_ONLY,    SMP_MODEL_PASSKEY}} /* keyboard display */
@@ -477,8 +477,6 @@
 
     SMP_TRACE_DEBUG0 ("smp_proc_id_info ");
     STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN);   /* reuse TK for IRK */
-    /* store the ID key from peer device */
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&p_cb->tk, TRUE);
 
     smp_key_distribution(p_cb, NULL);
 }
@@ -489,14 +487,17 @@
 void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8   *p = (UINT8 *)p_data;
-    BD_ADDR    mac_bda;
+    tBTM_LE_PID_KEYS    pid_key;
 
     SMP_TRACE_DEBUG0 ("smp_proc_id_addr  ");
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
 
-    STREAM_TO_BDADDR(mac_bda, p);
+    STREAM_TO_UINT8(pid_key.addr_type, p);
+    STREAM_TO_BDADDR(pid_key.static_addr, p);
+    memcpy(pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
 
-    /* TODO, update MAC address */
+    /* store the ID key from peer device */
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID, (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
 
     smp_key_distribution(p_cb, NULL);
 }
@@ -529,7 +530,11 @@
     UINT8   reason;
 
     SMP_TRACE_DEBUG0 ("smp_proc_compare  ");
-    if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
+    if (
+#if SMP_CONFORMANCE_TESTING == TRUE
+        p_cb->skip_test_compare_check ||
+#endif
+        !memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN))
     {
         /* compare the max encryption key size, and save the smaller one for the link */
         if ( p_cb->peer_enc_size < p_cb->loc_enc_size)
@@ -602,7 +607,7 @@
 void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     SMP_TRACE_DEBUG0 ("smp_proc_discard ");
-    smp_cb_cleanup(p_cb);
+    smp_reset_control_value(p_cb);
 }
 /*******************************************************************************
 ** Function     smp_proc_release_delay
@@ -736,7 +741,7 @@
     tSMP_ASSO_MODEL model = SMP_MODEL_MAX;
     UINT8 int_evt = 0;
     tSMP_KEY key;
-    tSMP_INT_DATA   *p;
+    tSMP_INT_DATA   *p = NULL;
 
     SMP_TRACE_DEBUG3 ("smp_decide_asso_model p_cb->peer_io_caps = %d p_cb->loc_io_caps = %d \
                        p_cb->peer_auth_req = %02x",
@@ -875,7 +880,12 @@
 void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     SMP_TRACE_DEBUG0 ("smp_pair_terminate ");
-    p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
+    if (p_data->reason == L2CAP_CONN_CANCEL)
+        p_cb->status = SMP_CONN_TOUT;
+    else
+        p_cb->status = SMP_PAIR_FAIL_UNKNOWN;
+
     smp_proc_pairing_cmpl(p_cb);
 }
 /*******************************************************************************
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 9eb2f10..e8d93de 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -198,6 +198,7 @@
 
     UINT8           rand_enc_proc;
     BOOLEAN         last_cmd;
+    UINT8           addr_type;
     BD_ADDR         local_bda;
     BOOLEAN         is_pair_cancel;
     BOOLEAN         discard_sec_req;
@@ -209,6 +210,7 @@
     BOOLEAN         enable_test_pair_fail;
     UINT8           pair_fail_status;
     BOOLEAN         remove_fixed_channel_disable;
+    BOOLEAN         skip_test_compare_check;
 #endif
 
 }tSMP_CB;
@@ -242,6 +244,7 @@
 SMP_API extern void  smp_set_test_rand_value (BOOLEAN enable, UINT8 *p_c_value);
 SMP_API extern void  smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status);
 SMP_API extern void  smp_remove_fixed_channel_disable (BOOLEAN disable);
+SMP_API extern void  smp_skip_compare_check (BOOLEAN enable);
 #endif
 /* smp main */
 extern void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
diff --git a/stack/smp/smp_keys.c b/stack/smp/smp_keys.c
index c61b548..a1955f2 100644
--- a/stack/smp/smp_keys.c
+++ b/stack/smp/smp_keys.c
@@ -181,7 +181,7 @@
 {
     UINT8   *tt = p_cb->tk;
     tSMP_KEY    key;
-    UINT32  passkey; //= 19655 test number; */
+    UINT32  passkey; /* 19655 test number; */
     UINT8 *pp = p->param_buf;
 
     SMP_TRACE_DEBUG0 ("smp_proc_passkey ");
@@ -445,23 +445,25 @@
 void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
 {
     UINT8 *p = (UINT8 *)p1;
-    tBTM_SEC_DEV_REC  *p_dev_rec;
+    tBLE_ADDR_TYPE    addr_type = 0;
+    BD_ADDR           remote_bda;
 
     SMP_TRACE_DEBUG0 ("smp_gen_p1_4_confirm");
-    if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+
+    if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
     {
         SMP_TRACE_ERROR0("can not generate confirm for unknown device");
         return;
     }
 
-    BTM_ReadConnectionAddr(p_cb->local_bda);
+    BTM_ReadConnectionAddr( p_cb->pairing_bda, p_cb->local_bda, &p_cb->addr_type);
 
     if (p_cb->role == HCI_ROLE_MASTER)
     {
         /* LSB : rat': initiator's(local) address type */
-        UINT8_TO_STREAM(p, 0);
+        UINT8_TO_STREAM(p, p_cb->addr_type);
         /* LSB : iat': responder's address type */
-        UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+        UINT8_TO_STREAM(p, addr_type);
         /* concatinate preq */
         smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
         /* concatinate pres */
@@ -470,9 +472,9 @@
     else
     {
         /* LSB : iat': initiator's address type */
-        UINT8_TO_STREAM(p, p_dev_rec->ble.ble_addr_type);
+        UINT8_TO_STREAM(p, addr_type);
         /* LSB : rat': responder's(local) address type */
-        UINT8_TO_STREAM(p, 0);
+        UINT8_TO_STREAM(p, p_cb->addr_type);
         /* concatinate preq */
         smp_concatenate_peer(p_cb, &p, SMP_OPCODE_PAIRING_REQ);
         /* concatinate pres */
@@ -495,15 +497,24 @@
 *******************************************************************************/
 void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
 {
-    UINT8   *p = (UINT8 *)p2;
+    UINT8       *p = (UINT8 *)p2;
+    BD_ADDR     remote_bda;
+    tBLE_ADDR_TYPE  addr_type = 0;
+
+    if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, remote_bda, &addr_type))
+    {
+        SMP_TRACE_ERROR0("can not generate confirm p2 for unknown device");
+        return;
+    }
 
     SMP_TRACE_DEBUG0 ("smp_gen_p2_4_confirm");
+
     memset(p, 0, sizeof(BT_OCTET16));
 
     if (p_cb->role == HCI_ROLE_MASTER)
     {
         /* LSB ra */
-        BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+        BDADDR_TO_STREAM(p, remote_bda);
         /* ia */
         BDADDR_TO_STREAM(p, p_cb->local_bda);
     }
@@ -512,7 +523,7 @@
         /* LSB ra */
         BDADDR_TO_STREAM(p, p_cb->local_bda);
         /* ia */
-        BDADDR_TO_STREAM(p, p_cb->pairing_bda);
+        BDADDR_TO_STREAM(p, remote_bda);
     }
 #if SMP_DEBUG == TRUE
     SMP_TRACE_DEBUG0("p2 = padding || ia || ra");
diff --git a/stack/smp/smp_l2c.c b/stack/smp/smp_l2c.c
index 648cd59..54b78b4 100644
--- a/stack/smp/smp_l2c.c
+++ b/stack/smp/smp_l2c.c
@@ -99,8 +99,6 @@
                 p_cb->loc_auth_req = p_cb->peer_auth_req = SMP_DEFAULT_AUTH_REQ;
                 p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
                 smp_sm_event(p_cb, SMP_L2CAP_CONN_EVT, NULL);
-
-                BTM_ReadConnectionAddr(p_cb->local_bda);
             }
         }
         else
diff --git a/stack/smp/smp_main.c b/stack/smp/smp_main.c
index a60f54b..59dddb4 100644
--- a/stack/smp/smp_main.c
+++ b/stack/smp/smp_main.c
@@ -174,7 +174,7 @@
 /* KEY_READY          */{ 0,    3,     0,      3,     1,   0,    2,   1,    6,     0   },
 /* ENC_CMPL           */{ 0,    0,     0,      0,     0,   0,    0,   2,    0,     0   },
 /* L2C_CONN           */{ 1,    0,     0,      0,     0,   0,    0,   0,    0,     0   },
-/* L2C_DISC           */{ 0,    0x83,  0,      0x83,  0x83,0x83, 0x83,0x83, 0x83,  2   },
+/* L2C_DISC           */{ 0x83,	0x83,  0,      0x83,  0x83,0x83, 0x83,0x83, 0x83,  2   },
 /* IO_RSP             */{ 0,    2,     0,      0,     0,   0,    0,   0,    0,     0   },
 /* SEC_GRANT          */{ 0,    1,     0,      0,     0,   0,    0,   0,    0,     0   },
 /* TK_REQ             */{ 0,    0,     0,      2,     0,   0,    0,   0,    0,     0   },
diff --git a/stack/smp/smp_utils.c b/stack/smp/smp_utils.c
index 5622880..168d6bd 100644
--- a/stack/smp/smp_utils.c
+++ b/stack/smp/smp_utils.c
@@ -336,18 +336,18 @@
 {
     BT_HDR      *p_buf = NULL ;
     UINT8       *p;
-    BT_OCTET16  irk;
+    BD_ADDR     static_addr;
+
+
     SMP_TRACE_EVENT0("smp_build_id_addr_cmd");
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_ID_ADDR_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
-        BTM_GetDeviceIDRoot(irk);
-
         UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
         UINT8_TO_STREAM (p, 0);     /* TODO: update with local address type */
-        BTM_ReadConnectionAddr(p_cb->local_bda);
-        BDADDR_TO_STREAM (p, p_cb->local_bda);
+        BTM_GetLocalDeviceAddr(static_addr);
+        BDADDR_TO_STREAM (p, static_addr);
 
         p_buf->offset = L2CAP_MIN_OFFSET;
         p_buf->len = SMP_ID_ADDR_SIZE;
@@ -367,7 +367,7 @@
 {
     BT_HDR      *p_buf = NULL ;
     UINT8       *p;
-    //BT_OCTET16  srk; remove
+
     SMP_TRACE_EVENT0("smp_build_signing_info_cmd");
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_SIGN_INFO_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
@@ -667,6 +667,20 @@
     SMP_TRACE_DEBUG1("smp_remove_fixed_channel_disable disable =%d", disable);
     smp_cb.remove_fixed_channel_disable = disable;
 }
+/*******************************************************************************
+**
+** Function         smp_skip_compare_check
+**
+** Description      This function is called to skip the compare value check
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_skip_compare_check(BOOLEAN enable)
+{
+    SMP_TRACE_DEBUG1("smp_skip_compare_check enable=%d", enable);
+    smp_cb.skip_test_compare_check = enable;
+}
 
 #endif
 
diff --git a/test/bluedroidtest/README.txt b/test/bluedroidtest/README.txt
index a443a29..0a47050 100644
--- a/test/bluedroidtest/README.txt
+++ b/test/bluedroidtest/README.txt
@@ -41,16 +41,29 @@
 
 Enabling Test Mode (Bluetooth must be enabled for this command to work)
 ======================================================================
->enable_test_mode
-ENABLE BT TEST MODE
+>dut_mode_configure 1
+BT DUT MODE CONFIGURE
 HAL REQUEST SUCCESS
 >
 
 Disabling Test Mode
 ===================
->disable_test_mode
-DISABLE BT TEST MODE
+>dut_mode_configure 0
+BT DUT MODE CONFIGURE
 HAL REQUEST SUCCESS
+>
+
+Running BLE Test commands (Bluetooth must be enabled)
+=====================================================
+NOTE: Unlike BR/EDR, there is no explicit DUT mode to run these BLE tests.
+
+> le_test_mode 1 <rx_freq>
+
+> le_test_mode 2 <tx_freq> <test_data_len> <payload_pattern>
+
+> le_test_mode 3 <no_args>
+Please refer to the BT Core spec pages-1099 to 1102 for possible values for
+the above parameters. These values need to be provided in Decimal format.
 
 Exit the test application
 =========================
@@ -68,6 +81,8 @@
 quit
 enable :: enables bluetooth
 disable :: disables bluetooth
-enable_test_mode :: enters bluedroid test mode
-disable_test_mode :: exits bluedroid test mode
+dut_mode_configure :: DUT mode - 1 to enter,0 to exit
+le_test_mode :: LE Test Mode - RxTest - 1 <rx_freq>,
+	                           TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>,
+	                           End Test - 3 <no_args>
 
diff --git a/test/bluedroidtest/bluedroidtest.c b/test/bluedroidtest/bluedroidtest.c
index 130bc60..ad9f402 100644
--- a/test/bluedroidtest/bluedroidtest.c
+++ b/test/bluedroidtest/bluedroidtest.c
@@ -474,6 +474,11 @@
     bdt_log("DUT MODE RECV : NOT IMPLEMENTED");
 }
 
+static void le_test_mode(bt_status_t status, uint16_t packet_count)
+{
+    bdt_log("LE TEST MODE END status:%s number_of_packets:%d", dump_bt_status(status), packet_count);
+}
+
 static bt_callbacks_t bt_callbacks = {
     sizeof(bt_callbacks_t),
     adapter_state_changed,
@@ -487,6 +492,8 @@
     NULL, /* acl_state_changed_cb */
     NULL, /* thread_evt_cb */
     dut_mode_recv, /*dut_mode_recv_cb */
+    NULL, /*authorize_request_cb */
+    le_test_mode /* le_test_mode_cb */
 };
 
 void bdt_init(void)
@@ -538,6 +545,58 @@
     check_return_status(status);
 }
 
+#define HCI_LE_RECEIVER_TEST_OPCODE 0x201D
+#define HCI_LE_TRANSMITTER_TEST_OPCODE 0x201E
+#define HCI_LE_END_TEST_OPCODE 0x201F
+
+void bdt_le_test_mode(char *p)
+{
+    int cmd;
+    unsigned char buf[3];
+    int arg1, arg2, arg3;
+
+    bdt_log("BT LE TEST MODE");
+    if (!bt_enabled) {
+        bdt_log("Bluetooth must be enabled for le_test to work.");
+        return;
+    }
+
+    memset(buf, 0, sizeof(buf));
+    cmd = get_int(&p, 0);
+    switch (cmd)
+    {
+        case 0x1: /* RX TEST */
+           arg1 = get_int(&p, -1);
+           if (arg1 < 0) bdt_log("%s Invalid arguments", __FUNCTION__);
+           buf[0] = arg1;
+           status = sBtInterface->le_test_mode(HCI_LE_RECEIVER_TEST_OPCODE, buf, 1);
+           break;
+        case 0x2: /* TX TEST */
+            arg1 = get_int(&p, -1);
+            arg2 = get_int(&p, -1);
+            arg3 = get_int(&p, -1);
+            if ((arg1 < 0) || (arg2 < 0) || (arg3 < 0))
+                bdt_log("%s Invalid arguments", __FUNCTION__);
+            buf[0] = arg1;
+            buf[1] = arg2;
+            buf[2] = arg3;
+            status = sBtInterface->le_test_mode(HCI_LE_TRANSMITTER_TEST_OPCODE, buf, 3);
+           break;
+        case 0x3: /* END TEST */
+            status = sBtInterface->le_test_mode(HCI_LE_END_TEST_OPCODE, buf, 0);
+           break;
+        default:
+            bdt_log("Unsupported command");
+            return;
+            break;
+    }
+    if (status != BT_STATUS_SUCCESS)
+    {
+        bdt_log("%s Test 0x%x Failed with status:0x%x", __FUNCTION__, cmd, status);
+    }
+    return;
+}
+
 void bdt_cleanup(void)
 {
     bdt_log("CLEANUP");
@@ -595,6 +654,11 @@
     bdt_dut_mode_configure(p);
 }
 
+void do_le_test_mode(char *p)
+{
+    bdt_le_test_mode(p);
+}
+
 void do_cleanup(char *p)
 {
     bdt_cleanup();
@@ -623,7 +687,9 @@
     { "enable", do_enable, ":: enables bluetooth", 0 },
     { "disable", do_disable, ":: disables bluetooth", 0 },
     { "dut_mode_configure", do_dut_mode_configure, ":: DUT mode - 1 to enter,0 to exit", 0 },
-
+    { "le_test_mode", do_le_test_mode, ":: LE Test Mode - RxTest - 1 <rx_freq>, \n\t \
+                      TxTest - 2 <tx_freq> <test_data_len> <payload_pattern>, \n\t \
+                      End Test - 3 <no_args>", 0 },
     /* add here */
 
     /* last entry */