first cut at LL privacy

Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/commit/d6bbacbd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/tree/d6bbacbd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/diff/d6bbacbd

Branch: refs/heads/develop
Commit: d6bbacbd95693af7bfdefef6ccdc4863dd6c53c9
Parents: 34e4509
Author: William San Filippo <[email protected]>
Authored: Wed May 18 15:59:54 2016 -0700
Committer: Paul Dietrich <[email protected]>
Committed: Thu Jun 2 14:12:15 2016 -0700

----------------------------------------------------------------------
 apps/bletest/src/bletest_hci.c                  |  32 ++
 apps/bletest/src/bletest_priv.h                 |   4 +
 apps/bletest/src/main.c                         | 125 ++++++--
 apps/bletiny/src/main.c                         |   2 +-
 .../controller/include/controller/ble_ll.h      |   2 +-
 .../controller/include/controller/ble_ll_adv.h  |   6 +
 .../controller/include/controller/ble_ll_conn.h |   3 +
 .../include/controller/ble_ll_resolv.h          |  27 +-
 .../controller/include/controller/ble_ll_scan.h |  14 +-
 .../include/controller/ble_ll_whitelist.h       |   2 +-
 net/nimble/controller/src/ble_ll.c              |  16 +-
 net/nimble/controller/src/ble_ll_adv.c          | 227 +++++++++-----
 net/nimble/controller/src/ble_ll_conn.c         | 247 ++++++++++++----
 net/nimble/controller/src/ble_ll_conn_hci.c     | 100 ++++---
 net/nimble/controller/src/ble_ll_conn_priv.h    |   3 +-
 net/nimble/controller/src/ble_ll_hci.c          |   2 +-
 net/nimble/controller/src/ble_ll_resolv.c       | 148 ++++++++--
 net/nimble/controller/src/ble_ll_scan.c         | 296 ++++++++++++++-----
 net/nimble/controller/src/ble_ll_whitelist.c    | 105 ++++---
 net/nimble/drivers/nrf51/include/ble/xcvr.h     |   6 +
 net/nimble/drivers/nrf51/src/ble_hw.c           |   9 +-
 net/nimble/drivers/nrf51/src/ble_phy.c          |   3 +-
 net/nimble/drivers/nrf52/include/ble/xcvr.h     |   8 +-
 net/nimble/drivers/nrf52/src/ble_hw.c           |   9 +-
 net/nimble/drivers/nrf52/src/ble_phy.c          |   2 +
 net/nimble/host/src/host_dbg.c                  |  23 +-
 net/nimble/include/nimble/ble.h                 |   2 +-
 net/nimble/include/nimble/hci_common.h          |   4 +
 28 files changed, 1054 insertions(+), 373 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/apps/bletest/src/bletest_hci.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/bletest_hci.c b/apps/bletest/src/bletest_hci.c
index 1eee29c..c227cc0 100755
--- a/apps/bletest/src/bletest_hci.c
+++ b/apps/bletest/src/bletest_hci.c
@@ -580,4 +580,36 @@ bletest_hci_le_create_connection(struct hci_create_conn 
*hcc)
     return rc;
 }
 
+int
+bletest_hci_le_add_resolv_list(uint8_t *local_irk, uint8_t *peer_irk,
+                               uint8_t *peer_ident_addr, uint8_t addr_type)
+{
+    int rc;
+    struct hci_add_dev_to_resolving_list padd;
+    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_ADD_TO_RESOLV_LIST_LEN];
+
+    padd.addr_type = addr_type;
+    memcpy(padd.addr, peer_ident_addr, BLE_DEV_ADDR_LEN);
+    swap_buf(padd.local_irk, local_irk, 16);
+    swap_buf(padd.peer_irk, peer_irk, 16);
+    rc = host_hci_cmd_add_device_to_resolving_list(&padd, buf, sizeof buf);
+    if (!rc) {
+        rc = ble_hci_cmd_tx_empty_ack(buf);
+    }
+    return rc;
+}
+
+int
+bletest_hci_le_enable_resolv_list(uint8_t enable)
+{
+    int rc;
+    uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_ADDR_RESOL_ENA_LEN];
+
+
+    rc = host_hci_cmd_set_addr_resolution_enable(enable, buf, sizeof buf);
+    if (!rc) {
+        rc = ble_hci_cmd_tx_empty_ack(buf);
+    }
+    return rc;
+}
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/apps/bletest/src/bletest_priv.h
----------------------------------------------------------------------
diff --git a/apps/bletest/src/bletest_priv.h b/apps/bletest/src/bletest_priv.h
index 4a00aef..28f3074 100644
--- a/apps/bletest/src/bletest_priv.h
+++ b/apps/bletest/src/bletest_priv.h
@@ -58,5 +58,9 @@ int bletest_hci_le_create_connection(struct hci_create_conn 
*hcc);
 int bletest_hci_le_set_scan_params(uint8_t scan_type, uint16_t scan_itvl,
                                    uint16_t scan_window, uint8_t own_addr_type,
                                    uint8_t filter_policy);
+int bletest_hci_le_add_resolv_list(uint8_t *local_irk, uint8_t *peer_irk,
+                                   uint8_t *peer_ident_addr, uint8_t 
addr_type);
+int bletest_hci_le_enable_resolv_list(uint8_t enable);
+
 
 #endif  /* H_BLETEST_PRIV_*/

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index 5a073c9..f4e4424 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -97,28 +97,38 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_ROLE_ADVERTISER         (0)
 #define BLETEST_ROLE_SCANNER            (1)
 #define BLETEST_ROLE_INITIATOR          (2)
-#define BLETEST_CFG_ROLE                (BLETEST_ROLE_INITIATOR)
-//#define BLETEST_CFG_ROLE                (BLETEST_ROLE_ADVERTISER)
+
+//#define BLETEST_CFG_ROLE                (BLETEST_ROLE_INITIATOR)
+#define BLETEST_CFG_ROLE                (BLETEST_ROLE_ADVERTISER)
 //#define BLETEST_CFG_ROLE                (BLETEST_ROLE_SCANNER)
-#define BLETEST_CFG_ADV_OWN_ADDR_TYPE   (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
+
+/* Advertiser config */
+#define BLETEST_CFG_ADV_OWN_ADDR_TYPE   (BLE_HCI_ADV_OWN_ADDR_PRIV_PUB)
 #define BLETEST_CFG_ADV_PEER_ADDR_TYPE  (BLE_HCI_ADV_PEER_ADDR_PUBLIC)
-#define BLETEST_CFG_FILT_DUP_ADV        (0)
+#define BLETEST_CFG_FILT_DUP_ADV        (1)
 #define BLETEST_CFG_ADV_ITVL            (60000 / BLE_HCI_ADV_ITVL)
 #define BLETEST_CFG_ADV_TYPE            BLE_HCI_ADV_TYPE_ADV_IND
 #define BLETEST_CFG_ADV_FILT_POLICY     (BLE_HCI_ADV_FILT_NONE)
+
+/* Scan config */
 #define BLETEST_CFG_SCAN_ITVL           (700000 / BLE_HCI_SCAN_ITVL)
 #define BLETEST_CFG_SCAN_WINDOW         (700000 / BLE_HCI_SCAN_ITVL)
-#define BLETEST_CFG_SCAN_TYPE           (BLE_HCI_SCAN_TYPE_ACTIVE)
+#define BLETEST_CFG_SCAN_TYPE           (BLE_HCI_SCAN_TYPE_PASSIVE)
+#define BLETEST_CFG_SCAN_OWN_ADDR_TYPE  (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
 #define BLETEST_CFG_SCAN_FILT_POLICY    (BLE_HCI_SCAN_FILT_NO_WL)
+
+/* Connection config */
 #define BLETEST_CFG_CONN_ITVL           (128)  /* in 1.25 msec increments */
 #define BLETEST_CFG_SLAVE_LATENCY       (0)
 #define BLETEST_CFG_INIT_FILTER_POLICY  (BLE_HCI_CONN_FILT_NO_WL)
 #define BLETEST_CFG_CONN_SPVN_TMO       (1000)  /* 20 seconds */
 #define BLETEST_CFG_MIN_CE_LEN          (6)
 #define BLETEST_CFG_MAX_CE_LEN          (BLETEST_CFG_CONN_ITVL)
-#define BLETEST_CFG_CONN_PEER_ADDR_TYPE (BLE_HCI_CONN_PEER_ADDR_PUBLIC)
+#define BLETEST_CFG_CONN_PEER_ADDR_TYPE (BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT)
 #define BLETEST_CFG_CONN_OWN_ADDR_TYPE  (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
 #define BLETEST_CFG_CONCURRENT_CONNS    (1)
+
+/* Test packet config */
 #define BLETEST_CFG_RAND_PKT_SIZE       (1)
 #define BLETEST_CFG_SUGG_DEF_TXOCTETS   (251)
 #define BLETEST_CFG_SUGG_DEF_TXTIME     \
@@ -176,6 +186,18 @@ const uint8_t g_ble_ll_encrypt_test_encrypted_data[16] =
     0x05, 0x8e, 0x3b, 0x8e, 0x27, 0xc2, 0xc6, 0x66
 };
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+uint8_t g_bletest_adv_irk[16] = {
+    0xec, 0x02, 0x34, 0xa3, 0x57, 0xc8, 0xad, 0x05,
+    0x34, 0x10, 0x10, 0xa6, 0x0a, 0x39, 0x7d, 0x9b
+};
+
+uint8_t g_bletest_init_irk[16] = {
+    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+    0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
+};
+#endif
+
 #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1)
 /* LTK 0x4C68384139F574D836BCF34E9DFB01BF */
 const uint8_t g_bletest_LTK[16] =
@@ -242,7 +264,7 @@ bletest_inc_adv_pkt_num(void)
  * @return uint8_t
  */
 uint8_t
-bletest_set_adv_data(uint8_t *dptr)
+bletest_set_adv_data(uint8_t *dptr, uint8_t *addr)
 {
     uint8_t len;
 
@@ -282,7 +304,7 @@ bletest_set_adv_data(uint8_t *dptr)
     dptr[0] = 0x08;
     dptr[1] = 0x1B;
     dptr[2] = 0x00;
-    memcpy(dptr + 3, g_dev_addr, BLE_DEV_ADDR_LEN);
+    memcpy(dptr + 3, addr, BLE_DEV_ADDR_LEN);
     len += 9;
 
     g_host_adv_len = len;
@@ -295,28 +317,50 @@ void
 bletest_init_advertising(void)
 {
     int rc;
+    int set_peer_addr;
     uint8_t adv_len;
+    uint8_t *addr;
     uint8_t rand_addr[BLE_DEV_ADDR_LEN];
     struct hci_adv_params adv;
 
     /* Just zero out advertising */
+    set_peer_addr = 0;
     memset(&adv, 0, sizeof(struct hci_adv_params));
 
+    /* If we are using a random address, we need to set it */
+    adv.own_addr_type = BLETEST_CFG_ADV_OWN_ADDR_TYPE;
+    if (adv.own_addr_type & 1) {
+        memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
+        rand_addr[5] |= 0xc0;
+        rc = bletest_hci_le_set_rand_addr(rand_addr);
+        assert(rc == 0);
+        addr = rand_addr;
+    } else {
+        addr = g_dev_addr;
+    }
+
     /* Set advertising parameters */
     adv.adv_type = BLETEST_CFG_ADV_TYPE;
     adv.adv_channel_map = 0x07;
     adv.adv_filter_policy = BLETEST_CFG_ADV_FILT_POLICY;
-    adv.own_addr_type = BLETEST_CFG_ADV_OWN_ADDR_TYPE;
     adv.peer_addr_type = BLETEST_CFG_ADV_PEER_ADDR_TYPE;
     if ((adv.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) ||
         (adv.adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) {
+        set_peer_addr = 1;
+        adv_len = 0;
+    } else {
+        adv_len = bletest_set_adv_data(&g_host_adv_data[0], addr);
+    }
+
+    if (adv.own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        set_peer_addr = 1;
+    }
+
+    if (set_peer_addr) {
         memcpy(adv.peer_addr, g_bletest_cur_peer_addr, BLE_DEV_ADDR_LEN);
         if (adv.peer_addr_type == BLE_HCI_ADV_PEER_ADDR_RANDOM) {
             adv.peer_addr[5] |= 0xc0;
         }
-        adv_len = 0;
-    } else {
-        adv_len = bletest_set_adv_data(&g_host_adv_data[0]);
     }
 
     console_printf("Trying to connect to %x.%x.%x.%x.%x.%x\n",
@@ -335,13 +379,18 @@ bletest_init_advertising(void)
     rc = bletest_hci_le_set_adv_params(&adv);
     assert(rc == 0);
 
-    /* If we are using a random address, we need to set it */
-    if (adv.own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-        memcpy(rand_addr, g_dev_addr, BLE_DEV_ADDR_LEN);
-        rand_addr[5] |= 0xc0;
-        rc = bletest_hci_le_set_rand_addr(rand_addr);
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    if (adv.own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        rc = bletest_hci_le_add_resolv_list(g_bletest_adv_irk,
+                                            g_bletest_init_irk,
+                                            adv.peer_addr,
+                                            adv.peer_addr_type);
+        assert(rc == 0);
+
+        rc = bletest_hci_le_enable_resolv_list(1);
         assert(rc == 0);
     }
+#endif
 
     /* Set advertising data */
     if (adv_len != 0) {
@@ -360,29 +409,45 @@ void
 bletest_init_scanner(void)
 {
     int rc;
+    uint8_t own_addr_type;
     uint8_t dev_addr[BLE_DEV_ADDR_LEN];
     uint8_t buf[BLE_HCI_CMD_HDR_LEN + BLE_HCI_SET_SCAN_PARAM_LEN];
-    uint8_t filter_policy;
+    uint8_t add_whitelist;
 
+    own_addr_type = BLETEST_CFG_SCAN_OWN_ADDR_TYPE;
     rc = host_hci_cmd_build_le_set_scan_params(BLETEST_CFG_SCAN_TYPE,
                                                BLETEST_CFG_SCAN_ITVL,
                                                BLETEST_CFG_SCAN_WINDOW,
-                                               BLE_HCI_ADV_OWN_ADDR_PUBLIC,
+                                               BLETEST_CFG_SCAN_OWN_ADDR_TYPE,
                                                BLETEST_CFG_SCAN_FILT_POLICY,
                                                buf, sizeof buf);
     assert(rc == 0);
     rc = ble_hci_cmd_tx_empty_ack(buf);
     if (rc == 0) {
-        filter_policy = BLETEST_CFG_SCAN_FILT_POLICY;
-        if (filter_policy & 1) {
-            /* Add some whitelist addresses */
+        add_whitelist = BLETEST_CFG_SCAN_FILT_POLICY;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+        if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+            rc = bletest_hci_le_add_resolv_list(g_bletest_init_irk,
+                                                g_bletest_adv_irk,
+                                                g_bletest_cur_peer_addr,
+                                                
BLETEST_CFG_ADV_PEER_ADDR_TYPE);
+            assert(rc == 0);
+
+            rc = bletest_hci_le_enable_resolv_list(1);
+            assert(rc == 0);
+
+            add_whitelist = 0;
+        }
+#endif
+        if (add_whitelist & 1) {
+            /* Add peer to whitelist */
             dev_addr[0] = 0x00;
             dev_addr[1] = 0x00;
             dev_addr[2] = 0x00;
             dev_addr[3] = 0x88;
             dev_addr[4] = 0x88;
             dev_addr[5] = 0x08;
-            rc = bletest_hci_le_add_to_whitelist(dev_addr, 
BLE_ADDR_TYPE_PUBLIC);
+            rc = 
bletest_hci_le_add_to_whitelist(dev_addr,BLE_ADDR_TYPE_PUBLIC);
             assert(rc == 0);
         }
     }
@@ -448,6 +513,20 @@ bletest_init_initiator(void)
         assert(rc == 0);
     }
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+        if ((hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) ||
+            (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM)) {
+            rc = bletest_hci_le_add_resolv_list(g_bletest_init_irk,
+                                                g_bletest_adv_irk,
+                                                g_bletest_cur_peer_addr,
+                                                
BLETEST_CFG_ADV_PEER_ADDR_TYPE);
+            assert(rc == 0);
+
+            rc = bletest_hci_le_enable_resolv_list(1);
+            assert(rc == 0);
+        }
+#endif
+
     rc = bletest_hci_le_create_connection(hcc);
     assert(rc == 0);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/apps/bletiny/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletiny/src/main.c b/apps/bletiny/src/main.c
index 47394b3..3657cc3 100755
--- a/apps/bletiny/src/main.c
+++ b/apps/bletiny/src/main.c
@@ -73,7 +73,7 @@ uint8_t g_host_adv_len;
 static uint8_t bletiny_addr[6] = {0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a};
 
 /* Create a mbuf pool of BLE mbufs */
-#define MBUF_NUM_MBUFS      (12)
+#define MBUF_NUM_MBUFS      (16)
 #define MBUF_BUF_SIZE       OS_ALIGN(BLE_MBUF_PAYLOAD_SIZE, 4)
 #define MBUF_MEMBLOCK_SIZE  (MBUF_BUF_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD)
 #define MBUF_MEMPOOL_SIZE   OS_MEMPOOL_SIZE(MBUF_NUM_MBUFS, MBUF_MEMBLOCK_SIZE)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll.h 
b/net/nimble/controller/include/controller/ble_ll.h
index 9a4014c..81cba53 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -299,7 +299,7 @@ int ble_ll_is_valid_random_addr(uint8_t *addr);
 uint16_t ble_ll_pdu_tx_time_get(uint16_t len);
 
 /* Is this address a resolvable private address? */
-int ble_ll_is_resolvable_priv_addr(uint8_t *addr);
+int ble_ll_is_rpa(uint8_t *addr, uint8_t addr_type);
 
 /* Is 'addr' our device address? 'addr_type' is public (0) or random (!=0) */
 int ble_ll_is_our_devaddr(uint8_t *addr, int addr_type);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll_adv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_adv.h 
b/net/nimble/controller/include/controller/ble_ll_adv.h
index 5a5d607..33a73ab 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -116,6 +116,12 @@ int ble_ll_adv_set_adv_params(uint8_t *cmd);
 int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen);
 
 /*---- API used by BLE LL ----*/
+/* Returns local resolvable private address */
+uint8_t *ble_ll_adv_get_local_rpa(void);
+
+/* Returns peer resolvable private address */
+uint8_t *ble_ll_adv_get_peer_rpa(void);
+
 /* Called when advertising event done posted to LL task */
 void ble_ll_adv_event_done(void *arg);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_conn.h 
b/net/nimble/controller/include/controller/ble_ll_conn.h
index f035852..035ca39 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -160,6 +160,9 @@ struct ble_ll_conn_sm
     uint8_t last_rxd_hdr_byte;  /* note: possibly can make 1 bit since we
                                    only use the MD bit now */
 
+    /* For privacy */
+    int8_t rpa_index;
+
     /* connection event mgmt */
     uint8_t reject_reason;
     uint8_t host_reply_opcode;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll_resolv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_resolv.h 
b/net/nimble/controller/include/controller/ble_ll_resolv.h
index bddf70b..251543b 100644
--- a/net/nimble/controller/include/controller/ble_ll_resolv.h
+++ b/net/nimble/controller/include/controller/ble_ll_resolv.h
@@ -27,7 +27,7 @@
  */
 struct ble_ll_resolv_entry
 {
-    uint8_t rl_valid;
+    uint8_t rl_reserved;
     uint8_t rl_addr_type;
     uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
     uint8_t rl_local_irk[16];
@@ -51,16 +51,11 @@ int ble_ll_resolv_list_rmv(uint8_t *cmdbuf);
 /* Address resolution enable command */
 int ble_ll_resolv_enable_cmd(uint8_t *cmdbuf);
 
+/* XXX: implement */
 int ble_ll_resolv_peer_addr_rd(uint8_t *cmdbuf);
 void ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf);
 
-/* Enable resolving list */
-void ble_ll_resolv_list_enable(void);
-
-/* Disable resolving list */
-void ble_ll_resolv_list_disable(void);
-
-/* Finds 'addr' in resolving list. */
+/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled 
*/
 struct ble_ll_resolv_entry *
 ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type);
 
@@ -76,4 +71,20 @@ void ble_ll_resolv_list_reset(void);
 void ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local,
                                  uint8_t *addr);
 
+/* Generate a resolvable private address. */
+int ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa,
+                          int local);
+
+/* Set the resolvable private address timeout */
+int ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf);
+
+/* Get the RPA timeout, in seconds */
+uint32_t ble_ll_resolv_get_rpa_tmo(void);
+
+/* Resolve a resolvable private address */
+int ble_ll_resolv_rpa(uint8_t *rpa, uint8_t *irk);
+
+/* Initialize resolv*/
+void ble_ll_resolv_init(void);
+
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll_scan.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_scan.h 
b/net/nimble/controller/include/controller/ble_ll_scan.h
index 8323138..7dafcee 100644
--- a/net/nimble/controller/include/controller/ble_ll_scan.h
+++ b/net/nimble/controller/include/controller/ble_ll_scan.h
@@ -61,6 +61,8 @@ struct ble_ll_scan_sm
     uint8_t scan_rsp_pending;
     uint8_t scan_rsp_cons_fails;
     uint8_t scan_rsp_cons_ok;
+    int8_t scan_rpa_index;
+    uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN];
     uint16_t upper_limit;
     uint16_t backoff_count;
     uint16_t scan_itvl;
@@ -119,6 +121,15 @@ int ble_ll_scan_initiator_start(struct hci_create_conn 
*hcc);
 /* Returns the PDU allocated by the scanner */
 struct os_mbuf *ble_ll_scan_get_pdu(void);
 
+/* Called to set the resolvable private address of the last connected peer */
+void ble_ll_scan_set_peer_rpa(uint8_t *rpa);
+
+/* Returns peer RPA of last connection made */
+uint8_t *ble_ll_scan_get_peer_rpa(void);
+
+/* Returns the local RPA used by the scanner/initiator */
+uint8_t *ble_ll_scan_get_local_rpa(void);
+
 /* Stop the scanning state machine */
 void ble_ll_scan_sm_stop(int chk_disable);
 
@@ -128,7 +139,4 @@ void ble_ll_scan_chk_resume(void);
 /* Called when wait for response timer expires in scanning mode */
 void ble_ll_scan_wfr_timer_exp(void);
 
-/* Returns the global scanning state machine */
-struct ble_ll_scan_sm *ble_ll_scan_sm_get(void);
-
 #endif /* H_BLE_LL_SCAN_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/include/controller/ble_ll_whitelist.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_whitelist.h 
b/net/nimble/controller/include/controller/ble_ll_whitelist.h
index f62ab27..3c37afd 100644
--- a/net/nimble/controller/include/controller/ble_ll_whitelist.h
+++ b/net/nimble/controller/include/controller/ble_ll_whitelist.h
@@ -39,6 +39,6 @@ void ble_ll_whitelist_enable(void);
 void ble_ll_whitelist_disable(void);
 
 /* Boolean function returning true if address matches a whitelist entry */
-int ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type);
+int ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident);
 
 #endif /* H_BLE_LL_WHITELIST_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll.c 
b/net/nimble/controller/src/ble_ll.c
index e53d56f..a5197bb 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -288,21 +288,23 @@ ble_ll_chk_txrx_time(uint16_t time)
     return rc;
 }
 
-/* WWW: check where called to see if correct */
 /**
- * Checks to see if the address is a resolvable private address. Th
+ * Checks to see if the address is a resolvable private address.
  *
+ * NOTE: the addr_type parameter will be 0 if the address is public;
+ * any other value is random (all non-zero values).
  *
  * @param addr
+ * @param addr_type Public (zero) or Random (non-zero) address
  *
  * @return int
  */
 int
-ble_ll_is_resolvable_priv_addr(uint8_t *addr)
+ble_ll_is_rpa(uint8_t *addr, uint8_t addr_type)
 {
     int rc;
 
-    if ((addr[5] & 0xc0) == 0x40) {
+    if (addr_type && ((addr[5] & 0xc0) == 0x40)) {
         rc = 1;
     } else {
         rc = 0;
@@ -385,7 +387,7 @@ ble_ll_set_random_addr(uint8_t *addr)
  * @param addr
  * @param addr_type
  *
- * @return int
+ * @return int 0: not our device address. 1: is our device address
  */
 int
 ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
@@ -1161,6 +1163,10 @@ ble_ll_init(uint8_t ll_task_prio, uint8_t num_acl_pkts, 
uint16_t acl_pkt_size)
     features |= BLE_LL_FEAT_LE_ENCRYPTION;
 #endif
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    ble_ll_resolv_init();
+#endif
+
     /* Initialize random number generation */
     ble_ll_rand_init();
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_adv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_adv.c 
b/net/nimble/controller/src/ble_ll_adv.c
index c49686c..a5974ed 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -57,6 +57,13 @@
  *  adv_pdu_len
  *      The length of the advertising PDU that will be sent. This does not
  *      include the preamble, access address and CRC.
+ *
+ *  initiator_addr:
+ *      This is the address that we send in directed advertisements (the
+ *      INITA field). If we are using Privacy this is a RPA that we need to
+ *      generate. We reserve space in the advsm to save time when creating
+ *      the ADV_DIRECT_IND. If own address type is not 2 or 3, this is simply
+ *      the peer address from the set advertising parameters.
  */
 struct ble_ll_adv_sm
 {
@@ -71,12 +78,14 @@ struct ble_ll_adv_sm
     uint8_t scan_rsp_len;
     uint8_t adv_pdu_len;
     int8_t adv_rpa_index;
+    uint8_t adv_directed;
     uint16_t adv_itvl_min;
     uint16_t adv_itvl_max;
     uint32_t adv_itvl_usecs;
     uint32_t adv_event_start_time;
     uint32_t adv_pdu_start_time;
     uint32_t adv_dir_hd_end_time;
+    uint32_t adv_rpa_timer;
     uint8_t adva[BLE_DEV_ADDR_LEN];
     uint8_t adv_rpa[BLE_DEV_ADDR_LEN];
     uint8_t peer_addr[BLE_DEV_ADDR_LEN];
@@ -108,6 +117,29 @@ struct ble_ll_adv_sm g_ble_ll_adv_sm;
 #define BLE_LL_ADV_SCHED_MAX_USECS          (852)
 #define BLE_LL_ADV_DIRECT_SCHED_MAX_USECS   (502)
 
+
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+void
+ble_ll_adv_chk_rpa_timeout(struct ble_ll_adv_sm *advsm)
+{
+    uint32_t now;
+
+    if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        now = os_time_get();
+        if ((int32_t)(now >= advsm->adv_rpa_timer)) {
+            ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type,
+                                  advsm->adva, 1);
+
+            if (advsm->adv_directed) {
+                ble_ll_resolv_gen_rpa(advsm->peer_addr, advsm->peer_addr_type,
+                                      advsm->initiator_addr, 0);
+            }
+            advsm->adv_rpa_timer = now + ble_ll_resolv_get_rpa_tmo();
+        }
+    }
+}
+#endif
+
 /**
  * Calculate the first channel that we should advertise upon when we start
  * an advertising event.
@@ -141,7 +173,6 @@ ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm)
 static void
 ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct os_mbuf *m)
 {
-    int         is_direct_adv;
     uint8_t     adv_data_len;
     uint8_t     *dptr;
     uint8_t     pdulen;
@@ -150,7 +181,6 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct 
os_mbuf *m)
     /* assume this is not a direct ind */
     adv_data_len = advsm->adv_len;
     pdulen = BLE_DEV_ADDR_LEN + adv_data_len;
-    is_direct_adv = 0;
 
     /* Must be an advertising type! */
     switch (advsm->adv_type) {
@@ -168,7 +198,6 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct 
os_mbuf *m)
 
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
-        is_direct_adv = 1;
         pdu_type = BLE_ADV_PDU_TYPE_ADV_DIRECT_IND;
         adv_data_len = 0;
         pdulen = BLE_ADV_DIRECT_IND_LEN;
@@ -192,8 +221,9 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct 
os_mbuf *m)
     /* Set the PDU length in the state machine (includes header) */
     advsm->adv_pdu_len = pdulen + BLE_LL_PDU_HDR_LEN;
 
-    /* Set TxAdd to random if needed */
-    if (advsm->own_addr_type & 1) {
+    /* Set TxAdd to random if needed. */
+    if (ble_ll_is_rpa(advsm->adva, 1) ||
+        (advsm->own_addr_type & 1)) {
         pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
     }
 
@@ -205,8 +235,8 @@ ble_ll_adv_pdu_make(struct ble_ll_adv_sm *advsm, struct 
os_mbuf *m)
     memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN);
     dptr += BLE_DEV_ADDR_LEN;
 
-    /* For ADV_DIRECT_IND, we need to put initiators address in there */
-    if (is_direct_adv) {
+    /* For ADV_DIRECT_IND add inita */
+    if (advsm->adv_directed) {
         memcpy(dptr, advsm->initiator_addr, BLE_DEV_ADDR_LEN);
     }
 
@@ -249,6 +279,15 @@ ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm)
 
     ble_ll_mbuf_init(m, pdulen, hdr);
 
+    /*
+     * XXX: Am I sure this is correct? The adva in this packet will be the
+     * same one that was being advertised and is based on the peer identity
+     * address in the set advertising parameters. If a different peer sends
+     * us a scan request (for some reason) we will reply with an adva that
+     * was not generated based on the local irk of the peer sending the scan
+     * request.
+     */
+
     /* Construct scan response */
     dptr = m->om_data;
     memcpy(dptr, advsm->adva, BLE_DEV_ADDR_LEN);
@@ -477,6 +516,7 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
     /* Assume min interval based on low duty cycle/indirect advertising */
     min_itvl = BLE_LL_ADV_ITVL_MIN;
 
+    advsm->adv_directed = 0;
     switch (adv_type) {
     /* Fall through intentional */
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
@@ -487,7 +527,8 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
 
     case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
         adv_filter_policy = BLE_HCI_ADV_FILT_NONE;
-        memcpy(advsm->initiator_addr, cmd + 7, BLE_DEV_ADDR_LEN);
+        advsm->adv_directed = 1;
+        memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
         break;
     case BLE_HCI_ADV_TYPE_ADV_IND:
         /* Nothing to do */
@@ -521,9 +562,12 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
     if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
         /* Copy peer address */
         memcpy(advsm->peer_addr, cmd + 7, BLE_DEV_ADDR_LEN);
+
+        /* Reset RPA timer so we generate a new RPA */
+        advsm->adv_rpa_timer = os_time_get();
     }
 #else
-    /* If we dont support privacy these own address types wont work */
+    /* If we dont support privacy some address types wont work */
     if (own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
         return BLE_ERR_UNSUPPORTED;
     }
@@ -598,7 +642,6 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
 {
     uint8_t adv_chan;
     uint8_t *addr;
-    struct ble_ll_resolv_entry *rl;
 
     /*
      * This is not in the specification. I will reject the command with a
@@ -621,27 +664,18 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
     }
     memcpy(advsm->adva, addr, BLE_DEV_ADDR_LEN);
 
-#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
-    /* WWW:
-     * 1) Make sure we are doing this for the proper adv types
-     */
-    if (ble_ll_resolv_enabled()) {
-        if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-            rl = ble_ll_resolv_list_find(advsm->peer_addr, 
advsm->peer_addr_type);
-            if (rl && ble_ll_resolv_irk_nonzero(rl->rl_local_irk)) {
-                ble_ll_resolv_gen_priv_addr(rl, 1, advsm->adva);
-            }
-        }
-        ble_phy_resolv_list_enable();
-    } else {
-        ble_phy_resolv_list_disable();
+    if (advsm->adv_directed) {
+        memcpy(advsm->initiator_addr, advsm->peer_addr, BLE_DEV_ADDR_LEN);
     }
+
+    /* This will generate an RPA for both initiator addr and adva */
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    ble_ll_adv_chk_rpa_timeout(advsm);
 #endif
 
     /* Set flag telling us that advertising is enabled */
     advsm->enabled = 1;
 
-    /* WWW: what about privacy for direct? */
     /* Determine the advertising interval we will use */
     if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) {
         /* Set it to max. allowed for high duty cycle advertising */
@@ -810,11 +844,13 @@ static int
 ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
 {
     int rc;
-    int index;
-    uint8_t chk_whitelist;
+    int resolved;
+    uint8_t chk_wl;
     uint8_t txadd;
+    uint8_t peer_addr_type;
     uint8_t *rxbuf;
     uint8_t *adva;
+    uint8_t *peer;
     struct ble_mbuf_hdr *ble_hdr;
     struct ble_ll_adv_sm *advsm;
     struct os_mbuf *scan_rsp;
@@ -829,27 +865,35 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
 
     /* Set device match bit if we are whitelisting */
     if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
-        chk_whitelist = advsm->adv_filter_policy & 1;
+        chk_wl = advsm->adv_filter_policy & 1;
     } else {
-        chk_whitelist = advsm->adv_filter_policy & 2;
+        chk_wl = advsm->adv_filter_policy & 2;
+    }
+
+    /* Get the peer address type */
+    if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+        txadd = BLE_ADDR_TYPE_RANDOM;
+    } else {
+        txadd = BLE_ADDR_TYPE_PUBLIC;
     }
 
     ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    peer = rxbuf + BLE_LL_PDU_HDR_LEN;
+    peer_addr_type = txadd;
+    resolved = 0;
 
 #if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
-    uint8_t *peer;
-
-    peer = rxbuf + BLE_LL_PDU_HDR_LEN;
-    if (ble_ll_is_resolvable_priv_addr(peer) && ble_ll_resolv_enabled()) {
-        index = ble_hw_resolv_list_match();
-        if (index >= 0) {
-            advsm->adv_rpa_index = index;
+    if (ble_ll_is_rpa(peer, txadd) && ble_ll_resolv_enabled()) {
+        advsm->adv_rpa_index = ble_hw_resolv_list_match();
+        if (advsm->adv_rpa_index >= 0) {
             ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
-            if (chk_whitelist) {
-                chk_whitelist = 0;
+            if (chk_wl) {
+                peer = 
g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr;
+                peer_addr_type = 
g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
+                resolved = 1;
             }
         } else {
-            if (chk_whitelist) {
+            if (chk_wl) {
                 return -1;
             }
         }
@@ -857,18 +901,8 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
 #endif
 
     /* Set device match bit if we are whitelisting */
-    if (chk_whitelist) {
-        /* Get the scanners address type */
-        if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
-            txadd = BLE_ADDR_TYPE_RANDOM;
-        } else {
-            txadd = BLE_ADDR_TYPE_PUBLIC;
-        }
-
-        /* Check for whitelist match */
-        if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, txadd)) {
-            return -1;
-        }
+    if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
+        return -1;
     }
 
     /*
@@ -888,6 +922,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
                 ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_SCAN_RSP_TXD;
                 STATS_INC(ble_ll_stats, scan_rsp_txg);
             }
+            os_mbuf_free_chain(scan_rsp);
         }
     }
 
@@ -910,35 +945,48 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct 
ble_mbuf_hdr *hdr)
     int valid;
     uint8_t pyld_len;
     uint8_t resolved;
+    uint8_t addr_type;
     uint8_t *inita;
+    uint8_t *ident_addr;
     uint32_t endtime;
     struct ble_ll_adv_sm *advsm;
 
     /* Check filter policy. */
     valid = 0;
+    resolved = BLE_MBUF_HDR_RESOLVED(hdr);
     advsm = &g_ble_ll_adv_sm;
     inita = rxbuf + BLE_LL_PDU_HDR_LEN;
     if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) {
+
         valid = 1;
-        if ((advsm->adv_filter_policy & 2) == 0) {
-            /*
-             * Only accept connect requests from the desired address if we
-             * are doing directed advertising
-             */
-            if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) ||
-                (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) {
-                /* XXX: not sure if this works if address is random */
-                /* WWW: deal with RPA */
-                /* Compare addresses */
-                if (memcmp(advsm->initiator_addr, inita, BLE_DEV_ADDR_LEN)) {
-                    valid = 0;
-                }
+        if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+            addr_type = BLE_ADDR_TYPE_RANDOM;
+        } else {
+            addr_type = BLE_ADDR_TYPE_PUBLIC;
+        }
+
+        /*
+         * Only accept connect requests from the desired address if we
+         * are doing directed advertising
+         */
+        if ((advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD) ||
+            (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD)) {
+            ident_addr = inita;
+
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+            if (resolved) {
+                ident_addr = 
g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr;
+                addr_type = 
g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
+            }
+#endif
+            if ((addr_type != advsm->peer_addr_type) ||
+                memcmp(advsm->peer_addr, ident_addr, BLE_DEV_ADDR_LEN)) {
+                valid = 0;
             }
         }
     }
 
     if (valid) {
-        resolved = BLE_MBUF_HDR_RESOLVED(hdr);
 #if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
         if (resolved) {
             /* Retain the resolvable private address that we received. */
@@ -951,13 +999,17 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct 
ble_mbuf_hdr *hdr)
             memcpy(inita,
                    g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_identity_addr,
                    BLE_DEV_ADDR_LEN);
+
+            /* Peer address type is an identity address */
+            addr_type = 
g_ble_ll_resolv_list[advsm->adv_rpa_index].rl_addr_type;
+            addr_type += 2;
         }
 #endif
 
         /* Try to start slave connection. If successful, stop advertising */
         pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
         endtime = hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len);
-        valid = ble_ll_conn_slave_start(rxbuf, endtime, resolved);
+        valid = ble_ll_conn_slave_start(rxbuf, endtime, addr_type);
         if (valid) {
             ble_ll_adv_sm_stop(advsm);
         }
@@ -1216,6 +1268,11 @@ ble_ll_adv_event_done(void *arg)
         }
     }
 
+    /* We need to regenerate our RPA's if we have passed timeout */
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    ble_ll_adv_chk_rpa_timeout(advsm);
+#endif
+
     /* Schedule advertising transmit */
     ble_ll_adv_set_sched(advsm, 0);
 
@@ -1252,6 +1309,44 @@ ble_ll_adv_can_chg_whitelist(void)
 }
 
 /**
+ * Returns the local resolvable private address currently being using by
+ * the advertiser
+ *
+ * @return uint8_t*
+ */
+uint8_t *
+ble_ll_adv_get_local_rpa(void)
+{
+    uint8_t *rpa;
+    struct ble_ll_adv_sm *advsm;
+
+    advsm = &g_ble_ll_adv_sm;
+
+    rpa = NULL;
+    if (advsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        rpa = advsm->adva;
+    }
+
+    return rpa;
+}
+
+/**
+ * Returns the peer resolvable private address of last device connecting to us
+ *
+ * @return uint8_t*
+ */
+uint8_t *
+ble_ll_adv_get_peer_rpa(void)
+{
+    struct ble_ll_adv_sm *advsm;
+
+    advsm = &g_ble_ll_adv_sm;
+
+    /* XXX: should this go into IRK list or connection? */
+    return advsm->adv_rpa;
+}
+
+/**
  * Called when the LL wait for response timer expires while in the advertising
  * state. Disables the phy and
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn.c 
b/net/nimble/controller/src/ble_ll_conn.c
index fe72a8e..3890a4f 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -32,7 +32,9 @@
 #include "controller/ble_ll_whitelist.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_ctrl.h"
+#include "controller/ble_ll_resolv.h"
 #include "controller/ble_phy.h"
+#include "controller/ble_hw.h"
 #include "ble_ll_conn_priv.h"
 #include "hal/hal_cputime.h"
 #include "hal/hal_gpio.h"
@@ -1116,6 +1118,10 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
     ble_phy_setchan(connsm->data_chan_index, connsm->access_addr,
                     connsm->crcinit);
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    ble_phy_resolv_list_disable();
+#endif
+
     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
         /* Set start time of transmission */
         rc = ble_phy_tx_set_start_time(sch->start_time + 
XCVR_PROC_DELAY_USECS);
@@ -1302,8 +1308,6 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
     connsm->slave_latency = hcc->conn_latency;
     connsm->supervision_tmo = hcc->supervision_timeout;
 
-    /* WWW: if not using whitelist, what happens if we resolve the address?
-       we would have to set the differently huh? CHeck this out... */
     /* Set own address type and peer address if needed */
     connsm->own_addr_type = hcc->own_addr_type;
     if (hcc->filter_policy == 0) {
@@ -1367,6 +1371,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
     connsm->sub_vers_nr = 0;
     connsm->reject_reason = BLE_ERR_SUCCESS;
     connsm->conn_rssi = BLE_LL_CONN_UNKNOWN_RSSI;
+    connsm->rpa_index = -1;
 
     /* Reset current control procedure */
     connsm->cur_ctrl_proc = BLE_LL_CTRL_PROC_IDLE;
@@ -1777,7 +1782,6 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, 
uint32_t endtime)
                 ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
             }
         }
-        /* WWW: enhanced connection complete! */
         ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
     }
 
@@ -1874,51 +1878,120 @@ ble_ll_conn_event_end(void *arg)
  *
  * @param m
  * @param adva
- * @param addr_type
+ * @param addr_type     Address type of ADVA from received advertisement.
  * @param txoffset      The tx window offset for this connection
  */
 static void
 ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
-                           uint16_t txoffset)
+                           uint16_t txoffset, int rpa_index)
 {
-    uint8_t pdu_type;
+    int is_rpa;
+    uint8_t hdr;
     uint8_t *dptr;
+    uint8_t *addr;
     struct ble_mbuf_hdr *ble_hdr;
+    struct ble_ll_resolv_entry *rl;
+    struct ble_ll_conn_sm *connsm;
 
     assert(m != NULL);
 
+    /* Retain pdu type but clear txadd/rxadd bits */
     ble_hdr = BLE_MBUF_HDR_PTR(m);
-    pdu_type = ble_hdr->txinfo.hdr_byte;
+    hdr = ble_hdr->txinfo.hdr_byte & BLE_ADV_PDU_HDR_TYPE_MASK;
     if (addr_type) {
         /* Set random address */
-        pdu_type |= BLE_ADV_PDU_HDR_RXADD_MASK;
+        hdr |= BLE_ADV_PDU_HDR_RXADD_MASK;
+    }
+
+    dptr = m->om_data;
+
+    /* Get pointer to our device address */
+    connsm = g_ble_ll_conn_create_sm;
+    if ((connsm->own_addr_type & 1) == 0) {
+        addr = g_dev_addr;
     } else {
-        /* Set public device address */
-        pdu_type &= ~BLE_ADV_PDU_HDR_RXADD_MASK;
+        hdr |= BLE_ADV_PDU_HDR_TXADD_RAND;
+        addr = g_random_addr;
     }
 
-    /* Set BLE transmit header */
-    ble_hdr->txinfo.hdr_byte = pdu_type;
+    /* XXX: do this ahead of time? Calculate the local rpa I mean */
+    if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        rl = NULL;
+        is_rpa = ble_ll_is_rpa(adva, addr_type);
+        if (is_rpa) {
+            if (rpa_index >= 0) {
+                rl = &g_ble_ll_resolv_list[rpa_index];
+            }
+        } else {
+            if (ble_ll_resolv_enabled()) {
+                rl = ble_ll_resolv_list_find(adva, addr_type);
+            }
+        }
 
-    dptr = m->om_data;
+        if (rl) {
+            hdr |= BLE_ADV_PDU_HDR_TXADD_RAND;
+            ble_ll_resolv_gen_priv_addr(rl, 1, dptr);
+            addr = NULL;
+        }
+    }
+
+    if (addr) {
+        memcpy(dptr, addr, BLE_DEV_ADDR_LEN);
+    }
     memcpy(dptr + BLE_DEV_ADDR_LEN, adva, BLE_DEV_ADDR_LEN);
     htole16(dptr + 20, txoffset);
