OSDN Git Service

LE Privacy 1.2 and LE secure connections
authorSatya Calloji <satyac@broadcom.com>
Fri, 6 Mar 2015 18:38:22 +0000 (10:38 -0800)
committerAndre Eisenbach <eisenbach@google.com>
Mon, 13 Apr 2015 07:09:06 +0000 (00:09 -0700)
Bug: 19816438
Original author: Chaojing Sun <cjsun@broadcom.com>
Change-Id: I5951f4d4e038f8348a62aa6d19b2111bae0b3ecc

74 files changed:
bta/ag/bta_ag_act.c
bta/dm/bta_dm_act.c
bta/dm/bta_dm_api.c
bta/dm/bta_dm_int.h
bta/dm/bta_dm_main.c
bta/hf_client/bta_hf_client_act.c
bta/include/bta_api.h
btif/include/btif_dm.h
btif/src/btif_config.c
btif/src/btif_dm.c
btif/src/btif_storage.c
device/include/controller.h
device/src/controller.c
hci/include/hci_packet_factory.h
hci/include/hci_packet_parser.h
hci/src/hci_packet_factory.c
hci/src/hci_packet_parser.c
include/bt_target.h
stack/Android.mk
stack/btm/btm_acl.c
stack/btm/btm_ble.c
stack/btm/btm_ble_addr.c
stack/btm/btm_ble_adv_filter.c
stack/btm/btm_ble_bgconn.c
stack/btm/btm_ble_gap.c
stack/btm/btm_ble_int.h
stack/btm/btm_ble_multi_adv.c
stack/btm/btm_ble_privacy.c [new file with mode: 0644]
stack/btm/btm_dev.c
stack/btm/btm_devctl.c
stack/btm/btm_inq.c
stack/btm/btm_int.h
stack/btm/btm_sec.c
stack/btu/btu_hcif.c
stack/gap/gap_ble.c
stack/gap/gap_int.h
stack/gatt/gatt_api.c
stack/gatt/gatt_int.h
stack/gatt/gatt_main.c
stack/gatt/gatt_sr.c
stack/gatt/gatt_utils.c
stack/hcic/hciblecmds.c
stack/hid/hidh_conn.c
stack/include/bt_types.h
stack/include/btm_api.h
stack/include/btm_ble_api.h
stack/include/gap_api.h
stack/include/gattdefs.h
stack/include/hcidefs.h
stack/include/hcimsgs.h
stack/include/l2c_api.h
stack/include/l2cdefs.h
stack/include/smp_api.h
stack/l2cap/l2c_api.c
stack/l2cap/l2c_ble.c
stack/l2cap/l2c_link.c
stack/l2cap/l2c_utils.c
stack/smp/aes.c
stack/smp/p_256_curvepara.c [new file with mode: 0644]
stack/smp/p_256_ecc_pp.c [new file with mode: 0644]
stack/smp/p_256_ecc_pp.h [new file with mode: 0644]
stack/smp/p_256_multprecision.c [new file with mode: 0644]
stack/smp/p_256_multprecision.h [new file with mode: 0644]
stack/smp/smp_act.c
stack/smp/smp_api.c
stack/smp/smp_br_main.c [new file with mode: 0644]
stack/smp/smp_cmac.c
stack/smp/smp_int.h
stack/smp/smp_keys.c
stack/smp/smp_l2c.c
stack/smp/smp_main.c
stack/smp/smp_utils.c
vnd/ble/vendor_ble.c [deleted file]
vnd/include/vendor_ble.h [deleted file]

index f661a19..1b625d1 100644 (file)
@@ -684,7 +684,7 @@ void bta_ag_start_close(tBTA_AG_SCB *p_scb, tBTA_AG_DATA *p_data)
 {
     /* Take the link out of sniff and set L2C idle time to 0 */
     bta_dm_pm_active(p_scb->peer_addr);
-    L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0);
+    L2CA_SetIdleTimeoutByBdAddr(p_scb->peer_addr, 0, BT_TRANSPORT_BR_EDR);
 
     /* if SCO is open close SCO and wait on RFCOMM close */
     if (bta_ag_sco_is_open(p_scb))
index 14b6093..062ae06 100644 (file)
@@ -413,7 +413,8 @@ void bta_dm_disable (tBTA_DM_MSG *p_data)
     UNUSED(p_data);
 
     /* Set l2cap idle timeout to 0 (so BTE immediately disconnects ACL link after last channel is closed) */
-    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0);
+    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_BR_EDR);
+    L2CA_SetIdleTimeoutByBdAddr((UINT8 *)BT_BD_ANY, 0, BT_TRANSPORT_LE);
 
     /* disable all active subsystems */
     bta_sys_disable(BTA_SYS_HW_BLUETOOTH);
@@ -4301,10 +4302,9 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
 {
     tBTM_STATUS status = BTM_SUCCESS;
     tBTA_DM_SEC sec_event;
-    charp_name = NULL;
+    char *p_name = NULL;
     UINT8 i;
-
-    APPL_TRACE_DEBUG("bta_dm_ble_smp_cback");
+    tBT_DEVICE_TYPE dev_type;
 
     if (!bta_dm_cb.p_sec_cback)
         return BTM_NOT_AUTHORIZED;
@@ -4371,31 +4371,24 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
             bta_dm_cb.p_sec_cback(BTA_DM_BLE_OOB_REQ_EVT, &sec_event);
             break;
 
+        case BTM_LE_NC_REQ_EVT:
+            bdcpy(sec_event.key_notif.bd_addr, bda);
+            BCM_STRNCPY_S((char*)sec_event.key_notif.bd_name, sizeof(BD_NAME), bta_dm_get_remname(), (BD_NAME_LEN));
+            sec_event.ble_req.bd_name[BD_NAME_LEN] = 0;
+            sec_event.key_notif.passkey = p_data->key_notif;
+            bta_dm_cb.p_sec_cback(BTA_DM_BLE_NC_REQ_EVT, &sec_event);
+            break;
+
         case BTM_LE_KEY_EVT:
             bdcpy(sec_event.ble_key.bd_addr, bda);
             sec_event.ble_key.key_type = p_data->key.key_type;
-
-            if (p_data->key.key_type == BTM_LE_KEY_PID)
-            {
-                for (i=0; i<BT_OCTET16_LEN; i++ )
-                {
-                    sec_event.ble_key.key_value.pid_key.irk[i] = p_data->key.p_key_value->pid_key.irk[i];
-                }
-                sec_event.ble_key.key_value.pid_key.addr_type = p_data->key.p_key_value->pid_key.addr_type;
-                memcpy( &(sec_event.ble_key.key_value.pid_key.static_addr),
-                        &(p_data->key.p_key_value->pid_key.static_addr),
-                        sizeof (BD_ADDR));
-            }
-            else
-            {
-                memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE));
-            }
-            // memcpy(&sec_event.ble_key.key_value, p_data->key.p_key_value, sizeof(tBTM_LE_KEY_VALUE)); todo will crash
+            sec_event.ble_key.p_key_value = p_data->key.p_key_value;
             bta_dm_cb.p_sec_cback(BTA_DM_BLE_KEY_EVT, &sec_event);
             break;
 
         case BTM_LE_COMPLT_EVT:
             bdcpy(sec_event.auth_cmpl.bd_addr, bda);
+            BTM_ReadDevInfo(bda, &dev_type, &sec_event.auth_cmpl.addr_type);
             p_name = BTM_SecReadDevName(bda);
             if (p_name != NULL)
             {
@@ -4417,6 +4410,7 @@ static UINT8 bta_dm_ble_smp_cback (tBTM_LE_EVT event, BD_ADDR bda, tBTM_LE_EVT_D
                 sec_event.auth_cmpl.success = TRUE;
                 GATT_ConfigServiceChangeCCC(bda, TRUE, BT_TRANSPORT_LE);
             }
+
             if (bta_dm_cb.p_sec_cback)
             {
                 //bta_dm_cb.p_sec_cback(BTA_DM_AUTH_CMPL_EVT, &sec_event);
@@ -4545,6 +4539,28 @@ void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data)
 
 /*******************************************************************************
 **
+** Function         bta_dm_ble_confirm_reply
+**
+** Description      This is response to SM numeric comparison request submitted
+**                  to application.
+**
+** Parameters:
+**
+*******************************************************************************/
+void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data)
+{
+    if (p_data->confirm.accept)
+    {
+        BTM_BleConfirmReply(p_data->confirm.bd_addr, BTM_SUCCESS);
+    }
+    else
+    {
+        BTM_BleConfirmReply(p_data->ble_passkey_reply.bd_addr, BTM_NOT_AUTHORIZED);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         bta_dm_security_grant
 **
 ** Description      This function grant SMP security request access.
index 92ab0a8..47b9488 100644 (file)
@@ -31,7 +31,6 @@
 #include "btm_int.h"
 #include <string.h>
 #include "utl.h"
-#include "vendor_ble.h"
 
 /*****************************************************************************
 **  Constants
@@ -793,6 +792,31 @@ void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passkey)
 }
 /*******************************************************************************
 **
+** Function         BTA_DmBleConfirmReply
+**
+** Description      Send BLE SMP SC user confirmation reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - numbers to compare are the same or different.
+**
+** Returns          void
+**
+*******************************************************************************/
+void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept)
+{
+    tBTA_DM_API_CONFIRM *p_msg = (tBTA_DM_API_CONFIRM *)GKI_getbuf(sizeof(tBTA_DM_API_CONFIRM));
+    if (p_msg != NULL)
+    {
+        memset(p_msg, 0, sizeof(tBTA_DM_API_CONFIRM));
+        p_msg->hdr.event = BTA_DM_API_BLE_CONFIRM_REPLY_EVT;
+        bdcpy(p_msg->bd_addr, bd_addr);
+        p_msg->accept = accept;
+        bta_sys_sendmsg(p_msg);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         BTA_DmBleSecurityGrant
 **
 ** Description      Grant security request access.
@@ -2004,7 +2028,9 @@ void BTA_VendorCleanup (void)
     if (cmn_ble_vsc_cb.max_filter > 0)
     {
         btm_ble_adv_filter_cleanup();
-        btm_ble_vendor_cleanup();
+#if BLE_PRIVACY_SPT == TRUE
+        btm_ble_resolving_list_cleanup ();
+#endif
     }
 
     if (cmn_ble_vsc_cb.tot_scan_results_strg > 0)
index 4ab8497..798a909 100644 (file)
@@ -85,6 +85,7 @@ enum
     BTA_DM_API_ADD_BLEKEY_EVT,
     BTA_DM_API_ADD_BLEDEVICE_EVT,
     BTA_DM_API_BLE_PASSKEY_REPLY_EVT,
+    BTA_DM_API_BLE_CONFIRM_REPLY_EVT,
     BTA_DM_API_BLE_SEC_GRANT_EVT,
     BTA_DM_API_BLE_SET_BG_CONN_TYPE,
     BTA_DM_API_BLE_CONN_PARAM_EVT,
@@ -1043,6 +1044,7 @@ extern void bta_dm_add_ampkey (tBTA_DM_MSG *p_data);
 extern void bta_dm_add_blekey (tBTA_DM_MSG *p_data);
 extern void bta_dm_add_ble_device (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_passkey_reply (tBTA_DM_MSG *p_data);
+extern void bta_dm_ble_confirm_reply (tBTA_DM_MSG *p_data);
 extern void bta_dm_security_grant (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_bg_conn_type (tBTA_DM_MSG *p_data);
 extern void bta_dm_ble_set_conn_params (tBTA_DM_MSG *p_data);
@@ -1106,8 +1108,6 @@ extern void bta_dm_search_cancel_transac_cmpl(tBTA_DM_MSG *p_data);
 extern void bta_dm_disc_rmt_name (tBTA_DM_MSG *p_data);
 extern tBTA_DM_PEER_DEVICE * bta_dm_find_peer_device(BD_ADDR peer_addr);
 
-extern void bta_dm_ble_config_local_privacy (tBTA_DM_MSG *p_data);
-
 extern void bta_dm_pm_active(BD_ADDR peer_addr);
 
 void bta_dm_eir_update_uuid(UINT16 uuid16, BOOLEAN adding);
index cf810a4..75de1f3 100644 (file)
@@ -82,6 +82,7 @@ const tBTA_DM_ACTION bta_dm_action[] =
     bta_dm_add_blekey,          /*  BTA_DM_API_ADD_BLEKEY_EVT           */
     bta_dm_add_ble_device,      /*  BTA_DM_API_ADD_BLEDEVICE_EVT        */
     bta_dm_ble_passkey_reply,   /*  BTA_DM_API_BLE_PASSKEY_REPLY_EVT    */
+    bta_dm_ble_confirm_reply,   /*  BTA_DM_API_BLE_CONFIRM_REPLY_EVT    */
     bta_dm_security_grant,
     bta_dm_ble_set_bg_conn_type,
     bta_dm_ble_set_conn_params,      /* BTA_DM_API_BLE_CONN_PARAM_EVT */
index 4cf99c7..46f05ff 100644 (file)
@@ -141,7 +141,7 @@ void bta_hf_client_start_close(tBTA_HF_CLIENT_DATA *p_data)
 {
     /* Take the link out of sniff and set L2C idle time to 0 */
     bta_dm_pm_active(bta_hf_client_cb.scb.peer_addr);
-    L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0);
+    L2CA_SetIdleTimeoutByBdAddr(bta_hf_client_cb.scb.peer_addr, 0, BT_TRANSPORT_BR_EDR);
 
     /* if SCO is open close SCO and wait on RFCOMM close */
     if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST)
index efa8d32..a3410c1 100644 (file)
@@ -626,13 +626,15 @@ typedef UINT8 tBTA_SIG_STRENGTH_MASK;
 #define BTA_DM_BLE_OOB_REQ_EVT          19      /* SMP OOB request event */
 #define BTA_DM_BLE_LOCAL_IR_EVT         20      /* BLE local IR event */
 #define BTA_DM_BLE_LOCAL_ER_EVT         21      /* BLE local ER event */
+#define BTA_DM_BLE_NC_REQ_EVT           22      /* SMP Numeric Comparison request event */
 // btla-specific ++
-#define BTA_DM_BLE_AUTH_CMPL_EVT        22      /* BLE Auth complete */
+#define BTA_DM_SP_RMT_OOB_EXT_EVT       23      /* Simple Pairing Remote OOB Extended Data request. */
+#define BTA_DM_BLE_AUTH_CMPL_EVT        24      /* BLE Auth complete */
 // btla-specific --
-#define BTA_DM_DEV_UNPAIRED_EVT         23
-#define BTA_DM_HW_ERROR_EVT             24      /* BT Chip H/W error */
-#define BTA_DM_LE_FEATURES_READ         25      /* Cotroller specific LE features are read */
-#define BTA_DM_ENER_INFO_READ           26      /* Energy info read */
+#define BTA_DM_DEV_UNPAIRED_EVT         25
+#define BTA_DM_HW_ERROR_EVT             26      /* BT Chip H/W error */
+#define BTA_DM_LE_FEATURES_READ         27      /* Cotroller specific LE features are read */
+#define BTA_DM_ENER_INFO_READ           28      /* Energy info read */
 typedef UINT8 tBTA_DM_SEC_EVT;
 
 /* Structure associated with BTA_DM_ENABLE_EVT */
@@ -663,6 +665,7 @@ typedef struct
 #define BTA_DM_AUTH_SMP_INVALID_CMD             (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_CMD)
 #define BTA_DM_AUTH_SMP_UNKNOWN_ERR             (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_FAIL_UNKNOWN)
 #define BTA_DM_AUTH_SMP_REPEATED_ATTEMPT        (BTA_DM_AUTH_FAIL_BASE + SMP_REPEATED_ATTEMPTS)
+#define BTA_DM_AUTH_SMP_INVALID_PARAMETERS      (BTA_DM_AUTH_FAIL_BASE + SMP_INVALID_PARAMETERS)
 #define BTA_DM_AUTH_SMP_INTERNAL_ERR            (BTA_DM_AUTH_FAIL_BASE + SMP_PAIR_INTERNAL_ERR)
 #define BTA_DM_AUTH_SMP_UNKNOWN_IO              (BTA_DM_AUTH_FAIL_BASE + SMP_UNKNOWN_IO_CAP)
 #define BTA_DM_AUTH_SMP_INIT_FAIL               (BTA_DM_AUTH_FAIL_BASE + SMP_INIT_FAIL)
@@ -706,6 +709,7 @@ typedef union
     tBTA_LE_PID_KEYS    pid_key;        /* peer device ID key */
     tBTA_LE_LENC_KEYS   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
     tBTA_LE_LCSRK_KEYS  lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
+    tBTA_LE_PID_KEYS    lid_key;        /* local device ID key for the particular remote */
 }tBTA_LE_KEY_VALUE;
 
 #define BTA_BLE_LOCAL_KEY_TYPE_ID         1
@@ -743,7 +747,7 @@ typedef struct
 {
     BD_ADDR                 bd_addr;        /* peer address */
     tBTM_LE_KEY_TYPE        key_type;
-    tBTM_LE_KEY_VALUE       key_value;
+    tBTM_LE_KEY_VALUE       *p_key_value;
 }tBTA_DM_BLE_KEY;
 
 /* Structure associated with BTA_DM_AUTH_CMPL_EVT */
@@ -756,7 +760,9 @@ typedef struct
     UINT8           key_type;           /* The type of Link Key */
     BOOLEAN         success;            /* TRUE of authentication succeeded, FALSE if failed. */
     UINT8           fail_reason;        /* The HCI reason/error code for when success=FALSE */
-
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+    tBLE_ADDR_TYPE  addr_type;      /* peer device address type */
+#endif
 } tBTA_DM_AUTH_CMPL;
 
 
@@ -806,10 +812,13 @@ typedef struct
     UINT8           level_flags; /* indicates individual flags */
 } tBTA_DM_BUSY_LEVEL;
 
-#define BTA_IO_CAP_OUT      BTM_IO_CAP_OUT      /* DisplayOnly */
-#define BTA_IO_CAP_IO       BTM_IO_CAP_IO       /* DisplayYesNo */
-#define BTA_IO_CAP_IN       BTM_IO_CAP_IN       /* KeyboardOnly */
-#define BTA_IO_CAP_NONE     BTM_IO_CAP_NONE     /* NoInputNoOutput */
+#define BTA_IO_CAP_OUT      BTM_IO_CAP_OUT      /* 0 DisplayOnly */
+#define BTA_IO_CAP_IO       BTM_IO_CAP_IO       /* 1 DisplayYesNo */
+#define BTA_IO_CAP_IN       BTM_IO_CAP_IN       /* 2 KeyboardOnly */
+#define BTA_IO_CAP_NONE     BTM_IO_CAP_NONE     /* 3 NoInputNoOutput */
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+#define BTA_IO_CAP_KBDISP   BTM_IO_CAP_KBDISP   /* 4 Keyboard display */
+#endif
 typedef tBTM_IO_CAP     tBTA_IO_CAP;
 
 #define BTA_AUTH_SP_NO    BTM_AUTH_SP_NO      /* 0 MITM Protection Not Required - Single Profile/non-bonding
@@ -833,6 +842,11 @@ typedef tBTM_AUTH_REQ   tBTA_AUTH_REQ;
 #define BTA_LE_AUTH_NO_BOND    BTM_LE_AUTH_REQ_NO_BOND  /* 0*/
 #define BTA_LE_AUTH_BOND       BTM_LE_AUTH_REQ_BOND     /* 1 << 0 */
 #define BTA_LE_AUTH_REQ_MITM   BTM_LE_AUTH_REQ_MITM    /* 1 << 2 */
+
+#define BTA_LE_AUTH_REQ_SC_ONLY         BTM_LE_AUTH_REQ_SC_ONLY         /* 1 << 3 */
+#define BTA_LE_AUTH_REQ_SC_BOND         BTM_LE_AUTH_REQ_SC_BOND      /* 1001 */
+#define BTA_LE_AUTH_REQ_SC_MITM         BTM_LE_AUTH_REQ_SC_MITM      /* 1100 */
+#define BTA_LE_AUTH_REQ_SC_MITM_BOND    BTM_LE_AUTH_REQ_SC_MITM_BOND /* 1101 */
 typedef tBTM_LE_AUTH_REQ       tBTA_LE_AUTH_REQ;       /* combination of the above bit pattern */
 
 #define BTA_OOB_NONE        BTM_OOB_NONE
@@ -1776,6 +1790,20 @@ extern void BTA_DmBlePasskeyReply(BD_ADDR bd_addr, BOOLEAN accept, UINT32 passke
 
 /*******************************************************************************
 **
+** Function         BTA_DmBleConfirmReply
+**
+** Description      Send BLE SMP SC user confirmation reply.
+**
+** Parameters:      bd_addr          - BD address of the peer
+**                  accept           - numbers to compare are the same or different.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTA_DmBleConfirmReply(BD_ADDR bd_addr, BOOLEAN accept);
+
+/*******************************************************************************
+**
 ** Function         BTA_DmAddBleDevice
 **
 ** Description      Add a BLE device.  This function will be normally called
@@ -1840,8 +1868,7 @@ extern void BTA_DmSetBlePrefConnParams(BD_ADDR bd_addr,
 ** Description      This function is called to set scan parameters used in
 **                  BLE connection request
 **
-** Parameters:      bd_addr          - BD address of the peripheral
-**                  scan_interval    - scan interval
+** Parameters:      scan_interval    - scan interval
 **                  scan_window      - scan window
 **
 ** Returns          void
index 297e2a9..f4bddd6 100644 (file)
@@ -109,6 +109,7 @@ typedef struct
     btif_dm_ble_lenc_keys_t   lenc_key;       /* local encryption reproduction keys LTK = = d1(ER,DIV,0)*/
     BOOLEAN                   is_lcsrk_key_rcvd;
     btif_dm_ble_lcsrk_keys_t  lcsrk_key;      /* local device CSRK = d1(ER,DIV,1)*/
+    BOOLEAN                   is_lidk_key_rcvd;   /* local identity key received */
 } btif_dm_ble_cb_t;
 
 #define BTIF_DM_LE_KEY_PENC        BTA_LE_KEY_PENC
index 8679e3c..2d1ffa6 100644 (file)
@@ -281,12 +281,14 @@ size_t btif_config_get_bin_length(const char *section, const char *key) {
 }
 
 bool btif_config_set_bin(const char *section, const char *key, const uint8_t *value, size_t length) {
-  static const char *lookup = "0123456789abcdef";
+  const char *lookup = "0123456789abcdef";
 
   assert(config != NULL);
   assert(section != NULL);
   assert(key != NULL);
-  assert(value != NULL);
+
+  if (length > 0)
+      assert(value != NULL);
 
   char *str = (char *)calloc(length * 2 + 1, 1);
   if (!str)
@@ -294,7 +296,7 @@ bool btif_config_set_bin(const char *section, const char *key, const uint8_t *va
 
   for (size_t i = 0; i < length; ++i) {
     str[(i * 2) + 0] = lookup[(value[i] >> 4) & 0x0F];
-    str[(i * 2) + 1] = lookup[(value[i] >> 0) & 0x0F];
+    str[(i * 2) + 1] = lookup[value[i] & 0x0F];
   }
 
   pthread_mutex_lock(&lock);
index 7a7ec01..2e687e1 100644 (file)
@@ -228,6 +228,7 @@ static btif_dm_local_key_cb_t ble_local_key_cb;
 static void btif_dm_ble_key_notif_evt(tBTA_DM_SP_KEY_NOTIF *p_ssp_key_notif);
 static void btif_dm_ble_auth_cmpl_evt (tBTA_DM_AUTH_CMPL *p_auth_cmpl);
 static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req);
+static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req) ;
 #endif
 
 static void bte_scan_filt_param_cfg_evt(UINT8 action_type,
@@ -1758,31 +1759,41 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
                 case BTA_LE_KEY_PENC:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PENC");
                     pairing_cb.ble.is_penc_key_rcvd = TRUE;
-                    memcpy(pairing_cb.ble.penc_key.ltk,p_data->ble_key.key_value.penc_key.ltk, 16);
-                    memcpy(pairing_cb.ble.penc_key.rand, p_data->ble_key.key_value.penc_key.rand,8);
-                    pairing_cb.ble.penc_key.ediv = p_data->ble_key.key_value.penc_key.ediv;
-                    pairing_cb.ble.penc_key.sec_level = p_data->ble_key.key_value.penc_key.sec_level;
+                    memcpy(pairing_cb.ble.penc_key.ltk,
+                           p_data->ble_key.p_key_value->penc_key.ltk, 16);
+                    memcpy(pairing_cb.ble.penc_key.rand,
+                           p_data->ble_key.p_key_value->penc_key.rand,8);
+                    pairing_cb.ble.penc_key.ediv = p_data->ble_key.p_key_value->penc_key.ediv;
+                    pairing_cb.ble.penc_key.sec_level =
+                           p_data->ble_key.p_key_value->penc_key.sec_level;
 
                     for (i=0; i<16; i++)
                     {
-                        BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",i,pairing_cb.ble.penc_key.ltk[i]);
+                        BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ltk[%d]=0x%02x",
+                                          i,pairing_cb.ble.penc_key.ltk[i]);
                     }
                     for (i=0; i<8; i++)
                     {
-                        BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.rand[%d]=0x%02x",i,pairing_cb.ble.penc_key.rand[i]);
+                        BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.rand[%d]=0x%02x",
+                                          i,pairing_cb.ble.penc_key.rand[i]);
                     }
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ediv=0x%04x",pairing_cb.ble.penc_key.ediv);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.sec_level=0x%02x",pairing_cb.ble.penc_key.sec_level);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.key_size=0x%02x",pairing_cb.ble.penc_key.key_size);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.ediv=0x%04x",
+                        pairing_cb.ble.penc_key.ediv);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.sec_level=0x%02x",
+                        pairing_cb.ble.penc_key.sec_level);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.penc_key.key_size=0x%02x",
+                        pairing_cb.ble.penc_key.key_size);
                     break;
 
                 case BTA_LE_KEY_PID:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PID");
                     pairing_cb.ble.is_pid_key_rcvd = TRUE;
-                    pairing_cb.ble.pid_key.addr_type = p_data->ble_key.key_value.pid_key.addr_type;
-                    memcpy(pairing_cb.ble.pid_key.irk, p_data->ble_key.key_value.pid_key.irk, 16);
+                    pairing_cb.ble.pid_key.addr_type =
+                           p_data->ble_key.p_key_value->pid_key.addr_type;
+                    memcpy(pairing_cb.ble.pid_key.irk,
+                           p_data->ble_key.p_key_value->pid_key.irk, 16);
                     memcpy(pairing_cb.ble.pid_key.static_addr,
-                            p_data->ble_key.key_value.pid_key.static_addr,BD_ADDR_LEN);
+                           p_data->ble_key.p_key_value->pid_key.static_addr,BD_ADDR_LEN);
                     for (i=0; i<16; i++)
                     {
                         BTIF_TRACE_DEBUG("pairing_cb.ble.pid_key.irk[%d]=0x%02x"
@@ -1798,28 +1809,39 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
                 case BTA_LE_KEY_PCSRK:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_PCSRK");
                     pairing_cb.ble.is_pcsrk_key_rcvd = TRUE;
-                    pairing_cb.ble.pcsrk_key.counter = p_data->ble_key.key_value.pcsrk_key.counter;
-                    pairing_cb.ble.pcsrk_key.sec_level = p_data->ble_key.key_value.pcsrk_key.sec_level;
-                    memcpy(pairing_cb.ble.pcsrk_key.csrk,p_data->ble_key.key_value.pcsrk_key.csrk,16);
+                    pairing_cb.ble.pcsrk_key.counter =
+                           p_data->ble_key.p_key_value->pcsrk_key.counter;
+                    pairing_cb.ble.pcsrk_key.sec_level =
+                           p_data->ble_key.p_key_value->pcsrk_key.sec_level;
+                    memcpy(pairing_cb.ble.pcsrk_key.csrk,
+                           p_data->ble_key.p_key_value->pcsrk_key.csrk,16);
 
                     for (i=0; i<16; i++)
                     {
-                        BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",i,pairing_cb.ble.pcsrk_key.csrk[i]);
+                        BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.csrk[%d]=0x%02x",
+                                          i,pairing_cb.ble.pcsrk_key.csrk[i]);
                     }
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.counter=0x%08x",pairing_cb.ble.pcsrk_key.counter);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",pairing_cb.ble.pcsrk_key.sec_level);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.counter=0x%08x",
+                                      pairing_cb.ble.pcsrk_key.counter);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.pcsrk_key.sec_level=0x%02x",
+                                      pairing_cb.ble.pcsrk_key.sec_level);
                     break;
 
                 case BTA_LE_KEY_LENC:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LENC");
                     pairing_cb.ble.is_lenc_key_rcvd = TRUE;
-                    pairing_cb.ble.lenc_key.div = p_data->ble_key.key_value.lenc_key.div;
-                    pairing_cb.ble.lenc_key.key_size = p_data->ble_key.key_value.lenc_key.key_size;
-                    pairing_cb.ble.lenc_key.sec_level = p_data->ble_key.key_value.lenc_key.sec_level;
-
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.div=0x%04x",pairing_cb.ble.lenc_key.div);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.key_size=0x%02x",pairing_cb.ble.lenc_key.key_size);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.sec_level=0x%02x",pairing_cb.ble.lenc_key.sec_level);
+                    pairing_cb.ble.lenc_key.div = p_data->ble_key.p_key_value->lenc_key.div;
+                    pairing_cb.ble.lenc_key.key_size =
+                           p_data->ble_key.p_key_value->lenc_key.key_size;
+                    pairing_cb.ble.lenc_key.sec_level =
+                           p_data->ble_key.p_key_value->lenc_key.sec_level;
+
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.div=0x%04x",
+                                      pairing_cb.ble.lenc_key.div);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.key_size=0x%02x",
+                                      pairing_cb.ble.lenc_key.key_size);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lenc_key.sec_level=0x%02x",
+                                      pairing_cb.ble.lenc_key.sec_level);
                     break;
 
 
@@ -1827,14 +1849,25 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
                 case BTA_LE_KEY_LCSRK:
                     BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LCSRK");
                     pairing_cb.ble.is_lcsrk_key_rcvd = TRUE;
-                    pairing_cb.ble.lcsrk_key.counter = p_data->ble_key.key_value.lcsrk_key.counter;
-                    pairing_cb.ble.lcsrk_key.div = p_data->ble_key.key_value.lcsrk_key.div;
-                    pairing_cb.ble.lcsrk_key.sec_level = p_data->ble_key.key_value.lcsrk_key.sec_level;
+                    pairing_cb.ble.lcsrk_key.counter =
+                        p_data->ble_key.p_key_value->lcsrk_key.counter;
+                    pairing_cb.ble.lcsrk_key.div =
+                        p_data->ble_key.p_key_value->lcsrk_key.div;
+                    pairing_cb.ble.lcsrk_key.sec_level =
+                        p_data->ble_key.p_key_value->lcsrk_key.sec_level;
+
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.div=0x%04x",
+                        pairing_cb.ble.lcsrk_key.div);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.counter=0x%08x",
+                        pairing_cb.ble.lcsrk_key.counter);
+                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",
+                        pairing_cb.ble.lcsrk_key.sec_level);
 
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.div=0x%04x",pairing_cb.ble.lcsrk_key.div);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.counter=0x%08x",pairing_cb.ble.lcsrk_key.counter);
-                    BTIF_TRACE_DEBUG("pairing_cb.ble.lcsrk_key.sec_level=0x%02x",pairing_cb.ble.lcsrk_key.sec_level);
+                    break;
 
+                case BTA_LE_KEY_LID:
+                    BTIF_TRACE_DEBUG("Rcv BTA_LE_KEY_LID");
+                    pairing_cb.ble.is_lidk_key_rcvd =  TRUE;
                     break;
 
                 default:
@@ -1855,15 +1888,22 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
             BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
             btif_dm_ble_passkey_req_evt(&p_data->pin_req);
             break;
+        case BTA_DM_BLE_NC_REQ_EVT:
+            BTIF_TRACE_DEBUG("BTA_DM_BLE_PASSKEY_REQ_EVT. ");
+            btif_dm_ble_key_nc_req_evt(&p_data->key_notif);
+            break;
         case BTA_DM_BLE_OOB_REQ_EVT:
             BTIF_TRACE_DEBUG("BTA_DM_BLE_OOB_REQ_EVT. ");
             break;
         case BTA_DM_BLE_LOCAL_IR_EVT:
             BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
             ble_local_key_cb.is_id_keys_rcvd = TRUE;
-            memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
-            memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
-            memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
+            memcpy(&ble_local_key_cb.id_keys.irk[0],
+                   &p_data->ble_id_keys.irk[0], sizeof(BT_OCTET16));
+            memcpy(&ble_local_key_cb.id_keys.ir[0],
+                   &p_data->ble_id_keys.ir[0], sizeof(BT_OCTET16));
+            memcpy(&ble_local_key_cb.id_keys.dhk[0],
+                   &p_data->ble_id_keys.dhk[0], sizeof(BT_OCTET16));
             btif_storage_add_ble_local_key( (char *)&ble_local_key_cb.id_keys.irk[0],
                                             BTIF_DM_LE_LOCAL_KEY_IR,
                                             BT_OCTET16_LEN);
@@ -1884,7 +1924,7 @@ static void btif_dm_upstreams_evt(UINT16 event, char* p_param)
             break;
 
         case BTA_DM_BLE_AUTH_CMPL_EVT:
-            BTIF_TRACE_DEBUG("BTA_DM_BLE_KEY_EVT. ");
+            BTIF_TRACE_DEBUG("BTA_DM_BLE_AUTH_CMPL_EVT. ");
             btif_dm_ble_auth_cmpl_evt(&p_data->auth_cmpl);
             break;
 
@@ -2982,6 +3022,14 @@ void btif_dm_save_ble_bonding_keys(void)
                                          sizeof(btif_dm_ble_lcsrk_keys_t));
     }
 
+    if (pairing_cb.ble.is_lidk_key_rcvd)
+    {
+        btif_storage_add_ble_bonding_key(&bd_addr,
+                                         NULL,
+                                         BTIF_DM_LE_KEY_LID,
+                                         0);
+    }
+
 }
 
 
@@ -3080,7 +3128,28 @@ static void btif_dm_ble_passkey_req_evt(tBTA_DM_PIN_REQ *p_pin_req)
     HAL_CBACK(bt_hal_cbacks, pin_request_cb,
               &bd_addr, &bd_name, cod);
 }
+static void btif_dm_ble_key_nc_req_evt(tBTA_DM_SP_KEY_NOTIF *p_notif_req)
+{
+    /* TODO implement key notification for numeric comparison */
+    BTIF_TRACE_DEBUG("%s", __FUNCTION__);
 
+    /* Remote name update */
+    btif_update_remote_properties(p_notif_req->bd_addr , p_notif_req->bd_name,
+                                          NULL, BT_DEVICE_TYPE_BLE);
+
+    bt_bdaddr_t bd_addr;
+    bdcpy(bd_addr.address, p_notif_req->bd_addr);
+
+    bt_bdname_t bd_name;
+    memcpy(bd_name.name, p_notif_req->bd_name, BD_NAME_LEN);
+
+    bond_state_changed(BT_STATUS_SUCCESS, &bd_addr, BT_BOND_STATE_BONDING);
+    pairing_cb.is_ssp = FALSE;
+
+    HAL_CBACK(bt_hal_cbacks, ssp_request_cb, &bd_addr, &bd_name,
+              COD_UNCLASSIFIED, BT_SSP_VARIANT_PASSKEY_CONFIRMATION,
+              p_notif_req->passkey);
+}
 
 void btif_dm_update_ble_remote_properties( BD_ADDR bd_addr, BD_NAME bd_name,
                                            tBT_DEVICE_TYPE dev_type)
index 56b8f5a..63508a9 100644 (file)
@@ -970,6 +970,9 @@ bt_status_t btif_storage_add_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
         case BTIF_DM_LE_KEY_LCSRK:
             name = "LE_KEY_LCSRK";
             break;
+        case BTIF_DM_LE_KEY_LID:
+            name = "LE_KEY_LID";
+            break;
         default:
             return BT_STATUS_FAIL;
     }
@@ -1013,6 +1016,8 @@ bt_status_t btif_storage_get_ble_bonding_key(bt_bdaddr_t *remote_bd_addr,
         case BTIF_DM_LE_KEY_LCSRK:
             name = "LE_KEY_LCSRK";
             break;
+        case BTIF_DM_LE_KEY_LID:
+            name =  "LE_KEY_LID";
         default:
             return BT_STATUS_FAIL;
     }
@@ -1236,6 +1241,28 @@ bt_status_t btif_in_fetch_bonded_ble_device(const char *remote_bd_addr,int add,
                 key_found = TRUE;
             }
 
+            if (btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_LID, buf,
+                                    sizeof(btif_dm_ble_pid_keys_t))== BT_STATUS_SUCCESS)
+            {
+                if(add)
+                {
+                    if (!is_device_added)
+                    {
+                        BTA_DmAddBleDevice(bta_bd_addr, addr_type, BT_DEVICE_TYPE_BLE);
+                        is_device_added = TRUE;
+                    }
+                    p = (tBTA_LE_KEY_VALUE *)buf;
+                    for (i=0; i<BD_ADDR_LEN; i++)
+                    {
+                        BTIF_TRACE_DEBUG("p->pid_key.static_addr[%d]=%02x"
+                                            ,i,p->pid_key.static_addr[i]);
+                    }
+
+                    BTA_DmAddBleKey (bta_bd_addr, (tBTA_LE_KEY_VALUE *)buf, BTIF_DM_LE_KEY_LID);
+                }
+                key_found = TRUE;
+            }
+
             memset(buf, 0, sizeof(buf));
             if (btif_storage_get_ble_bonding_key(&bd_addr,
                                                  BTIF_DM_LE_KEY_PCSRK,
index 2ef2332..af93e47 100644 (file)
@@ -42,6 +42,7 @@ typedef struct controller_t {
   const uint8_t *(*get_ble_supported_states)(void);
 
   bool (*supports_simple_pairing)(void);
+  bool (*supports_secure_connections)(void);
   bool (*supports_simultaneous_le_bredr)(void);
   bool (*supports_reading_remote_extended_features)(void);
   bool (*supports_interlaced_inquiry_scan)(void);
@@ -51,6 +52,7 @@ typedef struct controller_t {
 
   bool (*supports_ble)(void);
   bool (*supports_ble_connection_parameters_request)(void);
+  bool (*supports_ble_privacy)(void);
 
   // Get the cached acl data sizes for the controller.
   uint16_t (*get_acl_data_size_classic)(void);
@@ -65,6 +67,9 @@ typedef struct controller_t {
   // Get the number of acl packets the controller can buffer.
   uint16_t (*get_acl_buffer_count_classic)(void);
   uint8_t (*get_acl_buffer_count_ble)(void);
+
+  uint8_t (*get_ble_resolving_list_max_size)(void);
+  void (*set_ble_resolving_list_max_size)(int resolving_list_max_size);
 } controller_t;
 
 const controller_t *controller_get_interface();
index c1eadc0..6537cf1 100644 (file)
@@ -66,12 +66,14 @@ static uint16_t acl_buffer_count_classic;
 static uint8_t acl_buffer_count_ble;
 
 static uint8_t ble_white_list_size;
+static uint8_t ble_resolving_list_max_size;
 static uint8_t ble_supported_states[BLE_SUPPORTED_STATES_SIZE];
 static bt_device_features_t features_ble;
 
 static bool readable;
 static bool ble_supported;
 static bool simple_pairing_supported;
+static bool secure_connections_supported;
 
 #define AWAIT_COMMAND(command) future_await(hci->transmit_command_futured(command))
 
@@ -143,6 +145,12 @@ static future_t *start_up(void) {
     packet_parser->parse_generic_command_complete(response);
   }
 
+  secure_connections_supported = HCI_SC_CTRLR_SUPPORTED(features_classic[2].as_array);
+  if (secure_connections_supported) {
+    response = AWAIT_COMMAND(packet_factory->make_write_secure_connections_host_support(HCI_SC_MODE_ENABLED));
+    packet_parser->parse_generic_command_complete(response);
+  }
+
 #if (BLE_INCLUDED == TRUE)
   if (HCI_LE_SPT_SUPPORTED(features_classic[0].as_array)) {
     uint8_t simultaneous_le_host = HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array) ? BTM_BLE_SIMULTANEOUS_HOST : 0;
@@ -204,6 +212,13 @@ static future_t *start_up(void) {
       &features_ble
     );
 
+    if (HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array)) {
+        response = AWAIT_COMMAND(packet_factory->make_ble_read_resolving_list_size());
+        packet_parser->parse_ble_read_resolving_list_size_response(
+            response,
+            &ble_resolving_list_max_size);
+    }
+
     // Set the ble event mask next
     response = AWAIT_COMMAND(packet_factory->make_ble_set_event_mask(&BLE_EVENT_MASK));
     packet_parser->parse_generic_command_complete(response);
@@ -281,6 +296,11 @@ static bool supports_simple_pairing(void) {
   return simple_pairing_supported;
 }
 
+static bool supports_secure_connections(void) {
+  assert(readable);
+  return secure_connections_supported;
+}
+
 static bool supports_simultaneous_le_bredr(void) {
   assert(readable);
   return HCI_SIMUL_LE_BREDR_SUPPORTED(features_classic[0].as_array);
@@ -316,6 +336,12 @@ static bool supports_ble(void) {
   return ble_supported;
 }
 
+static bool supports_ble_privacy(void) {
+  assert(readable);
+  assert(ble_supported);
+  return HCI_LE_ENHANCED_PRIVACY_SUPPORTED(features_ble.as_array);
+}
+
 static bool supports_ble_connection_parameters_request(void) {
   assert(readable);
   assert(ble_supported);
@@ -354,6 +380,18 @@ static uint8_t get_acl_buffer_count_ble(void) {
   return acl_buffer_count_ble;
 }
 
+static uint8_t get_ble_resolving_list_max_size(void) {
+  assert(readable);
+  assert(ble_supported);
+  return ble_resolving_list_max_size;
+}
+
+static void set_ble_resolving_list_max_size(int resolving_list_max_size) {
+  assert(readable);
+  assert(ble_supported);
+  ble_resolving_list_max_size = resolving_list_max_size;
+}
+
 static const controller_t interface = {
   get_is_ready,
 
@@ -367,6 +405,7 @@ static const controller_t interface = {
   get_ble_supported_states,
 
   supports_simple_pairing,
+  supports_secure_connections,
   supports_simultaneous_le_bredr,
   supports_reading_remote_extended_features,
   supports_interlaced_inquiry_scan,
@@ -376,6 +415,7 @@ static const controller_t interface = {
 
   supports_ble,
   supports_ble_connection_parameters_request,
+  supports_ble_privacy,
 
   get_acl_data_size_classic,
   get_acl_data_size_ble,
@@ -384,7 +424,10 @@ static const controller_t interface = {
   get_acl_packet_size_ble,
 
   get_acl_buffer_count_classic,
-  get_acl_buffer_count_ble
+  get_acl_buffer_count_ble,
+
+  get_ble_resolving_list_max_size,
+  set_ble_resolving_list_max_size
 };
 
 const controller_t *controller_get_interface() {
index b5e207c..5a50b51 100644 (file)
@@ -30,12 +30,14 @@ typedef struct {
   BT_HDR *(*make_read_local_supported_commands)(void);
   BT_HDR *(*make_read_local_extended_features)(uint8_t page_number);
   BT_HDR *(*make_write_simple_pairing_mode)(uint8_t mode);
+  BT_HDR *(*make_write_secure_connections_host_support)(uint8_t mode);
   BT_HDR *(*make_set_event_mask)(const bt_event_mask_t *event_mask);
   BT_HDR *(*make_ble_write_host_support)(uint8_t supported_host, uint8_t simultaneous_host);
   BT_HDR *(*make_ble_read_white_list_size)(void);
   BT_HDR *(*make_ble_read_buffer_size)(void);
   BT_HDR *(*make_ble_read_supported_states)(void);
   BT_HDR *(*make_ble_read_local_supported_features)(void);
+  BT_HDR *(*make_ble_read_resolving_list_size)(void);
   BT_HDR *(*make_ble_set_event_mask)(const bt_event_mask_t *event_mask);
 } hci_packet_factory_t;
 
index 219a424..45b934a 100644 (file)
@@ -81,6 +81,12 @@ typedef struct {
     BT_HDR *response,
     bt_device_features_t *supported_features
   );
+
+  void (*parse_ble_read_resolving_list_size_response) (
+    BT_HDR *response,
+    uint8_t *resolving_list_size_ptr
+  );
+
 } hci_packet_parser_t;
 
 const hci_packet_parser_t *hci_packet_parser_get_interface();
index 032823d..89b82d1 100644 (file)
@@ -85,6 +85,15 @@ static BT_HDR *make_write_simple_pairing_mode(uint8_t mode) {
   return packet;
 }
 
+static BT_HDR *make_write_secure_connections_host_support(uint8_t mode) {
+  uint8_t *stream;
+  const uint8_t parameter_size = 1;
+  BT_HDR *packet = make_command(HCI_WRITE_SECURE_CONNS_SUPPORT, parameter_size, &stream);
+
+  UINT8_TO_STREAM(stream, mode);
+  return packet;
+}
+
 static BT_HDR *make_set_event_mask(const bt_event_mask_t *event_mask) {
   uint8_t *stream;
   uint8_t parameter_size = sizeof(bt_event_mask_t);
@@ -120,6 +129,10 @@ static BT_HDR *make_ble_read_local_supported_features(void) {
   return make_command_no_params(HCI_BLE_READ_LOCAL_SPT_FEAT);
 }
 
+static BT_HDR *make_ble_read_resolving_list_size(void) {
+  return make_command_no_params(HCI_BLE_READ_RESOLVING_LIST_SIZE);
+}
+
 static BT_HDR *make_ble_set_event_mask(const bt_event_mask_t *event_mask) {
   uint8_t *stream;
   uint8_t parameter_size = sizeof(bt_event_mask_t);
@@ -167,12 +180,14 @@ static const hci_packet_factory_t interface = {
   make_read_local_supported_commands,
   make_read_local_extended_features,
   make_write_simple_pairing_mode,
+  make_write_secure_connections_host_support,
   make_set_event_mask,
   make_ble_write_host_support,
   make_ble_read_white_list_size,
   make_ble_read_buffer_size,
   make_ble_read_supported_states,
   make_ble_read_local_supported_features,
+  make_ble_read_resolving_list_size,
   make_ble_set_event_mask
 };
 
index 0af9b70..6ff3c3d 100644 (file)
@@ -147,6 +147,16 @@ static void parse_ble_read_local_supported_features_response(
   buffer_allocator->free(response);
 }
 
+static void parse_ble_read_resolving_list_size_response(
+    BT_HDR *response,
+    uint8_t *resolving_list_size_ptr) {
+
+  uint8_t *stream = read_command_complete_header(response, HCI_BLE_READ_RESOLVING_LIST_SIZE, 1 /* bytes after */);
+  STREAM_TO_UINT8(*resolving_list_size_ptr, stream);
+
+  buffer_allocator->free(response);
+}
+
 // Internal functions
 
 static uint8_t *read_command_complete_header(
@@ -197,7 +207,8 @@ static const hci_packet_parser_t interface = {
   parse_ble_read_white_list_size_response,
   parse_ble_read_buffer_size_response,
   parse_ble_read_supported_states_response,
-  parse_ble_read_local_supported_features_response
+  parse_ble_read_local_supported_features_response,
+  parse_ble_read_resolving_list_size_response
 };
 
 const hci_packet_parser_t *hci_packet_parser_get_interface() {
index bf49ac3..b255073 100644 (file)
 
 /* First fixed channel supported */
 #ifndef L2CAP_FIRST_FIXED_CHNL
-#define L2CAP_FIRST_FIXED_CHNL              3
+#define L2CAP_FIRST_FIXED_CHNL              4
 #endif
 
 #ifndef L2CAP_LAST_FIXED_CHNL
 #define SMP_MIN_ENC_KEY_SIZE    7
 #endif
 
-/* Used for conformance testing ONLY */
-#ifndef SMP_CONFORMANCE_TESTING
-#define SMP_CONFORMANCE_TESTING           FALSE
+/* minimum link timeout after SMP pairing is done, leave room for key exchange
+   and racing condition for the following service connection.
+   Prefer greater than 0 second, and no less than default inactivity link idle
+   timer(L2CAP_LINK_INACTIVITY_TOUT) in l2cap) */
+#ifndef SMP_LINK_TOUT_MIN
+#if (L2CAP_LINK_INACTIVITY_TOUT > 0)
+#define SMP_LINK_TOUT_MIN               L2CAP_LINK_INACTIVITY_TOUT
+#else
+#define SMP_LINK_TOUT_MIN               2
+#endif
 #endif
-
 /******************************************************************************
 **
 ** SDP
index 22f013f..10eb446 100644 (file)
@@ -74,6 +74,7 @@ LOCAL_SRC_FILES:= \
     ./btm/btm_ble_multi_adv.c \
     ./btm/btm_ble_batchscan.c \
     ./btm/btm_ble_cont_energy.c \
+    ./btm/btm_ble_privacy.c \
     ./btm/btm_acl.c \
     ./btm/btm_sco.c \
     ./btm/btm_pm.c \
@@ -116,6 +117,10 @@ LOCAL_SRC_FILES:= \
     ./smp/smp_keys.c \
     ./smp/smp_api.c \
     ./smp/aes.c \
+    ./smp/smp_br_main.c\
+    ./smp/p_256_curvepara.c \
+    ./smp/p_256_ecc_pp.c \
+    ./smp/p_256_multprecision.c \
     ./avdt/avdt_ccb.c \
     ./avdt/avdt_scb_act.c \
     ./avdt/avdt_msg.c \
@@ -154,8 +159,7 @@ LOCAL_SRC_FILES:= \
     ./gap/gap_api.c \
     ./gap/gap_ble.c \
     ./gap/gap_conn.c \
-    ./gap/gap_utils.c \
-    ../vnd/ble/vendor_ble.c
+    ./gap/gap_utils.c
 
 LOCAL_MODULE := libbt-brcm_stack
 LOCAL_MODULE_TAGS := optional
index 0b7204b..b47564f 100644 (file)
@@ -234,30 +234,20 @@ void btm_acl_created (BD_ADDR bda, DEV_CLASS dc, BD_NAME bdn,
             p->hci_handle        = hci_handle;
             p->link_role         = link_role;
             p->link_up_issued    = FALSE;
+            memcpy (p->remote_addr, bda, BD_ADDR_LEN);
 
 #if BLE_INCLUDED == TRUE
             p->transport = transport;
-            if (transport == BT_TRANSPORT_LE)
-            {
 #if BLE_PRIVACY_SPT == TRUE
-                if (btm_cb.ble_ctr_cb.privacy)
-                {
-                    p->conn_addr_type = btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type;
-                    memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
-                }
-                else
+            if (transport == BT_TRANSPORT_LE)
+                btm_ble_refresh_local_resolvable_private_addr(bda,
+                                                    btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr);
 #endif
-                {
-                    p->conn_addr_type = BLE_ADDR_PUBLIC;
-                    memcpy(p->conn_addr, controller_get_interface()->get_address()->address, BD_ADDR_LEN);
-                }
-            }
 #endif
             p->switch_role_state = BTM_ACL_SWKEY_STATE_IDLE;
 
             btm_pm_sm_alloc(xx);
 
-            memcpy (p->remote_addr, bda, BD_ADDR_LEN);
 
             if (dc)
                 memcpy (p->remote_dc, dc, DEV_CLASS_LEN);
index ec09a99..eaaa115 100644 (file)
 #include "l2c_int.h"
 #include "gap_api.h"
 #include "bt_utils.h"
-
-#include "vendor_ble.h"
+#include "device/include/controller.h"
 #define LOG_TAG "bt_btm_ble"
 #include "osi/include/log.h"
 
 #if SMP_INCLUDED == TRUE
-extern BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length, UINT16 tlen, UINT8 *p_signature);
+extern BOOLEAN aes_cipher_msg_auth_code(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
@@ -166,7 +166,7 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_
     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_LCSRK))
+         key_type != BTM_LE_KEY_LCSRK && key_type != BTM_LE_KEY_LID))
     {
         BTM_TRACE_WARNING ("BTM_SecAddBleKey()  Wrong Type, or No Device record \
                         for bdaddr: %08x%04x, Type: %d",
@@ -179,12 +179,12 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_
                       (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
                       (bd_addr[4]<<8)+bd_addr[5], key_type);
 
-    if (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_LCSRK)
-    {
-        btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE);
-    }
+    btm_sec_save_le_key (bd_addr, key_type, p_le_key, FALSE);
+
+#if (BLE_PRIVACY_SPT == TRUE)
+    if (key_type == BTM_LE_KEY_PID || key_type == BTM_LE_KEY_LID)
+        btm_ble_resolving_list_load_dev (p_dev_rec);
+#endif
 
 #endif
 
@@ -207,7 +207,7 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_
 void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
 {
     tBTM_DEVCB *p_devcb = &btm_cb.devcb;
-    BTM_TRACE_DEBUG ("BTM_BleLoadLocalKeys");
+    BTM_TRACE_DEBUG ("%s", __func__);
     if (p_key != NULL)
     {
         switch (key_type)
@@ -217,7 +217,7 @@ void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
                 break;
 
             case BTM_BLE_KEY_TYPE_ER:
-                memcpy(p_devcb->er, p_key->er, sizeof(BT_OCTET16));
+                memcpy(p_devcb->ble_encryption_key_value, p_key->er, sizeof(BT_OCTET16));
                 break;
 
             default:
@@ -235,14 +235,13 @@ void BTM_BleLoadLocalKeys(UINT8 key_type, tBTM_BLE_LOCAL_KEYS *p_key)
 **                  root.
 **
 ** Returns          void
-**                  the local device ER is copied into er
+**                  the local device ER is copied into ble_encr_key_value
 **
 *******************************************************************************/
-void BTM_GetDeviceEncRoot (BT_OCTET16 er)
+void BTM_GetDeviceEncRoot (BT_OCTET16 ble_encr_key_value)
 {
-    BTM_TRACE_DEBUG ("BTM_GetDeviceEncRoot");
-
-    memcpy (er, btm_cb.devcb.er, BT_OCTET16_LEN);
+    BTM_TRACE_DEBUG ("%s", __func__);
+    memcpy (ble_encr_key_value, btm_cb.devcb.ble_encryption_key_value, BT_OCTET16_LEN);
 }
 
 /*******************************************************************************
@@ -424,7 +423,7 @@ void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
         return;
     }
 
-    p_dev_rec->sec_flags   |= BTM_SEC_LE_LINK_KEY_AUTHED;
+    p_dev_rec->sec_flags   |= BTM_SEC_LE_AUTHENTICATED;
     BTM_TRACE_DEBUG ("BTM_BlePasskeyReply");
     SMP_PasskeyReply(bd_addr, res_smp, passkey);
 #endif
@@ -432,6 +431,34 @@ void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
 
 /*******************************************************************************
 **
+** Function         BTM_BleConfirmReply
+**
+** Description      This function is called after Security Manager submitted
+**                  numeric comparison request to the application.
+**
+** Parameters:      bd_addr      - Address of the device with which numeric
+**                                 comparison was requested
+**                  res          - comparison result BTM_SUCCESS if success
+**
+*******************************************************************************/
+void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res)
+{
+    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_ERROR("Passkey reply to Unknown device");
+        return;
+    }
+
+    p_dev_rec->sec_flags   |= BTM_SEC_LE_AUTHENTICATED;
+    BTM_TRACE_DEBUG ("%s", __func__);
+    SMP_ConfirmReply(bd_addr, res_smp);
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_BleOobDataReply
 **
 ** Description      This function is called to provide the OOB data for
@@ -456,7 +483,7 @@ void BTM_BleOobDataReply(BD_ADDR bd_addr, UINT8 res, UINT8 len, UINT8 *p_data)
         return;
     }
 
-    p_dev_rec->sec_flags |= BTM_SEC_LE_LINK_KEY_AUTHED;
+    p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
     SMP_OobDataReply(bd_addr, res_smp, len, p_data);
 #endif
 }
@@ -482,8 +509,6 @@ void BTM_BleSetConnScanParams (UINT16 scan_interval, UINT16 scan_window)
     if (BTM_BLE_VALID_PRAM(scan_interval, BTM_BLE_SCAN_INT_MIN, BTM_BLE_SCAN_INT_MAX) &&
         BTM_BLE_VALID_PRAM(scan_window, BTM_BLE_SCAN_WIN_MIN, BTM_BLE_SCAN_WIN_MAX))
     {
-        btu_stop_timer(&p_ble_cb->scan_param_idle_timer);
-
         if (p_ble_cb->scan_int != scan_interval)
         {
             p_ble_cb->scan_int = scan_interval;
@@ -890,12 +915,12 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
                      bd_addr[2],bd_addr[3],
                      bd_addr[4],bd_addr[5]);
 
-    if ((p_rec = btm_find_dev (bd_addr)) != NULL && p_keys)
+    if ((p_rec = btm_find_dev (bd_addr)) != NULL && (p_keys || key_type== BTM_LE_KEY_LID))
     {
         switch (key_type)
         {
             case BTM_LE_KEY_PENC:
-                memcpy(p_rec->ble.keys.ltk, p_keys->penc_key.ltk, BT_OCTET16_LEN);
+                memcpy(p_rec->ble.keys.pltk, p_keys->penc_key.ltk, BT_OCTET16_LEN);
                 memcpy(p_rec->ble.keys.rand, p_keys->penc_key.rand, BT_OCTET8_LEN);
                 p_rec->ble.keys.sec_level = p_keys->penc_key.sec_level;
                 p_rec->ble.keys.ediv = p_keys->penc_key.ediv;
@@ -926,7 +951,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
                 break;
 
             case BTM_LE_KEY_PCSRK:
-                memcpy(p_rec->ble.keys.csrk, p_keys->pcsrk_key.csrk, BT_OCTET16_LEN);
+                memcpy(p_rec->ble.keys.pcsrk, p_keys->pcsrk_key.csrk, BT_OCTET16_LEN);
                 p_rec->ble.keys.srk_sec_level = p_keys->pcsrk_key.sec_level;
                 p_rec->ble.keys.counter  = p_keys->pcsrk_key.counter;
                 p_rec->ble.key_type |= BTM_LE_KEY_PCSRK;
@@ -944,6 +969,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
                 break;
 
             case BTM_LE_KEY_LENC:
+                memcpy(p_rec->ble.keys.lltk, p_keys->lenc_key.ltk, BT_OCTET16_LEN);
                 p_rec->ble.keys.div = p_keys->lenc_key.div; /* update DIV */
                 p_rec->ble.keys.sec_level = p_keys->lenc_key.sec_level;
                 p_rec->ble.keys.key_size = p_keys->lenc_key.key_size;
@@ -957,6 +983,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
                 break;
 
             case BTM_LE_KEY_LCSRK:/* local CSRK has been delivered */
+                memcpy (p_rec->ble.keys.lcsrk, p_keys->lcsrk_key.csrk, BT_OCTET16_LEN);
                 p_rec->ble.keys.div = p_keys->lcsrk_key.div; /* update DIV */
                 p_rec->ble.keys.local_csrk_sec_level = p_keys->lcsrk_key.sec_level;
                 p_rec->ble.keys.local_counter  = p_keys->lcsrk_key.counter;
@@ -968,6 +995,9 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
                                  p_rec->ble.keys.local_counter );
                 break;
 
+            case BTM_LE_KEY_LID:
+               p_rec->ble.key_type |= BTM_LE_KEY_LID;
+               break;
             default:
                 BTM_TRACE_WARNING("btm_sec_save_le_key (Bad key_type 0x%02x)", key_type);
                 return;
@@ -983,6 +1013,7 @@ void btm_sec_save_le_key(BD_ADDR bd_addr, tBTM_LE_KEY_TYPE key_type, tBTM_LE_KEY
         {
             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;
@@ -1071,8 +1102,7 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE
     else
     {
         req_sec_level = BTM_LE_SEC_UNAUTHENTICATE;
-        if ((auth_req == (BTM_LE_AUTH_REQ_BOND|BTM_LE_AUTH_REQ_MITM)) ||
-            (auth_req == (BTM_LE_AUTH_REQ_MITM)) )
+        if (auth_req & BTM_LE_AUTH_REQ_MITM)
         {
             req_sec_level = BTM_LE_SEC_AUTHENTICATED;
         }
@@ -1082,7 +1112,7 @@ void btm_ble_link_sec_check(BD_ADDR bd_addr, tBTM_LE_AUTH_REQ auth_req, tBTM_BLE
         /* currently encrpted  */
         if (p_dev_rec->sec_flags & BTM_SEC_LE_ENCRYPTED)
         {
-            if (p_dev_rec->sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+            if (p_dev_rec->sec_flags & BTM_SEC_LE_AUTHENTICATED)
                 cur_sec_level = BTM_LE_SEC_AUTHENTICATED;
             else
                 cur_sec_level = BTM_LE_SEC_UNAUTHENTICATE;
@@ -1132,6 +1162,8 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
     tBTM_STATUS         cmd = BTM_NO_RESOURCES;
     tBTM_BLE_SEC_ACT    sec_act = *(tBTM_BLE_SEC_ACT *)p_ref_data ;
     tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bd_addr);
+    tBTM_BLE_SEC_REQ_ACT sec_req_act;
+    tBTM_LE_AUTH_REQ    auth_req;
 
     if (p_rec == NULL)
     {
@@ -1151,24 +1183,26 @@ tBTM_STATUS btm_ble_set_encryption (BD_ADDR bd_addr, void *p_ref_data, UINT8 lin
         case BTM_BLE_SEC_ENCRYPT:
             if (link_role == BTM_ROLE_MASTER)
             {
-                if(p_rec->sec_state == BTM_SEC_STATE_ENCRYPTING) {
-                    BTM_TRACE_DEBUG ("State is already encrypting::");
-                    cmd = BTM_CMD_STARTED;
-                }
-                else {
                     /* start link layer encryption using the security info stored */
-                    if (btm_ble_start_encrypt(bd_addr, FALSE, NULL))
-                    {
-                        p_rec->sec_state = BTM_SEC_STATE_ENCRYPTING;
-                        cmd = BTM_CMD_STARTED;
-                    }
-                }
+                cmd = btm_ble_start_encrypt(bd_addr, FALSE, NULL);
                 break;
             }
             /* if salve role then fall through to call SMP_Pair below which will send a
                sec_request to request the master to encrypt the link */
         case BTM_BLE_SEC_ENCRYPT_NO_MITM:
         case BTM_BLE_SEC_ENCRYPT_MITM:
+            if (link_role == BTM_ROLE_MASTER)
+            {
+                auth_req = (sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
+                           ? SMP_AUTH_GEN_BOND : (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT);
+                btm_ble_link_sec_check (bd_addr, auth_req, &sec_req_act);
+
+                if (sec_req_act == BTM_BLE_SEC_REQ_ACT_ENCRYPT)
+                {
+                   cmd = btm_ble_start_encrypt(bd_addr, FALSE, NULL);
+                   break;
+                }
+            }
 
             if (SMP_Pair(bd_addr) == SMP_STARTED)
             {
@@ -1256,7 +1290,7 @@ tBTM_STATUS btm_ble_start_encrypt(BD_ADDR bda, BOOLEAN use_stk, BT_OCTET16 stk)
     else if (p_rec->ble.key_type & BTM_LE_KEY_PENC)
     {
         if (btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, p_rec->ble.keys.rand,
-                                      p_rec->ble.keys.ediv, p_rec->ble.keys.ltk))
+                                     p_rec->ble.keys.ediv, p_rec->ble.keys.pltk))
             rt = BTM_CMD_STARTED;
     }
     else
@@ -1357,7 +1391,7 @@ static void btm_enc_proc_slave_y(tSMP_ENC *p)
         {
             BTM_TRACE_DEBUG ("LTK request OK");
             /* calculating LTK , LTK = E er(div) */
-            SMP_Encrypt(p_cb->devcb.er, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
+            SMP_Encrypt(p_cb->devcb.ble_encryption_key_value, BT_OCTET16_LEN, (UINT8 *)&div, 2, &output);
             btm_enc_proc_ltk(&output);
         }
         else
@@ -1404,10 +1438,10 @@ void btm_ble_ltk_request_reply(BD_ADDR bda,  BOOLEAN use_stk, BT_OCTET16 stk)
     }
     else /* calculate LTK using peer device  */
     {
-        /* generate Y= Encrypt(DHK, Rand) received from encrypt request  */
-        SMP_Encrypt(p_cb->devcb.id_keys.dhk, BT_OCTET16_LEN, p_cb->enc_rand,
-                    BT_OCTET8_LEN, &output);
-        btm_enc_proc_slave_y(&output);
+        if (p_rec->ble.key_type & BTM_LE_KEY_LENC)
+            btsnd_hcic_ble_ltk_req_reply(btm_cb.enc_handle, p_rec->ble.keys.lltk);
+        else
+            btsnd_hcic_ble_ltk_req_neg_reply(btm_cb.enc_handle);
     }
 }
 
@@ -1480,12 +1514,48 @@ UINT8 btm_ble_io_capabilities_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p
         if ((p_data->io_cap == BTM_IO_CAP_NONE) && p_data->oob_data == SMP_OOB_NONE)
             p_data->auth_req &= ~BTM_LE_AUTH_REQ_MITM;
 
-        BTM_TRACE_DEBUG ("btm_ble_io_capabilities_req 6: IO_CAP:%d oob_data:%d auth_req:%d",
+        if (!(p_data->auth_req & SMP_SC_SUPPORT_BIT))
+        {
+            /* if Secure Connections are not supported then remove LK derivation,
+            ** and keypress notifications.
+            */
+            BTM_TRACE_DEBUG("%s-SC not supported -> No LK derivation, no keypress notifications",
+                            __func__);
+            p_data->auth_req &= ~SMP_KP_SUPPORT_BIT;
+            p_data->init_keys &= ~SMP_SEC_KEY_TYPE_LK;
+            p_data->resp_keys &= ~SMP_SEC_KEY_TYPE_LK;
+        }
+
+        BTM_TRACE_DEBUG ("btm_ble_io_capabilities_req 6: IO_CAP:%d oob_data:%d auth_req:0x%02x",
                           p_data->io_cap, p_data->oob_data, p_data->auth_req);
     }
     return callback_rc;
 }
 
+/*******************************************************************************
+**
+** Function         btm_ble_br_keys_req
+**
+** Description      This function is called to handle SMP request for keys sent
+**                  over BR/EDR.
+**
+** Returns          void
+**
+*******************************************************************************/
+UINT8 btm_ble_br_keys_req(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_LE_IO_REQ *p_data)
+{
+    UINT8           callback_rc = BTM_SUCCESS;
+    BTM_TRACE_DEBUG ("%s", __func__);
+    if (btm_cb.api.p_le_callback)
+    {
+        /* the callback function implementation may change the IO capability... */
+        callback_rc = (*btm_cb.api.p_le_callback) (BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr,
+                                                  (tBTM_LE_EVT_DATA *)p_data);
+    }
+
+    return callback_rc;
+}
+
 #if (BLE_PRIVACY_SPT == TRUE )
 /*******************************************************************************
 **
@@ -1607,9 +1677,7 @@ void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role,
         memcpy(p_dev_rec->ble.cur_rand_addr, bda, BD_ADDR_LEN);
 #endif
 
-    if (role == HCI_ROLE_SLAVE)
-        p_cb->inq_var.adv_mode  = BTM_BLE_ADV_DISABLE;
-    p_cb->inq_var.directed_conn = FALSE;
+    p_cb->inq_var.directed_conn = BTM_BLE_CONNECT_EVT;
 
     return;
 }
@@ -1620,14 +1688,14 @@ void btm_ble_connected (UINT8 *bda, UINT16 handle, UINT8 enc_mode, UINT8 role,
 **  Description     LE connection complete.
 **
 ******************************************************************************/
-void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
+void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced)
 {
 #if (BLE_PRIVACY_SPT == TRUE )
     UINT8       *p_data = p;
 #endif
-    UINT8       role, status, bda_type;
+    UINT8       role, status, bda_type, peer_addr_type;
     UINT16      handle;
-    BD_ADDR     bda = {0};
+    BD_ADDR     bda, local_rpa, peer_rpa;
     UINT16      conn_interval, conn_latency, conn_timeout;
     BOOLEAN     match = FALSE;
     UNUSED(evt_len);
@@ -1636,18 +1704,23 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
     STREAM_TO_UINT16   (handle, p);
     STREAM_TO_UINT8    (role, p);
     STREAM_TO_UINT8    (bda_type, p);
+    peer_addr_type = bda_type ;
     STREAM_TO_BDADDR   (bda, p);
 
     if (status == 0)
     {
 #if (BLE_PRIVACY_SPT == TRUE )
+        match = btm_identity_addr_to_random_pseudo (bda, &bda_type, TRUE);
 
-        if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
-            match = btm_public_addr_to_random_pseudo (bda, &bda_type);
+        if (enhanced)
+        {
+            STREAM_TO_BDADDR   (local_rpa, p);
+            STREAM_TO_BDADDR   (peer_rpa, p);
+        }
 
         /* possiblly receive connection complete with resolvable random on
            slave role while the device has been paired */
-        if (!match && /*role == HCI_ROLE_SLAVE && */BTM_BLE_IS_RESOLVE_BDA(bda))
+        if (!match && role == HCI_ROLE_SLAVE && BTM_BLE_IS_RESOLVE_BDA(bda))
         {
             btm_ble_resolve_random_addr(bda, btm_ble_resolve_random_addr_on_conn_cmpl, p_data);
         }
@@ -1660,8 +1733,19 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
             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);
+
+#if (BLE_PRIVACY_SPT == TRUE)
+            if (enhanced)
+            {
+                btm_ble_refresh_local_resolvable_private_addr(bda, local_rpa);
+
+                if (peer_addr_type & BLE_ADDR_TYPE_ID_BIT)
+                    btm_ble_refresh_peer_resolvable_private_addr(bda, peer_rpa, BLE_ADDR_RANDOM);
+            }
+#endif
         }
     }
     else
@@ -1669,33 +1753,14 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
         role = HCI_ROLE_UNKNOWN;
 
         if (status != HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
-        {
             btm_ble_set_conn_st(BLE_CONN_IDLE);
         }
-        /* this is to work around broadcom firmware problem to handle
-         * unsolicited command complete event for HCI_LE_Create_Connection_Cancel
-         * and LE connection complete event with status error code (0x2)
-         * unknown connection identifier from bluetooth controller
-         * the workaround is to release the HCI connection to avoid out of sync
-         * with bluetooth controller, which cause BT can't be turned off.
-        */
-        else if ((status == HCI_ERR_NO_CONNECTION) &&
-                 (btm_ble_get_conn_st() != BLE_CONN_CANCEL))
-        {
-            tL2C_LCB    *p_lcb;
-            handle = HCID_GET_HANDLE (handle);
-            p_lcb = l2cu_find_lcb_by_handle (handle);
-            if (p_lcb != NULL)
-            {
-                l2c_link_hci_disc_comp (handle, HCI_ERR_PEER_USER);
-                btm_sec_disconnected (handle, HCI_ERR_PEER_USER);
-            }
-        }
-    }
-    btm_ble_set_conn_st(BLE_CONN_IDLE);
+
     btm_ble_update_mode_operation(role, bda, status);
 }
 
+
+
 /*****************************************************************************
 ** Function btm_ble_create_ll_conn_complete
 **
@@ -1704,7 +1769,7 @@ void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len)
 ******************************************************************************/
 void btm_ble_create_ll_conn_complete (UINT8 status)
 {
-    if (status != 0)
+    if (status != HCI_SUCCESS)
     {
         btm_ble_set_conn_st(BLE_CONN_IDLE);
         btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
@@ -1731,9 +1796,16 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                 btm_ble_io_capabilities_req(p_dev_rec, (tBTM_LE_IO_REQ *)&p_data->io_req);
                 break;
 
+            case SMP_BR_KEYS_REQ_EVT:
+                btm_ble_br_keys_req(p_dev_rec, (tBTM_LE_IO_REQ *)&p_data->io_req);
+                break;
+
             case SMP_PASSKEY_REQ_EVT:
             case SMP_PASSKEY_NOTIF_EVT:
             case SMP_OOB_REQ_EVT:
+            case SMP_NC_REQ_EVT:
+            case SMP_SC_OOB_REQ_EVT:
+                /* fall through */
                 p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
 
             case SMP_SEC_REQUEST_EVT:
@@ -1746,6 +1818,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                 p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
                 btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
                 /* fall through */
+
             case SMP_COMPLT_EVT:
                 if (btm_cb.api.p_le_callback)
                 {
@@ -1763,8 +1836,6 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                     BTM_TRACE_DEBUG ("after update result=%d sec_level=0x%x sec_flags=0x%x",
                                       res, p_data->cmplt.sec_level , p_dev_rec->sec_flags );
 
-                    btm_sec_dev_rec_cback_event(p_dev_rec, res, TRUE);
-
                     if (p_data->cmplt.is_pair_cancel && btm_cb.api.p_bond_cancel_cmpl_callback )
                     {
                         BTM_TRACE_DEBUG ("Pairing Cancel completed");
@@ -1775,8 +1846,8 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                     {
                         if (!btm_cb.devcb.no_disc_if_pair_fail && p_data->cmplt.reason != SMP_CONN_TOUT)
                         {
-                            BTM_TRACE_DEBUG ("Pairing failed - Remove ACL");
-                            btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
+                            BTM_TRACE_DEBUG ("Pairing failed - prepare to remove ACL");
+                            l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
                         }
                         else
                         {
@@ -1786,7 +1857,10 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                     }
 #else
                     if (res != BTM_SUCCESS && p_data->cmplt.reason != SMP_CONN_TOUT)
-                        btm_remove_acl(bd_addr, BT_TRANSPORT_LE);
+                    {
+                        BTM_TRACE_DEBUG ("Pairing failed - prepare to remove ACL");
+                        l2cu_start_post_bond_timer(p_dev_rec->ble_hci_handle);
+                    }
 #endif
 
                     BTM_TRACE_DEBUG ("btm_cb pairing_state=%x pairing_flags=%x pin_code_len=%x",
@@ -1796,6 +1870,7 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                     BTM_TRACE_DEBUG ("btm_cb.pairing_bda %02x:%02x:%02x:%02x:%02x:%02x",
                                       btm_cb.pairing_bda[0], btm_cb.pairing_bda[1], btm_cb.pairing_bda[2],
                                       btm_cb.pairing_bda[3], btm_cb.pairing_bda[4], btm_cb.pairing_bda[5]);
+
                     /* Reset btm state only if the callback address matches pairing address*/
                     if(memcmp(bd_addr, btm_cb.pairing_bda, BD_ADDR_LEN) == 0)
                     {
@@ -1803,6 +1878,17 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
                         btm_cb.pairing_state = BTM_PAIR_STATE_IDLE;
                         btm_cb.pairing_flags = 0;
                     }
+
+                    if (res == BTM_SUCCESS)
+                    {
+                        p_dev_rec->sec_state = BTM_SEC_STATE_IDLE;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+                        /* add all bonded device into resolving list if IRK is available*/
+                        btm_ble_resolving_list_load_dev(p_dev_rec);
+#endif
+                    }
+
+                    btm_sec_dev_rec_cback_event(p_dev_rec, res, TRUE);
                 }
                 break;
 
@@ -1842,29 +1928,21 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data)
 BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len,
                               BLE_SIGNATURE signature)
 {
-    BOOLEAN     ret = FALSE;
-#if SMP_INCLUDED == TRUE
-    tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bd_addr);
-    UINT8   *p_buf, *pp;
-
-    BT_OCTET16  er;
-    UINT16      div;
-    UINT8       temp[4]; /* for (r || DIV)  r=1*/
-    UINT16      r=1;
-    UINT8       *p=temp, *p_mac = (UINT8 *)signature;
-    tSMP_ENC    output;
-    BT_OCTET16  local_csrk;
+    tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
 
-    BTM_TRACE_DEBUG ("BTM_BleDataSignature");
+    BTM_TRACE_DEBUG ("%s", __func__);
+    BOOLEAN ret = FALSE;
     if (p_rec == NULL)
     {
-        BTM_TRACE_ERROR("data signing can not be done from unknow device");
+        BTM_TRACE_ERROR("%s-data signing can not be done from unknown device", __func__);
     }
     else
     {
+        UINT8 *p_mac = (UINT8 *)signature;
+        UINT8 *p_buf, *pp;
         if ((p_buf = (UINT8 *)GKI_getbuf((UINT16)(len + 4))) != NULL)
         {
-            BTM_TRACE_DEBUG("Start to generate Local CSRK");
+            BTM_TRACE_DEBUG("%s-Start to generate Local CSRK", __func__);
             pp = p_buf;
             /* prepare plain text */
             if (p_text)
@@ -1873,76 +1951,23 @@ BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len,
                 pp = (p_buf + len);
             }
 
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
-            if ( btm_cb.devcb.enable_test_local_sign_cntr)
-            {
-                BTM_TRACE_DEBUG ("Use Test local counter value from script counter_val=%d", btm_cb.devcb.test_local_sign_cntr);
-                UINT32_TO_STREAM(pp, btm_cb.devcb.test_local_sign_cntr);
-            }
-            else
-            {
-                UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
-            }
-#else
             UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
-#endif
-            /* compute local csrk */
-            if (btm_get_local_div(bd_addr, &div))
-            {
-                BTM_TRACE_DEBUG ("compute_csrk div=%x", div);
-                BTM_GetDeviceEncRoot(er);
-
-                /* CSRK = d1(ER, DIV, 1) */
-                UINT16_TO_STREAM(p, div);
-                UINT16_TO_STREAM(p, r);
+            UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
 
-                if (!SMP_Encrypt(er, BT_OCTET16_LEN, temp, 4, &output))
-                {
-                    BTM_TRACE_ERROR("Local CSRK generation failed ");
-                }
-                else
-                {
-                    BTM_TRACE_DEBUG("local CSRK generation success");
-                    memcpy((void *)local_csrk, output.param_buf, BT_OCTET16_LEN);
-
-
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
-                    if (btm_cb.devcb.enable_test_local_sign_cntr)
-                    {
-                        UINT32_TO_STREAM(p_mac, btm_cb.devcb.test_local_sign_cntr);
-                    }
-                    else
-                    {
-                        UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
-                    }
-#else
-                    UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
-#endif
-
-                    if ((ret = AES_CMAC(local_csrk, p_buf, (UINT16)(len + 4), BTM_CMAC_TLEN_SIZE, p_mac)) == TRUE)
-                    {
-                        btm_ble_increment_sign_ctr(bd_addr, TRUE);
-
-#if BTM_BLE_CONFORMANCE_TESTING == TRUE
-                        if ( btm_cb.devcb.enable_test_mac_val)
-                        {
-                            BTM_TRACE_DEBUG ("Use MAC value from script");
-                            memcpy(p_mac, btm_cb.devcb.test_mac, BTM_CMAC_TLEN_SIZE);
-                        }
-#endif
-                    }
-                    BTM_TRACE_DEBUG("BTM_BleDataSignature p_mac = %d", p_mac);
-                    BTM_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
-                                     *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
-                    BTM_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
-                                     *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
-
-                    GKI_freebuf(p_buf);
-                }
+            if ((ret = aes_cipher_msg_auth_code(p_rec->ble.keys.lcsrk, p_buf, (UINT16)(len + 4),
+                                        BTM_CMAC_TLEN_SIZE, p_mac)) == TRUE)
+            {
+                  btm_ble_increment_sign_ctr(bd_addr, TRUE);
             }
+
+            BTM_TRACE_DEBUG("%s p_mac = %d", __func__, p_mac);
+            BTM_TRACE_DEBUG("p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = 0x%02x",
+                             *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
+            BTM_TRACE_DEBUG("p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = 0x%02x",
+                            *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
+            GKI_freebuf(p_buf);
         }
     }
-#endif  /* SMP_INCLUDED */
     return ret;
 }
 
@@ -1964,10 +1989,10 @@ BOOLEAN BTM_BleDataSignature (BD_ADDR bd_addr, UINT8 *p_text, UINT16 len,
 BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT32 counter,
                                 UINT8 *p_comp)
 {
-    BOOLEAN             verified = FALSE;
+    BOOLEAN verified = FALSE;
 #if SMP_INCLUDED == TRUE
-    tBTM_SEC_DEV_REC    *p_rec = btm_find_dev (bd_addr);
-    UINT8               p_mac[BTM_CMAC_TLEN_SIZE];
+    tBTM_SEC_DEV_REC *p_rec = btm_find_dev (bd_addr);
+    UINT8 p_mac[BTM_CMAC_TLEN_SIZE];
 
     if (p_rec == NULL || (p_rec && !(p_rec->ble.key_type & BTM_LE_KEY_PCSRK)))
     {
@@ -1983,9 +2008,10 @@ BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT
     }
     else
     {
-        BTM_TRACE_DEBUG ("BTM_BleVerifySignature rcv_cnt=%d >= expected_cnt=%d", counter, p_rec->ble.keys.counter);
+        BTM_TRACE_DEBUG ("%s rcv_cnt=%d >= expected_cnt=%d", __func__, counter,
+                          p_rec->ble.keys.counter);
 
-        if (AES_CMAC(p_rec->ble.keys.csrk, p_orig, len, BTM_CMAC_TLEN_SIZE, p_mac))
+        if (aes_cipher_msg_auth_code(p_rec->ble.keys.pcsrk, p_orig, len, BTM_CMAC_TLEN_SIZE, p_mac))
         {
             if (memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0)
             {
@@ -1999,6 +2025,148 @@ BOOLEAN BTM_BleVerifySignature (BD_ADDR bd_addr, UINT8 *p_orig, UINT16 len, UINT
 }
 
 /*******************************************************************************
+**
+** Function         BTM_GetLeSecurityState
+**
+** Description      This function is called to get security mode 1 flags and
+**                  encryption key size for LE peer.
+**
+** Returns          BOOLEAN TRUE if LE device is found, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN BTM_GetLeSecurityState (BD_ADDR bd_addr, UINT8 *p_le_dev_sec_flags, UINT8 *p_le_key_size)
+{
+#if (BLE_INCLUDED == TRUE)
+    tBTM_SEC_DEV_REC *p_dev_rec;
+    UINT16 dev_rec_sec_flags;
+#endif
+
+    *p_le_dev_sec_flags = 0;
+    *p_le_key_size = 0;
+
+#if (BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE)
+    if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
+    {
+        BTM_TRACE_ERROR ("%s fails", __func__);
+        return (FALSE);
+    }
+
+    if (p_dev_rec->ble_hci_handle == BTM_SEC_INVALID_HANDLE)
+    {
+        BTM_TRACE_ERROR ("%s-this is not LE device", __func__);
+        return (FALSE);
+    }
+
+    dev_rec_sec_flags = p_dev_rec->sec_flags;
+
+    if (dev_rec_sec_flags & BTM_SEC_LE_ENCRYPTED)
+    {
+        /* link is encrypted with LTK or STK */
+        *p_le_key_size = p_dev_rec->enc_key_size;
+        *p_le_dev_sec_flags |= BTM_SEC_LE_LINK_ENCRYPTED;
+
+        *p_le_dev_sec_flags |= (dev_rec_sec_flags & BTM_SEC_LE_AUTHENTICATED)
+            ? BTM_SEC_LE_LINK_PAIRED_WITH_MITM      /* set auth LTK flag */
+            : BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM;  /* set unauth LTK flag */
+    }
+    else if (p_dev_rec->ble.key_type & BTM_LE_KEY_PENC)
+    {
+        /* link is unencrypted, still LTK is available */
+        *p_le_key_size = p_dev_rec->ble.keys.key_size;
+
+        *p_le_dev_sec_flags |= (dev_rec_sec_flags & BTM_SEC_LE_LINK_KEY_AUTHED)
+            ? BTM_SEC_LE_LINK_PAIRED_WITH_MITM      /* set auth LTK flag */
+            : BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM;  /* set unauth LTK flag */
+    }
+
+    BTM_TRACE_DEBUG ("%s - le_dev_sec_flags: 0x%02x, le_key_size: %d",
+        __func__, *p_le_dev_sec_flags, *p_le_key_size);
+
+    return TRUE;
+#else
+    return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleSecurityProcedureIsRunning
+**
+** Description      This function indicates if LE security procedure is
+**                  currently running with the peer.
+**
+** Returns          BOOLEAN TRUE if security procedure is running, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN BTM_BleSecurityProcedureIsRunning(BD_ADDR bd_addr)
+{
+#if (BLE_INCLUDED == TRUE)
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+
+    if (p_dev_rec == NULL)
+    {
+        BTM_TRACE_ERROR ("%s device with BDA: %08x%04x is not found",
+                          __func__, (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+                          (bd_addr[4]<<8)+bd_addr[5]);
+        return FALSE;
+    }
+
+    return (p_dev_rec->sec_state == BTM_SEC_STATE_ENCRYPTING ||
+            p_dev_rec->sec_state == BTM_SEC_STATE_AUTHENTICATING);
+#else
+    return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         BTM_BleGetSupportedKeySize
+**
+** Description      This function gets the maximum encryption key size in bytes
+**                  the local device can suport.
+**                  record.
+**
+** Returns          the key size or 0 if the size can't be retrieved.
+**
+*******************************************************************************/
+extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr)
+{
+#if ((BLE_INCLUDED == TRUE) && (L2CAP_LE_COC_INCLUDED == TRUE))
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+    tBTM_LE_IO_REQ dev_io_cfg;
+    UINT8 callback_rc;
+
+    if (!p_dev_rec)
+    {
+        BTM_TRACE_ERROR ("%s device with BDA: %08x%04x is not found",
+                         __func__,(bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8)+bd_addr[3],
+                          (bd_addr[4]<<8)+bd_addr[5]);
+        return 0;
+    }
+
+    if (btm_cb.api.p_le_callback == NULL)
+    {
+        BTM_TRACE_ERROR ("%s can't access supported key size",__func__);
+        return 0;
+    }
+
+    callback_rc = (*btm_cb.api.p_le_callback) (BTM_LE_IO_REQ_EVT, p_dev_rec->bd_addr,
+                                               (tBTM_LE_EVT_DATA *) &dev_io_cfg);
+
+    if (callback_rc != BTM_SUCCESS)
+    {
+        BTM_TRACE_ERROR ("%s can't access supported key size",__func__);
+        return 0;
+    }
+
+    BTM_TRACE_DEBUG ("%s device supports key size = %d", __func__, dev_io_cfg.max_key_size);
+    return (dev_io_cfg.max_key_size);
+#else
+    return 0;
+#endif
+}
+
+/*******************************************************************************
 **  Utility functions for LE device IR/ER generation
 *******************************************************************************/
 /*******************************************************************************
@@ -2028,7 +2196,7 @@ static void btm_notify_new_key(UINT8 key_type)
 
             case BTM_BLE_KEY_TYPE_ER:
                 BTM_TRACE_DEBUG ("BTM_BLE_KEY_TYPE_ER");
-                p_locak_keys = (tBTM_BLE_LOCAL_KEYS *)&btm_cb.devcb.er;
+                p_locak_keys = (tBTM_BLE_LOCAL_KEYS *)&btm_cb.devcb.ble_encryption_key_value;
                 break;
 
             default:
@@ -2056,13 +2224,13 @@ static void btm_ble_process_er2(tBTM_RAND_ENC *p)
 
     if (p &&p->opcode == HCI_BLE_RAND)
     {
-        memcpy(&btm_cb.devcb.er[8], p->param_buf, BT_OCTET8_LEN);
+        memcpy(&btm_cb.devcb.ble_encryption_key_value[8], p->param_buf, BT_OCTET8_LEN);
         btm_notify_new_key(BTM_BLE_KEY_TYPE_ER);
     }
     else
     {
         BTM_TRACE_ERROR("Generating ER2 exception.");
-        memset(&btm_cb.devcb.er, 0, sizeof(BT_OCTET16));
+        memset(&btm_cb.devcb.ble_encryption_key_value, 0, sizeof(BT_OCTET16));
     }
 }
 
@@ -2082,11 +2250,11 @@ static void btm_ble_process_er(tBTM_RAND_ENC *p)
 
     if (p &&p->opcode == HCI_BLE_RAND)
     {
-        memcpy(&btm_cb.devcb.er[0], p->param_buf, BT_OCTET8_LEN);
+        memcpy(&btm_cb.devcb.ble_encryption_key_value[0], p->param_buf, BT_OCTET8_LEN);
 
         if (!btsnd_hcic_ble_rand((void *)btm_ble_process_er2))
         {
-            memset(&btm_cb.devcb.er, 0, sizeof(BT_OCTET16));
+            memset(&btm_cb.devcb.ble_encryption_key_value, 0, sizeof(BT_OCTET16));
             BTM_TRACE_ERROR("Generating ER2 failed.");
         }
     }
index e560ee7..142b8d8 100644 (file)
 #include "btu.h"
 #include "btm_int.h"
 #include "gap_api.h"
+#include "device/include/controller.h"
 
 #if (defined BLE_INCLUDED && BLE_INCLUDED == TRUE)
 #include "btm_ble_int.h"
 #include "smp_api.h"
 
-#include "vendor_ble.h"
 
 /*******************************************************************************
 **
@@ -199,7 +199,8 @@ void btm_gen_non_resolvable_private_addr (tBTM_BLE_ADDR_CBACK *p_cback, void *p)
     }
 
 }
-    #if SMP_INCLUDED == TRUE
+
+#if SMP_INCLUDED == TRUE
 /*******************************************************************************
 **  Utility functions for Random address resolving
 *******************************************************************************/
@@ -352,7 +353,8 @@ void btm_ble_resolve_random_addr(BD_ADDR random_bda, tBTM_BLE_RESOLVE_CBACK * p_
     else
         (*p_cback)(NULL, p);
 }
-    #endif
+#endif
+
 /*******************************************************************************
 **  address mapping between pseudo address and real connection address
 *******************************************************************************/
@@ -382,62 +384,62 @@ tBLE_ADDR_TYPE btm_ble_map_bda_to_conn_bda(BD_ADDR bd_addr)
 
 /*******************************************************************************
 **
-** Function         btm_find_dev_by_public_static_addr
+** Function         btm_find_dev_by_identity_addr
 **
 ** Description      find the security record whose LE static address is matching
 **
 *******************************************************************************/
-tBTM_SEC_DEV_REC* btm_find_dev_by_public_static_addr(BD_ADDR bd_addr)
+tBTM_SEC_DEV_REC* btm_find_dev_by_identity_addr(BD_ADDR bd_addr, UINT8 addr_type)
 {
-    UINT8               i;
-    tBTM_SEC_DEV_REC    *p_dev_rec = &btm_cb.sec_dev_rec[0];
 #if BLE_PRIVACY_SPT == TRUE
+    UINT8 i;
+    tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
     for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
     {
-        if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
-            BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+        if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
+            memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0)
         {
-            if ( memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) == 0)
+            if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
+                (addr_type & (~BLE_ADDR_TYPE_ID_BIT)))
             {
-                p_dev_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
-                /* found the match */
-                return p_dev_rec;
+                BTM_TRACE_WARNING("%s find pseudo->random match with diff addr type: %d vs %d",
+                    __func__, p_dev_rec->ble.static_addr_type, addr_type);
             }
+
+            /* found the match */
+            return p_dev_rec;
         }
     }
 #endif
+
     return NULL;
 }
 
 /*******************************************************************************
 **
-** Function         btm_public_addr_to_random_pseudo
+** Function         btm_identity_addr_to_random_pseudo
 **
 ** Description      This function map a static BD address to a pseudo random address
 **                  in security database.
 **
 *******************************************************************************/
-BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type)
+BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh)
 {
 #if BLE_PRIVACY_SPT == TRUE
-    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev_by_public_static_addr(bd_addr);
-
-    BTM_TRACE_EVENT ("btm_public_addr_to_random_pseudo");
+    tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev_by_identity_addr(bd_addr, *p_addr_type);
 
+    BTM_TRACE_EVENT ("%s", __func__);
     /* evt reported on static address, map static address to random pseudo */
-    if (p_dev_rec  != NULL &&
-        /* static address is not static address */
-        memcmp(p_dev_rec->bd_addr, bd_addr, BD_ADDR_LEN) != 0)
-        /* update current random */
-        btm_ble_read_irk_entry(p_dev_rec->ble.static_addr);
     if (p_dev_rec != NULL)
     {
-        /* assign the orginal random to be the current report address */
-        memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
-        /* always be a resolvable random if a match is found */
-        *p_addr_type = BLE_ADDR_RANDOM;
+        /* if RPA offloading is supported, or 4.2 controller, do RPA refresh */
+        if (refresh && controller_get_interface()->get_ble_resolving_list_max_size() != 0)
+            btm_ble_read_resolving_list_entry(p_dev_rec);
 
-        BTM_TRACE_ERROR("matched a public/reconnect address and map to random pseudo");
+        /* assign the original address to be the current report address */
+        memcpy(bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+        *p_addr_type = p_dev_rec->ble.ble_addr_type;
 
         return TRUE;
     }
@@ -447,26 +449,25 @@ BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type)
 
 /*******************************************************************************
 **
-** Function         btm_random_pseudo_to_public
+** Function         btm_random_pseudo_to_identity_addr
 **
 ** Description      This function map a random pseudo address to a public address
 **                  random_pseudo is input and output parameter
 **
 *******************************************************************************/
-BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
+BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type)
 {
 #if BLE_PRIVACY_SPT == TRUE
     tBTM_SEC_DEV_REC    *p_dev_rec = btm_find_dev (random_pseudo);
 
     if (p_dev_rec != NULL)
     {
-        if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
-            BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr) &&
-            (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
+        if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
         {
-            BTM_TRACE_EVENT ("btm_random_pseudo_to_public found the puclic static address!");
             * p_static_addr_type = p_dev_rec->ble.static_addr_type;
             memcpy(random_pseudo, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
+            if (controller_get_interface()->supports_ble_privacy())
+                *p_static_addr_type |= BLE_ADDR_TYPE_ID_BIT;
             return TRUE;
         }
     }
@@ -476,49 +477,106 @@ BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_
 
 /*******************************************************************************
 **
-** Function         btm_ble_refresh_rra
+** Function         btm_ble_refresh_peer_resolvable_private_addr
 **
-** Description      This function refresh the currently used RRA into security
+** Description      This function refresh the currently used resolvable remote private address into security
 **                  database and set active connection address.
 **
 *******************************************************************************/
-void btm_ble_refresh_rra(BD_ADDR static_bda, BD_ADDR rra)
+void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rpa,
+                                                  UINT8 rra_type)
 {
 #if BLE_PRIVACY_SPT == TRUE
-    tBTM_SEC_DEV_REC    *p_sec_rec = btm_find_dev_by_public_static_addr(static_bda);
-    tACL_CONN           *p_acl = btm_bda_to_acl (p_sec_rec->bd_addr, BT_TRANSPORT_LE);
     UINT8               rra_dummy = FALSE;
     BD_ADDR             dummy_bda = {0};
 
-    BTM_TRACE_ERROR("btm_ble_refresh_rra");
-
-    if (memcmp(dummy_bda, rra, BD_ADDR_LEN) == 0)
+    if (memcmp(dummy_bda, rpa, BD_ADDR_LEN) == 0)
         rra_dummy = TRUE;
 
-    /* connection refresh RRA */
-    if (p_acl != NULL /* && memcmp(p_acl->active_remote_addr, dummy_bda, BD_ADDR_LEN) == 0 */)
+    /* update security record here, in adv event or connection complete process */
+    tBTM_SEC_DEV_REC *p_sec_rec = btm_find_dev(pseudo_bda);
+    if (p_sec_rec != NULL)
     {
-        /* use static address, rra is empty */
-        if (rra_dummy)
+        memcpy(p_sec_rec->ble.cur_rand_addr, rpa, BD_ADDR_LEN);
+
+        /* unknown, if dummy address, set to static */
+        if (rra_type == BTM_BLE_ADDR_PSEUDO)
+            p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
+        else
+            p_sec_rec->ble.active_addr_type = rra_type;
+    }
+    else
+    {
+        BTM_TRACE_ERROR("No matching known device in record");
+        return;
+    }
+
+    BTM_TRACE_DEBUG("%s: active_addr_type: %d ",
+                    __func__, p_sec_rec->ble.active_addr_type);
+
+    /* connection refresh remote address */
+    tACL_CONN *p_acl = p_acl = btm_bda_to_acl(p_sec_rec->bd_addr, BT_TRANSPORT_LE);
+    if (p_acl != NULL)
+    {
+        if (rra_type == BTM_BLE_ADDR_PSEUDO)
         {
-            p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
-            memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
+            /* use static address, resolvable_private_addr is empty */
+            if (rra_dummy)
+            {
+                p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
+                memcpy(p_acl->active_remote_addr, p_sec_rec->ble.static_addr, BD_ADDR_LEN);
+            }
+            else
+            {
+                p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
+                memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
+            }
         }
         else
         {
-            p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
-            memcpy(p_acl->active_remote_addr, rra, BD_ADDR_LEN);
+              p_acl->active_remote_addr_type = rra_type;
+              memcpy(p_acl->active_remote_addr, rpa, BD_ADDR_LEN);
         }
+
+        BTM_TRACE_DEBUG("p_acl->active_remote_addr_type: %d ", p_acl->active_remote_addr_type);
+        BTM_TRACE_DEBUG("%s conn_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+                __func__,p_acl->active_remote_addr[0], p_acl->active_remote_addr[1],
+                p_acl->active_remote_addr[2], p_acl->active_remote_addr[3],
+                p_acl->active_remote_addr[4], p_acl->active_remote_addr[5]);
     }
-    /* update security record here, in adv event or connection complete process */
-    if (p_sec_rec != NULL)
-    {
-        memcpy(p_sec_rec->ble.cur_rand_addr, rra, BD_ADDR_LEN);
-        p_sec_rec->ble.active_addr_type = rra_dummy ? BTM_BLE_ADDR_STATIC: BTM_BLE_ADDR_RRA;
-    }
-    else
+#endif
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_refresh_local_resolvable_private_addr
+**
+** Description      This function refresh the currently used resolvable private address for the
+**                  active link to the remote device
+**
+*******************************************************************************/
+void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr,
+                                                   BD_ADDR local_rpa)
+{
+#if BLE_PRIVACY_SPT == TRUE
+    tACL_CONN *p = btm_bda_to_acl(pseudo_addr, BT_TRANSPORT_LE);
+    BD_ADDR     dummy_bda = {0};
+
+    if (p != NULL)
     {
-        BTM_TRACE_ERROR("No matching known device in record");
+        if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+        {
+            p->conn_addr_type = BLE_ADDR_RANDOM;
+            if (memcmp(local_rpa, dummy_bda, BD_ADDR_LEN))
+                memcpy(p->conn_addr, local_rpa, BD_ADDR_LEN);
+            else
+                memcpy(p->conn_addr, btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr, BD_ADDR_LEN);
+        }
+        else
+        {
+            p->conn_addr_type = BLE_ADDR_PUBLIC;
+            memcpy(p->conn_addr,&controller_get_interface()->get_address()->address, BD_ADDR_LEN);
+        }
     }
 #endif
 }
index 9a29798..ad6a56c 100644 (file)
 #include "bt_utils.h"
 #include "hcidefs.h"
 #include "btm_ble_api.h"
-#include "vendor_ble.h"
 #include "device/include/controller.h"
 
 #define BTM_BLE_ADV_FILT_META_HDR_LENGTH 3
 #define BTM_BLE_ADV_FILT_FEAT_SELN_LEN  13
 #define BTM_BLE_ADV_FILT_TRACK_NUM       2
 
+#define BTM_BLE_PF_SELECT_NONE              0
+
+/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
+#define BTM_BLE_META_HDR_LENGTH     3
+#define BTM_BLE_PF_FEAT_SEL_LEN     18
+#define BTM_BLE_PCF_ENABLE_LEN      2
+
+#define BTM_BLE_META_ADDR_LEN       7
+#define BTM_BLE_META_UUID_LEN       40
+
 #define BTM_BLE_PF_BIT_TO_MASK(x)          (UINT16)(1 << (x))
 
 
index 21d4c9b..a83a3c7 100644 (file)
@@ -30,7 +30,7 @@
 #include "l2c_int.h"
 #include "hcimsgs.h"
 #include "bt_utils.h"
-#include "vendor_ble.h"
+#include "device/include/controller.h"
 
 #ifndef BTM_BLE_SCAN_PARAM_TOUT
 #define BTM_BLE_SCAN_PARAM_TOUT      50    /* 50 seconds */
@@ -83,40 +83,38 @@ BOOLEAN btm_add_dev_to_controller (BOOLEAN to_add, BD_ADDR bd_addr)
         {
             if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
             {
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-                /* add device into IRK list */
-                btm_ble_vendor_irk_list_load_dev(p_dev_rec);
-#endif
                 started = btsnd_hcic_ble_add_white_list (p_dev_rec->ble.ble_addr_type, bd_addr);
+                p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
             }
-            if (memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0 &&
+            else 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);
+                p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
             }
         }
         else
         {
             if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC || !BTM_BLE_IS_RESOLVE_BDA(bd_addr))
             {
-                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.ble_addr_type, 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.static_addr, dummy_bda, BD_ADDR_LEN) != 0 &&
                 memcmp(p_dev_rec->ble.static_addr, bd_addr, BD_ADDR_LEN) != 0)
             {
-                    started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
+                started = btsnd_hcic_ble_remove_from_white_list (p_dev_rec->ble.static_addr_type, p_dev_rec->ble.static_addr);
             }
+            p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT;
         }
     }    /* if not a known device, shall we add it? */
     else
     {
         BTM_ReadDevInfo(bd_addr, &dev_type, &addr_type);
 
+        started = btsnd_hcic_ble_remove_from_white_list (addr_type, bd_addr);
         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);
     }
 
     return started;
@@ -316,6 +314,7 @@ BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr)
         return ret;
     }
 
+    /* Look for existing device to add/remove attribute */
     for (i = 0; i < BTM_BLE_MAX_BG_CONN_DEV_NUM; i ++, p_bg_dev ++)
     {
         if (p_bg_dev->in_use && memcmp(p_bg_dev->bd_addr, bd_addr, BD_ADDR_LEN) == 0)
@@ -373,28 +372,39 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
     tBTM_BLE_CB *p_cb = &btm_cb.ble_ctr_cb;
     BD_ADDR dummy_bda = {0};
     BOOLEAN exec = TRUE;
-    UINT16 scan_int, scan_win;
+    UINT16 scan_int;
+    UINT16 scan_win;
+    UINT8 own_addr_type = p_cb->addr_mgnt_cb.own_addr_type;
+    UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
 
     if (start)
     {
-        if ( p_cb->conn_state == BLE_CONN_IDLE )
-        {
-            exec = btm_execute_wl_dev_operation();
-        }
-        if ((p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0)
+        if (p_cb->conn_state == BLE_CONN_IDLE && btm_ble_count_unconn_dev_in_whitelist() > 0
             && btm_ble_topology_check(BTM_BLE_STATE_INIT))
         {
-            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;
+            p_cb->wl_state  |= BTM_BLE_WL_INIT;
+
+            btm_execute_wl_dev_operation();
+
+#if BLE_PRIVACY_SPT == TRUE
+            btm_ble_enable_resolving_list_for_platform();
+#endif
+            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 (btm_cb.ble_ctr_cb.enabled)
+            {
+                own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+                peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+            }
 
             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 */
+                                                peer_addr_type,        /* UINT8 addr_type_peer */
                                                 dummy_bda,              /* BD_ADDR bda_peer     */
-                                                p_cb->addr_mgnt_cb.own_addr_type,
-                                                   /* UINT8 addr_type_own,
-                                                   not allow random address for central  */
+                                                own_addr_type,          /* 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  */
@@ -404,11 +414,11 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
             {
                 /* start auto connection failed */
                 exec =  FALSE;
+                p_cb->wl_state &= ~BTM_BLE_WL_INIT;
             }
             else
             {
                 btm_ble_set_conn_st (BLE_BG_CONN);
-                p_cb->wl_state |= BTM_BLE_WL_INIT;
             }
         }
         else
@@ -422,12 +432,7 @@ BOOLEAN btm_ble_start_auto_conn(BOOLEAN start)
         {
             btsnd_hcic_ble_create_conn_cancel();
             btm_ble_set_conn_st (BLE_CONN_CANCEL);
-            p_cb->wl_state |= BTM_BLE_WL_INIT;
-
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-            if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
-                btm_ble_vendor_disable_irk_list();
-#endif
+            p_cb->wl_state &= ~BTM_BLE_WL_INIT;
         }
         else
         {
@@ -480,8 +485,8 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK   *p_select_c
                                                 scan_win,    /* scan window */
                                                 p_cb->addr_mgnt_cb.own_addr_type,
                                                 SP_ADV_WL)              /* process advertising packets only from devices in the White List */
-                )
-                return FALSE;
+               )
+               return FALSE;
 
             if (!btm_ble_topology_check(BTM_BLE_STATE_PASSIVE_SCAN))
             {
@@ -509,17 +514,11 @@ BOOLEAN btm_ble_start_select_conn(BOOLEAN start,tBTM_BLE_SEL_CBACK   *p_select_c
     {
         p_cb->scan_activity &= ~BTM_LE_SELECT_CONN_ACTIVE;
         p_cb->p_select_cback = NULL;
-
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-        if (btm_cb.cmn_ble_vsc_cb.rpa_offloading == TRUE)
-            btm_ble_vendor_disable_irk_list();
-#endif
-        p_cb->wl_state |= BTM_BLE_WL_SCAN;
+        p_cb->wl_state &= ~BTM_BLE_WL_SCAN;
 
         /* stop scanning */
         if (!BTM_BLE_IS_SCAN_ACTIVE(p_cb->scan_activity))
             btm_ble_stop_scan(); /* duplicate filtering enabled */
-        btm_update_scanner_filter_policy(SP_ADV_ALL);
     }
     return TRUE;
 }
@@ -669,13 +668,11 @@ tBTM_BLE_CONN_ST btm_ble_get_conn_st(void)
 void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st)
 {
     btm_cb.ble_ctr_cb.conn_state = new_st;
-    if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN) {
-        btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_INIT;
+
+    if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN)
         btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
-    } else {
-        btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_INIT;
+    else
         btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
-    }
 }
 
 /*******************************************************************************
index fa1d201..fc6dae0 100644 (file)
@@ -37,7 +37,6 @@
 
 #if BLE_INCLUDED == TRUE
 #include "l2c_int.h"
-#include "vendor_ble.h"
 
 #include "gattdefs.h"
 #include "gatt_int.h"
@@ -67,8 +66,8 @@ static void btm_ble_process_adv_pkt_cont(BD_ADDR bda, UINT8 addr_type, UINT8 evt
 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,
+                                     BD_ADDR_PTR p_peer_addr_ptr,
+                                     tBLE_ADDR_TYPE *p_peer_addr_type,
                                      tBLE_ADDR_TYPE *p_own_addr_type);
 static void btm_ble_stop_observe(void);
 
@@ -335,8 +334,8 @@ tBTM_STATUS BTM_BleObserve(BOOLEAN start, UINT8 duration,
                                             BTM_BLE_DEFAULT_SFP); /* assume observe always not using white list */
 
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-            /* enable IRK list */
-            btm_ble_vendor_irk_list_known_dev (TRUE);
+            /* enable resolving list */
+            btm_ble_enable_resolving_list_for_platform();
 #endif
             status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
         }
@@ -466,7 +465,7 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_
     }
 
     BTM_TRACE_DEBUG("btm_ble_vnd_cap_vsc_cmpl_cback: stat=%d, irk=%d, ADV ins:%d, rpa=%d, ener=%d",
-         status, btm_ble_vendor_cb.irk_avail_size, btm_cb.cmn_ble_vsc_cb.adv_inst_max,
+         status,btm_cb.cmn_ble_vsc_cb.max_irk_list_sz, btm_cb.cmn_ble_vsc_cb.adv_inst_max,
          btm_cb.cmn_ble_vsc_cb.rpa_offloading, btm_cb.cmn_ble_vsc_cb.energy_support);
 
     if (BTM_BleMaxMultiAdvInstanceCount() > 0)
@@ -477,10 +476,14 @@ static void btm_ble_vendor_capability_vsc_cmpl_cback (tBTM_VSC_CMPL *p_vcs_cplt_
         btm_ble_adv_filter_init();
     }
 
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+    /* VS capability included and non-4.2 device */
+    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz > 0 &&
+        controller_get_interface()->get_ble_resolving_list_max_size() == 0)
     {
-        btm_ble_vendor_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
+        btm_ble_resolving_list_init(btm_cb.cmn_ble_vsc_cb.max_irk_list_sz);
     }
+#endif
 
     if (btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg > 0)
         btm_ble_batchscan_init();
@@ -550,27 +553,23 @@ extern void BTM_BleReadControllerFeatures(tBTM_BLE_CTRL_FEATURES_CBACK  *p_vsc_c
 
 /*******************************************************************************
 **
-** Function         BTM_RegisterScanReqEvt
+** Function         BTM_BleEnableMixedPrivacyMode
 **
-** Description      This function is called to register a scan request callback
-**                  on the advertiser.
+** Description      This function is called to enabled Mixed mode if privacy 1.2
+**                  is applicable in controller.
 **
-** Parameters       p_scan_req_cback: scan request callback.  If NULL, remove the
-**                                    registration.
+** Parameters       mixed_on:  mixed mode to be used or not.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK   *p_scan_req_cback)
+void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on)
 {
-#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;
-    }
-#else
-    UNUSED(p_scan_req_cback);
+
+#if BLE_PRIVACY_SPT == TRUE
+    btm_cb.ble_ctr_cb.mixed_mode = mixed_on;
+
+    /* TODO: send VSC to enabled mixed mode */
 #endif
 }
 
@@ -581,34 +580,54 @@ void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK   *p_scan_req_cback)
 ** Description      This function is called to enable or disable the privacy in
 **                   LE channel of the local device.
 **
-** Parameters       enable: TRUE to enable it; FALSE to disable it.
+** Parameters       privacy_mode:  privacy mode on or off.
 **
-** Returns          void
+** Returns          BOOLEAN privacy mode set success; otherwise failed.
 **
 *******************************************************************************/
-void BTM_BleConfigPrivacy(BOOLEAN enable)
+BOOLEAN BTM_BleConfigPrivacy(BOOLEAN privacy_mode)
 {
-    tBTM_BLE_CB     *p_cb = &btm_cb.ble_ctr_cb;
+#if BLE_PRIVACY_SPT == TRUE
+    tBTM_BLE_CB  *p_cb = &btm_cb.ble_ctr_cb;
 
-    BTM_TRACE_EVENT (" BTM_BleConfigPrivacy");
+    BTM_TRACE_EVENT ("%s", __func__);
 
-    if (p_cb->privacy != enable)
+    /* if LE is not supported, return error */
+    if (!controller_get_interface()->supports_ble())
+        return FALSE;
+
+    uint8_t addr_resolution = 0;
+    if(!privacy_mode)/* if privacy disabled, always use public address */
     {
-        p_cb->privacy = enable;
+        p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
+        p_cb->privacy_mode = BTM_PRIVACY_NONE;
+    }
+    else /* privacy is turned on*/
+    {
+        /* always set host random address, used when privacy 1.1 or priavcy 1.2 is disabled */
+        p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_RANDOM;
+        btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
 
-        if (p_cb->privacy)
-        {
-            /* generate resolvable private address */
-            btm_gen_resolvable_private_addr((void*)btm_gen_resolve_paddr_low);
-        }
-        else /* if privacy disabled, always use public address */
+        if (BTM_BleMaxMultiAdvInstanceCount() > 0)
+            btm_ble_multi_adv_enb_privacy(privacy_mode);
+
+        /* 4.2 controller only allow privacy 1.2 or mixed mode, resolvable private address in controller */
+        if (controller_get_interface()->supports_ble_privacy())
         {
-            p_cb->addr_mgnt_cb.own_addr_type = BLE_ADDR_PUBLIC;
+            addr_resolution = 1;
+            /* check vendor specific capability */
+            p_cb->privacy_mode = btm_cb.ble_ctr_cb.mixed_mode ? BTM_PRIVACY_MIXED : BTM_PRIVACY_1_2;
         }
-
-        if (BTM_BleMaxMultiAdvInstanceCount() > 0)
-            btm_ble_multi_adv_enb_privacy(p_cb->privacy);
+        else  /* 4.1/4.0 controller */
+            p_cb->privacy_mode = BTM_PRIVACY_1_1;
     }
+
+    GAP_BleAttrDBUpdate (GATT_UUID_GAP_CENTRAL_ADDR_RESOL, (tGAP_BLE_ATTR_VALUE *)&addr_resolution);
+
+    return TRUE;
+#else
+    return FALSE;
+#endif
 }
 
 /*******************************************************************************
@@ -620,7 +639,7 @@ void BTM_BleConfigPrivacy(BOOLEAN enable)
 ** Returns          Max multi adv instance count
 **
 *******************************************************************************/
-extern UINT8  BTM_BleMaxMultiAdvInstanceCount()
+extern UINT8  BTM_BleMaxMultiAdvInstanceCount(void)
 {
     return btm_cb.cmn_ble_vsc_cb.adv_inst_max < BTM_BLE_MULTI_ADV_MAX ?
         btm_cb.cmn_ble_vsc_cb.adv_inst_max : BTM_BLE_MULTI_ADV_MAX;
@@ -674,10 +693,10 @@ static void btm_ble_resolve_random_addr_on_adv(void * p_rec, void *p)
 ** Returns          Return TRUE if local privacy is enabled else FALSE
 **
 *******************************************************************************/
-BOOLEAN BTM_BleLocalPrivacyEnabled()
+BOOLEAN BTM_BleLocalPrivacyEnabled(void)
 {
 #if BLE_PRIVACY_SPT == TRUE
-    return btm_cb.ble_ctr_cb.privacy;
+    return (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE);
 #else
     return false;
 #endif
@@ -719,7 +738,7 @@ BOOLEAN BTM_BleSetBgConnType(tBTM_BLE_CONN_TYPE   bg_conn_type,
                 {
                     btm_ble_start_auto_conn(FALSE);
                 }
-                started = btm_ble_start_select_conn(TRUE, p_select_cback);
+                btm_ble_start_select_conn(TRUE, p_select_cback);
                 break;
 
             case BTM_BLE_CONN_NONE:
@@ -783,41 +802,41 @@ void BTM_BleClearBgConnDev(void)
 *******************************************************************************/
 BOOLEAN BTM_BleUpdateBgConnDev(BOOLEAN add_remove, BD_ADDR   remote_bda)
 {
-    BOOLEAN ret = TRUE;
+    BOOLEAN ret = FALSE;
     BTM_TRACE_EVENT (" BTM_BleUpdateBgConnDev");
 
     /* update white list */
-    ret = btm_update_bg_conn_list(add_remove, remote_bda);
-
-    btm_update_dev_to_white_list(add_remove, remote_bda);
+    if (btm_update_bg_conn_list(add_remove, remote_bda))
+        ret = btm_update_dev_to_white_list(add_remove, remote_bda);
 
     return ret;
 }
 
 /*******************************************************************************
 **
-** Function         BTM_BleSetConnMode
+** Function         BTM_BleSetConnectableMode
 **
 ** 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
+** Parameters       conn_mode:  directed connectable mode, or non-directed.It can
+**                              be BTM_BLE_CONNECT_EVT, BTM_BLE_CONNECT_DIR_EVT or
+**                              BTM_BLE_CONNECT_LO_DUTY_DIR_EVT
 **
-** Returns          void
+** Returns          BTM_ILLEGAL_VALUE if controller does not support BLE.
+**                  BTM_SUCCESS is status set successfully; otherwise failure.
 **
 *******************************************************************************/
-tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
+tBTM_STATUS BTM_BleSetConnectableMode(tBTM_BLE_CONN_MODE connectable_mode)
 {
     tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
 
-    BTM_TRACE_EVENT ("BTM_BleSetConnMode is_directed = %d ", is_directed);
+    BTM_TRACE_EVENT ("%s connectable_mode = %d ", __func__, connectable_mode);
     if (!controller_get_interface()->supports_ble())
         return BTM_ILLEGAL_VALUE;
 
-    p_cb->directed_conn = is_directed;
+    p_cb->directed_conn = connectable_mode;
     return btm_ble_set_connectability( p_cb->connectable_mode);
-
 }
 
 /*******************************************************************************
@@ -830,38 +849,87 @@ tBTM_STATUS BTM_BleSetConnMode(BOOLEAN is_directed)
 **
 *******************************************************************************/
 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,
+                                     BD_ADDR_PTR p_peer_addr_ptr,
+                                     tBLE_ADDR_TYPE *p_peer_addr_type,
                                      tBLE_ADDR_TYPE *p_own_addr_type)
 {
-    UINT8 evt_type;
+    UINT8 evt_type, i = BTM_SEC_MAX_DEVICE_RECORDS;
+    tBTM_SEC_DEV_REC    *p_dev_rec;
 
-    UNUSED(p_own_addr_type);
+    evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
+                ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
+                : BTM_BLE_CONNECT_EVT;
 
-    if ( p_cb->directed_conn)
+    if (evt_type == BTM_BLE_CONNECT_EVT)
     {
-        /*  direct adv mode does not have privacy if privacy
-        is not enabled or no reconn addr config */
+        evt_type = p_cb->directed_conn;
 
-        *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;
+        if ( p_cb->directed_conn == BTM_BLE_CONNECT_DIR_EVT ||
+             p_cb->directed_conn == BTM_BLE_CONNECT_LO_DUTY_DIR_EVT)
+        {
+
+#if BLE_PRIVACY_SPT == TRUE
+            /* for privacy 1.2, convert peer address as static, own address set as ID addr */
+            if (btm_cb.ble_ctr_cb.privacy_mode ==  BTM_PRIVACY_1_2 ||
+                btm_cb.ble_ctr_cb.privacy_mode ==  BTM_PRIVACY_MIXED)
+            {
+                /* only do so for bonded device */
+                 if ((p_dev_rec = btm_find_or_alloc_dev (p_cb->direct_bda.bda)) != NULL &&
+                      p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
+                 {
+                     btm_ble_enable_resolving_list();
+                     memcpy(p_peer_addr_ptr, p_dev_rec->ble.static_addr, BD_ADDR_LEN);
+                     *p_peer_addr_type = p_dev_rec->ble.static_addr_type;
+                     *p_own_addr_type = BLE_ADDR_RANDOM_ID;
+                     return evt_type;
+                 }
+                 /* otherwise fall though as normal directed adv */
+            }
+#endif
+            /* direct adv mode does not have privacy, if privacy is not enabled  */
+            *p_peer_addr_type  = p_cb->direct_bda.type;
+            memcpy(p_peer_addr_ptr, p_cb->direct_bda.bda, BD_ADDR_LEN);
+            return evt_type;
+        }
     }
-    else /* undirect adv mode */
-    {
-        evt_type = BTM_BLE_CONNECT_EVT;
 
-        /* may need to reset random address if privacy is enabled */
-        if (btm_cb.ble_ctr_cb.privacy && /* own addr_type is random */
-            !BTM_BLE_IS_RESOLVE_BDA(btm_cb.ble_ctr_cb.addr_mgnt_cb.private_addr))
+    /* undirect adv mode or non-connectable mode*/
+#if BLE_PRIVACY_SPT == TRUE
+    /* when privacy 1.2 privacy only mode is used, or mixed mode */
+    if ((btm_cb.ble_ctr_cb.privacy_mode ==  BTM_PRIVACY_1_2 && p_cb->afp != AP_SCAN_CONN_ALL) ||
+        btm_cb.ble_ctr_cb.privacy_mode ==  BTM_PRIVACY_MIXED)
+    {
+        /* if enhanced privacy is required, set Identity address and matching IRK peer */
+        for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
         {
-            /* need to generate RRA and update random addresss in controller */
-            btm_gen_resolvable_private_addr((void *)btm_gen_resolve_paddr_low);
+            if ((btm_cb.sec_dev_rec[i].sec_flags & BTM_SEC_IN_USE) != 0 &&
+                (btm_cb.sec_dev_rec[i].ble.in_controller_list & BTM_RESOLVING_LIST_BIT) != 0)
+            {
+                memcpy(p_peer_addr_ptr, btm_cb.sec_dev_rec[i].ble.static_addr, BD_ADDR_LEN);
+                *p_peer_addr_type = btm_cb.sec_dev_rec[i].ble.static_addr_type;
+               break;
+            }
         }
+
+        if (i != BTM_SEC_MAX_DEVICE_RECORDS)
+            *p_own_addr_type = BLE_ADDR_RANDOM_ID;
+        else
+            /* resolving list is empty, not enabled */
+            *p_own_addr_type = BLE_ADDR_RANDOM;
     }
 
-    return evt_type;
+    /* privacy 1.1, or privacy 1.2, general discoverable/connectable mode, disable privacy in */
+    /* controller fall back to host based privacy */
+    else if (btm_cb.ble_ctr_cb.privacy_mode !=  BTM_PRIVACY_NONE)
+    {
+        *p_own_addr_type = BLE_ADDR_RANDOM;
+        btm_ble_disable_resolving_list ();
+    }
+#endif
 
+    /* if no privacy,do not set any peer address,*/
+    /* local address type go by global privacy setting */
+    return evt_type;
 }
 
 /*******************************************************************************
@@ -914,8 +982,8 @@ tBTM_STATUS BTM_BleSetAdvParams(UINT16 adv_int_min, UINT16 adv_int_max,
 
     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, &own_addr_type);
+    p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type,
+                                                     &own_addr_type);
 
     /* update adv params */
     btsnd_hcic_ble_write_adv_params (p_cb->adv_interval_min,
@@ -1433,6 +1501,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 *
         switch (evt_type)
         {
         case BTM_BLE_CONNECT_EVT:
+        case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT:
             *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_1;
             break;
 
@@ -1440,6 +1509,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 *
         case BTM_BLE_DISCOVER_EVT:
             *p_adv_int_min = *p_adv_int_max = BTM_BLE_GAP_ADV_FAST_INT_2;
             break;
+
         /* connectable directed event */
         case BTM_BLE_CONNECT_DIR_EVT:
             *p_adv_int_min = BTM_BLE_GAP_ADV_DIR_MIN_INT;
@@ -1453,6 +1523,7 @@ void btm_ble_select_adv_interval(tBTM_BLE_INQ_CB *p_cb, UINT8 evt_type, UINT16 *
     }
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_update_dmt_flag_bits
@@ -1546,22 +1617,20 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
     tBTM_BLE_INQ_CB     *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT16              mode = (combined_mode &  BTM_BLE_DISCOVERABLE_MASK);
     UINT8               new_mode = BTM_BLE_ADV_ENABLE;
-    UINT8               evt_type = (p_cb->connectable_mode == BTM_BLE_NON_CONNECTABLE) ? \
-                                   ((p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT : BTM_BLE_NON_CONNECT_EVT )\
-                                   : BTM_BLE_CONNECT_EVT;
+    UINT8               evt_type;
     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;
     UINT16              adv_int_min, adv_int_max;
 
-    BTM_TRACE_EVENT ("btm_ble_set_discoverability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
+    BTM_TRACE_EVENT ("%s mode=0x%0x combined_mode=0x%x", __FUNCTION__, mode, combined_mode);
 
     /*** Check mode parameter ***/
     if (mode > BTM_BLE_MAX_DISCOVERABLE)
         return(BTM_ILLEGAL_VALUE);
 
-    btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode);
+    p_cb->discoverable_mode = mode;
 
     evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
 
@@ -1575,28 +1644,33 @@ tBTM_STATUS btm_ble_set_discoverability(UINT16 combined_mode)
     /* update adv params if start advertising */
     BTM_TRACE_EVENT ("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 ||p_cb->adv_addr_type != own_addr_type || !p_cb->fast_adv_on))
+    if (new_mode == BTM_BLE_ADV_ENABLE)
     {
-        btm_ble_stop_adv();
+        btm_ble_set_adv_flag (btm_cb.btm_inq_vars.connectable_mode, combined_mode);
 
-        /* update adv params */
-        if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
-                                              adv_int_max,
-                                              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 (evt_type != p_cb->evt_type ||p_cb->adv_addr_type != own_addr_type
+            || !p_cb->fast_adv_on)
         {
-            p_cb->evt_type = evt_type;
-            p_cb->adv_addr_type = own_addr_type;
+            btm_ble_stop_adv();
+
+            /* update adv params */
+            if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+                                                  adv_int_max,
+                                                  evt_type,
+                                                  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)
@@ -1642,14 +1716,14 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
     tBTM_BLE_INQ_CB         *p_cb = &btm_cb.ble_ctr_cb.inq_var;
     UINT16                  mode = (combined_mode & BTM_BLE_CONNECTABLE_MASK);
     UINT8                   new_mode = BTM_BLE_ADV_ENABLE;
-    UINT8                   evt_type = (p_cb->scan_rsp) ? BTM_BLE_DISCOVER_EVT: BTM_BLE_NON_CONNECT_EVT;
+    UINT8                   evt_type;
     tBTM_STATUS             status = BTM_SUCCESS;
     BD_ADDR                 p_addr_ptr =  {0};
-    tBLE_ADDR_TYPE          init_addr_type = BLE_ADDR_PUBLIC,
+    tBLE_ADDR_TYPE          peer_addr_type = BLE_ADDR_PUBLIC,
                             own_addr_type = p_addr_cb->own_addr_type;
     UINT16                  adv_int_min, adv_int_max;
 
-    BTM_TRACE_EVENT ("btm_ble_set_connectability mode=0x%0x combined_mode=0x%x", mode, combined_mode);
+    BTM_TRACE_EVENT ("%s mode=0x%0x combined_mode=0x%x", __FUNCTION__, mode, combined_mode);
 
     /*** Check mode parameter ***/
     if (mode > BTM_BLE_MAX_CONNECTABLE)
@@ -1657,9 +1731,7 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
 
     p_cb->connectable_mode = mode;
 
-    btm_ble_set_adv_flag (combined_mode,  btm_cb.btm_inq_vars.discoverable_mode);
-
-    evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type, &own_addr_type);
+    evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &peer_addr_type, &own_addr_type);
 
     if (mode == BTM_BLE_NON_CONNECTABLE && p_cb->discoverable_mode == BTM_BLE_NON_DISCOVERABLE)
         new_mode = BTM_BLE_ADV_DISABLE;
@@ -1668,23 +1740,30 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
 
     btu_stop_timer(&p_cb->fast_adv_timer);
     /* update adv params if needed */
-    if ((p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type || !p_cb->fast_adv_on))
+    if (new_mode == BTM_BLE_ADV_ENABLE)
     {
-        btm_ble_stop_adv();
-
-        if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
-                                              adv_int_max,
-                                              evt_type,
-                                              own_addr_type,
-                                              init_addr_type,
-                                              p_addr_ptr,
-                                              p_cb->adv_chnl_map,
-                                              p_cb->afp))
-            status = BTM_NO_RESOURCES;
-        else
+        btm_ble_set_adv_flag (combined_mode, btm_cb.btm_inq_vars.discoverable_mode);
+        if (p_cb->evt_type != evt_type || p_cb->adv_addr_type != p_addr_cb->own_addr_type
+            || !p_cb->fast_adv_on)
         {
-            p_cb->evt_type = evt_type;
-            p_cb->adv_addr_type = own_addr_type;
+            btm_ble_stop_adv();
+
+            if (!btsnd_hcic_ble_write_adv_params (adv_int_min,
+                                                  adv_int_max,
+                                                  evt_type,
+                                                  own_addr_type,
+                                                  peer_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;
+            }
         }
     }
 
@@ -1696,6 +1775,7 @@ tBTM_STATUS btm_ble_set_connectability(UINT16 combined_mode)
         else
             status = btm_ble_stop_adv();
     }
+
     if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
     {
         p_cb->fast_adv_on = TRUE;
@@ -1748,7 +1828,7 @@ tBTM_STATUS btm_ble_start_inquiry (UINT8 mode, UINT8   duration)
 
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
         /* enable IRK list */
-        btm_ble_vendor_irk_list_known_dev (TRUE);
+        btm_ble_enable_resolving_list_for_platform();
 #endif
         status = btm_ble_start_scan(BTM_BLE_DUPLICATE_DISABLE);
     }
@@ -2379,6 +2459,31 @@ BOOLEAN btm_ble_update_inq_result(tINQ_DB_ENT *p_i, UINT8 addr_type, UINT8 evt_t
 
 /*******************************************************************************
 **
+** Function         btm_clear_all_pending_le_entry
+**
+** Description      This function is called to clear all LE pending entry in
+**                  inquiry database.
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_clear_all_pending_le_entry(void)
+{
+    UINT16       xx;
+    tINQ_DB_ENT  *p_ent = btm_cb.btm_inq_vars.inq_db;
+
+    for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++)
+    {
+        /* mark all pending LE entry as unused if an LE only device has scan response outstanding */
+        if ((p_ent->in_use) &&
+            (p_ent->inq_info.results.device_type == BT_DEVICE_TYPE_BLE) &&
+             !p_ent->scan_rsp)
+            p_ent->in_use = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_send_sel_conn_callback
 **
 ** Description      send selection connection request callback.
@@ -2444,6 +2549,10 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
     BOOLEAN             match = FALSE;
 #endif
 
+    /* Only process the results if the inquiry is still active */
+    if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
+        return;
+
     /* Extract the number of reports in this event. */
     STREAM_TO_UINT8(num_reports, p);
 
@@ -2454,29 +2563,12 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
         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 */
-        {
-            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
-
 #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-    /* map address to security record */
-    btm_public_addr_to_random_pseudo(bda, &addr_type);
-    BTM_TRACE_DEBUG("new address: %02x:%02x:%02x:%02x:%02x:%02x",
-                     bda[0], bda[1], bda[2], bda[3], bda[4], bda[5]);
-#endif
+        /* map address to security record */
+        match = btm_identity_addr_to_random_pseudo(bda, &addr_type, FALSE);
 
-        /* Only process the results if the inquiry is still active */
-        if (!BTM_BLE_IS_SCAN_ACTIVE(btm_cb.ble_ctr_cb.scan_activity))
-            return;
-
-    BTM_TRACE_DEBUG("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
+        BTM_TRACE_DEBUG("btm_ble_process_adv_pkt:bda= %0x:%0x:%0x:%0x:%0x:%0x",
                                      bda[0],bda[1],bda[2],bda[3],bda[4],bda[5]);
-#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
-#if SMP_INCLUDED == TRUE
         /* always do RRA resolution on host */
         if (!match && BTM_BLE_IS_RESOLVE_BDA(bda))
         {
@@ -2484,10 +2576,7 @@ void btm_ble_process_adv_pkt (UINT8 *p_data)
         }
         else
 #endif
-#endif
-        {
             btm_ble_process_adv_pkt_cont(bda, addr_type, evt_type, p);
-        }
 
         STREAM_TO_UINT8(data_len, p);
 
@@ -2626,13 +2715,12 @@ tBTM_STATUS btm_ble_start_scan (UINT8 filter_enable)
     tBTM_STATUS status = BTM_CMD_STARTED;
 
     /* start scan, disable duplicate filtering */
-    if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable)) {
+    if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, filter_enable))
+    {
         status = BTM_NO_RESOURCES;
-        btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN;
     }
     else
     {
-        btm_cb.ble_ctr_cb.wl_state |= BTM_BLE_WL_SCAN;
         if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI)
             btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT);
         else
@@ -2751,6 +2839,10 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI
         rt  =  (*p_handler) (BTM_BLE_STATE_SCAN_ADV_BIT);
         break;
 
+    case BTM_BLE_CONNECT_LO_DUTY_DIR_EVT:
+        rt = (*p_handler) (BTM_BLE_STATE_LO_DUTY_DIR_ADV_BIT);
+        break;
+
     default:
         BTM_TRACE_ERROR("unknown adv event : %d", adv_evt);
         break;
@@ -2777,6 +2869,16 @@ tBTM_STATUS btm_ble_start_adv(void)
     if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type))
         return BTM_WRONG_MODE;
 
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+    /* When privacy 1.2 goes into general connection/discoverable mode, */
+    /* disable controller privacy */
+    if (p_cb->afp == AP_SCAN_CONN_ALL && btm_cb.ble_ctr_cb.privacy_mode == BTM_PRIVACY_1_2)
+       btm_ble_disable_resolving_list();
+    else
+        /* enable resolving list is desired*/
+        btm_ble_enable_resolving_list_for_platform();
+#endif
+
     if (p_cb->afp != AP_SCAN_CONN_ALL)
     {
         btm_execute_wl_dev_operation();
@@ -2785,11 +2887,8 @@ tBTM_STATUS btm_ble_start_adv(void)
 
     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;
-
+         btm_ble_adv_states_operation(btm_ble_set_topology_mask, p_cb->evt_type);
          rt = BTM_SUCCESS;
     }
     else
@@ -2799,6 +2898,7 @@ tBTM_STATUS btm_ble_start_adv(void)
     }
     return rt;
 }
+
 /*******************************************************************************
 **
 ** Function         btm_ble_stop_adv
@@ -2833,96 +2933,6 @@ tBTM_STATUS btm_ble_stop_adv(void)
 
 /*******************************************************************************
 **
-** Function         btm_ble_set_topology_mask
-**
-** Description      set BLE topology mask
-**
-** Returns          TRUE is request is allowed, FALSE otherwise.
-**
-*******************************************************************************/
-BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask)
-{
-    BOOLEAN rt = TRUE;
-
-    request_state_mask &= BTM_BLE_STATE_ALL_MASK;
-
-    btm_cb.ble_ctr_cb.cur_states |= request_state_mask;
-
-    return rt;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_clear_topology_mask
-**
-** Description      Clear BLE topology bit mask
-**
-** Returns          TRUE is request is allowed, FALSE otherwise.
-**
-*******************************************************************************/
-BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask)
-{
-    request_state_mask &= BTM_BLE_STATE_ALL_MASK;
-
-    btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask;
-
-    return TRUE;
-}
-/*******************************************************************************
-**
-** 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, UINT8 status)
-{
-    tACL_CONN   *pa = &btm_cb.acl_db[0];
-    UINT16       xx;
-    UINT16       mask = BTM_BLE_STATE_ALL_CONN_MASK;
-
-    UNUSED(bd_addr);
-
-    if (link_role == HCI_ROLE_SLAVE)
-    {
-        btm_cb.ble_ctr_cb.inq_var.adv_mode  = BTM_BLE_ADV_DISABLE;
-        /* clear all adv states */
-        mask |= BTM_BLE_STATE_ALL_ADV_MASK;
-    }
-
-    btm_ble_clear_topology_mask (mask);
-
-    /* check the device link role maps */
-    for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, pa++)
-    {
-        if (pa->in_use && pa->transport == BT_TRANSPORT_LE)
-        {
-            if (pa->link_role == HCI_ROLE_MASTER)
-                btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT);
-            else
-                btm_ble_set_topology_mask (BTM_BLE_STATE_SLAVE_BIT);
-        }
-    }
-
-    if (btm_cb.cmn_ble_vsc_cb.adv_inst_max == 0 &&
-        btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
-    {
-        btm_ble_set_connectability ( btm_cb.ble_ctr_cb.inq_var.connectable_mode );
-    }
-
-    if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES)
-    {
-        if (!btm_send_pending_direct_conn())
-        {
-            btm_ble_resume_bg_conn();
-        }
-    }
-}
-
-/*******************************************************************************
-**
 ** Function         btm_ble_start_slow_adv
 **
 ** Description      Restart adv with slow adv interval
@@ -2932,22 +2942,25 @@ void btm_ble_update_mode_operation(UINT8 link_role, BD_ADDR bd_addr, UINT8 statu
 *******************************************************************************/
 static void btm_ble_start_slow_adv (void)
 {
-    tBTM_BLE_INQ_CB         *p_cb = &btm_cb.ble_ctr_cb.inq_var;
-    BD_ADDR                 p_addr_ptr= {0};
+    tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var;
 
     if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE)
     {
+        tBTM_LE_RANDOM_CB *p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
+        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;
+
         btm_ble_stop_adv();
 
-        btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT,
-                                         BTM_BLE_GAP_ADV_SLOW_INT,
-                                         p_cb->evt_type,
-                                         p_cb->adv_addr_type,
-                                         btm_cb.ble_ctr_cb.addr_mgnt_cb.own_addr_type,/* slow adv
-                                         mode never goes into directed adv */
-                                         p_addr_ptr,
-                                         p_cb->adv_chnl_map,
-                                         p_cb->afp);
+        p_cb->evt_type = btm_set_conn_mode_adv_init_addr(p_cb, p_addr_ptr, &init_addr_type,
+                                                         &own_addr_type);
+
+        /* slow adv mode never goes into directed adv */
+        btsnd_hcic_ble_write_adv_params (BTM_BLE_GAP_ADV_SLOW_INT, BTM_BLE_GAP_ADV_SLOW_INT,
+                                         p_cb->evt_type, own_addr_type,
+                                         init_addr_type, p_addr_ptr,
+                                         p_cb->adv_chnl_map, p_cb->afp);
 
         btm_ble_start_adv();
     }
@@ -3030,8 +3043,10 @@ void btm_ble_read_remote_features_complete(UINT8 *p)
     BTM_TRACE_EVENT ("btm_ble_read_remote_features_complete ");
 
     STREAM_TO_UINT8(status, p);
-    /* if LE read remote feature failed, expect disconnect complete to be received */
-    if (status == HCI_SUCCESS)
+
+    // if LE read remote feature failed for HCI_ERR_CONN_FAILED_ESTABLISHMENT,
+    // expect disconnect complete to be received
+    if (status != HCI_ERR_CONN_FAILED_ESTABLISHMENT)
     {
         STREAM_TO_UINT16 (handle, p);
 
@@ -3090,6 +3105,109 @@ void btm_ble_dir_adv_tout(void)
 
 /*******************************************************************************
 **
+** Function         btm_ble_set_topology_mask
+**
+** Description      set BLE topology mask
+**
+** Returns          TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state_mask)
+{
+    request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+    btm_cb.ble_ctr_cb.cur_states |= (request_state_mask & BTM_BLE_STATE_ALL_MASK);
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_clear_topology_mask
+**
+** Description      Clear BLE topology bit mask
+**
+** Returns          TRUE is request is allowed, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_clear_topology_mask (tBTM_BLE_STATE_MASK request_state_mask)
+{
+    request_state_mask &= BTM_BLE_STATE_ALL_MASK;
+    btm_cb.ble_ctr_cb.cur_states &= ~request_state_mask;
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_update_link_topology_mask
+**
+** Description      This function update the link topology mask
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_update_link_topology_mask(UINT8 link_role, BOOLEAN increase)
+{
+    btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_CONN_MASK);
+
+    if (increase)
+        btm_cb.ble_ctr_cb.link_count[link_role]++;
+    else if (btm_cb.ble_ctr_cb.link_count[link_role] > 0)
+        btm_cb.ble_ctr_cb.link_count[link_role]--;
+
+    if (btm_cb.ble_ctr_cb.link_count[HCI_ROLE_MASTER])
+        btm_ble_set_topology_mask (BTM_BLE_STATE_MASTER_BIT);
+
+    if (btm_cb.ble_ctr_cb.link_count[HCI_ROLE_SLAVE])
+        btm_ble_set_topology_mask(BTM_BLE_STATE_SLAVE_BIT);
+
+    if (link_role == HCI_ROLE_SLAVE && increase)
+    {
+        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 = BTM_BLE_CONNECT_EVT;
+        /* clear all adv states */
+        btm_ble_clear_topology_mask(BTM_BLE_STATE_ALL_ADV_MASK);
+    }
+}
+
+/*******************************************************************************
+**
+** 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, UINT8 status)
+{
+    if (status == HCI_ERR_DIRECTED_ADVERTISING_TIMEOUT)
+    {
+        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 = BTM_BLE_CONNECT_EVT;
+        /* clear all adv states */
+        btm_ble_clear_topology_mask (BTM_BLE_STATE_ALL_ADV_MASK);
+    }
+
+    if (btm_cb.ble_ctr_cb.inq_var.connectable_mode == BTM_BLE_CONNECTABLE)
+    {
+        btm_ble_set_connectability(btm_cb.btm_inq_vars.connectable_mode |
+                                   btm_cb.ble_ctr_cb.inq_var.connectable_mode);
+    }
+
+    /* when no connection is attempted, and controller is not rejecting last request
+       due to resource limitation, start next direct connection or background connection
+       now in order */
+    if (btm_ble_get_conn_st() == BLE_CONN_IDLE && status != HCI_ERR_HOST_REJECT_RESOURCES &&
+        !btm_send_pending_direct_conn())
+    {
+         btm_ble_resume_bg_conn();
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         btm_ble_init
 **
 ** Description      Initialize the control block variable values.
@@ -3122,7 +3240,6 @@ void btm_ble_init (void)
     p_cb->inq_var.evt_type = BTM_BLE_NON_CONNECT_EVT;
 
 #if BLE_VND_INCLUDED == FALSE
-    btm_ble_vendor_init(BTM_CS_IRK_LIST_MAX);
     btm_ble_adv_filter_init();
 #endif
 }
index 4741ca7..cb37ff4 100644 (file)
@@ -93,6 +93,9 @@ typedef UINT8   tBTM_BLE_SEC_REQ_ACT;
 #define BTM_BLE_IS_OBS_ACTIVE(x)   ((x) & BTM_LE_OBSERVE_ACTIVE)
 #define BTM_BLE_IS_SEL_CONN_ACTIVE(x)   ((x) & BTM_LE_SELECT_CONN_ACTIVE)
 
+/* BLE ADDR type ID bit */
+#define BLE_ADDR_TYPE_ID_BIT 0x02
+
 typedef struct
 {
     UINT16              data_mask;
@@ -136,7 +139,7 @@ typedef struct
     UINT8            evt_type;
     UINT8            adv_mode;
     tBLE_BD_ADDR     direct_bda;
-    BOOLEAN          directed_conn;
+    tBTM_BLE_EVT     directed_conn;
     BOOLEAN          fast_adv_on;
     TIMER_LIST_ENT   fast_adv_timer;
 
@@ -248,6 +251,18 @@ typedef UINT16 tBTM_BLE_STATE_MASK;
 #define BTM_BLE_STATE_ALL_SCAN_MASK         (BTM_BLE_STATE_PASSIVE_SCAN_BIT|BTM_BLE_STATE_ACTIVE_SCAN_BIT)
 #define BTM_BLE_STATE_ALL_CONN_MASK         (BTM_BLE_STATE_MASTER_BIT|BTM_BLE_STATE_SLAVE_BIT)
 
+#ifndef BTM_LE_RESOLVING_LIST_MAX
+#define BTM_LE_RESOLVING_LIST_MAX     0x20
+#endif
+
+typedef struct
+{
+    BD_ADDR         *resolve_q_random_pseudo;
+    UINT8           *resolve_q_action;
+    UINT8           q_next;
+    UINT8           q_pending;
+} tBTM_BLE_RESOLVE_Q;
+
 typedef struct
 {
     BOOLEAN     in_use;
@@ -255,6 +270,17 @@ typedef struct
     BD_ADDR     bd_addr;
     UINT8       attr;
 }tBTM_BLE_WL_OP;
+
+/* BLE privacy mode */
+#define BTM_PRIVACY_NONE    0              /* BLE no privacy */
+#define BTM_PRIVACY_1_1     1              /* BLE privacy 1.1, do not support privacy 1.0 */
+#define BTM_PRIVACY_1_2     2              /* BLE privacy 1.2 */
+#define BTM_PRIVACY_MIXED   3              /* BLE privacy mixed mode, broadcom propietary mode */
+typedef UINT8 tBTM_PRIVACY_MODE;
+
+/* data length change event callback */
+typedef void (tBTM_DATA_LENGTH_CHANGE_CBACK) (UINT16 max_tx_length, UINT16 max_rx_length);
+
 /* Define BLE Device Management control structure
 */
 typedef struct
@@ -276,7 +302,6 @@ typedef struct
     UINT16              scan_int;
     UINT16              scan_win;
     tBTM_BLE_SEL_CBACK  *p_select_cback;
-    TIMER_LIST_ENT      scan_param_idle_timer;
 
     /* white list information */
     UINT8                   num_empty_filter;      /* Number of entries in white list */
@@ -292,16 +317,18 @@ typedef struct
     tBTM_LE_RANDOM_CB   addr_mgnt_cb;
 
     BOOLEAN          enabled;
-    BOOLEAN          privacy;               /* local privacy enabled or disabled */
-    tBTM_BLE_WL_OP  wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
 
-#ifdef BTM_BLE_PC_ADV_TEST_MODE
-    tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback;
+#if BLE_PRIVACY_SPT == TRUE
+    BOOLEAN             mixed_mode; /* privacy 1.2 mixed mode is on or not */
+    tBTM_PRIVACY_MODE   privacy_mode;               /* privacy mode */
+    UINT8               resolving_list_avail_size;     /* resolving list available size */
+    tBTM_BLE_RESOLVE_Q   resolving_list_pend_q;
 #endif
+    tBTM_BLE_WL_OP  wl_op_q[BTM_BLE_MAX_BG_CONN_DEV_NUM];
 
     /* current BLE link state */
     tBTM_BLE_STATE_MASK           cur_states;  /* bit mask of tBTM_BLE_STATE */
-
+    UINT8  link_count[2];    /* total link count master and slave*/
 } tBTM_BLE_CB;
 
 #ifdef __cplusplus
@@ -317,7 +344,8 @@ extern BOOLEAN btm_ble_cancel_remote_name(BD_ADDR remote_bda);
 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_clear_all_pending_le_entry(void);
 
 extern void btm_ble_stop_scan();
 extern void btm_ble_stop_inquiry(void);
@@ -325,7 +353,7 @@ extern void btm_ble_init (void);
 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_write_adv_enable_complete(UINT8 * p);
-extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_conn_complete(UINT8 *p, UINT16 evt_len, BOOLEAN enhanced);
 extern void btm_read_ble_local_supported_states_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);
@@ -366,8 +394,12 @@ extern UINT8 btm_ble_read_sec_key_size(BD_ADDR bd_addr);
 extern BOOLEAN btm_update_dev_to_white_list(BOOLEAN to_add, BD_ADDR bd_addr);
 extern BOOLEAN btm_update_bg_conn_list(BOOLEAN to_add, BD_ADDR bd_addr);
 extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
-extern void btm_update_scan_filter_policy(tBTM_BLE_AFP adv_policy);
+extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
 extern void btm_ble_clear_white_list (void);
+extern void btm_read_white_list_size_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);
 
 /* background connection function */
 extern void btm_ble_suspend_bg_conn(void);
@@ -380,6 +412,7 @@ 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, UINT8 status);
 extern BOOLEAN btm_execute_wl_dev_operation(void);
+extern void btm_ble_update_link_topology_mask(UINT8 role, BOOLEAN increase);
 
 /* direct connection utility */
 extern BOOLEAN btm_send_pending_direct_conn(void);
@@ -389,9 +422,27 @@ extern void btm_ble_enqueue_direct_conn_req(void *p_param);
 extern void btm_gen_resolvable_private_addr (void *p_cmd_cplt_cback);
 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);
 extern void btm_gen_resolve_paddr_low(tBTM_RAND_ENC *p);
 
+/*  privacy function */
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+/* BLE address mapping with CS feature */
+extern BOOLEAN btm_identity_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type, BOOLEAN refresh);
+extern BOOLEAN btm_random_pseudo_to_identity_addr(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
+extern void btm_ble_refresh_peer_resolvable_private_addr(BD_ADDR pseudo_bda, BD_ADDR rra, UINT8 rra_type);
+extern void btm_ble_refresh_local_resolvable_private_addr(BD_ADDR pseudo_addr, BD_ADDR local_rpa);
+extern void btm_ble_read_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len) ;
+extern void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len);
+extern void btm_read_ble_resolving_list_size_complete (UINT8 *p, UINT16 evt_len);
+extern void btm_ble_enable_resolving_list(void);
+extern void btm_ble_disable_resolving_list(void);
+extern void btm_ble_enable_resolving_list_for_platform (void);
+extern void btm_ble_resolving_list_init(UINT8 max_irk_list_sz);
+extern void btm_ble_resolving_list_cleanup(void);
+#endif
+
 extern void btm_ble_multi_adv_configure_rpa (tBTM_BLE_MULTI_ADV_INST *p_inst);
 extern void btm_ble_multi_adv_init(void);
 extern void* btm_ble_multi_adv_get_ref(UINT8 inst_id);
@@ -407,11 +458,6 @@ extern BOOLEAN btm_ble_topology_check(tBTM_BLE_STATE_MASK request);
 extern BOOLEAN btm_ble_clear_topology_mask(tBTM_BLE_STATE_MASK request_state);
 extern BOOLEAN btm_ble_set_topology_mask(tBTM_BLE_STATE_MASK request_state);
 
-/* BLE address mapping with CS feature */
-extern BOOLEAN btm_public_addr_to_random_pseudo(BD_ADDR bd_addr, UINT8 *p_addr_type);
-extern BOOLEAN btm_random_pseudo_to_public(BD_ADDR random_pseudo, UINT8 *p_static_addr_type);
-extern void btm_ble_refresh_rra(BD_ADDR pseudo_bda, BD_ADDR rra);
-
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
 extern void btm_ble_set_no_disc_if_pair_fail (BOOLEAN disble_disc);
 extern void btm_ble_set_test_mac_value (BOOLEAN enable, UINT8 *p_test_mac_val);
index e980086..7055ba9 100644 (file)
@@ -266,8 +266,8 @@ tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
     UINT16_TO_STREAM (pp, p_params->adv_int_max);
     UINT8_TO_STREAM  (pp, p_params->adv_type);
 
-#if BLE_PRIVACY_SPT
-    if (btm_cb.ble_ctr_cb.privacy)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+    if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
     {
         UINT8_TO_STREAM  (pp, BLE_ADDR_RANDOM);
         BDADDR_TO_STREAM (pp, p_inst->rpa);
@@ -310,8 +310,8 @@ tBTM_STATUS btm_ble_multi_adv_set_params (tBTM_BLE_MULTI_ADV_INST *p_inst,
     {
         p_inst->adv_evt = p_params->adv_type;
 
-#if BLE_PRIVACY_SPT
-        if (btm_cb.ble_ctr_cb.privacy)
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+        if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
         {
             /* start timer */
             p_inst->raddr_timer_ent.param = (TIMER_PARAM_TYPE) p_inst;
@@ -773,12 +773,14 @@ void btm_ble_multi_adv_vse_cback(UINT8 len, UINT8 *p)
 
         if ((idx = btm_handle_to_acl_index(conn_handle)) != MAX_L2CAP_LINKS)
         {
-            if (btm_cb.ble_ctr_cb.privacy &&
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+            if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE &&
                 adv_inst <= BTM_BLE_MULTI_ADV_MAX && adv_inst !=  BTM_BLE_MULTI_ADV_DEFAULT_STD)
             {
                 memcpy(btm_cb.acl_db[idx].conn_addr, btm_multi_adv_cb.p_adv_inst[adv_inst - 1].rpa,
                                 BD_ADDR_LEN);
             }
+#endif
         }
 
         if (adv_inst < BTM_BleMaxMultiAdvInstanceCount() &&
diff --git a/stack/btm/btm_ble_privacy.c b/stack/btm/btm_ble_privacy.c
new file mode 100644 (file)
index 0000000..b905eac
--- /dev/null
@@ -0,0 +1,823 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 1999-2012 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains functions for BLE controller based privacy.
+ *
+ ******************************************************************************/
+#include <string.h>
+#include "bt_target.h"
+
+#if (BLE_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE)
+#include "bt_types.h"
+#include "hcimsgs.h"
+#include "btu.h"
+#include "vendor_hcidefs.h"
+#include "btm_int.h"
+#include "device/include/controller.h"
+
+/* RPA offload VSC specifics */
+#define BTM_BLE_META_IRK_ENABLE         0x01
+#define BTM_BLE_META_ADD_IRK_ENTRY      0x02
+#define BTM_BLE_META_REMOVE_IRK_ENTRY   0x03
+#define BTM_BLE_META_CLEAR_IRK_LIST     0x04
+#define BTM_BLE_META_READ_IRK_ENTRY     0x05
+#define BTM_BLE_META_CS_RESOLVE_ADDR    0x00000001
+#define BTM_BLE_IRK_ENABLE_LEN          2
+
+#define BTM_BLE_META_ADD_IRK_LEN        24
+#define BTM_BLE_META_REMOVE_IRK_LEN     8
+#define BTM_BLE_META_CLEAR_IRK_LEN      1
+#define BTM_BLE_META_READ_IRK_LEN       2
+#define BTM_BLE_META_ADD_WL_ATTR_LEN    9
+
+/*******************************************************************************
+**         Functions implemented controller based privacy using Resolving List
+*******************************************************************************/
+/*******************************************************************************
+**
+** Function         btm_ble_enq_resolving_list_pending
+**
+** Description      add target address into resolving pending operation queue
+**
+** Parameters       target_bda: target device address
+**                  add_entry: TRUE for add entry, FALSE for remove entry
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_enq_resolving_list_pending(BD_ADDR psuedo_bda, UINT8 op_code)
+{
+    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+    memcpy(p_q->resolve_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
+    p_q->resolve_q_action[p_q->q_next] = op_code;
+
+    p_q->q_next ++;
+    p_q->q_next %= controller_get_interface()->get_ble_resolving_list_max_size();
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_brcm_find_resolving_pending_entry
+**
+** Description      check to see if the action is in pending list
+**
+** Parameters       TRUE: action pending;
+**                  FALSE: new action
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_brcm_find_resolving_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
+{
+    tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+    for (UINT8 i = p_q->q_pending; i != p_q->q_next; )
+    {
+        if (memcmp(p_q->resolve_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
+            action == p_q->resolve_q_action[i])
+            return TRUE;
+
+        i ++;
+        i %= controller_get_interface()->get_ble_resolving_list_max_size();
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_deq_resolving_pending
+**
+** Description      dequeue target address from resolving pending operation queue
+**
+** Parameters       psuedo_addr: psuedo_addr device address
+**
+** Returns          void
+**
+*******************************************************************************/
+BOOLEAN btm_ble_deq_resolving_pending(BD_ADDR psuedo_addr)
+{
+    tBTM_BLE_RESOLVE_Q *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+    if (p_q->q_next != p_q->q_pending)
+    {
+        memcpy(psuedo_addr, p_q->resolve_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
+        memset(p_q->resolve_q_random_pseudo[p_q->q_pending], 0, BD_ADDR_LEN);
+
+        p_q->q_pending ++;
+        p_q->q_pending %= controller_get_interface()->get_ble_resolving_list_max_size();
+
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_find_resolving_list_entry
+**
+** Description      find the device record if the pseudo address is currently in
+**                  the resolving list
+**
+** Returns          pointer to the security device record; NULL otherwise
+**
+*******************************************************************************/
+tBTM_SEC_DEV_REC * btm_ble_find_resolving_list_entry(BD_ADDR pseudo_bda)
+{
+    tBTM_SEC_DEV_REC  *p_dev_rec = &btm_cb.sec_dev_rec[0];
+
+    for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec++)
+    {
+        if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE) &&
+            (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+            memcmp(p_dev_rec->bd_addr, pseudo_bda, BD_ADDR_LEN) == 0)
+        {
+            return p_dev_rec ;
+        }
+    }
+    return NULL;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_update_resolving_list
+**
+** Description      update resolving list entry in host maintained record
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_update_resolving_list(BD_ADDR pseudo_bda, BOOLEAN add)
+{
+    tBTM_SEC_DEV_REC   *p_dev_rec = btm_find_dev (pseudo_bda);
+
+    if (p_dev_rec == NULL)
+        return;
+
+    if (add)
+    {
+        p_dev_rec->ble.in_controller_list |= BTM_RESOLVING_LIST_BIT;
+        /* set resolving list entry index : = max- available - 1*/
+        p_dev_rec->ble.resolving_list_index =
+            controller_get_interface()->get_ble_resolving_list_max_size() -
+                                btm_cb.ble_ctr_cb.resolving_list_avail_size - 1;
+    } else {
+        p_dev_rec->ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
+        p_dev_rec->ble.resolving_list_index = 0;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_clear_resolving_list_complete
+**
+** Description      This function is called when command complete for
+**                  clear resolving list
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_clear_resolving_list_complete(UINT8 *p, UINT16 evt_len)
+{
+    UINT8 status;
+    STREAM_TO_UINT8(status, p);
+
+    BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+    /* standard HCI status only have one status byte, if greater than 3, VSC complete received */
+    if (evt_len >= 3)
+    {
+        /* VSC complete has one extra byte for op code and list size, skip it here */
+        p ++;
+        /* updated the available list size, and current list size */
+        UINT8 max_resolving_list_size;
+        STREAM_TO_UINT8(max_resolving_list_size, p);
+        controller_get_interface()->set_ble_resolving_list_max_size(max_resolving_list_size);
+    }
+
+    if (status == HCI_SUCCESS)
+    {
+        btm_cb.ble_ctr_cb.resolving_list_avail_size  =
+            controller_get_interface()->get_ble_resolving_list_max_size();
+
+        BTM_TRACE_DEBUG("%s resolving_list_avail_size = %d",
+                        __func__, btm_cb.ble_ctr_cb.resolving_list_avail_size);
+
+        for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++)
+            btm_cb.sec_dev_rec[i].ble.in_controller_list &= ~BTM_RESOLVING_LIST_BIT;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_add_resolving_list_entry_complete
+**
+** Description      This function is called when command complete for
+**                  add resolving list entry
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_add_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+    UINT8           status;
+    STREAM_TO_UINT8(status, p);
+
+    BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+    BD_ADDR pseudo_bda;
+    if (!btm_ble_deq_resolving_pending( pseudo_bda))
+    {
+        BTM_TRACE_DEBUG("no pending resolving list operation");
+        return;
+    }
+
+    if (status == HCI_SUCCESS)
+    {
+        /* privacy 1.2 command complete does not have these extra byte */
+        if (evt_len > 2)
+        {
+            /* VSC complete has one extra byte for op code, skip it here */
+            p ++;
+            STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
+        }
+        else
+            btm_cb.ble_ctr_cb.resolving_list_avail_size --;
+
+    }
+    else if (status == HCI_ERR_MEMORY_FULL) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED  */
+    {
+        btm_cb.ble_ctr_cb.resolving_list_avail_size = 0;
+        BTM_TRACE_DEBUG("%s Resolving list Full ", __func__);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_remove_resolving_list_entry_complete
+**
+** Description      This function is called when command complete for
+**                  remove resolving list entry
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_remove_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+    BD_ADDR         pseudo_bda;
+
+    UINT8           status;
+    STREAM_TO_UINT8  (status, p);
+
+    BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+    if (!btm_ble_deq_resolving_pending(pseudo_bda))
+    {
+        BTM_TRACE_ERROR("%s no pending resolving list operation", __func__);
+        return;
+    }
+
+    if (status == HCI_SUCCESS)
+    {
+        /* proprietary: spec does not have these extra bytes */
+        if (evt_len > 2)
+        {
+            p ++;  /* skip opcode */
+            STREAM_TO_UINT8(btm_cb.ble_ctr_cb.resolving_list_avail_size, p);
+        }
+        else
+            btm_cb.ble_ctr_cb.resolving_list_avail_size ++;
+
+    }
+}
+/*******************************************************************************
+**
+** Function         btm_ble_read_resolving_list_entry_complete
+**
+** Description      This function is called when command complete for
+**                  remove resolving list entry
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_read_resolving_list_entry_complete(UINT8 *p, UINT16 evt_len)
+{
+    UINT8           status, rra_type = BTM_BLE_ADDR_PSEUDO;
+    BD_ADDR         rra, pseudo_bda;
+
+    STREAM_TO_UINT8  (status, p);
+
+    BTM_TRACE_DEBUG("%s status = %d", __func__, status);
+
+    if (!btm_ble_deq_resolving_pending(pseudo_bda))
+    {
+        BTM_TRACE_ERROR("no pending resolving list operation");
+        return;
+    }
+
+    if (status == HCI_SUCCESS)
+    {
+        /* proprietary spec has extra bytes */
+        if (evt_len > 8)
+        {
+            p += (2 + 16 + 1 + 6); /* skip subcode, index, IRK value, address type, identity addr type */
+            STREAM_TO_BDADDR(rra, p);
+
+            BTM_TRACE_ERROR("%s peer_addr: %02x:%02x:%02x:%02x:%02x:%02x",
+                            __func__, rra[0], rra[1], rra[2], rra[3], rra[4], rra[5]);
+        }
+        else
+        {
+           STREAM_TO_BDADDR(rra, p);
+        }
+        btm_ble_refresh_peer_resolvable_private_addr(pseudo_bda, rra, rra_type);
+   }
+}
+/*******************************************************************************
+                VSC that implement controller based privacy
+********************************************************************************/
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_vsc_op_cmpl
+**
+** Description      IRK operation VSC complete handler
+**
+** Parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_vsc_op_cmpl (tBTM_VSC_CMPL *p_params)
+{
+    UINT8  *p = p_params->p_param_buf, op_subcode;
+    UINT16  evt_len = p_params->param_len;
+
+    op_subcode   = *(p + 1);
+
+    BTM_TRACE_DEBUG("%s op_subcode = %d", __func__, op_subcode);
+
+    if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST)
+    {
+        btm_ble_clear_resolving_list_complete(p, evt_len);
+    }
+    else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY)
+    {
+       btm_ble_add_resolving_list_entry_complete(p, evt_len);
+    }
+    else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY)
+    {
+        btm_ble_remove_resolving_list_entry_complete(p, evt_len);
+    }
+    else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY)
+    {
+         btm_ble_read_resolving_list_entry_complete(p, evt_len);
+    }
+    else if (op_subcode == BTM_BLE_META_IRK_ENABLE)
+    {
+        /* RPA offloading enable/disabled */
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_remove_resolving_list_entry
+**
+** Description      This function to remove an IRK entry from the list
+**
+** Parameters       ble_addr_type: address type
+**                  ble_addr: LE adddress
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_remove_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    tBTM_STATUS st = BTM_NO_RESOURCES;
+
+    if (controller_get_interface()->supports_ble_privacy())
+    {
+        if (btsnd_hcic_ble_rm_device_resolving_list (p_dev_rec->ble.static_addr_type,
+                                                 p_dev_rec->ble.static_addr))
+            st =  BTM_CMD_STARTED;
+    } else {
+        UINT8 param[20]= {0};
+        UINT8 *p = param;
+
+        UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
+        UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+        BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+
+        st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+                                        BTM_BLE_META_REMOVE_IRK_LEN,
+                                        param,
+                                        btm_ble_resolving_list_vsc_op_cmpl);
+    }
+
+    if (st == BTM_CMD_STARTED)
+    {
+        btm_ble_enq_resolving_list_pending( p_dev_rec->bd_addr, BTM_BLE_META_REMOVE_IRK_ENTRY);
+    }
+
+    return st;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_clear_resolving_list
+**
+** Description      This function clears the resolving  list
+**
+** Parameters       None.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_clear_resolving_list(void)
+{
+    tBTM_STATUS st = BTM_NO_RESOURCES;
+
+    if (controller_get_interface()->supports_ble_privacy())
+    {
+        if (btsnd_hcic_ble_clear_resolving_list())
+            st =  BTM_SUCCESS;
+    }
+    else
+    {
+        UINT8 param[20] = {0};
+        UINT8 *p = param;
+
+        UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST);
+        st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+                                        BTM_BLE_META_CLEAR_IRK_LEN,
+                                        param,
+                                        btm_ble_resolving_list_vsc_op_cmpl);
+    }
+
+    return st;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_read_resolving_list_entry
+**
+** Description      This function read an IRK entry by index
+**
+** Parameters       entry index.
+**
+** Returns          status
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    tBTM_STATUS st = BTM_NO_RESOURCES;
+
+    if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT))
+        return BTM_WRONG_MODE;
+
+    if (controller_get_interface()->supports_ble_privacy())
+    {
+        if (btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.static_addr_type,
+                                                 p_dev_rec->ble.static_addr))
+             st =  BTM_CMD_STARTED;
+    }
+    else
+    {
+        UINT8 param[20] = {0};
+        UINT8 *p = param;
+
+        UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY);
+        UINT8_TO_STREAM(p, p_dev_rec->ble.resolving_list_index);
+
+        st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+                                        BTM_BLE_META_READ_IRK_LEN,
+                                        param,
+                                        btm_ble_resolving_list_vsc_op_cmpl);
+    }
+
+    if (st == BTM_CMD_STARTED)
+    {
+        btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr, BTM_BLE_META_READ_IRK_ENTRY);
+    }
+
+    return st;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_load_dev
+**
+** Description      This function add a device which is using RPA into white list
+**
+** Parameters       pointer to device security record
+**
+** Returns          TRUE if device added, otherwise falase.
+**
+*******************************************************************************/
+BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    BOOLEAN         rt = FALSE;
+    tBTM_BLE_CB     *p_cb = &btm_cb.ble_ctr_cb;
+
+    BTM_TRACE_DEBUG("%s btm_cb.ble_ctr_cb.privacy_mode = %d", __func__,
+                    btm_cb.ble_ctr_cb.privacy_mode);
+
+    if (p_dev_rec != NULL && /* RPA is being used and PID is known */
+        p_dev_rec->sec_flags & BTM_SEC_IN_USE &&
+        /* only add RPA enabled device into resolving list */
+        (((p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0
+          && BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+       || ((p_dev_rec->ble.key_type & BTM_LE_KEY_LID) != 0
+          && btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)))
+    {
+        if (!(p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+            btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
+                                                      BTM_BLE_META_ADD_IRK_ENTRY) == FALSE)
+        {
+            if (p_cb->resolving_list_avail_size > 0)
+            {
+                btm_ble_update_resolving_list( p_dev_rec->bd_addr, TRUE);
+
+                if (controller_get_interface()->supports_ble_privacy())
+                {
+                    UINT8 dummy_irk[HCIC_BLE_IRK_SIZE];
+                    memset(dummy_irk, 0,  HCIC_BLE_IRK_SIZE);
+
+                    UINT8 *peer_irk;
+                    if (BTM_BLE_IS_RESOLVE_BDA(p_dev_rec->bd_addr))
+                        peer_irk = p_dev_rec->ble.keys.irk;
+                    else
+                        peer_irk = dummy_irk;
+
+                    UINT8 *local_irk;
+                    if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE)
+                        local_irk = btm_cb.devcb.id_keys.irk;
+                    else
+                        local_irk = dummy_irk;
+
+                    BD_ADDR dummy_bda = {0};
+                    /* for device not assigning static address, use pseudo address as identity */
+                    if (memcmp(p_dev_rec->ble.static_addr, dummy_bda, BD_ADDR_LEN) == 0)
+                    {
+                        memcpy(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
+                        p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
+                    }
+
+                    rt = btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
+                              p_dev_rec->ble.static_addr, peer_irk, local_irk); // use identical IRK for now 
+                }
+               else
+               {
+                    UINT8 param[40] = {0};
+                    UINT8 *p = param;
+
+                    UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
+                    ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
+                    UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
+                    BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
+
+                    if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
+                                                    BTM_BLE_META_ADD_IRK_LEN,
+                                                    param,
+                                                    btm_ble_resolving_list_vsc_op_cmpl)
+                                                    == BTM_CMD_STARTED)
+                        rt = TRUE;
+               }
+
+               if (rt)
+                    btm_ble_enq_resolving_list_pending(p_dev_rec->bd_addr,
+                                                       BTM_BLE_META_ADD_IRK_ENTRY);
+            }
+        }
+        else
+        {
+            BTM_TRACE_ERROR("Device already in Resolving list");
+            rt = TRUE;
+        }
+    }
+    else
+    {
+        BTM_TRACE_DEBUG("Device not a RPA enabled device");
+    }
+    return rt;
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_remove_dev
+**
+** Description      This function removes the device from resolving list
+**
+** Parameters
+**
+** Returns          status
+**
+*******************************************************************************/
+void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    btm_ble_update_resolving_list( p_dev_rec->bd_addr, FALSE);
+
+    if ((p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+        btm_ble_brcm_find_resolving_pending_entry(p_dev_rec->bd_addr,
+                                                  BTM_BLE_META_REMOVE_IRK_ENTRY) == FALSE)
+    {
+        btm_ble_remove_resolving_list_entry(p_dev_rec);
+    } else {
+        BTM_TRACE_DEBUG("Device not in resolving list");
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_vendor_enable_irk_feature
+**
+** Description      This function is called to enable or disable the RRA
+**                  offloading feature.
+**
+** Parameters       enable: enable or disable the RRA offloading feature
+**
+** Returns          BTM_SUCCESS if successful
+**
+*******************************************************************************/
+tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable)
+{
+    UINT8 param[20] = {0};
+    UINT8 *p = param;
+
+    /* select feature based on control block settings */
+    UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE);
+    UINT8_TO_STREAM(p, enable ? 0x01 : 0x00);
+
+    return BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN,
+                                    param, btm_ble_resolving_list_vsc_op_cmpl);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_disable_resolving_list
+**
+** Description      disable LE resolve address feature
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_ble_disable_resolving_list(void)
+{
+    if (btm_cb.ble_ctr_cb.enabled)
+    {
+        if (!controller_get_interface()->supports_ble_privacy())
+            btm_ble_vendor_enable_irk_feature(FALSE);
+        else
+            btsnd_hcic_ble_set_addr_resolution_enable(FALSE);
+
+        btm_cb.ble_ctr_cb.enabled = FALSE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_enable_resolving_list
+**
+** Description      enable LE resolve address list
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_ble_enable_resolving_list(void)
+{
+    if (!btm_cb.ble_ctr_cb.enabled &&
+        controller_get_interface()->get_ble_resolving_list_max_size() != 0)
+    {
+        if (!controller_get_interface()->supports_ble_privacy())
+            btm_ble_vendor_enable_irk_feature(TRUE);
+        else
+            btsnd_hcic_ble_set_addr_resolution_enable(TRUE);
+
+        btm_cb.ble_ctr_cb.enabled = TRUE;
+    }
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_empty
+**
+** Description      check to see if resoving list is empty or not
+**
+** Returns          TRUE: empty; FALSE non-empty
+**
+*******************************************************************************/
+BOOLEAN btm_ble_resolving_list_empty(void)
+{
+    return (controller_get_interface()->get_ble_resolving_list_max_size() ==
+                                    btm_cb.ble_ctr_cb.resolving_list_avail_size);
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_enable_resolving_list_for_platform
+**
+** Description      enable/disable resolving list feature depending on if any
+**                  resolving list is empty and whitelist is involoved in the
+**                  operation.
+**
+** Returns          none
+**
+*******************************************************************************/
+void btm_ble_enable_resolving_list_for_platform (void)
+{
+    /* if controller does not support, skip */
+    if (controller_get_interface()->get_ble_resolving_list_max_size() == 0)
+        return;
+
+    if (btm_cb.ble_ctr_cb.wl_state == BTM_BLE_WL_IDLE)
+    {
+        if (controller_get_interface()->get_ble_resolving_list_max_size() >
+                                              btm_cb.ble_ctr_cb.resolving_list_avail_size)
+            btm_ble_enable_resolving_list();
+        else
+            btm_ble_disable_resolving_list();
+
+        return;
+    }
+
+    tBTM_SEC_DEV_REC *p_dev = &btm_cb.sec_dev_rec[0];
+    for (UINT8 i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev ++)
+    {
+        if ((p_dev->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) &&
+            (p_dev->ble.in_controller_list & BTM_WHITE_LIST_BIT))
+        {
+            btm_ble_enable_resolving_list();
+            return;
+        }
+    }
+    btm_ble_disable_resolving_list();
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_init
+**
+** Description      Initialize resolving list in host stack
+**
+** Parameters       Max resolving list size
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_init(UINT8 max_irk_list_sz)
+{
+    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+    if (max_irk_list_sz > 0)
+    {
+        p_q->resolve_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
+                                                  max_irk_list_sz);
+        p_q->resolve_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
+
+        BTM_TRACE_DEBUG ("%s max_irk_list_sz = %d", __func__, max_irk_list_sz);
+    }
+
+    controller_get_interface()->set_ble_resolving_list_max_size(max_irk_list_sz);
+    btm_ble_clear_resolving_list();
+}
+
+/*******************************************************************************
+**
+** Function         btm_ble_resolving_list_cleanup
+**
+** Description      Cleanup resolving list dynamic memory
+**
+** Parameters
+**
+** Returns          void
+**
+*******************************************************************************/
+void btm_ble_resolving_list_cleanup(void)
+{
+    tBTM_BLE_RESOLVE_Q          *p_q = &btm_cb.ble_ctr_cb.resolving_list_pend_q;
+
+    if (p_q->resolve_q_random_pseudo)
+        GKI_freebuf(p_q->resolve_q_random_pseudo);
+
+    if (p_q->resolve_q_action)
+       GKI_freebuf(p_q->resolve_q_action);
+
+    controller_get_interface()->set_ble_resolving_list_max_size(0);
+}
+#endif
index d3d0481..3053dbe 100644 (file)
@@ -36,7 +36,6 @@
 #include "btm_int.h"
 #include "hcidefs.h"
 #include "l2c_api.h"
-#include "vendor_ble.h"
 
 static tBTM_SEC_DEV_REC *btm_find_oldest_dev (void);
 
@@ -185,9 +184,6 @@ BOOLEAN BTM_SecDeleteDevice (BD_ADDR bd_addr)
     if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
         return(FALSE);
 
-#if BLE_INCLUDED == TRUE && BLE_PRIVACY_SPT == TRUE
-    btm_ble_vendor_irk_list_remove_dev(p_dev_rec);
-#endif
     btm_sec_free_dev (p_dev_rec);
 
     /* Tell controller to get rid of the link key if it has one stored */
index 03ed726..b725fe2 100644 (file)
@@ -174,6 +174,15 @@ static void reset_complete(void *result) {
 
   l2c_link_processs_num_bufs(controller->get_acl_buffer_count_classic());
 #if (BLE_INCLUDED == TRUE)
+
+  /* Set up the BLE privacy settings */
+  if (controller->supports_ble() && controller->supports_ble_privacy() &&
+      controller->get_ble_resolving_list_max_size() > 0) {
+      btm_ble_resolving_list_init (controller->get_ble_resolving_list_max_size());
+      /* set the default random private address timeout */
+      btsnd_hcic_ble_set_rand_priv_addr_timeout(BTM_BLE_PRIVATE_ADDR_INT);
+  }
+
   if (controller->supports_ble()) {
     l2c_link_processs_ble_num_bufs(controller->get_acl_buffer_count_ble());
   }
index 2307051..c680baa 100644 (file)
@@ -2149,6 +2149,9 @@ void btm_process_inq_complete (UINT8 status, UINT8 mode)
         /* Notify caller that the inquiry has completed; (periodic inquiries do not send completion events */
         if (!(p_inq->inq_active & BTM_PERIODIC_INQUIRY_ACTIVE) && p_inq->inqparms.mode == 0)
         {
+#if BLE_INCLUDED == TRUE
+            btm_clear_all_pending_le_entry();
+#endif
             p_inq->state = BTM_INQ_INACTIVE_STATE;
 
             /* Increment so the start of a next inquiry has a new count */
index 37931e7..7d5cac3 100644 (file)
@@ -171,8 +171,11 @@ typedef struct
 
     BD_ADDR                 read_tx_pwr_addr;   /* read TX power target address     */
 
-    tBTM_BLE_LOCAL_ID_KEYS  id_keys;        /* local BLE ID keys                    */
-    BT_OCTET16              er;             /* BLE encryption key                   */
+#define BTM_LE_SUPPORT_STATE_SIZE   8
+UINT8                   le_supported_states[BTM_LE_SUPPORT_STATE_SIZE];
+
+tBTM_BLE_LOCAL_ID_KEYS id_keys; /* local BLE ID keys */
+BT_OCTET16 ble_encryption_key_value; /* BLE encryption key */
 
 #if BTM_BLE_CONFORMANCE_TESTING == TRUE
     BOOLEAN                 no_disc_if_pair_fail;
@@ -182,7 +185,6 @@ typedef struct
     UINT32                  test_local_sign_cntr;
 #endif
 
-
 #endif  /* BLE_INCLUDED */
 
     tBTM_IO_CAP          loc_io_caps;       /* IO capability of the local device */
@@ -440,6 +442,11 @@ typedef struct
 typedef struct
 {
     BT_OCTET16          irk;            /* peer diverified identity root */
+    BT_OCTET16          pltk;           /* peer long term key */
+    BT_OCTET16          pcsrk;          /* peer SRK peer device used to secured sign local data  */
+
+    BT_OCTET16          lltk;           /* local long term key */
+    BT_OCTET16          lcsrk;          /* local SRK peer device used to secured sign local data  */
     BT_OCTET16          ltk;            /* peer long term key */
     BT_OCTET16          csrk;           /* peer SRK peer device used to secured sign local data  */
 
@@ -460,16 +467,18 @@ typedef struct
     tBLE_ADDR_TYPE      ble_addr_type;  /* LE device type: public or random address */
     tBLE_ADDR_TYPE      static_addr_type;   /* static address type */
     BD_ADDR             static_addr;    /* static address */
+
+#define BTM_WHITE_LIST_BIT          0x01
+#define BTM_RESOLVING_LIST_BIT      0x02
+    UINT8               in_controller_list;   /* in controller resolving list or not */
+    UINT8               resolving_list_index;
 #if BLE_PRIVACY_SPT == TRUE
     BD_ADDR             cur_rand_addr;  /* current random address */
 
 #define BTM_BLE_ADDR_PSEUDO         0   /* address index device record */
 #define BTM_BLE_ADDR_RRA            1   /* cur_rand_addr */
-#define BTM_BLE_ADDR_RECONN         2   /* reconnection address */
-#define BTM_BLE_ADDR_STATIC         3   /* static_addr  */
+#define BTM_BLE_ADDR_STATIC         2   /* static_addr  */
     UINT8               active_addr_type;
-
-    BOOLEAN             privacy_enabled;   /* remote device privacy enabled or not */
 #endif
 
 #if SMP_INCLUDED == TRUE
@@ -503,15 +512,15 @@ typedef struct
 #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 /* 0x10 */
-#define BTM_SEC_LINK_KEY_AUTHED 0x20
+#define BTM_SEC_LINK_KEY_AUTHED BTM_SEC_FLAG_LKEY_AUTHED    /* 0x20 */
 #define BTM_SEC_ROLE_SWITCHED   0x40
 #define BTM_SEC_IN_USE          0x80
     /* LE link security flag */
-#define BTM_SEC_LE_AUTHENTICATED   0x0200       /* 0x0200 */
-#define BTM_SEC_LE_ENCRYPTED       0x0400      /* 0x04 */
-#define BTM_SEC_LE_NAME_KNOWN      0x0800
-#define BTM_SEC_LE_LINK_KEY_KNOWN  0x1000       /* 0x10 */
-#define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000
+#define BTM_SEC_LE_AUTHENTICATED   0x0200   /* LE link is encrypted after pairing with MITM */
+#define BTM_SEC_LE_ENCRYPTED       0x0400   /* LE link is encrypted */
+#define BTM_SEC_LE_NAME_KNOWN      0x0800   /* not used */
+#define BTM_SEC_LE_LINK_KEY_KNOWN  0x1000   /* bonded with peer (peer LTK and/or SRK is saved) */
+#define BTM_SEC_LE_LINK_KEY_AUTHED 0x2000   /* pairing is done with MITM */
 
     UINT16           sec_flags;          /* Current device security state      */
 
@@ -519,14 +528,17 @@ typedef struct
     BD_FEATURES     features[HCI_EXT_FEATURES_PAGE_MAX + 1];           /* Features supported by the device */
     UINT8           num_read_pages;
 
-#define BTM_SEC_STATE_IDLE              0
-#define BTM_SEC_STATE_AUTHENTICATING    1
-#define BTM_SEC_STATE_ENCRYPTING        2
-#define BTM_SEC_STATE_GETTING_NAME      3
-#define BTM_SEC_STATE_AUTHORIZING       4
-#define BTM_SEC_STATE_SWITCHING_ROLE    5
-#define BTM_SEC_STATE_DISCONNECTING     6
-#define BTM_SEC_STATE_DELAY_FOR_ENC     7   /* delay to check for encryption to work around controller problems */
+#define BTM_SEC_STATE_IDLE               0
+#define BTM_SEC_STATE_AUTHENTICATING     1
+#define BTM_SEC_STATE_ENCRYPTING         2
+#define BTM_SEC_STATE_GETTING_NAME       3
+#define BTM_SEC_STATE_AUTHORIZING        4
+#define BTM_SEC_STATE_SWITCHING_ROLE     5
+#define BTM_SEC_STATE_DISCONNECTING      6 /* disconnecting BR/EDR */
+#define BTM_SEC_STATE_DELAY_FOR_ENC      7 /* delay to check for encryption to work around */
+                                           /* controller problems */
+#define BTM_SEC_STATE_DISCONNECTING_BLE  8 /* disconnecting BLE */
+#define BTM_SEC_STATE_DISCONNECTING_BOTH 9 /* disconnecting BR/EDR and BLE */
 
     UINT8       sec_state;              /* Operating state                    */
     BOOLEAN     is_originator;          /* TRUE if device is originating connection */
@@ -560,6 +572,11 @@ typedef struct
     tBTM_SEC_BLE        ble;
     tBT_DEVICE_TYPE     device_type;
     tBTM_LE_CONN_PRAMS  conn_params;
+    BOOLEAN             new_encryption_key_is_p256; /* Set to TRUE when the newly generated LK
+                                                    ** is generated from P-256.
+                                                    ** Link encrypted with such LK can be used
+                                                    ** for SM over BR/EDR.
+                                                    */
 #endif
 
 // btla-specific ++
@@ -710,6 +727,7 @@ typedef struct
     void                *p_ref_data;
     UINT32              mx_proto_id;
     UINT32              mx_chan_id;
+    tBT_TRANSPORT       transport;
 } tBTM_SEC_QUEUE_ENTRY;
 
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -847,7 +865,6 @@ typedef struct
 #if  (!defined(BT_TRACE_VERBOSE) || (BT_TRACE_VERBOSE == FALSE))
     char state_temp_buffer[BTM_STATE_BUFFER_SIZE];
 #endif
-
 } tBTM_CB;
 
 
@@ -979,6 +996,10 @@ extern void btm_read_local_name_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);
+extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
+extern BOOLEAN btm_ble_resolving_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern void btm_ble_resolving_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
+extern tBTM_STATUS btm_ble_read_resolving_list_entry(tBTM_SEC_DEV_REC *p_dev_rec);
 #endif  /* BLE_INCLUDED */
 
 /* Vendor Specific Command complete evt handler */
index af76151..db8622e 100644 (file)
@@ -98,6 +98,16 @@ static BOOLEAN btm_dev_encrypted(tBTM_SEC_DEV_REC *p_dev_rec);
 static BOOLEAN btm_dev_authorized(tBTM_SEC_DEV_REC *p_dev_rec);
 static BOOLEAN btm_serv_trusted(tBTM_SEC_DEV_REC *p_dev_rec, tBTM_SEC_SERV_REC *p_serv_rec);
 
+static BOOLEAN btm_sec_queue_encrypt_request  (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+                                         tBTM_SEC_CALLBACK *p_callback, void *p_ref_data);
+static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport) ;
+static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC  *p_dev_rec, tBT_TRANSPORT transport,
+                                            UINT8 encr_enable);
+static BOOLEAN btm_sec_acceptor_rejects_bonding (tBTM_SEC_DEV_REC *p_dev_rec);
+
+static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec);
+static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec);
+
 /* TRUE - authenticated link key is possible */
 static const BOOLEAN btm_sec_io_map [BTM_IO_CAP_MAX][BTM_IO_CAP_MAX] =
 {
@@ -1170,7 +1180,8 @@ tBTM_STATUS BTM_SecBondCancel (BD_ADDR bd_addr)
         if (p_dev_rec->hci_handle != BTM_SEC_INVALID_HANDLE)
         {
             /* If some other thread disconnecting, we do not send second command */
-            if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING)
+            if ((p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING) ||
+                (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH))
                 return(BTM_CMD_STARTED);
 
             /* If the HCI link was set up by Bonding process */
@@ -1230,6 +1241,30 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key)
     return(BTM_UNKNOWN_ADDR);
 }
 
+/*******************************************************************************
+**
+** Function         BTM_SecGetDeviceLinkKeyType
+**
+** Description      This function is called to obtain link key type for the
+**                  device.
+**                  it returns BTM_SUCCESS if link key is available, or
+**                  BTM_UNKNOWN_ADDR if Security Manager does not know about
+**                  the device or device record does not contain link key info
+**
+** Returns          BTM_LKEY_TYPE_IGNORE if link key is unknown, link type
+**                  otherwise.
+**
+*******************************************************************************/
+tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr)
+{
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+
+    if ((p_dev_rec != NULL) && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN))
+    {
+        return p_dev_rec->link_key_type;
+    }
+    return BTM_LKEY_TYPE_IGNORE;
+}
 
 /*******************************************************************************
 **
@@ -1248,8 +1283,8 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key)
 **                  p_ref_data    - pointer to any data the caller wishes to receive
 **                                  in the callback function upon completion.
 *                                   can be set to NULL if not used.
-**                  transport  -    TRUE to encryption the link over LE trasnport
-**                                  or FALSE for BR/EDR trasnport
+**                  transport  -    TRUE to encryption the link over LE transport
+**                                  or FALSE for BR/EDR transport
 **
 ** Returns          BTM_SUCCESS   - already encrypted
 **                  BTM_PENDING   - command will be returned in the callback
@@ -1261,14 +1296,9 @@ tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr, LINK_KEY link_key)
 tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SEC_CBACK *p_callback,
                                void *p_ref_data)
 {
-    tBTM_SEC_DEV_REC  *p_dev_rec;
-    tBTM_STATUS       rc;
-#if BLE_INCLUDED == TRUE
-   tACL_CONN         *p = btm_bda_to_acl(bd_addr, transport);
-#endif
-
-    p_dev_rec = btm_find_dev (bd_addr);
+    tBTM_STATUS rc = 0;
 
+    tBTM_SEC_DEV_REC  *p_dev_rec = btm_find_dev (bd_addr);
     if (!p_dev_rec ||
         (transport == BT_TRANSPORT_BR_EDR && p_dev_rec->hci_handle == BTM_SEC_INVALID_HANDLE)
 #if BLE_INCLUDED == TRUE
@@ -1301,15 +1331,21 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE
         return(BTM_SUCCESS);
     }
 
-    if (p_dev_rec->p_callback)
+    /* enqueue security request if security is active */
+    if (p_dev_rec->p_callback || (p_dev_rec->sec_state != BTM_SEC_STATE_IDLE))
     {
-        /* Connection should be up and runnning */
-        BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy");
-
-        if (p_callback)
-            (*p_callback) (bd_addr, transport, p_ref_data, BTM_BUSY);
+        BTM_TRACE_WARNING ("Security Manager: BTM_SetEncryption busy, enqueue request");
 
-        return(BTM_BUSY);
+        if (btm_sec_queue_encrypt_request(bd_addr, transport, p_callback, p_ref_data))
+        {
+            return BTM_CMD_STARTED;
+        }
+        else
+        {
+            if (p_callback)
+                (*p_callback) (bd_addr, transport, p_ref_data, BTM_NO_RESOURCES);
+            return BTM_NO_RESOURCES;
+        }
     }
 
     p_dev_rec->p_callback        = p_callback;
@@ -1324,11 +1360,19 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     if (transport == BT_TRANSPORT_LE)
     {
-        rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
+        tACL_CONN *p = btm_bda_to_acl(bd_addr, transport);
+        if (p)
+        {
+           rc = btm_ble_set_encryption(bd_addr, p_ref_data, p->link_role);
+        }
+        else
+        {
+            rc = BTM_WRONG_MODE;
+            BTM_TRACE_WARNING("%s: cannot call btm_ble_set_encryption, p is NULL", __FUNCTION__);
+        }
     }
     else
 #endif
-
         rc = btm_sec_execute_procedure (p_dev_rec);
 
     if (rc != BTM_CMD_STARTED && rc != BTM_BUSY)
@@ -1339,6 +1383,7 @@ tBTM_STATUS BTM_SetEncryption (BD_ADDR bd_addr, tBT_TRANSPORT transport, tBTM_SE
             (*p_callback) (bd_addr, transport, p_dev_rec->p_ref_data, rc);
         }
     }
+
     return(rc);
 }
 
@@ -1353,32 +1398,51 @@ static tBTM_STATUS btm_sec_send_hci_disconnect (tBTM_SEC_DEV_REC *p_dev_rec, UIN
     BTM_TRACE_EVENT ("btm_sec_send_hci_disconnect:  handle:0x%x, reason=0x%x",
                       conn_handle, reason);
 
-    /* if some other thread disconnecting, we do not send second command */
-    if (BTM_SEC_STATE_DISCONNECTING != old_state)
+    /* send HCI_Disconnect on a transport only once */
+    switch (old_state)
     {
-        p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING;
+        case BTM_SEC_STATE_DISCONNECTING:
+            if (conn_handle == p_dev_rec->hci_handle)
+                return status;
 
-#if BTM_DISC_DURING_RS == TRUE
-        /* If a Role Switch is in progress, delay the HCI Disconnect to avoid controller problem (4329B1) */
-        if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING &&
-             p_dev_rec->hci_handle == conn_handle)
+            p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
+            break;
 
-        {
-                 BTM_TRACE_DEBUG("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;
-                 status = BTM_SUCCESS;
-        }
-        else
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+        case BTM_SEC_STATE_DISCONNECTING_BLE:
+            if (conn_handle == p_dev_rec->ble_hci_handle)
+                return status;
+
+            p_dev_rec->sec_state = BTM_SEC_STATE_DISCONNECTING_BOTH;
+            break;
+
+        case BTM_SEC_STATE_DISCONNECTING_BOTH:
+            return status;
 #endif
-        /* Tear down the HCI link */
-        if (!btsnd_hcic_disconnect (conn_handle, reason))
-        {
-            /* could not send disconnect. restore old state */
-            p_dev_rec->sec_state = old_state;
-            status = BTM_NO_RESOURCES;
-        }
+
+        default:
+            p_dev_rec->sec_state = (conn_handle == p_dev_rec->hci_handle) ?
+                    BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
+
+            break;
+    }
+
+    /* If a role switch is in progress, delay the HCI Disconnect to avoid controller problem */
+    if (p_dev_rec->rs_disc_pending == BTM_SEC_RS_PENDING && p_dev_rec->hci_handle == conn_handle)
+    {
+        BTM_TRACE_DEBUG("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;
+        status = BTM_SUCCESS;
+    }
+    /* Tear down the HCI link */
+    else if (!btsnd_hcic_disconnect (conn_handle, reason))
+    {
+         /* could not send disconnect. restore old state */
+         p_dev_rec->sec_state = old_state;
+         status = BTM_NO_RESOURCES;
     }
-    return (status);
+
+    return status;
 }
 
 /*******************************************************************************
@@ -1442,8 +1506,6 @@ void BTM_ConfirmReqReply(tBTM_STATUS res, BD_ADDR bd_addr)
 #if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
 void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey)
 {
-    tBTM_SEC_DEV_REC *p_dev_rec;
-
     BTM_TRACE_API ("BTM_PasskeyReqReply: State: %s  res:%d",
                     btm_pair_state_descr(btm_cb.pairing_state), res);
 
@@ -1456,7 +1518,8 @@ void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey)
     /* If timeout already expired or has been canceled, ignore the reply */
     if ( (btm_cb.pairing_state == BTM_PAIR_STATE_WAIT_AUTH_COMPLETE) && (res != BTM_SUCCESS) )
     {
-        if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
+        tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+        if (p_dev_rec != NULL)
         {
             btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
 
@@ -1484,9 +1547,7 @@ void BTM_PasskeyReqReply(tBTM_STATUS res, BD_ADDR bd_addr, UINT32 passkey)
         /* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
         btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
         btsnd_hcic_user_passkey_neg_reply (bd_addr);
-    }
-    else
-    {
+    } else {
         btm_cb.acl_disc_reason = HCI_SUCCESS;
         btsnd_hcic_user_passkey_reply (bd_addr, passkey);
     }
@@ -1585,7 +1646,7 @@ tBTM_STATUS BTM_ReadLocalOobData(void)
 *******************************************************************************/
 void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_OCTET16 r)
 {
-    BTM_TRACE_EVENT ("BTM_RemoteOobDataReply():  State: %s  res:%d",
+    BTM_TRACE_EVENT ("%s() - State: %s res: %d", __func__,
                       btm_pair_state_descr(btm_cb.pairing_state), res);
 
     /* If timeout already expired or has been canceled, ignore the reply */
@@ -1599,9 +1660,7 @@ void BTM_RemoteOobDataReply(tBTM_STATUS res, BD_ADDR bd_addr, BT_OCTET16 c, BT_O
         /* use BTM_PAIR_STATE_WAIT_AUTH_COMPLETE to report authentication failed event */
         btm_cb.acl_disc_reason = HCI_ERR_HOST_REJECT_SECURITY;
         btsnd_hcic_rem_oob_neg_reply (bd_addr);
-    }
-    else
-    {
+    } else {
         btm_cb.acl_disc_reason = HCI_SUCCESS;
         btsnd_hcic_rem_oob_reply (bd_addr, c, r);
     }
@@ -1630,7 +1689,6 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c,
 {
     UINT8   *p = p_data;
     UINT16  len = 0;
-    UINT16  delta;
 #if BTM_MAX_LOC_BD_NAME_LEN > 0
     UINT16  name_size;
     UINT8   name_type = BTM_EIR_SHORTENED_LOCAL_NAME_TYPE;
@@ -1648,7 +1706,7 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c,
         /* now optional part */
 
         /* add Hash C */
-        delta = BTM_OOB_HASH_C_SIZE + 2;
+        UINT16 delta = BTM_OOB_HASH_C_SIZE + 2;
         if (max_len >= delta)
         {
             *p++ = BTM_OOB_HASH_C_SIZE + 1;
@@ -1705,6 +1763,25 @@ UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c,
 
 /*******************************************************************************
 **
+** Function         BTM_IsLeScSuppLocally
+**
+** Description      This function is called to check if LE SC is supported.
+**
+** Parameters:      None.
+**
+** Returns          Boolean - TRUE if LE SC is supported.
+*******************************************************************************/
+BOOLEAN BTM_IsLeScSuppLocally (void)
+{
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+    return TRUE;
+#else
+    return FALSE;
+#endif
+}
+
+/*******************************************************************************
+**
 ** Function         BTM_ReadOobData
 **
 ** Description      This function is called to parse the OOB data payload
@@ -1791,12 +1868,11 @@ void BTM_SetOutService(BD_ADDR bd_addr, UINT8 service_id, UINT32 mx_chan_id)
 {
     tBTM_SEC_DEV_REC *p_dev_rec;
     tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
-    int i;
 
     btm_cb.p_out_serv = p_serv_rec;
     p_dev_rec = btm_find_dev (bd_addr);
 
-    for (i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++)
+    for (int i = 0; i < BTM_SEC_MAX_SERVICE_RECORDS; i++, p_serv_rec++)
     {
         if ((p_serv_rec->security_flags & BTM_SEC_IN_USE)
             && (p_serv_rec->service_id == service_id)
@@ -1835,14 +1911,14 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN
         is_possible = FALSE;
         if(p_dev_rec->p_cur_service)
         {
-        BTM_TRACE_DEBUG ("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);
+            BTM_TRACE_DEBUG ("%s() id: %d, link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x, flags: 0x%x",
+                          __func__, 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);
         }
         else
         {
-            BTM_TRACE_DEBUG ("btm_sec_is_upgrade_possible link_key_typet:%d, rmt_io_caps:%d, chk flags:x%x, ",
-                          p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
+            BTM_TRACE_DEBUG ("%s() link_key_typet: %d, rmt_io_caps: %d, chk flags: 0x%x",
+                          __func__, p_dev_rec->link_key_type, p_dev_rec->rmt_io_caps, mtm_check);
         }
         /* Already have a link key to the connected peer. Is the link key secure enough?
         ** Is a link key upgrade even possible?
@@ -1858,7 +1934,7 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN
             is_possible = TRUE;
         }
     }
-    BTM_TRACE_DEBUG ("btm_sec_is_upgrade_possible is_possible:%d sec_flags:0x%x", is_possible, p_dev_rec->sec_flags);
+    BTM_TRACE_DEBUG ("%s() is_possible: %d sec_flags: 0x%x", __func__, is_possible, p_dev_rec->sec_flags);
     return is_possible;
 }
 
@@ -1874,19 +1950,20 @@ static BOOLEAN btm_sec_is_upgrade_possible(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN
 *******************************************************************************/
 static void btm_sec_check_upgrade(tBTM_SEC_DEV_REC  *p_dev_rec, BOOLEAN is_originator)
 {
-    tBTM_SP_UPGRADE     evt_data;
 
-    BTM_TRACE_DEBUG ("btm_sec_check_upgrade...");
+    BTM_TRACE_DEBUG ("%s()", __func__);
 
     /* 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_DEBUG ("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 */
+        tBTM_SP_UPGRADE evt_data;
         memcpy (evt_data.bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN);
         evt_data.upgrade = TRUE;
         if (btm_cb.api.p_sp_callback)
@@ -1948,11 +2025,11 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
     else
         is_originator = FALSE;
 
-    BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req conn_type:0x%x, 0x%x", conn_type, p_ref_data);
+    BTM_TRACE_DEBUG ("%s() conn_type: 0x%x, 0x%x", __func__, conn_type, p_ref_data);
 #else
     is_originator = conn_type;
 
-    BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req is_originator:%d, 0x%x", is_originator, p_ref_data);
+    BTM_TRACE_DEBUG ("%s() is_originator:%d, 0x%x", __func__, is_originator, p_ref_data);
 #endif
 
     /* Find or get oldest record */
@@ -1966,10 +2043,8 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
     /* If there is no application registered with this PSM do not allow connection */
     if (!p_serv_rec)
     {
-        BTM_TRACE_WARNING ("btm_sec_l2cap_access_req()  PSM:%d no application registerd", psm);
-
+        BTM_TRACE_WARNING ("%s() PSM: %d no application registerd", __func__, psm);
         (*p_callback) (bd_addr, transport, p_ref_data, BTM_MODE_UNSUPPORTED);
-
         return(BTM_MODE_UNSUPPORTED);
     }
 
@@ -1977,7 +2052,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
     if (BT_PSM_SDP == psm)
     {
         (*p_callback) (bd_addr,transport, p_ref_data, BTM_SUCCESS_NO_SECURITY);
-
         return(BTM_SUCCESS);
     }
 #if (L2CAP_UCD_INCLUDED == TRUE)
@@ -2025,7 +2099,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
     /* we will process one after another */
     if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
     {
-        BTM_TRACE_EVENT ("btm_sec_l2cap_access_req() - busy - PSM:%d delayed  state: %s mode:%d, sm4:0x%x",
+        BTM_TRACE_EVENT ("%s() - busy - PSM:%d delayed  state: %s mode:%d, sm4:0x%x", __func__,
                           psm, btm_pair_state_descr(btm_cb.pairing_state), btm_cb.security_mode, p_dev_rec->sm4);
         BTM_TRACE_EVENT ("security_flags:x%x, sec_flags:x%x", security_required, p_dev_rec->sec_flags);
         rc = BTM_CMD_STARTED;
@@ -2064,7 +2138,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
             {
                 if (p_callback)
                     (*p_callback) (bd_addr, transport, (void *)p_ref_data, BTM_SUCCESS);
-
                 return(BTM_SUCCESS);
             }
         }
@@ -2076,7 +2149,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
     /* Save pointer to service record */
     p_dev_rec->p_cur_service = p_serv_rec;
 
-
     /* mess /w security_required in btm_sec_l2cap_access_req for Lisbon */
     if (btm_cb.security_mode == BTM_SEC_MODE_SP)
     {
@@ -2123,7 +2195,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
         }
     }
 
-    BTM_TRACE_DEBUG ("btm_sec_l2cap_access_req()  sm4:0x%x, sec_flags:0x%x, security_required:0x%x chk:%d",
+    BTM_TRACE_DEBUG ("%s()  sm4:0x%x, sec_flags:0x%x, security_required:0x%x chk:%d", __func__,
                       p_dev_rec->sm4, p_dev_rec->sec_flags, security_required, chk_acp_auth_done);
 
     old_security_required        = p_dev_rec->security_required;
@@ -2195,7 +2267,7 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
             p_dev_rec->sec_state         = BTM_SEC_STATE_DELAY_FOR_ENC;
             (*p_callback) (bd_addr, transport, p_ref_data, rc);
 
-            return(BTM_CMD_STARTED);
+            return BTM_SUCCESS;
         }
     }
 
@@ -2218,8 +2290,9 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
         btm_sec_check_upgrade(p_dev_rec, is_originator);
     }
 
-    BTM_TRACE_EVENT ("Security Manager: l2cap_access_req PSM:%d Handle:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
-                      psm, handle, p_dev_rec->sec_state, p_dev_rec->sec_flags, p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
+    BTM_TRACE_EVENT ("%s() PSM:%d Handle:%d State:%d Flags: 0x%x Required: 0x%x Service ID:%d",
+           __func__, psm, handle, p_dev_rec->sec_state, p_dev_rec->sec_flags,
+           p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
 
     if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
     {
@@ -2256,7 +2329,6 @@ tBTM_STATUS btm_sec_l2cap_access_req (BD_ADDR bd_addr, UINT16 psm, UINT16 handle
 tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_originator,
                                        UINT32 mx_proto_id, UINT32 mx_chan_id,
                                        tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
-
 {
     tBTM_SEC_DEV_REC  *p_dev_rec;
     tBTM_SEC_SERV_REC *p_serv_rec;
@@ -2264,7 +2336,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o
     UINT16             security_required;
     BOOLEAN transport   = FALSE;/* should check PSM range in LE connection oriented L2CAP connection */
 
-    BTM_TRACE_DEBUG ("btm_sec_mx_access_request is_originator:%d", is_originator);
+    BTM_TRACE_DEBUG ("%s() is_originator: %d", __func__, is_originator);
     /* Find or get oldest record */
     p_dev_rec = btm_find_or_alloc_dev (bd_addr);
 
@@ -2286,7 +2358,7 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o
     /* we will process one after another */
     if ( (p_dev_rec->p_callback) || (btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) )
     {
-        BTM_TRACE_EVENT ("btm_sec_mx_access_request service PSM:%d Proto:%d SCN:%d delayed  state: %s",
+        BTM_TRACE_EVENT ("%s() service PSM:%d Proto:%d SCN:%d delayed  state: %s", __func__,
                           psm, mx_proto_id, mx_chan_id, btm_pair_state_descr(btm_cb.pairing_state));
 
         rc = BTM_CMD_STARTED;
@@ -2351,15 +2423,15 @@ tBTM_STATUS btm_sec_mx_access_request (BD_ADDR bd_addr, UINT16 psm, BOOLEAN is_o
     /* scn, we need to request user's permission again. */
     p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED);
 
-    BTM_TRACE_EVENT ("Security Manager: mx_access_req proto_id:%d chan_id:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
-                      mx_proto_id, mx_chan_id, p_dev_rec->sec_state, p_dev_rec->sec_flags, p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
+    BTM_TRACE_EVENT ("%s() proto_id:%d chan_id:%d State:%d Flags:0x%x Required:0x%x Service ID:%d",
+                      __func__, mx_proto_id, mx_chan_id, p_dev_rec->sec_state, p_dev_rec->sec_flags,
+                      p_dev_rec->security_required, p_dev_rec->p_cur_service->service_id);
 
     if ((rc = btm_sec_execute_procedure (p_dev_rec)) != BTM_CMD_STARTED)
     {
         if (p_callback)
         {
             p_dev_rec->p_callback = NULL;
-
             (*p_callback) (bd_addr,transport, p_ref_data, (UINT8)rc);
         }
     }
@@ -2551,14 +2623,23 @@ void btm_sec_check_pending_reqs (void)
         while ((p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_dequeue (&bq)) != NULL)
         {
             /* Check that the ACL is still up before starting security procedures */
-            if (btm_bda_to_acl(p_e->bd_addr, BT_TRANSPORT_BR_EDR) != NULL)
+            if (btm_bda_to_acl(p_e->bd_addr, p_e->transport) != NULL)
             {
-                BTM_TRACE_EVENT ("btm_sec_check_pending_reqs() submitting  PSM: 0x%04x  Is_Orig: %u  mx_proto_id: %u  mx_chan_id: %u",
-                                  p_e->psm, p_e->is_orig, p_e->mx_proto_id, p_e->mx_chan_id);
+                if (p_e->psm != 0)
+                {
+                    BTM_TRACE_EVENT("%s PSM:0x%04x Is_Orig:%u mx_proto_id:%u mx_chan_id:%u",
+                                    __FUNCTION__, p_e->psm, p_e->is_orig,
+                                    p_e->mx_proto_id, p_e->mx_chan_id);
 
-                btm_sec_mx_access_request (p_e->bd_addr, p_e->psm, p_e->is_orig,
+                    btm_sec_mx_access_request (p_e->bd_addr, p_e->psm, p_e->is_orig,
                                            p_e->mx_proto_id, p_e->mx_chan_id,
                                            p_e->p_callback, p_e->p_ref_data);
+                }
+                else
+                {
+                    BTM_SetEncryption(p_e->bd_addr, p_e->transport, p_e->p_callback,
+                                      p_e->p_ref_data);
+                }
             }
 
             GKI_freebuf (p_e);
@@ -2577,14 +2658,6 @@ void btm_sec_check_pending_reqs (void)
 *******************************************************************************/
 void btm_sec_init (UINT8 sec_mode)
 {
-#if 0  /* cleared in btm_init; put back in if calling from anywhere else! */
-    int i;
-
-    memset (btm_cb.sec_serv_rec, 0, sizeof (btm_cb.sec_serv_rec));
-    memset (btm_cb.sec_dev_rec, 0, sizeof (btm_cb.sec_dev_rec));
-    memset (&btm_cb.pairing_tle, 0, sizeof(TIMER_LIST_ENT));
-
-#endif
     btm_cb.security_mode = sec_mode;
     memset (btm_cb.pairing_bda, 0xff, BD_ADDR_LEN);
     btm_cb.max_collision_delay = BTM_SEC_MAX_COLLISION_DELAY;
@@ -2602,8 +2675,7 @@ void btm_sec_init (UINT8 sec_mode)
 *******************************************************************************/
 void btm_sec_device_down (void)
 {
-    BTM_TRACE_EVENT ("btm_sec_device_down()  State: %s", btm_pair_state_descr(btm_cb.pairing_state));
-
+    BTM_TRACE_EVENT ("%s() State: %s", __func__, btm_pair_state_descr(btm_cb.pairing_state));
     btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
 }
 
@@ -3706,8 +3778,22 @@ void btm_sec_auth_complete (UINT16 handle, UINT8 status)
                 btm_sec_send_hci_disconnect (p_dev_rec, HCI_ERR_PEER_USER, p_dev_rec->hci_handle);
         }
         else
-            l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
+        {
+            BTM_TRACE_DEBUG ("TRYING TO DECIDE IF CAN USE SMP_BR_CHNL");
+            if (p_dev_rec->new_encryption_key_is_p256 && (btm_sec_use_smp_br_chnl(p_dev_rec)))
+            {
+                BTM_TRACE_DEBUG ("link encrypted afer dedic bonding can use SMP_BR_CHNL");
 
+                if (btm_sec_is_master(p_dev_rec))
+                {
+                    // Encryption is required to start SM over BR/EDR.
+                    // Indicate that this is encryption after authentication.
+                    BTM_SetEncryption(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR, NULL, NULL);
+                }
+            }
+
+            l2cu_start_post_bond_timer (p_dev_rec->hci_handle);
+        }
         return;
     }
 
@@ -3820,18 +3906,62 @@ void btm_sec_encrypt_change (UINT16 handle, UINT8 status, UINT8 encr_enable)
     if (acl_idx != MAX_L2CAP_LINKS )
         p_acl = &btm_cb.acl_db[acl_idx];
 
+    btm_sec_check_pending_enc_req (p_dev_rec, p_acl->transport, encr_enable);
+
     if (p_acl && p_acl->transport == BT_TRANSPORT_LE)
     {
-        if (status == HCI_ERR_KEY_MISSING || status == HCI_ERR_AUTH_FAILURE
-            ||status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
+        if (status == HCI_ERR_KEY_MISSING ||
+            status == HCI_ERR_AUTH_FAILURE ||
+            status == HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE)
+        {
             p_dev_rec->sec_flags &= ~ (BTM_SEC_LE_LINK_KEY_KNOWN);
+            p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
+        }
         btm_ble_link_encrypted(p_dev_rec->bd_addr, encr_enable);
         return;
     }
     else
         /* BR/EDR connection, update the encryption key size to be 16 as always */
         p_dev_rec->enc_key_size = 16;
-#endif
+
+    BTM_TRACE_DEBUG ("in btm_sec_encrypt_change new_encr_key_256 is %d",
+                       p_dev_rec->new_encryption_key_is_p256);
+
+    if ((status == HCI_SUCCESS) && encr_enable && (p_dev_rec->hci_handle == handle))
+    {
+        if (p_dev_rec->new_encryption_key_is_p256)
+        {
+            if (btm_sec_use_smp_br_chnl(p_dev_rec) &&
+                btm_sec_is_master(p_dev_rec))
+            {
+                /* BR/EDR is encrypted with LK that can be used to derive LE LTK */
+                p_dev_rec->new_encryption_key_is_p256 = FALSE;
+
+                BTM_TRACE_DEBUG ("btm_sec_encrypt_change start SM over BR/EDR");
+                SMP_BR_PairWith(p_dev_rec->bd_addr);
+            }
+        }
+        else
+        {   /* BR/EDR is successfully encrypted. Correct LK type if needed
+              (BR/EDR LK derived from LE LTK was used for encryption) */
+            if ((encr_enable == 1)  && /* encryption is ON for SSP */
+                /* LK type is for BR/EDR SC */
+                (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256 ||
+                 p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
+            {
+                if (p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256)
+                    p_dev_rec->link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
+                else /* BTM_LKEY_TYPE_AUTH_COMB_P_256 */
+                    p_dev_rec->link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
+
+                BTM_TRACE_DEBUG("updated link key type to %d", p_dev_rec->link_key_type);
+                btm_send_link_key_notif(p_dev_rec);
+            }
+        }
+    }
+#else
+    btm_sec_check_pending_enc_req (p_dev_rec, BT_TRANSPORT_BR_EDR, encr_enable);
+#endif /* BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE */
 
     /* If this encryption was started by peer do not need to do anything */
     if (p_dev_rec->sec_state != BTM_SEC_STATE_ENCRYPTING)
@@ -4316,6 +4446,14 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
         p_dev_rec->sec_flags &= ~(BTM_SEC_AUTHORIZED | BTM_SEC_AUTHENTICATED | BTM_SEC_ENCRYPTED | BTM_SEC_ROLE_SWITCHED);
     }
 
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+    if (p_dev_rec->sec_state == BTM_SEC_STATE_DISCONNECTING_BOTH)
+    {
+        p_dev_rec->sec_state = (transport == BT_TRANSPORT_LE) ?
+                                BTM_SEC_STATE_DISCONNECTING : BTM_SEC_STATE_DISCONNECTING_BLE;
+        return;
+    }
+#endif
     p_dev_rec->sec_state  = BTM_SEC_STATE_IDLE;
     p_dev_rec->security_required = BTM_SEC_NONE;
 
@@ -4345,12 +4483,19 @@ void btm_sec_disconnected (UINT16 handle, UINT8 reason)
 void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_type)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_or_alloc_dev (p_bda);
-    BOOLEAN          we_are_bonding = FALSE;
+    BOOLEAN         we_are_bonding = FALSE;
+    BOOLEAN         ltk_derived_lk  = FALSE;
 
     BTM_TRACE_EVENT ("btm_sec_link_key_notification()  BDA:%04x%08x, TYPE: %d",
                       (p_bda[0]<<8)+p_bda[1], (p_bda[2]<<24)+(p_bda[3]<<16)+(p_bda[4]<<8)+p_bda[5],
                       key_type);
 
+    if ((key_type >= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_COMBINATION) &&
+        (key_type <= BTM_LTK_DERIVED_LKEY_OFFSET + BTM_LKEY_TYPE_AUTH_COMB_P_256))
+    {
+        ltk_derived_lk = TRUE;
+        key_type -= BTM_LTK_DERIVED_LKEY_OFFSET;
+    }
     /* If connection was made to do bonding restore link security if changed */
     btm_restore_mode();
 
@@ -4373,13 +4518,39 @@ void btm_sec_link_key_notification (UINT8 *p_bda, UINT8 *p_link_key, UINT8 key_t
             btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE);
     }
 
+    /* save LTK derived LK no matter what */
+    if (ltk_derived_lk)
+    {
+        if (btm_cb.api.p_link_key_callback)
+        {
+                BTM_TRACE_DEBUG ("%s() Save LTK derived LK (key_type = %d)",
+                                  __FUNCTION__, p_dev_rec->link_key_type);
+                (*btm_cb.api.p_link_key_callback) (p_bda, p_dev_rec->dev_class,
+                                                   p_dev_rec->sec_bd_name,
+                                                   p_link_key, p_dev_rec->link_key_type);
+        }
+    }
+#if BTM_CROSS_TRANSP_KEY_DERIVATION == TRUE
+    else
+    {
+        if ((p_dev_rec->link_key_type == BTM_LKEY_TYPE_UNAUTH_COMB_P_256) ||
+            (p_dev_rec->link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256))
+        {
+             p_dev_rec->new_encr_key_256 = TRUE;
+             BTM_TRACE_DEBUG ("%s set new_encr_key_256 to %d",
+                               __func__, p_dev_rec->new_encr_key_256);
+        }
+    }
+#endif
+
     /* If name is not known at this point delay calling callback until the name is   */
     /* resolved. Unless it is a HID Device and we really need to send all link keys. */
     if ((!(p_dev_rec->sec_flags & BTM_SEC_NAME_KNOWN)
         &&  ((p_dev_rec->dev_class[1] & BTM_COD_MAJOR_CLASS_MASK) != BTM_COD_MAJOR_PERIPHERAL)) )
     {
         BTM_TRACE_EVENT ("btm_sec_link_key_notification()  Delayed BDA: %08x%04x Type:%d",
-                          (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3], (p_bda[4] << 8) + p_bda[5], key_type);
+                          (p_bda[0]<<24) + (p_bda[1]<<16) + (p_bda[2]<<8) + p_bda[3],
+                          (p_bda[4] << 8) + p_bda[5], key_type);
 
         p_dev_rec->link_key_not_sent = TRUE;
 
@@ -5147,7 +5318,7 @@ static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
     tBTM_SEC_SERV_REC *p_serv_rec = &btm_cb.sec_serv_rec[0];
     int i;
 
-    BTM_TRACE_DEBUG ("btm_sec_find_mx_serv");
+    BTM_TRACE_DEBUG ("%s()", __func__);
     if (is_originator && p_out_serv && p_out_serv->psm == psm
         && p_out_serv->mx_proto_id == mx_proto_id
         && p_out_serv->orig_mx_chan_id == mx_chan_id)
@@ -5185,13 +5356,12 @@ static tBTM_SEC_SERV_REC *btm_sec_find_mx_serv (UINT8 is_originator, UINT16 psm,
 *******************************************************************************/
 static void btm_sec_collision_timeout (TIMER_LIST_ENT *p_tle)
 {
-    tBTM_STATUS status;
     UNUSED(p_tle);
 
-    BTM_TRACE_EVENT ("btm_sec_collision_timeout()");
+    BTM_TRACE_EVENT ("%s()", __func__);
     btm_cb.sec_collision_tle.param = 0;
 
-    status = btm_sec_execute_procedure (btm_cb.p_collided_dev_rec);
+    tBTM_STATUS status = btm_sec_execute_procedure (btm_cb.p_collided_dev_rec);
 
     /* If result is pending reply from the user or from the device is pending */
     if (status != BTM_CMD_STARTED)
@@ -5232,16 +5402,10 @@ static void btm_send_link_key_notif (tBTM_SEC_DEV_REC *p_dev_rec)
 *******************************************************************************/
 UINT32 * BTM_ReadTrustedMask (BD_ADDR bd_addr)
 {
-    tBTM_SEC_DEV_REC *p_dev_rec;
-
-    if ((p_dev_rec = btm_find_dev (bd_addr)) != NULL)
-    {
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (bd_addr);
+    if (p_dev_rec != NULL)
         return(p_dev_rec->trusted_mask);
-    }
-    else
-    {
-        return NULL;
-    }
+    return NULL;
 }
 
 /*******************************************************************************
@@ -5260,7 +5424,7 @@ static void btm_restore_mode(void)
     if (btm_cb.security_mode_changed)
     {
         btm_cb.security_mode_changed = FALSE;
-        BTM_TRACE_DEBUG("btm_restore_mode: Authen Enable -> %d", (btm_cb.security_mode == BTM_SEC_MODE_LINK));
+        BTM_TRACE_DEBUG("%s() Auth enable -> %d", __func__, (btm_cb.security_mode == BTM_SEC_MODE_LINK));
         btsnd_hcic_write_auth_enable ((UINT8)(btm_cb.security_mode == BTM_SEC_MODE_LINK));
     }
 
@@ -5285,9 +5449,8 @@ static void btm_restore_mode(void)
 tBTM_SEC_DEV_REC *btm_sec_find_dev_by_sec_state (UINT8 state)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = &btm_cb.sec_dev_rec[0];
-    int i;
 
-    for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
+    for (int i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i++, p_dev_rec++)
     {
         if ((p_dev_rec->sec_flags & BTM_SEC_IN_USE)
             && (p_dev_rec->sec_state == state))
@@ -5307,8 +5470,9 @@ static void btm_sec_change_pairing_state (tBTM_PAIRING_STATE new_state)
 {
     tBTM_PAIRING_STATE  old_state = btm_cb.pairing_state;
 
-    BTM_TRACE_EVENT ("btm_sec_change_pairing_state  Old: %s",  btm_pair_state_descr(btm_cb.pairing_state));
-    BTM_TRACE_EVENT ("btm_sec_change_pairing_state  New: %s pairing_flags:0x%x",btm_pair_state_descr(new_state), btm_cb.pairing_flags);
+    BTM_TRACE_EVENT ("%s()  Old: %s", __func__, btm_pair_state_descr(btm_cb.pairing_state));
+    BTM_TRACE_EVENT ("%s()  New: %s pairing_flags:0x%x", __func__,
+            btm_pair_state_descr(new_state), btm_cb.pairing_flags);
 
     btm_cb.pairing_state = new_state;
 
@@ -5376,7 +5540,6 @@ static char *btm_pair_state_descr (tBTM_PAIRING_STATE state)
 }
 #endif
 
-
 /*******************************************************************************
 **
 ** Function         btm_sec_dev_rec_cback_event
@@ -5395,10 +5558,9 @@ void btm_sec_dev_rec_cback_event (tBTM_SEC_DEV_REC *p_dev_rec, UINT8 res, BOOLEA
     if (p_dev_rec->p_callback)
     {
         p_dev_rec->p_callback = NULL;
-
         (*p_callback) (p_dev_rec->bd_addr, transport, p_dev_rec->p_ref_data, res);
-
     }
+
     btm_sec_check_pending_reqs();
 }
 
@@ -5413,9 +5575,7 @@ static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr,  UINT16 psm,  BOOLEAN
                                          UINT32 mx_proto_id, UINT32 mx_chan_id,
                                          tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
 {
-    tBTM_SEC_QUEUE_ENTRY    *p_e;
-
-    p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf (sizeof(tBTM_SEC_QUEUE_ENTRY));
+    tBTM_SEC_QUEUE_ENTRY *p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf (sizeof(tBTM_SEC_QUEUE_ENTRY));
 
     if (p_e)
     {
@@ -5425,11 +5585,12 @@ static BOOLEAN btm_sec_queue_mx_request (BD_ADDR bd_addr,  UINT16 psm,  BOOLEAN
         p_e->p_ref_data     = p_ref_data;
         p_e->mx_proto_id    = mx_proto_id;
         p_e->mx_chan_id     = mx_chan_id;
+        p_e->transport      = BT_TRANSPORT_BR_EDR;
 
         memcpy (p_e->bd_addr, bd_addr, BD_ADDR_LEN);
 
-        BTM_TRACE_EVENT ("btm_sec_queue_mx_request() PSM: 0x%04x  Is_Orig: %u  mx_proto_id: %u  mx_chan_id: %u",
-                          psm, is_orig, mx_proto_id, mx_chan_id);
+        BTM_TRACE_EVENT ("%s() PSM: 0x%04x  Is_Orig: %u  mx_proto_id: %u  mx_chan_id: %u",
+                          __func__, psm, is_orig, mx_proto_id, mx_chan_id);
 
         GKI_enqueue (&btm_cb.sec_pending_q, p_e);
 
@@ -5448,7 +5609,8 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC  *p_dev_rec)
     if ((major == BTM_COD_MAJOR_AUDIO)
         &&  ((minor == BTM_COD_MINOR_CONFM_HANDSFREE) || (minor == BTM_COD_MINOR_CAR_AUDIO)) )
     {
-        BTM_TRACE_EVENT ("btm_sec_check_prefetch_pin: Skipping pre-fetch PIN for carkit COD Major: 0x%02x Minor: 0x%02x", major, minor);
+        BTM_TRACE_EVENT ("%s() Skipping pre-fetch PIN for carkit COD Major: 0x%02x Minor: 0x%02x",
+            __func__, major, minor);
 
         if (btm_cb.security_mode_changed == FALSE)
         {
@@ -5473,7 +5635,7 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC  *p_dev_rec)
             /* pin was not supplied - pre-fetch pin code now */
             if (btm_cb.api.p_pin_callback && ((btm_cb.pairing_flags & BTM_PAIR_FLAGS_PIN_REQD) == 0))
             {
-                BTM_TRACE_DEBUG("btm_sec_check_prefetch_pin: PIN code callback called");
+                BTM_TRACE_DEBUG("%s() PIN code callback called", __func__);
                 if (btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR) == NULL)
                 btm_cb.pairing_flags |= BTM_PAIR_FLAGS_PIN_REQD;
                 (btm_cb.api.p_pin_callback) (p_dev_rec->bd_addr, p_dev_rec->dev_class, p_dev_rec->sec_bd_name);
@@ -5486,6 +5648,137 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC  *p_dev_rec)
     return rv;
 }
 
+/*******************************************************************************
+**
+** Function         btm_sec_auth_payload_tout
+**
+** Description      Processes the HCI Autheniticated Payload Timeout Event
+**                  indicating that a packet containing a valid MIC on the
+**                  connection handle was not received within the programmed
+**                  timeout value. (Spec Default is 30 secs, but can be
+**                  changed via the BTM_SecSetAuthPayloadTimeout() function.
+**
+*******************************************************************************/
+void btm_sec_auth_payload_tout (UINT8 *p, UINT16 hci_evt_len)
+{
+    UINT16 handle;
+
+    STREAM_TO_UINT16 (handle, p);
+    handle = HCID_GET_HANDLE (handle);
+
+    /* Will be exposed to upper layers in the future if/when determined necessary */
+    BTM_TRACE_ERROR ("%s on handle 0x%02x", __func__, handle);
+}
+
+/*******************************************************************************
+**
+** Function         btm_sec_queue_encrypt_request
+**
+** Description      encqueue encryption request when device has active security
+**                  process pending.
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_queue_encrypt_request (BD_ADDR bd_addr, tBT_TRANSPORT transport,
+                                         tBTM_SEC_CALLBACK *p_callback, void *p_ref_data)
+{
+    tBTM_SEC_QUEUE_ENTRY  *p_e;
+    p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getbuf(sizeof(tBTM_SEC_QUEUE_ENTRY) + 1);
+
+    if (p_e)
+    {
+        p_e->psm  = 0;  /* if PSM 0, encryption request */
+        p_e->p_callback  = p_callback;
+        p_e->p_ref_data = (void *)(p_e + 1);
+        *(UINT8 *)p_e->p_ref_data = *(UINT8 *)(p_ref_data);
+        p_e->transport  = transport;
+        memcpy(p_e->bd_addr, bd_addr, BD_ADDR_LEN);
+        GKI_enqueue(&btm_cb.sec_pending_q, p_e);
+        return TRUE;
+    }
+
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_sec_clean_pending_req_queue
+**
+** Description      This function cleans up the pending security request when the
+**                  link to the target device dropped.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_sec_clean_pending_req_queue (BD_ADDR remote_bda, tBT_TRANSPORT transport)
+{
+    tBTM_SEC_QUEUE_ENTRY    *p_e;
+    BUFFER_Q                *bq = &btm_cb.sec_pending_q;
+
+    p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
+
+    if (p_e != NULL)
+    {
+        if (memcmp(p_e->bd_addr, remote_bda, BD_ADDR_LEN) == 0
+#if BLE_INCLUDED == TRUE
+            && p_e->transport == transport
+#endif
+            )
+        {
+            (*p_e->p_callback) (remote_bda, transport, p_e->p_ref_data, BTM_ERR_PROCESSING);
+            GKI_remove_from_queue(bq, (void *)p_e);
+        }
+        p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
+    }
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         btm_sec_check_pending_enc_req
+**
+** Description      This function is called to send pending encryption callback if
+**                  waiting
+**
+** Returns          void
+**
+*******************************************************************************/
+static void btm_sec_check_pending_enc_req (tBTM_SEC_DEV_REC  *p_dev_rec, tBT_TRANSPORT transport,
+                                            UINT8 encr_enable)
+{
+    tBTM_SEC_QUEUE_ENTRY    *p_e;
+    BUFFER_Q                *bq = &btm_cb.sec_pending_q;
+    UINT8                   res = encr_enable ? BTM_SUCCESS : BTM_ERR_PROCESSING;
+    UINT8                   sec_act ;
+
+    p_e = (tBTM_SEC_QUEUE_ENTRY *)GKI_getfirst(bq);
+
+    while (p_e != NULL)
+    {
+        if (memcmp(p_e->bd_addr, p_dev_rec->bd_addr, BD_ADDR_LEN) == 0 && p_e->psm == 0
+#if BLE_INCLUDED == TRUE
+            && p_e->transport == transport
+#endif
+            )
+        {
+            sec_act = *(UINT8 *)(p_e->p_ref_data);
+
+            if (encr_enable == 0 || transport == BT_TRANSPORT_BR_EDR
+#if BLE_INCLUDED == TRUE
+                || (sec_act == BTM_BLE_SEC_ENCRYPT || sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
+                || (sec_act == BTM_BLE_SEC_ENCRYPT_MITM && p_dev_rec->sec_flags
+                    & BTM_SEC_LE_AUTHENTICATED)
+#endif
+               )
+            {
+                (*p_e->p_callback) (p_dev_rec->bd_addr, transport, p_e->p_ref_data, res);
+                GKI_remove_from_queue(bq, (void *)p_e);
+            }
+        }
+        p_e = (tBTM_SEC_QUEUE_ENTRY *) GKI_getnext ((void *)p_e);
+    }
+    return;
+}
+
 #if (BLE_INCLUDED == TRUE)
 /*******************************************************************************
 **
@@ -5501,12 +5794,15 @@ static BOOLEAN btm_sec_check_prefetch_pin (tBTM_SEC_DEV_REC  *p_dev_rec)
 void btm_sec_clear_ble_keys (tBTM_SEC_DEV_REC  *p_dev_rec)
 {
 
-    BTM_TRACE_DEBUG ("btm_sec_clear_ble_keys: Clearing BLE Keys");
+    BTM_TRACE_DEBUG ("%s() Clearing BLE Keys", __func__);
 #if (SMP_INCLUDED== TRUE)
-    p_dev_rec->ble.key_type = 0;
+    p_dev_rec->ble.key_type = BTM_LE_KEY_NONE;
     memset (&p_dev_rec->ble.keys, 0, sizeof(tBTM_SEC_BLE_KEYS));
+
+#if (BLE_PRIVACY_SPT == TRUE)
+    btm_ble_resolving_list_remove_dev(p_dev_rec);
+#endif
 #endif
-    gatt_delete_dev_from_srv_chg_clt_list(p_dev_rec->bd_addr);
 }
 
 
@@ -5533,7 +5829,7 @@ BOOLEAN btm_sec_is_a_bonded_dev (BD_ADDR bda)
     {
         is_bonded = TRUE;
     }
-    BTM_TRACE_DEBUG ("btm_sec_is_a_bonded_dev is_bonded=%d", is_bonded);
+    BTM_TRACE_DEBUG ("%s() is_bonded=%d", __func__, is_bonded);
     return(is_bonded);
 }
 
@@ -5593,9 +5889,62 @@ BOOLEAN btm_sec_find_bonded_dev (UINT8 start_idx, UINT8 *p_found_idx, tBTM_SEC_D
             break;
         }
     }
-    BTM_TRACE_DEBUG ("btm_sec_find_bonded_dev=%d", found);
+    BTM_TRACE_DEBUG ("%s() found=%d", __func__, found);
 #endif
     return(found);
 }
+
+
+/*******************************************************************************
+**
+** Function         btm_sec_use_smp_br_chnl
+**
+** Description      The function checks if SMP BR connection can be used with
+**                  the peer.
+**                  Is called when authentication for dedicated bonding is
+**                  successfully completed.
+**
+** Returns          TRUE - if SMP BR connection can be used (the link key is
+**                         generated from P-256 and the peer supports Security
+**                         Manager over BR).
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_use_smp_br_chnl(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    UINT32  ext_feat;
+    UINT8   chnl_mask[L2CAP_FIXED_CHNL_ARRAY_SIZE];
+
+    BTM_TRACE_DEBUG ("%s() link_key_type = 0x%x", __func__,
+                      p_dev_rec->link_key_type);
+
+    if ((p_dev_rec->link_key_type != BTM_LKEY_TYPE_UNAUTH_COMB_P_256) &&
+        (p_dev_rec->link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256))
+         return FALSE;
+
+    if (!L2CA_GetPeerFeatures (p_dev_rec->bd_addr, &ext_feat, chnl_mask))
+        return FALSE;
+
+    if (!(chnl_mask[0] & L2CAP_FIXED_CHNL_SMP_BR_BIT))
+        return FALSE;
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         btm_sec_is_master
+**
+** Description      The function checks if the device is BR/EDR master after
+**                  pairing is completed.
+**
+** Returns          TRUE - if the device is master.
+**
+*******************************************************************************/
+static BOOLEAN btm_sec_is_master(tBTM_SEC_DEV_REC *p_dev_rec)
+{
+    tACL_CONN *p= btm_bda_to_acl(p_dev_rec->bd_addr, BT_TRANSPORT_BR_EDR);
+    return (p && (p->link_role == BTM_ROLE_MASTER));
+}
+
 #endif /* BLE_INCLUDED */
 
index c8a45d3..4477dff 100644 (file)
@@ -122,6 +122,10 @@ static void btu_hcif_encryption_key_refresh_cmpl_evt (UINT8 *p);
 #if (BLE_LLT_INCLUDED == TRUE)
 static void btu_ble_rc_param_req_evt(UINT8 *p);
 #endif
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+static void btu_ble_proc_enhanced_conn_cmpl (UINT8 *p, UINT16 evt_len);
+#endif
+
     #endif
 
 /*******************************************************************************
@@ -318,6 +322,11 @@ void btu_hcif_process_event (UNUSED_ATTR UINT8 controller_id, BT_HDR *p_msg)
                 case HCI_BLE_LTK_REQ_EVT: /* received only at slave device */
                     btu_ble_proc_ltk_req(p);
                     break;
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+                case HCI_BLE_ENHANCED_CONN_COMPLETE_EVT:
+                    btu_ble_proc_enhanced_conn_cmpl(p, hci_evt_len);
+                    break;
+#endif
 #if (BLE_LLT_INCLUDED == TRUE)
                case HCI_BLE_RC_PARAM_REQ_EVT:
                     btu_ble_rc_param_req_evt(p);
@@ -892,6 +901,29 @@ static void btu_hcif_hdl_command_complete (UINT16 opcode, UINT8 *p, UINT16 evt_l
         case HCI_BLE_TEST_END:
             btm_ble_test_command_complete(p);
             break;
+
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+        case HCI_BLE_ADD_DEV_RESOLVING_LIST:
+            btm_ble_add_resolving_list_entry_complete(p, evt_len);
+            break;
+
+        case HCI_BLE_RM_DEV_RESOLVING_LIST:
+            btm_ble_remove_resolving_list_entry_complete(p, evt_len);
+            break;
+
+        case HCI_BLE_CLEAR_RESOLVING_LIST:
+            btm_ble_clear_resolving_list_complete(p, evt_len);
+            break;
+
+        case HCI_BLE_READ_RESOLVABLE_ADDR_PEER:
+             btm_ble_read_resolving_list_entry_complete(p, evt_len);
+             break;
+
+        case HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL:
+        case HCI_BLE_SET_ADDR_RESOLUTION_ENABLE:
+        case HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT:
+            break;
+#endif
 #endif /* (BLE_INCLUDED == TRUE) */
 
         default:
@@ -1648,9 +1680,14 @@ static void btu_ble_process_adv_pkt (UINT8 *p)
 
 static void btu_ble_ll_conn_complete_evt ( UINT8 *p, UINT16 evt_len)
 {
-    btm_ble_conn_complete(p, evt_len);
+    btm_ble_conn_complete(p, evt_len, FALSE);
 }
-
+#if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE)
+static void btu_ble_proc_enhanced_conn_cmpl( UINT8 *p, UINT16 evt_len)
+{
+    btm_ble_conn_complete(p, evt_len, TRUE);
+}
+#endif
 static void btu_ble_ll_conn_param_upd_evt (UINT8 *p, UINT16 evt_len)
 {
     /* LE connection update has completed successfully as a master. */
index 78a7819..a102b06 100644 (file)
@@ -31,8 +31,6 @@
 
 #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)
 #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 */
@@ -133,7 +119,7 @@ tGAP_CLCB *gap_ble_find_clcb_by_conn_id(UINT16 conn_id)
 ** Returns           NULL if not found. Otherwise pointer to the connection link block.
 **
 *******************************************************************************/
-tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
+tGAP_CLCB *gap_clcb_alloc (BD_ADDR bda)
 {
     UINT8         i_clcb = 0;
     tGAP_CLCB    *p_clcb = NULL;
@@ -142,9 +128,8 @@ tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
     {
         if (!p_clcb->in_use)
         {
-            p_clcb->in_use      = TRUE;
-            p_clcb->conn_id     = conn_id;
-            p_clcb->connected   = TRUE;
+            memset(p_clcb, 0, sizeof(tGAP_CLCB));
+            p_clcb->in_use = TRUE;
             memcpy (p_clcb->bda, bda, BD_ADDR_LEN);
             break;
         }
@@ -154,67 +139,75 @@ tGAP_CLCB *gap_clcb_alloc (UINT16 conn_id, BD_ADDR bda)
 
 /*******************************************************************************
 **
-** Function         gap_find_alloc_clcb
+** Function         gap_ble_dealloc_clcb
 **
-** Description      The function find or allocates a GAP  connection link control block
+** Description      The function clean up the pending request queue in GAP
 **
-** Returns           NULL if not found. Otherwise pointer to the connection link block.
+** Returns          none
 **
 *******************************************************************************/
-tGAP_CLCB *gap_find_alloc_clcb (UINT16 conn_id, BD_ADDR bda)
+void gap_ble_dealloc_clcb(tGAP_CLCB *p_clcb)
 {
-    UINT8         i_clcb = 0;
-    tGAP_CLCB    *p_clcb = NULL;
+    tGAP_BLE_REQ    *p_q;
 
-    for (i_clcb = 0, p_clcb= gap_cb.clcb; i_clcb < GAP_MAX_CL; i_clcb++, p_clcb++)
+    while((p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q)) != NULL)
     {
-        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;
-        }
+         /* send callback to all pending requests if being removed*/
+         if (p_q->p_cback != NULL)
+            (*p_q->p_cback)(FALSE, p_clcb->bda, 0, NULL);
+
+         GKI_freebuf (p_q);
     }
-    return p_clcb;
+
+    memset(p_clcb, 0, sizeof(tGAP_CLCB));
 }
 
 /*******************************************************************************
 **
-** Function         gap_get_conn_id_if_connected
+** Function         gap_ble_enqueue_request
 **
-** Description      This function returns a connecttion handle to a ATT server
-**                  if the server is already connected
+** Description      The function enqueue a GAP client request
 **
-** Parameters       client_if: client interface.
-**                  bd_addr: peer device address.
-**
-** Returns          Connection handle or invalid handle value
+** Returns           TRUE is successul; FALSE otherwise
 **
 *******************************************************************************/
-UINT16 gap_get_conn_id_if_connected (BD_ADDR bd_addr)
+BOOLEAN gap_ble_enqueue_request (tGAP_CLCB *p_clcb, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
 {
-    tGAP_CLCB       *p_clcb;
-    UINT16          i;
-
-    GAP_TRACE_EVENT ("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]);
+    tGAP_BLE_REQ  *p_q = (tGAP_BLE_REQ *)GKI_getbuf(sizeof(tGAP_BLE_REQ));
 
-    for (i = 0, p_clcb = gap_cb.clcb; i < GAP_MAX_CL; i++, p_clcb++)
+    if (p_q != NULL)
     {
-        if (p_clcb->in_use && p_clcb->connected && !memcmp(p_clcb->bda, bd_addr,  BD_ADDR_LEN) )
-        {
-            return(p_clcb->conn_id);
-        }
+        p_q->p_cback = p_cback;
+        p_q->uuid = uuid;
+        GKI_enqueue(&p_clcb->pending_req_q, p_q);
+        return TRUE;
     }
 
-    /* If here, failed to allocate a client control block */
-    GATT_TRACE_DEBUG ("gap_get_conn_id_if_connected: not connected");
-    return(GATT_INVALID_CONN_ID);
+    return FALSE;
 }
+/*******************************************************************************
+**
+** Function         gap_ble_dequeue_request
+**
+** Description      The function dequeue a GAP client request if any
+**
+** Returns           TRUE is successul; FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN gap_ble_dequeue_request (tGAP_CLCB *p_clcb, UINT16 * p_uuid, tGAP_BLE_CMPL_CBACK **p_cback)
+{
+    tGAP_BLE_REQ *p_q = (tGAP_BLE_REQ *)GKI_dequeue(&p_clcb->pending_req_q);;
 
+    if (p_q != NULL)
+    {
+        *p_cback    = p_q->p_cback;
+        *p_uuid     = p_q->uuid;
+        GKI_freebuf((void *)p_q);
+        return TRUE;
+    }
+
+    return FALSE;
+}
 
 /*******************************************************************************
 **   GAP Attributes Database Request callback
@@ -266,6 +259,12 @@ tGATT_STATUS gap_read_attr_value (UINT16 handle, tGATT_VALUE *p_value, BOOLEAN i
                     UINT16_TO_STREAM(p, p_db_attr->attr_value.conn_param.sp_tout);  /* sp_tout */
                     p_value->len =8;
                     break;
+
+                /* address resolution */
+                case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+                    UINT8_TO_STREAM(p, p_db_attr->attr_value.addr_resolution);
+                    p_value->len =1;
+                    break;
             }
             return GATT_SUCCESS;
         }
@@ -430,6 +429,14 @@ void gap_attr_db_init(void)
     p_db_attr ++;
 #endif
 
+    /* add Central address resolution Characteristic */
+    uuid.len = LEN_UUID_16;
+    uuid.uu.uuid16 = p_db_attr->uuid = GATT_UUID_GAP_CENTRAL_ADDR_RESOL;
+    p_db_attr->handle = GATTS_AddCharacteristic(service_handle, &uuid,
+                                                GATT_PERM_READ, GATT_CHAR_PROP_BIT_READ);
+    p_db_attr->attr_value.addr_resolution = 0;
+    p_db_attr++;
+
     /* start service now */
     memset (&app_uuid.uu.uuid128, 0x81, LEN_UUID_128);
 
@@ -471,13 +478,18 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
                 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));
+                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;
 
+            case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+                p_db_attr->attr_value.addr_resolution = p_value->addr_resolution;
+                break;
+
             }
             break;
         }
@@ -488,6 +500,41 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
 
 /*******************************************************************************
 **
+** Function         gap_ble_send_cl_read_request
+**
+** Description      utility function to send a read request for a GAP charactersitic
+**
+** Returns          TRUE if read started, else FALSE if GAP is busy
+**
+*******************************************************************************/
+BOOLEAN gap_ble_send_cl_read_request(tGAP_CLCB *p_clcb)
+{
+    tGATT_READ_PARAM        param;
+    UINT16                  uuid = 0;
+    BOOLEAN                 started = FALSE;
+
+    if (gap_ble_dequeue_request(p_clcb, &uuid, &p_clcb->p_cback))
+    {
+        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)
+        {
+            p_clcb->cl_op_uuid = uuid;
+            started = TRUE;
+        }
+    }
+
+    return started;
+}
+
+/*******************************************************************************
+**
 ** Function         gap_ble_cl_op_cmpl
 **
 ** Description      GAP client operation complete callback
@@ -497,7 +544,7 @@ void GAP_BleAttrDBUpdate(UINT16 attr_uuid, tGAP_BLE_ATTR_VALUE *p_value)
 *******************************************************************************/
 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);
+    tGAP_BLE_CMPL_CBACK *p_cback = p_clcb->p_cback;
     UINT16                  op = p_clcb->cl_op_uuid;
 
     GAP_TRACE_EVENT("gap_ble_cl_op_cmpl status: %d", status);
@@ -505,15 +552,21 @@ void gap_ble_cl_op_cmpl(tGAP_CLCB *p_clcb, BOOLEAN status, UINT16 len, UINT8 *p_
     p_clcb->cl_op_uuid = 0;
     p_clcb->p_cback=NULL;
 
-    if (p_dev_name_cback)
+    if (p_cback && op)
     {
         GAP_TRACE_EVENT("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);
+        (* p_cback)(status, p_clcb->bda, len, (char *)p_name);
     }
 
-
+    /* if no further activity is requested in callback, drop the link */
+    if (p_clcb->connected)
+    {
+        if (!gap_ble_send_cl_read_request(p_clcb))
+        {
+            GATT_Disconnect(p_clcb->conn_id);
+            gap_ble_dealloc_clcb(p_clcb);
+        }
+    }
 }
 
 /*******************************************************************************
@@ -530,62 +583,27 @@ static void gap_ble_c_connect_cback (tGATT_IF gatt_if, BD_ADDR bda, UINT16 conn_
                                      tGATT_TRANSPORT transport)
 {
     tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (bda);
-    UINT16      cl_op_uuid;
 
     UNUSED(gatt_if);
     UNUSED(transport);
 
-    GAP_TRACE_EVENT ("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 == NULL)
+        if (connected)
         {
-            if ((p_clcb = gap_clcb_alloc(conn_id, bda))== NULL)
-            {
-                GAP_TRACE_ERROR ("gap_ble_c_connect_cback: no_resource");
-                return;
-            }
+            p_clcb->conn_id = conn_id;
+            p_clcb->connected = TRUE;
+            /* start operation is pending */
+            gap_ble_send_cl_read_request(p_clcb);
         }
-        p_clcb->conn_id = conn_id;
-        p_clcb->connected = TRUE;
-
-    }
-    else
-    {
-        if (p_clcb != NULL)
-            p_clcb->connected = FALSE;
-    }
-
-    if (p_clcb)
-    {
-        cl_op_uuid = p_clcb->cl_op_uuid;
-
-        GAP_TRACE_EVENT ("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);
-            }
-            else if (cl_op_uuid == GATT_UUID_GAP_PREF_CONN_PARAM)
-            {
-                 GAP_BleReadPeerPrefConnParams(bda);
-            }
-        }
-        /* current link disconnect */
         else
         {
+            p_clcb->connected = FALSE;
             gap_ble_cl_op_cmpl(p_clcb, FALSE, 0, NULL);
-            memset(p_clcb, 0, sizeof(tGAP_CLCB));
+            /* clean up clcb */
+            gap_ble_dealloc_clcb(p_clcb);
         }
     }
-
 }
 
 /*******************************************************************************
@@ -647,48 +665,62 @@ static void gap_ble_c_cmpl_cback (UINT16 conn_id, tGATTC_OPTYPE op, tGATT_STATUS
                 len = GAP_CHAR_DEV_NAME_SIZE;
             gap_ble_cl_op_cmpl(p_clcb, TRUE, len, pp);
             break;
-        case GATT_UUID_GAP_ICON:
+
+        case GATT_UUID_GAP_CENTRAL_ADDR_RESOL:
+            gap_ble_cl_op_cmpl(p_clcb, TRUE, 1, pp);
             break;
     }
 }
 
+
 /*******************************************************************************
 **
-** Function         gap_ble_cl_read_request
+** Function         gap_ble_accept_cl_operation
 **
-** Description      utility function to start a read request for a GAP charactersitic
+** Description      Start a process to read peer address resolution capability
 **
-** Returns          TRUE if read started, else FALSE if GAP is busy
+** Returns          TRUE if request accepted
 **
 *******************************************************************************/
-BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
+BOOLEAN gap_ble_accept_cl_operation(BD_ADDR peer_bda, UINT16 uuid, tGAP_BLE_CMPL_CBACK *p_cback)
 {
-    tGATT_READ_PARAM   param;
-
-    memset(&param, 0, sizeof(tGATT_READ_PARAM));
+    tGAP_CLCB *p_clcb;
+    BOOLEAN started = FALSE;
 
-    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 (p_cback == NULL && uuid != GATT_UUID_GAP_PREF_CONN_PARAM)
+        return(started);
 
-    if (GATTC_Read(p_clcb->conn_id, GATT_READ_BY_TYPE, &param) != GATT_SUCCESS)
-    {
-        GAP_TRACE_ERROR ("GAP_BleReadPeerPrefConnParams: GATT_Read Failed");
-        /* release the link here */
-        GATT_Disconnect(p_clcb->conn_id);
-        return(FALSE);
-    }
-    else
+    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
     {
-        p_clcb->p_cback = p_cback;
-        p_clcb->cl_op_uuid = uuid;
-        return TRUE;
+        if ((p_clcb = gap_clcb_alloc(peer_bda)) == NULL)
+        {
+            GAP_TRACE_ERROR("gap_ble_accept_cl_operation max connection reached");
+            return started;
+        }
     }
 
-}
+    GAP_TRACE_EVENT ("%s() - BDA: %08x%04x  cl_op_uuid: 0x%04x",
+                      __FUNCTION__,
+                      (peer_bda[0]<<24)+(peer_bda[1]<<16)+(peer_bda[2]<<8)+peer_bda[3],
+                      (peer_bda[4]<<8)+peer_bda[5], uuid);
+
+    if (GATT_GetConnIdIfConnected(gap_cb.gatt_if, peer_bda, &p_clcb->conn_id, BT_TRANSPORT_LE))
+        p_clcb->connected = TRUE;
+
+    /* hold the link here */
+    if (!GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
+        return started;
 
+    /* enqueue the request */
+    gap_ble_enqueue_request(p_clcb, uuid, p_cback);
+
+    if (p_clcb->connected && p_clcb->cl_op_uuid == 0)
+        started = gap_ble_send_cl_read_request(p_clcb);
+    else /* wait for connection up or pending operation to finish */
+        started = TRUE;
+
+   return started;
+}
 /*******************************************************************************
 **
 ** Function         GAP_BleReadPeerPrefConnParams
@@ -701,42 +733,7 @@ BOOLEAN gap_ble_cl_read_request(tGAP_CLCB *p_clcb, UINT16 uuid, void * p_cback)
 *******************************************************************************/
 BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
 {
-
-    tGAP_CLCB   *p_clcb = gap_find_clcb_by_bd_addr (peer_bda);
-
-    if (p_clcb == NULL)
-    {
-        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
-        {
-            GAP_TRACE_ERROR("GAP_BleReadPeerPrefConnParams max connection reached");
-            return FALSE;
-        }
-        p_clcb->connected = FALSE;
-    }
-
-    GAP_TRACE_API ("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);
-
-    /* hold the link here */
-    if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
-    {
-
-        if (p_clcb->connected)
-        {
-            return gap_ble_cl_read_request(p_clcb, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
-        }
-        /* Mark currently active operation */
-        p_clcb->cl_op_uuid = GATT_UUID_GAP_PREF_CONN_PARAM;
-
-        return(TRUE);
-    }
-    else
-        return FALSE;
+    return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_PREF_CONN_PARAM, NULL);
 }
 
 /*******************************************************************************
@@ -748,51 +745,24 @@ BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda)
 ** Returns          TRUE if request accepted
 **
 *******************************************************************************/
-BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback)
+BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
 {
-    tGAP_CLCB   *p_clcb = NULL;
-
-    if (p_cback == NULL)
-        return(FALSE);
-
-    if ((p_clcb = gap_find_clcb_by_bd_addr (peer_bda)) == NULL)
-    {
-        if ((p_clcb = gap_clcb_alloc(0, peer_bda)) == NULL)
-        {
-            GAP_TRACE_ERROR("GAP_BleReadPeerDevName max connection reached");
-            return FALSE;
-        }
-        p_clcb->connected = FALSE;
-    }
-
-    GAP_TRACE_EVENT ("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 */
-
-    if (GATT_Connect(gap_cb.gatt_if, p_clcb->bda, TRUE, BT_TRANSPORT_LE))
-    {
-        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);
-    }
-    else
-        return FALSE;
+    return gap_ble_accept_cl_operation (peer_bda, GATT_UUID_GAP_DEVICE_NAME, p_cback);
 }
 
+/*******************************************************************************
+**
+** Function         GAP_BleReadPeerAddressResolutionCap
+**
+** Description      Start a process to read peer address resolution capability
+**
+** Returns          TRUE if request accepted
+**
+*******************************************************************************/
+BOOLEAN GAP_BleReadPeerAddressResolutionCap (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback)
+{
+    return gap_ble_accept_cl_operation(peer_bda, GATT_UUID_GAP_CENTRAL_ADDR_RESOL, p_cback);
+}
 
 /*******************************************************************************
 **
@@ -811,7 +781,7 @@ BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda)
                       (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)
+    if (p_clcb == NULL)
     {
         GAP_TRACE_ERROR ("Cannot cancel current op is not get dev name");
         return FALSE;
index 0f63f3a..937db64 100644 (file)
@@ -97,7 +97,7 @@ typedef struct
 
 
 #if BLE_INCLUDED == TRUE
-#define GAP_MAX_CHAR_NUM          5
+#define GAP_MAX_CHAR_NUM          4
 
 typedef struct
 {
@@ -114,27 +114,20 @@ typedef struct
 
 typedef struct
 {
-    union
-    {
-        BD_ADDR         reconn_addr;
-        UINT8           privacy_flag;
-    }                   pending_data;
-    UINT8               op;
-    void                *p_pending_cback;
-}tGAP_BLE_PENDING_OP;
+    UINT16 uuid;
+    tGAP_BLE_CMPL_CBACK *p_cback;
+} tGAP_BLE_REQ;
 
 typedef struct
 {
     BD_ADDR                 bda;
-    BD_ADDR                 reconn_addr;
-    void                    * p_cback;
+    tGAP_BLE_CMPL_CBACK     *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;
+    BUFFER_Q                pending_req_q;
+
 }tGAP_CLCB;
 
 typedef struct
@@ -152,9 +145,7 @@ typedef struct
     /* 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;
index d7b06e4..8822d65 100644 (file)
@@ -1167,6 +1167,10 @@ void GATT_SetIdleTimeout (BD_ADDR bd_addr, UINT16 idle_tout, tBT_TRANSPORT trans
         if (p_tcb->att_lcid == L2CAP_ATT_CID)
         {
             status = L2CA_SetFixedChannelTout (bd_addr, L2CAP_ATT_CID, idle_tout);
+
+            if (idle_tout == GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP)
+                L2CA_SetIdleTimeoutByBdAddr(p_tcb->peer_bda,
+                                            GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP, BT_TRANSPORT_LE);
         }
         else
         {
index ccdb148..a1fbb9d 100644 (file)
@@ -296,8 +296,6 @@ typedef struct
 #define     GATT_CH_CONN                2
 #define     GATT_CH_CFG                 3
 #define     GATT_CH_OPEN                4
-#define     GATT_CH_W4_SEC_COMP         5
-#define     GATT_CH_W4_DATA_SIGN_COMP   6
 
 typedef UINT8 tGATT_CH_STATE;
 
index e1e9564..d781136 100644 (file)
@@ -96,6 +96,7 @@ void gatt_init (void)
     GATT_TRACE_DEBUG("gatt_init()");
 
     memset (&gatt_cb, 0, sizeof(tGATT_CB));
+    memset (&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
 
 #if defined(GATT_INITIAL_TRACE_LEVEL)
     gatt_cb.trace_level = GATT_INITIAL_TRACE_LEVEL;
@@ -1017,20 +1018,18 @@ void gatt_data_process (tGATT_TCB *p_tcb, BT_HDR *p_buf)
 *******************************************************************************/
 void gatt_add_a_bonded_dev_for_srv_chg (BD_ADDR bda)
 {
-    tGATTS_SRV_CHG *p_buf;
     tGATTS_SRV_CHG_REQ req;
     tGATTS_SRV_CHG srv_chg_clt;
 
     memcpy(srv_chg_clt.bda, bda, BD_ADDR_LEN);
     srv_chg_clt.srv_changed = FALSE;
-    if ((p_buf = gatt_add_srv_chg_clt(&srv_chg_clt)) != NULL)
+    if (gatt_add_srv_chg_clt(&srv_chg_clt) != NULL)
     {
         memcpy(req.srv_chg.bda, bda, BD_ADDR_LEN);
         req.srv_chg.srv_changed = FALSE;
         if (gatt_cb.cb_info.p_srv_chg_callback)
             (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req, NULL);
     }
-
 }
 
 /*******************************************************************************
index 5f9ddf0..439666b 100755 (executable)
@@ -1120,7 +1120,10 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle,
                 sr_data.write_req.need_rsp = TRUE;
             sr_data.write_req.handle = handle;
             sr_data.write_req.len = len;
-            memcpy (sr_data.write_req.value, p, len);
+            if (len != 0 && p != NULL)
+            {
+                memcpy (sr_data.write_req.value, p, len);
+            }
             break;
     }
 
index 11d8dff..5030c53 100644 (file)
@@ -2125,15 +2125,16 @@ void gatt_end_operation(tGATT_CLCB *p_clcb, tGATT_STATUS status, void *p_data)
 
     GATT_TRACE_DEBUG ("gatt_end_operation status=%d op=%d subtype=%d",
                        status, p_clcb->operation, p_clcb->op_subtype);
+    memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
 
     if (p_cmpl_cb != NULL && p_clcb->operation != 0)
     {
         if (p_clcb->operation == GATTC_OPTYPE_READ)
         {
-            memset(&cb_data.att_value, 0, sizeof(tGATT_VALUE));
             cb_data.att_value.handle   = p_clcb->s_handle;
             cb_data.att_value.len      = p_clcb->counter;
-            if (p_data)
+
+            if (p_data && p_clcb->counter)
                 memcpy (cb_data.att_value.value, p_data, cb_data.att_value.len);
         }
 
index fa46dec..9a5e106 100644 (file)
@@ -80,7 +80,7 @@ BOOLEAN btsnd_hcic_ble_set_random_addr (BD_ADDR random_bda)
 BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
                                        UINT8 adv_type, UINT8 addr_type_own,
                                        UINT8 addr_type_dir, BD_ADDR direct_bda,
-                                       UINT8 channel_map, UINT8 scan_filter_policy)
+                                       UINT8 channel_map, UINT8 adv_filter_policy)
 {
     BT_HDR *p;
     UINT8 *pp;
@@ -103,7 +103,7 @@ BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
     UINT8_TO_STREAM (pp, addr_type_dir);
     BDADDR_TO_STREAM (pp, direct_bda);
     UINT8_TO_STREAM (pp, channel_map);
-    UINT8_TO_STREAM (pp, scan_filter_policy);
+    UINT8_TO_STREAM (pp, adv_filter_policy);
 
     btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID,  p);
     return (TRUE);
@@ -768,5 +768,167 @@ BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason)
 }
 #endif
 
+BOOLEAN btsnd_hcic_ble_add_device_resolving_list (UINT8 addr_type_peer, BD_ADDR bda_peer,
+    UINT8 irk_peer[HCIC_BLE_IRK_SIZE],
+    UINT8 irk_local[HCIC_BLE_IRK_SIZE])
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_ADD_DEV_RESOLVING_LIST);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+    ARRAY_TO_STREAM (pp, irk_peer, HCIC_BLE_ENCRYT_KEY_SIZE);
+    ARRAY_TO_STREAM (pp, irk_local, HCIC_BLE_ENCRYT_KEY_SIZE);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_rm_device_resolving_list (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_RM_DEV_RESOLVING_LIST);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_clear_resolving_list (void)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_CLEAR_RESOLVING_LIST);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_resolvable_addr_peer (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_READ_RESOLVABLE_ADDR_PEER);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_read_resolvable_addr_local (UINT8 addr_type_peer, BD_ADDR bda_peer)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL);
+    UINT8_TO_STREAM (pp, addr_type_peer);
+    BDADDR_TO_STREAM (pp, bda_peer);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_addr_resolution_enable (UINT8 addr_resolution_enable)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_SET_ADDR_RESOLUTION_ENABLE);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE);
+    UINT8_TO_STREAM (pp, addr_resolution_enable);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout)
+{
+    BT_HDR *p;
+    UINT8 *pp;
+
+    if ((p = HCI_GET_CMD_BUF (HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT)) == NULL)
+        return (FALSE);
+
+    pp = (UINT8 *)(p + 1);
+
+    p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT;
+    p->offset = 0;
+
+    UINT16_TO_STREAM (pp, HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT);
+    UINT8_TO_STREAM (pp, HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT);
+    UINT16_TO_STREAM (pp, rpa_timout);
+
+    btu_hcif_send_cmd (LOCAL_BR_EDR_CONTROLLER_ID, p);
+
+    return (TRUE);
+}
+
+
 #endif
 
index d8b619d..0cc6976 100644 (file)
@@ -138,7 +138,7 @@ tHID_STATUS hidh_conn_disconnect (UINT8 dhandle)
 
         /* Set l2cap idle timeout to 0 (so ACL link is disconnected
          * immediately after last channel is closed) */
-        L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0);
+        L2CA_SetIdleTimeoutByBdAddr(hh_cb.devices[dhandle].addr, 0, BT_TRANSPORT_BR_EDR);
         /* Disconnect both interrupt and control channels */
         if (p_hcon->intr_cid)
             L2CA_DisconnectReq (p_hcon->intr_cid);
index 441cd17..8968af6 100644 (file)
@@ -330,6 +330,9 @@ typedef UINT8 BT_OCTET16[BT_OCTET16_LEN];   /* octet array: size 16 */
 typedef UINT8 PIN_CODE[PIN_CODE_LEN];       /* Pin Code (upto 128 bits) MSB is 0 */
 typedef UINT8 *PIN_CODE_PTR;                /* Pointer to Pin Code */
 
+#define BT_OCTET32_LEN    32
+typedef UINT8 BT_OCTET32[BT_OCTET32_LEN];   /* octet array: size 32 */
+
 #define DEV_CLASS_LEN   3
 typedef UINT8 DEV_CLASS[DEV_CLASS_LEN];     /* Device class */
 typedef UINT8 *DEV_CLASS_PTR;               /* Pointer to Device class */
@@ -500,8 +503,11 @@ typedef struct
 */
 #define BLE_ADDR_PUBLIC         0x00
 #define BLE_ADDR_RANDOM         0x01
-#define BLE_ADDR_TYPE_MASK      (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
+#define BLE_ADDR_PUBLIC_ID      0x02
+#define BLE_ADDR_RANDOM_ID      0x03
 typedef UINT8 tBLE_ADDR_TYPE;
+#define BLE_ADDR_TYPE_MASK      (BLE_ADDR_RANDOM | BLE_ADDR_PUBLIC)
+
 
 #define BT_TRANSPORT_BR_EDR    1
 #define BT_TRANSPORT_LE        2
index 731ac34..c108439 100644 (file)
@@ -29,9 +29,7 @@
 #include "sdp_api.h"
 #include "hcidefs.h"
 
-#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
 #include "smp_api.h"
-#endif
 /*****************************************************************************
 **  DEVICE CONTROL and COMMON
 *****************************************************************************/
@@ -206,8 +204,6 @@ typedef UINT8 (tBTM_FILTER_CB) (BD_ADDR bd_addr, DEV_CLASS dc);
 #define BTM_SSP_INQUIRY_ACTIVE      0x4     /* SSP is active, so inquiry is disallowed (work around for FW bug) */
 #define BTM_LE_GENERAL_INQUIRY_ACTIVE  BTM_BLE_GENERAL_INQUIRY     /* a general inquiry is in progress */
 #define BTM_LE_LIMITED_INQUIRY_ACTIVE  BTM_BLE_LIMITED_INQUIRY      /* 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 */
@@ -1087,6 +1083,7 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
 #define BTM_SEC_MODE_LINK           3
 #define BTM_SEC_MODE_SP             4
 #define BTM_SEC_MODE_SP_DEBUG       5
+#define BTM_SEC_MODE_SC             6
 
 /* Security Service Levels [bit mask] (BTM_SetSecurityLevel)
 ** Encryption should not be used without authentication
@@ -1129,9 +1126,16 @@ typedef void (tBTM_ESCO_CBACK) (tBTM_ESCO_EVT event, tBTM_ESCO_EVT_DATA *p_data)
 #define BTM_LKEY_TYPE_UNAUTH_COMB   HCI_LKEY_TYPE_UNAUTH_COMB
 #define BTM_LKEY_TYPE_AUTH_COMB     HCI_LKEY_TYPE_AUTH_COMB
 #define BTM_LKEY_TYPE_CHANGED_COMB  HCI_LKEY_TYPE_CHANGED_COMB
+
+#define BTM_LKEY_TYPE_UNAUTH_COMB_P_256 HCI_LKEY_TYPE_UNAUTH_COMB_P_256
+#define BTM_LKEY_TYPE_AUTH_COMB_P_256   HCI_LKEY_TYPE_AUTH_COMB_P_256
+
+#define BTM_LTK_DERIVED_LKEY_OFFSET 0x20    /* "easy" requirements for LK derived from LTK */
 #define BTM_LKEY_TYPE_IGNORE        0xff    /* used when event is response from
                                                hci return link keys request */
 
+typedef UINT8 tBTM_LINK_KEY_TYPE;
+
 /* Protocol level security (BTM_SetSecurityLevel) */
 #define BTM_SEC_PROTO_L2CAP         0
 #define BTM_SEC_PROTO_SDP           1
@@ -1456,11 +1460,12 @@ typedef struct
 
 enum
 {
-    BTM_SP_KEY_STARTED,         /* passkey entry started */
-    BTM_SP_KEY_ENTERED,         /* passkey digit entered */
-    BTM_SP_KEY_ERASED,          /* passkey digit erased */
-    BTM_SP_KEY_CLEARED,         /* passkey cleared */
-    BTM_SP_KEY_COMPLT           /* passkey entry completed */
+    BTM_SP_KEY_STARTED,         /* 0 - passkey entry started */
+    BTM_SP_KEY_ENTERED,         /* 1 - passkey digit entered */
+    BTM_SP_KEY_ERASED,          /* 2 - passkey digit erased */
+    BTM_SP_KEY_CLEARED,         /* 3 - passkey cleared */
+    BTM_SP_KEY_COMPLT,          /* 4 - passkey entry completed */
+    BTM_SP_KEY_OUT_OF_RANGE     /* 5 - out of range */
 };
 typedef UINT8   tBTM_SP_KEY_TYPE;
 
@@ -1543,32 +1548,46 @@ typedef void (tBTM_BOND_CANCEL_CMPL_CALLBACK) (tBTM_STATUS result);
 
 /* LE related event and data structure
 */
-enum
-{
-    BTM_LE_IO_REQ_EVT = 1,      /* received IO_CAPABILITY_REQUEST event */
-    BTM_LE_SEC_REQUEST_EVT, /* security request event */
-    BTM_LE_KEY_NOTIF_EVT,   /* received USER_PASSKEY_NOTIFY event */
-    BTM_LE_KEY_REQ_EVT,     /* received USER_PASSKEY_REQUEST event */
-    BTM_LE_OOB_REQ_EVT,     /* OOB data request event */
-    BTM_LE_COMPLT_EVT,      /* received SIMPLE_PAIRING_COMPLETE event */
-    BTM_LE_KEY_EVT         /* KEY update event */
-};
+#define BTM_LE_IO_REQ_EVT       SMP_IO_CAP_REQ_EVT     /* received IO_CAPABILITY_REQUEST event */
+#define BTM_LE_SEC_REQUEST_EVT  SMP_SEC_REQUEST_EVT    /* security request event */
+#define BTM_LE_KEY_NOTIF_EVT    SMP_PASSKEY_NOTIF_EVT  /* received USER_PASSKEY_NOTIFY event */
+#define BTM_LE_KEY_REQ_EVT      SMP_PASSKEY_REQ_EVT    /* received USER_PASSKEY_REQUEST event */
+#define BTM_LE_OOB_REQ_EVT      SMP_OOB_REQ_EVT        /* OOB data request event */
+#define BTM_LE_NC_REQ_EVT       SMP_NC_REQ_EVT          /* Numeric Comparison request event */
+#define BTM_LE_PR_KEYPR_NOT_EVT SMP_PEER_KEYPR_NOT_EVT /* Peer keypress notification recd event */
+/* SC OOB request event (both local and peer OOB data) can be expected in response */
+#define BTM_LE_SC_OOB_REQ_EVT   SMP_SC_OOB_REQ_EVT
+/* SC OOB local data set is created (as result of SMP_CrLocScOobData(...)) */
+#define BTM_LE_SC_LOC_OOB_EVT   SMP_SC_LOC_OOB_DATA_UP_EVT
+#define BTM_LE_BR_KEYS_REQ_EVT  SMP_BR_KEYS_REQ_EVT     /* SMP over BR keys request event */
+#define BTM_LE_COMPLT_EVT       SMP_COMPLT_EVT         /* SMP complete event */
+#define BTM_LE_LAST_FROM_SMP    BTM_LE_BR_KEYS_REQ_EVT
+#define BTM_LE_KEY_EVT          BTM_LE_LAST_FROM_SMP + 1 /* KEY update event */
 typedef UINT8 tBTM_LE_EVT;
 
+#define BTM_LE_KEY_NONE           0
 #define BTM_LE_KEY_PENC      SMP_SEC_KEY_TYPE_ENC        /* encryption information of peer device */
 #define BTM_LE_KEY_PID       SMP_SEC_KEY_TYPE_ID         /* identity key of the peer device */
-#define BTM_LE_KEY_PCSRK      SMP_SEC_KEY_TYPE_CSRK        /* peer SRK */
-#define BTM_LE_KEY_LENC      (SMP_SEC_KEY_TYPE_ENC << 3)       /* master role security information:div */
-#define BTM_LE_KEY_LID       (SMP_SEC_KEY_TYPE_ID << 3)        /* master device ID key */
-#define BTM_LE_KEY_LCSRK     (SMP_SEC_KEY_TYPE_CSRK << 3)       /* local CSRK has been deliver to peer */
+#define BTM_LE_KEY_PCSRK     SMP_SEC_KEY_TYPE_CSRK      /* peer SRK */
+#define BTM_LE_KEY_PLK       SMP_SEC_KEY_TYPE_LK
+#define BTM_LE_KEY_LLK       (SMP_SEC_KEY_TYPE_LK << 4)
+#define BTM_LE_KEY_LENC      (SMP_SEC_KEY_TYPE_ENC << 4)  /* master role security information:div */
+#define BTM_LE_KEY_LID       (SMP_SEC_KEY_TYPE_ID << 4)   /* master device ID key */
+#define BTM_LE_KEY_LCSRK     (SMP_SEC_KEY_TYPE_CSRK << 4) /* local CSRK has been deliver to peer */
 typedef UINT8 tBTM_LE_KEY_TYPE;
 
 #define BTM_LE_AUTH_REQ_NO_BOND SMP_AUTH_NO_BOND   /* 0 */
 #define BTM_LE_AUTH_REQ_BOND    SMP_AUTH_GEN_BOND  /* 1 << 0 */
 #define BTM_LE_AUTH_REQ_MITM    SMP_AUTH_YN_BIT    /* 1 << 2 */
 typedef UINT8 tBTM_LE_AUTH_REQ;
+#define BTM_LE_SC_SUPPORT_BIT           SMP_SC_SUPPORT_BIT     /* (1 << 3) */
+#define BTM_LE_KP_SUPPORT_BIT           SMP_KP_SUPPORT_BIT     /* (1 << 4) */
 
-#define BTM_LE_AUTH_REQ_MASK SMP_AUTH_MASK  /* 0x03*/
+#define BTM_LE_AUTH_REQ_SC_ONLY         SMP_AUTH_SC_ENC_ONLY    /* 1 << 3 */
+#define BTM_LE_AUTH_REQ_SC_BOND         SMP_AUTH_SC_GB          /* 1001 */
+#define BTM_LE_AUTH_REQ_SC_MITM         SMP_AUTH_SC_MITM_NB     /* 1100 */
+#define BTM_LE_AUTH_REQ_SC_MITM_BOND    SMP_AUTH_SC_MITM_GB     /* 1101 */
+#define BTM_LE_AUTH_REQ_MASK            SMP_AUTH_MASK           /* 0x1D */
 
 /* LE security level */
 #define BTM_LE_SEC_NONE             SMP_SEC_NONE
@@ -1593,7 +1612,6 @@ typedef struct
 {
     UINT8       reason;
     UINT8       sec_level;
-    BOOLEAN     privacy_supported;
     BOOLEAN     is_pair_cancel;
 }tBTM_LE_COMPLT;
 #endif
@@ -1619,6 +1637,7 @@ typedef struct
 /* BLE Encryption reproduction keys */
 typedef struct
 {
+    BT_OCTET16  ltk;
     UINT16      div;
     UINT8       key_size;
     UINT8       sec_level;
@@ -1630,7 +1649,7 @@ typedef struct
     UINT32          counter;
     UINT16          div;
     UINT8           sec_level;
-
+    BT_OCTET16      csrk;
 }tBTM_LE_LCSRK_KEYS;
 
 typedef struct
@@ -1643,10 +1662,10 @@ typedef struct
 typedef union
 {
     tBTM_LE_PENC_KEYS   penc_key;       /* received peer encryption key */
-    tBTM_LE_PCSRK_KEYS  pcsrk_key;       /* received peer device SRK */
+    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_LCSRK_KEYS   lcsrk_key;     /* local device CSRK = d1(ER,DIV,1)*/
 }tBTM_LE_KEY_VALUE;
 
 typedef struct
@@ -1659,9 +1678,12 @@ typedef union
 {
     tBTM_LE_IO_REQ      io_req;     /* BTM_LE_IO_REQ_EVT      */
     UINT32              key_notif;  /* BTM_LE_KEY_NOTIF_EVT   */
-                                    /* no callback dta for BTM_LE_KEY_REQ_EVT & BTM_LE_OOB_REQ_EVT  */
+                                    /* BTM_LE_NC_REQ_EVT */
+                                    /* no callback data for BTM_LE_KEY_REQ_EVT */
+                                    /* and BTM_LE_OOB_REQ_EVT  */
 #if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
     tBTM_LE_COMPLT      complt;     /* BTM_LE_COMPLT_EVT      */
+    tSMP_OOB_DATA_TYPE  req_oob_type;
 #endif
     tBTM_LE_KEY         key;
 } tBTM_LE_EVT_DATA;
@@ -3280,6 +3302,23 @@ extern tBTM_STATUS BTM_SecGetDeviceLinkKey (BD_ADDR bd_addr,
 
 /*******************************************************************************
 **
+** Function         BTM_SecGetDeviceLinkKeyType
+**
+** Description      This function is called to obtain link key type for the
+**                  device.
+**                  it returns BTM_SUCCESS if link key is available, or
+**                  BTM_UNKNOWN_ADDR if Security Manager does not know about
+**                  the device or device record does not contain link key info
+**
+** Returns          BTM_LKEY_TYPE_IGNORE if link key is unknown, link type
+**                  otherwise.
+**
+*******************************************************************************/
+extern tBTM_LINK_KEY_TYPE BTM_SecGetDeviceLinkKeyType (BD_ADDR bd_addr);
+
+
+/*******************************************************************************
+**
 ** Function         BTM_PINCodeReply
 **
 ** Description      This function is called after Security Manager submitted
@@ -3485,6 +3524,18 @@ extern UINT16 BTM_BuildOobData(UINT8 *p_data, UINT16 max_len, BT_OCTET16 c,
 
 /*******************************************************************************
 **
+** Function         BTM_IsLeScSuppLocally
+**
+** Description      This function is called to check if LE SC is supported.
+**
+** Parameters:      None.
+**
+**  Returns         Boolean - TRUE if LE SC is supported.
+*******************************************************************************/
+extern BOOLEAN BTM_IsLeScSuppLocally (void);
+
+/*******************************************************************************
+**
 ** Function         BTM_ReadOobData
 **
 ** Description      This function is called to parse the OOB data payload
index 307d39e..607e687 100644 (file)
@@ -47,6 +47,9 @@ typedef UINT8 tBTM_BLE_CHNL_MAP[CHNL_MAP_LEN];
 
 #define BTM_BLE_UNKNOWN_EVT     0xff
 
+typedef UINT8 tBTM_BLE_EVT;
+typedef UINT8 tBTM_BLE_CONN_MODE;
+
 typedef UINT32 tBTM_BLE_REF_VALUE;
 
 #define BTM_BLE_SCAN_MODE_PASS      0
@@ -86,8 +89,15 @@ typedef UINT8   tBTM_BLE_AFP;
 #endif
 
 /* scanning filter policy */
-#define SP_ADV_ALL     0x00     /* accept adv pakt from all, directed adv pkt not directed to me is ignored */
-#define SP_ADV_WL      0x01     /* accept adv pakt from device in white list, directed adv pkt not directed to me is ignored */
+#define SP_ADV_ALL     0x00     /* 0: accept adv packet from all, directed adv pkt not directed */
+                                /* to local device is ignored */
+#define SP_ADV_WL      0x01     /* 1: accept adv packet from device in white list, directed adv */
+                                /* packet not directed to local device is ignored */
+#define SP_ADV_ALL_RPA_DIR_ADV 0x02  /* 2: accept adv packet from all, directed adv pkt */
+                                     /* not directed to me is ignored except direct adv with RPA */
+#define SP_ADV_WL_RPA_DIR_ADV  0x03  /* 3: accept adv packet from device in white list, directed */
+                                     /* adv pkt not directed to me is ignored except direct adv */
+                                     /* with RPA */
 typedef UINT8   tBTM_BLE_SFP;
 
 #ifndef BTM_BLE_DEFAULT_SFP
@@ -317,6 +327,10 @@ typedef  UINT32  tBTM_BLE_AD_MASK;
 #define BTM_BLE_AD_TYPE_MANU            HCI_EIR_MANUFACTURER_SPECIFIC_TYPE      /* 0xff */
 typedef UINT8   tBTM_BLE_AD_TYPE;
 
+/* security settings used with L2CAP LE COC */
+#define BTM_SEC_LE_LINK_ENCRYPTED           0x01
+#define BTM_SEC_LE_LINK_PAIRED_WITHOUT_MITM 0x02
+#define BTM_SEC_LE_LINK_PAIRED_WITH_MITM    0x04
 /* adv tx power level */
 #define BTM_BLE_ADV_TX_POWER_MIN        0           /* minimum tx power */
 #define BTM_BLE_ADV_TX_POWER_LOW        1           /* low tx power     */
@@ -1153,6 +1167,20 @@ extern void BTM_BlePasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey);
 
 /*******************************************************************************
 **
+** Function         BTM_BleConfirmReply
+**
+** Description      This function is called after Security Manager submitted
+**                  numeric comparison request to the application.
+**
+** Parameters:      bd_addr      - Address of the device with which numeric
+**                                 comparison was requested
+**                  res          - comparison result BTM_SUCCESS if success
+**
+*******************************************************************************/
+extern void BTM_BleConfirmReply (BD_ADDR bd_addr, UINT8 res);
+
+/*******************************************************************************
+**
 ** Function         BTM_LeOobDataReply
 **
 ** Description      This function is called to provide the OOB data for
@@ -1392,21 +1420,6 @@ extern tBTM_STATUS BTM_BleBroadcast(BOOLEAN start);
 
 /*******************************************************************************
 **
-** Function         BTM_RegisterScanReqEvt
-**
-** Description      This function is called to register a scan request callback
-**                  on the advertiser.
-**
-** Parameters       p_scan_req_cback: scan request callback.  If NULL, remove the
-**                                    registration.
-**
-** Returns          void
-**
-*******************************************************************************/
-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
@@ -1414,10 +1427,10 @@ extern void BTM_RegisterScanReqEvt(tBTM_BLE_SCAN_REQ_CBACK *p_scan_req_cback);
 **
 ** Parameters       enable: TRUE to enable it; FALSE to disable it.
 **
-** Returns          void
+** Returns          BOOLEAN privacy mode set success; otherwise failed.
 **
 *******************************************************************************/
-extern void BTM_BleConfigPrivacy(BOOLEAN enable);
+extern BOOLEAN BTM_BleConfigPrivacy(BOOLEAN enable);
 
 /*******************************************************************************
 **
@@ -1428,7 +1441,21 @@ extern void BTM_BleConfigPrivacy(BOOLEAN enable);
 ** Returns          Return TRUE if local privacy is enabled else FALSE
 **
 *******************************************************************************/
-extern BOOLEAN BTM_BleLocalPrivacyEnabled();
+extern BOOLEAN BTM_BleLocalPrivacyEnabled(void);
+
+/*******************************************************************************
+**
+** Function         BTM_BleEnableMixedPrivacyMode
+**
+** Description      This function is called to enabled Mixed mode if privacy 1.2
+**                  is applicable in controller.
+**
+** Parameters       mixed_on:  mixed mode to be used or not.
+**
+** Returns          void
+**
+*******************************************************************************/
+extern void BTM_BleEnableMixedPrivacyMode(BOOLEAN mixed_on);
 
 /*******************************************************************************
 **
@@ -1443,18 +1470,20 @@ extern UINT8  BTM_BleMaxMultiAdvInstanceCount();
 
 /*******************************************************************************
 **
-** Function         BTM_BleSetConnMode
+** Function         BTM_BleSetConnectableMode
 **
 ** 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
+** Parameters       connectable_mode:  directed connectable mode, or non-directed.It can
+**                              be BTM_BLE_CONNECT_EVT, BTM_BLE_CONNECT_DIR_EVT or
+**                              BTM_BLE_CONNECT_LO_DUTY_DIR_EVT
 **
-** Returns          void
+** Returns          BTM_ILLEGAL_VALUE if controller does not support BLE.
+**                  BTM_SUCCESS is status set successfully; otherwise failure.
 **
 *******************************************************************************/
-extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
+extern tBTM_STATUS BTM_BleSetConnectableMode(tBTM_BLE_CONN_MODE connectable_mode);
 
 /*******************************************************************************
 **
@@ -1472,7 +1501,6 @@ extern tBTM_STATUS BTM_BleSetConnMode(BOOLEAN directed);
 extern void BTM_BleTurnOnPrivacyOnRemote(BD_ADDR bd_addr,
                                                  BOOLEAN privacy_on);
 
-
 /*******************************************************************************
 **
 ** Function         BTM_BleUpdateAdvWhitelist
@@ -1560,6 +1588,45 @@ extern BOOLEAN BTM_UseLeLink (BD_ADDR bd_addr);
 *******************************************************************************/
 extern tBTM_STATUS BTM_BleStackEnable (BOOLEAN enable);
 
+/*******************************************************************************
+**
+** Function         BTM_GetLeSecurityState
+**
+** Description      This function is called to get security mode 1 flags and
+**                  encryption key size for LE peer.
+**
+** Returns          BOOLEAN TRUE if LE device is found, FALSE otherwise.
+**
+*******************************************************************************/
+extern BOOLEAN BTM_GetLeSecurityState (BD_ADDR bd_addr,
+                                               UINT8 *p_le_dev_sec_flags,
+                                               UINT8 *p_le_key_size);
+
+/*******************************************************************************
+**
+** Function         BTM_BleSecurityProcedureIsRunning
+**
+** Description      This function indicates if LE security procedure is
+**                  currently running with the peer.
+**
+** Returns          BOOLEAN TRUE if security procedure is running, FALSE otherwise.
+**
+*******************************************************************************/
+extern BOOLEAN BTM_BleSecurityProcedureIsRunning (BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         BTM_BleGetSupportedKeySize
+**
+** Description      This function gets the maximum encryption key size in bytes
+**                  the local device can suport.
+**                  record.
+**
+** Returns          the key size or 0 if the size can't be retrieved.
+**
+*******************************************************************************/
+extern UINT8 BTM_BleGetSupportedKeySize (BD_ADDR bd_addr);
+
 /*******************************************************************************/
 /*                          Multi ADV API                                      */
 /*******************************************************************************
index 59c1294..755c49c 100644 (file)
@@ -120,13 +120,12 @@ typedef union
     BD_ADDR                 reconn_bda;
     UINT16                  icon;
     UINT8                   *p_dev_name;
-    UINT8                   privacy;
+    UINT8                   addr_resolution;
 
 }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_CMPL_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
@@ -362,33 +361,32 @@ extern BOOLEAN GAP_BleReadPeerPrefConnParams (BD_ADDR peer_bda);
 ** Returns          TRUE if request accepted
 **
 *******************************************************************************/
-extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_DEV_NAME_CBACK *p_cback);
+extern BOOLEAN GAP_BleReadPeerDevName (BD_ADDR peer_bda, tGAP_BLE_CMPL_CBACK *p_cback);
 
 
 /*******************************************************************************
 **
-** Function         GAP_BleCancelReadPeerDevName
+** Function         GAP_BleReadPeerAddressResolutionCap
 **
-** Description      Cancel reading a peripheral's device name.
+** Description      Start a process to read peer address resolution capability
 **
 ** Returns          TRUE if request accepted
 **
 *******************************************************************************/
-extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+extern BOOLEAN GAP_BleReadPeerAddressResolutionCap (BD_ADDR peer_bda,
+                                                    tGAP_BLE_CMPL_CBACK *p_cback);
 
 /*******************************************************************************
 **
-** Function         GAP_BleUpdateReconnectAddr
+** Function         GAP_BleCancelReadPeerDevName
 **
-** Description      Start a process to udpate the reconnect address if remote devive
-**                  has privacy enabled.
+** Description      Cancel reading a peripheral's device name.
 **
-** Returns          TRUE if read started, else FALSE if GAP is busy
+** Returns          TRUE if request accepted
 **
 *******************************************************************************/
-extern BOOLEAN GAP_BleUpdateReconnectAddr (BD_ADDR peer_bda,
-                                           BD_ADDR reconn_addr,
-                                           tGAP_BLE_RECONN_ADDR_CBACK *p_cback);
+extern BOOLEAN GAP_BleCancelReadPeerDevName (BD_ADDR peer_bda);
+
 
 #endif
 
index 38e18f3..bfbec27 100644 (file)
 
 /* GAP Profile Attributes
 */
-#define GATT_UUID_GAP_DEVICE_NAME       0x2A00
-#define GATT_UUID_GAP_ICON              0x2A01
-#define GATT_UUID_GAP_PRIVACY_FLAG      0x2A02
-#define GATT_UUID_GAP_RECONN_ADDR       0x2A03
-#define GATT_UUID_GAP_PREF_CONN_PARAM   0x2A04
+#define GATT_UUID_GAP_DEVICE_NAME        0x2A00
+#define GATT_UUID_GAP_ICON               0x2A01
+#define GATT_UUID_GAP_PREF_CONN_PARAM    0x2A04
+#define GATT_UUID_GAP_CENTRAL_ADDR_RESOL 0x2A05
 
 /* Attribute Profile Attribute UUID */
-#define GATT_UUID_GATT_SRV_CHGD         0x2A05
+#define GATT_UUID_GATT_SRV_CHGD          0x2A05
 /* Attribute Protocol Test */
 
 /* Link Loss Service */
@@ -72,8 +71,8 @@
 #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_ALERT_STATUS          0x2A3F    /* alert status */
+#define GATT_UUID_RINGER_CP             0x2A40    /* ringer control point */
 #define GATT_UUID_RINGER_SETTING        0x2A41    /* ringer setting */
 
 /* Glucose Service */
index 63a0bc5..31fd90b 100644 (file)
@@ -42,7 +42,7 @@
 #define HCI_OCF(p)  ( 0x3FF & (p))
 
 /*
-**  Defentions for Link Control Commands
+**  Definitions for Link Control Commands
 */
 /* Following opcode is used only in command complete event for flow control */
 #define HCI_COMMAND_NONE                0x0000
 #define HCI_READ_SYNC_TRAIN_PARAM               (0x0077 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_WRITE_SYNC_TRAIN_PARAM              (0x0078 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 
+#define HCI_READ_SECURE_CONNS_SUPPORT           (0x0079 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SECURE_CONNS_SUPPORT          (0x007A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
 #define HCI_CONT_BASEBAND_CMDS_FIRST    HCI_SET_EVENT_MASK
 #define HCI_CONT_BASEBAND_CMDS_LAST     HCI_READ_SYNC_TRAIN_PARAM
 
 #define HCI_BLE_LTK_REQ_NEG_REPLY       (0x001B | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_READ_SUPPORTED_STATES   (0x001C | HCI_GRP_BLE_CMDS)
                             /*0x001D, 0x001E and 0x001F are reserved*/
-
+#define HCI_BLE_RECEIVER_TEST           (0x001D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_TRANSMITTER_TEST        (0x001E | HCI_GRP_BLE_CMDS)
+/* BLE TEST COMMANDS */
+#define HCI_BLE_TEST_END                (0x001F | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_RC_PARAM_REQ_REPLY      (0x0020 | HCI_GRP_BLE_CMDS)
 #define HCI_BLE_RC_PARAM_REQ_NEG_REPLY  (0x0021 | HCI_GRP_BLE_CMDS)
 
+#define HCI_BLE_ADD_DEV_RESOLVING_LIST      (0x0027 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_RM_DEV_RESOLVING_LIST       (0x0028 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_CLEAR_RESOLVING_LIST        (0x0029 | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVING_LIST_SIZE    (0x002A | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVABLE_ADDR_PEER   (0x002B | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_READ_RESOLVABLE_ADDR_LOCAL  (0x002C | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_ADDR_RESOLUTION_ENABLE  (0x002D | HCI_GRP_BLE_CMDS)
+#define HCI_BLE_SET_RAND_PRIV_ADDR_TIMOUT   (0x002E | 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)
 
 /* LE Get Vendor Capabilities Command OCF */
 #define HCI_BLE_VENDOR_CAP_OCF    (0x0153 | HCI_GRP_VENDOR_SPECIFIC)
 #define HCI_SUPP_LE_STATES_INIT_MASTER_OFF           3
 #define HCI_LE_STATES_INIT_MASTER_SUPPORTED(x)      ((x)[HCI_SUPP_LE_STATES_INIT_MASTER_OFF] & HCI_SUPP_LE_STATES_INIT_MASTER_MASK)
 
+/*Low Duty Cycle Directed Advertising State . 0x0000000020000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_MASK          0x20
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_OFF           3
+#define HCI_LE_STATES_LOW_DUTY_DIR_ADV_SUPPORTED(x)      ((x)[HCI_SUPP_LE_STATES_LOW_DUTY_DIR_ADV_OFF] & HCI_SUPP_LE_STATES_LOW_DUTY_DIR_ADV_MASK)
+
+/*Low Duty Cycle Directed Advertising State and Passive scan combination. 0x0000000040000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_MASK          0x40
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_OFF           3
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_SUPPORTED(x)      ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_PASS_SCAN_MASK)
+
+/*Low Duty Cycle Directed Advertising State and Active scan combination . 0x0000000080000000 */
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_MASK          0x80
+#define HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_OFF           3
+#define HCI_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_SUPPORTED(x)      ((x)[HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_OFF] & HCI_SUPP_LE_STATES_LO_DUTY_DIR_ADV_ACTIVE_SCAN_MASK)
+
 /* Connectable Advertising State and Initiating State combination supported. 0x0000000100000000 */
 #define HCI_SUPP_LE_STATES_CONN_ADV_INIT_MASK          0x01
 #define HCI_SUPP_LE_STATES_CONN_ADV_INIT_OFF           4
 #define HCI_SET_TRIGGERED_CLOCK_CAPTURE_EVT 0x4E
 
 /* ULP HCI Event */
-#define HCI_BLE_EVENT                   0x03E
+#define HCI_BLE_EVENT                       0x3e
 /* ULP Event sub code */
 #define HCI_BLE_CONN_COMPLETE_EVT           0x01
 #define HCI_BLE_ADV_PKT_RPT_EVT             0x02
 #define HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT   0x04
 #define HCI_BLE_LTK_REQ_EVT                 0x05
 #define HCI_BLE_RC_PARAM_REQ_EVT            0x06
+#define HCI_BLE_DATA_LENGTH_CHANGE_EVT      0x07
+#define HCI_BLE_ENHANCED_CONN_COMPLETE_EVT  0x0a
+#define HCI_BLE_DIRECT_ADV_EVT              0x0b
 
 /* Definitions for LE Channel Map */
 #define HCI_BLE_CHNL_MAP_SIZE               5
                                                  because conflict w/ TCI_EVT and per
                                                  specification compliant */
 
-/* the event mask for BLE event mask */
-#define HCI_BLE_EVENT_MASK_DEF               "\x00\x00\x00\x00\x00\x00\x00\x3f"
-
-
-
 /*
 **  Defentions for HCI Error Codes that are past in the events
 */
     0x0000000000200000 Connectionless Broadcast Channel Map Change Event
     0x0000000000400000 Inquiry Response Notification Event
 */
-
+#if BLE_PRIVACY_SPT == TRUE
+/* BLE event mask */
+#define HCI_BLE_EVENT_MASK_DEF               "\x00\x00\x00\x00\x00\x00\x07\xff"
+#else
+#define HCI_BLE_EVENT_MASK_DEF              "\x00\x00\x00\x00\x00\x00\x00\x7f"
+#endif
 /*
 ** Definitions for packet type masks (BT1.2 and BT2.0 definitions)
 */
 #define HCI_SPD_MODE_DISABLED           0x00
 #define HCI_SPD_MODE_ENABLED            0x01
 
+/* Definitions for Write Secure Connections Host Support */
+#define HCI_SC_MODE_DISABLED            0x00
+#define HCI_SC_MODE_ENABLED             0x01
+
 /* Definitions for IO Capability Response/Command */
 #define HCI_IO_CAP_DISPLAY_ONLY         0x00
 #define HCI_IO_CAP_DISPLAY_YESNO        0x01
 #define HCI_LKEY_TYPE_UNAUTH_COMB       0x04
 #define HCI_LKEY_TYPE_AUTH_COMB         0x05
 #define HCI_LKEY_TYPE_CHANGED_COMB      0x06
+#define HCI_LKEY_TYPE_UNAUTH_COMB_P_256 0x07
+#define HCI_LKEY_TYPE_AUTH_COMB_P_256   0x08
 
 /* Internal definitions - not used over HCI */
 #define HCI_LKEY_TYPE_AMP_WIFI          0x80
@@ -1723,6 +1756,17 @@ typedef struct
 #define HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF        0
 #define HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(x) ((x)[HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_OFF] & HCI_LE_FEATURE_SLAVE_INIT_FEAT_EXC_MASK)
 
+/* Enhanced privacy Feature: bit 6 */
+#define HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK       0x40
+#define HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF        0
+#define HCI_LE_ENHANCED_PRIVACY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_ENHANCED_PRIVACY_OFF] & HCI_LE_FEATURE_ENHANCED_PRIVACY_MASK)
+
+
+/* Extended scanner filter policy : 7 */
+#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK       0x80
+#define HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF        0
+#define HCI_LE_EXT_SCAN_FILTER_POLICY_SUPPORTED(x) ((x)[HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_OFF] & HCI_LE_FEATURE_EXT_SCAN_FILTER_POLICY_MASK)
+
 /*
 **   Local Supported Commands encoding
 */
index 1447cce..dfc0d50 100644 (file)
@@ -639,6 +639,10 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
 ** BLE Commands
 **      Note: "local_controller_id" is for transport, not counted in HCI message size
 *********************************************************************************/
+#define HCIC_BLE_RAND_DI_SIZE                   8
+#define HCIC_BLE_ENCRYT_KEY_SIZE                16
+#define HCIC_BLE_IRK_SIZE                       16
+
 #define HCIC_PARAM_SIZE_SET_USED_FEAT_CMD       8
 #define HCIC_PARAM_SIZE_WRITE_RANDOM_ADDR_CMD    6
 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_PARAMS    15
@@ -667,6 +671,15 @@ extern void btsnd_hcic_vendor_spec_cmd (void *buffer, UINT16 opcode,
 #define HCIC_BLE_CHNL_MAP_SIZE                  5
 #define HCIC_PARAM_SIZE_BLE_WRITE_ADV_DATA      31
 
+#define HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST      (7 + HCIC_BLE_IRK_SIZE * 2)
+#define HCIC_PARAM_SIZE_BLE_RM_DEV_RESOLVING_LIST       7
+#define HCIC_PARAM_SIZE_BLE_CLEAR_RESOLVING_LIST        0
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVING_LIST_SIZE    0
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_PEER   7
+#define HCIC_PARAM_SIZE_BLE_READ_RESOLVABLE_ADDR_LOCAL  7
+#define HCIC_PARAM_SIZE_BLE_SET_ADDR_RESOLUTION_ENABLE  1
+#define HCIC_PARAM_SIZE_BLE_SET_RAND_PRIV_ADDR_TIMOUT   2
+
 /* ULP HCI command */
 extern BOOLEAN btsnd_hcic_ble_set_evt_mask (BT_EVENT_MASK event_mask);
 
@@ -681,7 +694,7 @@ extern BOOLEAN btsnd_hcic_ble_set_random_addr (BD_ADDR random_addr);
 extern BOOLEAN btsnd_hcic_ble_write_adv_params (UINT16 adv_int_min, UINT16 adv_int_max,
                                                 UINT8 adv_type, UINT8 addr_type_own,
                                                 UINT8 addr_type_dir, BD_ADDR direct_bda,
-                                                UINT8 channel_map, UINT8 scan_filter_policy);
+                                                UINT8 channel_map, UINT8 adv_filter_policy);
 
 extern BOOLEAN btsnd_hcic_ble_read_adv_chnl_tx_power (void);
 
@@ -759,6 +772,36 @@ extern BOOLEAN btsnd_hcic_ble_rc_param_req_neg_reply(UINT16 handle, UINT8 reason
 #endif /* BLE_LLT_INCLUDED */
 
 
+extern BOOLEAN btsnd_hcic_ble_add_device_resolving_list (UINT8 addr_type_peer,
+                                                               BD_ADDR bda_peer,
+                                                               UINT8 irk_peer[HCIC_BLE_IRK_SIZE],
+                                                               UINT8 irk_local[HCIC_BLE_IRK_SIZE]);
+
+extern BOOLEAN btsnd_hcic_ble_rm_device_resolving_list (UINT8 addr_type_peer,
+                                                                BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_clear_resolving_list (void);
+
+extern BOOLEAN btsnd_hcic_ble_read_resolvable_addr_peer (UINT8 addr_type_peer,
+                                                                 BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_read_resolvable_addr_local (UINT8 addr_type_peer,
+                                                                 BD_ADDR bda_peer);
+
+extern BOOLEAN btsnd_hcic_ble_set_addr_resolution_enable (UINT8 addr_resolution_enable);
+
+extern BOOLEAN btsnd_hcic_ble_set_rand_priv_addr_timeout (UINT16 rpa_timout);
+
 #endif /* BLE_INCLUDED */
 
+extern BOOLEAN btsnd_hcic_read_authenticated_payload_tout(UINT16 handle);
+
+extern BOOLEAN btsnd_hcic_write_authenticated_payload_tout(UINT16 handle,
+                                                                   UINT16 timeout);
+
+#define HCIC_PARAM_SIZE_WRITE_AUTHENT_PAYLOAD_TOUT  4
+
+#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_HANDLE_OFF  0
+#define HCI__WRITE_AUTHENT_PAYLOAD_TOUT_TOUT_OFF    2
+
 #endif
index c89efdd..837dbc8 100644 (file)
@@ -567,7 +567,8 @@ extern BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout,
 ** NOTE             This timeout applies to all logical channels active on the
 **                  ACL link.
 *******************************************************************************/
-extern BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout);
+extern BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout,
+                                           tBT_TRANSPORT transport);
 
 /*******************************************************************************
 **
@@ -964,6 +965,7 @@ typedef struct
     tL2CAP_FCR_OPTS         fixed_chnl_opts;
 
     UINT16                  default_idle_tout;
+    tL2CA_TX_COMPLETE_CB    *pL2CA_FixedTxComplete_Cb; /* fixed channel tx complete callback */
 } tL2CAP_FIXED_CHNL_REG;
 
 
index 86044bf..a6e25eb 100644 (file)
 #define L2CAP_CMD_REJ_INVALID_CID       2
 
 
-/* L2CAP Predefined CIDs  (0x0004-0x003E Reserved)
+/* L2CAP Predefined CIDs
 */
 #define L2CAP_SIGNALLING_CID            1
 #define L2CAP_CONNECTIONLESS_CID        2
 #define L2CAP_ATT_CID                   4
 #define L2CAP_BLE_SIGNALLING_CID        5
 #define L2CAP_SMP_CID                   6
+#define L2CAP_SMP_BR_CID                7
 #define L2CAP_AMP_TEST_CID              0x003F
 #define L2CAP_BASE_APPL_CID             0x0040
+#define L2CAP_BLE_CONN_MAX_CID          0x007F
 
-/* Fixed Channels mask bits
-*/
-#define L2CAP_FIXED_CHNL_SIG_BIT        (1 << L2CAP_SIGNALLING_CID)     /* Signal Channel Supported (Mandatory) */
-#define L2CAP_FIXED_CHNL_CNCTLESS_BIT   (1 << L2CAP_CONNECTIONLESS_CID) /* Connectionless Reception             */
-#define L2CAP_FIXED_CHNL_AMP_BIT        (1 << L2CAP_AMP_CID)            /* AMP Manager Supported                */
-#define L2CAP_FIXED_CHNL_ATT_BIT        (1 << L2CAP_ATT_CID)            /* Attribute protocol Supported         */
-#define L2CAP_FIXED_CHNL_BLE_SIG_BIT    (1 << L2CAP_BLE_SIGNALLING_CID) /* BLE Signalling Supported             */
-#define L2CAP_FIXED_CHNL_SMP_BIT        (1 << L2CAP_SMP_CID)            /* BLE Security Manager Supported       */
+/* Fixed Channels mask bits */
+
+/* Signal channel supported (Mandatory) */
+#define L2CAP_FIXED_CHNL_SIG_BIT     (1 << L2CAP_SIGNALLING_CID)
+
+/* Connectionless reception */
+#define L2CAP_FIXED_CHNL_CNCTLESS_BIT (1 << L2CAP_CONNECTIONLESS_CID)
+
+/* AMP Manager supported */
+#define L2CAP_FIXED_CHNL_AMP_BIT      (1 << L2CAP_AMP_CID)
+
+/* Attribute protocol supported */
+#define L2CAP_FIXED_CHNL_ATT_BIT      (1 << L2CAP_ATT_CID)
+
+/* BLE Signalling supported */
+#define L2CAP_FIXED_CHNL_BLE_SIG_BIT  (1 << L2CAP_BLE_SIGNALLING_CID)
+
+/* BLE Security Mgr supported */
+#define L2CAP_FIXED_CHNL_SMP_BIT      (1 << L2CAP_SMP_CID)
+
+/* Security Mgr over BR supported */
+#define L2CAP_FIXED_CHNL_SMP_BR_BIT   (1 << L2CAP_SMP_BR_CID)
 
 
 
index 79d1d6f..37669b4 100644 (file)
 #define SMP_PIN_CODE_LEN_MAX    PIN_CODE_LEN
 #define SMP_PIN_CODE_LEN_MIN    6
 
+#if BLE_INCLUDED == TRUE && SMP_INCLUDED == TRUE
+/* SMP command code */
+#define SMP_OPCODE_PAIRING_REQ            0x01
+#define SMP_OPCODE_PAIRING_RSP            0x02
+#define SMP_OPCODE_CONFIRM                0x03
+#define SMP_OPCODE_RAND                   0x04
+#define SMP_OPCODE_PAIRING_FAILED         0x05
+#define SMP_OPCODE_ENCRYPT_INFO           0x06
+#define SMP_OPCODE_MASTER_ID              0x07
+#define SMP_OPCODE_IDENTITY_INFO          0x08
+#define SMP_OPCODE_ID_ADDR                0x09
+#define SMP_OPCODE_SIGN_INFO              0x0A
+#define SMP_OPCODE_SEC_REQ                0x0B
+#define SMP_OPCODE_PAIR_PUBLIC_KEY        0x0C
+#define SMP_OPCODE_PAIR_DHKEY_CHECK       0x0D
+#define SMP_OPCODE_PAIR_KEYPR_NOTIF       0x0E
+#define SMP_OPCODE_MAX                    SMP_OPCODE_PAIR_KEYPR_NOTIF
+#define SMP_OPCODE_MIN                    SMP_OPCODE_PAIRING_REQ
+#define SMP_OPCODE_PAIR_COMMITM           0x0F
+#endif
+
 /* SMP event type */
 #define SMP_IO_CAP_REQ_EVT      1       /* IO capability request event */
 #define SMP_SEC_REQUEST_EVT     2       /* SMP pairing request */
 #define SMP_PASSKEY_NOTIF_EVT   3       /* passkey notification event */
 #define SMP_PASSKEY_REQ_EVT     4       /* passkey request event */
 #define SMP_OOB_REQ_EVT         5       /* OOB request event */
-#define SMP_COMPLT_EVT          6       /* SMP complete event */
+#define SMP_NC_REQ_EVT          6       /* Numeric Comparison request event */
+#define SMP_COMPLT_EVT          7       /* SMP complete event */
+#define SMP_PEER_KEYPR_NOT_EVT  8       /* Peer keypress notification received event */
+#define SMP_SC_OOB_REQ_EVT      9       /* SC OOB request event (both local and peer OOB data */
+                                        /* can be expected in response) */
+#define SMP_SC_LOC_OOB_DATA_UP_EVT  10  /* SC OOB local data set is created */
+                                        /* (as result of SMP_CrLocScOobData(...)) */
+#define SMP_BR_KEYS_REQ_EVT     12      /* SMP over BR keys request event */
 typedef UINT8   tSMP_EVT;
 
 
@@ -49,19 +77,31 @@ typedef UINT8   tSMP_EVT;
 #define SMP_INVALID_CMD             0x07
 #define SMP_PAIR_FAIL_UNKNOWN       0x08
 #define SMP_REPEATED_ATTEMPTS       0x09
-#define SMP_PAIR_FAILURE_MAX        SMP_REPEATED_ATTEMPTS
+#define SMP_INVALID_PARAMETERS      0x0A
+#define SMP_DHKEY_CHK_FAIL          0x0B
+#define SMP_NUMERIC_COMPAR_FAIL     0x0C
+#define SMP_BR_PARING_IN_PROGR      0x0D
+#define SMP_XTRANS_DERIVE_NOT_ALLOW 0x0E
+#define SMP_MAX_FAIL_RSN_PER_SPEC   SMP_XTRANS_DERIVE_NOT_ALLOW
+
 /* self defined error code */
-#define SMP_PAIR_INTERNAL_ERR       0x0A
-#define SMP_UNKNOWN_IO_CAP          0x0B    /* unknown IO capability, unable to decide associatino model */
-#define SMP_INIT_FAIL               0x0C
-#define SMP_CONFIRM_FAIL            0x0D
-#define SMP_BUSY                    0x0E
-#define SMP_ENC_FAIL                0x0F
-#define SMP_STARTED                 0x10
-#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_PAIR_INTERNAL_ERR       (SMP_MAX_FAIL_RSN_PER_SPEC + 0x01) /* 0x0E */
+
+/* 0x0F unknown IO capability, unable to decide association model */
+#define SMP_UNKNOWN_IO_CAP          (SMP_MAX_FAIL_RSN_PER_SPEC + 0x02) /* 0x0F */
+
+#define SMP_INIT_FAIL               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x03) /* 0x10 */
+#define SMP_CONFIRM_FAIL            (SMP_MAX_FAIL_RSN_PER_SPEC + 0x04) /* 0x11 */
+#define SMP_BUSY                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x05) /* 0x12 */
+#define SMP_ENC_FAIL                (SMP_MAX_FAIL_RSN_PER_SPEC + 0x06) /* 0x13 */
+#define SMP_STARTED                 (SMP_MAX_FAIL_RSN_PER_SPEC + 0x07) /* 0x14 */
+#define SMP_RSP_TIMEOUT             (SMP_MAX_FAIL_RSN_PER_SPEC + 0x08) /* 0x15 */
+#define SMP_DIV_NOT_AVAIL           (SMP_MAX_FAIL_RSN_PER_SPEC + 0x09) /* 0x16 */
+
+/* 0x17 unspecified failed reason */
+#define SMP_FAIL                    (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0A) /* 0x17 */
+
+#define SMP_CONN_TOUT               (SMP_MAX_FAIL_RSN_PER_SPEC + 0x0B)
 #define SMP_SUCCESS                 0
 
 typedef UINT8 tSMP_STATUS;
@@ -89,22 +129,55 @@ enum
 };
 typedef UINT8  tSMP_OOB_FLAG;
 
+/* type of OOB data required from application */
+enum
+{
+    SMP_OOB_INVALID_TYPE,
+    SMP_OOB_PEER,
+    SMP_OOB_LOCAL,
+    SMP_OOB_BOTH
+};
+typedef UINT8   tSMP_OOB_DATA_TYPE;
+
 #define SMP_AUTH_NO_BOND        0x00
 #define SMP_AUTH_GEN_BOND       0x01 //todo sdh change GEN_BOND to BOND
 
 /* SMP Authentication requirement */
-#define SMP_AUTH_YN_BIT           (1 << 2)
-#define SMP_AUTH_MASK           (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT)
+#define SMP_AUTH_YN_BIT         (1 << 2)
+#define SMP_SC_SUPPORT_BIT      (1 << 3)
+#define SMP_KP_SUPPORT_BIT      (1 << 4)
 
+#define SMP_AUTH_MASK    (SMP_AUTH_GEN_BOND|SMP_AUTH_YN_BIT|SMP_SC_SUPPORT_BIT|SMP_KP_SUPPORT_BIT)
 
 #define SMP_AUTH_BOND           SMP_AUTH_GEN_BOND
 
-#define SMP_AUTH_NB_ENC_ONLY    0x00 //(SMP_AUTH_MASK | BTM_AUTH_SP_NO)   /* no MITM, No Bonding, Encryptino only */
-#define SMP_AUTH_NB_IOCAP       (SMP_AUTH_NO_BOND | SMP_AUTH_YN_BIT)   /* MITM, No Bonding, Use IO Capability
-                                        to detrermine authenticaion procedure */
-#define SMP_AUTH_GB_ENC_ONLY    (SMP_AUTH_GEN_BOND )   /* no MITM, General Bonding, Encryptino only */
-#define SMP_AUTH_GB_IOCAP       (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT)  /* MITM, General Bonding, Use IO Capability
-                                        to detrermine authenticaion procedure   */
+/* no MITM, No Bonding, encryption only */
+#define SMP_AUTH_NB_ENC_ONLY    0x00 //(SMP_AUTH_MASK | BTM_AUTH_SP_NO)
+
+/* MITM, No Bonding, Use IO Capability to determine authentication procedure */
+#define SMP_AUTH_NB_IOCAP       (SMP_AUTH_NO_BOND | SMP_AUTH_YN_BIT)
+
+/* No MITM, General Bonding, Encryption only */
+#define SMP_AUTH_GB_ENC_ONLY    (SMP_AUTH_GEN_BOND )
+
+/* MITM, General Bonding, Use IO Capability to determine authentication procedure */
+#define SMP_AUTH_GB_IOCAP       (SMP_AUTH_GEN_BOND | SMP_AUTH_YN_BIT)
+
+/* Secure Connections, no MITM, no Bonding */
+#define SMP_AUTH_SC_ENC_ONLY    (SMP_SC_SUPPORT_BIT)
+
+/* Secure Connections, no MITM, Bonding */
+#define SMP_AUTH_SC_GB          (SMP_SC_SUPPORT_BIT | SMP_AUTH_GEN_BOND)
+
+/* Secure Connections, MITM, no Bonding */
+#define SMP_AUTH_SC_MITM_NB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_NO_BOND)
+
+/* Secure Connections, MITM, Bonding */
+#define SMP_AUTH_SC_MITM_GB     (SMP_SC_SUPPORT_BIT | SMP_AUTH_YN_BIT | SMP_AUTH_GEN_BOND)
+
+ /* All AuthReq RFU bits are set to 1 - NOTE: reserved bit in Bonding_Flags is not set */
+#define SMP_AUTH_ALL_RFU_SET    0xF8
+
 typedef UINT8 tSMP_AUTH_REQ;
 
 #define SMP_SEC_NONE                 0
@@ -112,14 +185,23 @@ typedef UINT8 tSMP_AUTH_REQ;
 #define SMP_SEC_AUTHENTICATED       (1 << 2)
 typedef UINT8 tSMP_SEC_LEVEL;
 
+/* Maximum Encryption Key Size range */
+#define SMP_ENCR_KEY_SIZE_MIN       7
+#define SMP_ENCR_KEY_SIZE_MAX       16
+
 /* SMP key types */
 #define SMP_SEC_KEY_TYPE_ENC                (1 << 0)    /* encryption key */
 #define SMP_SEC_KEY_TYPE_ID                 (1 << 1)    /* identity key */
 #define SMP_SEC_KEY_TYPE_CSRK               (1 << 2)    /* slave CSRK */
+#define SMP_SEC_KEY_TYPE_LK                 (1 << 3)    /* BR/EDR link key */
 typedef UINT8 tSMP_KEYS;
 
+#define SMP_BR_SEC_DEFAULT_KEY   (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
+                                  SMP_SEC_KEY_TYPE_CSRK)
+
 /* default security key distribution value */
-#define SMP_SEC_DEFAULT_KEY                  (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK)
+#define SMP_SEC_DEFAULT_KEY      (SMP_SEC_KEY_TYPE_ENC | SMP_SEC_KEY_TYPE_ID | \
+                                  SMP_SEC_KEY_TYPE_CSRK | SMP_SEC_KEY_TYPE_LK)
 
 /* data type for BTM_SP_IO_REQ_EVT */
 typedef struct
@@ -134,17 +216,55 @@ typedef struct
 
 typedef struct
 {
-    tSMP_STATUS     reason;
-    tSMP_SEC_LEVEL  sec_level;
-    BOOLEAN         is_pair_cancel;
+    tSMP_STATUS       reason;
+    tSMP_SEC_LEVEL    sec_level;
+    BOOLEAN     is_pair_cancel;
 } tSMP_CMPL;
 
+typedef struct
+{
+    BT_OCTET32  x;
+    BT_OCTET32  y;
+} tSMP_PUBLIC_KEY;
+
+/* the data associated with the info sent to the peer via OOB interface */
+typedef struct
+{
+    BOOLEAN         present;
+    BT_OCTET16      randomizer;
+    BT_OCTET16      commitment;
+
+    tBLE_BD_ADDR    addr_sent_to;
+    BT_OCTET32      private_key_used;   /* is used to calculate: */
+                    /* publ_key_used = P-256(private_key_used, curve_p256.G) - send it to the */
+                    /* other side */
+                    /* dhkey = P-256(private_key_used, publ key rcvd from the other side) */
+    tSMP_PUBLIC_KEY publ_key_used; /* P-256(private_key_used, curve_p256.G) */
+} tSMP_LOC_OOB_DATA;
+
+/* the data associated with the info received from the peer via OOB interface */
+typedef struct
+{
+    BOOLEAN         present;
+    BT_OCTET16      randomizer;
+    BT_OCTET16      commitment;
+    tBLE_BD_ADDR    addr_rcvd_from;
+} tSMP_PEER_OOB_DATA;
+
+typedef struct
+{
+    tSMP_LOC_OOB_DATA   loc_oob_data;
+    tSMP_PEER_OOB_DATA  peer_oob_data;
+} tSMP_SC_OOB_DATA;
+
+
 typedef union
 {
     UINT32          passkey;
     tSMP_IO_REQ     io_req;     /* IO request */
     tSMP_CMPL       cmplt;
-
+    tSMP_OOB_DATA_TYPE  req_oob_type;
+    tSMP_LOC_OOB_DATA   loc_oob_data;
 }tSMP_EVT_DATA;
 
 
@@ -157,9 +277,7 @@ typedef struct
     UINT8   param_buf[BT_OCTET16_LEN];
 } tSMP_ENC;
 
-/* Simple Pairing Events.  Called by the stack when Simple Pairing related
-** events occur.
-*/
+/* Security Manager events - Called by the stack when Security Manager related events occur.*/
 typedef UINT8 (tSMP_CALLBACK) (tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data);
 
 /* callback function for CMAC algorithm
@@ -219,6 +337,18 @@ extern BOOLEAN SMP_Register (tSMP_CALLBACK *p_cback);
 **
 *******************************************************************************/
 extern tSMP_STATUS SMP_Pair (BD_ADDR bd_addr);
+
+/*******************************************************************************
+**
+** Function         SMP_BR_PairWith
+**
+** Description      This function is called to start a SMP pairing over BR/EDR.
+**
+** Returns          SMP_STARTED if pairing started, otherwise reason for failure.
+**
+*******************************************************************************/
+extern tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr);
+
 /*******************************************************************************
 **
 ** Function         SMP_PairCancel
@@ -253,7 +383,7 @@ extern void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res);
 **                  Passkey request to the application.
 **
 ** Parameters:      bd_addr      - Address of the device for which PIN was requested
-**                  res          - result of the operation BTM_SUCCESS if success
+**                  res          - result of the operation SMP_SUCCESS if success
 **                  passkey      - numeric value in the range of
 **                  BTM_MIN_PASSKEY_VAL(0) - BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
 **
@@ -262,14 +392,28 @@ extern void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey);
 
 /*******************************************************************************
 **
+** Function         SMP_ConfirmReply
+**
+** Description      This function is called after Security Manager submitted
+**                  numeric comparison request to the application.
+**
+** Parameters:      bd_addr      - Address of the device with which numeric
+**                                 comparison was requested
+**                  res          - comparison result SMP_SUCCESS if success
+**
+*******************************************************************************/
+extern void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res);
+
+/*******************************************************************************
+**
 ** Function         SMP_OobDataReply
 **
 ** Description      This function is called to provide the OOB data for
-**                  Simple Pairing in response to BTM_SP_RMT_OOB_EVT
+**                  SMP in response to SMP_OOB_REQ_EVT
 **
 ** Parameters:      bd_addr     - Address of the peer device
 **                  res         - result of the operation SMP_SUCCESS if success
-**                  p_data      - simple pairing Randomizer  C.
+**                  p_data      - SM Randomizer  C.
 **
 *******************************************************************************/
 extern void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len,
@@ -277,6 +421,18 @@ extern void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len,
 
 /*******************************************************************************
 **
+** Function         SMP_SecureConnectionOobDataReply
+**
+** Description      This function is called to provide the SC OOB data for
+**                  SMP in response to SMP_SC_OOB_REQ_EVT
+**
+** Parameters:      p_data      - pointer to the data
+**
+*******************************************************************************/
+extern void SMP_SecureConnectionOobDataReply(UINT8 *p_data);
+
+/*******************************************************************************
+**
 ** Function         SMP_Encrypt
 **
 ** Description      This function is called to encrypt the data with the specified
@@ -295,6 +451,34 @@ extern BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
                             UINT8 *plain_text, UINT8 pt_len,
                             tSMP_ENC *p_out);
 
+/*******************************************************************************
+**
+** Function         SMP_KeypressNotification
+**
+** Description      This function is called to notify SM about Keypress Notification.
+**
+** Parameters:      bd_addr      - Address of the device to send keypress
+**                                 notification to
+**                  value        - keypress notification parameter value
+**
+*******************************************************************************/
+extern void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value);
+
+/*******************************************************************************
+**
+** Function         SMP_CreateLocalSecureConnectionsOobData
+**
+** Description      This function is called to start creation of local SC OOB
+**                  data set (tSMP_LOC_OOB_DATA).
+**
+** Parameters:      bd_addr      - Address of the device to send OOB data block
+**                                 to.
+**
+**  Returns         Boolean - TRUE: creation of local SC OOB data set started.
+*******************************************************************************/
+extern BOOLEAN SMP_CreateLocalSecureConnectionsOobData (
+                                                                  tBLE_BD_ADDR *addr_to_send_to);
+
 #ifdef __cplusplus
 }
 #endif
index 839ad1b..3a8d5de 100644 (file)
@@ -833,17 +833,22 @@ BOOLEAN L2CA_SetIdleTimeout (UINT16 cid, UINT16 timeout, BOOLEAN is_global)
 ** NOTE             This timeout applies to all logical channels active on the
 **                  ACL link.
 *******************************************************************************/
-BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout)
+BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout, tBT_TRANSPORT transport)
 {
     tL2C_LCB        *p_lcb;
 
     if (memcmp (BT_BD_ANY, bd_addr, BD_ADDR_LEN))
     {
-        p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, BT_TRANSPORT_BR_EDR);
+        p_lcb = l2cu_find_lcb_by_bd_addr( bd_addr, transport);
         if ((p_lcb) && (p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
+        {
             p_lcb->idle_timeout = timeout;
+
+            if (!p_lcb->ccb_queue.p_first_ccb)
+                l2cu_no_dynamic_ccbs (p_lcb);
+        }
         else
-            return (FALSE);
+            return FALSE;
     }
     else
     {
@@ -855,11 +860,14 @@ BOOLEAN L2CA_SetIdleTimeoutByBdAddr(BD_ADDR bd_addr, UINT16 timeout)
             if ((p_lcb->in_use) && (p_lcb->link_state == LST_CONNECTED))
             {
                 p_lcb->idle_timeout = timeout;
+
+                if (!p_lcb->ccb_queue.p_first_ccb)
+                    l2cu_no_dynamic_ccbs (p_lcb);
             }
         }
     }
 
-    return (TRUE);
+    return TRUE;
 }
 
 /*******************************************************************************
@@ -1639,18 +1647,6 @@ BOOLEAN L2CA_RemoveFixedChnl (UINT16 fixed_cid, BD_ADDR rem_bda)
     p_lcb->p_fixed_ccbs[fixed_cid - L2CAP_FIRST_FIXED_CHNL] = NULL;
     p_lcb->disc_reason = HCI_ERR_CONN_CAUSE_LOCAL_HOST;
 
-#if BLE_INCLUDED == TRUE
-    /* retain the link for a few more seconds after SMP pairing is done, since Android
-    platformalways do service discovery after pairing complete. This way would avoid
-    the link down (pairing is complete) and an immediate reconnection for service
-    discovery. Some devices do not do auto advertising when link is dropped, thus fail
-    the second connection and service discovery.
-    BEFORE :if ((fixed_cid == L2CAP_ATT_CID || fixed_cid == L2CAP_SMP_CID)
-                       && !p_lcb->ccb_queue.p_first_ccb)*/
-    if ((fixed_cid == L2CAP_ATT_CID ) && !p_lcb->ccb_queue.p_first_ccb)
-        p_lcb->idle_timeout = 0;
-#endif
-
     l2cu_release_ccb (p_ccb);
 
     return (TRUE);
@@ -1700,7 +1696,7 @@ BOOLEAN L2CA_SetFixedChannelTout (BD_ADDR rem_bda, UINT16 fixed_cid, UINT16 idle
         l2cu_no_dynamic_ccbs (p_lcb);
     }
 
-    return (TRUE);
+    return TRUE;
 }
 
 #endif /* #if (L2CAP_NUM_FIXED_CHNLS > 0) */
index a2b0a75..94ddf42 100644 (file)
@@ -35,7 +35,6 @@
 #if (BLE_INCLUDED == TRUE)
 static void l2cble_start_conn_update (tL2C_LCB *p_lcb);
 
-#include "vendor_ble.h"
 /*******************************************************************************
 **
 **  Function        L2CA_CancelBleConnectReq
@@ -463,6 +462,8 @@ void l2cble_advertiser_conn_comp (UINT16 handle, BD_ADDR bda, tBLE_ADDR_TYPE typ
 void l2cble_conn_comp(UINT16 handle, UINT8 role, BD_ADDR bda, tBLE_ADDR_TYPE type,
                       UINT16 conn_interval, UINT16 conn_latency, UINT16 conn_timeout)
 {
+    btm_ble_update_link_topology_mask(role, TRUE);
+
     if (role == HCI_ROLE_MASTER)
     {
         l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency, conn_timeout);
@@ -688,12 +689,13 @@ void l2cble_process_sig_cmd (tL2C_LCB *p_lcb, UINT8 *p, UINT16 pkt_len)
 *******************************************************************************/
 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;
+    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;
+    UINT16 scan_win;
+    BD_ADDR peer_addr;
+    UINT8 peer_addr_type = BLE_ADDR_PUBLIC;
+    UINT8 own_addr_type = BLE_ADDR_PUBLIC;
 
     /* There can be only one BLE connection request outstanding at a time */
     if (p_dev_rec == NULL)
@@ -705,22 +707,21 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
     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);
+    peer_addr_type = p_lcb->ble_addr_type;
+    memcpy(peer_addr, p_lcb->remote_bd_addr, BD_ADDR_LEN);
 
-#if BLE_PRIVACY_SPT == TRUE
-    /* if RPA offloading supported */
-    if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
-        btm_random_pseudo_to_public(init_addr, &init_addr_type);
-    /* otherwise, if remote is RPA enabled, use latest RPA */
-    else if (p_dev_rec->ble.active_addr_type == BTM_BLE_ADDR_RRA)
+#if ( (defined BLE_PRIVACY_SPT) && (BLE_PRIVACY_SPT == TRUE))
+    own_addr_type = btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
+    if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT)
     {
-        init_addr_type = BLE_ADDR_RANDOM;
-        memcpy(init_addr, p_dev_rec->ble.cur_rand_addr, BD_ADDR_LEN);
+        if (btm_cb.ble_ctr_cb.privacy_mode >=  BTM_PRIVACY_1_2)
+            own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+
+        btm_ble_enable_resolving_list();
+        btm_random_pseudo_to_identity_addr(peer_addr, &peer_addr_type);
     }
-    /* if privacy is on and current do not consider using reconnection address */
-    if (btm_cb.ble_ctr_cb.privacy ) /* && p_dev_rec->ble.use_reconn_addr */
-        own_addr_type = BLE_ADDR_RANDOM;
+    else
+        btm_ble_disable_resolving_list();
 #endif
 
     if (!btm_ble_topology_check(BTM_BLE_STATE_INIT))
@@ -733,8 +734,8 @@ BOOLEAN l2cble_init_direct_conn (tL2C_LCB *p_lcb)
     if (!btsnd_hcic_ble_create_ll_conn (scan_int,/* UINT16 scan_int      */
                                         scan_win, /* UINT16 scan_win      */
                                         FALSE,                   /* UINT8 white_list     */
-                                        init_addr_type,          /* UINT8 addr_type_peer */
-                                        init_addr,               /* BD_ADDR bda_peer     */
+                                        peer_addr_type,          /* UINT8 addr_type_peer */
+                                        peer_addr,               /* BD_ADDR bda_peer     */
                                         own_addr_type,         /* 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_DEF),  /* UINT16 conn_int_min  */
@@ -879,7 +880,7 @@ void l2c_ble_link_adjust_allocation (void)
     if (num_lowpri_links > low_quota)
     {
         l2cb.ble_round_robin_quota = low_quota;
-        qq = qq_remainder = 1;
+        qq = qq_remainder = 0;
     }
     /* If each low priority link can have at least one buffer */
     else if (num_lowpri_links > 0)
@@ -894,7 +895,7 @@ void l2c_ble_link_adjust_allocation (void)
     {
         l2cb.ble_round_robin_quota = 0;
         l2cb.ble_round_robin_unacked = 0;
-        qq = qq_remainder = 1;
+        qq = qq_remainder = 0;
     }
     L2CAP_TRACE_EVENT ("l2c_ble_link_adjust_allocation  num_hipri: %u  num_lowpri: %u  low_quota: %u  round_robin_quota: %u  qq: %u",
                         num_hipri_links, num_lowpri_links, low_quota,
index 836f4ba..fa2fcce 100644 (file)
@@ -385,6 +385,11 @@ BOOLEAN l2c_link_hci_disc_comp (UINT16 handle, UINT8 reason)
         /* Just in case app decides to try again in the callback context */
         p_lcb->link_state = LST_DISCONNECTING;
 
+#if (BLE_INCLUDED == TRUE)
+        /* Check for BLE and handle that differently */
+        if (p_lcb->transport == BT_TRANSPORT_LE)
+            btm_ble_update_link_topology_mask(p_lcb->link_role, FALSE);
+#endif
         /* Link is disconnected. For all channels, send the event through */
         /* their FSMs. The CCBs should remove themselves from the LCB     */
         for (p_ccb = p_lcb->ccb_queue.p_first_ccb; p_ccb; )
@@ -1142,20 +1147,17 @@ void l2c_link_check_send_pkts (tL2C_LCB *p_lcb, tL2C_CCB *p_ccb, BT_HDR *p_buf)
         for (xx = 0; xx < MAX_L2CAP_LINKS; xx++, p_lcb++)
         {
             /* If controller window is full, nothing to do */
+            if (((l2cb.controller_xmit_window == 0 ||
+                  (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
 #if (BLE_INCLUDED == TRUE)
-              if ( (l2cb.controller_xmit_window == 0 
-                && (p_lcb->transport == BT_TRANSPORT_BR_EDR))
-                || (p_lcb->transport == BT_TRANSPORT_LE 
-                  && l2cb.controller_le_xmit_window == 0 )
-                || (l2cb.round_robin_unacked >= l2cb.round_robin_quota
-                  && (p_lcb->transport == BT_TRANSPORT_BR_EDR))
-                || ((p_lcb->transport == BT_TRANSPORT_LE) 
-                  && (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota)))
-#else 
-            if ((l2cb.controller_xmit_window == 0) 
-              || (l2cb.round_robin_unacked >= l2cb.round_robin_quota))
+                && (p_lcb->transport == BT_TRANSPORT_BR_EDR)
 #endif
-                break;
+                )
+              || (p_lcb->transport == BT_TRANSPORT_LE &&
+                 (l2cb.ble_round_robin_unacked >= l2cb.ble_round_robin_quota ||
+                  l2cb.controller_le_xmit_window == 0 )))
+            break;
+
 
             /* Check for wraparound */
             if (p_lcb == &l2cb.lcb_pool[MAX_L2CAP_LINKS])
index 00ff2e7..d3ee908 100644 (file)
@@ -2815,13 +2815,15 @@ void l2cu_no_dynamic_ccbs (tL2C_LCB *p_lcb)
 void l2cu_process_fixed_chnl_resp (tL2C_LCB *p_lcb)
 {
 #if (BLE_INCLUDED == TRUE)
-    /* always exclude LE fixed channel on BR/EDR fix channel capability */
-    if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
-        p_lcb->peer_chnl_mask[0] &= ~(L2CAP_FIXED_CHNL_ATT_BIT| \
-                                      L2CAP_FIXED_CHNL_BLE_SIG_BIT| \
-                                      L2CAP_FIXED_CHNL_SMP_BIT);
-    else
-        p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
+     if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
+     {
+         /* ignore all not assigned BR/EDR channels */
+         p_lcb->peer_chnl_mask[0] &= (L2CAP_FIXED_CHNL_SIG_BIT| \
+                                      L2CAP_FIXED_CHNL_CNCTLESS_BIT| \
+                                      L2CAP_FIXED_CHNL_SMP_BR_BIT);
+     }
+     else
+         p_lcb->peer_chnl_mask[0] = l2cb.l2c_ble_fixed_chnls_mask;
 #endif
 
     /* Tell all registered fixed channels about the connection */
@@ -3305,6 +3307,10 @@ BT_HDR *l2cu_get_next_buffer_to_send (tL2C_LCB *p_lcb)
                     L2CAP_TRACE_ERROR("l2cu_get_buffer_to_send: No data to be sent");
                     return (NULL);
                 }
+                /* send tx complete */
+                if (l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)
+                    (*l2cb.fixed_reg[xx].pL2CA_FixedTxComplete_Cb)(p_ccb->local_cid, 1);
+
                 l2cu_check_channel_congestion (p_ccb);
                 l2cu_set_acl_hci_header (p_buf, p_ccb);
                 return (p_buf);
@@ -3433,9 +3439,7 @@ void l2cu_check_channel_congestion (tL2C_CCB *p_ccb)
         q_count += p_ccb->p_lcb->ucd_out_sec_pending_q.count;
     }
 #endif
-
     /* If the CCB queue limit is subject to a quota, check for congestion */
-
     /* if this channel has outgoing traffic */
     if (p_ccb->buff_quota != 0)
     {
index d2e86cd..54bcda6 100644 (file)
@@ -45,6 +45,9 @@
 
 #include <stdlib.h>
 
+/* add the target configuration to allow using internal data types and compilation options */
+#include "bt_target.h"
+
 /* define if you have fast 32-bit types on your system */
 #if 1
 #  define HAVE_UINT_32T
@@ -65,7 +68,7 @@
 #include "aes.h"
 
 #if defined( HAVE_UINT_32T )
-  typedef unsigned long uint_32t;
+  typedef UINT32 uint_32t;
 #endif
 
 /* functions for finite field multiplication in the AES Galois field    */
@@ -494,6 +497,11 @@ static void inv_shift_sub_rows( uint_8t st[N_BLOCK] )
 #if defined( AES_ENC_PREKEYED ) || defined( AES_DEC_PREKEYED )
 
 /*  Set the cipher key for the pre-keyed version */
+/*  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).
+*/
 
 return_type aes_set_key( const unsigned char key[], length_type keylen, aes_context ctx[1] )
 {
@@ -502,15 +510,15 @@ return_type aes_set_key( const unsigned char key[], length_type keylen, aes_cont
     switch( keylen )
     {
     case 16:
-    case 128:
+    case 128:           /* length in bits (128 = 8*16) */
         keylen = 16;
         break;
     case 24:
-    case 192:
+    case 192:           /* length in bits (192 = 8*24) */
         keylen = 24;
         break;
     case 32:
-    /*    case 256:           length in bits (256 = 8*32) */
+/*    case 256:           length in bits (256 = 8*32) */
         keylen = 32;
         break;
     default:
diff --git a/stack/smp/p_256_curvepara.c b/stack/smp/p_256_curvepara.c
new file mode 100644 (file)
index 0000000..131e769
--- /dev/null
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+  *
+  *  This file contains simple pairing algorithms
+  *
+  ******************************************************************************/
+
+#include <string.h>
+#include "p_256_ecc_pp.h"
+
+void p_256_init_curve(UINT32 keyLength)
+{
+    elliptic_curve_t *ec;
+
+    if(keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        ec = &curve_p256;
+
+        ec->p[7] = 0xFFFFFFFF;
+        ec->p[6] = 0x00000001;
+        ec->p[5] = 0x0;
+        ec->p[4] = 0x0;
+        ec->p[3] = 0x0;
+        ec->p[2] = 0xFFFFFFFF;
+        ec->p[1] = 0xFFFFFFFF;
+        ec->p[0] = 0xFFFFFFFF;
+
+        memset(ec->omega, 0, KEY_LENGTH_DWORDS_P256);
+        memset(ec->a, 0, KEY_LENGTH_DWORDS_P256);
+
+        ec->a_minus3 = TRUE;
+
+        //b
+        ec->b[7] =  0x5ac635d8;
+        ec->b[6] =  0xaa3a93e7;
+        ec->b[5] =  0xb3ebbd55;
+        ec->b[4] =  0x769886bc;
+        ec->b[3] =  0x651d06b0;
+        ec->b[2] =  0xcc53b0f6;
+        ec->b[1] =  0x3bce3c3e;
+        ec->b[0] =  0x27d2604b;
+
+        //base point
+        ec->G.x[7] =  0x6b17d1f2;
+        ec->G.x[6] =  0xe12c4247;
+        ec->G.x[5] =  0xf8bce6e5;
+        ec->G.x[4] =  0x63a440f2;
+        ec->G.x[3] =  0x77037d81;
+        ec->G.x[2] =  0x2deb33a0;
+        ec->G.x[1] =  0xf4a13945;
+        ec->G.x[0] =  0xd898c296;
+
+        ec->G.y[7] =  0x4fe342e2;
+        ec->G.y[6] =  0xfe1a7f9b;
+        ec->G.y[5] =  0x8ee7eb4a;
+        ec->G.y[4] =  0x7c0f9e16;
+        ec->G.y[3] =  0x2bce3357;
+        ec->G.y[2] =  0x6b315ece;
+        ec->G.y[1] =  0xcbb64068;
+        ec->G.y[0] =  0x37bf51f5;
+    }
+}
+
diff --git a/stack/smp/p_256_ecc_pp.c b/stack/smp/p_256_ecc_pp.c
new file mode 100644 (file)
index 0000000..2eaebd4
--- /dev/null
@@ -0,0 +1,262 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+  *
+  *  This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
+  *
+  ******************************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "p_256_ecc_pp.h"
+#include "p_256_multprecision.h"
+
+elliptic_curve_t curve;
+elliptic_curve_t curve_p256;
+
+static void p_256_init_point(Point *q)
+{
+    memset(q, 0, sizeof(Point));
+}
+
+static void p_256_copy_point(Point *q, Point *p)
+{
+    memcpy(q, p, sizeof(Point));
+}
+
+// q=2q
+static void ECC_Double(Point *q, Point *p, uint32_t keyLength)
+{
+    DWORD t1[KEY_LENGTH_DWORDS_P256];
+    DWORD t2[KEY_LENGTH_DWORDS_P256];
+    DWORD t3[KEY_LENGTH_DWORDS_P256];
+    DWORD *x1;
+    DWORD *x3;
+    DWORD *y1;
+    DWORD *y3;
+    DWORD *z1;
+    DWORD *z3;
+
+    if (multiprecision_iszero(p->z, keyLength))
+    {
+        multiprecision_init(q->z, keyLength);
+        return;                                     // return infinity
+    }
+
+    x1=p->x; y1=p->y; z1=p->z;
+    x3=q->x; y3=q->y; z3=q->z;
+
+    multiprecision_mersenns_squa_mod(t1, z1, keyLength);  // t1=z1^2
+    multiprecision_sub_mod(t2, x1, t1, keyLength);  // t2=x1-t1
+    multiprecision_add_mod(t1, x1, t1, keyLength);  // t1=x1+t1
+    multiprecision_mersenns_mult_mod(t2, t1, t2, keyLength);  // t2=t2*t1
+    multiprecision_lshift_mod(t3, t2, keyLength);
+    multiprecision_add_mod(t2, t3, t2, keyLength);  // t2=3t2
+
+    multiprecision_mersenns_mult_mod(z3, y1, z1, keyLength);  // z3=y1*z1
+    multiprecision_lshift_mod(z3, z3, keyLength);
+
+    multiprecision_mersenns_squa_mod(y3, y1, keyLength);  // y3=y1^2
+    multiprecision_lshift_mod(y3, y3, keyLength);
+    multiprecision_mersenns_mult_mod(t3, y3, x1, keyLength);  // t3=y3*x1=x1*y1^2
+    multiprecision_lshift_mod(t3, t3, keyLength);
+    multiprecision_mersenns_squa_mod(y3, y3, keyLength);  // y3=y3^2=y1^4
+    multiprecision_lshift_mod(y3, y3, keyLength);
+
+    multiprecision_mersenns_squa_mod(x3, t2, keyLength);  // x3=t2^2
+    multiprecision_lshift_mod(t1, t3, keyLength);                // t1=2t3
+    multiprecision_sub_mod(x3, x3, t1, keyLength);               // x3=x3-t1
+    multiprecision_sub_mod(t1, t3, x3, keyLength);               // t1=t3-x3
+    multiprecision_mersenns_mult_mod(t1, t1, t2, keyLength);  // t1=t1*t2
+    multiprecision_sub_mod(y3, t1, y3, keyLength);               // y3=t1-y3
+}
+
+// q=q+p,     zp must be 1
+static void ECC_Add(Point *r, Point *p, Point *q, uint32_t keyLength)
+{
+    DWORD t1[KEY_LENGTH_DWORDS_P256];
+    DWORD t2[KEY_LENGTH_DWORDS_P256];
+    DWORD *x1;
+    DWORD *x2;
+    DWORD *x3;
+    DWORD *y1;
+    DWORD *y2;
+    DWORD *y3;
+    DWORD *z1;
+    DWORD *z2;
+    DWORD *z3;
+
+    x1=p->x; y1=p->y; z1=p->z;
+    x2=q->x; y2=q->y; z2=q->z;
+    x3=r->x; y3=r->y; z3=r->z;
+
+    // if Q=infinity, return p
+    if (multiprecision_iszero(z2, keyLength))
+    {
+        p_256_copy_point(r, p);
+        return;
+    }
+
+    // if P=infinity, return q
+    if (multiprecision_iszero(z1, keyLength))
+    {
+        p_256_copy_point(r, q);
+        return;
+    }
+
+    multiprecision_mersenns_squa_mod(t1, z1, keyLength);      // t1=z1^2
+    multiprecision_mersenns_mult_mod(t2, z1, t1, keyLength);  // t2=t1*z1
+    multiprecision_mersenns_mult_mod(t1, x2, t1, keyLength);  // t1=t1*x2
+    multiprecision_mersenns_mult_mod(t2, y2, t2, keyLength);  // t2=t2*y2
+
+    multiprecision_sub_mod(t1, t1, x1, keyLength);  // t1=t1-x1
+    multiprecision_sub_mod(t2, t2, y1, keyLength);  // t2=t2-y1
+
+    if (multiprecision_iszero(t1, keyLength))
+    {
+        if (multiprecision_iszero(t2, keyLength))
+        {
+            ECC_Double(r, q, keyLength) ;
+            return;
+        }
+        else
+        {
+            multiprecision_init(z3, keyLength);
+            return;                             // return infinity
+        }
+    }
+
+    multiprecision_mersenns_mult_mod(z3, z1, t1, keyLength);  // z3=z1*t1
+    multiprecision_mersenns_squa_mod(y3, t1, keyLength);      // t3=t1^2
+    multiprecision_mersenns_mult_mod(z1, y3, t1, keyLength);  // t4=t3*t1
+    multiprecision_mersenns_mult_mod(y3, y3, x1, keyLength);  // t3=t3*x1
+    multiprecision_lshift_mod(t1, y3, keyLength);            // t1=2*t3
+    multiprecision_mersenns_squa_mod(x3, t2, keyLength);      // x3=t2^2
+    multiprecision_sub_mod(x3, x3, t1, keyLength);           // x3=x3-t1
+    multiprecision_sub_mod(x3, x3, z1, keyLength);           // x3=x3-t4
+    multiprecision_sub_mod(y3, y3, x3, keyLength);           // t3=t3-x3
+    multiprecision_mersenns_mult_mod(y3, y3, t2, keyLength);  // t3=t3*t2
+    multiprecision_mersenns_mult_mod(z1, z1, y1, keyLength);  // t4=t4*t1
+    multiprecision_sub_mod(y3, y3, z1, keyLength);
+}
+
+// Computing the Non-Adjacent Form of a positive integer
+static void ECC_NAF(uint8_t *naf, uint32_t *NumNAF, DWORD *k, uint32_t keyLength)
+{
+    uint32_t sign;
+    int i=0;
+    int j;
+    uint32_t var;
+
+    while ((var = multiprecision_most_signbits(k, keyLength))>=1)
+    {
+        if (k[0] & 0x01)  // k is odd
+        {
+            sign = (k[0] & 0x03);  // 1 or 3
+
+            // k = k-naf[i]
+            if (sign == 1)
+                k[0] = k[0] & 0xFFFFFFFE;
+            else
+            {
+                k[0] = k[0] + 1;
+                if (k[0] == 0)  //overflow
+                {
+                    j = 1;
+                    do
+                    {
+                        k[j]++;
+                    } while (k[j++]==0);  //overflow
+                }
+            }
+        }
+        else
+            sign = 0;
+
+        multiprecision_rshift(k, k, keyLength);
+        naf[i / 4] |= (sign) << ((i % 4) * 2);
+        i++;
+    }
+
+    *NumNAF=i;
+}
+
+// Binary Non-Adjacent Form for point multiplication
+void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength)
+{
+    uint32_t sign;
+    UINT8 naf[256 / 4 +1];
+    uint32_t NumNaf;
+    Point minus_p;
+    Point r;
+    DWORD *modp;
+
+    if (keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        modp = curve_p256.p;
+    }
+    else
+    {
+        modp = curve.p;
+    }
+
+    p_256_init_point(&r);
+    multiprecision_init(p->z, keyLength);
+    p->z[0] = 1;
+
+    // initialization
+    p_256_init_point(q);
+
+    // -p
+    multiprecision_copy(minus_p.x, p->x, keyLength);
+    multiprecision_sub(minus_p.y, modp, p->y, keyLength);
+
+    multiprecision_init(minus_p.z, keyLength);
+    minus_p.z[0]=1;
+
+    // NAF
+    memset(naf, 0, sizeof(naf));
+    ECC_NAF(naf, &NumNaf, n, keyLength);
+
+    for (int i = NumNaf - 1; i >= 0; i--)
+    {
+        p_256_copy_point(&r, q);
+        ECC_Double(q, &r, keyLength);
+        sign = (naf[i / 4] >> ((i % 4) * 2)) & 0x03;
+
+        if (sign == 1)
+        {
+            p_256_copy_point(&r, q);
+            ECC_Add(q, &r, p, keyLength);
+        }
+        else if (sign == 3)
+        {
+            p_256_copy_point(&r, q);
+            ECC_Add(q, &r, &minus_p, keyLength);
+        }
+    }
+
+    multiprecision_inv_mod(minus_p.x, q->z, keyLength);
+    multiprecision_mersenns_squa_mod(q->z, minus_p.x, keyLength);
+    multiprecision_mersenns_mult_mod(q->x, q->x, q->z, keyLength);
+    multiprecision_mersenns_mult_mod(q->z, q->z, minus_p.x, keyLength);
+    multiprecision_mersenns_mult_mod(q->y, q->y, q->z, keyLength);
+}
+
+
diff --git a/stack/smp/p_256_ecc_pp.h b/stack/smp/p_256_ecc_pp.h
new file mode 100644 (file)
index 0000000..fd3dc64
--- /dev/null
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+  *
+  *  This file contains simple pairing algorithms using Elliptic Curve Cryptography for private public key
+  *
+  ******************************************************************************/
+
+#pragma once
+
+#include "p_256_multprecision.h"
+
+typedef unsigned long  DWORD;
+
+typedef struct {
+    DWORD x[KEY_LENGTH_DWORDS_P256];
+    DWORD y[KEY_LENGTH_DWORDS_P256];
+    DWORD z[KEY_LENGTH_DWORDS_P256];
+} Point;
+
+typedef struct {
+    // curve's coefficients
+    DWORD a[KEY_LENGTH_DWORDS_P256];
+    DWORD b[KEY_LENGTH_DWORDS_P256];
+
+    //whether a is -3
+    int a_minus3;
+
+    // prime modulus
+    DWORD p[KEY_LENGTH_DWORDS_P256];
+
+    // Omega, p = 2^m -omega
+    DWORD omega[KEY_LENGTH_DWORDS_P256];
+
+    // base point, a point on E of order r
+    Point G;
+
+} elliptic_curve_t;
+
+extern elliptic_curve_t curve;
+extern elliptic_curve_t curve_p256;
+
+void ECC_PointMult_Bin_NAF(Point *q, Point *p, DWORD *n, uint32_t keyLength);
+
+#define ECC_PointMult(q, p, n, keyLength)  ECC_PointMult_Bin_NAF(q, p, n, keyLength)
+
+void p_256_init_curve(UINT32 keyLength);
+
+
diff --git a/stack/smp/p_256_multprecision.c b/stack/smp/p_256_multprecision.c
new file mode 100644 (file)
index 0000000..f939809
--- /dev/null
@@ -0,0 +1,704 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+  *
+  *  This file contains simple pairing algorithms
+  *
+  ******************************************************************************/
+
+#include <string.h>
+#include "bt_target.h"
+#include "p_256_ecc_pp.h"
+#include "p_256_multprecision.h"
+
+void multiprecision_init(DWORD *c, uint32_t keyLength)
+{
+    for (uint32_t i = 0; i < keyLength; i++)
+        c[i] = 0;
+}
+
+void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength)
+{
+    for (uint32_t i = 0; i < keyLength; i++)
+        c[i] = a[i];
+}
+
+int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    for (int i = keyLength - 1; i >= 0; i--)
+    {
+        if (a[i] > b[i])
+            return 1;
+        if (a[i] < b[i])
+            return -1;
+    }
+    return 0;
+}
+
+int multiprecision_iszero(DWORD *a, uint32_t keyLength)
+{
+    for (uint32_t i = 0; i < keyLength; i++)
+        if (a[i])
+            return 0;
+
+    return 1;
+}
+
+UINT32 multiprecision_dword_bits(DWORD a)
+{
+    uint32_t i;
+    for (i = 0; i < DWORD_BITS; i++, a >>= 1)
+        if (a == 0)
+            break;
+
+    return i;
+}
+
+UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength)
+{
+    int  i;
+    for (i = keyLength - 1; i >= 0; i--)
+        if (a[i])
+           break;
+    return (i + 1);
+}
+
+UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength)
+{
+    int aMostSignDWORDs;
+
+    aMostSignDWORDs = multiprecision_most_signdwords(a, keyLength);
+    if (aMostSignDWORDs == 0)
+        return 0;
+
+    return (((aMostSignDWORDs-1) << DWORD_BITS_SHIFT) +
+            multiprecision_dword_bits(a[aMostSignDWORDs-1]) );
+}
+
+DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD carrier;
+    DWORD temp;
+
+    carrier=0;
+    for (uint32_t i = 0; i < keyLength; i++)
+    {
+        temp = a[i] + carrier;
+        carrier = (temp < carrier);
+        temp += b[i];
+        carrier |= (temp < b[i]);
+        c[i]=temp;
+    }
+
+    return carrier;
+}
+
+//c=a-b
+DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD borrow;
+    DWORD temp;
+
+    borrow=0;
+    for (uint32_t i=0; i < keyLength; i++)
+    {
+        temp = a[i] - borrow;
+        borrow = (temp > a[i]);
+        c[i] = temp - b[i];
+        borrow |= (c[i] > temp);
+    }
+
+    return borrow;
+}
+
+// c = a << 1
+void multiprecision_lshift_mod(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+    DWORD carrier;
+    DWORD *modp;
+
+    if (keyLength == KEY_LENGTH_DWORDS_P192)
+    {
+        modp = curve.p;
+    }
+    else if (keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        modp = curve_p256.p;
+    }
+    else
+        return;
+
+    carrier = multiprecision_lshift(c, a, keyLength);
+    if (carrier)
+    {
+        multiprecision_sub(c, c, modp, keyLength);
+    }
+    else if (multiprecision_compare(c, modp, keyLength)>=0)
+    {
+        multiprecision_sub(c, c, modp, keyLength);
+    }
+}
+
+// c=a>>1
+void multiprecision_rshift(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+    int j;
+    DWORD b = 1;
+
+    j = DWORD_BITS - b;
+
+    DWORD carrier = 0;
+    DWORD temp;
+    for (int i = keyLength-1; i >= 0; i--)
+    {
+        temp = a[i]; // in case of c==a
+        c[i] = (temp >> b) | carrier;
+        carrier = temp << j;
+    }
+}
+
+// Curve specific optimization when p is a pseudo-Mersenns prime, p=2^(KEY_LENGTH_BITS)-omega
+void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD cc[2*KEY_LENGTH_DWORDS_P256];
+
+    multiprecision_mult(cc, a, b, keyLength);
+    if (keyLength == 6)
+    {
+        multiprecision_fast_mod(c, cc);
+    }
+    else if (keyLength == 8)
+    {
+        multiprecision_fast_mod_P256(c, cc);
+    }
+}
+
+// Curve specific optimization when p is a pseudo-Mersenns prime
+void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength)
+{
+    multiprecision_mersenns_mult_mod(c, a, a, keyLength);
+}
+
+// c=(a+b) mod p, b<p, a<p
+void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD carrier;
+    DWORD *modp;
+
+    if (keyLength == KEY_LENGTH_DWORDS_P192)
+    {
+        modp = curve.p;
+    }
+    else if (keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        modp = curve_p256.p;
+    }
+    else
+        return;
+
+    carrier = multiprecision_add(c, a, b, keyLength);
+    if (carrier)
+    {
+        multiprecision_sub(c, c, modp, keyLength);
+    }
+    else if (multiprecision_compare(c, modp, keyLength) >= 0)
+    {
+        multiprecision_sub(c, c, modp, keyLength);
+    }
+}
+
+// c=(a-b) mod p, a<p, b<p
+void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD borrow;
+    DWORD *modp;
+
+    if (keyLength == KEY_LENGTH_DWORDS_P192)
+    {
+        modp = curve.p;
+    }
+    else if(keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        modp = curve_p256.p;
+    }
+    else
+        return;
+
+    borrow = multiprecision_sub(c, a, b, keyLength);
+    if(borrow)
+        multiprecision_add(c, c, modp, keyLength);
+}
+
+// c=a<<b, b<DWORD_BITS, c has a buffer size of NumDWORDs+1
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength)
+{
+    int j;
+    uint32_t b = 1;
+    j = DWORD_BITS - b;
+
+    DWORD carrier = 0;
+    DWORD temp;
+
+    for (uint32_t i = 0; i < keyLength; i++)
+    {
+        temp = a[i];  // in case c==a
+        c[i] = (temp << b) | carrier;
+        carrier = temp >> j;
+    }
+
+    return carrier;
+}
+
+// c=a*b; c must have a buffer of 2*Key_LENGTH_DWORDS, c != a != b
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength)
+{
+    DWORD W;
+    DWORD U;
+    DWORD V;
+
+    U = V = W = 0;
+    multiprecision_init(c, keyLength);
+
+    //assume little endian right now
+    for (uint32_t i = 0; i < keyLength; i++)
+    {
+        U = 0;
+        for (uint32_t j = 0; j < keyLength; j++)
+        {
+            uint64_t result;
+            result = ((UINT64)a[i]) * ((uint64_t) b[j]);
+            W = result >> 32;
+            V = a[i] * b[j];
+            V = V + U;
+            U = (V < U);
+            U += W;
+            V = V + c[i+j];
+            U += (V < c[i+j]);
+            c[i+j] = V;
+        }
+        c[i+keyLength] = U;
+    }
+}
+
+void multiprecision_fast_mod(DWORD *c, DWORD *a)
+{
+    DWORD U;
+    DWORD V;
+    DWORD *modp = curve.p;
+
+    c[0] = a[0] + a[6];
+    U=c[0] < a[0];
+    c[0] += a[10];
+    U += c[0] < a[10];
+
+    c[1] = a[1] + U;
+    U = c[1] < a[1];
+    c[1] += a[7];
+    U += c[1] < a[7];
+    c[1] += a[11];
+    U += c[1]< a[11];
+
+    c[2] = a[2] + U;
+    U = c[2] < a[2];
+    c[2] += a[6];
+    U += c[2] < a[6];
+    c[2] += a[8];
+    U += c[2] < a[8];
+    c[2] += a[10];
+    U += c[2] < a[10];
+
+    c[3] = a[3]+U;
+    U = c[3] < a[3];
+    c[3] += a[7];
+    U += c[3] < a[7];
+    c[3] += a[9];
+    U += c[3] < a[9];
+    c[3] += a[11];
+    U += c[3] < a[11];
+
+    c[4] = a[4]+U;
+    U = c[4] < a[4];
+    c[4] += a[8];
+    U += c[4] < a[8];
+    c[4] += a[10];
+    U += c[4] < a[10];
+
+    c[5] = a[5]+U;
+    U = c[5] < a[5];
+    c[5] += a[9];
+    U += c[5] < a[9];
+    c[5] += a[11];
+    U += c[5] < a[11];
+
+    c[0] += U;
+    V = c[0] < U;
+    c[1] += V;
+    V = c[1] < V;
+    c[2] += V;
+    V = c[2] < V;
+    c[2] += U;
+    V = c[2] < U;
+    c[3] += V;
+    V = c[3] < V;
+    c[4] += V;
+    V = c[4] < V;
+    c[5] += V;
+    V = c[5] < V;
+
+    if (V)
+    {
+        multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
+    }
+    else if(multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P192) >= 0)
+    {
+        multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P192);
+    }
+}
+
+void multiprecision_fast_mod_P256(DWORD *c, DWORD *a)
+{
+    DWORD A;
+    DWORD B;
+    DWORD C;
+    DWORD D;
+    DWORD E;
+    DWORD F;
+    DWORD G;
+    uint8_t UA;
+    uint8_t UB;
+    uint8_t UC;
+    uint8_t UD;
+    uint8_t UE;
+    uint8_t UF;
+    uint8_t UG;
+    DWORD U;
+    DWORD *modp = curve_p256.p;
+
+    // C = a[13] + a[14] + a[15];
+    C = a[13];
+    C += a[14];
+    UC = (C < a[14]);
+    C += a[15];
+    UC += (C < a[15]);
+
+    // E = a[8] + a[9];
+    E = a[8];
+    E += a[9];
+    UE = (E < a[9]);
+
+    // F = a[9] + a[10];
+    F = a[9];
+    F += a[10];
+    UF = (F < a[10]);
+
+    // G = a[10] + a[11]
+    G = a[10];
+    G += a[11];
+    UG = (G < a[11]);
+
+    // B = a[12] + a[13] + a[14] + a[15] == C + a[12]
+    B = C;
+    UB = UC;
+    B += a[12];
+    UB += (B < a[12]);
+
+    // A = a[11] + a[12] + a[13] + a[14] == B + a[11] - a[15]
+    A = B;
+    UA = UB;
+    A += a[11];
+    UA += (A < a[11]);
+    UA -= (A < a[15]);
+    A -= a[15];
+
+    // D = a[10] + a[11] + a[12] + a[13] == A + a[10] - a[14]
+    D = A;
+    UD = UA;
+    D += a[10];
+    UD += (D < a[10]);
+    UD -= (D < a[14]);
+    D -= a[14];
+
+    c[0] = a[0];
+    c[0] += E;
+    U = (c[0] < E);
+    U += UE;
+    U -= (c[0] < A);
+    U -= UA;
+    c[0] -= A;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[1] < UU);
+        c[1] = a[1] - UU;
+    }
+    else
+    {
+        c[1] = a[1] + U;
+        U = (c[1] < a[1]);
+    }
+
+    c[1] += F;
+    U += (c[1] < F);
+    U += UF;
+    U -= (c[1] < B);
+    U -= UB;
+    c[1] -= B;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[2] < UU);
+        c[2] = a[2] - UU;
+    }
+    else
+    {
+        c[2] = a[2] + U;
+        U = (c[2] < a[2]);
+    }
+
+    c[2] += G;
+    U += (c[2] < G);
+    U += UG;
+    U -= (c[2] < C);
+    U -= UC;
+    c[2] -= C;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[3] < UU);
+        c[3] = a[3] - UU;
+    }
+    else
+    {
+        c[3] = a[3] + U;
+        U = (c[3] < a[3]);
+    }
+
+    c[3] += A;
+    U += (c[3] < A);
+    U += UA;
+    c[3] += a[11];
+    U += (c[3] < a[11]);
+    c[3] += a[12];
+    U += (c[3] < a[12]);
+    U -= (c[3] < a[14]);
+    c[3] -= a[14];
+    U -= (c[3] < a[15]);
+    c[3] -= a[15];
+    U -= (c[3] < E);
+    U -= UE;
+    c[3] -= E;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[4] < UU);
+        c[4] = a[4] - UU;
+    }
+    else
+    {
+        c[4] = a[4] + U;
+        U = (c[4] < a[4]);
+    }
+
+    c[4] += B;
+    U += (c[4] < B);
+    U += UB;
+    U -= (c[4] < a[15]);
+    c[4] -= a[15];
+    c[4] += a[12];
+    U += (c[4] < a[12]);
+    c[4] += a[13];
+    U += (c[4] < a[13]);
+    U -= (c[4] < F);
+    U -= UF;
+    c[4] -= F;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[5] < UU);
+        c[5] = a[5] - UU;
+    }
+    else
+    {
+        c[5] = a[5] + U;
+        U = (c[5] < a[5]);
+    }
+
+    c[5] += C;
+    U += (c[5] < C);
+    U += UC;
+    c[5] += a[13];
+    U += (c[5] < a[13]);
+    c[5] += a[14];
+    U += (c[5] < a[14]);
+    U -= (c[5] < G);
+    U -= UG;
+    c[5] -= G;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[6] < UU);
+        c[6] = a[6] - UU;
+    }
+    else
+    {
+        c[6] = a[6] + U;
+        U = (c[6] < a[6]);
+    }
+
+    c[6] += C;
+    U += (c[6] < C);
+    U += UC;
+    c[6] += a[14];
+    U += (c[6] < a[14]);
+    c[6] += a[14];
+    U += (c[6] < a[14]);
+    c[6] += a[15];
+    U += (c[6] < a[15]);
+    U -= (c[6] < E);
+    U -= UE;
+    c[6] -= E;
+
+    if (U & 0x80000000)
+    {
+        DWORD UU;
+        UU = 0 - U;
+        U = (a[7] < UU);
+        c[7] = a[7] - UU;
+    }
+    else
+    {
+        c[7] = a[7] + U;
+        U = (c[7] < a[7]);
+    }
+
+    c[7] += a[15];
+    U += (c[7] < a[15]);
+    c[7] += a[15];
+    U += (c[7] < a[15]);
+    c[7] += a[15];
+    U += (c[7] < a[15]);
+    c[7] += a[8];
+    U += (c[7] < a[8]);
+    U -= (c[7] < D);
+    U -= UD;
+    c[7] -= D;
+
+    if (U & 0x80000000)
+    {
+        while (U)
+        {
+            multiprecision_add(c, c, modp, KEY_LENGTH_DWORDS_P256);
+            U++;
+        }
+    }
+    else if (U)
+    {
+        while (U)
+        {
+            multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
+            U--;
+        }
+    }
+
+    if (multiprecision_compare(c, modp, KEY_LENGTH_DWORDS_P256)>=0)
+        multiprecision_sub(c, c, modp, KEY_LENGTH_DWORDS_P256);
+
+}
+
+void multiprecision_inv_mod(DWORD *aminus, DWORD *u, uint32_t keyLength)
+{
+    DWORD v[KEY_LENGTH_DWORDS_P256];
+    DWORD A[KEY_LENGTH_DWORDS_P256+1];
+    DWORD C[KEY_LENGTH_DWORDS_P256+1];
+    DWORD *modp;
+
+    if(keyLength == KEY_LENGTH_DWORDS_P256)
+    {
+        modp = curve_p256.p;
+    }
+    else
+    {
+        modp = curve.p;
+    }
+
+    multiprecision_copy(v, modp, keyLength);
+    multiprecision_init(A, keyLength);
+    multiprecision_init(C, keyLength);
+    A[0] = 1;
+
+    while (!multiprecision_iszero(u, keyLength))
+    {
+        while (!(u[0] & 0x01))  // u is even
+        {
+            multiprecision_rshift(u, u, keyLength);
+            if(!(A[0] & 0x01))  // A is even
+                multiprecision_rshift(A, A, keyLength);
+            else
+            {
+                A[keyLength]=multiprecision_add(A, A, modp, keyLength); // A =A+p
+                multiprecision_rshift(A, A, keyLength);
+                A[keyLength-1] |= (A[keyLength]<<31);
+            }
+        }
+
+        while (!(v[0] & 0x01))  // v is even
+        {
+            multiprecision_rshift(v, v, keyLength);
+            if (!(C[0] & 0x01))  // C is even
+            {
+                multiprecision_rshift(C, C, keyLength);
+            }
+            else
+            {
+                C[keyLength] = multiprecision_add(C, C, modp, keyLength); // C =C+p
+                multiprecision_rshift(C, C, keyLength);
+                C[keyLength-1] |= (C[keyLength] << 31);
+            }
+        }
+
+        if (multiprecision_compare(u, v, keyLength) >= 0)
+        {
+            multiprecision_sub(u, u, v, keyLength);
+            multiprecision_sub_mod(A, A, C, keyLength);
+        }
+        else
+        {
+            multiprecision_sub(v, v, u, keyLength);
+            multiprecision_sub_mod(C, C, A, keyLength);
+        }
+    }
+
+    if (multiprecision_compare(C, modp, keyLength) >= 0)
+        multiprecision_sub(aminus, C, modp, keyLength);
+    else
+        multiprecision_copy(aminus, C, keyLength);
+}
+
diff --git a/stack/smp/p_256_multprecision.h b/stack/smp/p_256_multprecision.h
new file mode 100644 (file)
index 0000000..0d1a964
--- /dev/null
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2006-2015 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+  *
+  *  This file contains simple pairing algorithms
+  *
+  ******************************************************************************/
+#pragma once
+
+#include "bt_types.h"
+
+/* Type definitions */
+typedef unsigned long  DWORD;
+
+#define DWORD_BITS      32
+#define DWORD_BYTES     4
+#define DWORD_BITS_SHIFT 5
+
+#define KEY_LENGTH_DWORDS_P192 6
+#define KEY_LENGTH_DWORDS_P256 8
+/* Arithmetic Operations */
+
+int multiprecision_compare(DWORD *a, DWORD *b, uint32_t keyLength);
+int multiprecision_iszero(DWORD *a, uint32_t keyLength);
+void multiprecision_init(DWORD *c, uint32_t keyLength);
+void multiprecision_copy(DWORD *c, DWORD *a, uint32_t keyLength);
+UINT32 multiprecision_dword_bits (DWORD a);
+UINT32 multiprecision_most_signdwords(DWORD *a, uint32_t keyLength);
+UINT32 multiprecision_most_signbits(DWORD *a, uint32_t keyLength);
+void multiprecision_inv_mod(DWORD *aminus, DWORD *a, uint32_t keyLength);
+DWORD multiprecision_add(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a+b
+void multiprecision_add_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+DWORD multiprecision_sub(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a-b
+void multiprecision_sub_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_rshift(DWORD * c, DWORD * a, uint32_t keyLength);  // c=a>>1, return carrier
+void multiprecision_lshift_mod(DWORD * c, DWORD * a, uint32_t keyLength); // c=a<<b, return carrier
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength);  // c=a<<b, return carrier
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength); // c=a*b
+void multiprecision_mersenns_mult_mod(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_mersenns_squa_mod(DWORD *c, DWORD *a, uint32_t keyLength);
+DWORD multiprecision_lshift(DWORD * c, DWORD * a, uint32_t keyLength);
+void multiprecision_mult(DWORD *c, DWORD *a, DWORD *b, uint32_t keyLength);
+void multiprecision_fast_mod(DWORD *c, DWORD *a);
+void multiprecision_fast_mod_P256(DWORD *c, DWORD *a);
+
+
index 6568316..397a2ca 100644 (file)
  *
  ******************************************************************************/
 
+#include <string.h>
 #include "bt_target.h"
 #include "bt_utils.h"
-
-#if SMP_INCLUDED == TRUE
-
-    #include <string.h>
-    #include "btm_int.h"
-    #include "l2c_api.h"
-    #include "smp_int.h"
-
-#define MAX_KEY_DISTRIBUTION_TYPES   3
+#include "btm_int.h"
+#include "l2c_api.h"
+#include "smp_int.h"
 
 const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
 {
     /* initiator */
-    {{SMP_MODEL_ENC_ONLY, SMP_MODEL_ENC_ONLY,   SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_PASSKEY}, /* Display Only */
-        {SMP_MODEL_ENC_ONLY,  SMP_MODEL_ENC_ONLY,   SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_PASSKEY}, /* SMP_CAP_IO = 1 */
-        {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}, /* 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_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENC_ONLY,    SMP_MODEL_KEY_NOTIF}}, /* keyboard display */
+    {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* Display Only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}, /* SMP_CAP_IO = 1 */
+        {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}, /* keyboard only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+        {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF,  SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_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_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 */
+    {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_KEY_NOTIF}, /* Display Only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_KEY_NOTIF,   SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_KEY_NOTIF}, /* SMP_CAP_IO = 1 */
+        {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_PASSKEY,   SMP_MODEL_ENCRYPTION_ONLY,    SMP_MODEL_PASSKEY}, /* keyboard only */
+        {SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY,   SMP_MODEL_ENCRYPTION_ONLY,  SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},/* No Input No Output */
+        {SMP_MODEL_PASSKEY,   SMP_MODEL_PASSKEY,    SMP_MODEL_KEY_NOTIF, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}} /* keyboard display */
     /* display only */    /*SMP_CAP_IO = 1 */  /* keyboard only */   /* No InputOutput */  /* keyboard display */
 };
 
+#define SMP_KEY_DIST_TYPE_MAX       4
 const tSMP_ACT smp_distribute_act [] =
 {
     smp_generate_ltk,
     smp_send_id_info,
-    smp_generate_csrk
+    smp_generate_csrk,
+    smp_derive_link_key_from_long_term_key
 };
 
 /*******************************************************************************
@@ -58,65 +55,154 @@ const tSMP_ACT smp_distribute_act [] =
 *******************************************************************************/
 static void smp_update_key_mask (tSMP_CB *p_cb, UINT8 key_type, BOOLEAN recv)
 {
-    SMP_TRACE_DEBUG ("smp_update_key_mask ");
-    SMP_TRACE_DEBUG("before update role=%d recv=%d loc_i_key = %02x, loc_r_key = %02x", p_cb->role, recv, p_cb->loc_i_key, p_cb->loc_r_key);
+    SMP_TRACE_DEBUG("%s before update role=%d recv=%d local_i_key = %02x, local_r_key = %02x",
+        __func__, p_cb->role, recv, p_cb->local_i_key, p_cb->local_r_key);
+
+    if (((p_cb->le_secure_connections_mode_is_used) || (p_cb->smp_over_br)) &&
+        ((key_type == SMP_SEC_KEY_TYPE_ENC) || (key_type == SMP_SEC_KEY_TYPE_LK)))
+    {
+        /* in LE SC mode LTK, CSRK and BR/EDR LK are derived locally instead of
+        ** being exchanged with the peer */
+        p_cb->local_i_key &= ~key_type;
+        p_cb->local_r_key &= ~key_type;
+    }
+    else
     if (p_cb->role == HCI_ROLE_SLAVE)
     {
         if (recv)
-            p_cb->loc_i_key &= ~key_type;
+            p_cb->local_i_key &= ~key_type;
         else
-            p_cb->loc_r_key &= ~key_type;
+            p_cb->local_r_key &= ~key_type;
     }
     else
     {
         if (recv)
-            p_cb->loc_r_key &= ~key_type;
+            p_cb->local_r_key &= ~key_type;
         else
-            p_cb->loc_i_key &= ~key_type;
+            p_cb->local_i_key &= ~key_type;
     }
 
-    SMP_TRACE_DEBUG("updated loc_i_key = %02x, loc_r_key = %02x", p_cb->loc_i_key, p_cb->loc_r_key);
+    SMP_TRACE_DEBUG("updated local_i_key = %02x, local_r_key = %02x", p_cb->local_i_key,
+                      p_cb->local_r_key);
 }
+
 /*******************************************************************************
-** Function     smp_io_cap_req
-** Description  send SMP IO request
+** Function     smp_send_app_cback
+** Description  notifies application about the events the application is interested in
 *******************************************************************************/
 void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     tSMP_EVT_DATA   cb_data;
     tSMP_STATUS callback_rc;
-    UNUSED(p_data);
-
-    SMP_TRACE_DEBUG ("smp_send_app_cback p_cb->cb_evt=%d", p_cb->cb_evt );
+    SMP_TRACE_DEBUG("%s p_cb->cb_evt=%d", __func__, p_cb->cb_evt);
     if (p_cb->p_callback && p_cb->cb_evt != 0)
     {
-        if (p_cb->cb_evt == SMP_IO_CAP_REQ_EVT)
+        switch (p_cb->cb_evt)
         {
-            cb_data.io_req.auth_req = p_cb->peer_auth_req;
-            cb_data.io_req.oob_data = SMP_OOB_NONE;
-            cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
-            cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
-            cb_data.io_req.init_keys = p_cb->loc_i_key ;
-            cb_data.io_req.resp_keys = p_cb->loc_r_key ;
-
-            SMP_TRACE_WARNING( "io_cap = %d",cb_data.io_req.io_cap);
+            case SMP_IO_CAP_REQ_EVT:
+                cb_data.io_req.auth_req = p_cb->peer_auth_req;
+                cb_data.io_req.oob_data = SMP_OOB_NONE;
+                cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
+                cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+                cb_data.io_req.init_keys = p_cb->local_i_key ;
+                cb_data.io_req.resp_keys = p_cb->local_r_key ;
+                SMP_TRACE_WARNING ( "io_cap = %d",cb_data.io_req.io_cap);
+                break;
+
+            case SMP_NC_REQ_EVT:
+                cb_data.passkey = p_data->passkey;
+                break;
+            case SMP_SC_OOB_REQ_EVT:
+                cb_data.req_oob_type = p_data->req_oob_type;
+                break;
+            case SMP_SC_LOC_OOB_DATA_UP_EVT:
+                cb_data.loc_oob_data = p_cb->sc_oob_data.loc_oob_data;
+                break;
+
+            case SMP_BR_KEYS_REQ_EVT:
+                cb_data.io_req.auth_req = 0;
+                cb_data.io_req.oob_data = SMP_OOB_NONE;
+                cb_data.io_req.io_cap = 0;
+                cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
+                cb_data.io_req.init_keys = SMP_BR_SEC_DEFAULT_KEY;
+                cb_data.io_req.resp_keys = SMP_BR_SEC_DEFAULT_KEY;
+                break;
+
+            default:
+                break;
         }
+
         callback_rc = (*p_cb->p_callback)(p_cb->cb_evt, p_cb->pairing_bda, &cb_data);
 
-        SMP_TRACE_DEBUG ("callback_rc=%d  p_cb->cb_evt=%d",callback_rc, p_cb->cb_evt );
+        SMP_TRACE_DEBUG("callback_rc=%d  p_cb->cb_evt=%d",callback_rc, p_cb->cb_evt );
 
-        if (callback_rc == SMP_SUCCESS && p_cb->cb_evt == SMP_IO_CAP_REQ_EVT)
+        if (callback_rc == SMP_SUCCESS)
         {
-            p_cb->loc_auth_req   = cb_data.io_req.auth_req;
-            p_cb->loc_io_caps    = cb_data.io_req.io_cap;
-            p_cb->loc_oob_flag   = cb_data.io_req.oob_data;
-            p_cb->loc_enc_size   = cb_data.io_req.max_key_size;
-            p_cb->loc_i_key      = cb_data.io_req.init_keys;
-            p_cb->loc_r_key      = cb_data.io_req.resp_keys;
+            switch (p_cb->cb_evt)
+            {
+                case SMP_IO_CAP_REQ_EVT:
+                    p_cb->loc_auth_req   = cb_data.io_req.auth_req;
+                    p_cb->local_io_capability  = cb_data.io_req.io_cap;
+                    p_cb->loc_oob_flag = cb_data.io_req.oob_data;
+                    p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+                    p_cb->local_i_key = cb_data.io_req.init_keys;
+                    p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+                    if (!(p_cb->loc_auth_req & SMP_AUTH_BOND))
+                    {
+                        SMP_TRACE_WARNING ("Non bonding: No keys will be exchanged");
+                        p_cb->local_i_key = 0;
+                        p_cb->local_r_key = 0;
+                    }
+
+                    SMP_TRACE_WARNING ( "rcvd auth_req: 0x%02x, io_cap: %d \
+                        loc_oob_flag: %d loc_enc_size: %d,"
+                        "local_i_key: 0x%02x, local_r_key: 0x%02x",
+                        p_cb->loc_auth_req, p_cb->local_io_capability, p_cb->loc_oob_flag,
+                        p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+                    p_cb->secure_connections_only_mode_required =
+                        (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+                    if (p_cb->secure_connections_only_mode_required)
+                    {
+                        p_cb->loc_auth_req |= SMP_SC_SUPPORT_BIT;
+                    }
+
+                    if (!(p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+                    {
+                        p_cb->loc_auth_req &= ~SMP_KP_SUPPORT_BIT;
+                        p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                        p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+                    }
+
+#if BTM_CROSS_TRANSP_KEY_DERIVATION == FALSE
+                    SMP_TRACE_WARNING ("Cross transport key derivation is not supported");
+                    p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                    p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+#endif
+
+                    SMP_TRACE_WARNING("set auth_req: 0x%02x, local_i_key: 0x%02x, local_r_key: 0x%02x",
+                        p_cb->loc_auth_req, p_cb->local_i_key, p_cb->local_r_key);
 
-            SMP_TRACE_WARNING( "new io_cap = %d p_cb->loc_enc_size = %d",p_cb->loc_io_caps, p_cb->loc_enc_size);
+                    smp_sm_event(p_cb, SMP_IO_RSP_EVT, NULL);
+                    break;
 
-            smp_sm_event(p_cb, SMP_IO_RSP_EVT, NULL);
+                case SMP_BR_KEYS_REQ_EVT:
+                    p_cb->loc_enc_size = cb_data.io_req.max_key_size;
+                    p_cb->local_i_key = cb_data.io_req.init_keys;
+                    p_cb->local_r_key = cb_data.io_req.resp_keys;
+
+                    p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                    p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+                    SMP_TRACE_WARNING ( "for SMP over BR max_key_size: 0x%02x,\
+                        local_i_key: 0x%02x, local_r_key: 0x%02x",
+                        p_cb->loc_enc_size, p_cb->local_i_key, p_cb->local_r_key);
+
+                    smp_br_state_machine_event(p_cb, SMP_BR_KEYS_RSP_EVT, NULL);
+                    break;
+            }
         }
     }
 
@@ -125,8 +211,10 @@ void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
         p_cb->discard_sec_req = FALSE;
         smp_sm_event(p_cb, SMP_DISCARD_SEC_REQ_EVT, NULL);
     }
-    SMP_TRACE_DEBUG ("smp_send_app_cback return");
+
+    SMP_TRACE_DEBUG("%s return", __func__);
 }
+
 /*******************************************************************************
 ** Function     smp_send_pair_fail
 ** Description  pairing failure to peer device if needed.
@@ -136,36 +224,23 @@ void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     p_cb->status = *(UINT8 *)p_data;
     p_cb->failure = *(UINT8 *)p_data;
 
-    SMP_TRACE_DEBUG ("smp_send_pair_fail status=%d failure=%d ",p_cb->status, p_cb->failure);
+    SMP_TRACE_DEBUG("%s status=%d failure=%d ", __func__, p_cb->status, p_cb->failure);
 
-    if (p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS)
+    if (p_cb->status <= SMP_MAX_FAIL_RSN_PER_SPEC && p_cb->status != SMP_SUCCESS)
     {
         smp_send_cmd(SMP_OPCODE_PAIRING_FAILED, p_cb);
+        p_cb->wait_for_authorization_complete = TRUE;
     }
 }
 
 /*******************************************************************************
 ** Function     smp_send_pair_req
-** Description  process pairing request to slave device
+** Description  actions related to sending pairing request
 *******************************************************************************/
 void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
-    UNUSED(p_data);
-
-    SMP_TRACE_DEBUG ("smp_send_pair_req  ");
-
-#if BLE_INCLUDED == TRUE
-    /* Disable L2CAP connection parameter updates while bonding since
-       some peripherals are not able to revert to fast connection parameters
-       during the start of service discovery. Connection paramter updates
-       get enabled again once service discovery completes. */
-    if (L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE) == FALSE)
-    {
-        SMP_TRACE_ERROR ("smp pair failed...!");
-        return;
-    }
-#endif
+    SMP_TRACE_DEBUG("%s", __func__);
 
     /* erase all keys when master sends pairing req*/
     if (p_dev_rec)
@@ -174,120 +249,167 @@ void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
        leave out to BTM to mandate key distribution for bonding case */
     smp_send_cmd(SMP_OPCODE_PAIRING_REQ, p_cb);
 }
+
 /*******************************************************************************
 ** Function     smp_send_pair_rsp
-** Description  process pairing response to slave device
+** Description  actions related to sending pairing response
 *******************************************************************************/
 void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    SMP_TRACE_DEBUG ("smp_send_pair_rsp  ");
-
-    p_cb->loc_i_key &= p_cb->peer_i_key;
-    p_cb->loc_r_key &= p_cb->peer_r_key;
+    p_cb->local_i_key &= p_cb->peer_i_key;
+    p_cb->local_r_key &= p_cb->peer_r_key;
 
     if (smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb))
     {
-        smp_decide_asso_model(p_cb, NULL);
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+            smp_use_oob_private_key(p_cb, NULL);
+        else
+            smp_decide_association_model(p_cb, NULL);
     }
 }
 
 /*******************************************************************************
-** Function     smp_send_pair_request
-** Description  process pairing request to slave device
+** Function     smp_send_confirm
+** Description  send confirmation to the peer
 *******************************************************************************/
 void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
-
-    SMP_TRACE_DEBUG ("smp_send_confirm  ");
+    SMP_TRACE_DEBUG("%s", __func__);
     smp_send_cmd(SMP_OPCODE_CONFIRM, p_cb);
 }
+
 /*******************************************************************************
 ** Function     smp_send_init
 ** Description  process pairing initializer to slave device
 *******************************************************************************/
 void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_INIT, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_rand
+** Description  send pairing random to the peer
+*******************************************************************************/
+void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_RAND, p_cb);
+}
 
-    SMP_TRACE_DEBUG ("smp_send_init  ");
+/*******************************************************************************
+** Function     smp_send_pair_public_key
+** Description  send pairing public key command to the peer
+*******************************************************************************/
+void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_PUBLIC_KEY, p_cb);
+}
 
-#if SMP_CONFORMANCE_TESTING == TRUE
-    if (p_cb->enable_test_rand_val)
-    {
-        SMP_TRACE_DEBUG ("Use rand value from script");
-        memcpy(p_cb->rand, p_cb->test_rand, BT_OCTET16_LEN);
-    }
-#endif
+/*******************************************************************************
+** Function     SMP_SEND_COMMITMENT
+** Description send commitment command to the peer
+*******************************************************************************/
+void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_COMMITM, p_cb);
+}
 
-    smp_send_cmd(SMP_OPCODE_INIT, p_cb);
+/*******************************************************************************
+** Function     smp_send_dhkey_check
+** Description send DHKey Check command to the peer
+*******************************************************************************/
+void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_send_cmd(SMP_OPCODE_PAIR_DHKEY_CHECK, p_cb);
+}
+
+/*******************************************************************************
+** Function     smp_send_keypress_notification
+** Description send Keypress Notification command to the peer
+*******************************************************************************/
+void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    p_cb->local_keypress_notification = *(UINT8 *) p_data;
+    smp_send_cmd(SMP_OPCODE_PAIR_KEYPR_NOTIF, p_cb);
 }
+
 /*******************************************************************************
 ** Function     smp_send_enc_info
-** Description  send security information command.
+** Description  send encryption information command.
 *******************************************************************************/
 void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     tBTM_LE_LENC_KEYS   le_key;
-    UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_send_enc_info  p_cb->loc_enc_size = %d", p_cb->loc_enc_size);
+    SMP_TRACE_DEBUG("%s p_cb->loc_enc_size = %d", __func__, p_cb->loc_enc_size);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
 
     smp_send_cmd(SMP_OPCODE_ENCRYPT_INFO, p_cb);
     smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
 
     /* save the DIV and key size information when acting as slave device */
+    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
     le_key.div =  p_cb->div;
     le_key.key_size = p_cb->loc_enc_size;
     le_key.sec_level = p_cb->sec_level;
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
 
-    SMP_TRACE_WARNING( "smp_send_enc_info");
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+
+    SMP_TRACE_WARNING ("%s", __func__);
 
     smp_key_distribution(p_cb, NULL);
 }
+
 /*******************************************************************************
 ** Function     smp_send_id_info
 ** Description  send ID information command.
 *******************************************************************************/
 void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
-
-    SMP_TRACE_DEBUG ("smp_send_id_info  ");
+    tBTM_LE_KEY_VALUE   le_key;
+    SMP_TRACE_DEBUG("%s", __func__);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, FALSE);
 
     smp_send_cmd(SMP_OPCODE_IDENTITY_INFO, p_cb);
     smp_send_cmd(SMP_OPCODE_ID_ADDR, p_cb);
 
-    SMP_TRACE_WARNING( "smp_send_id_info");
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LID,
+                            &le_key, TRUE);
 
-    smp_key_distribution(p_cb, NULL);
+    SMP_TRACE_WARNING ("%s", __func__);
+    smp_key_distribution_by_transport(p_cb, NULL);
 }
+
 /*******************************************************************************
 ** Function     smp_send_csrk_info
 ** Description  send CSRK command.
 *******************************************************************************/
 void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_KEY_VALUE   key;
-    UNUSED(p_data);
-
-    SMP_TRACE_DEBUG ("smp_send_csrk_info ");
+    tBTM_LE_LCSRK_KEYS  key;
+    SMP_TRACE_DEBUG("%s", __func__);
     smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, FALSE);
 
     if (smp_send_cmd(SMP_OPCODE_SIGN_INFO, p_cb))
     {
-        key.lcsrk_key.div = p_cb->div;
-        key.lcsrk_key.sec_level = p_cb->sec_level;
-        key.lcsrk_key.counter = 0; /* initialize the local counter */
-        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, TRUE);
+        key.div = p_cb->div;
+        key.sec_level = p_cb->sec_level;
+        key.counter = 0; /* initialize the local counter */
+        memcpy (key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, (tBTM_LE_KEY_VALUE *)&key, TRUE);
     }
 
-    smp_key_distribution(p_cb, NULL);
+    smp_key_distribution_by_transport(p_cb, NULL);
 }
 
 /*******************************************************************************
@@ -296,44 +418,54 @@ void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_send_ltk_reply(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    SMP_TRACE_DEBUG ("smp_send_ltk_reply ");
+    SMP_TRACE_DEBUG("%s", __func__);
     /* send stk as LTK response */
     btm_ble_ltk_request_reply(p_cb->pairing_bda, TRUE, p_data->key.p_data);
 }
+
 /*******************************************************************************
 ** Function     smp_proc_sec_req
 ** Description  process security request.
 *******************************************************************************/
 void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_AUTH_REQ        auth_req = *(tBTM_LE_AUTH_REQ *)p_data;
-    tBTM_BLE_SEC_REQ_ACT    sec_req_act;
-
+    tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ *)p_data;
+    tBTM_BLE_SEC_REQ_ACT sec_req_act;
+    UINT8 reason;
 
-    SMP_TRACE_DEBUG ("smp_proc_sec_req  auth_req=0x%x",auth_req);
+    SMP_TRACE_DEBUG("%s auth_req=0x%x", __func__, auth_req);
 
     p_cb->cb_evt = 0;
 
     btm_ble_link_sec_check(p_cb->pairing_bda, auth_req,  &sec_req_act);
 
-    SMP_TRACE_DEBUG ("smp_proc_sec_req  sec_req_act=0x%x",sec_req_act);
+    SMP_TRACE_DEBUG("%s sec_req_act=0x%x", __func__, sec_req_act);
 
     switch (sec_req_act)
     {
         case  BTM_BLE_SEC_REQ_ACT_ENCRYPT:
-            SMP_TRACE_DEBUG ("smp_proc_sec_req BTM_BLE_SEC_REQ_ACT_ENCRYPT");
+            SMP_TRACE_DEBUG("%s BTM_BLE_SEC_REQ_ACT_ENCRYPT", __func__);
             smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
             break;
 
         case BTM_BLE_SEC_REQ_ACT_PAIR:
-            /* initialize local i/r key to be default keys */
-            SMP_TRACE_DEBUG ("smp_proc_sec_req BTM_BLE_SEC_REQ_ACT_PAIR");
-            p_cb->peer_auth_req = auth_req;
-            p_cb->loc_r_key = p_cb->loc_i_key = SMP_SEC_DEFAULT_KEY ;
-            p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
-            btu_stop_timer (&p_cb->rsp_timer_ent);
-            btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
-                   SMP_WAIT_FOR_RSP_TOUT);
+            p_cb->secure_connections_only_mode_required =
+                    (btm_cb.security_mode == BTM_SEC_MODE_SC) ? TRUE : FALSE;
+
+            /* respond to non SC pairing request as failure in SC only mode */
+            if (p_cb->secure_connections_only_mode_required &&
+                (auth_req & SMP_SC_SUPPORT_BIT) == 0)
+            {
+                reason = SMP_PAIR_AUTH_FAIL;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            }
+            else
+            {
+                /* initialize local i/r key to be default keys */
+                p_cb->peer_auth_req = auth_req;
+                p_cb->local_r_key = p_cb->local_i_key = SMP_SEC_DEFAULT_KEY ;
+                p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+            }
             break;
 
         case BTM_BLE_SEC_REQ_ACT_DISCARD:
@@ -345,6 +477,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
             break;
     }
 }
+
 /*******************************************************************************
 ** Function     smp_proc_sec_grant
 ** Description  process security grant.
@@ -352,7 +485,7 @@ void smp_proc_sec_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8 res= *(UINT8 *)p_data;
-    SMP_TRACE_DEBUG ("smp_proc_sec_grant ");
+    SMP_TRACE_DEBUG("%s", __func__);
     if (res != SMP_SUCCESS)
     {
         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, p_data);
@@ -363,15 +496,17 @@ void smp_proc_sec_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
         p_cb->cb_evt = SMP_IO_CAP_REQ_EVT;
     }
 }
+
 /*******************************************************************************
 ** Function     smp_proc_pair_fail
 ** Description  process pairing failure from peer device
 *******************************************************************************/
 void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    SMP_TRACE_DEBUG ("smp_proc_pair_fail   ");
+    SMP_TRACE_DEBUG("%s", __func__);
     p_cb->status = *(UINT8 *)p_data;
 }
+
 /*******************************************************************************
 ** Function     smp_proc_pair_cmd
 ** Description  Process the SMP pairing request/response from peer device
@@ -382,7 +517,7 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UINT8   reason = SMP_ENC_KEY_SIZE;
     tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
 
-    SMP_TRACE_DEBUG ("smp_proc_pair_cmd  ");
+    SMP_TRACE_DEBUG("%s", __func__);
     /* erase all keys if it is slave proc pairing req*/
     if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE))
         btm_sec_clear_ble_keys(p_dev_rec);
@@ -396,43 +531,66 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     STREAM_TO_UINT8(p_cb->peer_i_key, p);
     STREAM_TO_UINT8(p_cb->peer_r_key, p);
 
-#if SMP_CONFORMANCE_TESTING == TRUE
-    if (p_cb->enable_test_pair_fail)
+    if (smp_command_has_invalid_parameters(p_cb))
     {
-        SMP_TRACE_DEBUG ("Forced pair fair");
-        if (p_cb->peer_enc_size < SMP_MIN_ENC_KEY_SIZE)
-        {
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-        }
-        else
-        {
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &(p_cb->pair_fail_status));
-        }
+        reason = SMP_INVALID_PARAMETERS;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
         return;
     }
-#endif
-
 
-    if (p_cb->peer_enc_size < SMP_MIN_ENC_KEY_SIZE)
-    {
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-    }
-    else if (p_cb->role == HCI_ROLE_SLAVE)
+    if (p_cb->role == HCI_ROLE_SLAVE)
     {
         if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
         {
-            p_cb->loc_i_key = p_cb->peer_i_key;
-            p_cb->loc_r_key = p_cb->peer_r_key;
+            /* peer (master) started pairing sending Pairing Request */
+            p_cb->local_i_key = p_cb->peer_i_key;
+            p_cb->local_r_key = p_cb->peer_r_key;
+
+            p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
         }
         else /* update local i/r key according to pairing request */
         {
-            p_cb->loc_i_key &= p_cb->peer_i_key;
-            p_cb->loc_r_key &= p_cb->peer_r_key;
+            /* paring started with this side (slave) sending Security Request */
+            p_cb->local_i_key &= p_cb->peer_i_key;
+            p_cb->local_r_key &= p_cb->peer_r_key;
+            p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+            if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+            {
+                if (smp_request_oob_data(p_cb)) return;
+            }
+            else
+            {
+                smp_send_pair_rsp(p_cb, NULL);
+            }
+        }
+    }
+    else /* Master receives pairing response */
+    {
+        p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+        if (p_cb->secure_connections_only_mode_required &&
+            (!(p_cb->le_secure_connections_mode_is_used) ||
+           (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)))
+        {
+            SMP_TRACE_ERROR ("Master requires secure connection only mode \
+                but it can't be provided -> Master fails pairing");
+            reason = SMP_PAIR_AUTH_FAIL;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
         }
 
-        p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+        {
+            if (smp_request_oob_data(p_cb)) return;
+        }
+        else
+        {
+            smp_decide_association_model(p_cb, NULL);
+        }
     }
 }
+
 /*******************************************************************************
 ** Function     smp_proc_confirm
 ** Description  process pairing confirm from peer device
@@ -440,8 +598,16 @@ void smp_proc_pair_cmd(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
 
-    SMP_TRACE_DEBUG ("smp_proc_confirm  ");
     if (p != NULL)
     {
         /* save the SConfirm for comparison later */
@@ -458,219 +624,483 @@ void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 void smp_proc_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UINT8 *p = (UINT8 *)p_data;
-    SMP_TRACE_DEBUG ("smp_proc_init ");
+    UINT8 reason = SMP_INVALID_PARAMETERS;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
     /* save the SRand for comparison */
     STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
-
 }
+
 /*******************************************************************************
-** Function     smp_proc_enc_info
-** Description  process encryption information from peer device
+** Function     smp_proc_rand
+** Description  process pairing random (nonce) from peer device
 *******************************************************************************/
-void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   *p = (UINT8 *)p_data;
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
 
-    SMP_TRACE_DEBUG ("smp_proc_enc_info  ");
-    STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    smp_key_distribution(p_cb, NULL);
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    /* save the SRand for comparison */
+    STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
 }
+
 /*******************************************************************************
-** Function     smp_proc_master_id
-** Description  process master ID from slave device
+** Function     smp_process_pairing_public_key
+** Description  process pairing public key command from the peer device
+**              - saves the peer public key;
+**              - sets the flag indicating that the peer public key is received;
+**              - calls smp_wait_for_both_public_keys(...).
+**
 *******************************************************************************/
-void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   *p = (UINT8 *)p_data;
-    tBTM_LE_PENC_KEYS   le_key;
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
 
-    SMP_TRACE_DEBUG (" smp_proc_master_id");
-    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    STREAM_TO_UINT16(le_key.ediv, p);
-    STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
 
-    /* store the encryption keys from peer device */
-    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
-    le_key.sec_level = p_cb->sec_level;
-    le_key.key_size  = p_cb->loc_enc_size;
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    STREAM_TO_ARRAY(p_cb->peer_publ_key.x, p, BT_OCTET32_LEN);
+    STREAM_TO_ARRAY(p_cb->peer_publ_key.y, p, BT_OCTET32_LEN);
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY;
 
-    smp_key_distribution(p_cb, NULL);
+    smp_wait_for_both_public_keys(p_cb, NULL);
 }
-/*******************************************************************************
-** Function     smp_proc_enc_info
-** Description  process identity information from peer device
-*******************************************************************************/
-void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
-    UINT8   *p = (UINT8 *)p_data;
 
-    SMP_TRACE_DEBUG ("smp_proc_id_info ");
-    STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN);   /* reuse TK for IRK */
-
-    smp_key_distribution(p_cb, NULL);
-}
 /*******************************************************************************
-** Function     smp_proc_id_addr
-** Description  process identity address from peer device
+** Function     smp_process_pairing_commitment
+** Description  process pairing commitment from peer device
 *******************************************************************************/
-void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   *p = (UINT8 *)p_data;
-    tBTM_LE_PID_KEYS    pid_key;
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
 
-    SMP_TRACE_DEBUG ("smp_proc_id_addr  ");
-    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    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);
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
 
-    /* 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);
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM;
 
-    smp_key_distribution(p_cb, NULL);
+    if (p != NULL)
+    {
+        STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN);
+    }
 }
+
 /*******************************************************************************
-** Function     smp_proc_srk_info
-** Description  process security information from peer device
+** Function     smp_process_dhkey_check
+** Description  process DHKey Check from peer device
 *******************************************************************************/
-void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tBTM_LE_PCSRK_KEYS   le_key;
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
 
-    SMP_TRACE_DEBUG ("smp_proc_srk_info ");
-    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    /* save CSRK to security record */
-    le_key.sec_level = p_cb->sec_level;
-    memcpy (le_key.csrk, p_data, BT_OCTET16_LEN);   /* get peer CSRK */
-    le_key.counter = 0; /* initialize the peer counter */
-    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PCSRK, (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
 
-    smp_key_distribution(p_cb, NULL);
+    if (p != NULL)
+    {
+        STREAM_TO_ARRAY(p_cb->remote_dhkey_check, p, BT_OCTET16_LEN);
+    }
+
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK;
 }
 
 /*******************************************************************************
-** Function     smp_proc_compare
-** Description  process compare value
+** Function     smp_process_keypress_notification
+** Description  process pairing keypress notification from peer device
 *******************************************************************************/
-void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   reason;
-
-    SMP_TRACE_DEBUG ("smp_proc_compare  ");
-    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)
-            p_cb->loc_enc_size = p_cb->peer_enc_size;
+    UINT8 *p = (UINT8 *)p_data;
+    UINT8 reason = SMP_INVALID_PARAMETERS;
 
-        if (p_cb->role == HCI_ROLE_SLAVE)
-            smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
-        else
-        {
-            /* master device always use received i/r key as keys to distribute */
-            p_cb->loc_i_key = p_cb->peer_i_key;
-            p_cb->loc_r_key = p_cb->peer_r_key;
+    SMP_TRACE_DEBUG("%s", __func__);
+    p_cb->status = *(UINT8 *)p_data;
 
-            smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
-        }
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
 
+    if (p != NULL)
+    {
+        STREAM_TO_UINT8(p_cb->peer_keypress_notification, p);
     }
     else
     {
-        reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        p_cb->peer_keypress_notification = BTM_SP_KEY_OUT_OF_RANGE;
     }
+    p_cb->cb_evt = SMP_PEER_KEYPR_NOT_EVT;
 }
+
 /*******************************************************************************
-** Function     smp_proc_sl_key
-** Description  process key ready events.
+** Function     smp_br_process_pairing_command
+** Description  Process the SMP pairing request/response from peer device via
+**              BR/EDR transport.
 *******************************************************************************/
-void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8 key_type = p_data->key.key_type;
+    UINT8   *p = (UINT8 *)p_data;
+    UINT8   reason = SMP_ENC_KEY_SIZE;
+    tBTM_SEC_DEV_REC *p_dev_rec = btm_find_dev (p_cb->pairing_bda);
 
-    SMP_TRACE_DEBUG ("smp_proc_sl_keysmp_proc_sl_key  ");
-    if (key_type == SMP_KEY_TYPE_TK)
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* rejecting BR pairing request over non-SC BR link */
+    if (!p_dev_rec->new_encryption_key_is_p256 && p_cb->role == HCI_ROLE_SLAVE)
     {
-        smp_generate_confirm(p_cb, NULL);
+        reason = SMP_XTRANS_DERIVE_NOT_ALLOW;
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+        return;
     }
-    else if (key_type == SMP_KEY_TYPE_CFM)
-    {
-        smp_set_state(SMP_ST_WAIT_CONFIRM);
 
-        if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM)
-            smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
+    /* erase all keys if it is slave proc pairing req*/
+    if (p_dev_rec && (p_cb->role == HCI_ROLE_SLAVE))
+        btm_sec_clear_ble_keys(p_dev_rec);
 
-    }
-}
-/*******************************************************************************
-** Function     smp_start_enc
-** Description  start encryption
-*******************************************************************************/
-void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
-    tBTM_STATUS cmd;
-    UINT8 reason = SMP_ENC_FAIL;
+    p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
 
-    SMP_TRACE_DEBUG ("smp_start_enc ");
-    if (p_data != NULL)
-        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+    STREAM_TO_UINT8(p_cb->peer_io_caps, p);
+    STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
+    STREAM_TO_UINT8(p_cb->peer_auth_req, p);
+    STREAM_TO_UINT8(p_cb->peer_enc_size, p);
+    STREAM_TO_UINT8(p_cb->peer_i_key, p);
+    STREAM_TO_UINT8(p_cb->peer_r_key, p);
+
+    if (smp_command_has_invalid_parameters(p_cb))
+    {
+        reason = SMP_INVALID_PARAMETERS;
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    /* peer (master) started pairing sending Pairing Request */
+    /* or being master device always use received i/r key as keys to distribute */
+    p_cb->local_i_key = p_cb->peer_i_key;
+    p_cb->local_r_key = p_cb->peer_r_key;
+
+    if (p_cb->role == HCI_ROLE_SLAVE)
+    {
+        p_dev_rec->new_encryption_key_is_p256 = FALSE;
+        p_cb->cb_evt = SMP_SEC_REQUEST_EVT;
+    }
+    else /* Master receives pairing response */
+    {
+        SMP_TRACE_DEBUG("%s master rcvs valid PAIRING RESPONSE."
+                          " Supposed to move to key distribution phase. ", __func__);
+    }
+
+    /* auth_req received via BR/EDR SM channel is set to 0,
+       but everything derived/exchanged has to be saved */
+    p_cb->peer_auth_req |= SMP_AUTH_BOND;
+    p_cb->loc_auth_req |= SMP_AUTH_BOND;
+}
+
+/*******************************************************************************
+** Function     smp_br_process_security_grant
+** Description  process security grant in case of pairing over BR/EDR transport.
+*******************************************************************************/
+void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 res= *(UINT8 *)p_data;
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (res != SMP_SUCCESS)
+    {
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, p_data);
+    }
+    else /*otherwise, start pairing */
+    {
+        /* send IO request callback */
+        p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+    }
+}
+
+/*******************************************************************************
+** Function     smp_br_check_authorization_request
+** Description  sets the SMP kes to be derived/distribute over BR/EDR transport
+**              before starting the distribution/derivation
+*******************************************************************************/
+void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 reason = SMP_SUCCESS;
+
+    SMP_TRACE_DEBUG("%s rcvs i_keys=0x%x r_keys=0x%x "
+                      "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+                      p_cb->local_r_key);
+
+    /* In LE SC mode LK field is ignored when BR/EDR transport is used */
+    p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+    p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+
+    /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+    ** Set local_r_key on master to expect only these keys. */
+    if (p_cb->role == HCI_ROLE_MASTER)
+    {
+        p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+    }
+
+    SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+                      "(i-initiator r-responder)", __FUNCTION__, p_cb->local_i_key,
+                      p_cb->local_r_key);
+
+    if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+            (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+        (p_cb->local_i_key || p_cb->local_r_key))
+    {
+        smp_br_state_machine_event(p_cb, SMP_BR_BOND_REQ_EVT, NULL);
+
+        /* if no peer key is expected, start master key distribution */
+        if (p_cb->role == HCI_ROLE_MASTER && p_cb->local_r_key == 0)
+            smp_key_distribution_by_transport(p_cb, NULL);
+    }
     else
-        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+    {
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+    }
+}
 
-    if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+/*******************************************************************************
+** Function     smp_br_select_next_key
+** Description  selects the next key to derive/send when BR/EDR transport is
+**              used.
+*******************************************************************************/
+void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason = SMP_SUCCESS;
+    SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
+                       __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
 
+    if (p_cb->role == HCI_ROLE_SLAVE||
+        (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+    {
+        smp_key_pick_key(p_cb, p_data);
+    }
+
+    if (!p_cb->local_i_key && !p_cb->local_r_key)
+    {
+        /* state check to prevent re-entrance */
+        if (p_cb->smp_over_br)
+            smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &reason);
+    }
 }
 
 /*******************************************************************************
-** Function     smp_proc_discard
-** Description   processing for discard security request
+** Function     smp_proc_enc_info
+** Description  process encryption information from peer device
 *******************************************************************************/
-void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    UINT8   *p = (UINT8 *)p_data;
 
-    SMP_TRACE_DEBUG ("smp_proc_discard ");
-    if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
-        smp_reset_control_value(p_cb);
+    SMP_TRACE_DEBUG("%s", __func__);
+    STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+
+    smp_key_distribution(p_cb, NULL);
 }
 /*******************************************************************************
-** Function     smp_proc_release_delay
-** Description  process the release delay request
+** Function     smp_proc_master_id
+** Description  process master ID from slave device
 *******************************************************************************/
-void smp_proc_release_delay(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    UINT8   *p = (UINT8 *)p_data;
+    tBTM_LE_PENC_KEYS   le_key;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, TRUE);
+
+    STREAM_TO_UINT16(le_key.ediv, p);
+    STREAM_TO_ARRAY(le_key.rand, p, BT_OCTET8_LEN );
+
+    /* store the encryption keys from peer device */
+    memcpy(le_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    le_key.sec_level = p_cb->sec_level;
+    le_key.key_size  = p_cb->loc_enc_size;
 
-    SMP_TRACE_DEBUG ("smp_proc_release_delay ");
-    btu_stop_timer (&p_cb->rsp_timer_ent);
-    btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
-                     SMP_WAIT_FOR_REL_DELAY_TOUT);
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+        btm_sec_save_le_key(p_cb->pairing_bda,
+                            BTM_LE_KEY_PENC,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+
+    smp_key_distribution(p_cb, NULL);
 }
 
 /*******************************************************************************
-** Function      smp_proc_release_delay_tout
-** Description   processing the release delay timeout
+** Function     smp_proc_enc_info
+** Description  process identity information from peer device
 *******************************************************************************/
-void smp_proc_release_delay_tout(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    UINT8   *p = (UINT8 *)p_data;
 
-    SMP_TRACE_DEBUG ("smp_proc_release_delay_tout ");
-    btu_stop_timer (&p_cb->rsp_timer_ent);
-    smp_proc_pairing_cmpl(p_cb);
+    SMP_TRACE_DEBUG("%s", __func__);
+    STREAM_TO_ARRAY (p_cb->tk, p, BT_OCTET16_LEN);   /* reuse TK for IRK */
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_id_addr
+** Description  process identity address from peer device
+*******************************************************************************/
+void smp_proc_id_addr(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   *p = (UINT8 *)p_data;
+    tBTM_LE_PID_KEYS    pid_key;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ID, TRUE);
+
+    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);
+
+    /* store the ID key from peer device */
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+        btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PID,
+                            (tBTM_LE_KEY_VALUE *)&pid_key, TRUE);
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_srk_info
+** Description  process security information from peer device
+*******************************************************************************/
+void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_LE_PCSRK_KEYS   le_key;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_CSRK, TRUE);
+
+    /* save CSRK to security record */
+    le_key.sec_level = p_cb->sec_level;
+    memcpy (le_key.csrk, p_data, BT_OCTET16_LEN);   /* get peer CSRK */
+    le_key.counter = 0; /* initialize the peer counter */
+
+    if ((p_cb->peer_auth_req & SMP_AUTH_BOND) && (p_cb->loc_auth_req & SMP_AUTH_BOND))
+        btm_sec_save_le_key(p_cb->pairing_bda,
+                            BTM_LE_KEY_PCSRK,
+                            (tBTM_LE_KEY_VALUE *)&le_key, TRUE);
+    smp_key_distribution_by_transport(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_proc_compare
+** Description  process compare value
+*******************************************************************************/
+void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (!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)
+            p_cb->loc_enc_size = p_cb->peer_enc_size;
+
+        if (p_cb->role == HCI_ROLE_SLAVE)
+            smp_sm_event(p_cb, SMP_RAND_EVT, NULL);
+        else
+        {
+            /* master device always use received i/r key as keys to distribute */
+            p_cb->local_i_key = p_cb->peer_i_key;
+            p_cb->local_r_key = p_cb->peer_r_key;
+
+            smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
+        }
+
+    }
+    else
+    {
+        reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_proc_sl_key
+** Description  process key ready events.
+*******************************************************************************/
+void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 key_type = p_data->key.key_type;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (key_type == SMP_KEY_TYPE_TK)
+    {
+        smp_generate_srand_mrand_confirm(p_cb, NULL);
+    }
+    else if (key_type == SMP_KEY_TYPE_CFM)
+    {
+        smp_set_state(SMP_STATE_WAIT_CONFIRM);
+
+        if (p_cb->flags & SMP_PAIR_FLAGS_CMD_CONFIRM)
+            smp_sm_event(p_cb, SMP_CONFIRM_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_start_enc
+** Description  start encryption
+*******************************************************************************/
+void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tBTM_STATUS cmd;
+    UINT8 reason = SMP_ENC_FAIL;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (p_data != NULL)
+        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, TRUE, p_data->key.p_data);
+    else
+        cmd = btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+
+    if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY)
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 }
 
+/*******************************************************************************
+** Function     smp_proc_discard
+** Description   processing for discard security request
+*******************************************************************************/
+void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (!(p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD))
+        smp_reset_control_value(p_cb);
+}
 
 /*******************************************************************************
 ** Function     smp_enc_cmpl
@@ -681,299 +1111,790 @@ void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UINT8 enc_enable = *(UINT8 *)p_data;
     UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
 
-    SMP_TRACE_DEBUG ("smp_enc_cmpl ");
+    SMP_TRACE_DEBUG("%s", __func__);
     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
 }
 
+/*******************************************************************************
+** Function     smp_check_auth_req
+** Description  check authentication request
+*******************************************************************************/
+void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 enc_enable = *(UINT8 *)p_data;
+    UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+
+    SMP_TRACE_DEBUG("%s rcvs enc_enable=%d i_keys=0x%x r_keys=0x%x "
+                      "(i-initiator r-responder)",
+                      __func__, enc_enable, p_cb->local_i_key, p_cb->local_r_key);
+    if (enc_enable == 1)
+    {
+        if (p_cb->le_secure_connections_mode_is_used)
+        {
+            /* In LE SC mode LTK is used instead of STK and has to be always saved */
+            p_cb->local_i_key |= SMP_SEC_KEY_TYPE_ENC;
+            p_cb->local_r_key |= SMP_SEC_KEY_TYPE_ENC;
+
+           /* In LE SC mode LK is derived from LTK only if both sides request it */
+           if (!(p_cb->local_i_key & SMP_SEC_KEY_TYPE_LK) ||
+               !(p_cb->local_r_key & SMP_SEC_KEY_TYPE_LK))
+            {
+                p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+                p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+            }
+
+            /* In LE SC mode only IRK, IAI, CSRK are exchanged with the peer.
+            ** Set local_r_key on master to expect only these keys.
+            */
+            if (p_cb->role == HCI_ROLE_MASTER)
+            {
+                p_cb->local_r_key &= (SMP_SEC_KEY_TYPE_ID | SMP_SEC_KEY_TYPE_CSRK);
+            }
+        }
+        else
+        {
+            /* in legacy mode derivation of BR/EDR LK is not supported */
+            p_cb->local_i_key &= ~SMP_SEC_KEY_TYPE_LK;
+            p_cb->local_r_key &= ~SMP_SEC_KEY_TYPE_LK;
+        }
+        SMP_TRACE_DEBUG("%s rcvs upgrades: i_keys=0x%x r_keys=0x%x "
+                          "(i-initiator r-responder)",
+                          __func__, p_cb->local_i_key, p_cb->local_r_key);
+
+        if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
+             (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
+            (p_cb->local_i_key || p_cb->local_r_key))
+        {
+            smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
+        }
+        else
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+    }
+    else if (enc_enable == 0)
+    {
+        /* if failed for encryption after pairing, send callback */
+        if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        /* if enc failed for old security information */
+        /* if master device, clean up and abck to idle; slave device do nothing */
+        else if (p_cb->role == HCI_ROLE_MASTER)
+        {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        }
+    }
+}
+
+/*******************************************************************************
+** Function     smp_key_pick_key
+** Description  Pick a key distribution function based on the key mask.
+*******************************************************************************/
+void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   key_to_dist = (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->local_r_key : p_cb->local_i_key;
+    UINT8   i = 0;
+
+    SMP_TRACE_DEBUG("%s key_to_dist=0x%x", __func__, key_to_dist);
+    while (i < SMP_KEY_DIST_TYPE_MAX)
+    {
+        SMP_TRACE_DEBUG("key to send = %02x, i = %d",  key_to_dist, i);
+
+        if (key_to_dist & (1 << i))
+        {
+            SMP_TRACE_DEBUG("smp_distribute_act[%d]", i);
+            (* smp_distribute_act[i])(p_cb, p_data);
+            break;
+        }
+        i ++;
+    }
+}
+/*******************************************************************************
+** Function     smp_key_distribution
+** Description  start key distribution if required.
+*******************************************************************************/
+void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   reason = SMP_SUCCESS;
+    SMP_TRACE_DEBUG("%s role=%d (0-master) r_keys=0x%x i_keys=0x%x",
+                      __func__, p_cb->role, p_cb->local_r_key, p_cb->local_i_key);
+
+    if (p_cb->role == HCI_ROLE_SLAVE||
+        (!p_cb->local_r_key && p_cb->role == HCI_ROLE_MASTER))
+    {
+        smp_key_pick_key(p_cb, p_data);
+    }
+
+    if (!p_cb->local_i_key && !p_cb->local_r_key)
+    {
+        /* state check to prevent re-entrant */
+        if (smp_get_state() == SMP_STATE_BOND_PENDING)
+        {
+            if (p_cb->total_tx_unacked == 0)
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            else
+                p_cb->wait_for_authorization_complete = TRUE;
+        }
+    }
+}
+
+/*******************************************************************************
+** Function         smp_decide_association_model
+** Description      This function is called to select assoc model to be used for
+**                  STK generation and to start STK generation process.
+**
+*******************************************************************************/
+void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   failure = SMP_UNKNOWN_IO_CAP;
+    UINT8 int_evt = 0;
+    tSMP_KEY key;
+    tSMP_INT_DATA   *p = NULL;
+
+    SMP_TRACE_DEBUG("%s Association Model = %d", __func__, p_cb->selected_association_model);
+
+    switch (p_cb->selected_association_model)
+    {
+        case SMP_MODEL_ENCRYPTION_ONLY:  /* TK = 0, go calculate Confirm */
+            if (p_cb->role == HCI_ROLE_MASTER &&
+                ((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
+                ((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0))
+            {
+                SMP_TRACE_ERROR ("IO capability does not meet authentication requirement");
+                failure = SMP_PAIR_AUTH_FAIL;
+                p = (tSMP_INT_DATA *)&failure;
+                int_evt = SMP_AUTH_CMPL_EVT;
+            }
+            else
+            {
+                p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+                SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
+
+                key.key_type = SMP_KEY_TYPE_TK;
+                key.p_data = p_cb->tk;
+                p = (tSMP_INT_DATA *)&key;
+
+                memset(p_cb->tk, 0, BT_OCTET16_LEN);
+                /* TK, ready  */
+                int_evt = SMP_KEY_READY_EVT;
+            }
+            break;
+
+        case SMP_MODEL_PASSKEY:
+            p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+            SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+
+            p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+            int_evt = SMP_TK_REQ_EVT;
+            break;
+
+        case SMP_MODEL_OOB:
+            SMP_TRACE_ERROR ("Association Model = SMP_MODEL_OOB");
+            p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+            SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+
+            p_cb->cb_evt = SMP_OOB_REQ_EVT;
+            int_evt = SMP_TK_REQ_EVT;
+            break;
+
+        case SMP_MODEL_KEY_NOTIF:
+            p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+            SMP_TRACE_DEBUG("Need to generate Passkey");
+
+            /* generate passkey and notify application */
+            smp_generate_passkey(p_cb, NULL);
+            break;
+
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+        case SMP_MODEL_SEC_CONN_OOB:
+            int_evt = SMP_PUBL_KEY_EXCH_REQ_EVT;
+            break;
+
+        case SMP_MODEL_OUT_OF_RANGE:
+            SMP_TRACE_ERROR("Association Model = SMP_MODEL_OUT_OF_RANGE (failed)");
+            p = (tSMP_INT_DATA *)&failure;
+            int_evt = SMP_AUTH_CMPL_EVT;
+            break;
+
+        default:
+            SMP_TRACE_ERROR("Association Model = %d (SOMETHING IS WRONG WITH THE CODE)",
+                             p_cb->selected_association_model);
+            p = (tSMP_INT_DATA *)&failure;
+            int_evt = SMP_AUTH_CMPL_EVT;
+    }
+
+    SMP_TRACE_EVENT ("sec_level=%d ", p_cb->sec_level );
+    if (int_evt)
+        smp_sm_event(p_cb, int_evt, p);
+}
+
+/*******************************************************************************
+** Function     smp_process_io_response
+** Description  process IO response for a slave device.
+*******************************************************************************/
+void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    uint8_t reason = SMP_PAIR_AUTH_FAIL;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+    {
+        /* pairing started by local (slave) Security Request */
+        smp_set_state(SMP_STATE_SEC_REQ_PENDING);
+        smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
+    }
+    else /* plan to send pairing respond */
+    {
+        /* pairing started by peer (master) Pairing Request */
+        p_cb->selected_association_model = smp_select_association_model(p_cb);
+
+        if (p_cb->secure_connections_only_mode_required &&
+            (!(p_cb->le_secure_connections_mode_is_used) ||
+            (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)))
+        {
+            SMP_TRACE_ERROR ("Slave requires secure connection only mode \
+                              but it can't be provided -> Slave fails pairing");
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
+        }
+
+        if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_OOB)
+        {
+            if (smp_request_oob_data(p_cb)) return;
+        }
+        smp_send_pair_rsp(p_cb, NULL);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_br_process_slave_keys_response
+** Description  process application keys response for a slave device
+**              (BR/EDR transport).
+*******************************************************************************/
+void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    smp_br_send_pair_response(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_br_send_pair_response
+** Description  actions related to sending pairing response over BR/EDR transport.
+*******************************************************************************/
+void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    p_cb->local_i_key &= p_cb->peer_i_key;
+    p_cb->local_r_key &= p_cb->peer_r_key;
+
+    smp_send_cmd (SMP_OPCODE_PAIRING_RSP, p_cb);
+}
+
+/*******************************************************************************
+** Function         smp_pairing_cmpl
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    if (p_cb->total_tx_unacked == 0)
+    {
+        /* update connection parameter to remote preferred */
+        L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, TRUE);
+        /* process the pairing complete */
+        smp_proc_pairing_cmpl(p_cb);
+    }
+}
+
+/*******************************************************************************
+** Function         smp_pair_terminate
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    p_cb->status = SMP_CONN_TOUT;
+    smp_proc_pairing_cmpl(p_cb);
+}
+
+/*******************************************************************************
+** Function         smp_idle_terminate
+** Description      This function calledin idle state to determine to send authentication
+**                  complete or not.
+*******************************************************************************/
+void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+    {
+        SMP_TRACE_DEBUG("Pairing terminated at IDLE state.");
+        p_cb->status = SMP_FAIL;
+        smp_proc_pairing_cmpl(p_cb);
+    }
+}
+
+/*******************************************************************************
+** Function     smp_fast_conn_param
+** Description  apply default connection parameter for pairing process
+*******************************************************************************/
+void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    /* disable connection parameter update */
+    L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
+}
+
+/*******************************************************************************
+** Function     smp_both_have_public_keys
+** Description  The function is called when both local and peer public keys are
+**              saved.
+**              Actions:
+**              - invokes DHKey computation;
+**              - on slave side invokes sending local public key to the peer.
+**              - invokes SC phase 1 process.
+*******************************************************************************/
+void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s",__func__);
+
+    /* invokes DHKey computation */
+    smp_compute_dhkey(p_cb);
+
+    /* on slave side invokes sending local public key to the peer */
+    if (p_cb->role == HCI_ROLE_SLAVE)
+        smp_send_pair_public_key(p_cb, NULL);
+
+    smp_sm_event(p_cb, SMP_SC_DHKEY_CMPLT_EVT, NULL);
+}
 
 /*******************************************************************************
-** Function     smp_check_auth_req
-** Description  check authentication request
+** Function     smp_start_secure_connection_phase1
+** Description  The function starts Secure Connection phase1 i.e. invokes initialization of Secure Connection
+**              phase 1 parameters and starts building/sending to the peer
+**              messages appropriate for the role and association model.
 *******************************************************************************/
-void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8 enc_enable = *(UINT8 *)p_data;
-    UINT8 reason = enc_enable ? SMP_SUCCESS : SMP_ENC_FAIL;
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    SMP_TRACE_DEBUG ("smp_check_auth_req enc_enable=%d i_keys=0x%x r_keys=0x%x (i-initiator r-responder)",
-                      enc_enable, p_cb->loc_i_key, p_cb->loc_r_key);
-    if (enc_enable == 1)
+    if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)
     {
-        if (/*((p_cb->peer_auth_req & SMP_AUTH_BOND) ||
-             (p_cb->loc_auth_req & SMP_AUTH_BOND)) &&*/
-            (p_cb->loc_i_key || p_cb->loc_r_key))
-        {
-            smp_sm_event(p_cb, SMP_BOND_REQ_EVT, NULL);
-        }
-        else
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
     }
-    else if (enc_enable == 0)
+    else
     {
-        /* if failed for encryption after pairing, send callback */
-        if (p_cb->flags & SMP_PAIR_FLAG_ENC_AFTER_PAIR)
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-        /* if enc failed for old security information */
-        /* if master device, clean up and abck to idle; slave device do nothing */
-        else if (p_cb->role == HCI_ROLE_MASTER)
-        {
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
-        }
+        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
+        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
     }
-}
-
-/*******************************************************************************
-** Function     smp_key_pick_key
-** Description  Pick a key distribution function based on the key mask.
-*******************************************************************************/
-void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
-{
-    UINT8   key_to_dist = (p_cb->role == HCI_ROLE_SLAVE) ? p_cb->loc_r_key : p_cb->loc_i_key;
-    UINT8   i = 0;
 
-    SMP_TRACE_DEBUG ("smp_key_pick_key key_to_dist=0x%x", key_to_dist);
-    while (i < MAX_KEY_DISTRIBUTION_TYPES)
+    switch(p_cb->selected_association_model)
     {
-        SMP_TRACE_DEBUG("key to send = %02x, i = %d",  key_to_dist, i);
-
-        if (key_to_dist & (1 << i))
-        {
-            SMP_TRACE_DEBUG ("smp_distribute_act[%d]", i);
-            (* smp_distribute_act[i])(p_cb, p_data);
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+            memset(p_cb->local_random, 0, BT_OCTET16_LEN);
+            smp_start_nonce_generation(p_cb);
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+            /* user has to provide passkey */
+            p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
+            smp_sm_event(p_cb, SMP_TK_REQ_EVT, NULL);
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+            /* passkey has to be provided to user */
+            SMP_TRACE_DEBUG("Need to generate SC Passkey");
+            smp_generate_passkey(p_cb, NULL);
+            break;
+        case SMP_MODEL_SEC_CONN_OOB:
+            /* use the available OOB information */
+            smp_process_secure_connection_oob_data(p_cb, NULL);
+            break;
+        default:
+            SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+                              p_cb->selected_association_model);
             break;
-        }
-        i ++;
     }
 }
+
 /*******************************************************************************
-** Function     smp_key_distribution
-** Description  start key distribution if required.
+** Function     smp_process_local_nonce
+** Description  The function processes new local nonce.
+**
+** Note         It is supposed to be called in SC phase1.
 *******************************************************************************/
-void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   reason = SMP_SUCCESS;
-    SMP_TRACE_DEBUG ("smp_key_distribution role=%d (0-master) r_keys=0x%x i_keys=0x%x",
-                      p_cb->role, p_cb->loc_r_key, p_cb->loc_i_key);
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    if (p_cb->role == HCI_ROLE_SLAVE||
-        (!p_cb->loc_r_key && p_cb->role == HCI_ROLE_MASTER))
+    switch(p_cb->selected_association_model)
     {
-        smp_key_pick_key(p_cb, p_data);
-    }
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+            if (p_cb->role == HCI_ROLE_SLAVE)
+            {
+                /* slave calculates and sends local commitment */
+                smp_calculate_local_commitment(p_cb);
+                smp_send_commitment(p_cb, NULL);
+                /* slave has to wait for peer nonce */
+                smp_set_state(SMP_STATE_WAIT_NONCE);
+            }
+            else    /* i.e. master */
+            {
+                if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM)
+                {
+                    /* slave commitment is already received, send local nonce, wait for remote nonce*/
+                    SMP_TRACE_DEBUG("master in assoc mode = %d \
+                    already rcvd slave commitment - race condition",
+                                      p_cb->selected_association_model);
+                    p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+                    smp_send_rand(p_cb, NULL);
+                    smp_set_state(SMP_STATE_WAIT_NONCE);
+                }
+            }
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+            smp_calculate_local_commitment(p_cb);
 
-    if (!p_cb->loc_i_key && !p_cb->loc_r_key)
-    {
-        /* state check to prevent re-entrant */
-        if (smp_get_state() == SMP_ST_BOND_PENDING)
-            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            if (p_cb->role == HCI_ROLE_MASTER)
+            {
+                smp_send_commitment(p_cb, NULL);
+            }
+            else    /* slave */
+            {
+                if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_COMM)
+                {
+                    /* master commitment is already received */
+                    smp_send_commitment(p_cb, NULL);
+                    smp_set_state(SMP_STATE_WAIT_NONCE);
+                }
+            }
+            break;
+        case SMP_MODEL_SEC_CONN_OOB:
+            if (p_cb->role == HCI_ROLE_MASTER)
+            {
+                smp_send_rand(p_cb, NULL);
+            }
+
+            smp_set_state(SMP_STATE_WAIT_NONCE);
+            break;
+        default:
+            SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+                              p_cb->selected_association_model);
+            break;
     }
 }
+
 /*******************************************************************************
-** Function         smp_decide_asso_model
-** Description      This function is called to compare both sides' io capability
-**                  oob data flag and authentication request, and decide the
-**                  association model to use for the authentication.
+** Function     smp_process_peer_nonce
+** Description  The function processes newly received and saved in CB peer nonce.
+**              The actions depend on the selected association model and the role.
+**
+** Note         It is supposed to be called in SC phase1.
 *******************************************************************************/
-void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UINT8   failure = SMP_UNKNOWN_IO_CAP;
-    tSMP_ASSO_MODEL model = SMP_MODEL_MAX;
-    UINT8 int_evt = 0;
-    tSMP_KEY key;
-    tSMP_INT_DATA   *p = NULL;
-    UNUSED(p_data);
+    UINT8   reason;
 
-    SMP_TRACE_DEBUG ("smp_decide_asso_model p_cb->peer_io_caps = %d p_cb->loc_io_caps = %d \
-                       p_cb->peer_auth_req = %02x",
-                       p_cb->peer_io_caps, p_cb->loc_io_caps, p_cb->peer_auth_req);
+    SMP_TRACE_DEBUG("%s start ", __func__);
 
-    /* OOB data present on both devices, use OOB association model */
-    if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
-    {
-        model = SMP_MODEL_OOB;
-    }
-    /* no MITM required, ignore IO cap, use encryption only */
-    else if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) &&
-             SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+    switch(p_cb->selected_association_model)
     {
-        model = SMP_MODEL_ENC_ONLY;
-    }
-    else/* use IO capability to decide assiciation model */
-    {
-        if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->loc_io_caps < SMP_IO_CAP_MAX)
-        {
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+            /* in these models only master receives commitment */
             if (p_cb->role == HCI_ROLE_MASTER)
-                model = smp_association_table[p_cb->role][p_cb->peer_io_caps][p_cb->loc_io_caps];
+            {
+                if (!smp_check_commitment(p_cb))
+                {
+                    reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+                    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                    break;
+                }
+            }
             else
-                model = smp_association_table[p_cb->role][p_cb->loc_io_caps][p_cb->peer_io_caps];
-        }
+            {
+                /* slave sends local nonce */
+                smp_send_rand(p_cb, NULL);
+            }
+
+            if(p_cb->selected_association_model == SMP_MODEL_SEC_CONN_JUSTWORKS)
+            {
+                /* go directly to phase 2 */
+                smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+            }
+            else    /* numeric comparison */
+            {
+                smp_set_state(SMP_STATE_WAIT_NONCE);
+                smp_sm_event(p_cb, SMP_SC_CALC_NC_EVT, NULL);
+            }
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+            if (!smp_check_commitment(p_cb))
+            {
+                reason = p_cb->failure = SMP_CONFIRM_VALUE_ERR;
+                smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+                break;
+            }
+
+            if (p_cb->role == HCI_ROLE_SLAVE)
+            {
+                smp_send_rand(p_cb, NULL);
+            }
+
+            if (++p_cb->round < 20)
+            {
+                smp_set_state(SMP_STATE_SEC_CONN_PHS1_START);
+                p_cb->flags &= ~SMP_PAIR_FLAG_HAVE_PEER_COMM;
+                smp_start_nonce_generation(p_cb);
+                break;
+            }
+
+            smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+            break;
+        case SMP_MODEL_SEC_CONN_OOB:
+            if (p_cb->role == HCI_ROLE_SLAVE)
+            {
+                smp_send_rand(p_cb, NULL);
+            }
+
+            smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
+            break;
+        default:
+            SMP_TRACE_ERROR ("Association Model = %d is not used in LE SC",
+                              p_cb->selected_association_model);
+            break;
     }
 
-    SMP_TRACE_DEBUG("Association Model = %d", model);
+    SMP_TRACE_DEBUG("%s end ",__FUNCTION__);
+}
 
-    if (model == SMP_MODEL_OOB)
-    {
-        SMP_TRACE_ERROR("Association Model = SMP_MODEL_OOB");
-        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
-        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
-        p_cb->cb_evt = SMP_OOB_REQ_EVT;
+/*******************************************************************************
+** Function     smp_match_dhkey_checks
+** Description  checks if the calculated peer DHKey Check value is the same as
+**              received from the peer DHKey check value.
+*******************************************************************************/
+void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8 reason = SMP_DHKEY_CHK_FAIL;
 
-        int_evt = SMP_TK_REQ_EVT;
-    }
-    else if (model == SMP_MODEL_PASSKEY)
-    {
-        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
-        SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_AUTHENTICATED) ", p_cb->sec_level );
+    SMP_TRACE_DEBUG("%s", __func__);
 
-        p_cb->cb_evt = SMP_PASSKEY_REQ_EVT;
-        int_evt = SMP_TK_REQ_EVT;
-    }
-    else if (model == SMP_MODEL_KEY_NOTIF)
+    if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN))
     {
-        p_cb->sec_level = SMP_SEC_AUTHENTICATED;
-
-        SMP_TRACE_DEBUG("Need to generate Passkey");
-        /* generate passkey and notify application */
-        smp_generate_passkey(p_cb, NULL);
+        SMP_TRACE_WARNING ("dhkey chcks do no match");
+        p_cb->failure = reason;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
     }
-    else if (model == SMP_MODEL_ENC_ONLY) /* TK = 0, go calculate Confirm */
-    {
-        if (p_cb->role == HCI_ROLE_MASTER &&
-            ((p_cb->peer_auth_req & SMP_AUTH_YN_BIT) != 0) &&
-            ((p_cb->loc_auth_req & SMP_AUTH_YN_BIT) == 0))
-        {
-            SMP_TRACE_ERROR("IO capability does not meet authentication requirement");
-            failure = SMP_PAIR_AUTH_FAIL;
-            p = (tSMP_INT_DATA *)&failure;
-            int_evt = SMP_AUTH_CMPL_EVT;
-        }
-        else
-        {
-            p_cb->sec_level = SMP_SEC_UNAUTHENTICATE;
-            SMP_TRACE_EVENT ("p_cb->sec_level =%d (SMP_SEC_UNAUTHENTICATE) ", p_cb->sec_level );
 
-            key.key_type = SMP_KEY_TYPE_TK;
-            key.p_data = p_cb->tk;
-            p = (tSMP_INT_DATA *)&key;
+    SMP_TRACE_EVENT ("dhkey chcks match");
 
-            memset(p_cb->tk, 0, BT_OCTET16_LEN);
-            /* TK, ready  */
-            int_evt = SMP_KEY_READY_EVT;
-        }
+    /* 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)
+        p_cb->loc_enc_size = p_cb->peer_enc_size;
+
+    if (p_cb->role == HCI_ROLE_SLAVE)
+    {
+        smp_sm_event(p_cb, SMP_PAIR_DHKEY_CHCK_EVT, NULL);
     }
-    else if (model == SMP_MODEL_MAX)
+    else
     {
-        SMP_TRACE_ERROR("Association Model = SMP_MODEL_MAX (failed)");
-        p = (tSMP_INT_DATA *)&failure;
-        int_evt = SMP_AUTH_CMPL_EVT;
+        /* master device always use received i/r key as keys to distribute */
+        p_cb->local_i_key = p_cb->peer_i_key;
+        p_cb->local_r_key = p_cb->peer_r_key;
+        smp_sm_event(p_cb, SMP_ENC_REQ_EVT, NULL);
     }
+}
 
-    SMP_TRACE_EVENT ("sec_level=%d ", p_cb->sec_level );
-    if (int_evt)
-        smp_sm_event(p_cb, int_evt, p);
+/*******************************************************************************
+** Function     smp_move_to_secure_connections_phase2
+** Description  Signal State Machine to start SC phase 2 initialization (to
+**              compute local DHKey Check value).
+**
+** Note         SM is supposed to be in the state SMP_STATE_SEC_CONN_PHS2_START.
+*******************************************************************************/
+void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s",__func__);
+    smp_sm_event(p_cb, SMP_SC_PHASE1_CMPLT_EVT, NULL);
 }
 
 /*******************************************************************************
-** Function     smp_proc_io_rsp
-** Description  process IO response for a slave device.
+** Function     smp_phase_2_dhkey_checks_are_present
+** Description  generates event if dhkey check from the peer is already received.
+**
+** Note         It is supposed to be used on slave to prevent race condition.
+**              It is supposed to be called after slave dhkey check is calculated.
 *******************************************************************************/
-void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    SMP_TRACE_DEBUG("%s",__func__);
 
-    SMP_TRACE_DEBUG ("smp_proc_io_rsp ");
-    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
-    {
-        smp_set_state(SMP_ST_SEC_REQ_PENDING);
-        smp_send_cmd(SMP_OPCODE_SEC_REQ, p_cb);
-    }
-    else /* respond to pairing request */
-    {
-        smp_send_pair_rsp(p_cb, NULL);
-    }
+    if (p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK)
+        smp_sm_event(p_cb, SMP_SC_2_DHCK_CHKS_PRES_EVT, NULL);
 }
+
 /*******************************************************************************
-** Function         smp_pairing_cmpl
-** Description      This function is called to send the pairing complete callback
-**                  and remove the connection if needed.
+** Function     smp_wait_for_both_public_keys
+** Description  generates SMP_BOTH_PUBL_KEYS_RCVD_EVT event when both local and master
+**              public keys are available.
+**
+** Note         on the slave it is used to prevent race condition.
+**
 *******************************************************************************/
-void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
+    SMP_TRACE_DEBUG("%s",__func__);
 
-    SMP_TRACE_DEBUG ("smp_pairing_cmpl ");
-
-    if ((p_cb->status == SMP_SUCCESS) ||
-        (p_cb->status <= SMP_REPEATED_ATTEMPTS && p_cb->status != SMP_SUCCESS))
-    {
-        smp_sm_event(p_cb, SMP_RELEASE_DELAY_EVT, p_data);
-    }
-    else
+    if ((p_cb->flags & SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY) &&
+        (p_cb->flags & SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY))
     {
-        /* this will transition to idle state right away */
-        smp_sm_event(p_cb, SMP_RELEASE_DELAY_TOUT_EVT, p_data);
+        if ((p_cb->role == HCI_ROLE_SLAVE) &&
+            ((p_cb->req_oob_type == SMP_OOB_LOCAL) || (p_cb->req_oob_type == SMP_OOB_BOTH)))
+        {
+            smp_set_state(SMP_STATE_PUBLIC_KEY_EXCH);
+        }
+        smp_sm_event(p_cb, SMP_BOTH_PUBL_KEYS_RCVD_EVT, NULL);
     }
-
 }
+
 /*******************************************************************************
-** Function         smp_pair_terminate
-** Description      This function is called to send the pairing complete callback
-**                  and remove the connection if needed.
+** Function     smp_start_passkey_verification
+** Description  Starts SC passkey entry verification.
 *******************************************************************************/
-void smp_pair_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
+    UINT8 *p = NULL;
 
-    SMP_TRACE_DEBUG ("smp_pair_terminate ");
+    SMP_TRACE_DEBUG("%s", __func__);
+    p = p_cb->local_random;
+    UINT32_TO_STREAM(p, p_data->passkey);
 
-    p_cb->status = SMP_CONN_TOUT;
+    p = p_cb->peer_random;
+    UINT32_TO_STREAM(p, p_data->passkey);
 
-    smp_proc_pairing_cmpl(p_cb);
+    p_cb->round = 0;
+    smp_start_nonce_generation(p_cb);
 }
 
 /*******************************************************************************
-** Function         smp_delay_terminate
-** Description      This function is called when connection dropped when smp delay
-**                  timer is still active.
+** Function     smp_process_secure_connection_oob_data
+** Description  Processes local/peer SC OOB data received from somewhere.
 *******************************************************************************/
-void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    SMP_TRACE_DEBUG ("smp_delay_terminate ");
+    SMP_TRACE_DEBUG("%s", __func__);
 
-    btu_stop_timer (&p_cb->rsp_timer_ent);
+    tSMP_SC_OOB_DATA *p_sc_oob_data = &p_cb->sc_oob_data;
+    if (p_sc_oob_data->loc_oob_data.present)
+    {
+        memcpy(p_cb->local_random, p_sc_oob_data->loc_oob_data.randomizer,
+               sizeof(p_cb->local_random));
+    }
+    else
+    {
+        SMP_TRACE_EVENT ("local OOB randomizer is absent");
+        memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+    }
+
+    if (!p_sc_oob_data->peer_oob_data.present)
+    {
+        SMP_TRACE_EVENT ("peer OOB data is absent");
+        memset(p_cb->peer_random, 0, sizeof (p_cb->peer_random));
+    }
+    else
+    {
+        memcpy(p_cb->peer_random, p_sc_oob_data->peer_oob_data.randomizer,
+               sizeof(p_cb->peer_random));
+        memcpy(p_cb->remote_commitment, p_sc_oob_data->peer_oob_data.commitment,
+               sizeof(p_cb->remote_commitment));
+
+        UINT8 reason = SMP_CONFIRM_VALUE_ERR;
+        /* check commitment */
+        if (!smp_check_commitment(p_cb))
+        {
+            p_cb->failure = reason;
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+            return;
+        }
 
-    /* if remote user terminate connection, keep the previous status */
-    /* this is to avoid reporting reverse status to uplayer */
-    if (p_data->reason != HCI_ERR_PEER_USER)
-        p_cb->status = SMP_CONN_TOUT;
+        if (p_cb->peer_oob_flag != SMP_OOB_PRESENT)
+        {
+            /* the peer doesn't have local randomiser */
+            SMP_TRACE_EVENT ("peer didn't receive local OOB data, set local randomizer to 0");
+            memset(p_cb->local_random, 0, sizeof (p_cb->local_random));
+        }
+    }
 
-    smp_proc_pairing_cmpl(p_cb);
+    print128(p_cb->local_random, (const UINT8 *)"local OOB randomizer");
+    print128(p_cb->peer_random, (const UINT8 *)"peer OOB randomizer");
+    smp_start_nonce_generation(p_cb);
 }
+
 /*******************************************************************************
-** Function         smp_idle_terminate
-** Description      This function called in idle state to determine to send authentication
-**                  complete or not.
+** Function     smp_set_local_oob_keys
+** Description  Saves calculated private/public keys in sc_oob_data.loc_oob_data,
+**              starts nonce generation
+**              (to be saved in sc_oob_data.loc_oob_data.randomizer).
 *******************************************************************************/
-void smp_idle_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    UNUSED(p_data);
-    if (p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
-    {
-        SMP_TRACE_DEBUG("Pairing terminated at IDLE state.");
-        p_cb->status = SMP_FAIL;
-        smp_proc_pairing_cmpl(p_cb);
-    }
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    memcpy(p_cb->sc_oob_data.loc_oob_data.private_key_used, p_cb->private_key,
+           BT_OCTET32_LEN);
+    p_cb->sc_oob_data.loc_oob_data.publ_key_used = p_cb->loc_publ_key;
+    smp_start_nonce_generation(p_cb);
 }
 
 /*******************************************************************************
-** Function     smp_fast_conn_param
-** Description  apply default connection parameter for pairing process
+** Function     smp_set_local_oob_random_commitment
+** Description  Saves calculated randomizer and commitment in sc_oob_data.loc_oob_data,
+**              passes sc_oob_data.loc_oob_data up for safekeeping.
 *******************************************************************************/
-void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    /* disable connection parameter update */
-    (void)L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, FALSE);
-}
+    SMP_TRACE_DEBUG("%s", __func__);
+    memcpy(p_cb->sc_oob_data.loc_oob_data.randomizer, p_cb->rand,
+           BT_OCTET16_LEN);
+
+    smp_calculate_f4(p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                     p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                     p_cb->sc_oob_data.loc_oob_data.randomizer, 0,
+                     p_cb->sc_oob_data.loc_oob_data.commitment);
+
+#if SMP_DEBUG == TRUE
+    UINT8   *p_print = NULL;
+    SMP_TRACE_DEBUG("local SC OOB data set:");
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.addr_sent_to;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"addr_sent_to",
+                                         sizeof(tBLE_BD_ADDR));
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.private_key_used;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"private_key_used",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.x;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.x",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.publ_key_used.y;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"publ_key_used.y",
+                                         BT_OCTET32_LEN);
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.randomizer;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"randomizer",
+                                         BT_OCTET16_LEN);
+    p_print = (UINT8*) &p_cb->sc_oob_data.loc_oob_data.commitment;
+    smp_debug_print_nbyte_little_endian (p_print,(const UINT8 *) "commitment",
+                                         BT_OCTET16_LEN);
+    SMP_TRACE_DEBUG("");
+#endif
 
+    /* pass created OOB data up */
+    p_cb->cb_evt = SMP_SC_LOC_OOB_DATA_UP_EVT;
+    smp_send_app_cback(p_cb, NULL);
+
+    smp_cb_cleanup(p_cb);
+}
 
 /*******************************************************************************
 **
@@ -991,7 +1912,7 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
 {
     tSMP_CB *p_cb = &smp_cb;
 
-    SMP_TRACE_DEBUG ("smp_link_encrypted encr_enable=%d",encr_enable);
+    SMP_TRACE_DEBUG("%s encr_enable=%d", __func__, encr_enable);
 
     if (memcmp(&smp_cb.pairing_bda[0], bda, BD_ADDR_LEN) == 0)
     {
@@ -1006,6 +1927,7 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
         smp_sm_event(&smp_cb, SMP_ENCRYPTED_EVT, &encr_enable);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         smp_proc_ltk_request
@@ -1018,8 +1940,8 @@ void smp_link_encrypted(BD_ADDR bda, UINT8 encr_enable)
 *******************************************************************************/
 BOOLEAN smp_proc_ltk_request(BD_ADDR bda)
 {
-    SMP_TRACE_DEBUG ("smp_proc_ltk_request state = %d", smp_cb.state);
-    if ( smp_cb.state == SMP_ST_ENC_PENDING &&
+    SMP_TRACE_DEBUG("%s state = %d",  __func__, smp_cb.state);
+    if ( smp_cb.state == SMP_STATE_ENCRYPTION_PENDING &&
          !memcmp(bda, smp_cb.pairing_bda, BD_ADDR_LEN))
     {
         smp_sm_event(&smp_cb, SMP_ENC_REQ_EVT, NULL);
@@ -1029,5 +1951,113 @@ BOOLEAN smp_proc_ltk_request(BD_ADDR bda)
 
     return FALSE;
 }
-#endif
+
+/*******************************************************************************
+**
+** Function         smp_process_secure_connection_long_term_key
+**
+** Description      This function is called to process SC LTK.
+**                  SC LTK is calculated and used instead of STK.
+**                  Here SC LTK is saved in BLE DB.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_process_secure_connection_long_term_key(void)
+{
+    tSMP_CB     *p_cb = &smp_cb;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    smp_save_secure_connections_long_term_key(p_cb);
+
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+    smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_derive_link_key_from_long_term_key
+**
+** Description      This function is called to derive BR/EDR LK from LTK.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (!smp_calculate_link_key_from_long_term_key(p_cb))
+    {
+        SMP_TRACE_ERROR ("%s failed", __FUNCTION__);
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        return;
+    }
+
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_LK, FALSE);
+
+    SMP_TRACE_DEBUG("%s successfully completed", __FUNCTION__);
+    smp_key_distribution(p_cb, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_br_process_link_key
+**
+** Description      This function is called to process BR/EDR LK:
+**                  - to derive SMP LTK from BR/EDR LK;
+*8                  - to save SMP LTK.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (!smp_calculate_long_term_key_from_link_key(p_cb))
+    {
+        SMP_TRACE_ERROR ("%s failed",__FUNCTION__);
+        smp_sm_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+        return;
+    }
+
+    SMP_TRACE_DEBUG("%s: LTK derivation from LK successfully completed", __FUNCTION__);
+    smp_save_secure_connections_long_term_key(p_cb);
+    smp_update_key_mask (p_cb, SMP_SEC_KEY_TYPE_ENC, FALSE);
+    smp_br_select_next_key(p_cb, NULL);
+}
+
+/*******************************************************************************
+** Function     smp_key_distribution_by_transport
+** Description  depending on the transport used at the moment calls either
+**              smp_key_distribution(...) or smp_br_key_distribution(...).
+*******************************************************************************/
+void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    if (p_cb->smp_over_br)
+    {
+        smp_br_select_next_key(p_cb, NULL);
+    }
+    else
+    {
+        smp_key_distribution(p_cb, NULL);
+    }
+}
+
+/*******************************************************************************
+** Function         smp_br_pairing_complete
+** Description      This function is called to send the pairing complete callback
+**                  and remove the connection if needed.
+*******************************************************************************/
+void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* process the pairing complete */
+    smp_proc_pairing_cmpl(p_cb);
+}
+
 
index 2ebf953..4d7b16d 100644 (file)
@@ -35,7 +35,7 @@
     #include "hcimsgs.h"
 
     #include "btu.h"
-
+    #include "p_256_ecc_pp.h"
 
 /*******************************************************************************
 **
@@ -48,8 +48,6 @@
 *******************************************************************************/
 void SMP_Init(void)
 {
-
-    SMP_TRACE_EVENT ("SMP_Init");
     memset(&smp_cb, 0, sizeof(tSMP_CB));
 
 #if defined(SMP_INITIAL_TRACE_LEVEL)
@@ -57,8 +55,11 @@ void SMP_Init(void)
 #else
     smp_cb.trace_level = BT_TRACE_LEVEL_NONE;    /* No traces */
 #endif
+    SMP_TRACE_EVENT ("%s", __FUNCTION__);
 
     smp_l2cap_if_init();
+    /* initialization of P-256 parameters */
+    p_256_init_curve(KEY_LENGTH_DWORDS_P256);
 }
 
 
@@ -131,8 +132,10 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
     tSMP_CB   *p_cb = &smp_cb;
     UINT8     status = SMP_PAIR_INTERNAL_ERR;
 
-    BTM_TRACE_EVENT ("SMP_Pair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
-    if (p_cb->state != SMP_ST_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+    SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
+                      __FUNCTION__, p_cb->state, p_cb->br_state, p_cb->flags);
+    if (p_cb->state != SMP_STATE_IDLE || p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD ||
+        p_cb->smp_over_br)
     {
         /* pending security on going, reject this one */
         return SMP_BUSY;
@@ -145,7 +148,7 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
 
         if (!L2CA_ConnectFixedChnl (L2CAP_SMP_CID, bd_addr))
         {
-            SMP_TRACE_ERROR("SMP_Pair: L2C connect fixed channel failed.");
+            SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.", __FUNCTION__);
             smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
             return status;
         }
@@ -154,6 +157,49 @@ tSMP_STATUS SMP_Pair (BD_ADDR bd_addr)
     }
 }
 
+/*******************************************************************************
+**
+** Function         SMP_BR_PairWith
+**
+** Description      This function is called to start a SMP pairing over BR/EDR.
+**                  Device support one SMP pairing at one time.
+**
+** Parameters       bd_addr - peer device bd address.
+**
+** Returns          SMP_STARTED if pairing started, otherwise reason for failure.
+**
+*******************************************************************************/
+tSMP_STATUS SMP_BR_PairWith (BD_ADDR bd_addr)
+{
+    tSMP_CB   *p_cb = &smp_cb;
+    UINT8     status = SMP_PAIR_INTERNAL_ERR;
+
+    SMP_TRACE_EVENT ("%s state=%d br_state=%d flag=0x%x ",
+                      __func__, p_cb->state, p_cb->br_state, p_cb->flags);
+
+    if (p_cb->state != SMP_STATE_IDLE ||
+        p_cb->smp_over_br ||
+        p_cb->flags & SMP_PAIR_FLAGS_WE_STARTED_DD)
+    {
+        /* pending security on going, reject this one */
+        return SMP_BUSY;
+    }
+
+    p_cb->role = HCI_ROLE_MASTER;
+    p_cb->flags = SMP_PAIR_FLAGS_WE_STARTED_DD;
+    p_cb->smp_over_br = TRUE;
+
+    memcpy (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN);
+
+    if (!L2CA_ConnectFixedChnl (L2CAP_SMP_BR_CID, bd_addr))
+    {
+        SMP_TRACE_ERROR("%s: L2C connect fixed channel failed.",__FUNCTION__);
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+        return status;
+    }
+
+    return SMP_STARTED;
+}
 
 /*******************************************************************************
 **
@@ -173,7 +219,7 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
     BOOLEAN   status = FALSE;
 
     BTM_TRACE_EVENT ("SMP_CancelPair state=%d flag=0x%x ", p_cb->state, p_cb->flags);
-    if ( (p_cb->state != SMP_ST_IDLE)  &&
+    if ( (p_cb->state != SMP_STATE_IDLE)  &&
          (!memcmp (p_cb->pairing_bda, bd_addr, BD_ADDR_LEN)) )
     {
         p_cb->is_pair_cancel = TRUE;
@@ -200,11 +246,27 @@ BOOLEAN SMP_PairCancel (BD_ADDR bd_addr)
 void SMP_SecurityGrant(BD_ADDR bd_addr, UINT8 res)
 {
     SMP_TRACE_EVENT ("SMP_SecurityGrant ");
-    if (smp_cb.state != SMP_ST_WAIT_APP_RSP ||
+
+    if (smp_cb.smp_over_br)
+    {
+        if (smp_cb.br_state != SMP_BR_STATE_WAIT_APP_RSP ||
+            smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
+            memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
+        {
+            return;
+        }
+
+        /* clear the SMP_SEC_REQUEST_EVT event after get grant */
+        /* avoid generating duplicate pair request */
+        smp_cb.cb_evt = 0;
+        smp_br_state_machine_event(&smp_cb, SMP_BR_API_SEC_GRANT_EVT, &res);
+        return;
+    }
+
+    if (smp_cb.state != SMP_STATE_WAIT_APP_RSP ||
         smp_cb.cb_evt != SMP_SEC_REQUEST_EVT ||
         memcmp (smp_cb.pairing_bda, bd_addr, BD_ADDR_LEN))
         return;
-
     /* clear the SMP_SEC_REQUEST_EVT event after get grant */
     /* avoid generate duplicate pair request */
     smp_cb.cb_evt = 0;
@@ -228,7 +290,6 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
 {
     tSMP_CB *p_cb = & smp_cb;
     UINT8   failure = SMP_PASSKEY_ENTRY_FAIL;
-    tBTM_SEC_DEV_REC *p_dev_rec;
 
     SMP_TRACE_EVENT ("SMP_PasskeyReply: Key: %d  Result:%d",
                       passkey, res);
@@ -246,13 +307,12 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
         return;
     }
 
-    if ((p_dev_rec = btm_find_dev (bd_addr)) == NULL)
+    if (btm_find_dev (bd_addr) == NULL)
     {
         SMP_TRACE_ERROR ("SMP_PasskeyReply() - no dev CB");
         return;
     }
 
-
     if (passkey > BTM_MAX_PASSKEY_VAL || res != SMP_SUCCESS)
     {
         SMP_TRACE_WARNING ("SMP_PasskeyReply() - Wrong key len: %d or passkey entry fail", passkey);
@@ -260,6 +320,10 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
 
     }
+    else if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_ENT)
+    {
+        smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &passkey);
+    }
     else
     {
         smp_convert_string_to_tk(p_cb->tk, passkey);
@@ -270,6 +334,56 @@ void SMP_PasskeyReply (BD_ADDR bd_addr, UINT8 res, UINT32 passkey)
 
 /*******************************************************************************
 **
+** Function         SMP_ConfirmReply
+**
+** Description      This function is called after Security Manager submitted
+**                  numeric comparison request to the application.
+**
+** Parameters:      bd_addr      - Address of the device with which numeric
+**                                 comparison was requested
+**                  res          - comparison result SMP_SUCCESS if success
+**
+*******************************************************************************/
+void SMP_ConfirmReply (BD_ADDR bd_addr, UINT8 res)
+{
+    tSMP_CB *p_cb = & smp_cb;
+    UINT8   failure = SMP_NUMERIC_COMPAR_FAIL;
+
+    SMP_TRACE_EVENT ("%s: Result:%d", __FUNCTION__, res);
+
+    /* If timeout already expired or has been canceled, ignore the reply */
+    if (p_cb->cb_evt != SMP_NC_REQ_EVT)
+    {
+        SMP_TRACE_WARNING ("%s() - Wrong State: %d", __FUNCTION__,p_cb->state);
+        return;
+    }
+
+    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
+    {
+        SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
+        return;
+    }
+
+    if (btm_find_dev (bd_addr) == NULL)
+    {
+        SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
+        return;
+    }
+
+    if (res != SMP_SUCCESS)
+    {
+        SMP_TRACE_WARNING ("%s() - Numeric Comparison fails",__FUNCTION__);
+        /* send pairing failure */
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+    }
+    else
+    {
+        smp_sm_event(p_cb, SMP_SC_NC_OK_EVT, NULL);
+    }
+}
+
+/*******************************************************************************
+**
 ** Function         SMP_OobDataReply
 **
 ** Description      This function is called to provide the OOB data for
@@ -285,13 +399,11 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data
     tSMP_CB *p_cb = & smp_cb;
     UINT8   failure = SMP_OOB_FAIL;
     tSMP_KEY        key;
-    UNUSED(bd_addr);
 
-    SMP_TRACE_EVENT ("SMP_OobDataReply State: %d  res:%d",
-                      smp_cb.state, res);
+    SMP_TRACE_EVENT ("%s State: %d  res:%d", __FUNCTION__, smp_cb.state, res);
 
     /* If timeout already expired or has been canceled, ignore the reply */
-    if (p_cb->state != SMP_ST_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
+    if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_OOB_REQ_EVT)
         return;
 
     if (res != SMP_SUCCESS || len == 0 || !p_data)
@@ -314,6 +426,69 @@ void SMP_OobDataReply(BD_ADDR bd_addr, tSMP_STATUS res, UINT8 len, UINT8 *p_data
 
 /*******************************************************************************
 **
+** Function         SMP_SecureConnectionOobDataReply
+**
+** Description      This function is called to provide the SC OOB data for
+**                  SMP in response to SMP_SC_OOB_REQ_EVT
+**
+** Parameters:      p_data      - pointer to the data
+**
+*******************************************************************************/
+void SMP_SecureConnectionOobDataReply(UINT8 *p_data)
+{
+    tSMP_CB  *p_cb = &smp_cb;
+
+    UINT8  failure = SMP_OOB_FAIL;
+    tSMP_SC_OOB_DATA  *p_oob = (tSMP_SC_OOB_DATA *) p_data;
+    if (!p_oob)
+    {
+        SMP_TRACE_ERROR("%s received no data",__FUNCTION__);
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+        return;
+    }
+
+    SMP_TRACE_EVENT ("%s req_oob_type: %d, loc_oob_data.present: %d, "
+                       "peer_oob_data.present: %d",
+                       __FUNCTION__, p_cb->req_oob_type, p_oob->loc_oob_data.present,
+                       p_oob->peer_oob_data.present);
+
+    if (p_cb->state != SMP_STATE_WAIT_APP_RSP || p_cb->cb_evt != SMP_SC_OOB_REQ_EVT)
+        return;
+
+    BOOLEAN  data_missing = FALSE;
+    switch (p_cb->req_oob_type)
+    {
+        case SMP_OOB_PEER:
+            if (!p_oob->peer_oob_data.present)
+                data_missing = TRUE;
+            break;
+        case SMP_OOB_LOCAL:
+            if (!p_oob->loc_oob_data.present)
+                data_missing = TRUE;
+            break;
+        case SMP_OOB_BOTH:
+            if (!p_oob->loc_oob_data.present || !p_oob->peer_oob_data.present)
+                data_missing = TRUE;
+            break;
+        default:
+            SMP_TRACE_EVENT ("Unexpected OOB data type requested. Fail OOB");
+            data_missing = TRUE;
+            break;
+    }
+
+    if (data_missing)
+    {
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+        return;
+    }
+
+    p_cb->sc_oob_data = *p_oob;
+
+    smp_sm_event(&smp_cb, SMP_SC_OOB_DATA_EVT, p_data);
+}
+
+/*******************************************************************************
+**
 ** Function         SMP_Encrypt
 **
 ** Description      This function is called to encrypt the data with the specified
@@ -337,4 +512,96 @@ BOOLEAN SMP_Encrypt (UINT8 *key, UINT8 key_len,
     status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
     return status;
 }
+
+/*******************************************************************************
+**
+** Function         SMP_KeypressNotification
+**
+** Description      This function is called to notify Security Manager about Keypress Notification.
+**
+** Parameters:     bd_addr      Address of the device to send keypress notification to
+**                 value        Keypress notification parameter value
+**
+*******************************************************************************/
+void SMP_KeypressNotification (BD_ADDR bd_addr, UINT8 value)
+{
+    tSMP_CB   *p_cb = &smp_cb;
+
+    SMP_TRACE_EVENT ("%s: Value: %d", __FUNCTION__,value);
+
+    if (memcmp (bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) != 0)
+    {
+        SMP_TRACE_ERROR ("%s() - Wrong BD Addr",__FUNCTION__);
+        return;
+    }
+
+    if (btm_find_dev (bd_addr) == NULL)
+    {
+        SMP_TRACE_ERROR ("%s() - no dev CB",__FUNCTION__);
+        return;
+    }
+
+    /* Keypress Notification is used by a device with KeyboardOnly IO capabilities */
+    /* during the passkey entry protocol */
+    if (p_cb->local_io_capability != SMP_IO_CAP_IN)
+    {
+        SMP_TRACE_ERROR ("%s() - wrong local IO capabilities %d",
+                          __FUNCTION__, p_cb->local_io_capability);
+        return;
+    }
+
+    if (p_cb->selected_association_model != SMP_MODEL_SEC_CONN_PASSKEY_ENT)
+    {
+        SMP_TRACE_ERROR ("%s() - wrong protocol %d", __FUNCTION__,
+                         p_cb->selected_association_model);
+        return;
+    }
+
+    smp_sm_event(p_cb, SMP_KEYPRESS_NOTIFICATION_EVENT, &value);
+}
+
+/*******************************************************************************
+**
+** Function         SMP_CreateLocalSecureConnectionsOobData
+**
+** Description      This function is called to start creation of local SC OOB
+**                  data set (tSMP_LOC_OOB_DATA).
+**
+** Parameters:      bd_addr      - Address of the device to send OOB data block to
+**
+**  Returns         Boolean - TRUE: creation of local SC OOB data set started.
+*******************************************************************************/
+BOOLEAN SMP_CreateLocalSecureConnectionsOobData (tBLE_BD_ADDR *addr_to_send_to)
+{
+    tSMP_CB *p_cb = &smp_cb;
+    UINT8   *bd_addr;
+
+    if (addr_to_send_to == NULL)
+    {
+        SMP_TRACE_ERROR ("%s addr_to_send_to is not provided",__FUNCTION__);
+        return FALSE;
+    }
+
+    bd_addr = addr_to_send_to->bda;
+
+    SMP_TRACE_EVENT ("%s addr type: %u,  BDA: %08x%04x,  state: %u, br_state: %u",
+                      __FUNCTION__, addr_to_send_to->type,
+                      (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
+                      (bd_addr[4]<<8)+bd_addr[5],
+                      p_cb->state,
+                      p_cb->br_state);
+
+    if ((p_cb->state != SMP_STATE_IDLE) || (p_cb->smp_over_br))
+    {
+        SMP_TRACE_WARNING ("%s creation of local OOB data set "\
+            "starts only in IDLE state",__FUNCTION__);
+        return FALSE;
+    }
+
+    p_cb->sc_oob_data.loc_oob_data.addr_sent_to = *addr_to_send_to;
+    smp_sm_event(p_cb, SMP_CR_LOC_SC_OOB_DATA_EVT, NULL);
+
+    return TRUE;
+}
+
 #endif /* SMP_INCLUDED */
diff --git a/stack/smp/smp_br_main.c b/stack/smp/smp_br_main.c
new file mode 100644 (file)
index 0000000..573db7f
--- /dev/null
@@ -0,0 +1,397 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2014-2015 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 <string.h>
+#include "smp_int.h"
+
+const char *const smp_br_state_name [SMP_BR_STATE_MAX+1] =
+{
+    "SMP_BR_STATE_IDLE",
+    "SMP_BR_STATE_WAIT_APP_RSP",
+    "SMP_BR_STATE_PAIR_REQ_RSP",
+    "SMP_BR_STATE_BOND_PENDING",
+    "SMP_BR_STATE_OUT_OF_RANGE"
+};
+
+const char *const smp_br_event_name [SMP_BR_MAX_EVT] =
+{
+    "BR_PAIRING_REQ_EVT",
+    "BR_PAIRING_RSP_EVT",
+    "BR_CONFIRM_EVT",
+    "BR_RAND_EVT",
+    "BR_PAIRING_FAILED_EVT",
+    "BR_ENCRPTION_INFO_EVT",
+    "BR_MASTER_ID_EVT",
+    "BR_ID_INFO_EVT",
+    "BR_ID_ADDR_EVT",
+    "BR_SIGN_INFO_EVT",
+    "BR_SECURITY_REQ_EVT",
+    "BR_PAIR_PUBLIC_KEY_EVT",
+    "BR_PAIR_DHKEY_CHCK_EVT",
+    "BR_PAIR_KEYPR_NOTIF_EVT",
+    "BR_KEY_READY_EVT",
+    "BR_ENCRYPTED_EVT",
+    "BR_L2CAP_CONN_EVT",
+    "BR_L2CAP_DISCONN_EVT",
+    "BR_KEYS_RSP_EVT",
+    "BR_API_SEC_GRANT_EVT",
+    "BR_TK_REQ_EVT",
+    "BR_AUTH_CMPL_EVT",
+    "BR_ENC_REQ_EVT",
+    "BR_BOND_REQ_EVT",
+    "BR_DISCARD_SEC_REQ_EVT",
+    "BR_OUT_OF_RANGE_EVT"
+};
+
+const char *smp_get_br_event_name(tSMP_BR_EVENT event);
+const char *smp_get_br_state_name(tSMP_BR_STATE state);
+
+#define SMP_BR_SM_IGNORE       0
+#define SMP_BR_NUM_ACTIONS     2
+#define SMP_BR_SME_NEXT_STATE  2
+#define SMP_BR_SM_NUM_COLS     3
+typedef const UINT8 (*tSMP_BR_SM_TBL)[SMP_BR_SM_NUM_COLS];
+
+enum
+{
+    SMP_SEND_PAIR_REQ,
+    SMP_BR_SEND_PAIR_RSP,
+    SMP_SEND_PAIR_FAIL,
+    SMP_SEND_ID_INFO,
+    SMP_BR_PROC_PAIR_CMD,
+    SMP_PROC_PAIR_FAIL,
+    SMP_PROC_ID_INFO,
+    SMP_PROC_ID_ADDR,
+    SMP_PROC_SRK_INFO,
+    SMP_BR_PROC_SEC_GRANT,
+    SMP_BR_PROC_SL_KEYS_RSP,
+    SMP_BR_KEY_DISTRIBUTION,
+    SMP_BR_PAIRING_COMPLETE,
+    SMP_SEND_APP_CBACK,
+    SMP_BR_CHECK_AUTH_REQ,
+    SMP_PAIR_TERMINATE,
+    SMP_IDLE_TERMINATE,
+    SMP_BR_SM_NO_ACTION
+};
+
+static const tSMP_ACT smp_br_sm_action[] =
+{
+    smp_send_pair_req,
+    smp_br_send_pair_response,
+    smp_send_pair_fail,
+    smp_send_id_info,
+    smp_br_process_pairing_command,
+    smp_proc_pair_fail,
+    smp_proc_id_info,
+    smp_proc_id_addr,
+    smp_proc_srk_info,
+    smp_br_process_security_grant,
+    smp_br_process_slave_keys_response,
+    smp_br_select_next_key,
+    smp_br_pairing_complete,
+    smp_send_app_cback,
+    smp_br_check_authorization_request,
+    smp_pair_terminate,
+    smp_idle_terminate
+};
+
+static const UINT8 smp_br_all_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                               Event                    Action           Next State */
+/* BR_PAIRING_FAILED        */  {SMP_PROC_PAIR_FAIL,  SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
+/* BR_AUTH_CMPL             */  {SMP_SEND_PAIR_FAIL,  SMP_BR_PAIRING_COMPLETE, SMP_BR_STATE_IDLE},
+/* BR_L2CAP_DISCONN         */  {SMP_PAIR_TERMINATE,  SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
+};
+
+/************ SMP Master FSM State/Event Indirection Table **************/
+static const UINT8 smp_br_master_entry_map[][SMP_BR_STATE_MAX] =
+{
+/* br_state name:               Idle      WaitApp  Pair    Bond
+                                          Rsp      ReqRsp  Pend       */
+/* BR_PAIRING_REQ           */  { 0,       0,       0,      0     },
+/* BR_PAIRING_RSP           */  { 0,       0,       1,      0     },
+/* BR_CONFIRM               */  { 0,       0,       0,      0     },
+/* BR_RAND                  */  { 0,       0,       0,      0     },
+/* BR_PAIRING_FAILED        */  { 0,       0x81,    0x81,   0     },
+/* BR_ENCRPTION_INFO        */  { 0,       0,       0,      0     },
+/* BR_MASTER_ID             */  { 0,       0,       0,      0     },
+/* BR_ID_INFO               */  { 0,       0,       0,      1     },
+/* BR_ID_ADDR               */  { 0,       0,       0,      2     },
+/* BR_SIGN_INFO             */  { 0,       0,       0,      3     },
+/* BR_SECURITY_REQ          */  { 0,       0,       0,      0     },
+/* BR_PAIR_PUBLIC_KEY_EVT   */  { 0,       0,       0,      0     },
+/* BR_PAIR_DHKEY_CHCK_EVT   */  { 0,       0,       0,      0     },
+/* BR_PAIR_KEYPR_NOTIF_EVT  */  { 0,       0,       0,      0     },
+/* BR_KEY_READY             */  { 0,       0,       0,      0     },
+/* BR_ENCRYPTED             */  { 0,       0,       0,      0     },
+/* BR_L2CAP_CONN            */  { 1,       0,       0,      0     },
+/* BR_L2CAP_DISCONN         */  { 2,       0x83,    0x83,   0x83  },
+/* BR_KEYS_RSP              */  { 0,       1,       0,      0     },
+/* BR_API_SEC_GRANT         */  { 0,       0,       0,      0     },
+/* BR_TK_REQ                */  { 0,       0,       0,      0     },
+/* BR_AUTH_CMPL             */  { 0,       0x82,    0x82,   0x82  },
+/* BR_ENC_REQ               */  { 0,       0,       0,      0     },
+/* BR_BOND_REQ              */  { 0,       0,       2,      0     },
+/* BR_DISCARD_SEC_REQ       */  { 0,       0,       0,      0     }
+};
+
+static const UINT8 smp_br_master_idle_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                                Event               Action               Next State */
+/* BR_L2CAP_CONN        */  {SMP_SEND_APP_CBACK, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_L2CAP_DISCONN   */  {SMP_IDLE_TERMINATE,  SMP_BR_SM_NO_ACTION, SMP_BR_STATE_IDLE}
+};
+
+static const UINT8 smp_br_master_wait_appln_response_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                                Event               Action              Next State */
+/* BR_KEYS_RSP           */{SMP_SEND_PAIR_REQ, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_PAIR_REQ_RSP}
+};
+
+static const UINT8 smp_br_master_pair_request_response_table [][SMP_BR_SM_NUM_COLS] =
+{
+/*                        Event               Action                  Next State */
+/* BR_PAIRING_RSP   */  {SMP_BR_PROC_PAIR_CMD, SMP_BR_CHECK_AUTH_REQ, SMP_BR_STATE_PAIR_REQ_RSP},
+/* BR_BOND_REQ      */  {SMP_BR_SM_NO_ACTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_master_bond_pending_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                                Event               Action              Next State */
+/* BR_ID_INFO               */{SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_ID_ADDR               */{SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_SIGN_INFO             */{SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_slave_entry_map[][SMP_BR_STATE_MAX] =
+{
+/* br_state name:               Idle      WaitApp  Pair    Bond
+                                          Rsp      ReqRsp  Pend      */
+/* BR_PAIRING_REQ           */  { 1,       0,       0,      0    },
+/* BR_PAIRING_RSP           */  { 0,       0,       0,      0    },
+/* BR_CONFIRM               */  { 0,       0,       0,      0    },
+/* BR_RAND                  */  { 0,       0,       0,      0    },
+/* BR_PAIRING_FAILED        */  { 0,       0x81,    0x81,   0x81 },
+/* BR_ENCRPTION_INFO        */  { 0,       0,       0,      0    },
+/* BR_MASTER_ID             */  { 0,       0,       0,      0    },
+/* BR_ID_INFO               */  { 0,       0,       0,      1    },
+/* BR_ID_ADDR               */  { 0,       0,       0,      2    },
+/* BR_SIGN_INFO             */  { 0,       0,       0,      3    },
+/* BR_SECURITY_REQ          */  { 0,       0,       0,      0    },
+/* BR_PAIR_PUBLIC_KEY_EVT   */  { 0,       0,       0,      0    },
+/* BR_PAIR_DHKEY_CHCK_EVT   */  { 0,       0,       0,      0    },
+/* BR_PAIR_KEYPR_NOTIF_EVT  */  { 0,       0,       0,      0    },
+/* BR_KEY_READY             */  { 0,       0,       0,      0    },
+/* BR_ENCRYPTED             */  { 0,       0,       0,      0    },
+/* BR_L2CAP_CONN            */  { 0,       0,       0,      0    },
+/* BR_L2CAP_DISCONN         */  { 0,       0x83,    0x83,   0x83 },
+/* BR_KEYS_RSP              */  { 0,       2,       0,      0    },
+/* BR_API_SEC_GRANT         */  { 0,       1,       0,      0    },
+/* BR_TK_REQ                */  { 0,       0,       0,      0    },
+/* BR_AUTH_CMPL             */  { 0,       0x82,    0x82,   0x82 },
+/* BR_ENC_REQ               */  { 0,       0,       0,      0    },
+/* BR_BOND_REQ              */  { 0,       3,       0,      0    },
+/* BR_DISCARD_SEC_REQ       */  { 0,       0,       0,      0    }
+};
+
+static const UINT8 smp_br_slave_idle_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                               Event                Action              Next State */
+/* BR_PAIRING_REQ    */ {SMP_BR_PROC_PAIR_CMD, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP}
+};
+
+static const UINT8 smp_br_slave_wait_appln_response_table [][SMP_BR_SM_NUM_COLS] =
+{
+/*                               Event                 Action             Next State */
+/* BR_API_SEC_GRANT */ {SMP_BR_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_KEYS_RSP     */{SMP_BR_PROC_SL_KEYS_RSP, SMP_BR_CHECK_AUTH_REQ,SMP_BR_STATE_WAIT_APP_RSP},
+/* BR_BOND_REQ        */ {SMP_BR_KEY_DISTRIBUTION, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const UINT8 smp_br_slave_bond_pending_table[][SMP_BR_SM_NUM_COLS] =
+{
+/*                                Event               Action               Next State */
+/* BR_ID_INFO               */  {SMP_PROC_ID_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_ID_ADDR               */  {SMP_PROC_ID_ADDR, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING},
+/* BR_SIGN_INFO             */  {SMP_PROC_SRK_INFO, SMP_BR_SM_NO_ACTION, SMP_BR_STATE_BOND_PENDING}
+};
+
+static const tSMP_BR_SM_TBL smp_br_state_table[][2] =
+{
+    /* SMP_BR_STATE_IDLE */
+    {smp_br_master_idle_table, smp_br_slave_idle_table},
+
+    /* SMP_BR_STATE_WAIT_APP_RSP */
+    {smp_br_master_wait_appln_response_table, smp_br_slave_wait_appln_response_table},
+
+    /* SMP_BR_STATE_PAIR_REQ_RSP */
+    {smp_br_master_pair_request_response_table, NULL},
+
+    /* SMP_BR_STATE_BOND_PENDING */
+    {smp_br_master_bond_pending_table, smp_br_slave_bond_pending_table},
+};
+
+typedef const UINT8 (*tSMP_BR_ENTRY_TBL)[SMP_BR_STATE_MAX];
+
+static const tSMP_BR_ENTRY_TBL smp_br_entry_table[] =
+{
+    smp_br_master_entry_map,
+    smp_br_slave_entry_map
+};
+
+#define SMP_BR_ALL_TABLE_MASK  0x80
+
+/*******************************************************************************
+** Function     smp_set_br_state
+** Returns      None
+*******************************************************************************/
+void smp_set_br_state(tSMP_BR_STATE br_state)
+{
+    if (br_state < SMP_BR_STATE_MAX)
+    {
+        SMP_TRACE_DEBUG( "BR_State change: %s(%d) ==> %s(%d)",
+                          smp_get_br_state_name(smp_cb.br_state), smp_cb.br_state,
+                          smp_get_br_state_name(br_state), br_state );
+        smp_cb.br_state = br_state;
+    }
+    else
+    {
+        SMP_TRACE_DEBUG("%s invalid br_state =%d", __FUNCTION__,br_state );
+    }
+}
+
+/*******************************************************************************
+** Function     smp_get_br_state
+** Returns      The smp_br state
+*******************************************************************************/
+tSMP_BR_STATE smp_get_br_state(void)
+{
+    return smp_cb.br_state;
+}
+
+/*******************************************************************************
+** Function     smp_get_br_state_name
+** Returns      The smp_br state name.
+*******************************************************************************/
+const char *smp_get_br_state_name(tSMP_BR_STATE br_state)
+{
+    const char *p_str = smp_br_state_name[SMP_BR_STATE_MAX];
+
+    if (br_state < SMP_BR_STATE_MAX)
+        p_str = smp_br_state_name[br_state];
+
+    return p_str;
+}
+/*******************************************************************************
+** Function     smp_get_br_event_name
+** Returns      The smp_br event name.
+*******************************************************************************/
+const char * smp_get_br_event_name(tSMP_BR_EVENT event)
+{
+    const char * p_str = smp_br_event_name[SMP_BR_MAX_EVT - 1];
+
+    if (event < SMP_BR_MAX_EVT)
+    {
+        p_str = smp_br_event_name[event- 1];
+    }
+    return p_str;
+}
+
+/*******************************************************************************
+**
+** Function     smp_br_state_machine_event
+**
+** Description  Handle events to the state machine. It looks up the entry
+**              in the smp_br_entry_table array.
+**              If it is a valid entry, it gets the state table.Set the next state,
+**              if not NULL state. Execute the action function according to the
+**              state table. If the state returned by action function is not NULL
+**              state, adjust the new state to the returned state.
+**
+** Returns      void.
+**
+*******************************************************************************/
+void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data)
+{
+    tSMP_BR_STATE       curr_state = p_cb->br_state;
+    tSMP_BR_SM_TBL      state_table;
+    UINT8               action, entry;
+    tSMP_BR_ENTRY_TBL   entry_table =  smp_br_entry_table[p_cb->role];
+
+    SMP_TRACE_EVENT("main %s", __func__);
+    if (curr_state >= SMP_BR_STATE_MAX)
+    {
+        SMP_TRACE_DEBUG( "Invalid br_state: %d", curr_state) ;
+        return;
+    }
+
+    SMP_TRACE_DEBUG( "SMP Role: %s State: [%s (%d)], Event: [%s (%d)]",
+                      (p_cb->role == HCI_ROLE_SLAVE) ? "Slave" : "Master",
+                      smp_get_br_state_name( p_cb->br_state),
+                      p_cb->br_state, smp_get_br_event_name(event), event) ;
+
+    /* look up the state table for the current state */
+    /* lookup entry / w event & curr_state */
+    /* If entry is ignore, return.
+     * Otherwise, get state table (according to curr_state or all_state) */
+    if ((event <= SMP_BR_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state])
+        != SMP_BR_SM_IGNORE ))
+    {
+        if (entry & SMP_BR_ALL_TABLE_MASK)
+        {
+            entry &= ~SMP_BR_ALL_TABLE_MASK;
+            state_table = smp_br_all_table;
+        }
+        else
+        {
+            state_table = smp_br_state_table[curr_state][p_cb->role];
+        }
+    }
+    else
+    {
+        SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
+                          smp_get_br_event_name(event), event,
+                          smp_get_br_state_name(curr_state), curr_state);
+        return;
+    }
+
+    /* Get possible next state from state table. */
+
+    smp_set_br_state(state_table[entry - 1][SMP_BR_SME_NEXT_STATE]);
+
+    /* If action is not ignore, clear param, exec action and get next state.
+     * The action function may set the Param for cback.
+     * Depending on param, call cback or free buffer. */
+    /* execute action functions */
+    for (UINT8 i = 0; i < SMP_BR_NUM_ACTIONS; i++)
+    {
+        if ((action = state_table[entry - 1][i]) != SMP_BR_SM_NO_ACTION)
+        {
+            (*smp_br_sm_action[action])(p_cb, (tSMP_INT_DATA *)p_data);
+        }
+        else
+        {
+            break;
+        }
+    }
+    SMP_TRACE_DEBUG( "result state = %s", smp_get_br_state_name( p_cb->br_state ) ) ;
+}
+
+
index 138c6f1..9ed2957 100644 (file)
@@ -49,7 +49,7 @@ BT_OCTET16 const_Rb = {
 
 void print128(BT_OCTET16 x, const UINT8 *key_name)
 {
-#if SMP_DEBUG == TRUE
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
     UINT8  *p = (UINT8 *)x;
     UINT8  i;
 
@@ -278,7 +278,7 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
 }
 /*******************************************************************************
 **
-** Function         AES_CMAC
+** Function         aes_cipher_msg_auth_code
 **
 ** Description      This is the AES-CMAC Generation Function with tlen implemented.
 **
@@ -288,17 +288,17 @@ static BOOLEAN cmac_generate_subkey(BT_OCTET16 key)
 **                  tlen - lenth of mac desired
 **                  p_signature - data pointer to where signed data to be stored, tlen long.
 **
-** Returns          void
+** Returns          FALSE if out of resources, TRUE in other cases.
 **
 *******************************************************************************/
-BOOLEAN AES_CMAC ( BT_OCTET16 key, UINT8 *input, UINT16 length,
-                UINT16 tlen, UINT8 *p_signature)
+BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
+                                 UINT16 tlen, UINT8 *p_signature)
 {
     UINT16  len, diff;
     UINT16  n = (length + BT_OCTET16_LEN - 1) / BT_OCTET16_LEN;       /* n is number of rounds */
     BOOLEAN ret = FALSE;
 
-    SMP_TRACE_EVENT ("AES_CMAC  ");
+    SMP_TRACE_EVENT ("%s", __func__);
 
     if (n == 0)  n = 1;
     len = n * BT_OCTET16_LEN;
@@ -380,7 +380,7 @@ void test_cmac(void)
 
     SMP_TRACE_WARNING("\n Example 1: len = %d\n", len);
 
-    AES_CMAC(key, M, len, 128, test_cmac_cback, 0);
+    aes_cipher_msg_auth_code(key, M, len, 128, test_cmac_cback, 0);
 
 }
     #endif
index af5102d..24aa3ec 100644 (file)
  *  This file contains internally used SMP definitions
  *
  ******************************************************************************/
-
 #ifndef  SMP_INT_H
 #define  SMP_INT_H
 
 #include "btu.h"
+#include "btm_ble_api.h"
+#include "btm_api.h"
 #include "smp_api.h"
 
-#define SMP_MODEL_ENC_ONLY  0
-#define SMP_MODEL_PASSKEY   1
-#define SMP_MODEL_OOB       2
-#define SMP_MODEL_KEY_NOTIF 3
-#define SMP_MODEL_MAX       4
+#define SMP_MODEL_ENCRYPTION_ONLY  0   /* Legacy mode, Just Works model */
+#define SMP_MODEL_PASSKEY       1   /* Legacy mode, Passkey Entry model, this side inputs the key */
+#define SMP_MODEL_OOB           2   /* Legacy mode, OOB model */
+#define SMP_MODEL_KEY_NOTIF     3   /* Legacy mode, Passkey Entry model, this side displays the key */
+#define SMP_MODEL_SEC_CONN_JUSTWORKS  4  /* Secure Connections mode, Just Works model */
+#define SMP_MODEL_SEC_CONN_NUM_COMP   5  /* Secure Connections mode, Numeric Comparison model */
+#define SMP_MODEL_SEC_CONN_PASSKEY_ENT 6 /* Secure Connections mode, Passkey Entry model, */
+                                    /* this side inputs the key */
+#define SMP_MODEL_SEC_CONN_PASSKEY_DISP 7   /* Secure Connections mode, Passkey Entry model, */
+                                    /* this side displays the key */
+#define SMP_MODEL_SEC_CONN_OOB  8   /* Secure Connections mode, OOB model */
+#define SMP_MODEL_OUT_OF_RANGE  9
 typedef UINT8   tSMP_ASSO_MODEL;
 
 
@@ -40,27 +48,15 @@ typedef UINT8   tSMP_ASSO_MODEL;
     #define SMP_MAX_CONN    2
 #endif
 
-#define SMP_WAIT_FOR_RSP_TOUT                  30
-#define SMP_WAIT_FOR_REL_DELAY_TOUT     5
-/* SMP L2CAP command code */
-#define SMP_OPCODE_PAIRING_REQ            0x01
-#define SMP_OPCODE_PAIRING_RSP            0x02
-#define SMP_OPCODE_CONFIRM                0x03
+#define SMP_WAIT_FOR_RSP_TOUT           30
+
 #define SMP_OPCODE_INIT                   0x04
-#define SMP_OPCODE_PAIRING_FAILED         0x05
-#define SMP_OPCODE_ENCRYPT_INFO           0x06
-#define SMP_OPCODE_MASTER_ID              0x07
-#define SMP_OPCODE_IDENTITY_INFO          0x08
-#define SMP_OPCODE_ID_ADDR                0x09
-#define SMP_OPCODE_SIGN_INFO              0x0A
-#define SMP_OPCODE_SEC_REQ                0x0B
-#define SMP_OPCODE_MAX                    (SMP_OPCODE_SEC_REQ + 1)
 
 /* SMP events */
 #define SMP_PAIRING_REQ_EVT             SMP_OPCODE_PAIRING_REQ
 #define SMP_PAIRING_RSP_EVT             SMP_OPCODE_PAIRING_RSP
 #define SMP_CONFIRM_EVT                 SMP_OPCODE_CONFIRM
-#define SMP_RAND_EVT                    SMP_OPCODE_INIT
+#define SMP_RAND_EVT                    SMP_OPCODE_RAND
 #define SMP_PAIRING_FAILED_EVT          SMP_OPCODE_PAIRING_FAILED
 #define SMP_ENCRPTION_INFO_EVT          SMP_OPCODE_ENCRYPT_INFO
 #define SMP_MASTER_ID_EVT               SMP_OPCODE_MASTER_ID
@@ -69,43 +65,136 @@ typedef UINT8   tSMP_ASSO_MODEL;
 #define SMP_SIGN_INFO_EVT               SMP_OPCODE_SIGN_INFO
 #define SMP_SECURITY_REQ_EVT            SMP_OPCODE_SEC_REQ
 
-#define SMP_SELF_DEF_EVT                SMP_SECURITY_REQ_EVT
-#define SMP_KEY_READY_EVT               (SMP_SELF_DEF_EVT + 1)
-#define SMP_ENCRYPTED_EVT               (SMP_SELF_DEF_EVT + 2)
-#define SMP_L2CAP_CONN_EVT              (SMP_SELF_DEF_EVT + 3)
-#define SMP_L2CAP_DISCONN_EVT           (SMP_SELF_DEF_EVT + 4)
-#define SMP_IO_RSP_EVT                  (SMP_SELF_DEF_EVT + 5)
-#define SMP_API_SEC_GRANT_EVT           (SMP_SELF_DEF_EVT + 6)
-#define SMP_TK_REQ_EVT                  (SMP_SELF_DEF_EVT + 7)
-#define SMP_AUTH_CMPL_EVT               (SMP_SELF_DEF_EVT + 8)
-#define SMP_ENC_REQ_EVT                 (SMP_SELF_DEF_EVT + 9)
-#define SMP_BOND_REQ_EVT                (SMP_SELF_DEF_EVT + 10)
-#define SMP_DISCARD_SEC_REQ_EVT         (SMP_SELF_DEF_EVT + 11)
-#define SMP_RELEASE_DELAY_EVT           (SMP_SELF_DEF_EVT + 12)
-#define SMP_RELEASE_DELAY_TOUT_EVT      (SMP_SELF_DEF_EVT + 13)
+#define SMP_PAIR_PUBLIC_KEY_EVT         SMP_OPCODE_PAIR_PUBLIC_KEY
+#define SMP_PAIR_KEYPRESS_NOTIFICATION_EVT SMP_OPCODE_PAIR_KEYPR_NOTIF
+
+#define SMP_PAIR_COMMITM_EVT            SMP_OPCODE_PAIR_COMMITM
+
+#define SMP_SELF_DEF_EVT                (SMP_PAIR_COMMITM_EVT + 1)
+#define SMP_KEY_READY_EVT               (SMP_SELF_DEF_EVT)
+#define SMP_ENCRYPTED_EVT               (SMP_SELF_DEF_EVT + 1)
+#define SMP_L2CAP_CONN_EVT              (SMP_SELF_DEF_EVT + 2)
+#define SMP_L2CAP_DISCONN_EVT           (SMP_SELF_DEF_EVT + 3)
+#define SMP_IO_RSP_EVT                  (SMP_SELF_DEF_EVT + 4)
+#define SMP_API_SEC_GRANT_EVT           (SMP_SELF_DEF_EVT + 5)
+#define SMP_TK_REQ_EVT                  (SMP_SELF_DEF_EVT + 6)
+#define SMP_AUTH_CMPL_EVT               (SMP_SELF_DEF_EVT + 7)
+#define SMP_ENC_REQ_EVT                 (SMP_SELF_DEF_EVT + 8)
+#define SMP_BOND_REQ_EVT                (SMP_SELF_DEF_EVT + 9)
+#define SMP_DISCARD_SEC_REQ_EVT         (SMP_SELF_DEF_EVT + 10)
+
+#define SMP_PAIR_DHKEY_CHCK_EVT         SMP_OPCODE_PAIR_DHKEY_CHECK
+
+#define SMP_PUBL_KEY_EXCH_REQ_EVT       (SMP_SELF_DEF_EVT + 11) /* request to start public */
+                                                                /* key exchange */
+
+#define SMP_LOC_PUBL_KEY_CRTD_EVT       (SMP_SELF_DEF_EVT + 12) /* local public key created */
+
+#define SMP_BOTH_PUBL_KEYS_RCVD_EVT     (SMP_SELF_DEF_EVT + 13) /* both local and peer public */
+                                                                /* keys are saved in cb */
+
+#define SMP_SC_DHKEY_CMPLT_EVT          (SMP_SELF_DEF_EVT + 14) /* DHKey computation is completed,*/
+                                                                /* time to start SC phase1 */
+
+#define SMP_HAVE_LOC_NONCE_EVT          (SMP_SELF_DEF_EVT + 15) /* new local nonce is generated */
+                                                                /*and saved in p_cb->rand */
+
+#define SMP_SC_PHASE1_CMPLT_EVT         (SMP_SELF_DEF_EVT + 16) /* time to start SC phase2 */
+
+#define SMP_SC_CALC_NC_EVT              (SMP_SELF_DEF_EVT + 17) /* request to calculate number */
+                                                             /* for user check. Used only in the */
+                                                             /* numeric compare protocol */
+
+/* Request to display the number for user check to the user.*/
+/* Used only in the numeric compare protocol */
+#define SMP_SC_DSPL_NC_EVT              (SMP_SELF_DEF_EVT + 18)
+
+#define SMP_SC_NC_OK_EVT                (SMP_SELF_DEF_EVT + 19) /* user confirms 'OK' numeric */
+                                                                /*comparison request */
+
+/* both local and peer DHKey Checks are already present - it is used on slave to prevent race condition */
+#define SMP_SC_2_DHCK_CHKS_PRES_EVT     (SMP_SELF_DEF_EVT + 20)
+
+/* same meaning as SMP_KEY_READY_EVT to separate between SC and legacy actions */
+#define SMP_SC_KEY_READY_EVT            (SMP_SELF_DEF_EVT + 21)
+#define SMP_KEYPRESS_NOTIFICATION_EVENT (SMP_SELF_DEF_EVT + 22)
+
+#define SMP_SC_OOB_DATA_EVT             (SMP_SELF_DEF_EVT + 23) /* SC OOB data from some */
+                                                                /* repository is provided */
+
+#define SMP_CR_LOC_SC_OOB_DATA_EVT      (SMP_SELF_DEF_EVT + 24)
+#define SMP_MAX_EVT                      SMP_CR_LOC_SC_OOB_DATA_EVT
+
 typedef UINT8 tSMP_EVENT;
-#define SMP_MAX_EVT         SMP_RELEASE_DELAY_TOUT_EVT + 1
 
-/* auumption it's only using the low 8 bits, if bigger than that, need to expand it to be 16 bits */
+/* Assumption it's only using the low 8 bits, if bigger than that, need to expand it to 16 bits */
 #define SMP_SEC_KEY_MASK                    0x00ff
 
 /* SMP pairing state */
 enum
 {
-    SMP_ST_IDLE,
-    SMP_ST_WAIT_APP_RSP,
-    SMP_ST_SEC_REQ_PENDING,
-    SMP_ST_PAIR_REQ_RSP,
-    SMP_ST_WAIT_CONFIRM,
-    SMP_ST_CONFIRM,
-    SMP_ST_RAND,
-    SMP_ST_ENC_PENDING,
-    SMP_ST_BOND_PENDING,
-    SMP_ST_RELEASE_DELAY,
-    SMP_ST_MAX
+    SMP_STATE_IDLE,
+    SMP_STATE_WAIT_APP_RSP,
+    SMP_STATE_SEC_REQ_PENDING,
+    SMP_STATE_PAIR_REQ_RSP,
+    SMP_STATE_WAIT_CONFIRM,
+    SMP_STATE_CONFIRM,
+    SMP_STATE_RAND,
+    SMP_STATE_PUBLIC_KEY_EXCH,
+    SMP_STATE_SEC_CONN_PHS1_START,
+    SMP_STATE_WAIT_COMMITMENT,
+    SMP_STATE_WAIT_NONCE,
+    SMP_STATE_SEC_CONN_PHS2_START,
+    SMP_STATE_WAIT_DHK_CHECK,
+    SMP_STATE_DHK_CHECK,
+    SMP_STATE_ENCRYPTION_PENDING,
+    SMP_STATE_BOND_PENDING,
+    SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA,
+    SMP_STATE_MAX
 };
 typedef UINT8 tSMP_STATE;
 
+/* SMP over BR/EDR events */
+#define SMP_BR_PAIRING_REQ_EVT              SMP_OPCODE_PAIRING_REQ
+#define SMP_BR_PAIRING_RSP_EVT              SMP_OPCODE_PAIRING_RSP
+#define SMP_BR_CONFIRM_EVT                  SMP_OPCODE_CONFIRM    /* not expected over BR/EDR */
+#define SMP_BR_RAND_EVT                     SMP_OPCODE_RAND       /* not expected over BR/EDR */
+#define SMP_BR_PAIRING_FAILED_EVT           SMP_OPCODE_PAIRING_FAILED
+#define SMP_BR_ENCRPTION_INFO_EVT           SMP_OPCODE_ENCRYPT_INFO /* not expected over BR/EDR */
+#define SMP_BR_MASTER_ID_EVT                SMP_OPCODE_MASTER_ID    /* not expected over BR/EDR */
+#define SMP_BR_ID_INFO_EVT                  SMP_OPCODE_IDENTITY_INFO
+#define SMP_BR_ID_ADDR_EVT                  SMP_OPCODE_ID_ADDR
+#define SMP_BR_SIGN_INFO_EVT                SMP_OPCODE_SIGN_INFO
+#define SMP_BR_SECURITY_REQ_EVT          SMP_OPCODE_SEC_REQ          /* not expected over BR/EDR */
+#define SMP_BR_PAIR_PUBLIC_KEY_EVT       SMP_OPCODE_PAIR_PUBLIC_KEY  /* not expected over BR/EDR */
+#define SMP_BR_PAIR_DHKEY_CHCK_EVT       SMP_OPCODE_PAIR_DHKEY_CHECK /* not expected over BR/EDR */
+#define SMP_BR_PAIR_KEYPR_NOTIF_EVT      SMP_OPCODE_PAIR_KEYPR_NOTIF /* not expected over BR/EDR */
+#define SMP_BR_SELF_DEF_EVT              SMP_BR_PAIR_KEYPR_NOTIF_EVT
+#define SMP_BR_KEY_READY_EVT                (SMP_BR_SELF_DEF_EVT + 1)
+#define SMP_BR_ENCRYPTED_EVT                (SMP_BR_SELF_DEF_EVT + 2)
+#define SMP_BR_L2CAP_CONN_EVT               (SMP_BR_SELF_DEF_EVT + 3)
+#define SMP_BR_L2CAP_DISCONN_EVT            (SMP_BR_SELF_DEF_EVT + 4)
+#define SMP_BR_KEYS_RSP_EVT                 (SMP_BR_SELF_DEF_EVT + 5)
+#define SMP_BR_API_SEC_GRANT_EVT            (SMP_BR_SELF_DEF_EVT + 6)
+#define SMP_BR_TK_REQ_EVT                   (SMP_BR_SELF_DEF_EVT + 7)
+#define SMP_BR_AUTH_CMPL_EVT                (SMP_BR_SELF_DEF_EVT + 8)
+#define SMP_BR_ENC_REQ_EVT                  (SMP_BR_SELF_DEF_EVT + 9)
+#define SMP_BR_BOND_REQ_EVT                 (SMP_BR_SELF_DEF_EVT + 10)
+#define SMP_BR_DISCARD_SEC_REQ_EVT          (SMP_BR_SELF_DEF_EVT + 11)
+#define SMP_BR_MAX_EVT                      (SMP_BR_SELF_DEF_EVT + 12)
+typedef UINT8 tSMP_BR_EVENT;
+
+/* SMP over BR/EDR pairing states */
+enum
+{
+    SMP_BR_STATE_IDLE = SMP_STATE_IDLE,
+    SMP_BR_STATE_WAIT_APP_RSP,
+    SMP_BR_STATE_PAIR_REQ_RSP,
+    SMP_BR_STATE_BOND_PENDING,
+    SMP_BR_STATE_MAX
+};
+typedef UINT8 tSMP_BR_STATE;
+
 /* random and encrption activity state */
 enum
 {
@@ -117,7 +206,13 @@ enum
     SMP_GEN_RAND_V,
     SMP_GEN_TK,
     SMP_GEN_SRAND_MRAND,
-    SMP_GEN_SRAND_MRAND_CONT
+    SMP_GEN_SRAND_MRAND_CONT,
+    SMP_GENERATE_PRIVATE_KEY_0_7,
+    SMP_GENERATE_PRIVATE_KEY_8_15,
+    SMP_GENERATE_PRIVATE_KEY_16_23,
+    SMP_GENERATE_PRIVATE_KEY_24_31,
+    SMP_GEN_NONCE_0_7,
+    SMP_GEN_NONCE_8_15
 };
 
 enum
@@ -125,6 +220,7 @@ enum
     SMP_KEY_TYPE_TK,
     SMP_KEY_TYPE_CFM,
     SMP_KEY_TYPE_CMP,
+    SMP_KEY_TYPE_PEER_DHK_CHCK,
     SMP_KEY_TYPE_STK,
     SMP_KEY_TYPE_LTK
 };
@@ -139,6 +235,8 @@ typedef union
     UINT8       *p_data;    /* UINT8 type data pointer */
     tSMP_KEY    key;
     UINT16      reason;
+    UINT32      passkey;
+    tSMP_OOB_DATA_TYPE  req_oob_type;
 }tSMP_INT_DATA;
 
 /* internal status mask */
@@ -146,6 +244,10 @@ typedef union
 #define SMP_PAIR_FLAGS_PEER_STARTED_DD         (1 << 1)
 #define SMP_PAIR_FLAGS_CMD_CONFIRM             (1 << SMP_OPCODE_CONFIRM) /* 1 << 3 */
 #define SMP_PAIR_FLAG_ENC_AFTER_PAIR           (1 << 4)
+#define SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK   (1 << 5) /* used on slave to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_PEER_PUBL_KEY  (1 << 6) /* used on slave to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_PEER_COMM      (1 << 7) /* used to resolve race condition */
+#define SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY (1 << 8) /* used on slave to resolve race condition */
 
 /* check if authentication requirement need MITM protection */
 #define SMP_NO_MITM_REQUIRED(x)  (((x) & SMP_AUTH_YN_BIT) == 0)
@@ -154,40 +256,66 @@ typedef union
 #define SMP_ENCRYT_DATA_SIZE               16
 #define SMP_ECNCRPYT_STATUS                HCI_SUCCESS
 
+typedef struct
+{
+    BD_ADDR bd_addr;
+    BT_HDR* p_copy;
+} tSMP_REQ_Q_ENTRY;
+
 /* SMP control block */
 typedef struct
 {
     tSMP_CALLBACK   *p_callback;
     TIMER_LIST_ENT  rsp_timer_ent;
     UINT8           trace_level;
-
     BD_ADDR         pairing_bda;
-
     tSMP_STATE      state;
+    BOOLEAN         smp_over_br;
+    tSMP_BR_STATE   br_state;           /* if SMP over BR/ERD has priority over SMP */
     UINT8           failure;
     UINT8           status;
     UINT8           role;
-    UINT          flags;
+    UINT16          flags;
     UINT8           cb_evt;
-
     tSMP_SEC_LEVEL  sec_level;
     BOOLEAN         connect_initialized;
     BT_OCTET16      confirm;
     BT_OCTET16      rconfirm;
-    BT_OCTET16      rrand;
-    BT_OCTET16      rand;
+    BT_OCTET16      rrand;                      /* for SC this is peer nonce */
+    BT_OCTET16      rand;                       /* for SC this is local nonce */
+    BT_OCTET32      private_key;
+    BT_OCTET32      dhkey;
+    BT_OCTET16      commitment;
+    BT_OCTET16      remote_commitment;
+    BT_OCTET16      local_random;               /* local randomizer - passkey or OOB randomizer */
+    BT_OCTET16      peer_random;                /* peer randomizer - passkey or OOB randomizer */
+    BT_OCTET16      dhkey_check;
+    BT_OCTET16      remote_dhkey_check;
+    tSMP_PUBLIC_KEY loc_publ_key;
+    tSMP_PUBLIC_KEY peer_publ_key;
+    tSMP_OOB_DATA_TYPE  req_oob_type;
+    tSMP_SC_OOB_DATA    sc_oob_data;
     tSMP_IO_CAP     peer_io_caps;
-    tSMP_IO_CAP     loc_io_caps;
+    tSMP_IO_CAP     local_io_capability;
     tSMP_OOB_FLAG   peer_oob_flag;
     tSMP_OOB_FLAG   loc_oob_flag;
     tSMP_AUTH_REQ   peer_auth_req;
     tSMP_AUTH_REQ   loc_auth_req;
+    BOOLEAN         secure_connections_only_mode_required;/* TRUE if locally SM is required to operate */
+                                            /* either in Secure Connections mode or not at all */
+    tSMP_ASSO_MODEL selected_association_model;
+    BOOLEAN         le_secure_connections_mode_is_used;
+    tBTM_SP_KEY_TYPE  local_keypress_notification;
+    tBTM_SP_KEY_TYPE  peer_keypress_notification;
+    UINT8           round;       /* authentication stage 1 round for passkey association model */
+    UINT32          number_to_display;
+    BT_OCTET16      mac_key;
     UINT8           peer_enc_size;
     UINT8           loc_enc_size;
     UINT8           peer_i_key;
     UINT8           peer_r_key;
-    UINT8           loc_i_key;
-    UINT8           loc_r_key;
+    UINT8           local_i_key;
+    UINT8           local_r_key;
 
     BT_OCTET16      tk;
     BT_OCTET16      ltk;
@@ -195,26 +323,15 @@ typedef struct
     BT_OCTET16      csrk;  /* storage for local CSRK */
     UINT16          ediv;
     BT_OCTET8       enc_rand;
-
-    UINT8           rand_enc_proc;
-    BOOLEAN         last_cmd;
+    UINT8           rand_enc_proc_state;
     UINT8           addr_type;
     BD_ADDR         local_bda;
     BOOLEAN         is_pair_cancel;
     BOOLEAN         discard_sec_req;
     UINT8           rcvd_cmd_code;
     UINT8           rcvd_cmd_len;
-#if SMP_CONFORMANCE_TESTING == TRUE
-    BOOLEAN         enable_test_confirm_val;
-    BT_OCTET16      test_confirm;
-    BOOLEAN         enable_test_rand_val;
-    BT_OCTET16      test_rand;
-    BOOLEAN         enable_test_pair_fail;
-    UINT8           pair_fail_status;
-    BOOLEAN         remove_fixed_channel_disable;
-    BOOLEAN         skip_test_compare_check;
-#endif
-
+    UINT16          total_tx_unacked;
+    BOOLEAN         wait_for_authorization_complete;
 }tSMP_CB;
 
 /* Server Action functions are of this type */
@@ -240,26 +357,53 @@ extern tSMP_CB *smp_cb_ptr;
 /* Functions provided by att_main.c */
 extern void smp_init (void);
 
-#if SMP_CONFORMANCE_TESTING == TRUE
-/* Used only for conformance testing */
-extern void  smp_set_test_confirm_value (BOOLEAN enable, UINT8 *p_c_value);
-extern void  smp_set_test_rand_value (BOOLEAN enable, UINT8 *p_c_value);
-extern void  smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status);
-extern void  smp_remove_fixed_channel_disable (BOOLEAN disable);
-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);
 
 extern void smp_proc_sec_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void  smp_set_fail_nc (BOOLEAN enable);
+extern void  smp_set_fail_conf (BOOLEAN enable);
+extern void  smp_set_passk_entry_fail(BOOLEAN enable);
+extern void  smp_set_oob_fail(BOOLEAN enable);
+extern void  smp_set_peer_sc_notif(BOOLEAN enable);
+extern void smp_aes_cmac_rfc4493_chk (UINT8 *key, UINT8 *msg, UINT8 msg_len,
+                                              UINT8 mac_len, UINT8 *mac);
+extern void smp_f4_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Z, UINT8 *mac);
+extern void smp_g2_calc_chk (UINT8 *U, UINT8 *V, UINT8 *X, UINT8 *Y);
+extern void smp_h6_calc_chk (UINT8 *key, UINT8 *key_id, UINT8 *mac);
+extern void smp_f5_key_calc_chk (UINT8 *w, UINT8 *mac);
+extern void smp_f5_mackey_or_ltk_calc_chk(UINT8 *t, UINT8 *counter,
+                                                  UINT8 *key_id, UINT8 *n1,
+                                                  UINT8 *n2, UINT8 *a1, UINT8 *a2,
+                                                  UINT8 *length, UINT8 *mac);
+extern void smp_f5_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+                                    UINT8 *mac_key, UINT8 *ltk);
+extern void smp_f6_calc_chk (UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r,
+                                     UINT8 *iocap, UINT8 *a1, UINT8 *a2, UINT8 *mac);
+/* smp_main */
+extern void         smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data);
+extern tSMP_STATE   smp_get_state(void);
+extern void         smp_set_state(tSMP_STATE state);
+
+/* smp_br_main */
+extern void smp_br_state_machine_event(tSMP_CB *p_cb, tSMP_BR_EVENT event, void *p_data);
+extern tSMP_BR_STATE    smp_get_br_state(void);
+extern void             smp_set_br_state(tSMP_BR_STATE state);
+
+
+/* smp_act.c */
 extern void smp_send_pair_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_send_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_sec_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_pair_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_send_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_pair_fail(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_init(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_proc_rand(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_pairing_public_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_master_id(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -270,14 +414,12 @@ extern void smp_proc_sl_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_start_enc(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_enc_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_discard(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_release_delay(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_release_delay_tout(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_pairing_cmpl(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_decide_asso_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_decide_association_model(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_app_cback(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_compare(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_check_auth_req(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_proc_io_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_io_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_id_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_enc_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_send_csrk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
@@ -289,13 +431,40 @@ extern void smp_send_pair_rsp(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_key_distribution(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_proc_srk_info(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_delay_terminate(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_fast_conn_param(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_key_pick_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_both_have_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_secure_connection_phase1(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_local_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_pairing_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_peer_nonce(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_match_dhkey_checks(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_keypress_notification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_move_to_secure_connections_phase2(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_phase_2_dhkey_checks_are_present(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_wait_for_both_public_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_passkey_verification(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_secure_connection_oob_data(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_process_secure_connection_long_term_key(void);
+extern void smp_derive_link_key_from_long_term_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_local_oob_keys(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_set_local_oob_random_commitment(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_pairing_command(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_security_grant(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_slave_keys_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_send_pair_response(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_check_authorization_request(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_select_next_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_process_link_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_key_distribution_by_transport(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_br_pairing_complete(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 
 /* smp_l2c */
 extern void smp_l2cap_if_init (void);
+extern void smp_data_ind (BD_ADDR bd_addr, BT_HDR *p_buf);
 
-/* smp utility */
+/* smp_util.c */
 extern BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
 extern void smp_cb_cleanup(tSMP_CB *p_cb);
 extern void smp_reset_control_value(tSMP_CB *p_cb);
@@ -307,17 +476,58 @@ extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b);
 extern BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
                                  UINT8 *plain_text, UINT8 pt_len,
                                  tSMP_ENC *p_out);
-/* smp key */
-extern void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb);
+extern void smp_reject_unexpected_pairing_command(BD_ADDR bd_addr);
+extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB *p_cb);
+extern void smp_reverse_array(UINT8 *arr, UINT8 len);
+extern UINT8 smp_calculate_random_input(UINT8 *random, UINT8 round);
+extern void smp_collect_local_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
+extern void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb);
+extern void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
+extern void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb);
+extern BOOLEAN smp_check_commitment(tSMP_CB *p_cb);
+extern void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb);
+extern void smp_remove_fixed_channel(tSMP_CB *p_cb);
+extern BOOLEAN smp_request_oob_data(tSMP_CB *p_cb);
+
+/* smp_keys.c */
+extern void smp_generate_srand_mrand_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_compare (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 extern void smp_generate_passkey (tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-extern void smp_genenrate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_compute_dhkey(tSMP_CB *p_cb);
+extern void smp_calculate_local_commitment(tSMP_CB *p_cb);
+extern void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf);
+extern void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+extern void smp_start_nonce_generation(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb);
+extern BOOLEAN smp_calculate_long_term_key_from_link_key(tSMP_CB *p_cb);
+extern void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c);
+extern UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y);
+extern BOOLEAN smp_calculate_f5(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+                           UINT8 *mac_key, UINT8 *ltk);
+extern BOOLEAN smp_calculate_f5_mackey_or_long_term_key(UINT8 *t, UINT8 *counter,
+                                         UINT8 *key_id, UINT8 *n1, UINT8 *n2, UINT8 *a1,
+                                         UINT8 *a2, UINT8 *length, UINT8 *mac);
+extern BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t);
+extern BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap,
+                               UINT8 *a1, UINT8 *a2, UINT8 *f3);
+extern BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *h2);
+#if SMP_DEBUG == TRUE
+extern void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name,
+                                                 UINT8 len);
+#endif
 
-/* smp main util */
-extern void smp_set_state(tSMP_STATE state);
-extern tSMP_STATE smp_get_state(void);
-extern void smp_reject_unexp_pair_req(BD_ADDR bd_addr);
+/* smp_cmac.c */
+extern BOOLEAN aes_cipher_msg_auth_code(BT_OCTET16 key, UINT8 *input, UINT16 length,
+                                                 UINT16 tlen, UINT8 *p_signature);
+extern void print128(BT_OCTET16 x, const UINT8 *key_name);
 
 #endif /* SMP_INT_H */
index 31313c9..47d0125 100644 (file)
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- *  Copyright (C) 2008-2012 Broadcom Corporation
+ *  Copyright (C) 1999-2012 Broadcom Corporation
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 
 /******************************************************************************
  *
- *  This file contains the implementation of the SMP utility functions used
- *  by SMP.
+ *  This file contains security manager protocol utility functions
  *
  ******************************************************************************/
-
 #include "bt_target.h"
-#include "bt_utils.h"
 
 #if SMP_INCLUDED == TRUE
-    #if SMP_DEBUG == TRUE
-        #include <stdio.h>
-    #endif
-    #include <string.h>
-
-    #include "btm_ble_api.h"
-    #include "smp_int.h"
-    #include "btm_int.h"
-    #include "btm_ble_int.h"
-    #include "hcimsgs.h"
-    #include "aes.h"
-    #ifndef SMP_MAX_ENC_REPEAT
-        #define SMP_MAX_ENC_REPEAT      3
-    #endif
+#if SMP_DEBUG == TRUE
+    #include <stdio.h>
+#endif
+#include <string.h>
+#include "bt_utils.h"
+#include "btm_ble_api.h"
+#include "smp_int.h"
+#include "btm_int.h"
+#include "btm_ble_int.h"
+#include "hcimsgs.h"
+#include "aes.h"
+#include "p_256_ecc_pp.h"
+#include "device/include/controller.h"
+
+#ifndef SMP_MAX_ENC_REPEAT
+  #define SMP_MAX_ENC_REPEAT  3
+#endif
 
 static void smp_rand_back(tBTM_RAND_ENC *p);
-static void smp_genenrate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
-static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+static void smp_generate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
+static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data);
 static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p);
 static void smp_generate_rand_vector (tSMP_CB *p_cb, tSMP_INT_DATA *p);
 static void smp_process_stk(tSMP_CB *p_cb, tSMP_ENC *p);
@@ -52,46 +52,84 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p);
 static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p);
 static void smp_process_compare(tSMP_CB *p_cb, tSMP_ENC *p);
 static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p);
+static BOOLEAN smp_calculate_legacy_short_term_key(tSMP_CB *p_cb, tSMP_ENC *output);
+static void smp_continue_private_key_creation(tSMP_CB *p_cb, tBTM_RAND_ENC *p);
+static void smp_process_private_key(tSMP_CB *p_cb);
+static void smp_finish_nonce_generation(tSMP_CB *p_cb);
+static void smp_process_new_nonce(tSMP_CB *p_cb);
 
 static const tSMP_ACT smp_encrypt_action[] =
 {
     smp_generate_compare,           /* SMP_GEN_COMPARE */
-    smp_genenrate_confirm,          /* SMP_GEN_CONFIRM*/
+    smp_generate_confirm,          /* SMP_GEN_CONFIRM*/
     smp_generate_stk,               /* SMP_GEN_STK*/
-    smp_genenrate_ltk_cont,          /* SMP_GEN_LTK */
+    smp_generate_ltk_cont,          /* SMP_GEN_LTK */
     smp_generate_ltk,               /* SMP_GEN_DIV_LTK */
     smp_generate_rand_vector,        /* SMP_GEN_RAND_V */
     smp_generate_y,                  /* SMP_GEN_EDIV */
     smp_generate_passkey,           /* SMP_GEN_TK */
-    smp_generate_confirm,           /* SMP_GEN_SRAND_MRAND */
-    smp_genenrate_rand_cont         /* SMP_GEN_SRAND_MRAND_CONT */
+    smp_generate_srand_mrand_confirm, /* SMP_GEN_SRAND_MRAND */
+    smp_generate_rand_cont         /* SMP_GEN_SRAND_MRAND_CONT */
 };
 
+#define SMP_PASSKEY_MASK    0xfff00000
+
+void smp_debug_print_nbyte_little_endian(UINT8 *p, const UINT8 *key_name, UINT8 len)
+{
+#if SMP_DEBUG == TRUE
+    int     ind, x;
+    int     col_count = 32;
+    int     row_count;
+    UINT8   p_buf[512];
+
+    SMP_TRACE_WARNING("%s(LSB ~ MSB):", key_name);
+    memset(p_buf, 0, sizeof(p_buf));
+    row_count = len % col_count ? len / col_count + 1: len / col_count;
 
-    #define SMP_PASSKEY_MASK    0xfff00000
+    ind = 0;
+    for (int row = 0; row <  row_count; row++)
+    {
+        for (int column = 0, x = 0; (ind < len) && (column < col_count); column++, ind++)
+        {
+            x += sprintf((char *)&p_buf[x], "%02x ", p[ind]);
+        }
+        SMP_TRACE_WARNING("  [%03d]: %s", row * col_count, p_buf);
+    }
+#endif
+}
 
-    #if SMP_DEBUG == TRUE
-static void smp_debug_print_nbyte_little_endian (UINT8 *p, const UINT8 *key_name, UINT8 len)
+void smp_debug_print_nbyte_big_endian (UINT8 *p, const UINT8 *key_name, UINT8 len)
 {
-    int     i, x = 0;
-    UINT8   p_buf[100];
-    memset(p_buf, 0, 100);
+#if SMP_DEBUG == TRUE
+    UINT8  p_buf[512];
+
+    SMP_TRACE_WARNING("%s(MSB ~ LSB):", key_name);
+    memset(p_buf, 0, sizeof(p_buf));
+    nrows = len % ncols ? len / ncols + 1: len / ncols;
 
-    for (i = 0; i < len; i ++)
+    int ind = 0;
+    int  ncols = 32; /* num entries in one line */
+    int  nrows;      /* num lines */
+    int  x;
+
+    for (int row = 0; row <  nrows; row++)
     {
-        x += sprintf ((char *)&p_buf[x], "%02x ", p[i]);
+        for (int col = 0, x = 0; (ind < len) && (col < ncols); col++, ind++)
+        {
+            x += sprintf ((char *)&p_buf[len-x-1], "%02x ", p[ind]);
+        }
+        SMP_TRACE_WARNING("[%03d]: %s", row * ncols, p_buf);
     }
-    SMP_TRACE_DEBUG("%s(LSB ~ MSB) = %s", key_name, p_buf);
+#endif
 }
-    #else
-        #define smp_debug_print_nbyte_little_endian(p, key_name, len)
-    #endif
 
 /*******************************************************************************
 **
 ** Function         smp_encrypt_data
 **
-** Description      This function is called to generate passkey.
+** Description      This function is called to encrypt data.
+**                  It uses AES-128 encryption algorithm.
+**                  Plain_text is encrypted using key, the result is at p_out.
 **
 ** Returns          void
 **
@@ -100,24 +138,24 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
                           UINT8 *plain_text, UINT8 pt_len,
                           tSMP_ENC *p_out)
 {
-    aes_context     ctx;
-    UINT8           *p_start = NULL;
-    UINT8           *p = NULL;
-    UINT8           *p_rev_data = NULL;    /* input data in big endilan format */
-    UINT8           *p_rev_key = NULL;     /* input key in big endilan format */
-    UINT8           *p_rev_output = NULL;  /* encrypted output in big endilan format */
-
-    SMP_TRACE_DEBUG ("smp_encrypt_data");
+    aes_context ctx;
+    UINT8 *p_start = NULL;
+    UINT8 *p = NULL;
+    UINT8 *p_rev_data = NULL;    /* input data in big endilan format */
+    UINT8 *p_rev_key = NULL;     /* input key in big endilan format */
+    UINT8 *p_rev_output = NULL;  /* encrypted output in big endilan format */
+
+    SMP_TRACE_DEBUG ("%s", __func__);
     if ( (p_out == NULL ) || (key_len != SMP_ENCRYT_KEY_SIZE) )
     {
-        BTM_TRACE_ERROR ("smp_encrypt_data Failed");
-        return(FALSE);
+        SMP_TRACE_ERROR ("%s failed", __func__);
+        return FALSE;
     }
 
     if ((p_start = (UINT8 *)GKI_getbuf((SMP_ENCRYT_DATA_SIZE*4))) == NULL)
     {
-        BTM_TRACE_ERROR ("smp_encrypt_data Failed unable to allocate buffer");
-        return(FALSE);
+        SMP_TRACE_ERROR ("%s failed unable to allocate buffer", __func__);
+        return FALSE;
     }
 
     if (pt_len > SMP_ENCRYT_DATA_SIZE)
@@ -131,15 +169,19 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
     p_rev_key = p; /* start at byte 32 */
     REVERSE_ARRAY_TO_STREAM (p, key, SMP_ENCRYT_KEY_SIZE); /* byte 32 to byte 47 */
 
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
     smp_debug_print_nbyte_little_endian(key, (const UINT8 *)"Key", SMP_ENCRYT_KEY_SIZE);
     smp_debug_print_nbyte_little_endian(p_start, (const UINT8 *)"Plain text", SMP_ENCRYT_DATA_SIZE);
+#endif
     p_rev_output = p;
     aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
     aes_encrypt(p_rev_data, p, &ctx);  /* outputs in byte 48 to byte 63 */
 
     p = p_out->param_buf;
     REVERSE_ARRAY_TO_STREAM (p, p_rev_output, SMP_ENCRYT_DATA_SIZE);
+#if SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE
     smp_debug_print_nbyte_little_endian(p_out->param_buf, (const UINT8 *)"Encrypted text", SMP_ENCRYT_KEY_SIZE);
+#endif
 
     p_out->param_len = SMP_ENCRYT_KEY_SIZE;
     p_out->status = HCI_SUCCESS;
@@ -147,10 +189,9 @@ BOOLEAN smp_encrypt_data (UINT8 *key, UINT8 key_len,
 
     GKI_freebuf(p_start);
 
-    return(TRUE);
+    return TRUE;
 }
 
-
 /*******************************************************************************
 **
 ** Function         smp_generate_passkey
@@ -164,13 +205,14 @@ void smp_generate_passkey(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_generate_passkey");
-    p_cb->rand_enc_proc = SMP_GEN_TK;
+    SMP_TRACE_DEBUG ("%s", __func__);
+    p_cb->rand_enc_proc_state = SMP_GEN_TK;
 
     /* generate MRand or SRand */
     if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
         smp_rand_back(NULL);
 }
+
 /*******************************************************************************
 **
 ** Function         smp_proc_passkey
@@ -187,7 +229,7 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p)
     UINT32  passkey; /* 19655 test number; */
     UINT8 *pp = p->param_buf;
 
-    SMP_TRACE_DEBUG ("smp_proc_passkey ");
+    SMP_TRACE_DEBUG ("%s", __func__);
     STREAM_TO_UINT32(passkey, pp);
     passkey &= ~SMP_PASSKEY_MASK;
 
@@ -207,10 +249,16 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p)
         (*p_cb->p_callback)(SMP_PASSKEY_NOTIF_EVT, p_cb->pairing_bda, (tSMP_EVT_DATA *)&passkey);
     }
 
-    smp_sm_event(p_cb, SMP_KEY_READY_EVT, (tSMP_INT_DATA *)&key);
+    if (p_cb->selected_association_model == SMP_MODEL_SEC_CONN_PASSKEY_DISP)
+    {
+        smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &passkey);
+    }
+    else
+    {
+        smp_sm_event(p_cb, SMP_KEY_READY_EVT, (tSMP_INT_DATA *)&key);
+    }
 }
 
-
 /*******************************************************************************
 **
 ** Function         smp_generate_stk
@@ -222,64 +270,58 @@ void smp_proc_passkey(tSMP_CB *p_cb , tBTM_RAND_ENC *p)
 ** Returns          void
 **
 *******************************************************************************/
-void smp_generate_stk (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_stk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    BT_OCTET16      ptext;
-    UINT8           *p = ptext;
-    tSMP_ENC        output;
-    tSMP_STATUS     status = SMP_PAIR_FAIL_UNKNOWN;
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_generate_stk ");
+    tSMP_ENC output;
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
 
-    memset(p, 0, BT_OCTET16_LEN);
-    if (p_cb->role == HCI_ROLE_MASTER)
-    {
-        memcpy(p, p_cb->rand, BT_OCTET8_LEN);
-        memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN);
-    }
-    else
-    {
-        memcpy(p, p_cb->rrand, BT_OCTET8_LEN);
-        memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
-    }
+    SMP_TRACE_DEBUG ("%s", __func__);
 
-    /* generate STK = Etk(rand|rrand)*/
-    if (!SMP_Encrypt( p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, &output))
+    if (p_cb->le_secure_connections_mode_is_used)
     {
-        SMP_TRACE_ERROR("smp_generate_stk failed");
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        SMP_TRACE_WARNING ("FOR LE SC LTK IS USED INSTEAD OF STK");
+        output.param_len = SMP_ENCRYT_KEY_SIZE;
+        output.status = HCI_SUCCESS;
+        output.opcode =  HCI_BLE_ENCRYPT;
+        memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE);
     }
-    else
+    else if (!smp_calculate_legacy_short_term_key(p_cb, &output))
     {
-        smp_process_stk(p_cb, &output);
+        SMP_TRACE_ERROR("%s failed", __func__);
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        return;
     }
 
+    smp_process_stk(p_cb, &output);
 }
+
 /*******************************************************************************
 **
-** Function         smp_generate_confirm
+** Function         smp_generate_srand_mrand_confirm
 **
 ** Description      This function is called to start the second pairing phase by
-**                  start generating initializer random number.
+**                  start generating random number.
 **
 **
 ** Returns          void
 **
 *******************************************************************************/
-void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_srand_mrand_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_generate_confirm");
-    p_cb->rand_enc_proc = SMP_GEN_SRAND_MRAND;
+    SMP_TRACE_DEBUG ("%s", __func__);
+    p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND;
     /* generate MRand or SRand */
     if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
         smp_rand_back(NULL);
 }
+
 /*******************************************************************************
 **
-** Function         smp_genenrate_rand_cont
+** Function         smp_generate_rand_cont
 **
 ** Description      This function is called to generate another 64 bits random for
 **                  MRand or Srand.
@@ -287,52 +329,65 @@ void smp_generate_confirm (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 ** Returns          void
 **
 *******************************************************************************/
-void smp_genenrate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+void smp_generate_rand_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_genenrate_rand_cont ");
-    p_cb->rand_enc_proc = SMP_GEN_SRAND_MRAND_CONT;
+    SMP_TRACE_DEBUG ("%s", __func__);
+    p_cb->rand_enc_proc_state = SMP_GEN_SRAND_MRAND_CONT;
     /* generate 64 MSB of MRand or SRand */
-
     if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
         smp_rand_back(NULL);
 }
+
 /*******************************************************************************
 **
 ** Function         smp_generate_ltk
 **
-** Description      This function is called to calculate LTK, starting with DIV
-**                  generation.
-**
+** Description      This function is called:
+**                  - in legacy pairing - to calculate LTK, starting with DIV
+**                    generation;
+**                  - in LE Secure Connections pairing over LE transport - to process LTK
+**                    already generated to encrypt LE link;
+**                  - in LE Secure Connections pairing over BR/EDR transport - to start
+**                    BR/EDR Link Key processing.
 **
 ** Returns          void
 **
 *******************************************************************************/
 void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    BOOLEAN     div_status;
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_generate_ltk ");
+    BOOLEAN div_status;
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+    if (smp_get_br_state() == SMP_BR_STATE_BOND_PENDING)
+    {
+        smp_br_process_link_key(p_cb, NULL);
+        return;
+    }
+    else if (p_cb->le_secure_connections_mode_is_used)
+    {
+        smp_process_secure_connection_long_term_key();
+        return;
+    }
 
     div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
 
     if (div_status)
     {
-        smp_genenrate_ltk_cont(p_cb, NULL);
+        smp_generate_ltk_cont(p_cb, NULL);
     }
     else
     {
         SMP_TRACE_DEBUG ("Generate DIV for LTK");
-        p_cb->rand_enc_proc = SMP_GEN_DIV_LTK;
+        p_cb->rand_enc_proc_state = SMP_GEN_DIV_LTK;
         /* generate MRand or SRand */
         if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
             smp_rand_back(NULL);
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         smp_compute_csrk
@@ -345,13 +400,14 @@ void smp_generate_ltk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
+    UNUSED(p_data);
+
     BT_OCTET16  er;
     UINT8       buffer[4]; /* for (r || DIV)  r=1*/
     UINT16      r=1;
     UINT8       *p=buffer;
     tSMP_ENC    output;
     tSMP_STATUS   status = SMP_PAIR_FAIL_UNKNOWN;
-    UNUSED(p_data);
 
     SMP_TRACE_DEBUG ("smp_compute_csrk div=%x", p_cb->div);
     BTM_GetDeviceEncRoot(er);
@@ -362,7 +418,14 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output))
     {
         SMP_TRACE_ERROR("smp_generate_csrk failed");
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        if (p_cb->smp_over_br)
+        {
+            smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &status);
+        }
+        else
+        {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+        }
     }
     else
     {
@@ -375,7 +438,7 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 **
 ** Function         smp_generate_csrk
 **
-** Description      This function is called to calculate LTK, starting with DIV
+** Description      This function is called to calculate CSRK, starting with DIV
 **                  generation.
 **
 **
@@ -384,9 +447,10 @@ void smp_compute_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    BOOLEAN     div_status;
     UNUSED(p_data);
 
+    BOOLEAN     div_status;
+
     SMP_TRACE_DEBUG ("smp_generate_csrk");
 
     div_status = btm_get_local_div(p_cb->pairing_bda, &p_cb->div);
@@ -397,13 +461,12 @@ void smp_generate_csrk(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     else
     {
         SMP_TRACE_DEBUG ("Generate DIV for CSRK");
-        p_cb->rand_enc_proc = SMP_GEN_DIV_CSRK;
+        p_cb->rand_enc_proc_state = SMP_GEN_DIV_CSRK;
         if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
             smp_rand_back(NULL);
     }
 }
 
-
 /*******************************************************************************
 ** Function         smp_concatenate_peer
 **                  add pairing command sent from local device into p1.
@@ -412,17 +475,18 @@ void smp_concatenate_local( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code)
 {
     UINT8   *p = *p_data;
 
-    SMP_TRACE_DEBUG ("smp_concatenate_local ");
+    SMP_TRACE_DEBUG ("%s", __func__);
     UINT8_TO_STREAM(p, op_code);
-    UINT8_TO_STREAM(p, p_cb->loc_io_caps);
+    UINT8_TO_STREAM(p, p_cb->local_io_capability);
     UINT8_TO_STREAM(p, p_cb->loc_oob_flag);
     UINT8_TO_STREAM(p, p_cb->loc_auth_req);
     UINT8_TO_STREAM(p, p_cb->loc_enc_size);
-    UINT8_TO_STREAM(p, p_cb->loc_i_key);
-    UINT8_TO_STREAM(p, p_cb->loc_r_key);
+    UINT8_TO_STREAM(p, p_cb->local_i_key);
+    UINT8_TO_STREAM(p, p_cb->local_r_key);
 
     *p_data = p;
 }
+
 /*******************************************************************************
 ** Function         smp_concatenate_peer
 **                  add pairing command received from peer device into p1.
@@ -442,6 +506,7 @@ void smp_concatenate_peer( tSMP_CB *p_cb, UINT8 **p_data, UINT8 op_code)
 
     *p_data = p;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_gen_p1_4_confirm
@@ -495,6 +560,7 @@ void smp_gen_p1_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p1)
     smp_debug_print_nbyte_little_endian ((UINT8 *)p1, (const UINT8 *)"P1", 16);
 #endif
 }
+
 /*******************************************************************************
 **
 ** Function         smp_gen_p2_4_confirm
@@ -540,6 +606,7 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
     smp_debug_print_nbyte_little_endian(p2, (const UINT8 *)"p2", 16);
 #endif
 }
+
 /*******************************************************************************
 **
 ** Function         smp_calculate_comfirm
@@ -551,10 +618,11 @@ void smp_gen_p2_4_confirm( tSMP_CB *p_cb, BT_OCTET16 p2)
 *******************************************************************************/
 void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda)
 {
+    UNUSED(bda);
+
     BT_OCTET16      p1;
     tSMP_ENC       output;
     tSMP_STATUS     status = SMP_PAIR_FAIL_UNKNOWN;
-    UNUSED(bda);
 
     SMP_TRACE_DEBUG ("smp_calculate_comfirm ");
     /* generate p1 = pres || preq || rat' || iat' */
@@ -576,6 +644,7 @@ void smp_calculate_comfirm (tSMP_CB *p_cb, BT_OCTET16 rand, BD_ADDR bda)
         smp_calculate_comfirm_cont(p_cb, &output);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         smp_calculate_comfirm_cont
@@ -612,7 +681,7 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p)
     }
     else
     {
-        switch (p_cb->rand_enc_proc)
+        switch (p_cb->rand_enc_proc_state)
         {
             case SMP_GEN_CONFIRM:
                 smp_process_confirm(p_cb, &output);
@@ -624,9 +693,10 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p)
         }
     }
 }
+
 /*******************************************************************************
 **
-** Function         smp_genenrate_confirm
+** Function         smp_generate_confirm
 **
 ** Description      This function is called when a 48 bits random number is generated
 **                  as SRand or MRand, continue to calculate Sconfirm or MConfirm.
@@ -634,17 +704,16 @@ static void smp_calculate_comfirm_cont(tSMP_CB *p_cb, tSMP_ENC *p)
 ** Returns          void
 **
 *******************************************************************************/
-static void smp_genenrate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+static void smp_generate_confirm(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
     UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_genenrate_confirm ");
-    p_cb->rand_enc_proc = SMP_GEN_CONFIRM;
-
+    SMP_TRACE_DEBUG ("%s", __func__);
+    p_cb->rand_enc_proc_state = SMP_GEN_CONFIRM;
     smp_debug_print_nbyte_little_endian ((UINT8 *)p_cb->rand,  (const UINT8 *)"local rand", 16);
-
     smp_calculate_comfirm(p_cb, p_cb->rand, p_cb->pairing_bda);
 }
+
 /*******************************************************************************
 **
 ** Function         smp_generate_compare
@@ -661,12 +730,11 @@ void smp_generate_compare (tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
     UNUSED(p_data);
 
     SMP_TRACE_DEBUG ("smp_generate_compare ");
-    p_cb->rand_enc_proc = SMP_GEN_COMPARE;
-
+    p_cb->rand_enc_proc_state = SMP_GEN_COMPARE;
     smp_debug_print_nbyte_little_endian ((UINT8 *)p_cb->rrand,  (const UINT8 *)"peer rand", 16);
-
     smp_calculate_comfirm(p_cb, p_cb->rrand, p_cb->local_bda);
 }
+
 /*******************************************************************************
 **
 ** Function         smp_process_confirm
@@ -681,19 +749,8 @@ static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p)
 {
     tSMP_KEY    key;
 
-    SMP_TRACE_DEBUG ("smp_process_confirm ");
-#if SMP_CONFORMANCE_TESTING == TRUE
-    if (p_cb->enable_test_confirm_val)
-    {
-        BTM_TRACE_DEBUG ("Use confirm value from script");
-        memcpy(p_cb->confirm, p_cb->test_confirm, BT_OCTET16_LEN);
-    }
-    else
-        memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN);
-#else
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
     memcpy(p_cb->confirm, p->param_buf, BT_OCTET16_LEN);
-#endif
-
 
 #if (SMP_DEBUG == TRUE)
     SMP_TRACE_DEBUG("Confirm  Generated");
@@ -702,9 +759,9 @@ static void smp_process_confirm(tSMP_CB *p_cb, tSMP_ENC *p)
 
     key.key_type = SMP_KEY_TYPE_CFM;
     key.p_data = p->param_buf;
-
     smp_sm_event(p_cb, SMP_KEY_READY_EVT, &key);
 }
+
 /*******************************************************************************
 **
 ** Function         smp_process_compare
@@ -758,28 +815,29 @@ static void smp_process_stk(tSMP_CB *p_cb, tSMP_ENC *p)
 
 /*******************************************************************************
 **
-** Function         smp_genenrate_ltk_cont
+** Function         smp_generate_ltk_cont
 **
 ** Description      This function is to calculate LTK = d1(ER, DIV, 0)= e(ER, DIV)
 **
 ** Returns          void
 **
 *******************************************************************************/
-static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+static void smp_generate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
+    UNUSED(p_data);
+
     BT_OCTET16  er;
     tSMP_ENC    output;
     tSMP_STATUS     status = SMP_PAIR_FAIL_UNKNOWN;
-    UNUSED(p_data);
 
-    SMP_TRACE_DEBUG ("smp_genenrate_ltk_cont ");
+    SMP_TRACE_DEBUG ("%s", __func__);
     BTM_GetDeviceEncRoot(er);
 
     /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/
     if (!SMP_Encrypt(er, BT_OCTET16_LEN, (UINT8 *)&p_cb->div,
                      sizeof(UINT16), &output))
     {
-        SMP_TRACE_ERROR("smp_genenrate_ltk_cont failed");
+        SMP_TRACE_ERROR("%s failed", __func__);
         smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
     }
     else
@@ -789,7 +847,6 @@ static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
         memcpy((void *)p_cb->ltk, output.param_buf, BT_OCTET16_LEN);
         smp_generate_rand_vector(p_cb, NULL);
     }
-
 }
 
 /*******************************************************************************
@@ -803,10 +860,12 @@ static void smp_genenrate_ltk_cont(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 *******************************************************************************/
 static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p)
 {
+    UNUSED(p);
+
     BT_OCTET16  dhk;
     tSMP_ENC   output;
     tSMP_STATUS     status = SMP_PAIR_FAIL_UNKNOWN;
-    UNUSED(p);
+
 
     SMP_TRACE_DEBUG ("smp_generate_y ");
     BTM_GetDeviceDHK(dhk);
@@ -822,6 +881,7 @@ static void smp_generate_y(tSMP_CB *p_cb, tSMP_INT_DATA *p)
         smp_process_ediv(p_cb, &output);
     }
 }
+
 /*******************************************************************************
 **
 ** Function         smp_generate_rand_vector
@@ -839,14 +899,14 @@ static void smp_generate_rand_vector (tSMP_CB *p_cb, tSMP_INT_DATA *p)
     /* generate EDIV and rand now */
     /* generate random vector */
     SMP_TRACE_DEBUG ("smp_generate_rand_vector ");
-    p_cb->rand_enc_proc = SMP_GEN_RAND_V;
+    p_cb->rand_enc_proc_state = SMP_GEN_RAND_V;
     if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
         smp_rand_back(NULL);
-
 }
+
 /*******************************************************************************
 **
-** Function         smp_genenrate_smp_process_edivltk_cont
+** Function         smp_process_ediv
 **
 ** Description      This function is to calculate EDIV = Y xor DIV
 **
@@ -874,65 +934,1340 @@ static void smp_process_ediv(tSMP_CB *p_cb, tSMP_ENC *p)
 
 /*******************************************************************************
 **
-** Function         smp_rand_back
+** Function         smp_calculate_legacy_short_term_key
 **
-** Description      This function is to process the rand command finished,
-**                  process the random/encrypted number for further action.
+** Description      The function calculates legacy STK.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_legacy_short_term_key(tSMP_CB *p_cb, tSMP_ENC *output)
+{
+    BT_OCTET16 ptext;
+    UINT8 *p = ptext;
+
+    SMP_TRACE_DEBUG ("%s", __func__);
+    memset(p, 0, BT_OCTET16_LEN);
+    if (p_cb->role == HCI_ROLE_MASTER)
+    {
+        memcpy(p, p_cb->rand, BT_OCTET8_LEN);
+        memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN);
+    }
+    else
+    {
+        memcpy(p, p_cb->rrand, BT_OCTET8_LEN);
+        memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
+    }
+
+    BOOLEAN encrypted;
+    /* generate STK = Etk(rand|rrand)*/
+    encrypted = SMP_Encrypt( p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, output);
+    if (!encrypted)
+    {
+        SMP_TRACE_ERROR("%s failed", __func__);
+    }
+    return encrypted;
+}
+
+/*******************************************************************************
+**
+** Function         smp_create_private_key
+**
+** Description      This function is called to create private key used to
+**                  calculate public key and DHKey.
+**                  The function starts private key creation requesting controller
+**                  to generate [0-7] octets of private key.
 **
 ** Returns          void
 **
 *******************************************************************************/
-static void smp_rand_back(tBTM_RAND_ENC *p)
+void smp_create_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
 {
-    tSMP_CB *p_cb = &smp_cb;
-    UINT8   *pp = p->param_buf;
-    UINT8   failure = SMP_PAIR_FAIL_UNKNOWN;
-    UINT8   state = p_cb->rand_enc_proc & ~0x80;
+    SMP_TRACE_DEBUG ("%s",__FUNCTION__);
+    p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_0_7;
+    if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+        smp_rand_back(NULL);
+}
 
-    SMP_TRACE_DEBUG ("smp_rand_back state=0x%x", state);
-    if (p && p->status == HCI_SUCCESS)
+/*******************************************************************************
+**
+** Function         smp_use_oob_private_key
+**
+** Description      This function is called
+**                  - to save the secret key used to calculate the public key used
+**                    in calculations of commitment sent OOB to a peer
+**                  - to use this secret key to recalculate the public key and
+**                    start the process of sending this public key to the peer
+**                  if secret/public keys have to be reused.
+**                  If the keys aren't supposed to be reused, continue from the
+**                  point from which request for OOB data was issued.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_use_oob_private_key(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG ("%s req_oob_type: %d, role: %d",
+                      __func__, p_cb->req_oob_type, p_cb->role);
+
+    switch (p_cb->req_oob_type)
     {
-        switch (state)
-        {
+        case SMP_OOB_BOTH:
+        case SMP_OOB_LOCAL:
+            SMP_TRACE_DEBUG("%s restore secret key", __func__)
+            memcpy(p_cb->private_key, p_cb->sc_oob_data.loc_oob_data.private_key_used, BT_OCTET32_LEN);
+            smp_process_private_key(p_cb);
+            break;
+        default:
+            SMP_TRACE_DEBUG("%s create secret key anew", __func__);
+            smp_set_state(SMP_STATE_PAIR_REQ_RSP);
+            smp_decide_association_model(p_cb, NULL);
+            break;
+    }
+}
 
-            case SMP_GEN_SRAND_MRAND:
-                memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
-                smp_genenrate_rand_cont(p_cb, NULL);
-                break;
+/*******************************************************************************
+**
+** Function         smp_continue_private_key_creation
+**
+** Description      This function is used to continue private key creation.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_continue_private_key_creation (tSMP_CB *p_cb, tBTM_RAND_ENC *p)
+{
+    UINT8   state = p_cb->rand_enc_proc_state & ~0x80;
+    SMP_TRACE_DEBUG ("%s state=0x%x", __func__, state);
 
-            case SMP_GEN_SRAND_MRAND_CONT:
-                memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
-                smp_genenrate_confirm(p_cb, NULL);
-                break;
+    switch (state)
+    {
+        case SMP_GENERATE_PRIVATE_KEY_0_7:
+            memcpy((void *)p_cb->private_key, p->param_buf, p->param_len);
+            p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_8_15;
+            if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+                smp_rand_back(NULL);
+            break;
+
+        case SMP_GENERATE_PRIVATE_KEY_8_15:
+            memcpy((void *)&p_cb->private_key[8], p->param_buf, p->param_len);
+            p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_16_23;
+            if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+                smp_rand_back(NULL);
+            break;
+
+        case SMP_GENERATE_PRIVATE_KEY_16_23:
+            memcpy((void *)&p_cb->private_key[16], p->param_buf, p->param_len);
+            p_cb->rand_enc_proc_state = SMP_GENERATE_PRIVATE_KEY_24_31;
+            if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+                smp_rand_back(NULL);
+            break;
+
+        case SMP_GENERATE_PRIVATE_KEY_24_31:
+            memcpy((void *)&p_cb->private_key[24], p->param_buf, p->param_len);
+            smp_process_private_key (p_cb);
+            break;
+
+        default:
+            break;
+    }
 
-            case SMP_GEN_DIV_LTK:
-                STREAM_TO_UINT16(p_cb->div, pp);
-                smp_genenrate_ltk_cont(p_cb, NULL);
-                break;
+    return;
+}
 
-            case SMP_GEN_DIV_CSRK:
-                STREAM_TO_UINT16(p_cb->div, pp);
-                smp_compute_csrk(p_cb, NULL);
-                break;
+/*******************************************************************************
+**
+** Function         smp_process_private_key
+**
+** Description      This function processes private key.
+**                  It calculates public key and notifies SM that private key /
+**                  public key pair is created.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_process_private_key(tSMP_CB *p_cb)
+{
+    Point       public_key;
+    BT_OCTET32  private_key;
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
+    ECC_PointMult(&public_key, &(curve_p256.G), (DWORD*) private_key, KEY_LENGTH_DWORDS_P256);
+    memcpy(p_cb->loc_publ_key.x, public_key.x, BT_OCTET32_LEN);
+    memcpy(p_cb->loc_publ_key.y, public_key.y, BT_OCTET32_LEN);
+
+    smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
+                                         BT_OCTET32_LEN);
+    smp_debug_print_nbyte_little_endian (p_cb->loc_publ_key.x, (const UINT8 *)"local public(x)",
+                                         BT_OCTET32_LEN);
+    smp_debug_print_nbyte_little_endian (p_cb->loc_publ_key.y, (const UINT8 *)"local public(y)",
+                                         BT_OCTET32_LEN);
+    p_cb->flags |= SMP_PAIR_FLAG_HAVE_LOCAL_PUBL_KEY;
+    smp_sm_event(p_cb, SMP_LOC_PUBL_KEY_CRTD_EVT, NULL);
+}
 
-            case SMP_GEN_TK:
-                smp_proc_passkey(p_cb, p);
-                break;
+/*******************************************************************************
+**
+** Function         smp_compute_dhkey
+**
+** Description      The function:
+**                  - calculates a new public key using as input local private
+**                    key and peer public key;
+**                  - saves the new public key x-coordinate as DHKey.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_compute_dhkey (tSMP_CB *p_cb)
+{
+    Point       peer_publ_key, new_publ_key;
+    BT_OCTET32  private_key;
 
-            case SMP_GEN_RAND_V:
-                memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
-                smp_generate_y(p_cb, NULL);
-                break;
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
 
-        }
+    memcpy(private_key, p_cb->private_key, BT_OCTET32_LEN);
+    memcpy(peer_publ_key.x, p_cb->peer_publ_key.x, BT_OCTET32_LEN);
+    memcpy(peer_publ_key.y, p_cb->peer_publ_key.y, BT_OCTET32_LEN);
 
-        return;
+    ECC_PointMult(&new_publ_key, &peer_publ_key, (DWORD*) private_key, KEY_LENGTH_DWORDS_P256);
+
+    memcpy(p_cb->dhkey, new_publ_key.x, BT_OCTET32_LEN);
+
+    smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Old DHKey",
+                                         BT_OCTET32_LEN);
+
+    smp_debug_print_nbyte_little_endian (p_cb->private_key, (const UINT8 *)"private",
+                                         BT_OCTET32_LEN);
+    smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.x, (const UINT8 *)"rem public(x)",
+                                         BT_OCTET32_LEN);
+    smp_debug_print_nbyte_little_endian (p_cb->peer_publ_key.y, (const UINT8 *)"rem public(y)",
+                                         BT_OCTET32_LEN);
+    smp_debug_print_nbyte_little_endian (p_cb->dhkey, (const UINT8 *)"Reverted DHKey",
+                                         BT_OCTET32_LEN);
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_local_commitment
+**
+** Description      The function calculates and saves local commmitment in CB.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_calculate_local_commitment(tSMP_CB *p_cb)
+{
+    UINT8 random_input;
+
+    SMP_TRACE_DEBUG("%s", __FUNCTION__);
+
+    switch (p_cb->selected_association_model)
+    {
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+            if (p_cb->role  == HCI_ROLE_MASTER)
+                SMP_TRACE_WARNING ("local commitment calc on master is not expected \
+                                    for Just Works/Numeric Comparison models");
+            smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand, 0,
+                             p_cb->commitment);
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+            random_input = smp_calculate_random_input(p_cb->local_random, p_cb->round);
+            smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
+                             random_input, p_cb->commitment);
+            break;
+        case SMP_MODEL_SEC_CONN_OOB:
+            SMP_TRACE_WARNING ("local commitment calc is expected for OOB model BEFORE pairing");
+            smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->loc_publ_key.x, p_cb->local_random, 0,
+                             p_cb->commitment);
+            break;
+        default:
+            SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
+                             p_cb->selected_association_model);
+            return;
     }
 
-    SMP_TRACE_ERROR("smp_rand_back Key generation failed: (%d)", p_cb->rand_enc_proc);
+    SMP_TRACE_EVENT ("local commitment calculation is completed");
+}
 
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+/*******************************************************************************
+**
+** Function         smp_calculate_peer_commitment
+**
+** Description      The function calculates and saves peer commmitment at the
+**                  provided output buffer.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_calculate_peer_commitment(tSMP_CB *p_cb, BT_OCTET16 output_buf)
+{
+    UINT8 ri;
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    switch (p_cb->selected_association_model)
+    {
+        case SMP_MODEL_SEC_CONN_JUSTWORKS:
+        case SMP_MODEL_SEC_CONN_NUM_COMP:
+            if (p_cb->role  == HCI_ROLE_SLAVE)
+                SMP_TRACE_WARNING ("peer commitment calc on slave is not expected \
+                for Just Works/Numeric Comparison models");
+            smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand, 0,
+                             output_buf);
+            break;
+        case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
+        case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
+            ri = smp_calculate_random_input(p_cb->peer_random, p_cb->round);
+            smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand, ri,
+                             output_buf);
+            break;
+        case SMP_MODEL_SEC_CONN_OOB:
+            smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->peer_publ_key.x, p_cb->peer_random, 0,
+                             output_buf);
+            break;
+        default:
+            SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
+                             p_cb->selected_association_model);
+            return;
+    }
 
+    SMP_TRACE_EVENT ("peer commitment calculation is completed");
 }
+
+/*******************************************************************************
+**
+** Function         smp_calculate_f4
+**
+** Description      The function calculates
+**                  C = f4(U, V, X, Z) = AES-CMAC (U||V||Z)
+**                                               X
+**                  where
+**                  input:  U is 256 bit,
+**                          V is 256 bit,
+**                          X is 128 bit,
+**                          Z is 8 bit,
+**                  output: C is 128 bit.
+**
+** Returns          void
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+void smp_calculate_f4(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 z, UINT8 *c)
+{
+    UINT8   msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */ + 1 /* Z size */;
+    UINT8   msg[BT_OCTET32_LEN + BT_OCTET32_LEN + 1];
+    UINT8   key[BT_OCTET16_LEN];
+    UINT8   cmac[BT_OCTET16_LEN];
+    UINT8   *p = NULL;
+#if SMP_DEBUG == TRUE
+    UINT8   *p_prnt = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+#if SMP_DEBUG == TRUE
+    p_prnt = u;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"U", BT_OCTET32_LEN);
+    p_prnt = v;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"V", BT_OCTET32_LEN);
+    p_prnt = x;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"X", BT_OCTET16_LEN);
+    p_prnt = &z;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Z", 1);
+#endif
+
+    p = msg;
+    UINT8_TO_STREAM(p, z);
+    ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
+    ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = msg;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", msg_len);
+#endif
+
+    p = key;
+    ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = key;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+    aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac);
+#if SMP_DEBUG == TRUE
+    p_prnt = cmac;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES_CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = c;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_numeric_comparison_display_number
+**
+** Description      The function calculates and saves number to display in numeric
+**                  comparison association mode.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_calculate_numeric_comparison_display_number(tSMP_CB *p_cb,
+                                                     tSMP_INT_DATA *p_data)
+{
+    SMP_TRACE_DEBUG ("%s", __func__);
+
+    if (p_cb->role == HCI_ROLE_MASTER)
+    {
+        p_cb->number_to_display =
+            smp_calculate_g2(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
+                             p_cb->rrand);
+    }
+    else
+    {
+        p_cb->number_to_display =
+            smp_calculate_g2(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand,
+                             p_cb->rand);
+    }
+
+    if (p_cb->number_to_display >= (BTM_MAX_PASSKEY_VAL + 1))
+    {
+        UINT8 reason;
+        reason = p_cb->failure = SMP_PAIR_FAIL_UNKNOWN;
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+        return;
+    }
+
+    SMP_TRACE_EVENT("Number to display in numeric comparison = %d", p_cb->number_to_display);
+    p_cb->cb_evt = SMP_NC_REQ_EVT;
+    smp_sm_event(p_cb, SMP_SC_DSPL_NC_EVT, &p_cb->number_to_display);
+    return;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_g2
+**
+** Description      The function calculates
+**                  g2(U, V, X, Y) = AES-CMAC (U||V||Y) mod 2**32 mod 10**6
+**                                           X
+**                  and
+**                  Vres = g2(U, V, X, Y) mod 10**6
+**                  where
+**                  input:  U     is 256 bit,
+**                          V     is 256 bit,
+**                          X     is 128 bit,
+**                          Y     is 128 bit,
+**
+** Returns          Vres.
+**                  Expected value has to be in the range [0 - 999999] i.e. [0 - 0xF423F].
+**                  Vres = 1000000 means that the calculation fails.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+UINT32 smp_calculate_g2(UINT8 *u, UINT8 *v, UINT8 *x, UINT8 *y)
+{
+    UINT8   msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */
+                      + BT_OCTET16_LEN /* Y size */;
+    UINT8   msg[BT_OCTET32_LEN + BT_OCTET32_LEN + BT_OCTET16_LEN];
+    UINT8   key[BT_OCTET16_LEN];
+    UINT8   cmac[BT_OCTET16_LEN];
+    UINT8   *p = NULL;
+    UINT32  vres;
+#if SMP_DEBUG == TRUE
+    UINT8   *p_prnt = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    p = msg;
+    ARRAY_TO_STREAM(p, y, BT_OCTET16_LEN);
+    ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
+    ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = u;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"U", BT_OCTET32_LEN);
+    p_prnt = v;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"V", BT_OCTET32_LEN);
+    p_prnt = x;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"X", BT_OCTET16_LEN);
+    p_prnt = y;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Y", BT_OCTET16_LEN);
+#endif
+
+    p = key;
+    ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = key;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+    if(!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+        return (BTM_MAX_PASSKEY_VAL + 1);
+    }
+
+#if SMP_DEBUG == TRUE
+    p_prnt = cmac;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    /* vres = cmac mod 2**32 mod 10**6 */
+    p = &cmac[0];
+    STREAM_TO_UINT32(vres, p);
+#if SMP_DEBUG == TRUE
+    p_prnt = (UINT8 *) &vres;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"cmac mod 2**32", 4);
+#endif
+
+    while (vres > BTM_MAX_PASSKEY_VAL)
+        vres -= (BTM_MAX_PASSKEY_VAL + 1);
+#if SMP_DEBUG == TRUE
+    p_prnt = (UINT8 *) &vres;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"cmac mod 2**32 mod 10**6", 4);
+#endif
+
+    SMP_TRACE_ERROR("Value for numeric comparison = %d", vres);
+    return vres;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_f5
+**
+** Description      The function provides two AES-CMAC that are supposed to be used as
+**                  - MacKey (MacKey is used in pairing DHKey check calculation);
+**                  - LTK (LTK is used to ecrypt the link after completion of Phase 2
+**                    and on reconnection, to derive BR/EDR LK).
+**                  The function inputs are W, N1, N2, A1, A2.
+**                  F5 rules:
+**                  - the value used as key in MacKey/LTK (T) is calculated
+**                    (function smp_calculate_f5_key(...));
+**                    The formula is:
+**                          T = AES-CMAC    (W)
+**                                      salt
+**                    where salt is internal parameter of smp_calculate_f5_key(...).
+**                  - MacKey and LTK are calculated as AES-MAC values received with the
+**                    key T calculated in the previous step and the plaintext message
+**                    built from the external parameters N1, N2, A1, A2 and the internal
+**                    parameters counter, keyID, length.
+**                    The function smp_calculate_f5_mackey_or_long_term_key(...) is used in the
+**                    calculations.
+**                    The same formula is used in calculation of MacKey and LTK and the
+**                    same parameter values except the value of the internal parameter
+**                    counter:
+**                    - in MacKey calculations the value is 0;
+**                    - in LTK calculations the value is 1.
+**                      MacKey  = AES-CMAC (Counter=0||keyID||N1||N2||A1||A2||Length=256)
+**                                        T
+**                      LTK     = AES-CMAC (Counter=1||keyID||N1||N2||A1||A2||Length=256)
+**                                        T
+**                  The parameters are
+**                  input:
+**                          W       is 256 bits,
+**                          N1      is 128 bits,
+**                          N2      is 128 bits,
+**                          A1 is 56 bit,
+**                          A2 is 56 bit.
+**                  internal:
+**                          Counter is 8 bits,  its value is 0 for MacKey,
+**                                                          1 for LTK;
+**                          KeyId   is 32 bits, its value is
+**                                              0x62746c65 (MSB~LSB);
+**                          Length  is 16 bits, its value is 0x0100
+**                                              (MSB~LSB).
+**                  output:
+**                          MacKey  is 128 bits;
+**                          LTK     is 128 bits
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+                         UINT8 *mac_key, UINT8 *ltk)
+{
+    BT_OCTET16  t;    /* AES-CMAC output in smp_calculate_f5_key(...), key in */
+                      /* smp_calculate_f5_mackey_or_long_term_key(...) */
+#if SMP_DEBUG == TRUE
+    UINT8   *p_prnt = NULL;
+#endif
+    /* internal parameters: */
+
+    /*
+        counter is 0 for MacKey,
+                is 1 for LTK
+    */
+    UINT8   counter_mac_key[1]  = {0};
+    UINT8   counter_ltk[1]      = {1};
+    /*
+        keyID   62746c65
+    */
+    UINT8   key_id[4] = {0x65, 0x6c, 0x74, 0x62};
+    /*
+        length  0100
+    */
+    UINT8   length[2] = {0x00, 0x01};
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_prnt = w;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"W", BT_OCTET32_LEN);
+    p_prnt = n1;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N1", BT_OCTET16_LEN);
+    p_prnt = n2;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N2", BT_OCTET16_LEN);
+    p_prnt = a1;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A1", 7);
+    p_prnt = a2;
+    smp_debug_print_nbyte_little_endian (p_prnt,(const UINT8 *) "A2", 7);
+#endif
+
+    if (!smp_calculate_f5_key(w, t))
+    {
+        SMP_TRACE_ERROR("%s failed to calc T",__FUNCTION__);
+        return FALSE;
+    }
+#if SMP_DEBUG == TRUE
+    p_prnt = t;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"T", BT_OCTET16_LEN);
+#endif
+
+    if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_mac_key, key_id, n1, n2, a1, a2,
+                                                  length, mac_key))
+    {
+        SMP_TRACE_ERROR("%s failed to calc MacKey", __FUNCTION__);
+        return FALSE;
+    }
+#if SMP_DEBUG == TRUE
+    p_prnt = mac_key;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"MacKey", BT_OCTET16_LEN);
+#endif
+
+    if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_ltk, key_id, n1, n2, a1, a2,
+                                                  length, ltk))
+    {
+        SMP_TRACE_ERROR("%s failed to calc LTK",__FUNCTION__);
+        return FALSE;
+    }
+#if SMP_DEBUG == TRUE
+    p_prnt = ltk;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"LTK", BT_OCTET16_LEN);
+#endif
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_f5_mackey_or_long_term_key
+**
+** Description      The function calculates the value of MacKey or LTK by the rules
+**                  defined for f5 function.
+**                  At the moment exactly the same formula is used to calculate
+**                  LTK and MacKey.
+**                  The difference is the value of input parameter Counter:
+**                  - in MacKey calculations the value is 0;
+**                  - in LTK calculations the value is 1.
+**                  The formula:
+**                  mac = AES-CMAC (Counter||keyID||N1||N2||A1||A2||Length)
+**                                T
+**                  where
+**                  input:      T       is 256 bits;
+**                              Counter is 8 bits, its value is 0 for MacKey,
+**                                                              1 for LTK;
+**                              keyID   is 32 bits, its value is 0x62746c65;
+**                              N1      is 128 bits;
+**                              N2      is 128 bits;
+**                              A1      is 56 bits;
+**                              A2      is 56 bits;
+**                              Length  is 16 bits, its value is 0x0100
+**                  output:     LTK     is 128 bit.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_mackey_or_long_term_key(UINT8 *t, UINT8 *counter,
+                                  UINT8 *key_id, UINT8 *n1, UINT8 *n2, UINT8 *a1, UINT8 *a2,
+                                  UINT8 *length, UINT8 *mac)
+{
+    UINT8   *p = NULL;
+    UINT8   cmac[BT_OCTET16_LEN];
+    UINT8   key[BT_OCTET16_LEN];
+    UINT8   msg_len = 1 /* Counter size */ + 4 /* keyID size */ +
+            BT_OCTET16_LEN /* N1 size */ + BT_OCTET16_LEN /* N2 size */ +
+            7 /* A1 size*/ + 7 /* A2 size*/ + 2 /* Length size */;
+    UINT8   msg[1 + 4 + BT_OCTET16_LEN + BT_OCTET16_LEN + 7 + 7 + 2];
+    BOOLEAN ret = TRUE;
+#if SMP_DEBUG == TRUE
+    UINT8   *p_prnt = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_prnt = t;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"T", BT_OCTET16_LEN);
+    p_prnt = counter;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Counter", 1);
+    p_prnt = key_id;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"KeyID", 4);
+    p_prnt = n1;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N1", BT_OCTET16_LEN);
+    p_prnt = n2;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"N2", BT_OCTET16_LEN);
+    p_prnt = a1;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A1", 7);
+    p_prnt = a2;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"A2", 7);
+    p_prnt = length;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"Length", 2);
+#endif
+
+    p = key;
+    ARRAY_TO_STREAM(p, t, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = key;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+    p = msg;
+    ARRAY_TO_STREAM(p, length, 2);
+    ARRAY_TO_STREAM(p, a2, 7);
+    ARRAY_TO_STREAM(p, a1, 7);
+    ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
+    ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
+    ARRAY_TO_STREAM(p, key_id, 4);
+    ARRAY_TO_STREAM(p, counter, 1);
+#if SMP_DEBUG == TRUE
+    p_prnt = msg;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", msg_len);
+#endif
+
+    if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+        ret = FALSE;
+    }
+
+#if SMP_DEBUG == TRUE
+    p_prnt = cmac;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = mac;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_f5_key
+**
+** Description      The function calculates key T used in calculation of
+**                  MacKey and LTK (f5 output is defined as MacKey || LTK).
+**                  T = AES-CMAC    (W)
+**                              salt
+**                  where
+**                  Internal:   salt    is 128 bit.
+**                  input:      W       is 256 bit.
+**                  Output:     T       is 128 bit.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_key(UINT8 *w, UINT8 *t)
+{
+    UINT8 *p = NULL;
+    /* Please see 2.2.7 LE Secure Connections Key Generation Function f5 */
+    /*
+        salt:   6C88 8391 AAF5 A538 6037 0BDB 5A60 83BE
+    */
+    BT_OCTET16  salt = {
+        0xBE, 0x83, 0x60, 0x5A, 0xDB, 0x0B, 0x37, 0x60,
+        0x38, 0xA5, 0xF5, 0xAA, 0x91, 0x83, 0x88, 0x6C
+    };
+#if SMP_DEBUG == TRUE
+    UINT8   *p_prnt = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_prnt = salt;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"salt", BT_OCTET16_LEN);
+    p_prnt = w;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"W", BT_OCTET32_LEN);
+#endif
+
+    BT_OCTET16 key;
+    BT_OCTET32 msg;
+
+    p = key;
+    ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN);
+    p = msg;
+    ARRAY_TO_STREAM(p, w, BT_OCTET32_LEN);
+#if SMP_DEBUG == TRUE
+    p_prnt = key;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"K", BT_OCTET16_LEN);
+    p_prnt = msg;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"M", BT_OCTET32_LEN);
+#endif
+
+    BT_OCTET16 cmac;
+    BOOLEAN ret = TRUE;
+    if (!aes_cipher_msg_auth_code(key, msg, BT_OCTET32_LEN, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+        ret = FALSE;
+    }
+
+#if SMP_DEBUG == TRUE
+    p_prnt = cmac;
+    smp_debug_print_nbyte_little_endian (p_prnt, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = t;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_local_dhkey_check
+**
+** Description      The function calculates and saves local device DHKey check
+**                  value in CB.
+**                  Before doing this it calls smp_calculate_f5_mackey_and_long_term_key(...).
+**                  to calculate MacKey and LTK.
+**                  MacKey is used in dhkey calculation.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_calculate_local_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8   iocap[3], a[7], b[7];
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    smp_calculate_f5_mackey_and_long_term_key(p_cb);
+
+    smp_collect_local_io_capabilities(iocap, p_cb);
+
+    smp_collect_local_ble_address(a, p_cb);
+    smp_collect_peer_ble_address(b, p_cb);
+    smp_calculate_f6(p_cb->mac_key, p_cb->rand, p_cb->rrand, p_cb->peer_random, iocap, a, b,
+                     p_cb->dhkey_check);
+
+    SMP_TRACE_EVENT ("local DHKey check calculation is completed");
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_peer_dhkey_check
+**
+** Description      The function calculates peer device DHKey check value.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_calculate_peer_dhkey_check(tSMP_CB *p_cb, tSMP_INT_DATA *p_data)
+{
+    UINT8       iocap[3], a[7], b[7];
+    BT_OCTET16  param_buf;
+    BOOLEAN     ret;
+    tSMP_KEY    key;
+    tSMP_STATUS status = SMP_PAIR_FAIL_UNKNOWN;
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    smp_collect_peer_io_capabilities(iocap, p_cb);
+
+    smp_collect_local_ble_address(a, p_cb);
+    smp_collect_peer_ble_address(b, p_cb);
+    ret = smp_calculate_f6(p_cb->mac_key, p_cb->rrand, p_cb->rand, p_cb->local_random, iocap,
+                           b, a, param_buf);
+
+    if (ret)
+    {
+        SMP_TRACE_EVENT ("peer DHKey check calculation is completed");
+#if (SMP_DEBUG == TRUE)
+        smp_debug_print_nbyte_little_endian (param_buf, (const UINT8 *)"peer DHKey check",
+                                             BT_OCTET16_LEN);
+#endif
+        key.key_type = SMP_KEY_TYPE_PEER_DHK_CHCK;
+        key.p_data   = param_buf;
+        smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &key);
+    }
+    else
+    {
+        SMP_TRACE_EVENT ("peer DHKey check calculation failed");
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &status);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_f6
+**
+** Description      The function calculates
+**                  C = f6(W, N1, N2, R, IOcap, A1, A2) = AES-CMAC (N1||N2||R||IOcap||A1||A2)
+**                                                                W
+**                  where
+**                  input:  W is 128 bit,
+**                          N1 is 128 bit,
+**                          N2 is 128 bit,
+**                          R is 128 bit,
+**                          IOcap is 24 bit,
+**                          A1 is 56 bit,
+**                          A2 is 56 bit,
+**                  output: C is 128 bit.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f6(UINT8 *w, UINT8 *n1, UINT8 *n2, UINT8 *r, UINT8 *iocap, UINT8 *a1,
+                         UINT8 *a2, UINT8 *c)
+{
+    UINT8   *p = NULL;
+    UINT8   msg_len = BT_OCTET16_LEN /* N1 size */ + BT_OCTET16_LEN /* N2 size */ +
+                      BT_OCTET16_LEN /* R size */ + 3 /* IOcap size */ + 7 /* A1 size*/
+                      + 7 /* A2 size*/;
+    UINT8   msg[BT_OCTET16_LEN + BT_OCTET16_LEN + BT_OCTET16_LEN + 3 + 7 + 7];
+#if SMP_DEBUG == TRUE
+    UINT8   *p_print = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_print = w;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"W", BT_OCTET16_LEN);
+    p_print = n1;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"N1", BT_OCTET16_LEN);
+    p_print = n2;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"N2", BT_OCTET16_LEN);
+    p_print = r;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"R", BT_OCTET16_LEN);
+    p_print = iocap;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"IOcap", 3);
+    p_print = a1;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"A1", 7);
+    p_print = a2;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"A2", 7);
+#endif
+
+    UINT8 cmac[BT_OCTET16_LEN];
+    UINT8 key[BT_OCTET16_LEN];
+
+    p = key;
+    ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+    p_print = key;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+    p = msg;
+    ARRAY_TO_STREAM(p, a2, 7);
+    ARRAY_TO_STREAM(p, a1, 7);
+    ARRAY_TO_STREAM(p, iocap, 3);
+    ARRAY_TO_STREAM(p, r, BT_OCTET16_LEN);
+    ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
+    ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
+#if SMP_DEBUG == TRUE
+    p_print = msg;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"M", msg_len);
+#endif
+
+    BOOLEAN ret = TRUE;
+    if(!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed", __FUNCTION__);
+        ret = FALSE;
+    }
+
+#if SMP_DEBUG == TRUE
+    p_print = cmac;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = c;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_link_key_from_long_term_key
+**
+** Description      The function calculates and saves BR/EDR link key derived from
+**                  LE SC LTK.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_link_key_from_long_term_key(tSMP_CB *p_cb)
+{
+    tBTM_SEC_DEV_REC *p_dev_rec;
+
+    SMP_TRACE_DEBUG ("%s", __func__);
+
+    if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+    {
+        SMP_TRACE_ERROR("%s failed to find Security Record", __func__);
+        return FALSE;
+    }
+
+    BT_OCTET16 intermediate_link_key;
+    BOOLEAN ret = TRUE;
+
+    ret = smp_calculate_h6(p_cb->ltk, (UINT8 *)"1pmt" /* reversed "tmp1" */,intermediate_link_key);
+    if (!ret)
+    {
+        SMP_TRACE_ERROR("%s failed to derive intermediate_link_key", __func__);
+        return ret;
+    }
+
+    BT_OCTET16 link_key;
+    ret = smp_calculate_h6(intermediate_link_key, (UINT8 *) "rbel" /* reversed "lebr" */, link_key);
+    if (!ret)
+    {
+        SMP_TRACE_ERROR("%s failed", __func__);
+    }
+    else
+    {
+        UINT8 link_key_type;
+        if (btm_cb.security_mode == BTM_SEC_MODE_SC)
+        {
+            /* Secure Connections Only Mode */
+            link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
+        }
+        else if (controller_get_interface()->supports_secure_connections())
+        {
+            /* both transports are SC capable */
+            if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
+                link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
+            else
+                link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB_P_256;
+        }
+        else if (btm_cb.security_mode == BTM_SEC_MODE_SP)
+        {
+            /* BR/EDR transport is SSP capable */
+            if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
+                link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
+            else
+                link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
+        }
+        else
+        {
+            SMP_TRACE_ERROR ("%s failed to update link_key. Sec Mode = %d, sm4 = 0x%02x",
+                 __func__, btm_cb.security_mode, p_dev_rec->sm4);
+            return FALSE;
+        }
+
+        link_key_type += BTM_LTK_DERIVED_LKEY_OFFSET;
+
+        UINT8 *p;
+        BT_OCTET16 notif_link_key;
+        p = notif_link_key;
+        ARRAY16_TO_STREAM(p, link_key);
+
+        btm_sec_link_key_notification (p_cb->pairing_bda, notif_link_key, link_key_type);
+
+        SMP_TRACE_EVENT ("%s is completed", __func__);
+    }
+
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_long_term_key_from_link_key
+**
+** Description      The function calculates and saves SC LTK derived from BR/EDR
+**                  link key.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_long_term_key_from_link_key(tSMP_CB *p_cb)
+{
+    BOOLEAN ret = TRUE;
+    tBTM_SEC_DEV_REC *p_dev_rec;
+    UINT8 rev_link_key[16];
+
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    if ((p_dev_rec = btm_find_dev (p_cb->pairing_bda)) == NULL)
+    {
+        SMP_TRACE_ERROR("%s failed to find Security Record",__FUNCTION__);
+        return FALSE;
+    }
+
+    UINT8 br_link_key_type;
+    if ((br_link_key_type = BTM_SecGetDeviceLinkKeyType (p_cb->pairing_bda))
+        == BTM_LKEY_TYPE_IGNORE)
+    {
+        SMP_TRACE_ERROR("%s failed to retrieve BR link type",__FUNCTION__);
+        return FALSE;
+    }
+
+    if ((br_link_key_type != BTM_LKEY_TYPE_AUTH_COMB_P_256) &&
+        (br_link_key_type != BTM_LKEY_TYPE_UNAUTH_COMB_P_256))
+    {
+        SMP_TRACE_ERROR("%s LE SC LTK can't be derived from LK %d",
+                         __FUNCTION__, br_link_key_type);
+        return FALSE;
+    }
+
+    UINT8 *p1;
+    UINT8 *p2;
+    p1 = rev_link_key;
+    p2 = p_dev_rec->link_key;
+    REVERSE_ARRAY_TO_STREAM(p1, p2, 16);
+
+    BT_OCTET16 intermediate_long_term_key;
+    /* "tmp2" obtained from the spec */
+    ret = smp_calculate_h6(rev_link_key, (UINT8 *) "2pmt" /* reversed "tmp2" */,
+                           intermediate_long_term_key);
+
+    if (!ret)
+    {
+        SMP_TRACE_ERROR("%s failed to derive intermediate_long_term_key",__FUNCTION__);
+        return ret;
+    }
+
+    /* "brle" obtained from the spec */
+    ret = smp_calculate_h6(intermediate_long_term_key, (UINT8 *) "elrb" /* reversed "brle" */,
+                           p_cb->ltk);
+
+    if (!ret)
+    {
+        SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+    }
+    else
+    {
+        p_cb->sec_level = (br_link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)
+                           ? SMP_SEC_AUTHENTICATED : SMP_SEC_UNAUTHENTICATE;
+        SMP_TRACE_EVENT ("%s is completed",__FUNCTION__);
+    }
+
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_calculate_h6
+**
+** Description      The function calculates
+**                  C = h6(W, KeyID) = AES-CMAC (KeyID)
+**                                             W
+**                  where
+**                  input:  W is 128 bit,
+**                          KeyId is 32 bit,
+**                  output: C is 128 bit.
+**
+** Returns          FALSE if out of resources, TRUE in other cases.
+**
+** Note             The LSB is the first octet, the MSB is the last octet of
+**                  the AES-CMAC input/output stream.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_h6(UINT8 *w, UINT8 *keyid, UINT8 *c)
+{
+#if SMP_DEBUG == TRUE
+    UINT8   *p_print = NULL;
+#endif
+
+    SMP_TRACE_DEBUG ("%s",__FUNCTION__);
+#if SMP_DEBUG == TRUE
+    p_print = w;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"W", BT_OCTET16_LEN);
+    p_print = keyid;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"keyID", 4);
+#endif
+
+    UINT8 *p = NULL;
+    UINT8 key[BT_OCTET16_LEN];
+
+    p = key;
+    ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
+
+#if SMP_DEBUG == TRUE
+    p_print = key;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"K", BT_OCTET16_LEN);
+#endif
+
+    UINT8 msg_len = 4 /* KeyID size */;
+    UINT8 msg[4];
+
+    p = msg;
+    ARRAY_TO_STREAM(p, keyid, 4);
+
+#if SMP_DEBUG == TRUE
+    p_print = msg;
+    smp_debug_print_nbyte_little_endian (p_print,(const UINT8 *) "M", msg_len);
+#endif
+
+    BOOLEAN ret = TRUE;
+    UINT8 cmac[BT_OCTET16_LEN];
+    if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac))
+    {
+        SMP_TRACE_ERROR("%s failed",__FUNCTION__);
+        ret = FALSE;
+    }
+
+#if SMP_DEBUG == TRUE
+    p_print = cmac;
+    smp_debug_print_nbyte_little_endian (p_print, (const UINT8 *)"AES-CMAC", BT_OCTET16_LEN);
+#endif
+
+    p = c;
+    ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+    return ret;
+}
+
+/*******************************************************************************
+**
+** Function         smp_start_nonce_generation
+**
+** Description      This function starts nonce generation.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_start_nonce_generation(tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG("%s", __FUNCTION__);
+    p_cb->rand_enc_proc_state = SMP_GEN_NONCE_0_7;
+    if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+        smp_rand_back(NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_finish_nonce_generation
+**
+** Description      This function finishes nonce generation.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_finish_nonce_generation(tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG("%s", __FUNCTION__);
+    p_cb->rand_enc_proc_state = SMP_GEN_NONCE_8_15;
+    if (!btsnd_hcic_ble_rand((void *)smp_rand_back))
+        smp_rand_back(NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_process_new_nonce
+**
+** Description      This function notifies SM that it has new nonce.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_process_new_nonce(tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG ("%s round %d", __FUNCTION__, p_cb->round);
+    smp_sm_event(p_cb, SMP_HAVE_LOC_NONCE_EVT, NULL);
+}
+
+/*******************************************************************************
+**
+** Function         smp_rand_back
+**
+** Description      This function is to process the rand command finished,
+**                  process the random/encrypted number for further action.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void smp_rand_back(tBTM_RAND_ENC *p)
+{
+    tSMP_CB *p_cb = &smp_cb;
+    UINT8   *pp = p->param_buf;
+    UINT8   failure = SMP_PAIR_FAIL_UNKNOWN;
+    UINT8   state = p_cb->rand_enc_proc_state & ~0x80;
+
+    SMP_TRACE_DEBUG ("%s state=0x%x", __FUNCTION__, state);
+    if (p && p->status == HCI_SUCCESS)
+    {
+        switch (state)
+        {
+            case SMP_GEN_SRAND_MRAND:
+                memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
+                smp_generate_rand_cont(p_cb, NULL);
+                break;
+
+            case SMP_GEN_SRAND_MRAND_CONT:
+                memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
+                smp_generate_confirm(p_cb, NULL);
+                break;
+
+            case SMP_GEN_DIV_LTK:
+                STREAM_TO_UINT16(p_cb->div, pp);
+                smp_generate_ltk_cont(p_cb, NULL);
+                break;
+
+            case SMP_GEN_DIV_CSRK:
+                STREAM_TO_UINT16(p_cb->div, pp);
+                smp_compute_csrk(p_cb, NULL);
+                break;
+
+            case SMP_GEN_TK:
+                smp_proc_passkey(p_cb, p);
+                break;
+
+            case SMP_GEN_RAND_V:
+                memcpy(p_cb->enc_rand, p->param_buf, BT_OCTET8_LEN);
+                smp_generate_y(p_cb, NULL);
+                break;
+
+            case SMP_GENERATE_PRIVATE_KEY_0_7:
+            case SMP_GENERATE_PRIVATE_KEY_8_15:
+            case SMP_GENERATE_PRIVATE_KEY_16_23:
+            case SMP_GENERATE_PRIVATE_KEY_24_31:
+                smp_continue_private_key_creation(p_cb, p);
+                break;
+
+            case SMP_GEN_NONCE_0_7:
+                memcpy((void *)p_cb->rand, p->param_buf, p->param_len);
+                smp_finish_nonce_generation(p_cb);
+                break;
+
+            case SMP_GEN_NONCE_8_15:
+                memcpy((void *)&p_cb->rand[8], p->param_buf, p->param_len);
+                smp_process_new_nonce(p_cb);
+                break;
+        }
+
+        return;
+    }
+
+    SMP_TRACE_ERROR("%s key generation failed: (%d)", __FUNCTION__, p_cb->rand_enc_proc_state);
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+}
+
 #endif
 
index 3c91cc0..7ff278d 100644 (file)
 #include "smp_int.h"
 
 
+static void smp_tx_complete_callback(UINT16 cid, UINT16 num_pkt);
 
-static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
-        UINT16 reason, tBT_TRANSPORT transport);
-static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
+static void smp_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+                               tBT_TRANSPORT transport);
+static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
+
+static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+                                    tBT_TRANSPORT transport);
+static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf);
 
 /*******************************************************************************
 **
@@ -49,7 +54,7 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf);
 void smp_l2cap_if_init (void)
 {
     tL2CAP_FIXED_CHNL_REG  fixed_reg;
-    SMP_TRACE_EVENT ("SMDBG l2c smp_l2cap_if_init");
+    SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);
     fixed_reg.fixed_chnl_opts.mode         = L2CAP_FCR_BASIC_MODE;
     fixed_reg.fixed_chnl_opts.max_transmit = 0;
     fixed_reg.fixed_chnl_opts.rtrans_tout  = 0;
@@ -57,43 +62,49 @@ void smp_l2cap_if_init (void)
     fixed_reg.fixed_chnl_opts.mps          = 0;
     fixed_reg.fixed_chnl_opts.tx_win_sz    = 0;
 
-    fixed_reg.pL2CA_FixedConn_Cb = smp_connect_cback;
-    fixed_reg.pL2CA_FixedData_Cb = smp_data_ind;
+    fixed_reg.pL2CA_FixedConn_Cb = smp_connect_callback;
+    fixed_reg.pL2CA_FixedData_Cb = smp_data_received;
+    fixed_reg.pL2CA_FixedTxComplete_Cb = smp_tx_complete_callback;
+
     fixed_reg.pL2CA_FixedCong_Cb = NULL;    /* do not handle congestion on this channel */
     fixed_reg.default_idle_tout  = 60;      /* set 60 seconds timeout, 0xffff default idle timeout */
 
-    /* Now, register with L2CAP */
     L2CA_RegisterFixedChannel (L2CAP_SMP_CID, &fixed_reg);
+
+    fixed_reg.pL2CA_FixedConn_Cb = smp_br_connect_callback;
+    fixed_reg.pL2CA_FixedData_Cb = smp_br_data_received;
+
+    L2CA_RegisterFixedChannel (L2CAP_SMP_BR_CID, &fixed_reg);
 }
 
 /*******************************************************************************
 **
-** Function         smp_connect_cback
+** Function         smp_connect_callback
 **
 ** Description      This callback function is called by L2CAP to indicate that
 **                  SMP channel is
 **                      connected (conn = TRUE)/disconnected (conn = FALSE).
 **
 *******************************************************************************/
-static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
-                                    tBT_TRANSPORT transport)
+static void smp_connect_callback (UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected, UINT16 reason,
+                                  tBT_TRANSPORT transport)
 {
     tSMP_CB   *p_cb = &smp_cb;
     tSMP_INT_DATA   int_data;
+    BD_ADDR dummy_bda = {0};
 
-    SMP_TRACE_EVENT ("SMDBG l2c smp_connect_cback ");
+    SMP_TRACE_EVENT ("SMDBG l2c %s", __FUNCTION__);
 
-    if (transport == BT_TRANSPORT_BR_EDR)
-    {
-        SMP_TRACE_ERROR ("smp_connect_cback : Wrong transport");
+    if (transport == BT_TRANSPORT_BR_EDR || memcmp(bd_addr, dummy_bda, BD_ADDR_LEN) == 0)
         return;
-    }
 
     if (memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0)
     {
-        SMP_TRACE_EVENT ("smp_connect_cback()  for pairing BDA: %08x%04x  Event: %s",
+        SMP_TRACE_EVENT ("%s()  for pairing BDA: %08x%04x  Event: %s",
+                        __FUNCTION__,
                         (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
-                        (bd_addr[4]<<8)+bd_addr[5], (connected) ? "connected" : "disconnected");
+                        (bd_addr[4]<<8)+bd_addr[5],
+                        (connected) ? "connected" : "disconnected");
 
         if (connected)
         {
@@ -104,7 +115,7 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
                 p_cb->role = L2CA_GetBleConnRole(bd_addr);
 
                 /* initialize local i/r key to be default keys */
-                p_cb->loc_r_key = p_cb->loc_i_key =  SMP_SEC_DEFAULT_KEY;
+                p_cb->local_r_key = p_cb->local_i_key =  SMP_SEC_DEFAULT_KEY;
                 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);
@@ -121,7 +132,7 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
 
 /*******************************************************************************
 **
-** Function         smp_data_ind
+** Function         smp_data_received
 **
 ** Description      This function is called when data is received from L2CAP on
 **                  SMP channel.
@@ -130,19 +141,17 @@ static void smp_connect_cback (UINT16 chan, BD_ADDR bd_addr, BOOLEAN connected,
 ** Returns          void
 **
 *******************************************************************************/
-static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
+static void smp_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
 {
     tSMP_CB *p_cb = &smp_cb;
     UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
     UINT8   cmd ;
-    SMP_TRACE_EVENT ("SMDBG l2c smp_data_ind");
-
-    SMP_TRACE_EVENT ("Got smp_data_ind");
+    SMP_TRACE_EVENT ("SMDBG l2c %s", __FUNCTION__);
 
     STREAM_TO_UINT8(cmd, p);
 
     /* sanity check */
-    if ((SMP_OPCODE_MAX <= cmd) || (cmd == 0))
+    if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
     {
         SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
         GKI_freebuf (p_buf);
@@ -152,7 +161,7 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
     /* reject the pairing request if there is an on-going SMP pairing */
     if (SMP_OPCODE_PAIRING_REQ == cmd || SMP_OPCODE_SEC_REQ == cmd)
     {
-        if (p_cb->state == SMP_ST_IDLE)
+        if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE))
         {
             p_cb->role = L2CA_GetBleConnRole(bd_addr);
             memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
@@ -160,7 +169,7 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
         else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
         {
             GKI_freebuf (p_buf);
-            smp_reject_unexp_pair_req(bd_addr);
+            smp_reject_unexpected_pairing_command(bd_addr);
             return;
         }
         /* else, out of state pairing request/security request received, passed into SM */
@@ -168,12 +177,23 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
 
     if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
     {
-        if (p_cb->state != SMP_ST_RELEASE_DELAY)
-        {
-            btu_stop_timer (&p_cb->rsp_timer_ent);
-            btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
+        btu_stop_timer (&p_cb->rsp_timer_ent);
+        btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
                              SMP_WAIT_FOR_RSP_TOUT);
+
+        if (cmd == SMP_OPCODE_CONFIRM)
+        {
+            SMP_TRACE_DEBUG ("in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
+                              "loc_auth_req = 0x%02x",
+                              __FUNCTION__, cmd, p_cb->peer_auth_req, p_cb->loc_auth_req);
+
+            if ((p_cb->peer_auth_req  & SMP_SC_SUPPORT_BIT) &&
+                (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+            {
+                cmd = SMP_OPCODE_PAIR_COMMITM;
+            }
         }
+
         p_cb->rcvd_cmd_code = cmd;
         p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
         smp_sm_event(p_cb, cmd, p);
@@ -181,4 +201,137 @@ static void smp_data_ind (UINT16 chan, BD_ADDR bd_addr, BT_HDR *p_buf)
 
     GKI_freebuf (p_buf);
 }
-#endif
+
+/*******************************************************************************
+**
+** Function         smp_tx_complete_callback
+**
+** Description      SMP channel tx complete callback
+**
+*******************************************************************************/
+static void smp_tx_complete_callback (UINT16 cid, UINT16 num_pkt)
+{
+    tSMP_CB *p_cb = &smp_cb;
+
+    if (p_cb->total_tx_unacked >= num_pkt)
+        p_cb->total_tx_unacked -= num_pkt;
+    else
+        SMP_TRACE_ERROR("Unexpected %s: num_pkt = %d", __FUNCTION__,num_pkt);
+
+    UINT8 reason = SMP_SUCCESS;
+    if (p_cb->total_tx_unacked == 0 && p_cb->wait_for_authorization_complete)
+        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &reason);
+}
+
+/*******************************************************************************
+**
+** Function         smp_br_connect_callback
+**
+** Description      This callback function is called by L2CAP to indicate that
+**                  SMP BR channel is
+**                      connected (conn = TRUE)/disconnected (conn = FALSE).
+**
+*******************************************************************************/
+static void smp_br_connect_callback(UINT16 channel, BD_ADDR bd_addr, BOOLEAN connected,
+                                    UINT16 reason, tBT_TRANSPORT transport)
+{
+    tSMP_CB *p_cb = &smp_cb;
+    tSMP_INT_DATA int_data;
+
+    SMP_TRACE_EVENT ("%s", __func__);
+
+    if (transport != BT_TRANSPORT_BR_EDR)
+    {
+        SMP_TRACE_WARNING("%s is called on unexpected transport %d",
+                           __func__, transport);
+        return;
+    }
+
+    if (!(memcmp(bd_addr, p_cb->pairing_bda, BD_ADDR_LEN) == 0))
+        return;
+
+    SMP_TRACE_EVENT ("%s for pairing BDA: %08x%04x  Event: %s",
+                     __func__,
+                     (bd_addr[0]<<24)+(bd_addr[1]<<16)+(bd_addr[2]<<8) + bd_addr[3],
+                     (bd_addr[4]<<8)+bd_addr[5],
+                     (connected) ? "connected" : "disconnected");
+
+    if (connected)
+    {
+        if(!p_cb->connect_initialized)
+        {
+            p_cb->connect_initialized = TRUE;
+            /* initialize local i/r key to be default keys */
+            p_cb->local_r_key = p_cb->local_i_key =  SMP_BR_SEC_DEFAULT_KEY;
+            p_cb->loc_auth_req = p_cb->peer_auth_req = 0;
+            p_cb->cb_evt = SMP_BR_KEYS_REQ_EVT;
+            smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_CONN_EVT, NULL);
+        }
+    }
+    else
+    {
+        int_data.reason = reason;
+        /* Disconnected while doing security */
+        smp_br_state_machine_event(p_cb, SMP_BR_L2CAP_DISCONN_EVT, &int_data);
+    }
+}
+
+/*******************************************************************************
+**
+** Function         smp_br_data_received
+**
+** Description      This function is called when data is received from L2CAP on
+**                  SMP BR channel.
+**
+** Returns          void
+**
+*******************************************************************************/
+static void smp_br_data_received(UINT16 channel, BD_ADDR bd_addr, BT_HDR *p_buf)
+{
+    tSMP_CB *p_cb = &smp_cb;
+    UINT8   *p = (UINT8 *)(p_buf + 1) + p_buf->offset;
+    UINT8   cmd ;
+    SMP_TRACE_EVENT ("SMDBG l2c %s", __func__);
+
+    STREAM_TO_UINT8(cmd, p);
+
+    /* sanity check */
+    if ((SMP_OPCODE_MAX < cmd) || (SMP_OPCODE_MIN > cmd))
+    {
+        SMP_TRACE_WARNING( "Ignore received command with RESERVED code 0x%02x", cmd);
+        GKI_freebuf(p_buf);
+        return;
+    }
+
+    /* reject the pairing request if there is an on-going SMP pairing */
+    if (SMP_OPCODE_PAIRING_REQ == cmd)
+    {
+        if ((p_cb->state == SMP_STATE_IDLE) && (p_cb->br_state == SMP_BR_STATE_IDLE))
+        {
+            p_cb->role = HCI_ROLE_SLAVE;
+            p_cb->smp_over_br = TRUE;
+            memcpy(&p_cb->pairing_bda[0], bd_addr, BD_ADDR_LEN);
+        }
+        else if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN))
+        {
+            GKI_freebuf (p_buf);
+            smp_reject_unexpected_pairing_command(bd_addr);
+            return;
+        }
+        /* else, out of state pairing request received, passed into State Machine */
+    }
+
+    if (memcmp(&bd_addr[0], p_cb->pairing_bda, BD_ADDR_LEN) == 0)
+    {
+        btu_stop_timer (&p_cb->rsp_timer_ent);
+        btu_start_timer (&p_cb->rsp_timer_ent, BTU_TTYPE_SMP_PAIRING_CMD,
+                             SMP_WAIT_FOR_RSP_TOUT);
+
+        p_cb->rcvd_cmd_code = cmd;
+        p_cb->rcvd_cmd_len = (UINT8) p_buf->len;
+        smp_br_state_machine_event(p_cb, cmd, p);
+    }
+
+    GKI_freebuf (p_buf);
+}
+#endif /* SMP_INCLUDED == TRUE */
index aee15da..9f6fde6 100644 (file)
 
 #if SMP_INCLUDED == TRUE
 
-    #include <string.h>
-    #include "smp_int.h"
+#include <string.h>
+#include "smp_int.h"
 
-
-const char * const smp_state_name [] =
+const char *const smp_state_name [] =
 {
-    "SMP_ST_IDLE",
-    "SMP_ST_WAIT_APP_RSP",
-    "SMP_ST_SEC_REQ_PENDING",
-    "SMP_ST_PAIR_REQ_RSP",
-    "SMP_ST_WAIT_CONFIRM",
-    "SMP_ST_CONFIRM",
-    "SMP_ST_RAND",
-    "SMP_ST_ENC_PENDING",
-    "SMP_ST_BOND_PENDING",
-    "SMP_ST_RELEASE_DELAY",
-    "SMP_ST_MAX"
+    "SMP_STATE_IDLE",
+    "SMP_STATE_WAIT_APP_RSP",
+    "SMP_STATE_SEC_REQ_PENDING",
+    "SMP_STATE_PAIR_REQ_RSP",
+    "SMP_STATE_WAIT_CONFIRM",
+    "SMP_STATE_CONFIRM",
+    "SMP_STATE_RAND",
+    "SMP_STATE_PUBLIC_KEY_EXCH",
+    "SMP_STATE_SEC_CONN_PHS1_START",
+    "SMP_STATE_WAIT_COMMITMENT",
+    "SMP_STATE_WAIT_NONCE",
+    "SMP_STATE_SEC_CONN_PHS2_START",
+    "SMP_STATE_WAIT_DHK_CHECK",
+    "SMP_STATE_DHK_CHECK",
+    "SMP_STATE_ENCRYPTION_PENDING",
+    "SMP_STATE_BOND_PENDING",
+    "SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA",
+    "SMP_STATE_MAX"
 };
-const char * const smp_event_name [] =
+
+const char *const smp_event_name [] =
 {
     "PAIRING_REQ_EVT",
     "PAIRING_RSP_EVT",
@@ -51,6 +58,10 @@ const char * const smp_event_name [] =
     "ID_ADDR_EVT",
     "SIGN_INFO_EVT",
     "SECURITY_REQ_EVT",
+    "PAIR_PUBLIC_KEY_EVT",
+    "PAIR_DHKEY_CHECK_EVT",
+    "PAIR_KEYPRESS_NOTIFICATION_EVT",
+    "PAIR_COMMITMENT_EVT",
     "KEY_READY_EVT",
     "ENCRYPTED_EVT",
     "L2CAP_CONN_EVT",
@@ -62,18 +73,32 @@ const char * const smp_event_name [] =
     "ENC_REQ_EVT",
     "BOND_REQ_EVT",
     "DISCARD_SEC_REQ_EVT",
-    "RELEASE_DELAY_EVT",
-    "RELEASE_DELAY_TOUT_EVT",
-    "MAX_EVT"
+    "PUBLIC_KEY_EXCHANGE_REQ_EVT",
+    "LOCAL_PUBLIC_KEY_CRTD_EVT",
+    "BOTH_PUBLIC_KEYS_RCVD_EVT",
+    "SEC_CONN_DHKEY_COMPLETE_EVT",
+    "HAVE_LOCAL_NONCE_EVT",
+    "SEC_CONN_PHASE1_CMPLT_EVT",
+    "SEC_CONN_CALC_NC_EVT",
+    "SEC_CONN_DISPLAY_NC_EVT",
+    "SEC_CONN_OK_EVT",
+    "SEC_CONN_2_DHCK_CHECKS_PRESENT_EVT",
+    "SEC_CONN_KEY_READY_EVT",
+    "KEYPRESS_NOTIFICATION_EVT",
+    "SEC_CONN_OOB_DATA_EVT",
+    "CREATE_LOCAL_SEC_CONN_OOB_DATA_EVT",
+    "OUT_OF_RANGE_EVT"
 };
-const char * smp_get_event_name(tSMP_EVENT event);
-const char * smp_get_state_name(tSMP_STATE state);
 
-    #define SMP_SM_IGNORE       0
-    #define SMP_NUM_ACTIONS     2
-    #define SMP_SME_NEXT_STATE  2
-    #define SMP_SM_NUM_COLS     3
-typedef const UINT8 (*tSMP_SM_TBL)[SMP_SM_NUM_COLS];
+const char *smp_get_event_name(tSMP_EVENT event);
+const char *smp_get_state_name(tSMP_STATE state);
+
+#define SMP_SM_IGNORE       0
+#define SMP_NUM_ACTIONS     2
+#define SMP_SME_NEXT_STATE  2
+#define SMP_SM_NUM_COLS     3
+
+typedef const UINT8(*tSMP_SM_TBL)[SMP_SM_NUM_COLS];
 
 enum
 {
@@ -82,14 +107,14 @@ enum
     SMP_SEND_PAIR_RSP,
     SMP_SEND_CONFIRM,
     SMP_SEND_PAIR_FAIL,
-    SMP_SEND_INIT,
-    SMP_SEND_SECU_INFO,
+    SMP_SEND_RAND,
+    SMP_SEND_ENC_INFO,
     SMP_SEND_ID_INFO,
     SMP_SEND_LTK_REPLY,
     SMP_PROC_PAIR_CMD,
     SMP_PROC_PAIR_FAIL,
     SMP_PROC_CONFIRM,
-    SMP_PROC_INIT,
+    SMP_PROC_RAND,
     SMP_PROC_ENC_INFO,
     SMP_PROC_MASTER_ID,
     SMP_PROC_ID_INFO,
@@ -111,9 +136,31 @@ enum
     SMP_PAIR_TERMINATE,
     SMP_ENC_CMPL,
     SMP_PROC_DISCARD,
-    SMP_PROC_REL_DELAY,
-    SMP_PROC_REL_DELAY_TOUT,
-    SMP_DELAY_TERMINATE,
+    SMP_CREATE_PRIVATE_KEY,
+    SMP_USE_OOB_PRIVATE_KEY,
+    SMP_SEND_PAIR_PUBLIC_KEY,
+    SMP_PROCESS_PAIR_PUBLIC_KEY,
+    SMP_HAVE_BOTH_PUBLIC_KEYS,
+    SMP_START_SEC_CONN_PHASE1,
+    SMP_PROCESS_LOCAL_NONCE,
+    SMP_SEND_COMMITMENT,
+    SMP_PROCESS_PAIRING_COMMITMENT,
+    SMP_PROCESS_PEER_NONCE,
+    SMP_CALCULATE_LOCAL_DHKEY_CHECK,
+    SMP_SEND_DHKEY_CHECK,
+    SMP_PROCESS_DHKEY_CHECK,
+    SMP_CALCULATE_PEER_DHKEY_CHECK,
+    SMP_MATCH_DHKEY_CHECKS,
+    SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER,
+    SMP_MOVE_TO_SEC_CONN_PHASE2,
+    SMP_PH2_DHKEY_CHECKS_ARE_PRESENT,
+    SMP_WAIT_FOR_BOTH_PUBLIC_KEYS,
+    SMP_START_PASSKEY_VERIFICATION,
+    SMP_SEND_KEYPRESS_NOTIFICATION,
+    SMP_PROCESS_KEYPRESS_NOTIFICATION,
+    SMP_PROCESS_SECURE_CONNECTION_OOB_DATA,
+    SMP_SET_LOCAL_OOB_KEYS,
+    SMP_SET_LOCAL_OOB_RAND_COMMITMENT,
     SMP_IDLE_TERMINATE,
     SMP_FAST_CONN_PARAM,
     SMP_SM_NO_ACTION
@@ -126,14 +173,14 @@ static const tSMP_ACT smp_sm_action[] =
     smp_send_pair_rsp,
     smp_send_confirm,
     smp_send_pair_fail,
-    smp_send_init,
+    smp_send_rand,
     smp_send_enc_info,
     smp_send_id_info,
     smp_send_ltk_reply,
     smp_proc_pair_cmd,
     smp_proc_pair_fail,
     smp_proc_confirm,
-    smp_proc_init,
+    smp_proc_rand,
     smp_proc_enc_info,
     smp_proc_master_id,
     smp_proc_id_info,
@@ -142,243 +189,531 @@ static const tSMP_ACT smp_sm_action[] =
     smp_proc_sec_grant,
     smp_proc_sl_key,
     smp_proc_compare,
-    smp_proc_io_rsp,
+    smp_process_io_response,
     smp_generate_compare,
-    smp_generate_confirm,
+    smp_generate_srand_mrand_confirm,
     smp_generate_stk,
     smp_key_distribution,
     smp_start_enc,
     smp_pairing_cmpl,
-    smp_decide_asso_model,
+    smp_decide_association_model,
     smp_send_app_cback,
     smp_check_auth_req,
     smp_pair_terminate,
     smp_enc_cmpl,
     smp_proc_discard,
-    smp_proc_release_delay,
-    smp_proc_release_delay_tout,
-    smp_delay_terminate,
+    smp_create_private_key,
+    smp_use_oob_private_key,
+    smp_send_pair_public_key,
+    smp_process_pairing_public_key,
+    smp_both_have_public_keys,
+    smp_start_secure_connection_phase1,
+    smp_process_local_nonce,
+    smp_send_commitment,
+    smp_process_pairing_commitment,
+    smp_process_peer_nonce,
+    smp_calculate_local_dhkey_check,
+    smp_send_dhkey_check,
+    smp_process_dhkey_check,
+    smp_calculate_peer_dhkey_check,
+    smp_match_dhkey_checks,
+    smp_calculate_numeric_comparison_display_number,
+    smp_move_to_secure_connections_phase2,
+    smp_phase_2_dhkey_checks_are_present,
+    smp_wait_for_both_public_keys,
+    smp_start_passkey_verification,
+    smp_send_keypress_notification,
+    smp_process_keypress_notification,
+    smp_process_secure_connection_oob_data,
+    smp_set_local_oob_keys,
+    smp_set_local_oob_random_commitment,
     smp_idle_terminate,
     smp_fast_conn_param
 };
+
 /************ SMP Master FSM State/Event Indirection Table **************/
-static const UINT8 smp_ma_entry_map[][SMP_ST_MAX] =
-{
-/* state name:           Idle WaitApp SecReq Pair   Wait Confirm Init Enc   Bond  Rel
-                               Rsp    Pend   ReqRsp Cfm              Pend  Pend   Delay    */
-/* PAIR_REQ           */{ 0,    0,     0,      0,     0,   0,    0,   0,    0,     0   },
-/* PAIR_RSP           */{ 0,    0,     0,      1,     0,   0,    0,   0,    0,     0   },
-/* CONFIRM            */{ 0,    0,     0,      0,     0,   1,    0,   0,    0,     0   },
-/* INIT               */{ 0,    0,     0,      0,     0,   0,    1,   0,    0,     0   },
-/* PAIR_FAIL          */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0,    0,     0   },
-/* ENC_INFO           */{ 0,    0,     0,      0,     0,   0,    0,   0,    1,     0   },
-/* MASTER_ID          */{ 0,    0,     0,      0,     0,   0,    0,   0,    4,     0   },
-/* ID_INFO            */{ 0,    0,     0,      0,     0,   0,    0,   0,    2,     0   },
-/* ID_ADDR            */{ 0,    0,     0,      0,     0,   0,    0,   0,    5,     0   },
-/* SIGN_INFO          */{ 0,    0,     0,      0,     0,   0,    0,   0,    3,     0   },
-/* SEC_REQ            */{ 2,    0,     0,      0,     0,   0,    0,   0,    0,     0   },
-/* 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           */{ 3,   0x83,  0,      0x83,  0x83,0x83, 0x83,0x83, 0x83,  3   },
-/* 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   },
-/* AUTH_CMPL          */{ 0,    0x82,  0,      0x82,  0x82,0x82, 0x82,0x82, 0x82,  0   },
-/* ENC_REQ            */{ 0,    4,     0,      0,     0,   0,    3,   0,    0,     0   },
-/* BOND_REQ           */{ 0,    0,     0,      0,     0,   0,    0,   3,    0,     0   },
-/* DISCARD_SEC_REQ    */{ 0,    5,     0,      0,     0,   0,    0,   3,    0,     0   },
-/* RELEASE_DELAY      */{ 0,    0,     0,      0,     0,   0,    0,   0,    0,     1   },
-/* RELEASE_DELAY_TOUT */{ 0,    0,     0,      0,     0,   0,    0,   0,    0,     2   },
-};
-
-static const UINT8 smp_all_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                              Next State */
-/* PAIR_FAIL */          {SMP_PROC_PAIR_FAIL,       SMP_PROC_REL_DELAY_TOUT,    SMP_ST_IDLE},
-/* AUTH_CMPL */          {SMP_SEND_PAIR_FAIL,      SMP_PAIRING_CMPL,      SMP_ST_RELEASE_DELAY},
-/* L2C_DISC  */          {SMP_PAIR_TERMINATE,      SMP_SM_NO_ACTION,      SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_idle_table[][SMP_SM_NUM_COLS] = {
-/* Event       Action                   Next State */
-/* L2C_CONN */      {SMP_SEND_APP_CBACK,     SMP_SM_NO_ACTION,   SMP_ST_WAIT_APP_RSP},
-/* SEC_REQ  */      {SMP_PROC_SEC_REQ,       SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* L2C_DISC  */     {SMP_IDLE_TERMINATE,     SMP_SM_NO_ACTION,      SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_wait_app_rsp_table[][SMP_SM_NUM_COLS] = {
-/* Event                                                                Action          Next State */
-/* SEC_GRANT            */ { SMP_PROC_SEC_GRANT,   SMP_SEND_APP_CBACK, SMP_ST_WAIT_APP_RSP},
-/* IO_RSP               */ { SMP_SEND_PAIR_REQ,    SMP_FAST_CONN_PARAM,   SMP_ST_PAIR_REQ_RSP},
-/* KEY_READY            */ { SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION,   SMP_ST_WAIT_CONFIRM},/* TK ready */
-/* ENC_REQ              */ { SMP_START_ENC,        SMP_FAST_CONN_PARAM,   SMP_ST_ENC_PENDING},/* start enc mode setup */
-/* DISCARD_SEC_REQ      */ { SMP_PROC_DISCARD,     SMP_SM_NO_ACTION,   SMP_ST_IDLE}
-};
-
-static const UINT8 smp_ma_pair_req_rsp_table [][SMP_SM_NUM_COLS] = {
-/* Event                       Action              Next State */
-/* PAIR_RSP */ { SMP_PROC_PAIR_CMD,     SMP_DECIDE_ASSO_MODEL,  SMP_ST_PAIR_REQ_RSP},
-/* TK_REQ   */ { SMP_SEND_APP_CBACK,    SMP_SM_NO_ACTION,       SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */{ SMP_GENERATE_CONFIRM,  SMP_SM_NO_ACTION,       SMP_ST_WAIT_CONFIRM} /* TK ready */
-};
-
-static const UINT8 smp_ma_wait_confirm_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* KEY_READY*/ {SMP_SEND_CONFIRM,       SMP_SM_NO_ACTION,       SMP_ST_CONFIRM}/* CONFIRM ready */
-};
-
-static const UINT8 smp_ma_confirm_table [][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* CONFIRM  */ { SMP_PROC_CONFIRM,      SMP_SEND_INIT,          SMP_ST_RAND}
-};
-
-static const UINT8 smp_ma_init_table [][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* INIT     */ { SMP_PROC_INIT,         SMP_GENERATE_COMPARE,    SMP_ST_RAND},
-/* KEY_READY*/ { SMP_PROC_COMPARE,      SMP_SM_NO_ACTION,   SMP_ST_RAND},  /* Compare ready */
-/* ENC_REQ  */ { SMP_GENERATE_STK,      SMP_SM_NO_ACTION,   SMP_ST_ENC_PENDING}
-};
-static const UINT8 smp_ma_enc_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* KEY_READY */ { SMP_START_ENC,        SMP_SM_NO_ACTION,   SMP_ST_ENC_PENDING},  /* STK ready */
-/* ENCRYPTED */ { SMP_CHECK_AUTH_REQ,   SMP_SM_NO_ACTION,   SMP_ST_ENC_PENDING},
-/* BOND_REQ  */ { SMP_KEY_DISTRIBUTE,   SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING}
-};
-static const UINT8 smp_ma_bond_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* ENC_INFO */ { SMP_PROC_ENC_INFO,     SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING},
-/* ID_INFO  */ { SMP_PROC_ID_INFO,      SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING},
-/* SIGN_INFO*/ { SMP_PROC_SRK_INFO,     SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING},
-/* MASTER_ID*/ { SMP_PROC_MASTER_ID,    SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING},
-/* ID_ADDR  */ { SMP_PROC_ID_ADDR,      SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING},
-/* KEY_READY */ {SMP_SEND_SECU_INFO,    SMP_SM_NO_ACTION,   SMP_ST_BOND_PENDING}   /* LTK ready */
-};
-
-static const UINT8 smp_ma_rel_delay_table[][SMP_SM_NUM_COLS] = {
-/* Event       Action                   Next State */
-/* RELEASE_DELAY*/       {SMP_PROC_REL_DELAY,      SMP_SM_NO_ACTION,      SMP_ST_RELEASE_DELAY},
-/* RELEASE_DELAY_TOUT*/  {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION,      SMP_ST_IDLE},
-/* L2C_DISC*/            {SMP_DELAY_TERMINATE,     SMP_SM_NO_ACTION,     SMP_ST_IDLE}
+static const UINT8 smp_master_entry_map[][SMP_STATE_MAX] =
+{
+/* state name:             Idle WaitApp SecReq Pair   Wait Confirm Rand PublKey SCPhs1  Wait  Wait  SCPhs2  Wait   DHKChk Enc   Bond  CrLocSc
+                                 Rsp    Pend   ReqRsp Cfm               Exch    Strt    Cmtm  Nonce Strt    DHKChk        Pend  Pend  OobData   */
+/* PAIR_REQ             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_RSP             */{ 0,    0,     0,      1,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* CONFIRM              */{ 0,    0,     0,      0,     0,   1,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* RAND                 */{ 0,    0,     0,      0,     0,   0,    1,   0,      0,      0,    1,    0,      0,     0,     0,    0,     0   },
+/* PAIR_FAIL            */{ 0,    0x81,  0,      0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0,    0,     0   },
+/* ENC_INFO             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    1,     0   },
+/* MASTER_ID            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    4,     0   },
+/* ID_INFO              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    2,     0   },
+/* ID_ADDR              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    5,     0   },
+/* SIGN_INFO            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    3,     0   },
+/* SEC_REQ              */{ 2,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_PUBLIC_KEY      */{ 0,    0,     0,      0,     0,   0,    0,   2,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_DHKEY_CHCK      */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      1,     0,     0,    0,     0   },
+/* PAIR_KEYPR_NOTIF     */{ 0,    8,     0,      0,     0,   0,    0,   0,      5,      2,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_COMMITM         */{ 0,    0,     0,      0,     0,   0,    0,   0,      6,      1,    0,    0,      0,     0,     0,    0,     0   },
+/* KEY_READY            */{ 0,    3,     0,      3,     1,   0,    2,   0,      4,      0,    0,    0,      0,     0,     1,    6,     0   },
+/* ENC_CMPL             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     2,    0,     0   },
+/* L2C_CONN             */{ 1,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* L2C_DISC             */{ 3,    0x83,  0,      0x83,  0x83,0x83, 0x83,0x83,   0x83,   0x83, 0x83, 0x83,   0x83,  0x83,  0x83, 0x83,  0   },
+/* IO_RSP               */{ 0,    2,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SEC_GRANT            */{ 0,    1,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* TK_REQ               */{ 0,    0,     0,      2,     0,   0,    0,   0,      3,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* AUTH_CMPL            */{ 4,    0x82,  0,      0x82,  0x82,0x82, 0x82,0x82,   0x82,   0x82, 0x82, 0x82,   0x82,  0x82,  0x82, 0x82,  0   },
+/* ENC_REQ              */{ 0,    4,     0,      0,     0,   0,    3,   0,      0,      0,    0,    0,      0,     2,     0,    0,     0   },
+/* BOND_REQ             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     3,    0,     0   },
+/* DISCARD_SEC_REQ      */{ 0,    5,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     3,    0,     0   },
+/* PUBL_KEY_EXCH_REQ    */{ 0,    0,     0,      4,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* LOC_PUBL_KEY_CRTD    */{ 0,    0,     0,      0,     0,   0,    0,   1,      0,      0,    0,    0,      0,     0,     0,    0,     1   },
+/* BOTH_PUBL_KEYS_RCVD  */{ 0,    0,     0,      0,     0,   0,    0,   3,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_DHKEY_CMPLT       */{ 0,    0,     0,      0,     0,   0,    0,   0,      1,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* HAVE_LOC_NONCE       */{ 0,    0,     0,      0,     0,   0,    0,   0,      2,      0,    0,    0,      0,     0,     0,    0,     2   },
+/* SC_PHASE1_CMPLT      */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    1,      0,     0,     0,    0,     0   },
+/* SC_CALC_NC           */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    2,    0,      0,     0,     0,    0,     0   },
+/* SC_DSPL_NC           */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    3,    0,      0,     0,     0,    0,     0   },
+/* SC_NC_OK             */{ 0,    6,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_2_DHCK_CHKS_PRES  */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_KEY_READY         */{ 0,    7,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     1,     0,    0,     0   },
+/* KEYPR_NOTIF          */{ 0,    9,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_OOB_DATA          */{ 0,    10,    0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* CR_LOC_SC_OOB_DATA   */{ 5,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+};
+
+static const UINT8 smp_all_table[][SMP_SM_NUM_COLS] =
+{
+/*                       Event                     Action                 Next State */
+/* PAIR_FAIL */          {SMP_PROC_PAIR_FAIL,      SMP_PAIRING_CMPL, SMP_STATE_IDLE},
+/* AUTH_CMPL */          {SMP_SEND_PAIR_FAIL,      SMP_PAIRING_CMPL, SMP_STATE_IDLE},
+/* L2C_DISC  */          {SMP_PAIR_TERMINATE,      SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+};
+
+static const UINT8 smp_master_idle_table[][SMP_SM_NUM_COLS] =
+{
+/*                   Event                  Action               Next State */
+/* L2C_CONN */      {SMP_SEND_APP_CBACK,     SMP_SM_NO_ACTION,   SMP_STATE_WAIT_APP_RSP},
+/* SEC_REQ  */      {SMP_PROC_SEC_REQ,       SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* L2C_DISC  */     {SMP_IDLE_TERMINATE,     SMP_SM_NO_ACTION, SMP_STATE_IDLE},
+/* AUTH_CMPL */     {SMP_PAIRING_CMPL,       SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+/* CR_LOC_SC_OOB_DATA   */ ,{SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
+
+};
+
+static const UINT8 smp_master_wait_for_app_response_table[][SMP_SM_NUM_COLS] =
+{
+/*                            Event                Action               Next State */
+/* SEC_GRANT            */ {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* IO_RSP               */ {SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+
+                    /* TK ready */
+/* KEY_READY            */ {SMP_GENERATE_CONFIRM, SMP_SM_NO_ACTION,   SMP_STATE_WAIT_CONFIRM},
+
+                    /* start enc mode setup */
+/* ENC_REQ              */ { SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_STATE_ENCRYPTION_PENDING},
+/* DISCARD_SEC_REQ      */ { SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+/* user confirms NC 'OK', i.e. phase 1 is completed */
+/* SC_NC_OK             */,{ SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
+/* user-provided passkey is rcvd */
+/* SC_KEY_READY  */ { SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF */ { SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* KEYPR_NOTIF          */ { SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SC_OOB_DATA      */ { SMP_USE_OOB_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
+};
+
+static const UINT8 smp_master_pair_request_response_table[][SMP_SM_NUM_COLS] =
+{
+/*               Event                  Action                  Next State */
+/* PAIR_RSP */ { SMP_PROC_PAIR_CMD,     SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
+/* TK_REQ   */ { SMP_SEND_APP_CBACK,    SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+
+                    /* TK ready */
+/* KEY_READY */{ SMP_GENERATE_CONFIRM,  SMP_SM_NO_ACTION, SMP_STATE_WAIT_CONFIRM}
+/* PUBL_KEY_EXCH_REQ    */,{ SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH}
+};
+
+static const UINT8 smp_master_wait_for_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/*              Event                   Action          Next State */
+/* KEY_READY*/ {SMP_SEND_CONFIRM,     SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}/* CONFIRM ready */
+};
+
+static const UINT8 smp_master_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/*               Event                  Action                 Next State */
+/* CONFIRM  */ { SMP_PROC_CONFIRM, SMP_SEND_RAND, SMP_STATE_RAND}
+};
+
+static const UINT8 smp_master_rand_table[][SMP_SM_NUM_COLS] =
+{
+/*               Event                  Action                   Next State */
+/* RAND     */ { SMP_PROC_RAND,         SMP_GENERATE_COMPARE, SMP_STATE_RAND},
+/* KEY_READY*/ { SMP_PROC_COMPARE,      SMP_SM_NO_ACTION,   SMP_STATE_RAND},  /* Compare ready */
+/* ENC_REQ  */ { SMP_GENERATE_STK,      SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
+};
+
+static const UINT8 smp_master_public_key_exchange_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                        Action              Next State */
+/* LOC_PUBL_KEY_CRTD    */{ SMP_SEND_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY      */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* BOTH_PUBL_KEYS_RCVD  */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_master_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                Next State */
+/* SC_DHKEY_CMPLT       */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* HAVE_LOC_NONCE       */{ SMP_PROCESS_LOCAL_NONCE, SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
+/* TK_REQ               */{ SMP_SEND_APP_CBACK,    SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display,*/
+/* It's time to start commitment calculation */
+/* KEY_READY            */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF  */{ SMP_PROCESS_KEYPRESS_NOTIFICATION,  SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_COMMITM  */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_master_wait_commitment_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* PAIR_COMMITM         */{ SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_RAND, SMP_STATE_WAIT_NONCE},
+/* PAIR_KEYPR_NOTIF */{ SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
+};
+
+static const UINT8 smp_master_wait_nonce_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* peer nonce is received */
+/* RAND                 */{SMP_PROC_RAND,  SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
+/* NC model, time to calculate number for NC */
+/* SC_CALC_NC           */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
+/* NC model, time to display calculated number for NC to the user */
+/* SC_DSPL_NC           */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+};
+
+static const UINT8 smp_master_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_SEND_DHKEY_CHECK, SMP_STATE_WAIT_DHK_CHECK},
+};
+
+static const UINT8 smp_master_wait_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* PAIR_DHKEY_CHCK  */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
+};
+
+static const UINT8 smp_master_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check actually received from peer */
+/* SC_KEY_READY         */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
+/* locally calculated peer dhkey check is ready -> calculate STK, go to sending */
+/* HCI LE Start Encryption command */
+/* ENC_REQ              */{SMP_GENERATE_STK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+};
+
+static const UINT8 smp_master_enc_pending_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* STK ready */
+/* KEY_READY */ { SMP_START_ENC,        SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* ENCRYPTED */ { SMP_CHECK_AUTH_REQ,   SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* BOND_REQ  */ { SMP_KEY_DISTRIBUTE,   SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+};
+static const UINT8 smp_master_bond_pending_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* ENC_INFO */ { SMP_PROC_ENC_INFO,     SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_INFO  */ { SMP_PROC_ID_INFO,      SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* SIGN_INFO*/ { SMP_PROC_SRK_INFO,     SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* MASTER_ID*/ { SMP_PROC_MASTER_ID,    SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_ADDR  */ { SMP_PROC_ID_ADDR,      SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* KEY_READY */{SMP_SEND_ENC_INFO,      SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING} /* LTK ready */
+};
+
+static const UINT8 smp_master_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] =
+{
+/*                       Event                   Action            Next State */
+/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS,   SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
+/* HAVE_LOC_NONCE    */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
 };
 
 
 /************ SMP Slave FSM State/Event Indirection Table **************/
-static const UINT8 smp_sl_entry_map[][SMP_ST_MAX] =
-{
-/* state name:            Idle Wait   SecReq Pair   Wait Confirm Init Enc   Bond  Rel
-                               AppRsp Pend   ReqRsp Cfm              Pend  Pend   Delay   */
-/* PAIR_REQ */           { 2,    0,    1,      0,     0,   0,    0,   0,    0,     0       },
-/* PAIR_RSP */           { 0,    0,    0,      0,     0,   0,    0,   0,    0,     0       },
-/* CONFIRM  */           { 0,    4,    0,      1,     1,   0,    0,   0,    0,     0       },
-/* INIT     */           { 0,    0,    0,      0,     0,   1,    2,   0,    0,     0       },
-/* PAIR_FAIL*/           { 0,    0x81, 0x81,   0x81,  0x81,0x81, 0x81,0x81, 0,     0       },
-/* ENC_INFO */           { 0,    0,    0,      0,     0,   0,    0,   0,    3,     0       },
-/* MASTER_ID*/           { 0,    0,    0,      0,     0,   0,    0,   0,    5,     0       },
-/* ID_INFO  */           { 0,    0,    0,      0,     0,   0,    0,   0,    4,     0       },
-/* ID_ADDR  */           { 0,    0,    0,      0,     0,   0,    0,   0,    6,     0       },
-/* SIGN_INFO*/           { 0,    0,    0,      0,     0,   0,    0,   0,    2,     0       },
-/* SEC_REQ  */           { 0,    0,    0,      0,     0,   0,    0,   0,    0,     0       },
-
-/* KEY_READY*/           { 0,    3,    0,      3,     2,   2,    1,   2,    1,     0       },
-/* ENC_CMPL */           { 0,    0,    2,      0,     0,   0,    0,   3,    0,     0       },
-/* L2C_CONN */           { 1,    0,    0,      0,     0,   0,    0,   0,    0,     0       },
-/* L2C_DISC */           { 0,    0x83, 0x83,   0x83,  0x83,0x83, 0x83,0x83, 0x83,  2       },
-/* IO_RSP   */           { 0,    1,    0,      0,     0,   0,    0,   0,    0,     0       },
-/* SEC_GRANT*/           { 0,    2,    0,      0,     0,   0,    0,   0,    0,     0       },
-
-/* TK_REQ   */           { 0,    0,    0,      2,     0,   0,    0,   0,    0,     0       },
-/* AUTH_CMPL*/           { 0,    0x82, 0x82,   0x82,  0x82,0x82, 0x82,0x82, 0x82,  0       },
-/* ENC_REQ  */           { 0,    0,    0,      0,     0,   0,    0,   1,    0,     0       },
-/* BOND_REQ */           { 0,    0,    0,      0,     0,   0,    0,   4,    0,     0       },
-/* DISCARD_SEC_REQ    */ { 0,    0,    0,      0,     0,   0,    0,   0,    0,     0       },
-/* RELEASE_DELAY      */ { 0,    0,    0,      0,     0,   0,    0,   0,    0,     1       },
-/* RELEASE_DELAY_TOUT */ { 0,    0,    0,      0,     0,   0,    0,   0,    0,     2       },
-};
-
-static const UINT8 smp_sl_idle_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                              Next State */
-/* L2C_CONN */      {SMP_SEND_APP_CBACK,  SMP_SM_NO_ACTION,       SMP_ST_WAIT_APP_RSP},
-/* PAIR_REQ */      {SMP_PROC_PAIR_CMD,   SMP_SEND_APP_CBACK,     SMP_ST_WAIT_APP_RSP}
-};
-
-static const UINT8 smp_sl_wait_app_rsp_table [][SMP_SM_NUM_COLS] = {
-/* Event                               Action              Next State */
-/* IO_RSP    */ {SMP_PROC_IO_RSP,       SMP_SM_NO_ACTION,       SMP_ST_PAIR_REQ_RSP},
-/* SEC_GRANT */ {SMP_PROC_SEC_GRANT,    SMP_SEND_APP_CBACK,     SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */ {SMP_PROC_SL_KEY,       SMP_SM_NO_ACTION,       SMP_ST_WAIT_APP_RSP},/* TK ready */
-/* CONFIRM   */ {SMP_PROC_CONFIRM,      SMP_SM_NO_ACTION,       SMP_ST_CONFIRM}
-};
-
-static const UINT8 smp_sl_sec_request_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action          Next State */
-/* PAIR_REQ */{SMP_PROC_PAIR_CMD,       SMP_SEND_PAIR_RSP,      SMP_ST_PAIR_REQ_RSP},
-/* ENCRYPTED*/{SMP_ENC_CMPL,        SMP_SM_NO_ACTION,       SMP_ST_PAIR_REQ_RSP},
-};
-
-static const UINT8 smp_sl_pair_req_rsp_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                  Next State */
-/* CONFIRM  */ {SMP_PROC_CONFIRM,       SMP_SM_NO_ACTION,   SMP_ST_CONFIRM},
-/* TK_REQ   */ {SMP_SEND_APP_CBACK,     SMP_SM_NO_ACTION,   SMP_ST_WAIT_APP_RSP},
-/* KEY_READY */{SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,   SMP_ST_PAIR_REQ_RSP} /* TK/Confirm ready */
-
-};
-
-static const UINT8 smp_sl_wait_confirm_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                          Next State */
-/* CONFIRM  */ {SMP_PROC_CONFIRM,       SMP_SEND_CONFIRM,   SMP_ST_CONFIRM},
-/* KEY_READY*/ {SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,   SMP_ST_WAIT_CONFIRM}
-};
-static const UINT8 smp_sl_confirm_table [][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                  Next State */
-/* INIT_EVT */{ SMP_PROC_INIT,          SMP_GENERATE_COMPARE,   SMP_ST_RAND},
-/* KEY_READY*/ {SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,       SMP_ST_CONFIRM} /* TK/Confirm ready */
-};
-static const UINT8 smp_sl_init_table [][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                          Next State */
-/* KEY_READY */ {SMP_PROC_COMPARE,      SMP_SM_NO_ACTION,       SMP_ST_RAND},   /* compare match */
-/* INIT_EVT  */ {SMP_SEND_INIT,         SMP_SM_NO_ACTION,       SMP_ST_ENC_PENDING}
-};
-static const UINT8 smp_sl_enc_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                  Next State */
-/* ENC_REQ   */ {SMP_GENERATE_STK,      SMP_SM_NO_ACTION,       SMP_ST_ENC_PENDING},
-/* KEY_READY */ {SMP_SEND_LTK_REPLY,    SMP_SM_NO_ACTION,       SMP_ST_ENC_PENDING},/* STK ready */
-/* ENCRYPTED */ {SMP_CHECK_AUTH_REQ,    SMP_SM_NO_ACTION,       SMP_ST_ENC_PENDING},
-/* BOND_REQ  */ {SMP_KEY_DISTRIBUTE,    SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING}
-};
-static const UINT8 smp_sl_bond_pending_table[][SMP_SM_NUM_COLS] = {
-/* Event                               Action                                  Next State */
-/* KEY_READY */ {SMP_SEND_SECU_INFO,    SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING},   /* LTK ready */
-/* SIGN_INFO */ {SMP_PROC_SRK_INFO,     SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING},   /* rev SRK */
-/* ENC_INFO */ { SMP_PROC_ENC_INFO,     SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING},
-/* ID_INFO  */ { SMP_PROC_ID_INFO,      SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING},
-/* MASTER_ID*/ { SMP_PROC_MASTER_ID,    SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING},
-/* ID_ADDR  */ { SMP_PROC_ID_ADDR,      SMP_SM_NO_ACTION,       SMP_ST_BOND_PENDING}
-
-};
-
-static const UINT8 smp_sl_rel_delay_table[][SMP_SM_NUM_COLS] = {
-/* Event       Action                   Next State */
-/* RELEASE_DELAY*/       {SMP_PROC_REL_DELAY,      SMP_SM_NO_ACTION,      SMP_ST_RELEASE_DELAY},
-/* RELEASE_DELAY_TOUT*/  {SMP_PROC_REL_DELAY_TOUT, SMP_SM_NO_ACTION,      SMP_ST_IDLE}
-};
-
-static const tSMP_SM_TBL smp_state_table[][2] = {
-    {smp_ma_idle_table,          smp_sl_idle_table},                  /* SMP_ST_IDLE*/
-    {smp_ma_wait_app_rsp_table,  smp_sl_wait_app_rsp_table},           /* SMP_ST_WAIT_APP_RSP */
-    {NULL,                       smp_sl_sec_request_table},            /* SMP_ST_SEC_REQ_PENDING */
-    {smp_ma_pair_req_rsp_table,  smp_sl_pair_req_rsp_table},           /* SMP_ST_PAIR_REQ_RSP */
-    {smp_ma_wait_confirm_table,  smp_sl_wait_confirm_table},           /* SMP_ST_WAIT_CONFIRM */
-    {smp_ma_confirm_table,       smp_sl_confirm_table},                /* SMP_ST_CONFIRM */
-    {smp_ma_init_table,          smp_sl_init_table},                   /* SMP_ST_RAND */
-    {smp_ma_enc_pending_table,   smp_sl_enc_pending_table},            /* SMP_ST_ENC_PENDING */
-    {smp_ma_bond_pending_table,  smp_sl_bond_pending_table},           /* SMP_ST_BOND_PENDING */
-    {smp_ma_rel_delay_table,     smp_sl_rel_delay_table}               /* SMP_ST_RELEASE_DELAY */
-};
+static const UINT8 smp_slave_entry_map[][SMP_STATE_MAX] =
+{
+/* state name:             Idle WaitApp SecReq Pair   Wait Confirm Rand PublKey SCPhs1  Wait  Wait  SCPhs2  Wait   DHKChk Enc   Bond  CrLocSc
+                                 Rsp    Pend   ReqRsp Cfm               Exch    Strt    Cmtm  Nonce Strt    DHKChk        Pend  Pend  OobData   */
+/* PAIR_REQ             */{ 2,    0,     1,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_RSP             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* CONFIRM              */{ 0,    4,     0,      1,     1,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* RAND                 */{ 0,    0,     0,      0,     0,   1,    2,   0,      0,      0,    1,    0,      0,     0,     0,    0,     0   },
+/* PAIR_FAIL            */{ 0,    0x81,  0x81,   0x81,  0x81,0x81, 0x81,0x81,   0x81,   0x81, 0x81, 0x81,   0x81,  0x81,  0x81, 0,     0   },
+/* ENC_INFO             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    3,     0   },
+/* MASTER_ID            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    5,     0   },
+/* ID_INFO              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    4,     0   },
+/* ID_ADDR              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    6,     0   },
+/* SIGN_INFO            */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    2,     0   },
+/* SEC_REQ              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_PUBLIC_KEY      */{ 0,    0,     0,      5,     0,   0,    0,   2,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_DHKEY_CHCK      */{ 0,    5,     0,      0,     0,   0,    0,   0,      0,      0,    0,    2,      1,     2,     0,    0,     0   },
+/* PAIR_KEYPR_NOTIF     */{ 0,    9,     0,      0,     0,   0,    0,   0,      5,      2,    0,    0,      0,     0,     0,    0,     0   },
+/* PAIR_COMMITM         */{ 0,    8,     0,      0,     0,   0,    0,   0,      0,      1,    0,    0,      0,     0,     0,    0,     0   },
+/* KEY_READY            */{ 0,    3,     0,      3,     2,   2,    1,   0,      4,      0,    0,    0,      0,     0,     2,    1,     0   },
+/* ENC_CMPL             */{ 0,    0,     2,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     3,    0,     0   },
+/* L2C_CONN             */{ 1,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* L2C_DISC             */{ 0,    0x83,  0x83,   0x83,  0x83,0x83, 0x83,0x83,   0x83,   0x83, 0x83, 0x83,   0x83,  0x83,  0x83, 0x83,  0   },
+/* IO_RSP               */{ 0,    1,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SEC_GRANT            */{ 0,    2,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* TK_REQ               */{ 0,    0,     0,      2,     0,   0,    0,   0,      3,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* AUTH_CMPL            */{ 0,    0x82,  0x82,   0x82,  0x82,0x82, 0x82,0x82,   0x82,   0x82, 0x82, 0x82,   0x82,  0x82,  0x82, 0x82,  0   },
+/* ENC_REQ              */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     1,    0,     0   },
+/* BOND_REQ             */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     4,    0,     0   },
+/* DISCARD_SEC_REQ      */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* PUBL_KEY_EXCH_REQ    */{ 0,    0,     0,      4,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* LOC_PUBL_KEY_CRTD    */{ 0,    0,     0,      0,     0,   0,    0,   1,      0,      0,    0,    0,      0,     0,     0,    0,     1   },
+/* BOTH_PUBL_KEYS_RCVD  */{ 0,    0,     0,      0,     0,   0,    0,   3,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_DHKEY_CMPLT       */{ 0,    0,     0,      0,     0,   0,    0,   0,      1,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* HAVE_LOC_NONCE       */{ 0,    0,     0,      0,     0,   0,    0,   0,      2,      0,    0,    0,      0,     0,     0,    0,     2   },
+/* SC_PHASE1_CMPLT      */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    1,      0,     0,     0,    0,     0   },
+/* SC_CALC_NC           */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    2,    0,      0,     0,     0,    0,     0   },
+/* SC_DSPL_NC           */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    3,    0,      0,     0,     0,    0,     0   },
+/* SC_NC_OK             */{ 0,    6,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_2_DHCK_CHKS_PRES  */{ 0,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      2,     0,     0,    0,     0   },
+/* SC_KEY_READY         */{ 0,    7,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     1,     0,    0,     0   },
+/* KEYPR_NOTIF          */{ 0,    10,    0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* SC_OOB_DATA          */{ 0,    11,    0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+/* CR_LOC_SC_OOB_DATA   */{ 3,    0,     0,      0,     0,   0,    0,   0,      0,      0,    0,    0,      0,     0,     0,    0,     0   },
+};
+
+static const UINT8 smp_slave_idle_table[][SMP_SM_NUM_COLS] =
+{
+/*                   Event                 Action                Next State */
+/* L2C_CONN */      {SMP_SEND_APP_CBACK,  SMP_SM_NO_ACTION,      SMP_STATE_WAIT_APP_RSP},
+/* PAIR_REQ */      {SMP_PROC_PAIR_CMD,   SMP_SEND_APP_CBACK,     SMP_STATE_WAIT_APP_RSP}
+/* CR_LOC_SC_OOB_DATA   */ ,{SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA}
+};
+
+static const UINT8 smp_slave_wait_for_app_response_table [][SMP_SM_NUM_COLS] =
+{
+/*               Event                   Action                 Next State */
+/* IO_RSP    */ {SMP_PROC_IO_RSP,       SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+/* SEC_GRANT */ {SMP_PROC_SEC_GRANT,    SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+
+                        /* TK ready */
+/* KEY_READY */ {SMP_PROC_SL_KEY,   SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* CONFIRM   */ {SMP_PROC_CONFIRM,   SMP_SM_NO_ACTION, SMP_STATE_CONFIRM}
+/* DHKey Check from master is received before phase 1 is completed - race */
+/* PAIR_DHKEY_CHCK      */,{SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION,  SMP_STATE_WAIT_APP_RSP},
+/* user confirms NC 'OK', i.e. phase 1 is completed */
+/* SC_NC_OK             */ {SMP_MOVE_TO_SEC_CONN_PHASE2, SMP_SM_NO_ACTION,  SMP_STATE_SEC_CONN_PHS2_START},
+/* user-provided passkey is rcvd */
+/* SC_KEY_READY   */ {SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_COMMITM   */ {SMP_PROCESS_PAIRING_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* PAIR_KEYPR_NOTIF */ {SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
+/* KEYPR_NOTIF */ {SMP_SEND_KEYPRESS_NOTIFICATION, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SC_OOB_DATA          */ {SMP_SEND_PAIR_RSP,    SMP_SM_NO_ACTION,    SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_sec_request_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* PAIR_REQ */{SMP_PROC_PAIR_CMD,       SMP_SM_NO_ACTION,       SMP_STATE_PAIR_REQ_RSP},
+/* ENCRYPTED*/{SMP_ENC_CMPL,            SMP_SM_NO_ACTION,       SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_pair_request_response_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* CONFIRM  */ {SMP_PROC_CONFIRM,       SMP_SM_NO_ACTION,   SMP_STATE_CONFIRM},
+/* TK_REQ   */ {SMP_SEND_APP_CBACK,     SMP_SM_NO_ACTION,   SMP_STATE_WAIT_APP_RSP},
+
+                    /* TK/Confirm ready */
+/* KEY_READY */{SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,   SMP_STATE_PAIR_REQ_RSP}
+/* PUBL_KEY_EXCH_REQ    */,{ SMP_CREATE_PRIVATE_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY      */ { SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION,   SMP_STATE_PAIR_REQ_RSP},
+};
+
+static const UINT8 smp_slave_wait_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* CONFIRM  */ {SMP_PROC_CONFIRM,       SMP_SEND_CONFIRM,   SMP_STATE_CONFIRM},
+/* KEY_READY*/ {SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,   SMP_STATE_WAIT_CONFIRM}
+};
+
+static const UINT8 smp_slave_confirm_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* RAND     */ {SMP_PROC_RAND,          SMP_GENERATE_COMPARE,   SMP_STATE_RAND},
+
+                    /* TK/Confirm ready */
+/* KEY_READY*/ {SMP_PROC_SL_KEY,        SMP_SM_NO_ACTION,       SMP_STATE_CONFIRM}
+};
+
+static const UINT8 smp_slave_rand_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* KEY_READY */ {SMP_PROC_COMPARE,      SMP_SM_NO_ACTION,   SMP_STATE_RAND}, /* compare match */
+/* RAND      */ {SMP_SEND_RAND,         SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING}
+};
+
+static const UINT8 smp_slave_public_key_exch_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* LOC_PUBL_KEY_CRTD  */{ SMP_WAIT_FOR_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* PAIR_PUBLIC_KEY      */{ SMP_PROCESS_PAIR_PUBLIC_KEY, SMP_SM_NO_ACTION, SMP_STATE_PUBLIC_KEY_EXCH},
+/* BOTH_PUBL_KEYS_RCVD */{ SMP_HAVE_BOTH_PUBLIC_KEYS, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_slave_sec_conn_phs1_start_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* SC_DHKEY_CMPLT       */{ SMP_START_SEC_CONN_PHASE1, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* HAVE_LOC_NONCE       */{ SMP_PROCESS_LOCAL_NONCE,SMP_SM_NO_ACTION, SMP_STATE_WAIT_COMMITMENT},
+/* TK_REQ               */{ SMP_SEND_APP_CBACK,      SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+/* SMP_MODEL_SEC_CONN_PASSKEY_DISP model, passkey is sent up to display, it's time to start */
+/* commitment calculation */
+/* KEY_READY */{ SMP_START_PASSKEY_VERIFICATION, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS1_START},
+/* PAIR_KEYPR_NOTIF  */{ SMP_PROCESS_KEYPRESS_NOTIFICATION,SMP_SEND_APP_CBACK, SMP_STATE_SEC_CONN_PHS1_START},
+};
+
+static const UINT8 smp_slave_wait_commitment_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* PAIR_COMMITM  */{SMP_PROCESS_PAIRING_COMMITMENT, SMP_SEND_COMMITMENT,  SMP_STATE_WAIT_NONCE},
+/* PAIR_KEYPR_NOTIF */{SMP_PROCESS_KEYPRESS_NOTIFICATION, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_COMMITMENT},
+};
+
+static const UINT8 smp_slave_wait_nonce_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* peer nonce is received */
+/* RAND           */{SMP_PROC_RAND, SMP_PROCESS_PEER_NONCE, SMP_STATE_SEC_CONN_PHS2_START},
+/* NC model, time to calculate number for NC */
+/* SC_CALC_NC  */{SMP_CALCULATE_NUMERIC_COMPARISON_DISPLAY_NUMBER, SMP_SM_NO_ACTION, SMP_STATE_WAIT_NONCE},
+/* NC model, time to display calculated number for NC to the user */
+/* SC_DSPL_NC   */{SMP_SEND_APP_CBACK, SMP_SM_NO_ACTION, SMP_STATE_WAIT_APP_RSP},
+};
+
+static const UINT8 smp_slave_sec_conn_phs2_start_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* SC_PHASE1_CMPLT */{SMP_CALCULATE_LOCAL_DHKEY_CHECK, SMP_PH2_DHKEY_CHECKS_ARE_PRESENT, SMP_STATE_WAIT_DHK_CHECK},
+/* DHKey Check from master is received before slave DHKey calculation is completed - race */
+/* PAIR_DHKEY_CHCK  */{SMP_PROCESS_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_SEC_CONN_PHS2_START},
+};
+
+static const UINT8 smp_slave_wait_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* PAIR_DHKEY_CHCK      */{SMP_PROCESS_DHKEY_CHECK, SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_STATE_DHK_CHECK},
+/* DHKey Check from master was received before slave came to this state */
+/* SC_2_DHCK_CHKS_PRES  */{SMP_CALCULATE_PEER_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
+};
+
+static const UINT8 smp_slave_dhk_check_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+
+/* locally calculated peer dhkey check is ready -> compare it withs DHKey Check */
+/* actually received from peer */
+/* SC_KEY_READY         */{SMP_MATCH_DHKEY_CHECKS, SMP_SM_NO_ACTION, SMP_STATE_DHK_CHECK},
 
-typedef const UINT8 (*tSMP_ENTRY_TBL)[SMP_ST_MAX];
-static const tSMP_ENTRY_TBL smp_entry_table[] ={
-    smp_ma_entry_map,
-    smp_sl_entry_map
+/* dhkey checks match -> send local dhkey check to master, go to wait for HCI LE */
+/* Long Term Key Request Event */
+/* PAIR_DHKEY_CHCK      */{SMP_SEND_DHKEY_CHECK, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+};
+
+static const UINT8 smp_slave_enc_pending_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* ENC_REQ   */ {SMP_GENERATE_STK,      SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+
+                    /* STK ready */
+/* KEY_READY */ {SMP_SEND_LTK_REPLY,    SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* ENCRYPTED */ {SMP_CHECK_AUTH_REQ,    SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
+/* BOND_REQ  */ {SMP_KEY_DISTRIBUTE,    SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+};
+static const UINT8 smp_slave_bond_pending_table[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+
+                /* LTK ready */
+/* KEY_READY */{ SMP_SEND_ENC_INFO,     SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+
+                /* rev SRK */
+/* SIGN_INFO */{ SMP_PROC_SRK_INFO,     SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ENC_INFO */ { SMP_PROC_ENC_INFO,     SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_INFO  */ { SMP_PROC_ID_INFO,      SMP_SM_NO_ACTION,  SMP_STATE_BOND_PENDING},
+/* MASTER_ID*/ { SMP_PROC_MASTER_ID,    SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING},
+/* ID_ADDR  */ { SMP_PROC_ID_ADDR,      SMP_SM_NO_ACTION, SMP_STATE_BOND_PENDING}
+
+};
+
+static const UINT8 smp_slave_create_local_sec_conn_oob_data[][SMP_SM_NUM_COLS] =
+{
+/*                          Event                  Action                 Next State */
+/* LOC_PUBL_KEY_CRTD */ {SMP_SET_LOCAL_OOB_KEYS, SMP_SM_NO_ACTION, SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA},
+/* HAVE_LOC_NONCE    */ {SMP_SET_LOCAL_OOB_RAND_COMMITMENT, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
+};
+
+static const tSMP_SM_TBL smp_state_table[][2] =
+{
+    /* SMP_STATE_IDLE */
+    {smp_master_idle_table, smp_slave_idle_table},
+
+    /* SMP_STATE_WAIT_APP_RSP */
+    {smp_master_wait_for_app_response_table, smp_slave_wait_for_app_response_table},
+
+    /* SMP_STATE_SEC_REQ_PENDING */
+    {NULL, smp_slave_sec_request_table},
+
+    /* SMP_STATE_PAIR_REQ_RSP */
+    {smp_master_pair_request_response_table, smp_slave_pair_request_response_table},
+
+    /* SMP_STATE_WAIT_CONFIRM */
+    {smp_master_wait_for_confirm_table, smp_slave_wait_confirm_table},
+
+    /* SMP_STATE_CONFIRM */
+    {smp_master_confirm_table, smp_slave_confirm_table},
+
+    /* SMP_STATE_RAND */
+    {smp_master_rand_table, smp_slave_rand_table},
+
+    /* SMP_STATE_PUBLIC_KEY_EXCH */
+    {smp_master_public_key_exchange_table,smp_slave_public_key_exch_table},
+
+    /* SMP_STATE_SEC_CONN_PHS1_START */
+    {smp_master_sec_conn_phs1_start_table, smp_slave_sec_conn_phs1_start_table},
+
+    /* SMP_STATE_WAIT_COMMITMENT */
+    {smp_master_wait_commitment_table, smp_slave_wait_commitment_table},
+
+    /* SMP_STATE_WAIT_NONCE */
+    {smp_master_wait_nonce_table, smp_slave_wait_nonce_table},
+
+     /* SMP_STATE_SEC_CONN_PHS2_START */
+    {smp_master_sec_conn_phs2_start_table, smp_slave_sec_conn_phs2_start_table},
+
+    /* SMP_STATE_WAIT_DHK_CHECK */
+    {smp_master_wait_dhk_check_table, smp_slave_wait_dhk_check_table},
+
+    /* SMP_STATE_DHK_CHECK */
+    {smp_master_dhk_check_table, smp_slave_dhk_check_table},
+
+    /* SMP_STATE_ENCRYPTION_PENDING */
+    {smp_master_enc_pending_table, smp_slave_enc_pending_table},
+
+     /* SMP_STATE_BOND_PENDING */
+    {smp_master_bond_pending_table, smp_slave_bond_pending_table},
+
+    /* SMP_STATE_CREATE_LOCAL_SEC_CONN_OOB_DATA */
+    {smp_master_create_local_sec_conn_oob_data, smp_slave_create_local_sec_conn_oob_data}
+};
+
+typedef const UINT8 (*tSMP_ENTRY_TBL)[SMP_STATE_MAX];
+static const tSMP_ENTRY_TBL smp_entry_table[] =
+{
+    smp_master_entry_map,
+    smp_slave_entry_map
 };
 
 #if SMP_DYNAMIC_MEMORY == FALSE
@@ -386,14 +721,13 @@ tSMP_CB  smp_cb;
 #endif
 #define SMP_ALL_TBL_MASK        0x80
 
-
 /*******************************************************************************
 ** Function     smp_set_state
 ** Returns      None
 *******************************************************************************/
 void smp_set_state(tSMP_STATE state)
 {
-    if (state < SMP_ST_MAX)
+    if (state < SMP_STATE_MAX)
     {
         SMP_TRACE_DEBUG( "State change: %s(%d) ==> %s(%d)",
                           smp_get_state_name(smp_cb.state), smp_cb.state,
@@ -415,7 +749,6 @@ tSMP_STATE smp_get_state(void)
     return smp_cb.state;
 }
 
-
 /*******************************************************************************
 **
 ** Function     smp_sm_event
@@ -439,7 +772,7 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
     tSMP_ENTRY_TBL  entry_table =  smp_entry_table[p_cb->role];
 
     SMP_TRACE_EVENT("main smp_sm_event");
-    if (curr_state >= SMP_ST_MAX)
+    if (curr_state >= SMP_STATE_MAX)
     {
         SMP_TRACE_DEBUG( "Invalid state: %d", curr_state) ;
         return;
@@ -453,7 +786,7 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
     /* lookup entry /w event & curr_state */
     /* If entry is ignore, return.
      * Otherwise, get state table (according to curr_state or all_state) */
-    if ((event < SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
+    if ((event <= SMP_MAX_EVT) && ( (entry = entry_table[event - 1][curr_state]) != SMP_SM_IGNORE ))
     {
         if (entry & SMP_ALL_TBL_MASK)
         {
@@ -466,7 +799,8 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
     else
     {
         SMP_TRACE_DEBUG( "Ignore event [%s (%d)] in state [%s (%d)]",
-                          smp_get_event_name(event), event, smp_get_state_name(curr_state), curr_state);
+                          smp_get_event_name(event), event, smp_get_state_name(curr_state),
+                          curr_state);
         return;
     }
 
@@ -493,34 +827,35 @@ void smp_sm_event(tSMP_CB *p_cb, tSMP_EVENT event, void *p_data)
     SMP_TRACE_DEBUG( "result state = %s", smp_get_state_name( p_cb->state ) ) ;
 }
 
-
 /*******************************************************************************
 ** Function     smp_get_state_name
 ** Returns      The smp state name.
 *******************************************************************************/
 const char * smp_get_state_name(tSMP_STATE state)
 {
-    const char * p_str = smp_state_name[SMP_ST_MAX];
+    const char *p_str = smp_state_name[SMP_STATE_MAX];
 
-    if (state < SMP_ST_MAX)
+    if (state < SMP_STATE_MAX)
     {
         p_str = smp_state_name[state];
     }
     return p_str;
 }
+
 /*******************************************************************************
 ** Function     smp_get_event_name
 ** Returns      The smp event name.
 *******************************************************************************/
 const char * smp_get_event_name(tSMP_EVENT event)
 {
-    const char * p_str = smp_event_name[SMP_MAX_EVT - 1];
+    const char *p_str = smp_event_name[SMP_MAX_EVT];
 
-    if (event < SMP_MAX_EVT)
+    if (event <= SMP_MAX_EVT)
     {
         p_str = smp_event_name[event- 1];
     }
     return p_str;
 }
+
 #endif
 
index ead44fc..9f2e532 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License.
  *
- ******************************************************************************/
+******************************************************************************/
 
 /******************************************************************************
  *
- *  This file contains functions for the SMP L2Cap utility functions
+ *  This file contains functions for the SMP L2CAP utility functions
  *
  ******************************************************************************/
 #include "bt_target.h"
 #include "l2c_int.h"
 #include "smp_int.h"
 #include "device/include/controller.h"
-
+#include "btm_int.h"
 
 #define SMP_PAIRING_REQ_SIZE    7
 #define SMP_CONFIRM_CMD_SIZE    (BT_OCTET16_LEN + 1)
+#define SMP_RAND_CMD_SIZE       (BT_OCTET16_LEN + 1)
 #define SMP_INIT_CMD_SIZE       (BT_OCTET16_LEN + 1)
 #define SMP_ENC_INFO_SIZE       (BT_OCTET16_LEN + 1)
 #define SMP_MASTER_ID_SIZE      (BT_OCTET8_LEN + 2 + 1)
 #define SMP_ID_ADDR_SIZE        (BD_ADDR_LEN + 1 + 1)
 #define SMP_SIGN_INFO_SIZE      (BT_OCTET16_LEN + 1)
 #define SMP_PAIR_FAIL_SIZE      2
+#define SMP_SECURITY_REQUEST_SIZE  2
+#define SMP_PAIR_PUBL_KEY_SIZE  (1 /* opcode */ + (2*BT_OCTET32_LEN))
+#define SMP_PAIR_COMMITM_SIZE           (1 /* opcode */ + BT_OCTET16_LEN /*Commitment*/)
+#define SMP_PAIR_DHKEY_CHECK_SIZE       (1 /* opcode */ + BT_OCTET16_LEN /*DHKey Check*/)
+#define SMP_PAIR_KEYPR_NOTIF_SIZE       (1 /* opcode */ + 1 /*Notif Type*/)
+
+/* SMP command sizes per spec */
+static const UINT8 smp_cmd_size_per_spec[] =
+{
+    0,
+    SMP_PAIRING_REQ_SIZE,       /* 0x01: pairing request */
+    SMP_PAIRING_REQ_SIZE,       /* 0x02: pairing response */
+    SMP_CONFIRM_CMD_SIZE,       /* 0x03: pairing confirm */
+    SMP_RAND_CMD_SIZE,          /* 0x04: pairing random */
+    SMP_PAIR_FAIL_SIZE,         /* 0x05: pairing failed */
+    SMP_ENC_INFO_SIZE,          /* 0x06: encryption information */
+    SMP_MASTER_ID_SIZE,         /* 0x07: master identification */
+    SMP_ID_INFO_SIZE,           /* 0x08: identity information */
+    SMP_ID_ADDR_SIZE,           /* 0x09: identity address information */
+    SMP_SIGN_INFO_SIZE,         /* 0x0A: signing information */
+    SMP_SECURITY_REQUEST_SIZE,  /* 0x0B: security request */
+    SMP_PAIR_PUBL_KEY_SIZE,     /* 0x0C: pairing public key */
+    SMP_PAIR_DHKEY_CHECK_SIZE,  /* 0x0D: pairing dhkey check */
+    SMP_PAIR_KEYPR_NOTIF_SIZE,  /* 0x0E: pairing keypress notification */
+    SMP_PAIR_COMMITM_SIZE       /* 0x0F: pairing commitment */
+};
 
+static BOOLEAN smp_parameter_unconditionally_valid(tSMP_CB *p_cb);
+static BOOLEAN smp_parameter_unconditionally_invalid(tSMP_CB *p_cb);
+
+/* type for SMP command length validation functions */
+typedef BOOLEAN (*tSMP_CMD_LEN_VALID)(tSMP_CB *p_cb);
+
+static BOOLEAN smp_command_has_valid_fixed_length(tSMP_CB *p_cb);
+
+static const tSMP_CMD_LEN_VALID smp_cmd_len_is_valid[] =
+{
+    smp_parameter_unconditionally_invalid,
+    smp_command_has_valid_fixed_length, /* 0x01: pairing request */
+    smp_command_has_valid_fixed_length, /* 0x02: pairing response */
+    smp_command_has_valid_fixed_length, /* 0x03: pairing confirm */
+    smp_command_has_valid_fixed_length, /* 0x04: pairing random */
+    smp_command_has_valid_fixed_length, /* 0x05: pairing failed */
+    smp_command_has_valid_fixed_length, /* 0x06: encryption information */
+    smp_command_has_valid_fixed_length, /* 0x07: master identification */
+    smp_command_has_valid_fixed_length, /* 0x08: identity information */
+    smp_command_has_valid_fixed_length, /* 0x09: identity address information */
+    smp_command_has_valid_fixed_length, /* 0x0A: signing information */
+    smp_command_has_valid_fixed_length, /* 0x0B: security request */
+    smp_command_has_valid_fixed_length, /* 0x0C: pairing public key */
+    smp_command_has_valid_fixed_length, /* 0x0D: pairing dhkey check */
+    smp_command_has_valid_fixed_length, /* 0x0E: pairing keypress notification */
+    smp_command_has_valid_fixed_length  /* 0x0F: pairing commitment */
+};
+
+/* type for SMP command parameter ranges validation functions */
+typedef BOOLEAN (*tSMP_CMD_PARAM_RANGES_VALID)(tSMP_CB *p_cb);
+
+static BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb);
+static BOOLEAN smp_pairing_keypress_notification_is_valid(tSMP_CB *p_cb);
+
+static const tSMP_CMD_PARAM_RANGES_VALID smp_cmd_param_ranges_are_valid[] =
+{
+    smp_parameter_unconditionally_invalid,
+    smp_pairing_request_response_parameters_are_valid, /* 0x01: pairing request */
+    smp_pairing_request_response_parameters_are_valid, /* 0x02: pairing response */
+    smp_parameter_unconditionally_valid, /* 0x03: pairing confirm */
+    smp_parameter_unconditionally_valid, /* 0x04: pairing random */
+    smp_parameter_unconditionally_valid, /* 0x05: pairing failed */
+    smp_parameter_unconditionally_valid, /* 0x06: encryption information */
+    smp_parameter_unconditionally_valid, /* 0x07: master identification */
+    smp_parameter_unconditionally_valid, /* 0x08: identity information */
+    smp_parameter_unconditionally_valid, /* 0x09: identity address information */
+    smp_parameter_unconditionally_valid, /* 0x0A: signing information */
+    smp_parameter_unconditionally_valid, /* 0x0B: security request */
+    smp_parameter_unconditionally_valid, /* 0x0C: pairing public key */
+    smp_parameter_unconditionally_valid, /* 0x0D: pairing dhkey check */
+    smp_pairing_keypress_notification_is_valid, /* 0x0E: pairing keypress notification */
+    smp_parameter_unconditionally_valid /* 0x0F: pairing commitment */
+};
 
 /* type for action functions */
 typedef BT_HDR * (*tSMP_CMD_ACT)(UINT8 cmd_code, tSMP_CB *p_cb);
 
-static BT_HDR * smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-static BT_HDR * smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
-
-const tSMP_CMD_ACT smp_cmd_build_act[] =
+static BT_HDR *smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pair_public_key_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_commitment_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pair_dhkey_check_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+static BT_HDR *smp_build_pairing_keypress_notification_cmd(UINT8 cmd_code, tSMP_CB *p_cb);
+
+static const tSMP_CMD_ACT smp_cmd_build_act[] =
 {
     NULL,
-    smp_build_pairing_cmd,      /* 0x01: pairing request */
-    smp_build_pairing_cmd,      /* 0x02: pairing response */
-    smp_build_confirm_cmd,      /* 0x03: pairing confirm */
-    smp_build_rand_cmd,         /* 0x04: pairing initializer request */
-    smp_build_pairing_fail,     /* 0x05: pairing failure */
-    smp_build_encrypt_info_cmd, /* 0x06: security information command */
-    smp_build_master_id_cmd,    /* 0x07: master identity command */
-    smp_build_identity_info_cmd,  /* 0x08: identity information command */
-    smp_build_id_addr_cmd,          /* 0x09: signing information */
-    smp_build_signing_info_cmd,    /* 0x0A: signing information */
-    smp_build_security_request    /* 0x0B: security request */
+    smp_build_pairing_cmd,          /* 0x01: pairing request */
+    smp_build_pairing_cmd,          /* 0x02: pairing response */
+    smp_build_confirm_cmd,          /* 0x03: pairing confirm */
+    smp_build_rand_cmd,             /* 0x04: pairing random */
+    smp_build_pairing_fail,         /* 0x05: pairing failure */
+    smp_build_encrypt_info_cmd,     /* 0x06: encryption information */
+    smp_build_master_id_cmd,        /* 0x07: master identification */
+    smp_build_identity_info_cmd,    /* 0x08: identity information */
+    smp_build_id_addr_cmd,          /* 0x09: identity address information */
+    smp_build_signing_info_cmd,     /* 0x0A: signing information */
+    smp_build_security_request,     /* 0x0B: security request */
+    smp_build_pair_public_key_cmd,  /* 0x0C: pairing public key */
+    smp_build_pair_dhkey_check_cmd, /* 0x0D: pairing DHKey check */
+    smp_build_pairing_keypress_notification_cmd, /* 0x0E: pairing keypress notification */
+    smp_build_pairing_commitment_cmd /* 0x0F: pairing commitment */
+};
+
+static const UINT8 smp_association_table[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
+{
+    /* display only */    /* Display Yes/No */   /* keyboard only */
+                       /* No Input/Output */ /* keyboard display */
+
+     /* initiator */
+     /* model = tbl[peer_io_caps][loc_io_caps] */
+     /* Display Only */
+    {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+     /* Display Yes/No */
+     {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+     /* Keyboard only */
+     {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY,
+                           SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+     /* No Input No Output */
+     {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},
+
+     /* keyboard display */
+     {SMP_MODEL_KEY_NOTIF, SMP_MODEL_KEY_NOTIF, SMP_MODEL_PASSKEY,
+                           SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF}},
+
+     /* responder */
+     /* model = tbl[loc_io_caps][peer_io_caps] */
+     /* Display Only */
+    {{SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+      /* Display Yes/No */
+     {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_KEY_NOTIF},
+
+      /* keyboard only */
+     {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY,
+                         SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY},
+
+      /* No Input No Output */
+     {SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY,
+                                 SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_ENCRYPTION_ONLY},
+
+      /* keyboard display */
+     {SMP_MODEL_PASSKEY, SMP_MODEL_PASSKEY, SMP_MODEL_KEY_NOTIF,
+                         SMP_MODEL_ENCRYPTION_ONLY, SMP_MODEL_PASSKEY}}
+};
+
+static const UINT8 smp_association_table_sc[2][SMP_IO_CAP_MAX][SMP_IO_CAP_MAX] =
+{
+     /* display only */    /* Display Yes/No */   /* keyboard only */
+                                             /* No InputOutput */  /* keyboard display */
+
+     /* initiator */
+     /* model = tbl[peer_io_caps][loc_io_caps] */
+
+     /* Display Only */
+    {{SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT},
+
+     /* Display Yes/No */
+     {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP},
+
+     /* keyboard only */
+     {SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+                                       SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP},
+
+     /* No Input No Output */
+     {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS},
+
+     /* keyboard display */
+     {SMP_MODEL_SEC_CONN_PASSKEY_DISP, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+                                       SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP}},
+
+     /* responder */
+     /* model = tbl[loc_io_caps][peer_io_caps] */
+
+     /* Display Only */
+    {{SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_DISP},
+
+     /* Display Yes/No */
+     {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP},
+
+     /* keyboard only */
+     {SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_PASSKEY_ENT,
+                                      SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_PASSKEY_ENT},
+
+     /* No Input No Output */
+     {SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS,
+                                    SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_JUSTWORKS},
+
+     /* keyboard display */
+     {SMP_MODEL_SEC_CONN_PASSKEY_ENT, SMP_MODEL_SEC_CONN_NUM_COMP, SMP_MODEL_SEC_CONN_PASSKEY_DISP,
+                       SMP_MODEL_SEC_CONN_JUSTWORKS, SMP_MODEL_SEC_CONN_NUM_COMP}}
 };
+
+static tSMP_ASSO_MODEL smp_select_legacy_association_model(tSMP_CB *p_cb);
+static tSMP_ASSO_MODEL smp_select_association_model_secure_connections(tSMP_CB *p_cb);
+
 /*******************************************************************************
 **
 ** Function         smp_send_msg_to_L2CAP
@@ -86,22 +280,28 @@ const tSMP_CMD_ACT smp_cmd_build_act[] =
 *******************************************************************************/
 BOOLEAN  smp_send_msg_to_L2CAP(BD_ADDR rem_bda, BT_HDR *p_toL2CAP)
 {
-    UINT16              l2cap_ret;
+    UINT16 l2cap_ret;
+    UINT16 fixed_cid = L2CAP_SMP_CID;
+
+    if (smp_cb.smp_over_br)
+    {
+        fixed_cid = L2CAP_SMP_BR_CID;
+    }
 
-    SMP_TRACE_EVENT("smp_send_msg_to_L2CAP");
+    SMP_TRACE_EVENT("%s", __FUNCTION__);
+    smp_cb.total_tx_unacked += 1;
 
-    if ((l2cap_ret = L2CA_SendFixedChnlData (L2CAP_SMP_CID, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED)
+    if ((l2cap_ret = L2CA_SendFixedChnlData (fixed_cid, rem_bda, p_toL2CAP)) == L2CAP_DW_FAILED)
     {
+        smp_cb.total_tx_unacked -= 1;
         SMP_TRACE_ERROR("SMP   failed to pass msg:0x%0x to L2CAP",
                          *((UINT8 *)(p_toL2CAP + 1) + p_toL2CAP->offset));
-        GKI_freebuf(p_toL2CAP);
         return FALSE;
     }
     else
-    {
         return TRUE;
-    }
 }
+
 /*******************************************************************************
 **
 ** Function         smp_send_cmd
@@ -115,7 +315,7 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
     BOOLEAN sent = FALSE;
     UINT8 failure = SMP_PAIR_INTERNAL_ERR;
     SMP_TRACE_EVENT("smp_send_cmd on l2cap cmd_code=0x%x", cmd_code);
-    if ( cmd_code < SMP_OPCODE_MAX &&
+    if ( cmd_code <= (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */) &&
          smp_cmd_build_act[cmd_code] != NULL)
     {
         p_buf = (*smp_cmd_build_act[cmd_code])(cmd_code, p_cb);
@@ -133,13 +333,18 @@ BOOLEAN smp_send_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 
     if (!sent)
     {
-        smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+        if (p_cb->smp_over_br)
+        {
+            smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
+        }
+        else
+        {
+            smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &failure);
+        }
     }
     return sent;
 }
 
-
-
 /*******************************************************************************
 **
 ** Function         smp_rsp_timeout
@@ -155,11 +360,11 @@ void smp_rsp_timeout(TIMER_LIST_ENT *p_tle)
     UINT8 failure = SMP_RSP_TIMEOUT;
     UNUSED(p_tle);
 
-    SMP_TRACE_EVENT("smp_rsp_timeout state:%d", p_cb->state);
+    SMP_TRACE_EVENT("%s state:%d br_state:%d", __FUNCTION__, p_cb->state, p_cb->br_state);
 
-    if (smp_get_state() == SMP_ST_RELEASE_DELAY)
+    if (p_cb->smp_over_br)
     {
-        smp_sm_event(p_cb, SMP_RELEASE_DELAY_TOUT_EVT, NULL);
+        smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &failure);
     }
     else
     {
@@ -178,18 +383,19 @@ BT_HDR * smp_build_pairing_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 {
     BT_HDR      *p_buf = NULL ;
     UINT8       *p;
+
     SMP_TRACE_EVENT("smp_build_pairing_cmd");
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIRING_REQ_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
         UINT8_TO_STREAM (p, cmd_code);
-        UINT8_TO_STREAM (p, p_cb->loc_io_caps);
+        UINT8_TO_STREAM (p, p_cb->local_io_capability);
         UINT8_TO_STREAM (p, p_cb->loc_oob_flag);
         UINT8_TO_STREAM (p, p_cb->loc_auth_req);
         UINT8_TO_STREAM (p, p_cb->loc_enc_size);
-        UINT8_TO_STREAM (p, p_cb->loc_i_key);
-        UINT8_TO_STREAM (p, p_cb->loc_r_key);
+        UINT8_TO_STREAM (p, p_cb->local_i_key);
+        UINT8_TO_STREAM (p, p_cb->local_r_key);
 
         p_buf->offset = L2CAP_MIN_OFFSET;
         /* 1B ERR_RSP op code + 1B cmd_op_code + 2B handle + 1B status */
@@ -230,7 +436,7 @@ static BT_HDR * smp_build_confirm_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 **
 ** Function         smp_build_rand_cmd
 **
-** Description      Build Initializer command.
+** Description      Build Random command.
 **
 *******************************************************************************/
 static BT_HDR * smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
@@ -239,16 +445,17 @@ static BT_HDR * smp_build_rand_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
     UINT8       *p;
     UNUSED(cmd_code);
 
-    SMP_TRACE_EVENT("smp_build_rand_cmd");
-    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_INIT_CMD_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+    SMP_TRACE_EVENT("%s", __func__);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_RAND_CMD_SIZE + L2CAP_MIN_OFFSET))
+         != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
-        UINT8_TO_STREAM (p, SMP_OPCODE_INIT);
+        UINT8_TO_STREAM (p, SMP_OPCODE_RAND);
         ARRAY_TO_STREAM (p, p_cb->rand, BT_OCTET16_LEN);
 
         p_buf->offset = L2CAP_MIN_OFFSET;
-        p_buf->len = SMP_INIT_CMD_SIZE;
+        p_buf->len = SMP_RAND_CMD_SIZE;
     }
 
     return p_buf;
@@ -280,6 +487,7 @@ static BT_HDR * smp_build_encrypt_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 
     return p_buf;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_build_master_id_cmd
@@ -293,7 +501,8 @@ static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
     UINT8       *p;
     UNUSED(cmd_code);
 
-    SMP_TRACE_EVENT("smp_build_master_id_cmd ");
+    SMP_TRACE_EVENT("%s", __func__);
+
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_MASTER_ID_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
@@ -308,6 +517,7 @@ static BT_HDR * smp_build_master_id_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 
     return p_buf;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_build_identity_info_cmd
@@ -339,6 +549,7 @@ static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 
     return p_buf;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_build_id_addr_cmd
@@ -348,18 +559,18 @@ static BT_HDR * smp_build_identity_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 *******************************************************************************/
 static BT_HDR * smp_build_id_addr_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 {
-    BT_HDR      *p_buf = NULL ;
-    UINT8       *p;
+    BT_HDR *p_buf = NULL;
+    UINT8 *p;
+
     UNUSED(cmd_code);
     UNUSED(p_cb);
-
     SMP_TRACE_EVENT("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;
 
         UINT8_TO_STREAM (p, SMP_OPCODE_ID_ADDR);
-        UINT8_TO_STREAM (p, 0);     /* TODO: update with local address type */
+        UINT8_TO_STREAM (p, 0);
         BDADDR_TO_STREAM (p, controller_get_interface()->get_address()->address);
 
         p_buf->offset = L2CAP_MIN_OFFSET;
@@ -396,6 +607,7 @@ static BT_HDR * smp_build_signing_info_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
 
     return p_buf;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_build_pairing_fail
@@ -409,7 +621,7 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb)
     UINT8       *p;
     UNUSED(cmd_code);
 
-    SMP_TRACE_EVENT("smp_build_pairing_fail");
+    SMP_TRACE_EVENT("%s", __func__);
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
@@ -423,6 +635,7 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb)
 
     return p_buf;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_build_security_request
@@ -430,14 +643,13 @@ static BT_HDR * smp_build_pairing_fail(UINT8 cmd_code, tSMP_CB *p_cb)
 ** Description      Build security request command.
 **
 *******************************************************************************/
-static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
+static BT_HDR *smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
 {
     BT_HDR      *p_buf = NULL ;
     UINT8       *p;
     UNUSED(cmd_code);
 
-    SMP_TRACE_EVENT("smp_build_security_request");
-
+    SMP_TRACE_EVENT("%s", __func__);
     if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + 2 + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
@@ -446,7 +658,7 @@ static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
         UINT8_TO_STREAM (p,  p_cb->loc_auth_req);
 
         p_buf->offset = L2CAP_MIN_OFFSET;
-        p_buf->len = 2;
+        p_buf->len = SMP_SECURITY_REQUEST_SIZE;
 
         SMP_TRACE_EVENT("opcode=%d auth_req=0x%x",SMP_OPCODE_SEC_REQ,  p_cb->loc_auth_req );
     }
@@ -457,6 +669,128 @@ static BT_HDR * smp_build_security_request(UINT8 cmd_code, tSMP_CB *p_cb)
 
 /*******************************************************************************
 **
+** Function         smp_build_pair_public_key_cmd
+**
+** Description      Build pairing public key command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pair_public_key_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+    BT_HDR  *p_buf = NULL ;
+    UINT8   *p;
+    UINT8   publ_key[2*BT_OCTET32_LEN];
+    UINT8   *p_publ_key = publ_key;
+    UNUSED(cmd_code);
+
+    SMP_TRACE_EVENT("%s", __FUNCTION__);
+
+    memcpy(p_publ_key, p_cb->loc_publ_key.x, BT_OCTET32_LEN);
+    memcpy(p_publ_key + BT_OCTET32_LEN, p_cb->loc_publ_key.y, BT_OCTET32_LEN);
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +
+        SMP_PAIR_PUBL_KEY_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+    {
+        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+        UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_PUBLIC_KEY);
+        ARRAY_TO_STREAM (p, p_publ_key, 2*BT_OCTET32_LEN);
+
+        p_buf->offset = L2CAP_MIN_OFFSET;
+        p_buf->len = SMP_PAIR_PUBL_KEY_SIZE;
+    }
+
+    return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function         smp_build_pairing_commitment_cmd
+**
+** Description      Build pairing commitment command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pairing_commitment_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+    BT_HDR *p_buf = NULL;
+    UINT8 *p;
+    UNUSED(cmd_code);
+
+    SMP_TRACE_EVENT("%s", __func__);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_COMMITM_SIZE + L2CAP_MIN_OFFSET))
+        != NULL)
+    {
+        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+        UINT8_TO_STREAM (p, SMP_OPCODE_CONFIRM);
+        ARRAY_TO_STREAM (p, p_cb->commitment, BT_OCTET16_LEN);
+
+        p_buf->offset = L2CAP_MIN_OFFSET;
+        p_buf->len = SMP_PAIR_COMMITM_SIZE;
+    }
+
+    return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function         smp_build_pair_dhkey_check_cmd
+**
+** Description      Build pairing DHKey check command.
+**
+*******************************************************************************/
+static BT_HDR *smp_build_pair_dhkey_check_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+    BT_HDR *p_buf = NULL;
+    UINT8 *p;
+    UNUSED(cmd_code);
+
+    SMP_TRACE_EVENT("%s", __FUNCTION__);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +
+        SMP_PAIR_DHKEY_CHECK_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+    {
+        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+        UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_DHKEY_CHECK);
+        ARRAY_TO_STREAM (p, p_cb->dhkey_check, BT_OCTET16_LEN);
+
+        p_buf->offset = L2CAP_MIN_OFFSET;
+        p_buf->len = SMP_PAIR_DHKEY_CHECK_SIZE;
+    }
+
+    return p_buf;
+}
+
+/*******************************************************************************
+**
+** Function         smp_build_pairing_keypress_notification_cmd
+**
+** Description      Build keypress notification command.
+**
+*******************************************************************************/
+static BT_HDR * smp_build_pairing_keypress_notification_cmd(UINT8 cmd_code, tSMP_CB *p_cb)
+{
+    BT_HDR      *p_buf = NULL ;
+    UINT8       *p;
+    UNUSED(cmd_code);
+
+    SMP_TRACE_EVENT("%s", __FUNCTION__);
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR)\
+        + SMP_PAIR_KEYPR_NOTIF_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+    {
+        p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
+
+        UINT8_TO_STREAM (p, SMP_OPCODE_PAIR_KEYPR_NOTIF);
+        UINT8_TO_STREAM (p, p_cb->local_keypress_notification);
+
+        p_buf->offset = L2CAP_MIN_OFFSET;
+        p_buf->len = SMP_PAIR_KEYPR_NOTIF_SIZE;
+    }
+
+    return p_buf;
+}
+
+/*******************************************************************************
+**
 ** Function         smp_convert_string_to_tk
 **
 ** Description      This function is called to convert a 6 to 16 digits numeric
@@ -500,6 +834,7 @@ void smp_mask_enc_key(UINT8 loc_enc_size, UINT8 * p_data)
     }
     return;
 }
+
 /*******************************************************************************
 **
 ** Function         smp_xor_128
@@ -521,7 +856,6 @@ void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b)
     }
 }
 
-
 /*******************************************************************************
 **
 ** Function         smp_cb_cleanup
@@ -537,10 +871,31 @@ void smp_cb_cleanup(tSMP_CB   *p_cb)
     UINT8           trace_level = p_cb->trace_level;
 
     SMP_TRACE_EVENT("smp_cb_cleanup");
+
     memset(p_cb, 0, sizeof(tSMP_CB));
     p_cb->p_callback = p_callback;
     p_cb->trace_level = trace_level;
 }
+
+/*******************************************************************************
+**
+** Function         smp_remove_fixed_channel
+**
+** Description      This function is called to remove the fixed channel
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_remove_fixed_channel(tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (p_cb->smp_over_br)
+        L2CA_RemoveFixedChnl (L2CAP_SMP_BR_CID, p_cb->pairing_bda);
+    else
+        L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
+}
+
 /*******************************************************************************
 **
 ** Function         smp_reset_control_value
@@ -556,27 +911,18 @@ void smp_reset_control_value(tSMP_CB *p_cb)
 {
     SMP_TRACE_EVENT("smp_reset_control_value");
     btu_stop_timer (&p_cb->rsp_timer_ent);
-#if SMP_CONFORMANCE_TESTING == TRUE
-
-    SMP_TRACE_EVENT("smp_cb.remove_fixed_channel_disable=%d", smp_cb.remove_fixed_channel_disable);
-    if (!smp_cb.remove_fixed_channel_disable)
-    {
-        L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
-    }
-    else
-    {
-        SMP_TRACE_EVENT("disable the removal of the fixed channel");
-    }
-
+    p_cb->flags = 0;
+    /* set the link idle timer to drop the link when pairing is done
+       usually service discovery will follow authentication complete, to avoid
+       racing condition for a link down/up, set link idle timer to be
+       SMP_LINK_TOUT_MIN to guarantee SMP key exchange */
+    L2CA_SetIdleTimeoutByBdAddr(p_cb->pairing_bda, SMP_LINK_TOUT_MIN, BT_TRANSPORT_LE);
 
-#else
     /* We can tell L2CAP to remove the fixed channel (if it has one) */
-    L2CA_RemoveFixedChnl (L2CAP_SMP_CID, p_cb->pairing_bda);
-
-#endif
+    smp_remove_fixed_channel(p_cb);
     smp_cb_cleanup(p_cb);
-
 }
+
 /*******************************************************************************
 **
 ** Function         smp_proc_pairing_cmpl
@@ -590,6 +936,8 @@ void smp_reset_control_value(tSMP_CB *p_cb)
 void smp_proc_pairing_cmpl(tSMP_CB *p_cb)
 {
     tSMP_EVT_DATA   evt_data = {0};
+    tSMP_CALLBACK   *p_callback = p_cb->p_callback;
+    BD_ADDR         pairing_bda;
 
     SMP_TRACE_DEBUG ("smp_proc_pairing_cmpl ");
 
@@ -607,35 +955,204 @@ void smp_proc_pairing_cmpl(tSMP_CB *p_cb)
     SMP_TRACE_DEBUG ("send SMP_COMPLT_EVT reason=0x%0x sec_level=0x%0x",
                       evt_data.cmplt.reason,
                       evt_data.cmplt.sec_level );
-    if (p_cb->p_callback)
-        (*p_cb->p_callback) (SMP_COMPLT_EVT, p_cb->pairing_bda, &evt_data);
 
-#if 0 /* TESTING CODE : as a master, reencrypt using LTK */
-    if (evt_data.cmplt.reason == 0 && p_cb->role == HCI_ROLE_MASTER)
+    memcpy (pairing_bda, p_cb->pairing_bda, BD_ADDR_LEN);
+
+    smp_reset_control_value(p_cb);
+
+    if (p_callback)
+        (*p_callback) (SMP_COMPLT_EVT, pairing_bda, &evt_data);
+}
+
+/*******************************************************************************
+**
+** Function         smp_command_has_invalid_parameters
+**
+** Description      Checks if the received SMP command has invalid parameters i.e.
+**                  if the command length is valid and the command parameters are
+**                  inside specified range.
+**                  It returns TRUE if the command has invalid parameters.
+**
+** Returns          TRUE if the command has invalid parameters, FALSE otherwise.
+**
+*******************************************************************************/
+BOOLEAN smp_command_has_invalid_parameters(tSMP_CB *p_cb)
+{
+    UINT8 cmd_code = p_cb->rcvd_cmd_code;
+
+    SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, cmd_code);
+
+    if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
+        (cmd_code < SMP_OPCODE_MIN))
     {
-        btm_ble_start_encrypt(p_cb->pairing_bda, FALSE, NULL);
+        SMP_TRACE_WARNING("Somehow received command with the RESERVED code 0x%02x", cmd_code);
+        return TRUE;
     }
-#endif
 
-    smp_reset_control_value(p_cb);
+    if (!(*smp_cmd_len_is_valid[cmd_code])(p_cb))
+        return TRUE;
+
+    if (!(*smp_cmd_param_ranges_are_valid[cmd_code])(p_cb))
+        return TRUE;
+
+    return FALSE;
 }
 
 /*******************************************************************************
 **
-** Function         smp_reject_unexp_pair_req
+** Function         smp_command_has_valid_fixed_length
+**
+** Description      Checks if the received command size is equal to the size
+**                  according to specs.
+**
+** Returns          TRUE if the command size is as expected, FALSE otherwise.
 **
-** Description      send pairing failure to an unexpected pairing request during
+** Note             The command is expected to have fixed length.
+*******************************************************************************/
+BOOLEAN smp_command_has_valid_fixed_length(tSMP_CB *p_cb)
+{
+    UINT8   cmd_code = p_cb->rcvd_cmd_code;
+
+    SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, cmd_code);
+
+    if (p_cb->rcvd_cmd_len != smp_cmd_size_per_spec[cmd_code])
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with invalid length\
+            0x%02x (per spec the length is 0x%02x).",
+            cmd_code, p_cb->rcvd_cmd_len, smp_cmd_size_per_spec[cmd_code]);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_pairing_request_response_parameters_are_valid
+**
+** Description      Validates parameter ranges in the received SMP command
+**                  pairing request or pairing response.
+**                  The parameters to validate:
+**                  IO capability,
+**                  OOB data flag,
+**                  Bonding_flags in AuthReq
+**                  Maximum encryption key size.
+**                  Returns FALSE if at least one of these parameters is out of range.
+**
+*******************************************************************************/
+BOOLEAN smp_pairing_request_response_parameters_are_valid(tSMP_CB *p_cb)
+{
+    UINT8   io_caps = p_cb->peer_io_caps;
+    UINT8   oob_flag = p_cb->peer_oob_flag;
+    UINT8   bond_flag = p_cb->peer_auth_req & 0x03; //0x03 is gen bond with appropriate mask
+    UINT8   enc_size = p_cb->peer_enc_size;
+
+    SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, p_cb->rcvd_cmd_code);
+
+    if (io_caps >= BTM_IO_CAP_MAX)
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with IO Capabilty \
+            value (0x%02x) out of range).",
+            p_cb->rcvd_cmd_code, io_caps);
+        return FALSE;
+    }
+
+    if (!((oob_flag == SMP_OOB_NONE) || (oob_flag == SMP_OOB_PRESENT)))
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with OOB data flag value \
+            (0x%02x) out of range).",
+             p_cb->rcvd_cmd_code, oob_flag);
+        return FALSE;
+    }
+
+    if (!((bond_flag == SMP_AUTH_NO_BOND) || (bond_flag == SMP_AUTH_BOND)))
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Bonding_Flags value (0x%02x)\
+                           out of range).",
+                           p_cb->rcvd_cmd_code, bond_flag);
+        return FALSE;
+    }
+
+    if ((enc_size < SMP_ENCR_KEY_SIZE_MIN) || (enc_size > SMP_ENCR_KEY_SIZE_MAX))
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Maximum Encryption \
+            Key value (0x%02x) out of range).",
+            p_cb->rcvd_cmd_code, enc_size);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_pairing_keypress_notification_is_valid
+**
+** Description      Validates Notification Type parameter range in the received SMP command
+**                  pairing keypress notification.
+**                  Returns FALSE if this parameter is out of range.
+**
+*******************************************************************************/
+BOOLEAN smp_pairing_keypress_notification_is_valid(tSMP_CB *p_cb)
+{
+    tBTM_SP_KEY_TYPE keypress_notification = p_cb->peer_keypress_notification;
+
+    SMP_TRACE_DEBUG("%s for cmd code 0x%02x", __func__, p_cb->rcvd_cmd_code);
+
+    if (keypress_notification >= BTM_SP_KEY_OUT_OF_RANGE)
+    {
+        SMP_TRACE_WARNING("Rcvd from the peer cmd 0x%02x with Pairing Keypress \
+            Notification value (0x%02x) out of range).",
+            p_cb->rcvd_cmd_code, keypress_notification);
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_parameter_unconditionally_valid
+**
+** Description      Always returns TRUE.
+**
+*******************************************************************************/
+BOOLEAN smp_parameter_unconditionally_valid(tSMP_CB *p_cb)
+{
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_parameter_unconditionally_invalid
+**
+** Description      Always returns FALSE.
+**
+*******************************************************************************/
+BOOLEAN smp_parameter_unconditionally_invalid(tSMP_CB *p_cb)
+{
+    return FALSE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_reject_unexpected_pairing_command
+**
+** Description      send pairing failure to an unexpected pairing command during
 **                  an active pairing process.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void smp_reject_unexp_pair_req(BD_ADDR bd_addr)
+void smp_reject_unexpected_pairing_command(BD_ADDR bd_addr)
 {
     BT_HDR *p_buf;
     UINT8   *p;
 
-    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
+    SMP_TRACE_DEBUG ("%s", __FUNCTION__);
+
+    if ((p_buf = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) +\
+        SMP_PAIR_FAIL_SIZE + L2CAP_MIN_OFFSET)) != NULL)
     {
         p = (UINT8 *)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
@@ -649,87 +1166,412 @@ void smp_reject_unexp_pair_req(BD_ADDR bd_addr)
     }
 }
 
-#if SMP_CONFORMANCE_TESTING == TRUE
 /*******************************************************************************
+** Function         smp_select_association_model
 **
-** Function         smp_set_test_confirm_value
+** Description      This function selects association model to use for STK
+**                  generation. Selection is based on both sides' io capability,
+**                  oob data flag and authentication request.
 **
-** Description      This function is called to set the test confirm value
+** Note             If Secure Connections Only mode is required locally then we
+**                  come to this point only if both sides support Secure Connections
+**                  mode, i.e. if p_cb->secure_connections_only_mode_required = TRUE then we come
+**                  to this point only if
+**                      (p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) ==
+**                      (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT) ==
+**                      SMP_SC_SUPPORT_BIT
 **
-** Returns          void
+*******************************************************************************/
+tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB *p_cb)
+{
+    tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+    p_cb->le_secure_connections_mode_is_used = FALSE;
+
+    SMP_TRACE_EVENT("%s", __FUNCTION__);
+    SMP_TRACE_DEBUG("%s p_cb->peer_io_caps = %d p_cb->local_io_capability = %d",
+                       __FUNCTION__, p_cb->peer_io_caps, p_cb->local_io_capability);
+    SMP_TRACE_DEBUG("%s p_cb->peer_oob_flag = %d p_cb->loc_oob_flag = %d",
+                       __FUNCTION__, p_cb->peer_oob_flag, p_cb->loc_oob_flag);
+    SMP_TRACE_DEBUG("%s p_cb->peer_auth_req = 0x%02x p_cb->loc_auth_req = 0x%02x",
+                       __FUNCTION__, p_cb->peer_auth_req, p_cb->loc_auth_req);
+    SMP_TRACE_DEBUG("%s p_cb->secure_connections_only_mode_required = %s",
+                       __FUNCTION__, p_cb->secure_connections_only_mode_required ?
+                                    "TRUE" : "FALSE");
+
+    if ((p_cb->peer_auth_req & SMP_SC_SUPPORT_BIT) && (p_cb->loc_auth_req & SMP_SC_SUPPORT_BIT))
+    {
+        p_cb->le_secure_connections_mode_is_used = TRUE;
+    }
+
+    SMP_TRACE_DEBUG("use_sc_process = %d", p_cb->le_secure_connections_mode_is_used);
+
+    if (p_cb->le_secure_connections_mode_is_used)
+    {
+        model = smp_select_association_model_secure_connections(p_cb);
+    }
+    else
+    {
+        model = smp_select_legacy_association_model(p_cb);
+    }
+    return model;
+}
+
+/*******************************************************************************
+** Function         smp_select_legacy_association_model
+**
+** Description      This function is called to select association mode if at least
+**                  one side doesn't support secure connections.
 **
 *******************************************************************************/
-void smp_set_test_confirm_value(BOOLEAN enable, UINT8 *p_c_val)
+tSMP_ASSO_MODEL smp_select_legacy_association_model(tSMP_CB *p_cb)
 {
-    SMP_TRACE_DEBUG("smp_set_test_confirm_value enable=%d", enable);
-    smp_cb.enable_test_confirm_val = enable;
-    memcpy(smp_cb.test_confirm, p_c_val, BT_OCTET16_LEN);
+    tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* if OOB data is present on both devices, then use OOB association model */
+    if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+        return SMP_MODEL_OOB;
+
+    /* else if neither device requires MITM, then use Just Works association model */
+    if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) && SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+        return SMP_MODEL_ENCRYPTION_ONLY;
+
+    /* otherwise use IO capability to select association model */
+    if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->local_io_capability < SMP_IO_CAP_MAX)
+    {
+        if (p_cb->role == HCI_ROLE_MASTER)
+        {
+            model = smp_association_table[p_cb->role][p_cb->peer_io_caps]
+                                         [p_cb->local_io_capability];
+        }
+        else
+        {
+            model = smp_association_table[p_cb->role][p_cb->local_io_capability]
+                                         [p_cb->peer_io_caps];
+        }
+    }
+
+    return model;
 }
 
+/*******************************************************************************
+** Function         smp_select_association_model_secure_connections
+**
+** Description      This function is called to select association mode if both
+**                  sides support secure connections.
+**
+*******************************************************************************/
+tSMP_ASSO_MODEL smp_select_association_model_secure_connections(tSMP_CB *p_cb)
+{
+    tSMP_ASSO_MODEL model = SMP_MODEL_OUT_OF_RANGE;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+    /* if OOB data is present on at least one device, then use OOB association model */
+    if (p_cb->peer_oob_flag == SMP_OOB_PRESENT || p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+        return SMP_MODEL_SEC_CONN_OOB;
+
+    /* else if neither device requires MITM, then use Just Works association model */
+    if (SMP_NO_MITM_REQUIRED (p_cb->peer_auth_req) && SMP_NO_MITM_REQUIRED(p_cb->loc_auth_req))
+        return SMP_MODEL_SEC_CONN_JUSTWORKS;
+
+    /* otherwise use IO capability to select association model */
+    if (p_cb->peer_io_caps < SMP_IO_CAP_MAX && p_cb->local_io_capability < SMP_IO_CAP_MAX)
+    {
+        if (p_cb->role == HCI_ROLE_MASTER)
+        {
+            model = smp_association_table_sc[p_cb->role][p_cb->peer_io_caps]
+                                            [p_cb->local_io_capability];
+        }
+        else
+        {
+            model = smp_association_table_sc[p_cb->role][p_cb->local_io_capability]
+                                            [p_cb->peer_io_caps];
+        }
+    }
+
+    return model;
+}
 
 /*******************************************************************************
+** Function         smp_reverse_array
 **
-** Function         smp_set_test_confirm_value
+** Description      This function reverses array bytes
 **
-** Description      This function is called to set the test rand value
+*******************************************************************************/
+void smp_reverse_array(UINT8 *arr, UINT8 len)
+{
+    UINT8 i =0, tmp;
+
+    SMP_TRACE_DEBUG("smp_reverse_array");
+
+    for (i = 0; i < len/2; i ++)
+    {
+        tmp = arr[i];
+        arr[i] = arr[len -1 - i];
+        arr[len -1 - i] = tmp;
+    }
+}
+
+/*******************************************************************************
+** Function         smp_calculate_random_input
 **
-** Returns          void
+** Description      This function returns random input value to be used in commitment
+**                  calculation for SC passkey entry association mode
+**                  (if bit["round"] in "random" array == 1 then returns 0x81
+**                   else returns 0x80).
+**
+** Returns          ri value
 **
 *******************************************************************************/
-void smp_set_test_rand_value(BOOLEAN enable, UINT8 *p_c_val)
+UINT8 smp_calculate_random_input(UINT8 *random, UINT8 round)
 {
-    SMP_TRACE_DEBUG("smp_set_test_rand_value enable=%d", enable);
-    smp_cb.enable_test_rand_val = enable;
-    memcpy(smp_cb.test_rand, p_c_val, BT_OCTET16_LEN);
+    UINT8 i = round/8;
+    UINT8 j = round%8;
+    UINT8 ri;
+
+    SMP_TRACE_DEBUG("random: 0x%02x, round: %d, i: %d, j: %d", random[i], round, i, j);
+    ri = ((random[i] >> j) & 1) | 0x80;
+    SMP_TRACE_DEBUG("%s ri=0x%02x", __func__, ri);
+    return ri;
 }
 
+/*******************************************************************************
+** Function         smp_collect_local_io_capabilities
+**
+** Description      This function puts into IOcap array local device
+**                  IOCapability, OOB data, AuthReq.
+**
+** Returns          void
+**
+*******************************************************************************/
+void smp_collect_local_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    iocap[0] = p_cb->local_io_capability;
+    iocap[1] = p_cb->loc_oob_flag;
+    iocap[2] = p_cb->loc_auth_req;
+}
 
 /*******************************************************************************
+** Function         smp_collect_peer_io_capabilities
+**
+** Description      This function puts into IOcap array peer device
+**                  IOCapability, OOB data, AuthReq.
 **
-** Function         smp_set_test_pair_fail_status
+** Returns          void
 **
-** Description      This function is called to set the test fairing fair status
+*******************************************************************************/
+void smp_collect_peer_io_capabilities(UINT8 *iocap, tSMP_CB *p_cb)
+{
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    iocap[0] = p_cb->peer_io_caps;
+    iocap[1] = p_cb->peer_oob_flag;
+    iocap[2] = p_cb->peer_auth_req;
+}
+
+/*******************************************************************************
+** Function         smp_collect_local_ble_address
+**
+** Description      This function puts into le_addr array local device le address:
+**                  le_addr[0-5] = local BD ADDR,
+**                  le_addr[6] = local le address type (PUBLIC/RANDOM).
 **
 ** Returns          void
 **
 *******************************************************************************/
-void smp_set_test_pair_fail_status (BOOLEAN enable, UINT8 status)
+void smp_collect_local_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
 {
-    SMP_TRACE_DEBUG("smp_set_test_confirm_value enable=%d", enable);
-    smp_cb.enable_test_pair_fail = enable;
-    smp_cb.pair_fail_status = status;
+    tBLE_ADDR_TYPE  addr_type = 0;
+    BD_ADDR         bda;
+    UINT8           *p = le_addr;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    BTM_ReadConnectionAddr( p_cb->pairing_bda, bda, &addr_type);
+    BDADDR_TO_STREAM(p, bda);
+    UINT8_TO_STREAM(p, addr_type);
 }
 
 /*******************************************************************************
+** Function         smp_collect_peer_ble_address
 **
-** Function         smp_set_test_pair_fail_status
+** Description      This function puts into le_addr array peer device le address:
+**                  le_addr[0-5] = peer BD ADDR,
+**                  le_addr[6] = peer le address type (PUBLIC/RANDOM).
 **
-** Description      This function is called to disable the removal of fixed channel
-**                  in  smp_reset_control_value
 ** Returns          void
 **
 *******************************************************************************/
-void smp_remove_fixed_channel_disable (BOOLEAN disable)
+void smp_collect_peer_ble_address(UINT8 *le_addr, tSMP_CB *p_cb)
 {
-    SMP_TRACE_DEBUG("smp_remove_fixed_channel_disable disable =%d", disable);
-    smp_cb.remove_fixed_channel_disable = disable;
+    tBLE_ADDR_TYPE  addr_type = 0;
+    BD_ADDR         bda;
+    UINT8           *p = le_addr;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (!BTM_ReadRemoteConnectionAddr(p_cb->pairing_bda, bda, &addr_type))
+    {
+        SMP_TRACE_ERROR("can not collect peer le addr information for unknown device");
+        return;
+    }
+
+    BDADDR_TO_STREAM(p, bda);
+    UINT8_TO_STREAM(p, addr_type);
 }
+
 /*******************************************************************************
+** Function         smp_check_commitment
 **
-** Function         smp_skip_compare_check
+** Description      This function compares peer commitment values:
+**                  - expected (i.e. calculated locally),
+**                  - received from the peer.
 **
-** Description      This function is called to skip the compare value check
+** Returns          TRUE  if the values are the same
+**                  FALSE otherwise
+**
+*******************************************************************************/
+BOOLEAN smp_check_commitment(tSMP_CB *p_cb)
+{
+    BT_OCTET16 expected;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    smp_calculate_peer_commitment(p_cb, expected);
+    print128(expected, (const UINT8 *)"calculated peer commitment");
+    print128(p_cb->remote_commitment, (const UINT8 *)"received peer commitment");
+
+    if (memcmp(p_cb->remote_commitment, expected, BT_OCTET16_LEN))
+    {
+        SMP_TRACE_WARNING("Commitment check fails");
+        return FALSE;
+    }
+
+    SMP_TRACE_DEBUG("Commitment check succeeds");
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_save_secure_connections_long_term_key
+**
+** Description      The function saves SC LTK as BLE key for future use as local
+**                  and/or peer key.
 **
 ** Returns          void
 **
 *******************************************************************************/
-void smp_skip_compare_check(BOOLEAN enable)
+void smp_save_secure_connections_long_term_key(tSMP_CB *p_cb)
 {
-    SMP_TRACE_DEBUG("smp_skip_compare_check enable=%d", enable);
-    smp_cb.skip_test_compare_check = enable;
+    tBTM_LE_LENC_KEYS   lle_key;
+    tBTM_LE_PENC_KEYS   ple_key;
+
+    SMP_TRACE_DEBUG("%s-Save LTK as local LTK key", __func__);
+    memcpy(lle_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    lle_key.div = 0;
+    lle_key.key_size = p_cb->loc_enc_size;
+    lle_key.sec_level = p_cb->sec_level;
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LENC, (tBTM_LE_KEY_VALUE *)&lle_key, TRUE);
+
+    SMP_TRACE_DEBUG("%s-Save LTK as peer LTK key", __func__);
+    ple_key.ediv = 0;
+    memset(ple_key.rand, 0, BT_OCTET8_LEN);
+    memcpy(ple_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+    ple_key.sec_level = p_cb->sec_level;
+    ple_key.key_size  = p_cb->loc_enc_size;
+    btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, (tBTM_LE_KEY_VALUE *)&ple_key, TRUE);
 }
 
-#endif
+/*******************************************************************************
+**
+** Function         smp_calculate_f5_mackey_and_long_term_key
+**
+** Description      The function calculates MacKey and LTK and saves them in CB.
+**                  To calculate MacKey and LTK it calls smp_calc_f5(...).
+**                  MacKey is used in dhkey calculation, LTK is used to encrypt
+**                  the link.
+**
+** Returns          FALSE if out of resources, TRUE otherwise.
+**
+*******************************************************************************/
+BOOLEAN smp_calculate_f5_mackey_and_long_term_key(tSMP_CB *p_cb)
+{
+    UINT8 a[7];
+    UINT8 b[7];
+    UINT8 *p_na;
+    UINT8 *p_nb;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (p_cb->role == HCI_ROLE_MASTER)
+    {
+        smp_collect_local_ble_address(a, p_cb);
+        smp_collect_peer_ble_address(b, p_cb);
+        p_na = p_cb->rand;
+        p_nb = p_cb->rrand;
+    }
+    else
+    {
+        smp_collect_local_ble_address(b, p_cb);
+        smp_collect_peer_ble_address(a, p_cb);
+        p_na = p_cb->rrand;
+        p_nb = p_cb->rand;
+    }
+
+    if(!smp_calculate_f5(p_cb->dhkey, p_na, p_nb, a, b, p_cb->mac_key, p_cb->ltk))
+    {
+        SMP_TRACE_ERROR("%s failed", __func__);
+        return FALSE;
+    }
+
+    SMP_TRACE_EVENT ("%s is completed", __func__);
+    return TRUE;
+}
+
+/*******************************************************************************
+**
+** Function         smp_request_oob_data
+**
+** Description      Requests application to provide OOB data.
+**
+** Returns          TRUE - OOB data has to be provided by application
+**                  FALSE - otherwise (unexpected)
+**
+*******************************************************************************/
+BOOLEAN smp_request_oob_data(tSMP_CB *p_cb)
+{
+    tSMP_OOB_DATA_TYPE req_oob_type = SMP_OOB_INVALID_TYPE;
+
+    SMP_TRACE_DEBUG("%s", __func__);
+
+    if (p_cb->peer_oob_flag == SMP_OOB_PRESENT && p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+    {
+        /* both local and peer rcvd data OOB */
+        req_oob_type = SMP_OOB_BOTH;
+    }
+    else if (p_cb->peer_oob_flag == SMP_OOB_PRESENT)
+    {
+        /* peer rcvd OOB local data, local didn't receive OOB peer data */
+        req_oob_type = SMP_OOB_LOCAL;
+    }
+    else if (p_cb->loc_oob_flag == SMP_OOB_PRESENT)
+    {
+        req_oob_type = SMP_OOB_PEER;
+    }
+
+    SMP_TRACE_DEBUG("req_oob_type = %d", req_oob_type);
+
+    if (req_oob_type == SMP_OOB_INVALID_TYPE)
+        return FALSE;
+
+    p_cb->req_oob_type = req_oob_type;
+    p_cb->cb_evt = SMP_SC_OOB_REQ_EVT;
+    smp_sm_event(p_cb, SMP_TK_REQ_EVT, &req_oob_type);
+
+    return TRUE;
+}
 
 
 #endif
diff --git a/vnd/ble/vendor_ble.c b/vnd/ble/vendor_ble.c
deleted file mode 100644 (file)
index 72c50b3..0000000
+++ /dev/null
@@ -1,754 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2003-2014 Broadcom Corporation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
-**
-**  Name:          vendor_ble.c
-**
-**  Description:   This file contains vendor specific feature for BLE
-**
-******************************************************************************/
-#include <string.h>
-#include "bt_target.h"
-
-#if (BLE_INCLUDED == TRUE)
-#include "bt_types.h"
-#include "hcimsgs.h"
-#include "btu.h"
-#include "vendor_ble.h"
-#include "vendor_hcidefs.h"
-#include "gatt_int.h"
-#include "device/include/controller.h"
-
-/*** This needs to be moved to a VSC control block eventually per coding conventions ***/
-#if VENDOR_DYNAMIC_MEMORY == FALSE
-tBTM_BLE_VENDOR_CB  btm_ble_vendor_cb;
-#endif
-
-static const BD_ADDR     na_bda= {0};
-
-/*******************************************************************************
-**         Resolve Address Using IRK List functions
-*******************************************************************************/
-
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_enq_irk_pending
-**
-** Description      add target address into IRK pending operation queue
-**
-** Parameters       target_bda: target device address
-**                  add_entry: TRUE for add entry, FALSE for remove entry
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_vendor_enq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_bda, UINT8 to_add)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_Q          *p_q = &btm_ble_vendor_cb.irk_pend_q;
-
-    memcpy(p_q->irk_q[p_q->q_next], target_bda, BD_ADDR_LEN);
-    memcpy(p_q->irk_q_random_pseudo[p_q->q_next], psuedo_bda, BD_ADDR_LEN);
-    p_q->irk_q_action[p_q->q_next] = to_add;
-
-    p_q->q_next ++;
-    p_q->q_next %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
-#endif
-    return ;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_find_irk_pending_entry
-**
-** Description      check to see if the action is in pending list
-**
-** Parameters       TRUE: action pending;
-**                  FALSE: new action
-**
-** Returns          void
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_find_irk_pending_entry(BD_ADDR psuedo_addr, UINT8 action)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_Q          *p_q = &btm_ble_vendor_cb.irk_pend_q;
-    UINT8   i;
-
-    for (i = p_q->q_pending; i != p_q->q_next; )
-    {
-        if (memcmp(p_q->irk_q_random_pseudo[i], psuedo_addr, BD_ADDR_LEN) == 0 &&
-            action == p_q->irk_q_action[i])
-            return TRUE;
-
-        i ++;
-        i %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
-    }
-#endif
-    return FALSE;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_deq_irk_pending
-**
-** Description      add target address into IRK pending operation queue
-**
-** Parameters       target_bda: target device address
-**                  add_entry: TRUE for add entry, FALSE for remove entry
-**
-** Returns          void
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_deq_irk_pending(BD_ADDR target_bda, BD_ADDR psuedo_addr)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_Q          *p_q = &btm_ble_vendor_cb.irk_pend_q;
-
-    if (p_q->q_next != p_q->q_pending)
-    {
-        memcpy(target_bda, p_q->irk_q[p_q->q_pending], BD_ADDR_LEN);
-        memcpy(psuedo_addr, p_q->irk_q_random_pseudo[p_q->q_pending], BD_ADDR_LEN);
-
-        p_q->q_pending ++;
-        p_q->q_pending %= btm_cb.cmn_ble_vsc_cb.max_irk_list_sz;
-
-        return TRUE;
-    }
-#endif
-    return FALSE;
-
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_find_irk_entry
-**
-** Description      find IRK entry in local host IRK list by static address
-**
-** Returns          IRK list entry pointer
-**
-*******************************************************************************/
-tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry(BD_ADDR target_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_ENTRY  *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
-    UINT8   i;
-
-    for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
-    {
-        if (p_irk_entry->in_use && memcmp(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN) == 0)
-        {
-            return p_irk_entry ;
-        }
-    }
-#endif
-    return NULL;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_find_irk_entry_by_psuedo_addr
-**
-** Description      find IRK entry in local host IRK list by psuedo address
-**
-** Returns          IRK list entry pointer
-**
-*******************************************************************************/
-tBTM_BLE_IRK_ENTRY * btm_ble_vendor_find_irk_entry_by_psuedo_addr (BD_ADDR psuedo_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_ENTRY  *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
-    UINT8   i;
-
-    if(p_irk_entry == NULL)
-        return NULL;
-
-    for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
-    {
-        if (p_irk_entry->in_use && memcmp(p_irk_entry->psuedo_bda, psuedo_bda, BD_ADDR_LEN) == 0)
-        {
-            return p_irk_entry ;
-        }
-    }
-#endif
-    return NULL;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_alloc_irk_entry
-**
-** Description      allocate IRK entry in local host IRK list
-**
-** Returns          IRK list index
-**
-*******************************************************************************/
-UINT8 btm_ble_vendor_alloc_irk_entry(BD_ADDR target_bda, BD_ADDR pseudo_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_ENTRY  *p_irk_entry = &btm_ble_vendor_cb.irk_list[0];
-    UINT8   i;
-
-    for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++, p_irk_entry++)
-    {
-        if (!p_irk_entry->in_use)
-        {
-            memcpy(p_irk_entry->bd_addr, target_bda, BD_ADDR_LEN);
-            memcpy(p_irk_entry->psuedo_bda, pseudo_bda, BD_ADDR_LEN);
-
-            p_irk_entry->index = i;
-            p_irk_entry->in_use = TRUE;
-
-            return i;
-        }
-    }
-#endif
-    return BTM_CS_IRK_LIST_INVALID;
-}
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_update_irk_list
-**
-** Description      update IRK entry in local host IRK list
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_vendor_update_irk_list(BD_ADDR target_bda, BD_ADDR pseudo_bda, BOOLEAN add)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_IRK_ENTRY   *p_irk_entry = btm_ble_vendor_find_irk_entry(target_bda);
-    UINT8       i;
-
-    if (add)
-    {
-        if (p_irk_entry == NULL)
-        {
-            if ((i = btm_ble_vendor_alloc_irk_entry(target_bda, pseudo_bda)) == BTM_CS_IRK_LIST_INVALID)
-            {
-                BTM_TRACE_ERROR("max IRK capacity reached");
-            }
-        }
-        else
-        {
-            BTM_TRACE_WARNING(" IRK already in queue");
-        }
-    }
-    else
-    {
-        if (p_irk_entry != NULL)
-        {
-            memset(p_irk_entry, 0, sizeof(tBTM_BLE_IRK_ENTRY));
-        }
-        else
-        {
-            BTM_TRACE_ERROR("No IRK exist in list, can not remove");
-        }
-    }
-#endif
-    return ;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_irk_vsc_op_cmpl
-**
-** Description      IRK operation VSC complete handler
-**
-** Parameters
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_vsc_op_cmpl (tBTM_VSC_CMPL *p_params)
-{
-    UINT8  status;
-    UINT8  *p = p_params->p_param_buf, op_subcode;
-    UINT16  evt_len = p_params->param_len;
-    UINT8   i;
-    tBTM_BLE_VENDOR_CB  *p_cb = &btm_ble_vendor_cb;
-    BD_ADDR         target_bda, pseudo_bda, rra;
-
-
-    STREAM_TO_UINT8(status, p);
-
-    evt_len--;
-
-    op_subcode   = *p ++;
-    BTM_TRACE_DEBUG("btm_ble_vendor_irk_vsc_op_cmpl op_subcode = %d", op_subcode);
-    if (evt_len < 1)
-    {
-        BTM_TRACE_ERROR("cannot interpret IRK VSC cmpl callback");
-        return;
-    }
-
-    if (BTM_BLE_META_IRK_ENABLE == op_subcode)
-    {
-        BTM_TRACE_DEBUG("IRK enable: %d, %d", status, op_subcode);
-        return;
-    }
-    else
-    if (op_subcode == BTM_BLE_META_CLEAR_IRK_LIST)
-    {
-        if (status == HCI_SUCCESS)
-        {
-            STREAM_TO_UINT8(p_cb->irk_avail_size, p);
-            p_cb->irk_list_size = 0;
-
-            BTM_TRACE_DEBUG("p_cb->irk_list_size = %d", p_cb->irk_avail_size);
-
-            for (i = 0; i < btm_cb.cmn_ble_vsc_cb.max_irk_list_sz; i ++)
-                memset(&p_cb->irk_list[i], 0, sizeof(tBTM_BLE_IRK_ENTRY));
-        }
-    }
-    else if (op_subcode == BTM_BLE_META_ADD_IRK_ENTRY)
-    {
-        if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
-        {
-            BTM_TRACE_ERROR("no pending IRK operation");
-            return;
-        }
-
-        if (status == HCI_SUCCESS)
-        {
-            STREAM_TO_UINT8(p_cb->irk_avail_size, p);
-            btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, TRUE);
-        }
-        else if (status == 0x07) /* BT_ERROR_CODE_MEMORY_CAPACITY_EXCEEDED  */
-        {
-            p_cb->irk_avail_size = 0;
-            BTM_TRACE_ERROR("IRK Full ");
-        }
-        else
-        {
-            /* give the credit back if invalid parameter failed the operation */
-            p_cb->irk_list_size ++;
-        }
-    }
-    else if (op_subcode == BTM_BLE_META_REMOVE_IRK_ENTRY)
-    {
-        if (!btm_ble_vendor_deq_irk_pending(target_bda, pseudo_bda))
-        {
-            BTM_TRACE_ERROR("no pending IRK operation");
-            return;
-        }
-        if (status == HCI_SUCCESS)
-        {
-            STREAM_TO_UINT8(p_cb->irk_avail_size, p);
-            btm_ble_vendor_update_irk_list(target_bda, pseudo_bda, FALSE);
-        }
-        else
-        {
-            /* give the credit back if invalid parameter failed the operation */
-            if (p_cb->irk_avail_size > 0)
-                p_cb->irk_list_size --;
-        }
-
-    }
-    else if (op_subcode == BTM_BLE_META_READ_IRK_ENTRY)
-    {
-        if (status == HCI_SUCCESS)
-        {
-            //STREAM_TO_UINT8(index, p);
-            p += (1 + 16 + 1); /* skip index, IRK value, address type */
-            STREAM_TO_BDADDR(target_bda, p);
-            STREAM_TO_BDADDR(rra, p);
-            btm_ble_refresh_rra(target_bda, rra);
-        }
-    }
-
-}
-/*******************************************************************************
-**
-** Function         btm_ble_remove_irk_entry
-**
-** Description      This function to remove an IRK entry from the list
-**
-** Parameters       ble_addr_type: address type
-**                  ble_addr: LE adddress
-**
-** Returns          status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_remove_irk_entry(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8           param[20], *p;
-    tBTM_STATUS     st;
-    tBTM_BLE_VENDOR_CB  *p_cb = &btm_ble_vendor_cb;
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return BTM_MODE_UNSUPPORTED;
-
-    p = param;
-    memset(param, 0, 20);
-
-    UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
-    UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
-    BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
-
-    if ((st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                    BTM_BLE_META_REMOVE_IRK_LEN,
-                                    param,
-                                    btm_ble_vendor_irk_vsc_op_cmpl))
-        != BTM_NO_RESOURCES)
-    {
-        btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, FALSE);
-        p_cb->irk_list_size --;
-    }
-
-    return st;
-#endif
-    return BTM_MODE_UNSUPPORTED;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_clear_irk_list
-**
-** Description      This function clears the IRK entry list
-**
-** Parameters       None.
-**
-** Returns          status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_vendor_clear_irk_list(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8           param[20], *p;
-    tBTM_STATUS     st;
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return BTM_MODE_UNSUPPORTED;
-
-    p = param;
-    memset(param, 0, 20);
-
-    UINT8_TO_STREAM(p, BTM_BLE_META_CLEAR_IRK_LIST);
-
-    st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                    BTM_BLE_META_CLEAR_IRK_LEN,
-                                    param,
-                                    btm_ble_vendor_irk_vsc_op_cmpl);
-
-    return st;
-#endif
-    return BTM_MODE_UNSUPPORTED;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_read_irk_entry
-**
-** Description      This function read an IRK entry by index
-**
-** Parameters       entry index.
-**
-** Returns          status
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8           param[20], *p;
-    tBTM_STATUS     st = BTM_UNKNOWN_ADDR;
-    tBTM_BLE_IRK_ENTRY *p_entry;
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return BTM_MODE_UNSUPPORTED;
-
-    if ((p_entry = btm_ble_vendor_find_irk_entry(target_bda)) == NULL)
-        return st;
-
-    p = param;
-    memset(param, 0, 20);
-
-    UINT8_TO_STREAM(p, BTM_BLE_META_READ_IRK_ENTRY);
-    UINT8_TO_STREAM(p, p_entry->index);
-
-    st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                    BTM_BLE_META_READ_IRK_LEN,
-                                    param,
-                                    btm_ble_vendor_irk_vsc_op_cmpl);
-
-    return st;
-#endif
-    return BTM_MODE_UNSUPPORTED;
-}
-
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_enable_irk_list_known_dev
-**
-** Description      This function add all known device with random address into
-**                  IRK list.
-**
-** Parameters       enable: enable IRK list with known device, or disable it
-**
-** Returns          status
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8               i;
-    UINT8               count = 0;
-    tBTM_SEC_DEV_REC    *p_dev_rec = &btm_cb.sec_dev_rec[0];
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return;
-
-    /* add all known device with random address into IRK list */
-    for (i = 0; i < BTM_SEC_MAX_DEVICE_RECORDS; i ++, p_dev_rec ++)
-    {
-        if (p_dev_rec->sec_flags & BTM_SEC_IN_USE)
-        {
-            if (btm_ble_vendor_irk_list_load_dev(p_dev_rec))
-                count ++;
-        }
-    }
-
-    if ((count > 0 && enable) || !enable)
-        btm_ble_vendor_enable_irk_feature(enable);
-#endif
-    return ;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_irk_list_load_dev
-**
-** Description      This function add a device which is using RPA into white list
-**
-** Parameters
-**
-** Returns          status
-**
-*******************************************************************************/
-BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8           param[40], *p;
-    tBTM_BLE_VENDOR_CB  *p_cb = &btm_ble_vendor_cb;
-    BOOLEAN         rt = FALSE;
-    tBTM_BLE_IRK_ENTRY  *p_irk_entry = NULL;
-    BTM_TRACE_DEBUG ("btm_ble_vendor_irk_list_load_dev:max_irk_size=%d", p_cb->irk_avail_size);
-    memset(param, 0, 40);
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return FALSE;
-
-    if (p_dev_rec != NULL && /* RPA is being used and PID is known */
-        (p_dev_rec->ble.key_type & BTM_LE_KEY_PID) != 0)
-    {
-
-        if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) == NULL &&
-            btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, TRUE) == FALSE)
-        {
-
-            if (p_cb->irk_avail_size > 0)
-            {
-                p = param;
-
-                UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
-                ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
-                UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
-                BDADDR_TO_STREAM(p,p_dev_rec->ble.static_addr);
-
-                if (BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC,
-                                                BTM_BLE_META_ADD_IRK_LEN,
-                                                param,
-                                                btm_ble_vendor_irk_vsc_op_cmpl)
-                       != BTM_NO_RESOURCES)
-                {
-                    btm_ble_vendor_enq_irk_pending(p_dev_rec->ble.static_addr, p_dev_rec->bd_addr, TRUE);
-                    p_cb->irk_list_size ++;
-                    rt = TRUE;
-
-                    btm_ble_vendor_enable_irk_feature(TRUE);
-                }
-            }
-        }
-        else
-        {
-            BTM_TRACE_ERROR("Device already in IRK list");
-            rt = TRUE;
-        }
-    }
-    else
-    {
-        BTM_TRACE_DEBUG("Device not a RPA enabled device");
-    }
-    return rt;
-#endif
-    return FALSE;
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_irk_list_remove_dev
-**
-** Description      This function remove the device from IRK list
-**
-** Parameters
-**
-** Returns          status
-**
-*******************************************************************************/
-void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    tBTM_BLE_VENDOR_CB  *p_cs_cb = &btm_ble_vendor_cb;
-    tBTM_BLE_IRK_ENTRY *p_irk_entry;
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return;
-
-    if ((p_irk_entry = btm_ble_vendor_find_irk_entry_by_psuedo_addr(p_dev_rec->bd_addr)) != NULL &&
-        btm_ble_vendor_find_irk_pending_entry(p_dev_rec->bd_addr, FALSE) == FALSE)
-    {
-        btm_ble_remove_irk_entry(p_dev_rec);
-    }
-    else
-    {
-        BTM_TRACE_ERROR("Device not in IRK list");
-    }
-
-    if (p_cs_cb->irk_list_size == 0)
-        btm_ble_vendor_enable_irk_feature(FALSE);
-#endif
-}
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_disable_irk_list
-**
-** Description      disable LE resolve address feature
-**
-** Parameters
-**
-** Returns          status
-**
-*******************************************************************************/
-void btm_ble_vendor_disable_irk_list(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    btm_ble_vendor_enable_irk_feature(FALSE);
-#endif
-}
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_enable_irk_feature
-**
-** Description      This function is called to enable or disable the RRA
-**                  offloading feature.
-**
-** Parameters       enable: enable or disable the RRA offloading feature
-**
-** Returns          BTM_SUCCESS if successful
-**
-*******************************************************************************/
-tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    UINT8           param[20], *p;
-    tBTM_STATUS     st = BTM_WRONG_MODE;
-    tBTM_BLE_PF_COUNT *p_bda_filter;
-
-    if (btm_cb.cmn_ble_vsc_cb.max_irk_list_sz == 0)
-        return BTM_MODE_UNSUPPORTED;
-
-    if (btm_ble_vendor_cb.enable != enable)
-    {
-        p = param;
-        memset(param, 0, 20);
-
-        /* select feature based on control block settings */
-        UINT8_TO_STREAM(p, BTM_BLE_META_IRK_ENABLE);
-        UINT8_TO_STREAM(p, enable ? 0x01 : 0x00);
-
-        st = BTM_VendorSpecificCommand (HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_IRK_ENABLE_LEN,
-                                        param, btm_ble_vendor_irk_vsc_op_cmpl);
-
-        btm_ble_vendor_cb.enable = enable;
-    }
-
-    return st;
-#endif
-    return BTM_MODE_UNSUPPORTED;
-}
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_init
-**
-** Description      Initialize customer specific feature information in host stack
-**
-** Parameters  Max IRK list size
-**                   Max filter supported
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_vendor_init(UINT8 max_irk_list_sz)
-{
-    memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
-
-#if BLE_PRIVACY_SPT == TRUE
-    if (max_irk_list_sz > 0)
-    {
-        btm_ble_vendor_cb.irk_list =  (tBTM_BLE_IRK_ENTRY*)GKI_getbuf (sizeof (tBTM_BLE_IRK_ENTRY)
-                                                                        * max_irk_list_sz);
-        btm_ble_vendor_cb.irk_pend_q.irk_q =  (BD_ADDR*) GKI_getbuf (sizeof (BD_ADDR) *
-                                                                     max_irk_list_sz);
-        btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo = (BD_ADDR*)GKI_getbuf (sizeof (BD_ADDR) *
-                                                                                 max_irk_list_sz);
-        btm_ble_vendor_cb.irk_pend_q.irk_q_action = (UINT8*) GKI_getbuf (max_irk_list_sz);
-    }
-
-    btm_ble_vendor_cb.irk_avail_size = max_irk_list_sz;
-#endif
-}
-
-/*******************************************************************************
-**
-** Function         btm_ble_vendor_cleanup
-**
-** Description      Cleanup VSC specific dynamic memory
-**
-** Parameters
-**
-** Returns          void
-**
-*******************************************************************************/
-void btm_ble_vendor_cleanup(void)
-{
-#if BLE_PRIVACY_SPT == TRUE
-    if (btm_ble_vendor_cb.irk_list)
-        GKI_freebuf(btm_ble_vendor_cb.irk_list);
-
-    if (btm_ble_vendor_cb.irk_pend_q.irk_q)
-       GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q);
-
-    if (btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo)
-        GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_random_pseudo);
-
-    if (btm_ble_vendor_cb.irk_pend_q.irk_q_action)
-        GKI_freebuf(btm_ble_vendor_cb.irk_pend_q.irk_q_action);
-#endif
-    memset(&btm_ble_vendor_cb, 0, sizeof(tBTM_BLE_VENDOR_CB));
-}
-
-#endif
-
diff --git a/vnd/include/vendor_ble.h b/vnd/include/vendor_ble.h
deleted file mode 100644 (file)
index b235ea9..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-/******************************************************************************
- *
- *  Copyright (C) 2003-2014 Broadcom Corporation
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-/*****************************************************************************
-**
-**  Name:          vendor_ble.h
-**
-**  Description:   This file contains vendor specific feature header
-**                 for BLE
-******************************************************************************/
-#ifndef VENDOR_BLE_H
-#define VENDOR_BLE_H
-
-#include "btm_int.h"
-#include "btm_ble_api.h"
-#include "vendor_api.h"
-
-/* RPA offload VSC specifics */
-#define BTM_BLE_META_IRK_ENABLE         0x01
-#define BTM_BLE_META_ADD_IRK_ENTRY      0x02
-#define BTM_BLE_META_REMOVE_IRK_ENTRY   0x03
-#define BTM_BLE_META_CLEAR_IRK_LIST     0x04
-#define BTM_BLE_META_READ_IRK_ENTRY     0x05
-#define BTM_BLE_META_CS_RESOLVE_ADDR    0x00000001
-#define BTM_BLE_IRK_ENABLE_LEN          2
-
-/* BLE meta vsc header: 1 bytes of sub_code, 1 byte of PCF action */
-#define BTM_BLE_META_HDR_LENGTH     3
-#define BTM_BLE_PF_FEAT_SEL_LEN     18
-#define BTM_BLE_PCF_ENABLE_LEN      2
-#define BTM_BLE_META_ADDR_LEN       7
-#define BTM_BLE_META_UUID_LEN       40
-#define BTM_BLE_META_ADD_IRK_LEN        24
-#define BTM_BLE_META_REMOVE_IRK_LEN     8
-#define BTM_BLE_META_CLEAR_IRK_LEN      1
-#define BTM_BLE_META_READ_IRK_LEN       2
-#define BTM_BLE_META_ADD_WL_ATTR_LEN    9
-
-#define BTM_BLE_PF_SELECT_NONE              0
-#define BTM_BLE_PF_ADDR_FILTER_BIT          BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_ADDR_FILTER)
-#define BTM_BLE_PF_SRVC_DATA_BIT            BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA)
-#define BTM_BLE_PF_SRVC_UUID_BIT            BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_UUID)
-#define BTM_BLE_PF_SRVC_SOL_UUID_BIT        BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_SOL_UUID)
-#define BTM_BLE_PF_LOCAL_NAME_BIT           BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_LOCAL_NAME)
-#define BTM_BLE_PF_MANU_DATA_BIT            BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_MANU_DATA)
-#define BTM_BLE_PF_SRVC_DATA_PATTERN_BIT    BTM_BLE_PF_BIT_TO_MASK(BTM_BLE_PF_SRVC_DATA_PATTERN)
-typedef UINT8 tBTM_BLE_PF_SEL_MASK;
-
-#define BTM_BLE_MAX_FILTER_COUNTER  (BTM_BLE_MAX_ADDR_FILTER + 1) /* per device filter + one generic filter indexed by 0 */
-
-#define BTM_CS_IRK_LIST_INVALID     0xff
-
-typedef struct
-{
-    BOOLEAN         in_use;
-    BD_ADDR         bd_addr;        /* must be the address used in controller */
-    BD_ADDR         psuedo_bda;        /* the random pseudo address */
-    UINT8           index;
-}tBTM_BLE_IRK_ENTRY;
-
-
-typedef struct
-{
-    BD_ADDR         *irk_q;
-    BD_ADDR         *irk_q_random_pseudo;
-    UINT8           *irk_q_action;
-    UINT8           q_next;
-    UINT8           q_pending;
-} tBTM_BLE_IRK_Q;
-
-/* control block for BLE customer specific feature */
-typedef struct
-{
-    BOOLEAN             enable;
-
-    UINT8               op_type;
-    tBLE_BD_ADDR        cur_filter_target;
-
-    UINT8               irk_list_size;
-    UINT8               irk_avail_size;
-    tBTM_BLE_IRK_ENTRY  *irk_list;
-    tBTM_BLE_IRK_Q      irk_pend_q;
-    UINT8                max_filter_supported;
-    tBTM_BLE_PF_CMPL_CBACK *p_scan_pf_cback;
-}tBTM_BLE_VENDOR_CB;
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-#if VENDOR_DYNAMIC_MEMORY == FALSE
-extern tBTM_BLE_VENDOR_CB  btm_ble_vendor_cb;
-#else
-extern tBTM_BLE_VENDOR_CB *btm_ble_vendor_ptr;
-#define btm_ble_vendor_cb (*btm_ble_vendor_ptr)
-#endif
-
-extern void btm_ble_vendor_irk_list_known_dev(BOOLEAN enable);
-extern tBTM_STATUS btm_ble_read_irk_entry(BD_ADDR target_bda);
-extern void btm_ble_vendor_disable_irk_list(void);
-extern BOOLEAN btm_ble_vendor_irk_list_load_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern void btm_ble_vendor_irk_list_remove_dev(tBTM_SEC_DEV_REC *p_dev_rec);
-extern tBTM_STATUS btm_ble_enable_vendor_feature (BOOLEAN enable, UINT32 feature_bit);
-
-extern void btm_ble_vendor_init(UINT8 max_irk_list_sz);
-extern void btm_ble_vendor_cleanup(void);
-extern BOOLEAN btm_ble_vendor_write_device_wl_attribute (tBLE_ADDR_TYPE addr_type, BD_ADDR bd_addr, UINT8 attribute);
-extern tBTM_STATUS btm_ble_vendor_enable_irk_feature(BOOLEAN enable);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif