You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by we...@apache.org on 2015/11/14 02:26:33 UTC

incubator-mynewt-larva git commit: Start of connection process finished. Sending connect requests and receiving them and starting the connection is finished.

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master c6ccb0e8e -> d478f7bce


Start of connection process finished. Sending connect requests and receiving them and starting the connection is finished.


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

Branch: refs/heads/master
Commit: d478f7bce60928125771d781b051dab566b42ad8
Parents: c6ccb0e
Author: wes3 <wi...@micosa.io>
Authored: Fri Nov 13 17:26:13 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Fri Nov 13 17:26:28 2015 -0800

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll.h      |  13 +-
 .../controller/include/controller/ble_ll_adv.h  |   3 +
 .../controller/include/controller/ble_ll_conn.h |  16 +
 .../controller/include/controller/ble_ll_scan.h |  45 +-
 net/nimble/controller/src/ble_ll.c              |  53 +-
 net/nimble/controller/src/ble_ll_adv.c          | 175 ++++--
 net/nimble/controller/src/ble_ll_conn.c         | 604 +++++++++++++++++--
 net/nimble/controller/src/ble_ll_hci.c          |   1 +
 net/nimble/controller/src/ble_ll_scan.c         |  81 ++-
 net/nimble/drivers/nrf52/src/ble_phy.c          |   5 +
 10 files changed, 829 insertions(+), 167 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 c93b55f..317cb2c 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -70,8 +70,8 @@ extern struct ble_ll_obj g_ble_ll_data;
 #define BLE_LL_STATE_STANDBY        (0)
 #define BLE_LL_STATE_ADV            (1)
 #define BLE_LL_STATE_SCANNING       (2)
-#define BLE_LL_STATE_INITITATING    (3)
-#define BLE_LL_STATE_CONNECT        (4)
+#define BLE_LL_STATE_INITIATING     (3)
+#define BLE_LL_STATE_CONNECTION     (4)
 
 /* BLE LL Task Events */
 #define BLE_LL_EVENT_HCI_CMD        (OS_EVENT_T_PERUSER)
@@ -402,15 +402,6 @@ struct ble_conn_req_data
 #define BLE_CONN_REQ_HOP_MASK           (0x1F)
 #define BLE_CONN_REQ_SCA_MASK           (0xE0)
 
-#define BLE_MASTER_SCA_251_500_PPM      (0)
-#define BLE_MASTER_SCA_151_250_PPM      (1)
-#define BLE_MASTER_SCA_101_150_PPM      (2)
-#define BLE_MASTER_SCA_76_100_PPM       (3)
-#define BLE_MASTER_SCA_51_75_PPM        (4)
-#define BLE_MASTER_SCA_31_50_PPM        (5)
-#define BLE_MASTER_SCA_21_30_PPM        (6)
-#define BLE_MASTER_SCA_0_20_PPM         (7)
-
 /*
  * Initiator filter policy 
  * 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 664668a..1e985b0 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -125,4 +125,7 @@ int ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu);
 /* Boolean function denoting whether or not the whitelist can be changed */
 int ble_ll_adv_can_chg_whitelist(void);
 
+/* Called when a connection request has been received at the link layer */
+void ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, uint8_t flags);
+
 #endif /* H_BLE_LL_ADV_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 7c58b67..ff62ff6 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -17,7 +17,23 @@
 #ifndef H_BLE_LL_CONN_
 #define H_BLE_LL_CONN_
 
+/* Definitions for source clock accuracy */
+#define BLE_MASTER_SCA_251_500_PPM      (0)
+#define BLE_MASTER_SCA_151_250_PPM      (1)
+#define BLE_MASTER_SCA_101_150_PPM      (2)
+#define BLE_MASTER_SCA_76_100_PPM       (3)
+#define BLE_MASTER_SCA_51_75_PPM        (4)
+#define BLE_MASTER_SCA_31_50_PPM        (5)
+#define BLE_MASTER_SCA_21_30_PPM        (6)
+#define BLE_MASTER_SCA_0_20_PPM         (7)
+
 int ble_ll_conn_create(uint8_t *cmdbuf);
 int ble_ll_conn_create_cancel(void);
+int ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva);
+int ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva);
+void ble_ll_init_rx_pdu_proc(uint8_t pdu_type, uint8_t *rxbuf, uint8_t crcok);
+int ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu);
+int ble_ll_init_rx_pdu_start(uint8_t pdu_type);
+void ble_ll_conn_slave_start(uint8_t *rxbuf);
 
 #endif /* H_BLE_LL_CONN_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 b7ce24f..bb296e7 100644
--- a/net/nimble/controller/include/controller/ble_ll_scan.h
+++ b/net/nimble/controller/include/controller/ble_ll_scan.h
@@ -17,6 +17,10 @@
 #ifndef H_BLE_LL_SCAN_
 #define H_BLE_LL_SCAN_
 
+/* 
+ * Configuration items for the number of duplicate advertisers and the
+ * number of advertisers from which we have heard a scan response 
+ */
 #define BLE_LL_SCAN_CFG_NUM_DUP_ADVS         (8)
 #define BLE_LL_SCAN_CFG_NUM_SCAN_RSP_ADVS    (8)
 
@@ -28,9 +32,6 @@
     #error "Cannot have more than 255 scan response entries!"
 #endif
 
-/* Maximum amount of scan response data in a scan response */
-#define BLE_SCAN_RSP_DATA_MAX_LEN       (31)
-
 /*
  * SCAN_REQ 
  *      -> ScanA    (6 bytes)
@@ -56,9 +57,36 @@
  * Sent by the LL in the advertising state; received by the LL in the
  * scanning state. 
  */
+#define BLE_SCAN_RSP_DATA_MAX_LEN       (31)
 #define BLE_SCAN_RSP_MIN_LEN            (6)
 #define BLE_SCAN_RSP_MAX_LEN            (6 + BLE_SCAN_RSP_DATA_MAX_LEN)
 
+/* Scanning state machine (used when initiating as well) */
+struct ble_ll_scan_sm
+{
+    uint8_t scan_enabled;
+    uint8_t scan_type;
+    uint8_t own_addr_type;
+    uint8_t scan_chan;
+    uint8_t scan_filt_policy;
+    uint8_t scan_filt_dups;
+    uint8_t scan_rsp_pending;
+    uint8_t scan_rsp_cons_fails;
+    uint8_t scan_rsp_cons_ok;
+    uint16_t upper_limit;
+    uint16_t backoff_count;
+    uint16_t scan_itvl;
+    uint16_t scan_window;
+    uint32_t scan_win_start_time;
+    struct os_mbuf *scan_req_pdu;
+    struct os_event scan_win_end_ev;
+};
+
+/* Scan types */
+#define BLE_SCAN_TYPE_PASSIVE   (BLE_HCI_SCAN_TYPE_PASSIVE)
+#define BLE_SCAN_TYPE_ACTIVE    (BLE_HCI_SCAN_TYPE_ACTIVE)
+#define BLE_SCAN_TYPE_INITIATE  (2)
+
 /*---- HCI ----*/
 /* Set scanning parameters */
 int ble_ll_scan_set_scan_params(uint8_t *cmd);
@@ -89,11 +117,20 @@ int ble_ll_scan_can_chg_whitelist(void);
 /* Boolean function returning true if scanning enabled */
 int ble_ll_scan_enabled(void);
 
+/* Boolean function returns true if whitelist is enabled for scanning */
+int ble_ll_scan_whitelist_enabled(void);
+
 /* Initialize the scanner when we start initiating */
 struct hci_create_conn;
-void ble_ll_scan_initiator_start(struct hci_create_conn *hcc);
+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);
 
+/* Stop the scanning state machine */
+void ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm);
+
+/* 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-larva/blob/d478f7bc/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 be327c3..645fdde 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -24,8 +24,17 @@
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_conn.h"
 #include "controller/ble_ll_hci.h"
 
+/* 
+ * XXX: Just thought of something! Can I always set the DEVMATCH bit at
+ * the lower layer? This way the LL just looks at devmatch when it wants
+ * to see if a packet is "for us". I am referring to packets that pass
+ * whitelisting but also need to be "for us" (connect requests, scan requests,
+ * scan responses, etc). Look into this. This way I would not need to do
+   additional whitelist checks at the upper layer. */
+
 /* XXX:
  * 
  * 1) use the sanity task!
@@ -202,21 +211,29 @@ ble_ll_set_random_addr(uint8_t *addr)
     return rc;
 }
 
+/**
+ * Checks to see if an address is our device address (either public or 
+ * random) 
+ * 
+ * @param addr 
+ * @param addr_type 
+ * 
+ * @return int 
+ */
 int
 ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
 {
     int rc;
     uint8_t *our_addr;
 
-    rc = 0;
     if (addr_type) {
-        our_addr = g_dev_addr;
-    } else {
         our_addr = g_random_addr;
+    } else {
+        our_addr = g_dev_addr;
     }
 
     rc = 0;
-    if (!memcmp(our_addr, g_random_addr, BLE_DEV_ADDR_LEN)) {
+    if (!memcmp(our_addr, addr, BLE_DEV_ADDR_LEN)) {
         rc = 1;
     }
 
@@ -245,9 +262,9 @@ ble_ll_pdu_tx_time_get(uint16_t len)
 /**
  * ll rx pkt in proc
  *  
- * Process received packet from PHY 
+ * Process received packet from PHY.
  *  
- * Callers: LL task. 
+ * Context: Link layer task
  *  
  */
 void
@@ -295,7 +312,9 @@ ble_ll_rx_pkt_in_proc(void)
         /* Process the PDU */
         switch (g_ble_ll_data.ll_state) {
         case BLE_LL_STATE_ADV:
-            /* XXX: implement this */
+            if (ble_hdr->crcok && (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+                ble_ll_adv_conn_req_rxd(rxbuf, ble_hdr->flags);
+            }
             break;
         case BLE_LL_STATE_SCANNING:
             if (ble_hdr->crcok) {
@@ -310,8 +329,14 @@ ble_ll_rx_pkt_in_proc(void)
                 ble_phy_rx();
             }
             break;
-        default:
+        case BLE_LL_STATE_INITIATING:
+            ble_ll_init_rx_pdu_proc(pdu_type, rxbuf, ble_hdr->crcok);
+            break;
+        case BLE_LL_STATE_CONNECTION:
             /* XXX: implement */
+            break;
+        default:
+            /* We should not receive packets in standby state! */
             assert(0);
             break;
         }
@@ -369,9 +394,13 @@ ble_ll_rx_start(struct os_mbuf *rxpdu)
             rc = -1;
         }
         break;
+    case BLE_LL_STATE_INITIATING:
+        rc = ble_ll_init_rx_pdu_start(pdu_type);
+        break;
     case BLE_LL_STATE_SCANNING:
         rc = ble_ll_scan_rx_pdu_start(pdu_type, rxpdu);
         break;
+    case BLE_LL_STATE_CONNECTION:
     default:
         /* XXX: should we really assert here? What to do... */
         rc = -1;
@@ -465,6 +494,14 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t crcok)
             rc = ble_ll_scan_rx_pdu_end(rxpdu);
         }
         break;
+    case BLE_LL_STATE_INITIATING:
+        if (crcok) {
+            rc = ble_ll_init_rx_pdu_end(rxpdu);
+        }
+        break;
+    case BLE_LL_STATE_CONNECTION:
+        /* XXX */
+        break;
     default:
         assert(0);
         break;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 18af12d..67acf8f 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -25,6 +25,7 @@
 #include "controller/ble_ll_adv.h"
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_conn.h"
 #include "controller/ble_ll_whitelist.h"
 #include "hal/hal_cputime.h"
 #include "hal/hal_gpio.h"
@@ -52,12 +53,18 @@
  * now, we set it to max.
  * 6) Currently, when we set scheduling events, we dont take into account
  * processor overhead/delays. We will want to do that.
- * 7) Need to implement the whole HCI command done stuff.
  * 8) For set adv enable command: if we get a connection, or we time out,
  *    we need to send a CONNECTION COMPLETE event. Do this.
  * 9) How does the advertising channel tx power get set? I dont implement
  * that currently.
  * 10) Deal with whitelisting at LL when pdu is handed up to LL task.
+ * 11) What about High duty cycle advertising? Do we exit the advertising state
+ * after 1.28 seconds automatically? Seems like we do!!! 4.4.2.4.2 Vol 6 Part B
+ * => YES! we have to implement this and set back a CONN COMPLETE event with
+ *    error code DIRECTED ADV TIMEOUT.
+ * 12) Something to consider: if we are attempting to advertise but dont have
+ * any connection state machines available, I dont think we should enable
+ * advertising.
  */
 
 /* 
@@ -147,6 +154,37 @@ ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm)
     return adv_chan;
 }
 
+
+/**
+ * Compares the advertiser address in an advertising PDU with our
+ * address to see if there is a match
+ * 
+ * @param rxbuf Pointer to received PDU
+ * 
+ * @return int Returns memcmp return values (0 = match).
+ */
+static int
+ble_ll_adv_addr_cmp(uint8_t *rxbuf)
+{
+    int rc;
+    uint8_t *adva;
+    uint8_t *our_addr;
+    uint8_t rxaddr_type;
+
+    /* Determine if this is addressed to us */
+    rxaddr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
+    if (rxaddr_type) {
+        our_addr = g_random_addr;
+    } else {
+        our_addr = g_dev_addr;
+    }
+
+    adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
+    rc = memcmp(our_addr, adva, BLE_DEV_ADDR_LEN);
+
+    return rc;
+}
+
 /**
  * Create the advertising PDU 
  * 
@@ -753,61 +791,60 @@ ble_ll_adv_set_adv_data(uint8_t *cmd, uint8_t len)
 }
 
 /**
- * Called when the LL receives a scan request.  
+ * Called when the LL receives a scan request or connection request
  *  
  * Context: Called from interrupt context. 
  * 
  * @param rxbuf 
  * 
- * @return -1: scan request not for us. 
- *          0: Scan request is for us and we successfully went from rx to tx.
+ * @return -1: request not for us or is a connect request. 
+ *          0: request (scan) is for us and we successfully went from rx to tx.
  *        > 0: PHY error attempting to go from rx to tx.
  */
 static int
-ble_ll_adv_rx_scan_req(struct os_mbuf *rxpdu)
+ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
 {
     int rc;
-    uint8_t rxaddr_type;
-    uint8_t *our_addr;
-    uint8_t *adva;
-    uint8_t addr_type;
+    uint8_t chk_whitelist;
+    uint8_t txadd;
     uint8_t *rxbuf;
     struct ble_mbuf_hdr *ble_hdr;
     struct ble_ll_adv_sm *advsm;
 
-    /* Determine if this is addressed to us */
     rxbuf = rxpdu->om_data;
-    rxaddr_type = rxbuf[0] & BLE_ADV_PDU_HDR_RXADD_MASK;
-    if (rxaddr_type) {
-        our_addr = g_random_addr;
+    if (ble_ll_adv_addr_cmp(rxbuf)) {
+        return -1;
+    }
+
+    /* Set device match bit if we are whitelisting */
+    advsm = &g_ble_ll_adv_sm;
+    if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
+        chk_whitelist = advsm->adv_filter_policy & 1;
     } else {
-        our_addr = g_dev_addr;
+        chk_whitelist = advsm->adv_filter_policy & 2;
     }
 
-    rc = -1;
-    adva = rxbuf + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN;
-    if (!memcmp(our_addr, adva, BLE_DEV_ADDR_LEN)) {
-        /* Set device match bit if we are whitelisting */
-        advsm = &g_ble_ll_adv_sm;
-        if (advsm->adv_filter_policy & 1) {
-            /* Get the scanners address type */
-            if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
-                addr_type = BLE_ADDR_TYPE_RANDOM;
-            } else {
-                addr_type = BLE_ADDR_TYPE_PUBLIC;
-            }
-
-            /* Check for whitelist match */
-            if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, 
-                                        addr_type)) {
-                return rc;
-            } else {
-                ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
-                ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
-            }
+    /* 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;
         }
 
-        /* Setup to transmit the scan response */
+        /* Check for whitelist match */
+        if (!ble_ll_whitelist_match(rxbuf + BLE_LL_PDU_HDR_LEN, txadd)) {
+            return -1;
+        } else {
+            ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+            ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
+        }
+    }
+
+    /* Setup to transmit the scan response if appropriate */
+    rc = -1;
+    if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
         rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_RX_TX, 
                         BLE_PHY_TRANSITION_NONE);
         if (!rc) {
@@ -819,16 +856,60 @@ ble_ll_adv_rx_scan_req(struct os_mbuf *rxpdu)
 }
 
 /**
- * Called on phy rx pdu end when in advertising state.
+ * Called when a connect request has been received. 
+ *  
+ * Context: Link Layer 
+ * 
+ * @param rxbuf 
+ * @param flags 
+ */
+void
+ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, uint8_t flags)
+{
+    int valid;
+    struct ble_ll_adv_sm *advsm;
+
+    /* Check filter policy. */
+    valid = 0;
+    advsm = &g_ble_ll_adv_sm;
+    if (advsm->adv_filter_policy & 2) {
+        if (flags & BLE_MBUF_HDR_F_DEVMATCH) {
+            /* valid connection request received */
+            valid = 1;
+        }
+    } else {
+        /* If this is for us? */
+        if (!ble_ll_adv_addr_cmp(rxbuf)) {
+            valid = 1;
+        }
+    }
+
+    if (valid) {
+        /* Stop advertising and start connection */
+        ble_ll_adv_sm_stop(advsm);
+        ble_ll_conn_slave_start(rxbuf);
+    }
+}
+
+/**
+ * Called on phy rx pdu end when in advertising state. 
+ *  
+ * There are only two pdu types we care about in this state: scan requests 
+ * and connection requests. When we receive a scan request we must determine if 
+ * we need to send a scan response and that needs to be acted on within T_IFS.
+ *  
+ * When we receive a connection request, we need to determine if we will allow 
+ * this device to start a connection with us. However, no immediate response is 
+ * sent so we handle this at the link layer task. 
  * 
  * Context: Interrupt 
  *  
- * @param pdu_type 
- * @param rxpdu 
+ * @param pdu_type Type of pdu received.
+ * @param rxpdu Pointer to received PDU
  *  
  * @return int 
  *       < 0: Disable the phy after reception.
- *      == 0: Do not disable the PHY as we are gi
+ *      == 0: Do not disable the PHY
  *       > 0: Do not disable PHY as that has already been done.
  */
 int
@@ -836,22 +917,20 @@ ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu)
 {
     int rc;
 
-    /* We only care about scan requests and connection requests */
     rc = -1;
-    if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
-        rc = ble_ll_adv_rx_scan_req(rxpdu);
+    if ((pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) ||
+        (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ)) {
+        /* Process request */
+        rc = ble_ll_adv_rx_req(pdu_type, rxpdu);
         if (rc) {
             /* XXX: One thing left to reconcile here. We have
              * the advertisement schedule element still running.
              * How to deal with the end of the advertising event?
              * Need to figure that out.
+             * 
+             * XXX: This applies to connection requests as well.
              */
         }
-    } else {
-        if (pdu_type == BLE_ADV_PDU_TYPE_CONNECT_REQ) {
-            rc = 0;
-            /* XXX: deal with this. Dont forget filter policy  */
-        }
     }
 
     return rc;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 0f1f46c..58b2097 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -22,25 +22,53 @@
 #include "nimble/ble.h"
 #include "nimble/hci_common.h"
 #include "controller/ble_ll.h"
+#include "controller/ble_ll_hci.h"
 #include "controller/ble_ll_conn.h"
 #include "controller/ble_ll_scan.h"
+#include "controller/ble_ll_whitelist.h"
 #include "controller/ble_phy.h"
 
 /* XXX TODO
  * 1) Implemement connection supervisor timeout.
- * 2) Create connection request.
- * 3) Process rxd connection request.
- * 4) What about channel map. Where is that set?
- * 5) Review data channel index selection
- * 6) Closing the connection: the MD bit.
- * 7) notifying host about connections: how often do we need to do this? On
+ * 2) Add set channel map command and implement channel change procedure.
+ * 3) Closing the connection: the MD bit.
+ * 4) notifying host about connections: how often do we need to do this? On
  * creation, establishment and/or loss?
- * 8) Deal with window widening. Easy...
- * 9) Close connection if window widening gets too big! 4.5.7
- * 10) portions of the connect request need to be modified (possibly) based
- * on the advertiser.
+ * 5) Deal with window widening. Easy...
+ * 6) Close connection if window widening gets too big! 4.5.7
+ * 7) How does state get set to ESTABLISHED? Do that...
+ * 8) In both cases when I start the connection SM I need to set up a
+ * schedule item to deal with receiving packets and transmitting them.
+ * 9) Implement flow control and all that.
+ * 10) Implement getting a data packet. How do we do that?
+ * 11) Send connection complete event when connection dies.
  */
 
+/* XXX: Something I need to think about. At what point do I consider the
+ * connection created? When I send the connect request or when I send
+ * the connection complete event. I just dont want there to be weird race
+ * conditions if I get cancel connection create command. I want to make
+ * sure that I deal with that properly. I think the connection state will tell
+ * me. Anyway, just make sure there are no issues here
+ */
+
+/* Channel map size */
+#define BLE_LL_CONN_CHMAP_LEN           (5)
+
+/* Configuration parameters */
+#define BLE_LL_CONN_CFG_TX_WIN_SIZE     (1)
+#define BLE_LL_CONN_CFG_TX_WIN_OFF      (0)
+#define BLE_LL_CONN_CFG_MASTER_SCA      (BLE_MASTER_SCA_251_500_PPM << 5)
+#define BLE_LL_CONN_CFG_MAX_CONNS       (8)
+
+/* Roles */
+#define BLE_LL_CONN_ROLE_NONE           (0)
+#define BLE_LL_CONN_ROLE_MASTER         (1)
+#define BLE_LL_CONN_ROLE_SLAVE          (2)
+
+/* Connection request */
+#define BLE_LL_CONN_REQ_ADVA_OFF        (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
+
 /* Scanning state machine */
 struct ble_ll_conn_sm
 {
@@ -48,17 +76,23 @@ struct ble_ll_conn_sm
     uint8_t unmapped_chan;
     uint8_t last_unmapped_chan;
     uint8_t num_used_chans;
-    uint8_t chanmap[5];
+    uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
     uint8_t hop_inc;
     uint8_t conn_state;
+    uint8_t conn_role;
+    uint8_t master_sca;
+    uint8_t conn_tx_win_size;
     uint8_t own_addr_type;
     uint8_t peer_addr_type;
     uint8_t peer_addr[BLE_DEV_ADDR_LEN];
     uint16_t conn_spvn_tmo;
+    uint16_t conn_itvl;
     uint16_t conn_slave_latency;
     uint16_t conn_event_cntr;
+    uint16_t conn_handle;
+    uint16_t conn_tx_win_off;
     uint32_t access_addr;
-    struct os_mbuf *conn_req_pdu;
+    uint32_t crcinit;       /* only low 24 bits used */
 };
 
 struct ble_ll_conn_sm g_ble_ll_conn_sm;
@@ -68,6 +102,84 @@ struct ble_ll_conn_sm g_ble_ll_conn_sm;
 #define BLE_LL_CONN_STATE_CREATED       (1)
 #define BLE_LL_CONN_STATE_ESTABLISHED   (2)
 
+/* Connection handles */
+static uint8_t g_ble_ll_conn_handles[(BLE_LL_CONN_CFG_MAX_CONNS + 7) / 8];
+static uint16_t g_ble_ll_conn_handles_out;
+
+struct os_mempool g_ble_ll_conn_pool;
+os_membuf_t g_ble_ll_conn_buf[OS_MEMPOOL_SIZE(BLE_LL_CONN_CFG_MAX_CONNS, 
+                                              sizeof(struct ble_ll_conn_sm))];
+
+/**
+ * Calculates the number of used channels in the channel map 
+ * 
+ * @param chmap 
+ * 
+ * @return uint8_t Number of used channels
+ */
+uint8_t
+ble_ll_conn_calc_used_chans(uint8_t *chmap)
+{
+    int i;
+    int j;
+    uint8_t mask;
+    uint8_t chanbyte;
+    uint8_t used_channels;
+
+    used_channels = 0;
+    for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; ++i) {
+        chanbyte = chmap[i];
+        if (chanbyte) {
+            if (chanbyte == 0xff) {
+                used_channels += 8;
+            } else {
+                mask = 0x01;
+                for (j = 0; j < 8; ++j) {
+                    if (chanbyte & mask) {
+                        ++used_channels;
+                    }
+                    mask <<= 1;
+                }
+            }
+        }
+    }
+    return used_channels;
+}
+
+
+static uint16_t
+ble_ll_conn_get_unused_handle(void)
+{
+    uint8_t bytepos;
+    uint8_t bitpos;
+    int handle;
+
+    /* Keep track of total number so you can deny it! */
+    if (g_ble_ll_conn_handles_out == BLE_LL_CONN_CFG_MAX_CONNS) {
+        /* Handles can only be in range 0 to 0x0EFF */
+        return 0xFFFF;
+    }
+
+    /* Return an unused handle */
+    for (handle = 0; handle < BLE_LL_CONN_CFG_MAX_CONNS; ++handle) {
+        /* Get byte position and bit position */
+        bytepos = handle / 8;
+        bitpos = handle & 0x7;
+
+        /* See if handle avaiable */
+        if ((g_ble_ll_conn_handles[bytepos] & (1 << bitpos)) == 0) {
+            g_ble_ll_conn_handles[bytepos] |= (1 << bitpos);
+            ++g_ble_ll_conn_handles_out;
+            break;
+        }
+    }
+
+    /* We better have a free one! If not, something wrong! */
+    assert(handle < BLE_LL_CONN_CFG_MAX_CONNS);
+
+    return handle;
+}
+
 static uint32_t
 ble_ll_conn_calc_access_addr(void)
 {
@@ -191,7 +303,7 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
            we just calculate */
         /* Iterate through channel map to find this channel */
         cntr = 0;
-        for (i = 0; i < 5; i++) {
+        for (i = 0; i < BLE_LL_CONN_CHMAP_LEN; i++) {
             usable_chans = conn->chanmap[i];
             if (usable_chans != 0) {
                 mask = 0x01;
@@ -213,40 +325,129 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
 
 /**
  * Initialize the connection state machine. This is done once per connection 
- * when the HCI command "create connection" is issued to the controller. 
+ * when the HCI command "create connection" is issued to the controller or 
+ * when a slave receives a connect request, 
  * 
  * @param connsm 
  */
-void
+static void
 ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
 {
-    /* Hop increment is a random value between 5 and 16. */
-    connsm->hop_inc = (rand() % 12) + 5;
-
-    /* Reset event counter */
+    /* Reset event counter and last unmapped channel; get a handle */
+    connsm->last_unmapped_chan = 0;
     connsm->conn_event_cntr = 0;
+    connsm->conn_handle = ble_ll_conn_get_unused_handle();
+
+    if (hcc != NULL) {
+        /* Must be master */
+        connsm->conn_role = BLE_LL_CONN_ROLE_MASTER;
+        connsm->conn_tx_win_size = BLE_LL_CONN_CFG_TX_WIN_SIZE;
+        connsm->conn_tx_win_off = BLE_LL_CONN_CFG_TX_WIN_OFF;
+        connsm->master_sca = BLE_LL_CONN_CFG_MASTER_SCA;
+
+        /* Hop increment is a random value between 5 and 16. */
+        connsm->hop_inc = (rand() % 12) + 5;
+
+        /* Set slave latency, supervision timeout and connection interval */
+        connsm->conn_slave_latency = hcc->conn_latency;
+        connsm->conn_spvn_tmo = hcc->supervision_timeout;
+        /* XXX: for now, just make connection interval equal to max */
+        connsm->conn_itvl = hcc->conn_itvl_max;
+
+        /* Set own address type and peer address if needed */
+        connsm->own_addr_type = hcc->own_addr_type;
+        if (hcc->filter_policy == 0) {
+            memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
+            connsm->peer_addr_type = hcc->peer_addr_type;
+        }
 
-    /* Set slave latency */
-    connsm->conn_slave_latency = hcc->conn_latency;
-    connsm->conn_spvn_tmo = hcc->supervision_timeout;
+        /* XXX: what to do with min/max connection event length? */
 
-    /* Set own address type and peer address if needed */
-    connsm->own_addr_type = hcc->own_addr_type;
-    if (hcc->filter_policy == 0) {
-        memcpy(&connsm->peer_addr, &hcc->peer_addr, BLE_DEV_ADDR_LEN);
-        connsm->peer_addr_type = hcc->peer_addr_type;
+        /* XXX: for now, just set the channel map to all 1's. Needs to get
+           set to default or initialized or something */
+        connsm->num_used_chans = 37;
+        memset(connsm->chanmap, 0xff, BLE_LL_CONN_CHMAP_LEN - 1);
+        connsm->chanmap[4] = 0x1f;
+
+        /*  Calculate random access address and crc initialization value */
+        connsm->access_addr = ble_ll_conn_calc_access_addr();
+        connsm->crcinit = rand() & 0xffffff;
+    } else {
+        connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
+    }
+}
+
+/**
+ * Send a connection complete event 
+ * 
+ * @param status The BLE error code associated with the event
+ */
+static void
+ble_ll_conn_comp_event_send(uint8_t status)
+{
+    uint8_t *evbuf;
+    struct ble_ll_conn_sm *connsm;
+
+    if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_COMPLETE - 1)) {
+        evbuf = os_memblock_get(&g_hci_cmd_pool);
+        if (evbuf) {
+            connsm = &g_ble_ll_conn_sm;
+            evbuf[0] = BLE_HCI_EVCODE_LE_META;
+            evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+            evbuf[3] = status;
+            if (status == BLE_ERR_SUCCESS) {
+                htole16(evbuf + 4, connsm->conn_handle);
+                evbuf[6] = connsm->conn_role;
+                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->conn_slave_latency);
+                evbuf[18] = connsm->master_sca;
+            }
+
+            /* XXX: what to do if we fail to send event? */
+            ble_ll_hci_event_send(evbuf);
+        }
     }
+}
+
+/**
+ * Update the connection request PDU with the address type and address of 
+ * advertiser we are going to send connect request to. 
+ * 
+ * @param m 
+ * @param adva 
+ * @param addr_type 
+ */
+void
+ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type)
+{
+    uint8_t pdu_type;
+    uint8_t *dptr;
 
-    /* XXX: set connection interval */
-    /* XXX: what to do with min/max connection event? */
-    /* XXX: where does the channel map get set? */
+    assert(m != NULL);
 
-    /* XXX: Calculate random access address */
-    connsm->access_addr = ble_ll_conn_calc_access_addr();
+    dptr = m->om_data;
+    pdu_type = dptr[0];
+    if (addr_type) {
+        /* Set random address */
+        pdu_type |= BLE_ADV_PDU_HDR_RXADD_MASK;
+    } else {
+        /* Set public device address */
+        pdu_type &= ~BLE_ADV_PDU_HDR_RXADD_MASK;
+    }
+    dptr[0] = pdu_type;
+    memcpy(dptr + BLE_LL_CONN_REQ_ADVA_OFF, adva, BLE_DEV_ADDR_LEN); 
 }
 
+/**
+ * Make a connect request PDU 
+ * 
+ * @param connsm 
+ */
 void
-ble_ll_conn_req_make(struct ble_ll_conn_sm *connsm)
+ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
 {
     uint8_t pdu_type;
     uint8_t *addr;
@@ -275,17 +476,25 @@ ble_ll_conn_req_make(struct ble_ll_conn_sm *connsm)
 
     /* Construct the connect request */
     dptr = m->om_data;
-    dptr[0] = pdu_type;     /* XXX: this can change based on advertiser addr */
+    dptr[0] = pdu_type;
     dptr[1] = BLE_CONNECT_REQ_LEN;
     memcpy(dptr + BLE_LL_PDU_HDR_LEN, addr, BLE_DEV_ADDR_LEN);
-    /* XXX: what about this next address? I cant put this in here yet, right? */
-#if 0
-    memcpy(dptr + BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN, adv_addr, 
-           BLE_DEV_ADDR_LEN);
-#endif
-    dptr += BLE_LL_PDU_HDR_LEN + (2 * BLE_DEV_ADDR_LEN);
+
+    /* Skip the advertiser's address as we dont know that yet */
+    dptr += (BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN);
 
     /* Access address */
+    htole32(dptr, connsm->access_addr);
+    dptr[4] = connsm->crcinit >> 16;
+    dptr[5] = connsm->crcinit >> 8;
+    dptr[6] = (uint8_t)connsm->crcinit;
+    dptr[7] = connsm->conn_tx_win_size;
+    htole16(dptr + 8, connsm->conn_tx_win_off);
+    htole16(dptr + 10, connsm->conn_itvl);
+    htole16(dptr + 12, connsm->conn_slave_latency);
+    htole16(dptr + 14, connsm->conn_spvn_tmo);
+    memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CONN_CHMAP_LEN);
+    dptr[21] = connsm->hop_inc | connsm->master_sca;
 }
 
 /**
@@ -304,6 +513,13 @@ ble_ll_conn_create(uint8_t *cmdbuf)
     struct hci_create_conn *hcc;
     struct ble_ll_conn_sm *connsm;
 
+    /* XXX: what happens if we have too many! Do something about this */
+
+    /* 
+     * XXX: right now, we only allow one connection, so if the connection
+     * state machine is used we return error. Otherewise, we would only need
+     * to check the scanner. If it is enabled, it means we are initiating.
+     */
     /* If already enabled, we return an error */
     connsm = &g_ble_ll_conn_sm;
     if (ble_ll_scan_enabled() || (connsm->conn_state != BLE_LL_CONN_STATE_IDLE)) {
@@ -381,25 +597,311 @@ ble_ll_conn_create(uint8_t *cmdbuf)
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
-    /* Set state machine parameters */
-    ble_ll_scan_initiator_start(hcc);
-
-    /* XXX: I have not dealt with lots of the state machine parameters! */
-
     /* Initialize the connection sm */
     ble_ll_conn_sm_init(connsm, hcc);
 
     /* Create the connection request */
-    ble_ll_conn_req_make(connsm);
+    ble_ll_conn_req_pdu_make(connsm);
 
-    /* XXX: gotta start scanning! */
-
-    return BLE_ERR_SUCCESS;
+    /* Start scanning */
+    return ble_ll_scan_initiator_start(hcc);
 }
 
+/**
+ * Called when HCI command to cancel a create connection command has been 
+ * received. 
+ *  
+ * Context: Link Layer (HCI command parser) 
+ * 
+ * @return int 
+ */
 int
 ble_ll_conn_create_cancel(void)
 {
-    /* XXX: implement this */
-    return BLE_ERR_SUCCESS;
+    int rc;
+
+    /* 
+     * If we receive this command and we have not got a connection
+     * create command, we have to return disallowed. The spec does not say
+     * what happens if the connection has already been established.
+     */
+    if (ble_ll_scan_enabled()) {
+        /* stop scanning */
+        ble_ll_scan_sm_stop(ble_ll_scan_sm_get());
+
+        /* XXX: what to do with connection state machine? */
+
+        /* Send connection complete event */
+        ble_ll_conn_comp_event_send(BLE_ERR_UNK_CONN_ID);
+        rc = BLE_ERR_SUCCESS;
+    } else {
+        /* If we have established connection or we are idle do not allow */
+        rc = BLE_ERR_CMD_DISALLOWED;
+    }
+
+    return rc;
+}
+
+/* Returns true if the address matches the connection peer address */
+int
+ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
+{
+    int rc;
+    struct ble_ll_conn_sm *connsm;
+
+    rc = 0;
+    connsm = &g_ble_ll_conn_sm;
+    if ((connsm->peer_addr_type == addr_type) &&
+        !memcmp(adva, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
+        rc = 1;
+    }
+
+    return rc;
+}
+
+/**
+ * Send a connection requestion to an advertiser 
+ * 
+ * @param addr_type Address type of advertiser
+ * @param adva Address of advertiser
+ */
+int
+ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva)
+{
+    int rc;
+    struct os_mbuf *m;
+    struct ble_ll_conn_sm *connsm;
+
+    m = ble_ll_scan_get_pdu();
+    ble_ll_conn_req_pdu_update(m, adva, addr_type);
+    rc = ble_phy_tx(m, BLE_PHY_TRANSITION_RX_TX, BLE_PHY_TRANSITION_NONE);
+    if (!rc) {
+        connsm = &g_ble_ll_conn_sm;
+        connsm->peer_addr_type = addr_type;
+        memcpy(connsm->peer_addr, adva, BLE_DEV_ADDR_LEN);
+        connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
+    }
+
+    return rc;
+}
+
+/**
+ * Process a received PDU while in the initiating state.
+ *  
+ * Context: Link Layer task. 
+ * 
+ * @param pdu_type 
+ * @param rxbuf 
+ */
+void
+ble_ll_init_rx_pdu_proc(uint8_t pdu_type, uint8_t *rxbuf, uint8_t crcok)
+{
+    struct ble_ll_scan_sm *scansm;
+    struct ble_ll_conn_sm *connsm;
+
+    /* XXX: Do I care what pdu type I receive? Not sure exactly how to
+       deal with knowing a connection request was sent. */
+
+    /* 
+     * XXX: Not sure I like this but I will deal with it for now. Just
+     * check the connection state machine. If state is created, we move
+     * to the connected state.
+     */
+    connsm = &g_ble_ll_conn_sm;
+    if (crcok && (connsm->conn_state == BLE_LL_CONN_STATE_CREATED)) {
+        /* Stop scanning */
+        scansm = ble_ll_scan_sm_get();
+        ble_ll_scan_sm_stop(scansm);
+
+        /* We are now in connection state */
+        ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+
+        /* Send connection complete event */
+        ble_ll_conn_comp_event_send(BLE_ERR_SUCCESS);
+    } else {
+        /* We need to re-enable the PHY if we are in idle state */
+        if (ble_phy_state_get() == BLE_PHY_STATE_IDLE) {
+            /* XXX: If this returns error, we will need to attempt to
+               re-start scanning! */
+            ble_phy_rx();
+        }
+    }
+}
+
+/**
+ * Called when a receive PDU has ended. 
+ *  
+ * Context: Interrupt 
+ * 
+ * @param rxpdu 
+ * 
+ * @return int 
+ *       < 0: Disable the phy after reception.
+ *      == 0: Success. Do not disable the PHY.
+ *       > 0: Do not disable PHY as that has already been done.
+ */
+int
+ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
+{
+    int rc;
+    int chk_send_req;
+    uint8_t pdu_type;
+    uint8_t addr_type;
+    uint8_t *adv_addr;
+    uint8_t *init_addr;
+    uint8_t *rxbuf;
+    struct ble_mbuf_hdr *ble_hdr;
+
+    /* Only interested in ADV IND or ADV DIRECT IND */
+    rxbuf = rxpdu->om_data;
+    pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
+
+    switch (pdu_type) {
+    case BLE_ADV_PDU_TYPE_ADV_IND:
+        chk_send_req = 1;
+        break;
+    case BLE_ADV_PDU_TYPE_ADV_DIRECT_IND:
+        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;
+        }
+        break;
+    default:
+        chk_send_req = 0;
+        break;
+    }
+
+    /* Should we send a connect request? */
+    rc = -1;
+    if (chk_send_req) {
+        /* Check filter policy */
+        adv_addr = 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;
+        }
+
+        /* Check filter policy */
+        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;
+            }
+
+            /* Set BLE mbuf header flags */
+            ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
+            ble_hdr->flags |= BLE_MBUF_HDR_F_DEVMATCH;
+        } 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)) {
+                return -1;
+            }
+        }
+
+        /* Setup to transmit the connect request */
+        rc = ble_ll_conn_request_send(addr_type, adv_addr);
+    }
+
+    return rc;
+}
+
+/**
+ * Called on pdu start (by link layer) when in initiating state. 
+ * 
+ * @param pdu_type 
+ * 
+ * @return int 
+ */
+int
+ble_ll_init_rx_pdu_start(uint8_t pdu_type)
+{
+    int rc;
+
+    /* We might respond to adv ind or adv direct ind only */
+    rc = 0;
+    if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
+        (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND)) {
+        rc = 1;
+    }
+
+    return rc;
+}
+
+/**
+ * Called when a device has received a connect request while advertising and 
+ * the connect request has passed the advertising filter policy and is for 
+ * us. This will start a connection in the slave role. 
+ * 
+ * @param rxbuf Pointer to received PDU
+ */
+void
+ble_ll_conn_slave_start(uint8_t *rxbuf)
+{
+    uint32_t crcinit;
+    uint8_t *dptr;
+    struct ble_ll_conn_sm *connsm;
+
+    /* XXX: Should we error check the parameters? */
+
+    /* Set the pointer at the start of the connection data */
+    dptr = rxbuf + BLE_LL_CONN_REQ_ADVA_OFF + BLE_DEV_ADDR_LEN;
+
+    connsm = &g_ble_ll_conn_sm;
+    connsm->access_addr = le32toh(dptr);
+    crcinit = dptr[4];
+    crcinit <<= 16;
+    crcinit |= dptr[5];
+    crcinit <<= 8;
+    crcinit |= dptr[6];
+    connsm->crcinit = crcinit;
+    connsm->conn_tx_win_size = dptr[7];
+    connsm->conn_tx_win_off = le16toh(dptr + 8);
+    connsm->conn_itvl = le16toh(dptr + 10);
+    connsm->conn_slave_latency = le16toh(dptr + 12);
+    connsm->conn_spvn_tmo = le16toh(dptr + 14);
+    memcpy(&connsm->chanmap, dptr + 16, BLE_LL_CONN_CHMAP_LEN);
+    connsm->hop_inc = dptr[21] & 0x1F;
+    connsm->master_sca = dptr[21] >> 5;
+
+    /* Set the address of device that we are connecting with */
+    memcpy(&connsm->peer_addr, rxbuf + BLE_LL_PDU_HDR_LEN, BLE_DEV_ADDR_LEN);
+    if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+        connsm->peer_addr_type = BLE_ADDR_TYPE_RANDOM;
+    } else {
+        connsm->peer_addr_type = BLE_ADDR_TYPE_PUBLIC;
+    }
+
+    connsm->num_used_chans = ble_ll_conn_calc_used_chans(connsm->chanmap);
+
+    /* Need to initialize the connection state machine */
+    ble_ll_conn_sm_init(connsm, NULL);
+
+    /* Set connection state to created */
+    connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
+
+    /* Set state to connection */
+    ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+
+    /* Send connection complete event */
+    ble_ll_conn_comp_event_send(BLE_ERR_SUCCESS);
+}
+
+/* Initializet the connection module */
+void
+ble_ll_conn_init(void)
+{
+    int rc;
+
+    /* Create connection memory pool */
+    rc = os_mempool_init(&g_ble_ll_conn_pool, BLE_LL_CONN_CFG_MAX_CONNS, 
+                         sizeof(struct ble_ll_conn_sm), &g_ble_ll_conn_buf, 
+                         "LLConnPool");
+
+    assert(rc == 0);
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 f344d87..98f9307 100644
--- a/net/nimble/controller/src/ble_ll_hci.c
+++ b/net/nimble/controller/src/ble_ll_hci.c
@@ -246,6 +246,7 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen)
         if (len == BLE_HCI_CREATE_CONN_LEN) {
             rc = ble_ll_conn_create(cmdbuf);
         }
+        /* This is a hack; command status gets sent instead of cmd complete */
         rc += (BLE_ERR_MAX + 1);
         break;
     case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/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 05416a4..aaeab1b 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -52,32 +52,6 @@
  * code might be made simpler.
  */
 
-/* Scanning state machine */
-struct ble_ll_scan_sm
-{
-    uint8_t scan_enabled;
-    uint8_t scan_type;
-    uint8_t own_addr_type;
-    uint8_t scan_chan;
-    uint8_t scan_filt_policy;
-    uint8_t scan_filt_dups;
-    uint8_t scan_rsp_pending;
-    uint8_t scan_rsp_cons_fails;
-    uint8_t scan_rsp_cons_ok;
-    uint16_t upper_limit;
-    uint16_t backoff_count;
-    uint16_t scan_itvl;
-    uint16_t scan_window;
-    uint32_t scan_win_start_time;
-    struct os_mbuf *scan_req_pdu;
-    struct os_event scan_win_end_ev;
-};
-
-/* Scan types */
-#define BLE_SCAN_TYPE_PASSIVE   (BLE_HCI_SCAN_TYPE_PASSIVE)
-#define BLE_SCAN_TYPE_ACTIVE    (BLE_HCI_SCAN_TYPE_ACTIVE)
-#define BLE_SCAN_TYPE_INITIATE  (2)
-
 /* The scanning state machine global object */
 struct ble_ll_scan_sm g_ble_ll_scan_sm;
 
@@ -421,7 +395,6 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
         adv_data_len -= BLE_DEV_ADDR_LEN;
     }
 
-    rc = BLE_ERR_MEM_CAPACITY;
     if (ble_ll_hci_is_le_event_enabled(subev - 1)) {
         evbuf = os_memblock_get(&g_hci_cmd_pool);
         if (evbuf) {
@@ -552,7 +525,11 @@ ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
         rc =  BLE_LL_SCHED_STATE_DONE;
     } else {
         /* Set link layer state to scanning */
-        ble_ll_state_set(BLE_LL_STATE_SCANNING);
+        if (g_ble_ll_scan_sm.scan_type == BLE_SCAN_TYPE_INITIATE) {
+            ble_ll_state_set(BLE_LL_STATE_INITIATING);
+        } else {
+            ble_ll_state_set(BLE_LL_STATE_SCANNING);
+        }
 
         /* Set end time to end of scan window */
         sch->next_wakeup = sch->end_time;
@@ -564,13 +541,9 @@ ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
 }
 
 /**
- * ll scan sm stop 
- *  
  * Stop the scanning state machine 
- * 
- * @param scansm Pointer to scanning state machine.
  */
-static void
+void
 ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
 {
     /* XXX: Stop any timers we may have started */
@@ -578,9 +551,6 @@ ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
     /* Remove any scheduled advertising items */
     ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_SCAN);
 
-    /* Disable the PHY */
-    ble_phy_disable();
-
     /* Disable whitelisting (just in case) */
     ble_ll_whitelist_disable();
 
@@ -676,7 +646,7 @@ ble_ll_scan_sm_start(struct ble_ll_scan_sm *scansm)
         assert(0);
     }
 
-    return 0;
+    return BLE_ERR_SUCCESS;
 }
 
 void
@@ -755,19 +725,17 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
     int rc;
     struct ble_ll_scan_sm *scansm;
 
-    /* 
-     * If there is a chance that we will respond to the PDU we must
-     * return the appropriate value so that the PHY goes from rx to tx.
-     */
     rc = 0;
     scansm = &g_ble_ll_scan_sm;
-    if (scansm->scan_type == BLE_SCAN_TYPE_ACTIVE) {
+
+    switch (scansm->scan_type) {
+    case BLE_SCAN_TYPE_ACTIVE:
+        /* If adv ind or scan ind, we may send scan request */
         if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
             (pdu_type == BLE_ADV_PDU_TYPE_ADV_SCAN_IND)) {
             rc = 1;
         }
 
-        /* XXX: could post event here to LL task to do the backoff... */
         /* 
          * If there is a scan response pending, it means that we did
          * not receive a scan response to our previous request unless
@@ -778,6 +746,10 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
                 ble_ll_scan_req_backoff(scansm, 0);
             }
         }
+        break;
+    case BLE_SCAN_TYPE_PASSIVE:
+    default:
+        break;
     }
 
     /* 
@@ -792,7 +764,6 @@ ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
     return rc;
 }
 
-
 /* 
  * NOTE: If this returns a positive number there was an error but
  * there is no need to disable the PHY on return as that was
@@ -1078,6 +1049,11 @@ ble_ll_scan_set_enable(uint8_t *cmd)
         }
     } else {
         if (scansm->scan_enabled) {
+            /* XXX: what happens if a receive has started? What about
+             * the phy pdu? Do we need to do anything with it? The rx pdu
+               at the phy??? Keep it there? */
+            /* Disable the PHY */
+            ble_phy_disable();
             ble_ll_scan_sm_stop(scansm);
         }
     }
@@ -1107,7 +1083,7 @@ ble_ll_scan_can_chg_whitelist(void)
     return rc;
 }
 
-void
+int
 ble_ll_scan_initiator_start(struct hci_create_conn *hcc)
 {
     struct ble_ll_scan_sm *scansm;
@@ -1118,6 +1094,7 @@ ble_ll_scan_initiator_start(struct hci_create_conn *hcc)
     scansm->scan_window = hcc->scan_window;
     scansm->scan_filt_policy = hcc->filter_policy;
     scansm->own_addr_type = hcc->own_addr_type;
+    return ble_ll_scan_sm_start(scansm);
 }
 
 /**
@@ -1138,6 +1115,20 @@ 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)
+{
+    return g_ble_ll_scan_sm.scan_filt_policy & 1;
+}
+
 /**
  * ble ll scan init 
  *  

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/d478f7bc/net/nimble/drivers/nrf52/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/nrf52/src/ble_phy.c b/net/nimble/drivers/nrf52/src/ble_phy.c
index 4713c39..cd5549d 100644
--- a/net/nimble/drivers/nrf52/src/ble_phy.c
+++ b/net/nimble/drivers/nrf52/src/ble_phy.c
@@ -23,6 +23,11 @@
 #include "controller/ble_ll.h"
 #include "mcu/nrf52_bitfields.h"
 
+/* 
+ * XXX: TODO
+ * 1) make phy rx start and end function pointers to call?
+ */
+
 /* To disable all radio interrupts */
 #define NRF52_RADIO_IRQ_MASK_ALL    (0x34FF)