+
+    /* Set BLE transmit header */
+    ble_hdr->txinfo.hdr_byte = hdr;
 }
 
 /* Returns true if the address matches the connection peer address */
 static int
-ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
+ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva, int index)
 {
     int rc;
+    uint8_t *peer_addr;
     struct ble_ll_conn_sm *connsm;
 
     /* XXX: Deal with different types of random addresses here! */
     connsm = g_ble_ll_conn_create_sm;
-    if (connsm && (connsm->peer_addr_type == addr_type) &&
-        !memcmp(adva, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
-        rc = 1;
-    } else {
-        rc = 0;
+    if (!connsm) {
+        return 0;
+    }
+
+    switch (connsm->peer_addr_type) {
+    /* Fall-through intentional */
+    case BLE_HCI_CONN_PEER_ADDR_PUBLIC:
+    case BLE_HCI_CONN_PEER_ADDR_RANDOM:
+        if (addr_type != connsm->peer_addr_type) {
+            return 0;
+        }
+        peer_addr = adva;
+        break;
+    case BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT:
+        if ((index < 0) ||
+            (g_ble_ll_resolv_list[index].rl_addr_type != 0)) {
+            return 0;
+        }
+        peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
+        break;
+    case BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT:
+        if ((index < 0) ||
+            (g_ble_ll_resolv_list[index].rl_addr_type != 1)) {
+            return 0;
+        }
+        peer_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
+        break;
+    default:
+        peer_addr = NULL;
+        break;
+    }
+
+    rc = 0;
+    if (peer_addr) {
+        if (!memcmp(peer_addr, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
+            rc = 1;
+        }
     }
 
     return rc;
@@ -1946,13 +2019,14 @@ ble_ll_conn_req_txend(void *arg)
  * @param adva Address of advertiser
  */
 static int
-ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva, uint16_t txoffset)
+ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva, uint16_t txoffset,
+                         int rpa_index)
 {
     int rc;
     struct os_mbuf *m;
 
     m = ble_ll_scan_get_pdu();
-    ble_ll_conn_req_pdu_update(m, adva, addr_type, txoffset);
+    ble_ll_conn_req_pdu_update(m, adva, addr_type, txoffset, rpa_index);
     ble_phy_set_txend_cb(ble_ll_conn_req_txend, NULL);
     rc = ble_phy_tx(m, BLE_PHY_TRANSITION_NONE);
     return rc;
@@ -1988,8 +2062,10 @@ ble_ll_conn_event_halt(void)
 void
 ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
 {
+    int8_t rpa_index;
     uint8_t addr_type;
     uint8_t payload_len;
+    uint8_t *addr;
     uint32_t endtime;
     struct ble_ll_conn_sm *connsm;
 
@@ -2000,11 +2076,6 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct 
ble_mbuf_hdr *ble_hdr)
     if (connsm && CONN_F_CONN_REQ_TXD(connsm)) {
         /* Set address of advertiser to which we are connecting. */
         if (ble_ll_scan_whitelist_enabled()) {
-            /*
-             * XXX: need to see if the whitelist tells us exactly what peer
-             * addr type we should use? Not sure it matters. If whitelisting
-             * is not used the peer addr and type already set
-             */
             /* Get address type of advertiser */
             if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
                 addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM;
@@ -2012,15 +2083,31 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct 
ble_mbuf_hdr *ble_hdr)
                 addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
             }
 
+            /*
+             * Did we resolve this address? If so, set correct peer address
+             * and peer address type.
+             */
+            rpa_index = connsm->rpa_index;
+
+            if (rpa_index >= 0) {
+                addr_type = g_ble_ll_resolv_list[rpa_index].rl_addr_type + 2;
+                addr = g_ble_ll_resolv_list[rpa_index].rl_identity_addr;
+            } else {
+                addr = rxbuf + BLE_LL_PDU_HDR_LEN;
+            }
+
             connsm->peer_addr_type = addr_type;
-            memcpy(connsm->peer_addr, rxbuf + BLE_LL_PDU_HDR_LEN,
-                   BLE_DEV_ADDR_LEN);
+            memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN);
+        }
+
+        if (connsm->rpa_index >= 0) {
+            ble_ll_scan_set_peer_rpa(rxbuf + BLE_LL_PDU_HDR_LEN);
         }
 
         /* Connection has been created. Stop scanning */
         g_ble_ll_conn_create_sm = NULL;
         ble_ll_scan_sm_stop(0);
-        payload_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;;
+        payload_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
         endtime = ble_hdr->beg_cputime + BLE_TX_DUR_USECS_M(payload_len);
         ble_ll_conn_created(connsm, endtime);
     } else {
@@ -2044,15 +2131,22 @@ int
 ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
 {
     int rc;
+    int resolved;
     int chk_send_req;
+    int chk_wl;
+    int index;
     uint8_t pdu_type;
     uint8_t addr_type;
+    uint8_t peer_addr_type;
     uint8_t *adv_addr;
+    uint8_t *peer;
     uint8_t *init_addr;
     uint8_t *rxbuf;
     uint8_t pyld_len;
+    uint8_t inita_is_rpa;
     uint32_t endtime;
     struct ble_mbuf_hdr *ble_hdr;
+    struct ble_ll_conn_sm *connsm;
 
     /*
      * We have to restart receive if we cant hand up pdu. We return 0 so that
@@ -2068,22 +2162,34 @@ ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
         goto init_rx_isr_exit;
     }
 
+    /* Get connection state machine to use if connection to be established */
+    connsm = g_ble_ll_conn_create_sm;
+
     /* Only interested in ADV IND or ADV DIRECT IND */
     rxbuf = rxpdu->om_data;
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
     pyld_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
 
+    inita_is_rpa = 0;
+
     switch (pdu_type) {
     case BLE_ADV_PDU_TYPE_ADV_IND:
         chk_send_req = 1;
         break;
     case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
+        /* XXX: needs to be fixed for privacy */
+        chk_send_req = 0;
         init_addr = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
         addr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
-        if (ble_ll_is_our_devaddr(init_addr, addr_type)) {
-            chk_send_req = 1;
-        } else {
-            chk_send_req = 0;
+        if (addr_type) {
+            inita_is_rpa = (uint8_t)ble_ll_is_rpa(init_addr, addr_type);
+        }
+
+        if (!inita_is_rpa && ble_ll_is_our_devaddr(init_addr, addr_type)) {
+            /* We should not respond if we expect the device to be private */
+            if (connsm->own_addr_type <= BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+                chk_send_req = 1;
+            }
         }
         break;
     default:
@@ -2101,34 +2207,65 @@ ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
             addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
         }
 
-        /* Check filter policy */
+        index = -1;
         ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
-        if (ble_ll_scan_whitelist_enabled()) {
-            /* Check if device is on whitelist. If not, leave */
-            if (!ble_ll_whitelist_match(adv_addr, addr_type)) {
-                return -1;
+        peer = adv_addr;
+        peer_addr_type = addr_type;
+
+        resolved = 0;
+        chk_wl = ble_ll_scan_whitelist_enabled();
+
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+        if (ble_ll_is_rpa(adv_addr, addr_type) && ble_ll_resolv_enabled()) {
+            index = ble_hw_resolv_list_match();
+            if (index >= 0) {
+                ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
+                connsm->rpa_index = index;
+                peer = g_ble_ll_resolv_list[index].rl_identity_addr;
+                peer_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
+                resolved = 1;
+            } else {
+                if (chk_wl) {
+                    return -1;
+                }
             }
+        }
+#endif
 
-            /* Set BLE mbuf header flags */
-            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
+        /* Check filter policy */
+        if (chk_wl) {
+            if (!ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
+                return -1;
+            }
         } else {
-            /* XXX: Resolvable? Deal with those */
-            /* XXX: HW device matching? If so, implement */
             /* Must match the connection address */
-            if (!ble_ll_conn_is_peer_adv(addr_type, adv_addr)) {
+            if (!ble_ll_conn_is_peer_adv(addr_type, adv_addr, index)) {
+                return -1;
+            }
+        }
+        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
+
+        /*
+         * If the inita is a RPA, we must see if it resolves based on the
+         * identity address of the resolved ADVA.
+         */
+        if (inita_is_rpa) {
+            if ((index < 0) ||
+                !ble_ll_resolv_rpa(init_addr,
+                                   g_ble_ll_resolv_list[index].rl_local_irk)) {
                 return -1;
             }
         }
 
         /* Attempt to schedule new connection. Possible that this might fail */
         endtime = ble_hdr->beg_cputime + BLE_TX_DUR_USECS_M(pyld_len);
-        if (!ble_ll_sched_master_new(g_ble_ll_conn_create_sm, endtime,
+        if (!ble_ll_sched_master_new(connsm, endtime,
                                      NIMBLE_OPT_LL_CONN_INIT_SLOTS)) {
             /* Setup to transmit the connect request */
             rc = ble_ll_conn_request_send(addr_type, adv_addr,
-                                          g_ble_ll_conn_create_sm->tx_win_off);
+                                          connsm->tx_win_off, index);
             if (!rc) {
-                CONN_F_CONN_REQ_TXD(g_ble_ll_conn_create_sm) = 1;
+                CONN_F_CONN_REQ_TXD(connsm) = 1;
                 STATS_INC(ble_ll_conn_stats, conn_req_txd);
             }
         } else {
@@ -2747,7 +2884,7 @@ ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, 
uint8_t *chanmap)
  * @return 0: connection not started; 1 connecton started
  */
 int
-ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t 
resolved)
+ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t pat)
 {
     int rc;
     uint32_t temp;
@@ -2824,23 +2961,9 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t 
conn_req_end, uint8_t resolved)
         goto err_slave_start;
     }
 
-    /* WWW: what about master when it makes a connection? It has to do this
-       properly! */
     /* Set the address of device that we are connecting with */
     memcpy(&connsm->peer_addr, inita, BLE_DEV_ADDR_LEN);
-    if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
-        if (resolved) {
-            connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM_IDENT;
-        } else {
-            connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_RANDOM;
-        }
-    } else {
-        if (resolved) {
-            connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC_IDENT;
-        } else {
-            connsm->peer_addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
-        }
-    }
+    connsm->peer_addr_type = pat;
 
     /* Calculate number of used channels; make sure it meets min requirement */
     connsm->num_used_chans = ble_ll_conn_calc_used_chans(connsm->chanmap);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_conn_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_hci.c 
b/net/nimble/controller/src/ble_ll_conn_hci.c
index f1b0cd9..08ced85 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -30,6 +30,7 @@
 #include "controller/ble_ll_conn.h"
 #include "controller/ble_ll_ctrl.h"
 #include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_adv.h"
 #include "ble_ll_conn_priv.h"
 
 /*
@@ -88,7 +89,6 @@ static void
 ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
 {
     uint8_t pdu_type;
-    uint8_t *addr;
     uint8_t *dptr;
     struct os_mbuf *m;
 
@@ -98,26 +98,13 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
     /* Construct first PDU header byte */
     pdu_type = BLE_ADV_PDU_TYPE_CONNECT_REQ;
 
-    /* Get pointer to our device address */
-    if (connsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_PUBLIC) {
-        addr = g_dev_addr;
-    } else if (connsm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-        pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
-        addr = g_random_addr;
-    } else {
-        /* XXX: unsupported for now  */
-        addr = NULL;
-        assert(0);
-    }
-
     /* Set BLE transmit header */
     ble_ll_mbuf_init(m, BLE_CONNECT_REQ_LEN, pdu_type);
 
     /* Construct the connect request */
     dptr = m->om_data;
-    memcpy(dptr, addr, BLE_DEV_ADDR_LEN);
 
-    /* Skip the advertiser's address as we dont know that yet */
+    /* Skip inita and adva advertiser's address as we dont know that yet */
     dptr += (2 * BLE_DEV_ADDR_LEN);
 
     /* Access address */
@@ -142,23 +129,74 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
 void
 ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
 {
+    uint8_t peer_addr_type;
+    uint8_t enabled;
+    uint8_t enh_enabled;
     uint8_t *evbuf;
+    uint8_t *evdata;
+    uint8_t *rpa;
 
-    if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE)) {
+    enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE);
+    enh_enabled = 
ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE);
+
+    if (enabled || enh_enabled) {
         evbuf = os_memblock_get(&g_hci_cmd_pool);
         if (evbuf) {
+            /* Put common elements in event */
             evbuf[0] = BLE_HCI_EVCODE_LE_META;
-            evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
-            evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+            if (enh_enabled) {
+                evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
+                evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
+            } else {
+                evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
+                evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+            }
             evbuf[3] = status;
-            htole16(evbuf + 4, connsm->conn_handle);
-            evbuf[6] = connsm->conn_role - 1;
-            evbuf[7] = connsm->peer_addr_type;
-            memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
-            htole16(evbuf + 14, connsm->conn_itvl);
-            htole16(evbuf + 16, connsm->slave_latency);
-            htole16(evbuf + 18, connsm->supervision_tmo);
-            evbuf[20] = connsm->master_sca;
+
+            if (connsm) {
+                htole16(evbuf + 4, connsm->conn_handle);
+                evbuf[6] = connsm->conn_role - 1;
+                peer_addr_type = connsm->peer_addr_type;
+
+                evdata = evbuf + 14;
+                if (enh_enabled) {
+                    memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
+                    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                        if (connsm->own_addr_type > 
BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+                            rpa = ble_ll_scan_get_local_rpa();
+                        } else {
+                            rpa = NULL;
+                        }
+                    } else {
+                        rpa = ble_ll_adv_get_local_rpa();
+                    }
+                    if (rpa) {
+                        memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
+                    }
+
+                    if (connsm->peer_addr_type > 
BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                        if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                            rpa = ble_ll_scan_get_peer_rpa();
+                        } else {
+                            rpa = ble_ll_adv_get_peer_rpa();
+                        }
+                        memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
+                    }
+                    evdata += 12;
+                } else {
+                    if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                        peer_addr_type -= 2;
+                    }
+                }
+
+                evbuf[7] = peer_addr_type;
+                memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
+
+                htole16(evdata, connsm->conn_itvl);
+                htole16(evdata + 2, connsm->slave_latency);
+                htole16(evdata + 4, connsm->supervision_tmo);
+                evdata[6] = connsm->master_sca;
+            }
             ble_ll_hci_event_send(evbuf);
         }
     }
