Initial version of BLE support for Bluedroid

Change-Id: I9825a5cef9be2559c34c2a529b211b7d471147cf
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