@@ -341,11 +379,6 @@ ble_ll_conn_create(uint8_t *cmdbuf)
             return BLE_ERR_INV_HCI_CMD_PARMS;
         }
 
-        /* XXX: not supported */
-        if (hcc->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
-            return BLE_ERR_UNSUPPORTED;
-        }
-
         memcpy(&hcc->peer_addr, cmdbuf + 6, BLE_DEV_ADDR_LEN);
     }
 
@@ -355,11 +388,6 @@ ble_ll_conn_create(uint8_t *cmdbuf)
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
-    /* XXX: not supported */
-    if (hcc->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-        return BLE_ERR_UNSUPPORTED;
-    }
-
     /* Check connection interval, latency and supervision timeoout */
     hcc->conn_itvl_min = le16toh(cmdbuf + 13);
     hcc->conn_itvl_max = le16toh(cmdbuf + 15);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_conn_priv.h 
b/net/nimble/controller/src/ble_ll_conn_priv.h
index 24a7a1e..7794a6a 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -92,8 +92,7 @@ void ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
                                 struct ble_ll_len_req *req);
 
 /* Advertising interface */
-int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end,
-                            uint8_t resolved);
+int ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end, uint8_t 
pat);
 
 /* Link Layer interface */
 void ble_ll_conn_module_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_hci.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci.c 
b/net/nimble/controller/src/ble_ll_hci.c
index ec26019..d6e574d 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -663,7 +663,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, 
uint8_t *rsplen)
         rc = ble_ll_resolv_enable_cmd(cmdbuf);
         break;
     case BLE_HCI_OCF_LE_SET_RPA_TMO:
-        /* XXX: implement */
+        rc = ble_ll_resolv_set_rpa_tmo(cmdbuf);
         break;
 #endif
     case BLE_HCI_OCF_LE_RD_MAX_DATA_LEN:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_resolv.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_resolv.c 
b/net/nimble/controller/src/ble_ll_resolv.c
index 62d85e4..b81d957 100644
--- a/net/nimble/controller/src/ble_ll_resolv.c
+++ b/net/nimble/controller/src/ble_ll_resolv.c
@@ -36,6 +36,7 @@
 uint8_t g_ble_ll_addr_res_enabled;
 uint8_t g_ble_ll_resolv_list_size;
 uint8_t g_ble_ll_resolv_list_cnt;
+uint32_t g_ble_ll_resolv_rpa_tmo;
 
 struct ble_ll_resolv_entry 
g_ble_ll_resolv_list[NIMBLE_OPT_LL_RESOLV_LIST_SIZE];
 
@@ -67,7 +68,7 @@ ble_ll_resolv_list_chg_allowed(void)
  *
  * @param irk
  *
- * @return int 0: IRK has a non-zero value. 1: IRK is all zero.
+ * @return int 0: IRK is zero . 1: IRK has non-zero value.
  */
 int
 ble_ll_resolv_irk_nonzero(uint8_t *irk)
@@ -75,10 +76,10 @@ ble_ll_resolv_irk_nonzero(uint8_t *irk)
     int i;
     int rc;
 
-    rc = 1;
+    rc = 0;
     for (i = 0; i < 16; ++i) {
         if (*irk != 0) {
-            rc = 0;
+            rc = 1;
             break;
         }
         ++irk;
@@ -178,27 +179,6 @@ ble_ll_resolv_list_find(uint8_t *addr, uint8_t addr_type)
 }
 
 /**
- * Is there a match between the device and a device on the resolving list
- *
- * @param addr
- * @param addr_type Public address (0) or random address (1)
- *
- * @return int
- */
-int
-ble_ll_resolv_list_match(uint8_t *addr, uint8_t addr_type)
-{
-    int rc;
-    /* WWW: will this be used? */
-#ifdef BLE_USES_HW_RESOLV_LIST
-    rc = ble_hw_resolv_list_match();
-#else
-    rc = ble_ll_is_on_resolv_list(addr, addr_type);
-#endif
-    return rc;
-}
-
-/**
  * Add a device to the resolving list
  *
  * @return int
@@ -292,7 +272,6 @@ ble_ll_resolv_enable_cmd(uint8_t *cmdbuf)
         g_ble_ll_conn_create_sm) {
         rc = BLE_ERR_CMD_DISALLOWED;
     } else {
-        /* WWW: do we do anything here if we change state? */
         g_ble_ll_addr_res_enabled = cmdbuf[0];
         rc = BLE_ERR_SUCCESS;
     }
@@ -313,6 +292,41 @@ ble_ll_resolv_local_addr_rd(uint8_t *cmdbuf)
 }
 
 /**
+ * Set the resolvable private address timeout.
+ *
+ * @param cmdbuf
+ *
+ * @return int
+ */
+int
+ble_ll_resolv_set_rpa_tmo(uint8_t *cmdbuf)
+{
+    int rc;
+    uint16_t tmo_secs;
+
+    tmo_secs = le16toh(cmdbuf);
+    if ((tmo_secs > 0) && (tmo_secs <= 0xA1B8)) {
+        g_ble_ll_resolv_rpa_tmo = tmo_secs * OS_TICKS_PER_SEC;
+    } else {
+        rc = BLE_ERR_INV_HCI_CMD_PARMS;
+    }
+
+    return rc;
+}
+
+/**
+ * Returns the Resolvable Private address timeout, in os ticks
+ *
+ *
+ * @return uint32_t
+ */
+uint32_t
+ble_ll_resolv_get_rpa_tmo(void)
+{
+    return OS_TICKS_PER_SEC * g_ble_ll_resolv_rpa_tmo;
+}
+
+/**
  * Called the generate a resolvable private address
  *
  *
@@ -348,7 +362,68 @@ ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry 
*rl, int local,
 
     /* Calculate hash */
     ble_hw_encrypt_block(&ecb);
-    swap_buf(addr, ecb.cipher_text, 3);
+    swap_buf(addr, ecb.cipher_text + 13, 3);
+}
+
+/**
+ * Generate a resolvable private address.
+ *
+ * @param addr
+ * @param addr_type
+ * @param rpa
+ *
+ * @return int
+ */
+int
+ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int 
local)
+{
+    int rc;
+    uint8_t *irk;
+    struct ble_ll_resolv_entry *rl;
+
+    rc = 0;
+    rl = ble_ll_resolv_list_find(addr, addr_type);
+    if (rl) {
+        if (local) {
+            irk = rl->rl_local_irk;
+        } else {
+            irk = rl->rl_peer_irk;
+        }
+        if (ble_ll_resolv_irk_nonzero(irk)) {
+            ble_ll_resolv_gen_priv_addr(rl, local, rpa);
+            rc = 1;
+        }
+    }
+
+    return rc;
+}
+
+/**
+ * Resolve a Resolvable Private Address
+ *
+ * @param rpa
+ * @param index
+ *
+ * @return int
+ */
+int
+ble_ll_resolv_rpa(uint8_t *rpa, uint8_t *irk)
+{
+    int rc;
+    struct ble_encryption_block ecb;
+
+    memcpy(ecb.key, irk, BLE_ENC_BLOCK_SIZE);
+    memset(ecb.plain_text, 0, BLE_ENC_BLOCK_SIZE);
+    swap_buf(&ecb.plain_text[13], rpa + 3, 3);
+    ble_hw_encrypt_block(&ecb);
+    if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) &&
+        (ecb.cipher_text[13] == rpa[2])) {
+        rc = 1;
+    } else {
+        rc = 0;
+    }
+
+    return rc;
 }
 
 /**
@@ -368,10 +443,25 @@ ble_ll_resolv_enabled(void)
 void
 ble_ll_resolv_list_reset(void)
 {
-    ble_ll_resolv_list_clr();
     g_ble_ll_addr_res_enabled = 0;
-    /* XXX: deal with HW restrictions */
-    g_ble_ll_resolv_list_size = NIMBLE_OPT_LL_RESOLV_LIST_SIZE;
+    ble_ll_resolv_list_clr();
+    ble_ll_resolv_init();
+}
+
+void
+ble_ll_resolv_init(void)
+{
+    uint8_t hw_size;
+
+    /* Default is 15 minutes */
+    g_ble_ll_resolv_rpa_tmo = 15 * 60 * OS_TICKS_PER_SEC;
+
+    hw_size = ble_hw_resolv_list_size();
+    if (hw_size > NIMBLE_OPT_LL_RESOLV_LIST_SIZE) {
+        hw_size = NIMBLE_OPT_LL_RESOLV_LIST_SIZE;
+    }
+    g_ble_ll_resolv_list_size = hw_size;
+
 }
 
 #endif  /* if BLE_LL_CFG_FEAT_LL_PRIVACY == 1 */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d6bbacbd/net/nimble/controller/src/ble_ll_scan.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_scan.c 
b/net/nimble/controller/src/ble_ll_scan.c
index f675ec7..008f632 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -26,12 +26,14 @@
 #include "nimble/nimble_opt.h"
 #include "nimble/hci_common.h"
 #include "controller/ble_phy.h"
+#include "controller/ble_hw.h"
 #include "controller/ble_ll.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_scan.h"
 #include "controller/ble_ll_hci.h"
 #include "controller/ble_ll_whitelist.h"
+#include "controller/ble_ll_resolv.h"
 #include "hal/hal_cputime.h"
 #include "hal/hal_gpio.h"
 
@@ -122,7 +124,8 @@ ble_ll_scan_req_backoff(struct ble_ll_scan_sm *scansm, int 
success)
  *
  * @param scansm Pointer to scanning state machine
  * @param adv_addr Pointer to device address of advertiser
- * @param addr_type 0 if public; non-zero if random
+ * @param addr_type 0 if public; non-zero if random. This is the addr type of
+ *                  the advertiser; not our "own address type"
  */
 static void
 ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm *scansm, uint8_t *adv_addr,
@@ -130,8 +133,12 @@ ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm *scansm, 
uint8_t *adv_addr,
 {
     uint8_t     *dptr;
     uint8_t     pdu_type;
-    uint8_t     *addr;
+    uint8_t     *scana;
     struct os_mbuf *m;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    uint8_t rpa[BLE_DEV_ADDR_LEN];
+    struct ble_ll_resolv_entry *rl;
+#endif
 
     /* Construct first PDU header byte */
     pdu_type = BLE_ADV_PDU_TYPE_SCAN_REQ;
@@ -144,22 +151,39 @@ ble_ll_scan_req_pdu_make(struct ble_ll_scan_sm *scansm, 
uint8_t *adv_addr,
     assert(m != NULL);
 
     /* Get pointer to our device address */
-    if (scansm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_PUBLIC) {
-        addr = g_dev_addr;
-    } else if (scansm->own_addr_type == BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-        pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
-        addr = g_random_addr;
+    if ((scansm->own_addr_type & 1) == 0) {
+        scana = g_dev_addr;
     } else {
-        /* XXX: unsupported for now  */
-        addr = NULL;
-        assert(0);
+        pdu_type |= BLE_ADV_PDU_HDR_TXADD_RAND;
+        scana = g_random_addr;
     }
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    if (scansm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+        if (ble_ll_is_rpa(adv_addr, adv_addr_type)) {
+            rl = NULL;
+            if (scansm->scan_rpa_index >= 0) {
+                /* Generate a RPA to use for scana */
+                rl = &g_ble_ll_resolv_list[scansm->scan_rpa_index];
+            } else {
+                if (ble_ll_resolv_enabled()) {
+                    rl = ble_ll_resolv_list_find(adv_addr, adv_addr_type);
+                }
+            }
+
+            if (rl) {
+                ble_ll_resolv_gen_priv_addr(rl, 1, rpa);
+                scana = rpa;
+            }
+        }
+    }
+#endif
+
     ble_ll_mbuf_init(m, BLE_SCAN_REQ_LEN, pdu_type);
 
     /* Construct the scan request */
     dptr = m->om_data;
-    memcpy(dptr, addr, BLE_DEV_ADDR_LEN);
+    memcpy(dptr, scana, BLE_DEV_ADDR_LEN);
     memcpy(dptr + BLE_DEV_ADDR_LEN, adv_addr, BLE_DEV_ADDR_LEN);
 }
 
@@ -185,16 +209,18 @@ ble_ll_scan_find_dup_adv(uint8_t *addr, uint8_t txadd)
             /* Address type must match */
             if (txadd) {
                 if ((adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) == 0) {
-                    continue;
+                    goto next_dup_adv;
                 }
             } else {
                 if (adv->sc_adv_flags & BLE_LL_SC_ADV_F_RANDOM_ADDR) {
-                    continue;
+                    goto next_dup_adv;
                 }
             }
 
             return adv;
         }
+
+next_dup_adv:
         ++adv;
         --num_advs;
     }
@@ -237,11 +263,12 @@ ble_ll_scan_is_dup_adv(uint8_t pdu_type, uint8_t txadd, 
uint8_t *addr)
  * the list of duplicate addresses when the controller sends an advertising
  * report to the host.
  *
- * @param addr
+ * @param addr   Pointer to advertisers address or identity address
  * @param Txadd. TxAdd bit (0 public, random otherwise)
+ * @param subev  Type of advertising report sent (direct or normal).
  */
 void
-ble_ll_scan_add_dup_adv(uint8_t *addr, uint8_t txadd)
+ble_ll_scan_add_dup_adv(uint8_t *addr, uint8_t txadd, uint8_t subev)
 {
     uint8_t num_advs;
     struct ble_ll_scan_advertisers *adv;
@@ -266,11 +293,11 @@ ble_ll_scan_add_dup_adv(uint8_t *addr, uint8_t txadd)
         }
     }
 
-    /*
-     * XXX: need to set correct flag based on type of report being sent
-     * for now, we dont send direct advertising reports
-     */
-    adv->sc_adv_flags |= BLE_LL_SC_ADV_F_ADV_RPT_SENT;
+    if (subev == BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT) {
+        adv->sc_adv_flags |= BLE_LL_SC_ADV_F_DIRECT_RPT_SENT;
+    } else {
+        adv->sc_adv_flags |= BLE_LL_SC_ADV_F_ADV_RPT_SENT;
+    }
 }
 
 /**
@@ -348,24 +375,37 @@ ble_ll_scan_add_scan_rsp_adv(uint8_t *addr, uint8_t txadd)
  * @param pdu_type
  * @param txadd
  * @param rxbuf
- * @param rssi
+ * @param hdr
+ * @param scansm
  */
 static void
 ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
-                           int8_t rssi)
+                           struct ble_mbuf_hdr *hdr,
+                           struct ble_ll_scan_sm *scansm)
 {
     int rc;
+    int index;
     uint8_t evtype;
     uint8_t subev;
     uint8_t *evbuf;
+    uint8_t *orig_evbuf;
+    uint8_t *adv_addr;
+    uint8_t *inita;
+    uint8_t addr_type;
     uint8_t adv_data_len;
+    uint8_t event_len;
 
+    inita = NULL;
     subev = BLE_HCI_LE_SUBEV_ADV_RPT;
     if (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND) {
-        /* XXX: NOTE: the direct advertising report is only used when InitA
-           is a resolvable private address. We dont support that yet! */
-        //subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT;
+        if (scansm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+            inita = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
+            if ((inita[5] & 0x40) == 0x40) {
+                subev = BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT;
+            }
+        }
         evtype = BLE_HCI_ADV_RPT_EVTYPE_DIR_IND;
+        event_len = BLE_HCI_LE_ADV_DIRECT_RPT_LEN;
         adv_data_len = 0;
     } else {
         if (pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) {
@@ -377,41 +417,61 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t 
txadd, uint8_t *rxbuf,
         } else {
             evtype = BLE_HCI_ADV_RPT_EVTYPE_SCAN_RSP;
         }
-        subev = BLE_HCI_LE_SUBEV_ADV_RPT;
-
         adv_data_len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
         adv_data_len -= BLE_DEV_ADDR_LEN;
+        event_len = BLE_HCI_LE_ADV_RPT_MIN_LEN + adv_data_len;
     }
 
     if (ble_ll_hci_is_le_event_enabled(subev)) {
         evbuf = os_memblock_get(&g_hci_cmd_pool);
         if (evbuf) {
             evbuf[0] = BLE_HCI_EVCODE_LE_META;
-            evbuf[1] = 12 + adv_data_len;
+            evbuf[1] = event_len;
             evbuf[2] = subev;
             evbuf[3] = 1;       /* number of reports */
             evbuf[4] = evtype;
 
-            /* WWW: Yeah... if we are using private resolvable addresses
-               we need to deal here. The address type is different... */
-            /* XXX: need to deal with resolvable addresses here! */
             if (txadd) {
-                evbuf[5] = BLE_HCI_ADV_OWN_ADDR_RANDOM;
+                addr_type = BLE_HCI_ADV_OWN_ADDR_RANDOM;
             } else {
-                evbuf[5] = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
+                addr_type = BLE_HCI_ADV_OWN_ADDR_PUBLIC;
             }
+
             rxbuf += BLE_LL_PDU_HDR_LEN;
-            memcpy(evbuf + 6, rxbuf, BLE_DEV_ADDR_LEN);
-            evbuf[12] = adv_data_len;
-            memcpy(evbuf + 13, rxbuf + BLE_DEV_ADDR_LEN,
-                   adv_data_len);
-            evbuf[13 + adv_data_len] = rssi;
+            if (BLE_MBUF_HDR_RESOLVED(hdr)) {
+                index = scansm->scan_rpa_index;
+                adv_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
+                /*
+                 * NOTE: this looks a bit odd, but the resolved address types
+                 * are 2 greater than the unresolved ones in the spec, so
+                 * we just add 2 here.
+                 */
+                addr_type += 2;
+            } else{
+                adv_addr = rxbuf;
+            }
+
+            orig_evbuf = evbuf;
+            evbuf += 5;
+            if (inita) {
+                evbuf[0] = BLE_HCI_ADV_OWN_ADDR_RANDOM;
+                memcpy(evbuf + 1, inita, adv_data_len);
+                evbuf += BLE_DEV_ADDR_LEN + 1;
+            } else {
+                evbuf[7] = adv_data_len;
+                memcpy(evbuf + 8, rxbuf + BLE_DEV_ADDR_LEN, adv_data_len);
+                evbuf[8 + adv_data_len] = hdr->rxinfo.rssi;
+            }
 
-            rc = ble_ll_hci_event_send(evbuf);
+            /* The advertisers address type and address are always in event */
+            evbuf[0] = addr_type;
+            memcpy(evbuf + 1, adv_addr, BLE_DEV_ADDR_LEN);
+
+            rc = ble_ll_hci_event_send(orig_evbuf);
             if (!rc) {
                 /* If filtering, add it to list of duplicate addresses */
                 if (g_ble_ll_scan_sm.scan_filt_dups) {
-                    ble_ll_scan_add_dup_adv(rxbuf, txadd);
+                    ble_ll_scan_add_dup_adv(adv_addr, txadd, subev);
                 }
             }
         }
@@ -429,7 +489,7 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, 
uint8_t *rxbuf,
  *
  * @return int 0: pdu allowed by filter policy. 1: pdu not allowed
  */
-int
+static int
 ble_ll_scan_chk_filter_policy(uint8_t pdu_type, uint8_t *rxbuf, uint8_t flags)
 {
     uint8_t *addr;
@@ -474,7 +534,7 @@ ble_ll_scan_chk_filter_policy(uint8_t pdu_type, uint8_t 
*rxbuf, uint8_t flags)
         addr = rxbuf + BLE_LL_PDU_HDR_LEN;
         addr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
         if (!ble_ll_is_our_devaddr(addr + BLE_DEV_ADDR_LEN, addr_type)) {
-            if (!chk_inita || !ble_ll_is_resolvable_priv_addr(addr)) {
+            if (!chk_inita || !ble_ll_is_rpa(addr, addr_type)) {
                 return 1;
             }
         }
@@ -511,6 +571,14 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, uint8_t 
chan)
     ble_phy_encrypt_disable();
 #endif
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    if (ble_ll_resolv_enabled()) {
+        ble_phy_resolv_list_enable();
+    } else {
+        ble_phy_resolv_list_disable();
+    }
+#endif
+
     /* Start receiving */
     rc = ble_phy_rx();
     if (!rc) {
@@ -829,10 +897,14 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
 {
     int rc;
     int chk_send_req;
-    int chk_whitelist;
+    int chk_wl;
+    int index;
+    int resolved;
     uint8_t pdu_type;
     uint8_t addr_type;
+    uint8_t peer_addr_type;
     uint8_t *adv_addr;
+    uint8_t *peer;
     uint8_t *rxbuf;
     struct ble_mbuf_hdr *ble_hdr;
     struct ble_ll_scan_sm *scansm;
@@ -863,12 +935,13 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
     /* Get pdu type, pointer to address and address "type"  */
     rxbuf = rxpdu->om_data;
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
-    adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
+    peer = rxbuf + BLE_LL_PDU_HDR_LEN;
     if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
         addr_type = BLE_ADDR_TYPE_RANDOM;
     } else {
         addr_type = BLE_ADDR_TYPE_PUBLIC;
     }
+    peer_addr_type = addr_type;
 
     /* Determine if request may be sent and if whitelist needs to be checked */
     chk_send_req = 0;
@@ -878,34 +951,51 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
         if (scansm->scan_type == BLE_SCAN_TYPE_ACTIVE) {
             chk_send_req = 1;
         }
-        chk_whitelist = 1;
+        chk_wl = 1;
         break;
     case BLE_ADV_PDU_TYPE_ADV_NONCONN_IND:
     case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
-        chk_whitelist = 1;
+        chk_wl = 1;
         break;
     default:
-        chk_whitelist = 0;
+        chk_wl = 0;
         break;
     }
 
-    /* Set device match bit if we are whitelisting */
-    if (chk_whitelist && (scansm->scan_filt_policy & 1)) {
-        /* Check if device is on whitelist. If not, leave */
-        if (!ble_ll_whitelist_match(adv_addr, addr_type)) {
-            return -1;
+    ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+    if ((scansm->scan_filt_policy & 1) == 0) {
+        chk_wl = 0;
+    }
+    resolved = 0;
+
+    index = -1;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    if (ble_ll_is_rpa(peer, peer_addr_type) && ble_ll_resolv_enabled()) {
+        index = ble_hw_resolv_list_match();
+        if (index >= 0) {
+            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_RESOLVED;
+            peer = g_ble_ll_resolv_list[index].rl_identity_addr;
+            peer_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
+            resolved = 1;
+        } else {
+            if (chk_wl) {
+                goto scan_rx_isr_exit;
+            }
         }
-        ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
-        ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
     }
+#endif
+    scansm->scan_rpa_index = index;
+
+    /* If whitelist enabled, check to see if device is in the white list */
+    if (chk_wl && !ble_ll_whitelist_match(peer, peer_addr_type, resolved)) {
+        return -1;
+    }
+    ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_DEVMATCH;
 
     /* Should we send a scan request? */
     if (chk_send_req) {
-        /*
-         * Check to see if we have received a scan response from this
-         * advertisor. If so, no need to send scan request.
-         */
-        if (ble_ll_scan_have_rxd_scan_rsp(adv_addr, addr_type)) {
+        /* Dont send scan request if we have sent one to this advertiser */
+        if (ble_ll_scan_have_rxd_scan_rsp(peer, peer_addr_type)) {
             return -1;
         }
 
@@ -916,6 +1006,7 @@ ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t 
crcok)
         --scansm->backoff_count;
         if (scansm->backoff_count == 0) {
             /* Setup to transmit the scan request */
+            adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
             ble_ll_scan_req_pdu_make(scansm, adv_addr, addr_type);
             rc = ble_phy_tx(scansm->scan_req_pdu, BLE_PHY_TRANSITION_TX_RX);
 
@@ -1006,8 +1097,11 @@ ble_ll_scan_wfr_timer_exp(void)
 void
 ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
 {
+    int index;
     uint8_t *adv_addr;
     uint8_t *adva;
+    uint8_t *ident_addr;
+    uint8_t ident_addr_type;
     uint8_t txadd;
     uint8_t rxadd;
     uint8_t scan_rsp_chk;
@@ -1032,13 +1126,26 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, 
struct ble_mbuf_hdr *hdr)
     txadd = rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK;
     adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
 
+    ident_addr = adv_addr;
+    ident_addr_type = txadd;
+
+    scansm = &g_ble_ll_scan_sm;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    index = scansm->scan_rpa_index;
+    if (index >= 0) {
+        ident_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
+        ident_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
+    }
+#else
+    index = -1;
+#endif
+
     /*
      * XXX: The BLE spec is a bit unclear here. What if we get a scan
      * response from an advertiser that we did not send a request to?
      * Do we send an advertising report? Do we add it to list of devices
      * that we have heard a scan response from?
      */
-    scansm = &g_ble_ll_scan_sm;
     if (ptype == BLE_ADV_PDU_TYPE_SCAN_RSP) {
         /*
          * If this is a scan response in reply to a request we sent we need
@@ -1056,7 +1163,7 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, 
struct ble_mbuf_hdr *hdr)
             if (((txadd && rxadd) || ((txadd + rxadd) == 0)) &&
                 !memcmp(adv_addr, adva, BLE_DEV_ADDR_LEN)) {
                 /* We have received a scan response. Add to list */
-                ble_ll_scan_add_scan_rsp_adv(adv_addr, txadd);
+                ble_ll_scan_add_scan_rsp_adv(ident_addr, ident_addr_type);
 
                 /* Perform scan request backoff procedure */
                 ble_ll_scan_req_backoff(scansm, 1);
@@ -1066,13 +1173,13 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, 
struct ble_mbuf_hdr *hdr)
 
     /* Filter duplicates */
     if (scansm->scan_filt_dups) {
-        if (ble_ll_scan_is_dup_adv(ptype, txadd, adv_addr)) {
+        if (ble_ll_scan_is_dup_adv(ptype, ident_addr_type, ident_addr)) {
             goto scan_continue;
         }
     }
 
     /* Send the advertising report */
-    ble_ll_hci_send_adv_report(ptype, txadd, rxbuf, hdr->rxinfo.rssi);
+    ble_ll_hci_send_adv_report(ptype, ident_addr_type, rxbuf, hdr, scansm);
 
 scan_continue:
     /*
@@ -1237,6 +1344,61 @@ ble_ll_scan_enabled(void)
     return (int)g_ble_ll_scan_sm.scan_enabled;
 }
 
+/**
+ * Returns the peer resolvable private address of last device connecting to us
+ *
+ * @return uint8_t*
+ */
+uint8_t *
+ble_ll_scan_get_peer_rpa(void)
+{
+    struct ble_ll_scan_sm *scansm;
+
+    /* XXX: should this go into IRK list or connection? */
+    scansm = &g_ble_ll_scan_sm;
+    return scansm->scan_peer_rpa;
+}
+
+/**
+ * Returns the local resolvable private address currently being using by
+ * the scanner/initiator
+ *
+ * @return uint8_t*
+ */
+uint8_t *
+ble_ll_scan_get_local_rpa(void)
+{
+    uint8_t *rpa;
+    struct ble_ll_scan_sm *scansm;
+
+    scansm = &g_ble_ll_scan_sm;
+
+    /*
+     * The RPA we used is in connect request or scan request and is the
+     * first address in the packet
+     */
+    rpa = scansm->scan_req_pdu->om_data;
+
+    return rpa;
+}
+
+/**
+ * Set the Resolvable Private Address in the scanning (or initiating) state
+ * machine.
+ *
+ * XXX: should this go into IRK list or connection?
+ *
+ * @param rpa
+ */
+void
+ble_ll_scan_set_peer_rpa(uint8_t *rpa)
+{
+    struct ble_ll_scan_sm *scansm;
+
+    scansm = &g_ble_ll_scan_sm;
+    memcpy(scansm->scan_peer_rpa, rpa, BLE_DEV_ADDR_LEN);
+}
+
 /* Returns the PDU allocated by the scanner */
 struct os_mbuf *
 ble_ll_scan_get_pdu(void)
@@ -1244,13 +1406,6 @@ ble_ll_scan_get_pdu(void)
     return g_ble_ll_scan_sm.scan_req_pdu;
 }
 
-/* Returns the global scanning state machine */
-struct ble_ll_scan_sm *
-ble_ll_scan_sm_get(void)
-{
-    return &g_ble_ll_scan_sm;
-}
-
 /* Returns true if whitelist is enabled for scanning */
 int
 ble_ll_scan_whitelist_enabled(void)
@@ -1320,4 +1475,3 @@ ble_ll_scan_init(void)
                                               sizeof(struct ble_mbuf_hdr));
     assert(scansm->scan_req_pdu != NULL);
 }
-

Reply via email to