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 2016/01/19 01:14:59 UTC

[2/2] incubator-mynewt-larva git commit: Many changes to the scheduler and link layer to allow for scheduling of multiple connections. Also allows concurrent connections and/or advertising and/or scanning and/or initiating state machines

Many changes to the scheduler and link layer to allow for scheduling of multiple connections. Also allows concurrent connections and/or advertising and/or scanning and/or initiating state machines


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/b6e2b5ff
Tree: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/tree/b6e2b5ff
Diff: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/diff/b6e2b5ff

Branch: refs/heads/master
Commit: b6e2b5ffa358ad9696f71d30df4f94466f78ae67
Parents: ccc970c
Author: wes3 <wi...@micosa.io>
Authored: Mon Jan 18 16:14:37 2016 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Mon Jan 18 16:14:50 2016 -0800

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll.h      |  26 +-
 .../controller/include/controller/ble_ll_adv.h  |  13 +-
 .../controller/include/controller/ble_ll_conn.h |   8 +-
 .../controller/include/controller/ble_ll_hci.h  |   2 +-
 .../controller/include/controller/ble_ll_scan.h |  16 +-
 .../include/controller/ble_ll_sched.h           |  47 +-
 net/nimble/controller/src/ble_ll.c              | 125 +--
 net/nimble/controller/src/ble_ll_adv.c          | 264 ++++---
 net/nimble/controller/src/ble_ll_conn.c         | 682 +++++++++-------
 net/nimble/controller/src/ble_ll_conn_hci.c     |   4 +-
 net/nimble/controller/src/ble_ll_conn_priv.h    |  16 +-
 net/nimble/controller/src/ble_ll_ctrl.c         |   2 +-
 net/nimble/controller/src/ble_ll_scan.c         | 386 ++++++----
 net/nimble/controller/src/ble_ll_sched.c        | 770 ++++++++++++++++---
 net/nimble/drivers/native/src/ble_phy.c         |   9 +-
 net/nimble/drivers/nrf52/src/ble_phy.c          |  21 +-
 net/nimble/include/nimble/ble.h                 |  26 +-
 project/bletest/src/main.c                      | 232 +++++-
 18 files changed, 1885 insertions(+), 764 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 6e5b6e1..948d8e6 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -70,6 +70,8 @@ struct ble_ll_stats
     uint32_t hci_events_sent;
     uint32_t bad_ll_state;
     uint32_t bad_acl_hdr;
+    uint32_t sched_state_conn_errs;
+    uint32_t sched_state_adv_errs;
     uint32_t rx_bytes;
     uint32_t rx_valid_adv_pdus;
     uint32_t rx_invalid_adv_pdus;
@@ -108,7 +110,7 @@ extern struct ble_ll_stats g_ble_ll_stats;
 #define BLE_LL_EVENT_HCI_CMD        (OS_EVENT_T_PERUSER)
 #define BLE_LL_EVENT_ADV_EV_DONE    (OS_EVENT_T_PERUSER + 1)
 #define BLE_LL_EVENT_RX_PKT_IN      (OS_EVENT_T_PERUSER + 2)
-#define BLE_LL_EVENT_SCAN_WIN_END   (OS_EVENT_T_PERUSER + 3)
+#define BLE_LL_EVENT_SCAN           (OS_EVENT_T_PERUSER + 3)
 #define BLE_LL_EVENT_CONN_SPVN_TMO  (OS_EVENT_T_PERUSER + 4)
 #define BLE_LL_EVENT_CONN_EV_END    (OS_EVENT_T_PERUSER + 5)
 #define BLE_LL_EVENT_TX_PKT_IN      (OS_EVENT_T_PERUSER + 6)
@@ -306,7 +308,8 @@ void ble_ll_acl_data_in(struct os_mbuf *txpkt);
 int ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan);
 
 /* Called by the PHY when a packet reception ends */
-int ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t chan, uint8_t crcok);
+struct ble_mbuf_hdr;
+int ble_ll_rx_end(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *ble_hdr);
 
 /*--- Controller API ---*/
 void ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr);
@@ -336,10 +339,14 @@ uint8_t ble_ll_read_supp_features(void);
  * XXX: temporary LL debug log. Will get removed once we transition to real
  * log
  */ 
-#undef BLE_LL_LOG
-
-#define BLE_LL_LOG_ID_RX_START          (1)
-#define BLE_LL_LOG_ID_RX_END            (2)
+#define BLE_LL_LOG
+
+#define BLE_LL_LOG_ID_PHY_SETCHAN       (1)
+#define BLE_LL_LOG_ID_RX_START          (2)
+#define BLE_LL_LOG_ID_RX_END            (3)
+#define BLE_LL_LOG_ID_WFR_EXP           (4)
+#define BLE_LL_LOG_ID_PHY_TXEND         (5)
+#define BLE_LL_LOG_ID_PHY_DISABLE       (9)
 #define BLE_LL_LOG_ID_CONN_EV_START     (10)
 #define BLE_LL_LOG_ID_CONN_TX           (15)
 #define BLE_LL_LOG_ID_CONN_RX           (16)
@@ -347,11 +354,8 @@ uint8_t ble_ll_read_supp_features(void);
 #define BLE_LL_LOG_ID_CONN_RX_ACK       (18)
 #define BLE_LL_LOG_ID_CONN_EV_END       (20)
 #define BLE_LL_LOG_ID_CONN_END          (30)
-#define BLE_LL_LOG_ID_PHY_SETCHAN       (200)
-#define BLE_LL_LOG_ID_PHY_DISABLE       (201)
-#define BLE_LL_LOG_ID_PHY_ISR           (202)
-#define BLE_LL_LOG_ID_PHY_RX            (220)
-#define BLE_LL_LOG_ID_PHY_TX            (221)
+#define BLE_LL_LOG_ID_ADV_TXBEG         (50)
+#define BLE_LL_LOG_ID_ADV_TXDONE        (60)
 
 #ifdef BLE_LL_LOG
 void ble_ll_log(uint8_t id, uint8_t arg8, uint16_t arg16, uint32_t arg32);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 a01df8c..b3bc298 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -129,10 +129,10 @@ void ble_ll_adv_init(void);
 void ble_ll_adv_reset(void);
 
 /* Called on rx pdu start when in advertising state */
-int ble_ll_adv_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu);
+int ble_ll_adv_rx_isr_start(uint8_t pdu_type, struct os_mbuf *rxpdu);
 
 /* Called on rx pdu end when in advertising state */
-int ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu);
+int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok);
 
 /* Processes received packets at the link layer task */
 void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf,
@@ -144,4 +144,13 @@ int ble_ll_adv_can_chg_whitelist(void);
 /* Called when a connection request has been received at the link layer */
 int ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr);
 
+/* Called when an advertising event has been scheduled */
+void ble_ll_adv_scheduled(uint32_t sch_start);
+
+/* Called to halt currently running advertising event */
+void ble_ll_adv_halt(void);
+
+/* Called to determine if advertising is enabled */
+uint8_t ble_ll_adv_enabled(void);
+
 #endif /* H_BLE_LL_ADV_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 a11e02d..444ee72 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -18,6 +18,8 @@
 #define H_BLE_LL_CONN_
 
 #include "os/os.h"
+#include "nimble/ble.h"
+#include "controller/ble_ll_sched.h"
 #include "hal/hal_cputime.h"
 
 /* Roles */
@@ -114,11 +116,12 @@ struct ble_ll_conn_sm
     uint32_t access_addr;
     uint32_t crcinit;           /* only low 24 bits used */
     uint32_t anchor_point;
-    uint32_t last_anchor_point;
+    uint32_t last_anchor_point; /* slave only */
     uint32_t ce_end_time;   /* cputime at which connection event should end */
     uint32_t terminate_timeout;
     uint32_t slave_cur_tx_win_usecs;
     uint32_t slave_cur_window_widening;
+    uint32_t last_scheduled;
 
     /* address information */
     uint8_t own_addr_type;
@@ -148,6 +151,9 @@ struct ble_ll_conn_sm
 
     /* LL control procedure response timer */
     struct os_callout_func ctrl_proc_rsp_timer;
+
+    /* For scheduling connections */
+    struct ble_ll_sched_item conn_sch;
 };
 
 /* 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/net/nimble/controller/include/controller/ble_ll_hci.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_hci.h b/net/nimble/controller/include/controller/ble_ll_hci.h
index e9d98a2..32a093a 100644
--- a/net/nimble/controller/include/controller/ble_ll_hci.h
+++ b/net/nimble/controller/include/controller/ble_ll_hci.h
@@ -32,7 +32,7 @@
  * number of completed packets event to the host. This number is in
  * milliseconds.
  */
-#define BLE_LL_CFG_NUM_COMP_PKT_RATE    (1000)  /* msecs */
+#define BLE_LL_CFG_NUM_COMP_PKT_RATE    (2000)  /* msecs */
 
 /* Initialize LL HCI */
 void ble_ll_hci_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 31c57fe..75542c3 100644
--- a/net/nimble/controller/include/controller/ble_ll_scan.h
+++ b/net/nimble/controller/include/controller/ble_ll_scan.h
@@ -17,6 +17,8 @@
 #ifndef H_BLE_LL_SCAN_
 #define H_BLE_LL_SCAN_
 
+#include "controller/ble_ll_sched.h"
+
 /* 
  * Configuration items for the number of duplicate advertisers and the
  * number of advertisers from which we have heard a scan response 
@@ -77,9 +79,11 @@ struct ble_ll_scan_sm
     uint16_t backoff_count;
     uint16_t scan_itvl;
     uint16_t scan_window;
+    uint32_t last_sched_time;
     uint32_t scan_win_start_time;
     struct os_mbuf *scan_req_pdu;
-    struct os_event scan_win_end_ev;
+    struct os_event scan_sched_ev;
+    struct ble_ll_sched_item scan_sch;
 };
 
 /* Scan types */
@@ -96,7 +100,7 @@ int ble_ll_scan_set_enable(uint8_t *cmd);
 
 /*--- Controller Internal API ---*/
 /* Process scan window end event */
-void ble_ll_scan_win_end_proc(void *arg);
+void ble_ll_scan_event_proc(void *arg);
 
 /* Initialize the scanner */
 void ble_ll_scan_init(void);
@@ -105,10 +109,10 @@ void ble_ll_scan_init(void);
 void ble_ll_scan_reset(void);
 
 /* Called when Link Layer starts to receive a PDU and is in scanning state */
-int ble_ll_scan_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu);
+int ble_ll_scan_rx_isr_start(uint8_t pdu_type, struct os_mbuf *rxpdu);
 
 /* Called when Link Layer has finished receiving a PDU while scanning */
-int ble_ll_scan_rx_pdu_end(struct os_mbuf *rxpdu);
+int ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);
 
 /* Process a scan response PDU */
 void ble_ll_scan_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf, 
@@ -131,10 +135,10 @@ int ble_ll_scan_initiator_start(struct hci_create_conn *hcc);
 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, int conn_created);
+void ble_ll_scan_sm_stop(int chk_disable);
 
 /* Resume scanning */
-void ble_ll_scan_resume(void);
+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);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/net/nimble/controller/include/controller/ble_ll_sched.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_sched.h b/net/nimble/controller/include/controller/ble_ll_sched.h
index 48914ae..eff9b2f 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -17,15 +17,16 @@
 #ifndef H_BLE_LL_SCHED_
 #define H_BLE_LL_SCHED_
 
+/* Time per BLE scheduler slot */
+#define BLE_LL_SCHED_USECS_PER_SLOT (1250)
+
 /* BLE scheduler errors */
 #define BLE_LL_SCHED_ERR_OVERLAP    (1)
 
 /* Types of scheduler events */
-#define BLE_LL_SCHED_TYPE_ADV       (0)
-#define BLE_LL_SCHED_TYPE_SCAN      (1)
-#define BLE_LL_SCHED_TYPE_TX        (2)
-#define BLE_LL_SCHED_TYPE_RX        (3)
-#define BLE_LL_SCHED_TYPE_CONN      (4)
+#define BLE_LL_SCHED_TYPE_ADV       (1)
+#define BLE_LL_SCHED_TYPE_SCAN      (2)
+#define BLE_LL_SCHED_TYPE_CONN      (3)
 
 /* Return values for schedule callback. */
 #define BLE_LL_SCHED_STATE_RUNNING  (0)
@@ -37,28 +38,48 @@ typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch);
 
 struct ble_ll_sched_item
 {
-    int             sched_type;
+    uint8_t         sched_type;
+    uint8_t         enqueued;
     uint32_t        start_time;
     uint32_t        end_time;
-    uint32_t        next_wakeup;
     void            *cb_arg;
     sched_cb_func   sched_cb;
     TAILQ_ENTRY(ble_ll_sched_item) link;
 };
 
-/* Add an item to the schedule */
-int ble_ll_sched_add(struct ble_ll_sched_item *sch);
-
-/* Remove item(s) from schedule */
-int ble_ll_sched_rmv(uint8_t sched_type, void *cb_arg);
-
 /* Initialize the scheduler */
 int ble_ll_sched_init(void);
 
+/* Remove item(s) from schedule */
+void ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch);
+
 /* Get a schedule item */
 struct ble_ll_sched_item *ble_ll_sched_get_item(void);
 
 /* Free a schedule item */
 void ble_ll_sched_free_item(struct ble_ll_sched_item *sch);
 
+/* Schedule a new master connection */
+struct ble_ll_conn_sm;
+int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm, uint32_t adv_rxend, 
+                            uint8_t req_slots);
+
+/* Schedule a new slave connection */
+int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm);
+
+/* Schedule a new advertising event */
+int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch);
+
+/* Reschedule an advertising event */
+int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch);
+
+/* Reschedule a connection that had previously been scheduled or that is over */
+int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm);
+
+/* Schedule a scanning schedule item (start or stop) */
+void ble_ll_sched_scan(struct ble_ll_sched_item *sch);
+
+/* Stop the scheduler */
+void ble_ll_sched_stop(void);
+
 #endif /* H_LL_SCHED_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 927d82d..eb44261 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -29,15 +29,6 @@
 #include "ble_ll_conn_priv.h"
 #include "hal/hal_cputime.h"
 
-/* 
- * XXX: I need to re-think the whoele LL state code and how I deal with it.
- * I dont think I am handling it very well. The LL state should only change
- * at the LL task I think. I am also not sure how to make sure that any packets
- * handled by the LL are handled by the appropriate state. For example, can I
- * get a scan window end and then process packets? When the schedule event for
- * the scan window ends, what do I do to the LL state? Check all this out.
- */
-
 /* XXX:
  * 
  * 1) use the sanity task!
@@ -49,6 +40,11 @@
  * start of a frame. Need to look at the various states to see if this is the
  * right thing to do.
  * 
+ * 5) Make sure there is no way we can start a wfr timer and then have
+ * whatever event end and not stop the timer. We want to make sure the timer
+ * cant fire off unless we are sure that it will fire off when the device is
+ * in standby state. At least in standby we are sure no erroneous action will
+ * be taken
  */
 
 /* Configuration for supported features */
@@ -259,12 +255,17 @@ ble_ll_is_our_devaddr(uint8_t *addr, int addr_type)
 void
 ble_ll_wfr_timer_exp(void *arg)
 {
-    struct ble_ll_obj *lldata;
+    int rx_start;
+    uint8_t lls;
+
+    rx_start = ble_phy_rx_started();
+    lls = g_ble_ll_data.ll_state;
+
+    ble_ll_log(BLE_LL_LOG_ID_WFR_EXP, lls, 0, (uint32_t)rx_start);
 
     /* If we have started a reception, there is nothing to do here */
-    if (!ble_phy_rx_started()) {
-        lldata = &g_ble_ll_data;
-        switch (lldata->ll_state) {
+    if (!rx_start) {
+        switch (lls) {
         case BLE_LL_STATE_ADV:
             ble_ll_adv_wfr_timer_exp();
             break;
@@ -365,6 +366,7 @@ ble_ll_rx_pkt_in(void)
     os_sr_t sr;
     uint8_t pdu_type;
     uint8_t *rxbuf;
+    uint8_t crcok;
     struct os_mbuf_pkthdr *pkthdr;
     struct ble_mbuf_hdr *ble_hdr;
     struct os_mbuf *m;
@@ -383,17 +385,18 @@ ble_ll_rx_pkt_in(void)
         /* Count statistics */
         rxbuf = m->om_data;
         ble_hdr = BLE_MBUF_HDR_PTR(m); 
-        if (ble_hdr->rxinfo.crcok) {
+        crcok = BLE_MBUF_HDR_CRC_OK(ble_hdr);
+        if (crcok) {
             /* The total bytes count the PDU header and PDU payload */
             g_ble_ll_stats.rx_bytes += pkthdr->omp_len;
         }
 
         if (ble_hdr->rxinfo.channel < BLE_PHY_NUM_DATA_CHANS) {
-            ble_ll_conn_rx_data_pdu(m, ble_hdr->rxinfo.crcok);
+            ble_ll_conn_rx_data_pdu(m, ble_hdr);
         } else {
             /* Get advertising PDU type */
             pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
-            if (ble_hdr->rxinfo.crcok) {
+            if (crcok) {
                 /* Count by type only with valid crc */
                 ++g_ble_ll_stats.rx_valid_adv_pdus;
                 ble_ll_count_rx_adv_pdus(pdu_type);
@@ -402,7 +405,7 @@ ble_ll_rx_pkt_in(void)
             }
 
             /* Process the PDU */
-            switch (g_ble_ll_data.ll_state) {
+            switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) {
             case BLE_LL_STATE_ADV:
                 ble_ll_adv_rx_pkt_in(pdu_type, rxbuf, ble_hdr);
                 break;
@@ -418,6 +421,7 @@ ble_ll_rx_pkt_in(void)
                 break;
             }
 
+
             /* Free the packet buffer */
             os_mbuf_free(m);
         }
@@ -488,7 +492,7 @@ ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
          */
         if (g_ble_ll_data.ll_state == BLE_LL_STATE_CONNECTION) {
             /* Call conection pdu rx start function */
-            ble_ll_conn_rx_pdu_start();
+            ble_ll_conn_rx_isr_start();
 
             /* Set up to go from rx to tx */
             rc = 1;
@@ -504,7 +508,7 @@ ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
 
     switch (g_ble_ll_data.ll_state) {
     case BLE_LL_STATE_ADV:
-        rc = ble_ll_adv_rx_pdu_start(pdu_type, rxpdu);
+        rc = ble_ll_adv_rx_isr_start(pdu_type, rxpdu);
         break;
     case BLE_LL_STATE_INITIATING:
         if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
@@ -515,7 +519,7 @@ ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
         }
         break;
     case BLE_LL_STATE_SCANNING:
-        rc = ble_ll_scan_rx_pdu_start(pdu_type, rxpdu);
+        rc = ble_ll_scan_rx_isr_start(pdu_type, rxpdu);
         break;
     case BLE_LL_STATE_CONNECTION:
         /* Should not occur */
@@ -537,7 +541,8 @@ ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
  *  
  * NOTE: Called from interrupt context!
  * 
- * @param rxbuf 
+ * @param rxpdu Pointer to received PDU 
+ *        ble_hdr Pointer to BLE header of received mbuf 
  * 
  * @return int 
  *       < 0: Disable the phy after reception.
@@ -545,18 +550,24 @@ ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
  *       > 0: Do not disable PHY as that has already been done.
  */
 int
-ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t chan, uint8_t crcok)
+ble_ll_rx_end(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *ble_hdr)
 {
     int rc;
     int badpkt;
     uint8_t pdu_type;
     uint8_t len;
+    uint8_t chan;
+    uint8_t crcok;
     uint16_t mblen;
     uint8_t *rxbuf;
 
     /* Set the rx buffer pointer to the start of the received data */
     rxbuf = rxpdu->om_data;
 
+    /* Get channel and CRC status from BLE header */
+    chan = ble_hdr->rxinfo.channel;
+    crcok = BLE_MBUF_HDR_CRC_OK(ble_hdr);
+
     ble_ll_log(BLE_LL_LOG_ID_RX_END, 
                chan, 
                ((uint16_t)crcok << 8) | rxbuf[1], 
@@ -581,14 +592,19 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t chan, uint8_t crcok)
          * Data channel pdu. We should be in CONNECTION state with an
          * ongoing connection.
          */
-        rc = ble_ll_conn_rx_pdu_end(rxpdu, ble_phy_access_addr_get());
+        rc = ble_ll_conn_rx_isr_end(rxpdu, ble_phy_access_addr_get());
         return rc;
     } 
 
-    /* Get advertising PDU type */
+    /* Get advertising PDU type and length */
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
     len = rxbuf[1] & BLE_ADV_PDU_HDR_LEN_MASK;
 
+    /* Setup the mbuf lengths */
+    mblen = len + BLE_LL_PDU_HDR_LEN;
+    OS_MBUF_PKTHDR(rxpdu)->omp_len = mblen;
+    rxpdu->om_len = mblen;
+
     /* If the CRC checks, make sure lengths check! */
     if (crcok) {
         badpkt = 0;
@@ -621,38 +637,35 @@ ble_ll_rx_end(struct os_mbuf *rxpdu, uint8_t chan, uint8_t crcok)
         if (badpkt) {
             ++g_ble_ll_stats.rx_adv_malformed_pkts;
             os_mbuf_free(rxpdu);
-            return -1;
+            rxpdu = NULL;
+            rc = -1;
         }
     }
 
-    /* Setup the mbuf lengths */
-    mblen = len + BLE_LL_PDU_HDR_LEN;
-    OS_MBUF_PKTHDR(rxpdu)->omp_len = mblen;
-    rxpdu->om_len = mblen;
 
     /* Hand packet to the appropriate state machine (if crc ok) */
-    rc = -1;
-    if (crcok) {
-        switch (g_ble_ll_data.ll_state) {
-        case BLE_LL_STATE_ADV:
-            rc = ble_ll_adv_rx_pdu_end(pdu_type, rxpdu);
-            break;
-        case BLE_LL_STATE_SCANNING:
-            rc = ble_ll_scan_rx_pdu_end(rxpdu);
-            break;
-        case BLE_LL_STATE_INITIATING:
-            rc = ble_ll_init_rx_pdu_end(rxpdu);
-            break;
-        /* Invalid states */
-        case BLE_LL_STATE_CONNECTION:
-        default:
-            assert(0);
-            break;
-        }
+    switch (BLE_MBUF_HDR_RX_STATE(ble_hdr)) {
+    case BLE_LL_STATE_ADV:
+        rc = ble_ll_adv_rx_isr_end(pdu_type, rxpdu, crcok);
+        break;
+    case BLE_LL_STATE_SCANNING:
+        rc = ble_ll_scan_rx_isr_end(rxpdu, crcok);
+        break;
+    case BLE_LL_STATE_INITIATING:
+        rc = ble_ll_init_rx_isr_end(rxpdu, crcok);
+        break;
+    /* Invalid states */
+    case BLE_LL_STATE_CONNECTION:
+    default:
+        rc = -1;
+        assert(0);
+        break;
     }
 
     /* Hand packet up to higher layer (regardless of CRC failure) */
-    ble_ll_rx_pdu_in(rxpdu);
+    if (rxpdu) {
+        ble_ll_rx_pdu_in(rxpdu);
+    }
 
     return rc;
 }
@@ -668,6 +681,7 @@ void
 ble_ll_task(void *arg)
 {
     struct os_event *ev;
+    struct os_callout_func *cf;
 
     /* Init ble phy */
     ble_phy_init();
@@ -681,9 +695,11 @@ ble_ll_task(void *arg)
     /* Wait for an event */
     while (1) {
         ev = os_eventq_get(&g_ble_ll_data.ll_evq);
-
         switch (ev->ev_type) {
         case OS_EVENT_T_TIMER:
+            cf = (struct os_callout_func *)ev;
+            assert(cf->cf_func);
+            cf->cf_func(cf->cf_arg);
             break;
         case BLE_LL_EVENT_HCI_CMD:
             /* Process HCI command */
@@ -692,8 +708,8 @@ ble_ll_task(void *arg)
         case BLE_LL_EVENT_ADV_EV_DONE:
             ble_ll_adv_event_done(ev->ev_arg);
             break;
-        case BLE_LL_EVENT_SCAN_WIN_END:
-            ble_ll_scan_win_end_proc(ev->ev_arg);
+        case BLE_LL_EVENT_SCAN:
+            ble_ll_scan_event_proc(ev->ev_arg);
             break;
         case BLE_LL_EVENT_RX_PKT_IN:
             ble_ll_rx_pkt_in();
@@ -821,7 +837,8 @@ ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr)
  * layer; it does not perform a HW reset of the controller nor does it reset 
  * the HCI interface. 
  * 
- * 
+ * Context: Link Layer task (HCI command) 
+ *  
  * @return int The ble error code to place in the command complete event that 
  * is returned when this command is issued. 
  */
@@ -829,12 +846,16 @@ int
 ble_ll_reset(void)
 {
     int rc;
+    os_sr_t sr;
 
     /* Stop the phy */
     ble_phy_disable();
 
     /* Stop any wait for response timer */
+    OS_ENTER_CRITICAL(sr);
     ble_ll_wfr_disable();
+    ble_ll_sched_stop();
+    OS_EXIT_CRITICAL(sr);
 
     /* Stop any scanning */
     ble_ll_scan_reset();

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 5302f66..d74b61a 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -46,14 +46,12 @@
  * 2) Only public device addresses supported right now.
  * 3) How do features get supported? What happens if device does not support
  * advertising? (for example)
- * 4) Correct calculation of schedule start and end times for the various
- * scheduled advertising activities.
- * 5) How to determine the advertising interval we will actually use. As of
+ * 4) How to determine the advertising interval we will actually use. As of
  * 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) How does the advertising channel tx power get set? I dont implement
+ * 5) How does the advertising channel tx power get set? I dont implement
  * that currently.
+ * 6) The time between transmissions inside an advertising event is set to
+ * max. Need to deal with this.
  */
 
 /* 
@@ -89,6 +87,7 @@ struct ble_ll_adv_sm
     struct os_mbuf *adv_pdu;
     struct os_mbuf *scan_rsp_pdu;
     struct os_event adv_txdone_ev;
+    struct ble_ll_sched_item adv_sch;
 };
 
 /* The advertising state machine global object */
@@ -149,7 +148,6 @@ ble_ll_adv_first_chan(struct ble_ll_adv_sm *advsm)
     return adv_chan;
 }
 
-
 /**
  * Compares the advertiser address in an advertising PDU (scan request or 
  * connect request) with our address to see if there is a match
@@ -327,15 +325,24 @@ ble_ll_adv_scan_rsp_pdu_make(struct ble_ll_adv_sm *advsm)
 }
 
 /**
- * Scheduler callback when an advertising PDU has been sent. 
+ * Called to indicate the advertising event is over.
+ *  
+ * Context: Interrupt 
+ * 
+ * @param advsm 
  * 
- * @param arg 
  */
-static int
-ble_ll_adv_tx_done_cb(struct ble_ll_sched_item *sch)
+static void
+ble_ll_adv_tx_done(void *arg)
 {
-    os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_adv_sm.adv_txdone_ev);
-    return BLE_LL_SCHED_STATE_DONE;
+    struct ble_ll_adv_sm *advsm;
+
+    advsm = (struct ble_ll_adv_sm *)arg;
+    os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
+
+    ble_ll_log(BLE_LL_LOG_ID_ADV_TXDONE, ble_ll_state_get(), 0, 0);
+
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
 }
 
 /**
@@ -363,24 +370,25 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
     rc = ble_phy_setchan(advsm->adv_chan, 0, 0);
     assert(rc == 0);
 
-    /* Set the callbacks */
-    ble_phy_set_txend_cb(NULL, NULL);
-
     /* Set phy mode based on type of advertisement */
     if (advsm->adv_type == BLE_HCI_ADV_TYPE_ADV_NONCONN_IND) {
         end_trans = BLE_PHY_TRANSITION_NONE;
+        ble_phy_set_txend_cb(ble_ll_adv_tx_done, advsm);
     } else {
         end_trans = BLE_PHY_TRANSITION_TX_RX;
+        ble_phy_set_txend_cb(NULL, NULL);
     }
 
     /* This is for debug */
     start_time = cputime_get32();
 
+    /* XXX: transmit using an output compare */
     /* Transmit advertisement */
     rc = ble_phy_tx(advsm->adv_pdu, BLE_PHY_TRANSITION_NONE, end_trans);
     if (rc) {
         /* Transmit failed. */
-        rc = ble_ll_adv_tx_done_cb(sch);
+        ble_ll_adv_tx_done(advsm);
+        rc =  BLE_LL_SCHED_STATE_DONE;
     } else {
         /* Check if we were late getting here */
         if ((int32_t)(start_time - (advsm->adv_pdu_start_time -
@@ -394,68 +402,71 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
         /* Count # of adv. sent */
         ++g_ble_ll_adv_stats.adv_txg;
 
-        /* Set next schedule wakeup time */
-        sch->next_wakeup = sch->end_time;
-        sch->sched_cb = ble_ll_adv_tx_done_cb;
-
+        /* This schedule item is now running */
         rc = BLE_LL_SCHED_STATE_RUNNING;
     }
 
     return rc;
 }
 
-static struct ble_ll_sched_item *
-ble_ll_adv_sched_set(struct ble_ll_adv_sm *advsm)
+static void
+ble_ll_adv_set_sched(struct ble_ll_adv_sm *advsm, int sched_new)
 {
-    int rc;
     uint32_t max_usecs;
     struct ble_ll_sched_item *sch;
 
-    sch = ble_ll_sched_get_item();
-    if (sch) {
-        /* Set sched type */
-        sch->sched_type = BLE_LL_SCHED_TYPE_ADV;
+    sch = &advsm->adv_sch;
+    sch->cb_arg = advsm;
+    sch->sched_cb = ble_ll_adv_tx_start_cb;
+    sch->sched_type = BLE_LL_SCHED_TYPE_ADV;
 
-        /* XXX: HW output compare to trigger tx start? Look into this */
-        /* Set the start time of the event */
-        sch->start_time = advsm->adv_pdu_start_time - 
-            cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+    /* Set end time to maximum time this schedule item may take */
+    max_usecs = BLE_TX_DUR_USECS_M(advsm->adv_pdu_len);
+    switch (advsm->adv_type) {
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
+        max_usecs += BLE_LL_ADV_DIRECT_SCHED_MAX_USECS;
+        break;
+    case BLE_HCI_ADV_TYPE_ADV_IND:
+    case BLE_HCI_ADV_TYPE_ADV_SCAN_IND:
+        max_usecs += BLE_LL_ADV_SCHED_MAX_USECS;
+        break;
+    default:
+        break;
+    }
 
-        /* Set the callback and argument */
-        sch->cb_arg = advsm;
-        sch->sched_cb = ble_ll_adv_tx_start_cb;
-
-        /* Set end time to maximum time this schedule item may take */
-        max_usecs = BLE_TX_DUR_USECS_M(advsm->adv_pdu_len);
-        switch (advsm->adv_type) {
-        case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
-        case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
-            max_usecs += BLE_LL_ADV_DIRECT_SCHED_MAX_USECS;
-            break;
-        case BLE_HCI_ADV_TYPE_ADV_IND:
-        case BLE_HCI_ADV_TYPE_ADV_SCAN_IND:
-            max_usecs += BLE_LL_ADV_SCHED_MAX_USECS;
-            break;
-        default:
-            break;
-        }
+    /* 
+     * XXX: For now, just schedule some additional time so we insure we have
+     * enough time to do everything we want.
+     */
+    max_usecs += XCVR_PROC_DELAY_USECS;
 
+    if (sched_new) {
         /* 
-         * We dont really care if this is super accurate; it really is only
-         * used to block time in the scheduler.
-         */ 
-        sch->end_time = advsm->adv_pdu_start_time +
-            cputime_usecs_to_ticks(max_usecs);
-
-        /* XXX: for now, we cant get an overlap so assert on error. */
-        /* Add the item to the scheduler */
-        rc = ble_ll_sched_add(sch);
-        assert(rc == 0);
+         * We have to add the scheduling delay and tx start delay to the max
+         * time of the event since the pdu does not start at the scheduled start.
+         */
+        max_usecs += XCVR_TX_SCHED_DELAY_USECS;
+        sch->start_time = cputime_get32();
+        sch->end_time = sch->start_time + cputime_usecs_to_ticks(max_usecs);
     } else {
-        ++g_ble_ll_adv_stats.cant_set_sched;
+        sch->start_time = advsm->adv_pdu_start_time - 
+            cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+        sch->end_time = advsm->adv_pdu_start_time + 
+            cputime_usecs_to_ticks(max_usecs);
     }
+}
 
-    return sch;
+/**
+ * Called when advertising need to be halted. This normally should not be called 
+ * and is only called when a scheduled item executes but advertising is still 
+ * running. 
+ * 
+ */
+void
+ble_ll_adv_halt(void)
+{
+    ble_ll_adv_tx_done(&g_ble_ll_adv_sm);
 }
 
 /**
@@ -575,19 +586,23 @@ ble_ll_adv_set_adv_params(uint8_t *cmd)
 static void
 ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
 {
+    os_sr_t sr;
+
     if (advsm->enabled) {
         /* Disable whitelisting (just in case) */
         ble_ll_whitelist_disable();
 
         /* Remove any scheduled advertising items */
-        ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_ADV, NULL);
+        ble_ll_sched_rmv_elem(&advsm->adv_sch);
         os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
 
         /* Set to standby if we are no longer advertising */
+        OS_ENTER_CRITICAL(sr);
         if (ble_ll_state_get() == BLE_LL_STATE_ADV) {
             ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
         }
+        OS_EXIT_CRITICAL(sr);
 
         /* Disable advertising */
         advsm->enabled = 0;
@@ -608,9 +623,7 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
 static int
 ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
 {
-    int rc;
     uint8_t adv_chan;
-    struct ble_ll_sched_item *sch;
 
     /* 
      * XXX: not sure if I should do this or just report whatever random
@@ -661,12 +674,25 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
     }
 
     /* 
-     * Set start time for the advertising event. This time is the same
-     * as the time we will send the first PDU. Since there does not seem
-     * to be any requirements as to when we start, we do it asap.
-     */ 
-    advsm->adv_event_start_time = cputime_get32() +
-        cputime_usecs_to_ticks(BLE_LL_IFS + XCVR_PROC_DELAY_USECS);
+     * Schedule advertising. We set the initial schedule start and end
+     * times to the earliest possible start/end.
+     */
+    ble_ll_adv_set_sched(advsm, 1);
+    ble_ll_sched_adv_new(&advsm->adv_sch);
+
+    return BLE_ERR_SUCCESS;
+}
+
+void
+ble_ll_adv_scheduled(uint32_t sch_start)
+{
+    struct ble_ll_adv_sm *advsm;
+
+    advsm = &g_ble_ll_adv_sm;
+
+    /* The event start time is when we start transmission of the adv PDU */
+    advsm->adv_event_start_time = sch_start +
+        cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
 
     advsm->adv_pdu_start_time = advsm->adv_event_start_time;
 
@@ -677,17 +703,6 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
      */
     advsm->adv_dir_hd_end_time = advsm->adv_event_start_time +
         cputime_usecs_to_ticks(BLE_LL_ADV_STATE_HD_MAX * 1000);
-
-    /* Add to schedule. If we cant, we will just inform host we are too busy */
-    rc = BLE_ERR_SUCCESS;
-    sch = ble_ll_adv_sched_set(advsm);
-    if (!sch) {
-        advsm->enabled = 0;
-        ble_ll_whitelist_disable();
-        rc = BLE_ERR_CTLR_BUSY;
-    }
-
-    return rc;
 }
 
 /**
@@ -707,7 +722,9 @@ ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen)
 }
 
 /**
- * Turn advertising on/off.
+ * Turn advertising on/off. 
+ *  
+ * Context: Link Layer task 
  * 
  * @param cmd 
  * 
@@ -873,7 +890,7 @@ ble_ll_adv_rx_req(uint8_t pdu_type, struct os_mbuf *rxpdu)
     /* Setup to transmit the scan response if appropriate */
     rc = -1;
     if (pdu_type == BLE_ADV_PDU_TYPE_SCAN_REQ) {
-        /* NOTE: no callback nneds to be set as it should be NULL already */
+        ble_phy_set_txend_cb(ble_ll_adv_tx_done, &g_ble_ll_adv_sm);
         rc = ble_phy_tx(advsm->scan_rsp_pdu, BLE_PHY_TRANSITION_RX_TX, 
                         BLE_PHY_TRANSITION_NONE);
         if (!rc) {
@@ -964,15 +981,25 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
  *       > 0: Do not disable PHY as that has already been done.
  */
 int
-ble_ll_adv_rx_pdu_end(uint8_t pdu_type, struct os_mbuf *rxpdu)
+ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok)
 {
     int rc;
 
     rc = -1;
-    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 (rxpdu == NULL) {
+        ble_ll_adv_tx_done(&g_ble_ll_adv_sm);
+    } else {
+        if (crcok) {
+            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) {
+        ble_ll_state_set(BLE_LL_STATE_STANDBY);
     }
 
     return rc;
@@ -997,12 +1024,20 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
     int adv_event_over;
 
     /* 
-     * We should remove the schedule item in all cases except when we
-     * are sending a scan response or we have stopped advertising due to
-     * receiving a connect request
+     * If we have received a scan request and we are transmitting a response
+     * or we have received a valid connect request, dont "end" the advertising
+     * event. In the case of a connect request we will stop advertising. In
+     * the case of the scan response transmission we will get a transmit
+     * end callback.
+     * 
+     * XXX: I dont know why I wait to reschedule after transmitting a scan
+     * response. I wont schedule over it and I can use the transmission time
+     * to schedule the next advertising event. I also get rid of the code to
+     * deal with the "scan response transmitted". All depends on how we
+     * schedule the next transmissions in the advertising event.
      */
     adv_event_over = 1;
-    if (hdr->rxinfo.crcok) {
+    if (BLE_MBUF_HDR_CRC_OK(hdr)) {
         if (ptype == BLE_ADV_PDU_TYPE_CONNECT_REQ) {
             if (ble_ll_adv_conn_req_rxd(rxbuf, hdr)) {
                 adv_event_over = 0;
@@ -1034,7 +1069,7 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
  *   > 0: Continue to receive frame and go from rx to tx when done
  */
 int
-ble_ll_adv_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
+ble_ll_adv_rx_isr_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
 {
     int rc;
     struct ble_ll_adv_sm *advsm;
@@ -1061,6 +1096,14 @@ ble_ll_adv_rx_pdu_start(uint8_t pdu_type, struct os_mbuf *rxpdu)
         }
     }
 
+    /* 
+     * If we abort the frame, we need to post the LL task to check if the
+     * advertising event is over.
+     */
+    if (rc < 0) {
+        ble_ll_adv_tx_done(advsm);
+    }
+
     return rc;
 }
 
@@ -1078,15 +1121,19 @@ ble_ll_adv_event_done(void *arg)
     uint8_t final_adv_chan;
     int32_t delta_t;
     uint32_t itvl;
+    uint32_t start_time;
     struct ble_ll_adv_sm *advsm;
 
     /* Stop advertising event */
     advsm = (struct ble_ll_adv_sm *)arg;
     assert(advsm->enabled);
 
-    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_ADV, NULL);
+    /* Check if we need to resume scanning */
+    ble_ll_scan_chk_resume();
+
+    /* Remove the element from the schedule if it is still there. */
+    ble_ll_sched_rmv_elem(&advsm->adv_sch);
     os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
-    ble_ll_state_set(BLE_LL_STATE_STANDBY);
 
     /* For debug purposes */
 #ifdef BLETEST
@@ -1144,7 +1191,10 @@ ble_ll_adv_event_done(void *arg)
      * count a statistic and close the current advertising event. We will
      * then setup the next advertising event.
      */
-    delta_t = (int32_t)(advsm->adv_pdu_start_time - cputime_get32());
+    start_time = advsm->adv_pdu_start_time - 
+        cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
+
+    delta_t = (int32_t)(start_time - cputime_get32());
     if (delta_t < 0) {
         /* Count times we were late */
         ++g_ble_ll_adv_stats.late_tx_done;
@@ -1179,9 +1229,14 @@ ble_ll_adv_event_done(void *arg)
         }
     }
 
-    if (!ble_ll_adv_sched_set(advsm)) {
-        /* XXX: we will need to set a timer here to wake us up */
-        assert(0);
+    ble_ll_adv_set_sched(advsm, 0);
+
+    /* 
+     * In the unlikely event we cant reschedule this, just post a done
+     * event and we will reschedule the next advertising event
+     */ 
+    if (ble_ll_sched_adv_reschedule(&advsm->adv_sch)) {
+        os_eventq_put(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
     }
 }
 
@@ -1217,7 +1272,7 @@ void
 ble_ll_adv_wfr_timer_exp(void)
 {
     ble_phy_disable();
-    os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_adv_sm.adv_txdone_ev);
+    ble_ll_adv_tx_done(&g_ble_ll_adv_sm);
 }
 
 /**
@@ -1246,6 +1301,13 @@ ble_ll_adv_reset(void)
     ble_ll_adv_init();
 }
 
+/* Called to determine if advertising is enabled */
+uint8_t
+ble_ll_adv_enabled(void)
+{
+    return g_ble_ll_adv_sm.enabled;
+}
+
 /**
  * Initialize the advertising functionality of a BLE device. This should 
  * be called once on initialization

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 4566d10..373909b 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -32,6 +32,13 @@
 #include "hal/hal_cputime.h"
 #include "hal/hal_gpio.h"
 
+/* 
+ * XXX: looks like the current code will allow the 1st packet in a
+ * connection to extend past the end of the allocated connection end
+ * time. That is not good. Need to deal with that. Need to extend connection
+ * end time.
+ */
+
 /* XXX TODO
  * 1) Add set channel map command and implement channel change procedure.
  * 2) Make sure we have implemented all ways a connection can die/end. Not
@@ -56,8 +63,22 @@
  * the host that issued the create connection.
  * 9) How does peer address get set if we are using whitelist? Look at filter
  * policy and make sure you are doing this correctly.
+ * 10) Right now I use a fixed definition for required slots. CHange this.
+ * 11) Use output compare for transmit.
+ */
+
+/* 
+ * XXX: How should we deal with a late connection event? We need to determine
+ * what we want to do under the following cases:
+ *  1) The current connection event has not ended but a schedule item starts
+ *  2) The connection event start cb is called but we are later than we
+ *  expected. What to do? If we cant transmit at correct point in slot we
+ *  are hosed. Well, anchor point can get really messed up!
  */
 
+/* XXX: we need to make sure we hit the proper tx time for the anchor or we
+   could mess up the slave. Use output compare */
+
 /* XXX: this does not belong here! Move to transport? */
 extern int ble_hs_rx_data(struct os_mbuf *om);
 
@@ -76,19 +97,25 @@ extern int ble_hs_rx_data(struct os_mbuf *om);
  * XXX: move this definition and figure out how we determine the worst-case
  * jitter (spec. should have this).
  */
-#define BLE_LL_WFR_USECS    (BLE_LL_IFS + 40 + 32)
+#define BLE_LL_WFR_USECS                    (BLE_LL_IFS + 40 + 32)
 
 /* 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)
-#define BLE_LL_CONN_CFG_OUR_SCA             (500)   /* in ppm */
+#define BLE_LL_CFG_CONN_TX_WIN_SIZE         (1)
+#define BLE_LL_CFG_CONN_TX_WIN_OFF          (0)
+#define BLE_LL_CFG_CONN_MASTER_SCA          (BLE_MASTER_SCA_251_500_PPM << 5)
+#define BLE_LL_CFG_CONN_MAX_CONNS           (8)
+#define BLE_LL_CFG_CONN_OUR_SCA             (60)    /* in ppm */
+#define BLE_LL_CFG_CONN_INIT_SLOTS          (8)
+
+/* We cannot have more than 254 connections given our current implementation */
+#if (BLE_LL_CFG_CONN_MAX_CONNS >= 255)
+    #error "Maximum # of connections is 254"
+#endif
 
 /* LL configuration definitions */
 #define BLE_LL_CFG_SUPP_MAX_RX_BYTES        (251)
-#define BLE_LL_CFG_SUPP_MAX_TX_BYTES        (251)
-#define BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES   (251)
+#define BLE_LL_CFG_SUPP_MAX_TX_BYTES        (27)
+#define BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES   (27)
 
 /* Sleep clock accuracy table (in ppm) */
 static const uint16_t g_ble_sca_ppm_tbl[8] =
@@ -115,7 +142,7 @@ struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
 struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm;
 
 /* Connection state machine array */
-struct ble_ll_conn_sm g_ble_ll_conn_sm[BLE_LL_CONN_CFG_MAX_CONNS];
+struct ble_ll_conn_sm g_ble_ll_conn_sm[BLE_LL_CFG_CONN_MAX_CONNS];
 
 /* List of active connections */
 struct ble_ll_conn_active_list g_ble_ll_conn_active_list;
@@ -149,6 +176,40 @@ struct ble_ll_conn_stats g_ble_ll_conn_stats;
 /* Some helpful macros */
 #define BLE_IS_RETRY_M(ble_hdr) ((ble_hdr)->txinfo.flags & BLE_MBUF_HDR_F_TXD)
 
+int 
+ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2)
+{
+    int rc;
+
+    /* Set time that we last serviced the schedule */
+    if ((int32_t)(s1->last_scheduled - s2->last_scheduled) < 0) {
+        rc = 1;
+    } else {
+        rc = 0;
+    }
+
+    return rc;
+}
+
+/**
+ * Called to return the currently running connection state machine end time. 
+ * Always called when interrupts are disabled.
+ * 
+ * @return uint32_t 
+ */
+uint32_t
+ble_ll_conn_get_ce_end_time(void)
+{
+    uint32_t ce_end_time;
+
+    if (g_ble_ll_conn_cur_sm) {
+        ce_end_time = g_ble_ll_conn_cur_sm->ce_end_time;
+    } else {
+        ce_end_time = cputime_get32();
+    }
+    return ce_end_time;
+}
+
 /**
  * Checks if pdu is a L2CAP pdu, meaning it is not a control pdu nor an empty 
  * pdu. Called only for transmit PDU's.
@@ -192,9 +253,6 @@ ble_ll_conn_current_sm_over(void)
     /* Disable the wfr timer */
     ble_ll_wfr_disable();
 
-    /* Remove any scheduled items for this connection */
-    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_CONN, g_ble_ll_conn_cur_sm);
-
     /* Link-layer is in standby state now */
     ble_ll_state_set(BLE_LL_STATE_STANDBY);
 
@@ -214,9 +272,11 @@ ble_ll_conn_find_active_conn(uint16_t handle)
 {
     struct ble_ll_conn_sm *connsm;
 
-    SLIST_FOREACH(connsm, &g_ble_ll_conn_active_list, act_sle) {
-        if (connsm->conn_handle == handle) {
-            break;
+    connsm = NULL;
+    if ((handle != 0) && (handle <= BLE_LL_CFG_CONN_MAX_CONNS)) {
+        connsm = &g_ble_ll_conn_sm[handle - 1];
+        if (connsm->conn_state == BLE_LL_CONN_STATE_IDLE) {
+            connsm = NULL;
         }
     }
     return connsm;
@@ -264,7 +324,7 @@ ble_ll_conn_calc_window_widening(struct ble_ll_conn_sm *connsm)
     if (time_since_last_anchor > 0) {
         delta_msec = cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
         total_sca_ppm = g_ble_sca_ppm_tbl[connsm->master_sca] + 
-                        BLE_LL_CONN_CFG_OUR_SCA;
+                        BLE_LL_CFG_CONN_OUR_SCA;
         window_widening = (total_sca_ppm * delta_msec) / 1000;
     }
 
@@ -468,6 +528,7 @@ ble_ll_conn_wfr_timer_exp(void)
     struct ble_ll_conn_sm *connsm;
 
     connsm = g_ble_ll_conn_cur_sm;
+    ble_ll_conn_current_sm_over();
     if (connsm) {
         ble_ll_event_send(&connsm->conn_ev_end);
         ++g_ble_ll_conn_stats.wfr_expirations;
@@ -488,6 +549,8 @@ ble_ll_conn_wait_txend(void *arg)
 {
     struct ble_ll_conn_sm *connsm;
 
+    ble_ll_conn_current_sm_over();
+
     connsm = (struct ble_ll_conn_sm *)arg;
     ble_ll_event_send(&connsm->conn_ev_end);
 }
@@ -679,26 +742,6 @@ ble_ll_conn_tx_data_pdu(struct ble_ll_conn_sm *connsm, int beg_transition)
 }
 
 /**
- * Connection end schedule callback. Called when the scheduled connection 
- * event ends. 
- *  
- * Context: Interrupt 
- *  
- * @param sch 
- * 
- * @return int 
- */
-static int
-ble_ll_conn_ev_end_sched_cb(struct ble_ll_sched_item *sch)
-{
-    struct ble_ll_conn_sm *connsm;
-
-    connsm = (struct ble_ll_conn_sm *)sch->cb_arg;
-    ble_ll_event_send(&connsm->conn_ev_end);
-    return BLE_LL_SCHED_STATE_DONE;
-}
-
-/**
  * Schedule callback for start of connection event 
  *  
  * Context: Interrupt 
@@ -715,18 +758,19 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
     uint32_t wfr_time;
     struct ble_ll_conn_sm *connsm;
 
-    /* set led */
-    gpio_clear(LED_BLINK_PIN);
+    /* XXX: note that we can extend end time here if we want. Look at this */
 
     /* Set current connection state machine */
     connsm = (struct ble_ll_conn_sm *)sch->cb_arg;
     g_ble_ll_conn_cur_sm = connsm;
+    assert(connsm);
 
     /* Set LL state */
     ble_ll_state_set(BLE_LL_STATE_CONNECTION);
 
     /* Log connection event start */
-    ble_ll_log(BLE_LL_LOG_ID_CONN_EV_START, connsm->data_chan_index, 0, 0);
+    ble_ll_log(BLE_LL_LOG_ID_CONN_EV_START, connsm->data_chan_index, 0, 
+               connsm->ce_end_time);
 
     /* Set channel */
     rc = ble_phy_setchan(connsm->data_chan_index, connsm->access_addr, 
@@ -736,12 +780,9 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
     if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
         rc = ble_ll_conn_tx_data_pdu(connsm, BLE_PHY_TRANSITION_NONE);
         if (!rc) {
-            sch->next_wakeup = sch->end_time;
-            sch->sched_cb = ble_ll_conn_ev_end_sched_cb;
             rc = BLE_LL_SCHED_STATE_RUNNING;
         } else {
             /* Inform LL task of connection event end */
-            ble_ll_event_send(&connsm->conn_ev_end);
             rc = BLE_LL_SCHED_STATE_DONE;
         }
     } else {
@@ -749,7 +790,6 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
         if (rc) {
             /* End the connection event as we have no more buffers */
             ++g_ble_ll_conn_stats.slave_ce_failures;
-            ble_ll_event_send(&connsm->conn_ev_end);
             rc = BLE_LL_SCHED_STATE_DONE;
         } else {
             /* 
@@ -758,17 +798,32 @@ ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
              */ 
             connsm->slave_set_last_anchor = 1;
 
+            /* 
+             * Set the wait for response time. The anchor point is when we
+             * expect the master to start transmitting. Worst-case, we expect
+             * to hear a reply within the anchor point plus:
+             *  -> the current tx window size
+             *  -> The current window widening amount
+             *  -> Amount of time it takes to detect packet start.
+             */
             usecs = connsm->slave_cur_tx_win_usecs + BLE_LL_WFR_USECS +
                 connsm->slave_cur_window_widening;
             wfr_time = connsm->anchor_point + cputime_usecs_to_ticks(usecs);
             ble_ll_wfr_enable(wfr_time);
 
             /* Set next wakeup time to connection event end time */
-            sch->next_wakeup = sch->end_time;
-            sch->sched_cb = ble_ll_conn_ev_end_sched_cb;
             rc = BLE_LL_SCHED_STATE_RUNNING;
         }
     }
+
+    if (rc == BLE_LL_SCHED_STATE_DONE) {
+        ble_ll_event_send(&connsm->conn_ev_end);
+        ble_ll_state_set(BLE_LL_STATE_STANDBY);
+        g_ble_ll_conn_cur_sm = NULL;
+    }
+
+    /* Set time that we last serviced the schedule */
+    connsm->last_scheduled = cputime_get32();
     return rc;
 }
 
@@ -821,71 +876,6 @@ ble_ll_conn_can_send_next_pdu(struct ble_ll_conn_sm *connsm, uint32_t begtime)
 }
 
 /**
- * Set the schedule for connection events
- *  
- * Context: Link Layer task 
- * 
- * @param connsm 
- * 
- * @return struct ble_ll_sched_item * 
- */
-static struct ble_ll_sched_item *
-ble_ll_conn_sched_set(struct ble_ll_conn_sm *connsm)
-{
-    int rc;
-    uint32_t usecs;
-    struct ble_ll_sched_item *sch;
-
-    sch = ble_ll_sched_get_item();
-    if (sch) {
-        /* Set sched type, arg and callback function */
-        sch->sched_type = BLE_LL_SCHED_TYPE_CONN;
-        sch->cb_arg = connsm;
-        sch->sched_cb = ble_ll_conn_event_start_cb;
-
-        /* Set the start time of the event */
-        if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-            sch->start_time = connsm->anchor_point - 
-                cputime_usecs_to_ticks(XCVR_TX_SCHED_DELAY_USECS);
-
-            /* We will attempt to schedule the maximum CE length */
-            usecs = connsm->max_ce_len * BLE_LL_CONN_CE_USECS;
-        } else {
-            /* Include window widening and scheduling delay */
-            usecs = connsm->slave_cur_window_widening +
-                XCVR_RX_SCHED_DELAY_USECS;
-
-            sch->start_time = connsm->anchor_point - 
-                cputime_usecs_to_ticks(usecs);
-
-            /* Schedule entire connection interval for slave */
-            usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
-        }
-
-        /* 
-         * We must end at least an IFS before the next scheduled event to
-         * insure the minimum time between frames.
-         */
-        usecs -= (BLE_LL_IFS + BLE_LL_PROC_DELAY);
-        sch->end_time = connsm->anchor_point + cputime_usecs_to_ticks(usecs);
-        connsm->ce_end_time = sch->end_time;
-
-        /* XXX: for now, we cant get an overlap so assert on error. */
-        /* Add the item to the scheduler */
-        rc = ble_ll_sched_add(sch);
-        assert(rc == 0);
-    } else {
-        /* Count # of times we could not set schedule */
-        ++g_ble_ll_conn_stats.cant_set_sched;
-
-        /* XXX: for now just assert; must handle this later though */
-        assert(0);
-    }
-
-    return sch;
-}
-
-/**
  * Connection supervision timer callback; means that the connection supervision
  * timeout has been reached and we should perform the appropriate actions. 
  *  
@@ -915,11 +905,13 @@ void
 ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm, 
                         struct hci_create_conn *hcc)
 {
-    /* Must be master */
+    /* Set master role */
     connsm->conn_role = BLE_LL_CONN_ROLE_MASTER;
-    connsm->tx_win_size = BLE_LL_CONN_CFG_TX_WIN_SIZE;
-    connsm->tx_win_off = BLE_LL_CONN_CFG_TX_WIN_OFF;
-    connsm->master_sca = BLE_LL_CONN_CFG_MASTER_SCA;
+
+    /* Set default ce parameters */
+    connsm->tx_win_size = BLE_LL_CFG_CONN_TX_WIN_SIZE;
+    connsm->tx_win_off = BLE_LL_CFG_CONN_TX_WIN_OFF;
+    connsm->master_sca = BLE_LL_CFG_CONN_MASTER_SCA;
 
     /* Hop increment is a random value between 5 and 16. */
     connsm->hop_inc = (rand() % 12) + 5;
@@ -962,17 +954,22 @@ ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
     /*  Calculate random access address and crc initialization value */
     connsm->access_addr = ble_ll_conn_calc_access_addr();
     connsm->crcinit = rand() & 0xffffff;
+
+    /* Set initial schedule callback */
+    connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
 }
 
 /**
- * Start the connection state machine. This is done once per connection 
- * when the HCI command "create connection" is issued to the controller or 
- * when a slave receives a connect request, 
+ * Create a new connection state machine. This is done once per 
+ * connection when the HCI command "create connection" is issued to the 
+ * controller or when a slave receives a connect request. 
+ *  
+ * Context: Link Layer task 
  * 
  * @param connsm 
  */
 void
-ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm)
+ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm)
 {
     struct ble_ll_conn_global_params *conn_params;
 
@@ -1030,20 +1027,6 @@ ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm)
     connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
     connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
 
-    /* 
-     * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
-     * exceeds the minimum, data length procedure needs to occur
-     */
-    if ((connsm->max_tx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
-        (connsm->max_rx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
-        (connsm->max_tx_time > BLE_LL_CONN_SUPP_TIME_MIN) ||
-        (connsm->max_rx_time > BLE_LL_CONN_SUPP_TIME_MIN)) {
-        /* Start the data length update procedure */
-        if (ble_ll_read_supp_features() & BLE_LL_FEAT_DATA_LEN_EXT) {
-            ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
-        }
-    }
-
     /* Add to list of active connections */
     SLIST_INSERT_HEAD(&g_ble_ll_conn_active_list, connsm, act_sle);
 }
@@ -1114,13 +1097,8 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
     struct os_mbuf *m;
     struct os_mbuf_pkthdr *pkthdr;
 
-    /* If this is the current state machine, we need to end it */
-    if (connsm == g_ble_ll_conn_cur_sm) {
-        ble_ll_conn_current_sm_over();
-    } else {
-        /* Remove scheduler events just in case */
-        ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_CONN, connsm);
-    }
+    /* Remove scheduler events just in case */
+    ble_ll_sched_rmv_elem(&connsm->conn_sch);
 
     /* Stop supervision timer */
     cputime_timer_stop(&connsm->conn_spvn_timer);
@@ -1173,6 +1151,75 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
     ble_ll_log(BLE_LL_LOG_ID_CONN_END,connsm->conn_handle,0,connsm->event_cntr);
 }
 
+static int
+ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
+{
+    uint16_t latency;
+    uint32_t itvl;
+    uint32_t cur_ww;
+    uint32_t max_ww;
+
+    /* 
+     * XXX: not quite sure I am interpreting slave latency correctly here.
+     * The spec says if you applied slave latency and you dont hear a packet,
+     * you dont apply slave latency. Does that mean you dont apply slave
+     * latency until you hear a packet or on the next interval if you listen
+     * and dont hear anything, can you apply slave latency?
+     */
+    /* Set event counter to the next connection event that we will tx/rx in */
+    itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+    latency = 1;
+    if (connsm->allow_slave_latency) {
+        if (connsm->pkt_rxd) {
+            latency += connsm->slave_latency;
+            itvl = itvl * latency;
+        }
+    }
+    connsm->event_cntr += latency;
+
+    /* Set next connection event start time */
+    connsm->anchor_point += cputime_usecs_to_ticks(itvl);
+
+    /* Calculate data channel index of next connection event */
+    connsm->last_unmapped_chan = connsm->unmapped_chan;
+    while (latency > 0) {
+        --latency;
+        connsm->data_chan_index = ble_ll_conn_calc_dci(connsm);
+    }
+
+    /* 
+     * If we are trying to terminate connection, check if next wake time is
+     * passed the termination timeout. If so, no need to continue with
+     * connection as we will time out anyway.
+     */
+    if (connsm->pending_ctrl_procs & (1 << BLE_LL_CTRL_PROC_TERMINATE)) {
+        if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) {
+            return -1;
+        }
+    }
+
+    /* 
+     * Calculate ce end time. For a slave, we need to add window widening and
+     * the transmit window if we still have one.
+     */
+    itvl = BLE_LL_CFG_CONN_INIT_SLOTS * BLE_LL_SCHED_USECS_PER_SLOT;
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+        cur_ww = ble_ll_conn_calc_window_widening(connsm);
+        max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS;
+        if (cur_ww >= max_ww) {
+            return -1;
+        }
+        connsm->slave_cur_window_widening = cur_ww;
+        itvl += cur_ww + connsm->slave_cur_tx_win_usecs;
+    } else {
+        /* We adjust end time for connection to end of time slot */
+        itvl -= XCVR_TX_SCHED_DELAY_USECS;
+    }
+    connsm->ce_end_time = connsm->anchor_point + cputime_usecs_to_ticks(itvl);
+
+    return 0;
+}
+
 /**
  * Called when a connection has been created. This function will 
  *  -> Set the connection state to created.
@@ -1185,10 +1232,13 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
  *  Context: Link Layer
  * 
  * @param connsm 
+ *  
+ * @ return 0: connection NOT created. 1: connection created 
  */
-static void
+static int
 ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
 {
+    int rc;
     uint32_t usecs;
 
     /* Set state to created */
@@ -1201,34 +1251,56 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
     /* Clear packet received flag */
     connsm->pkt_rxd = 0;
 
+    /* Consider time created the last scheduled time */
+    connsm->last_scheduled = cputime_get32();
+
     /* 
-     * Set first connection event time. If we are a master, the endtime
-     * represents the end of the advertisement that we are transmitting the
-     * connect request to. If a slave, it is the end time of connect request.
-     * Thus, for the master, we need to add an IFS time plus the time it takes
-     * to transmit the connection request. For both master and slave, the
-     * actual connection starts 1.25 msecs plus the transmit window offset
-     * from the end of the connection request.
+     * Set first connection event time. If slave the endtime is the receive end
+     * time of the connect request. The actual connection starts 1.25 msecs plus
+     * the transmit window offset from the end of the connection request.
      */
+    rc = 1;
     connsm->last_anchor_point = endtime;
-    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-        usecs = BLE_LL_CONN_REQ_DURATION + BLE_LL_IFS;
-        connsm->last_anchor_point += cputime_usecs_to_ticks(usecs);
-
-    } else {
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
         connsm->slave_cur_tx_win_usecs = 
             connsm->tx_win_size * BLE_LL_CONN_TX_WIN_USECS;
-        usecs = 0;
+        usecs = 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
+        connsm->anchor_point = endtime + cputime_usecs_to_ticks(usecs);
+        usecs = connsm->slave_cur_tx_win_usecs + (BLE_LL_CFG_CONN_INIT_SLOTS *
+                                                  BLE_LL_SCHED_USECS_PER_SLOT);
+        connsm->ce_end_time = connsm->anchor_point + 
+            cputime_usecs_to_ticks(usecs);
+        connsm->slave_cur_window_widening = 0;
+
+        /* Start the scheduler for the first connection event */
+        while (ble_ll_sched_slave_new(connsm)) {
+            if (ble_ll_conn_next_event(connsm)) {
+                ++g_ble_ll_conn_stats.cant_set_sched;
+                rc = 0;
+                break;
+            }
+        }
     }
-    usecs += 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
-    connsm->anchor_point = endtime + cputime_usecs_to_ticks(usecs);
-    connsm->slave_cur_window_widening = 0;
 
     /* Send connection complete event to inform host of connection */
-    ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
+    if (rc) {
+        /* 
+         * Section 4.5.10 Vol 6 PART B. If the max tx/rx time or octets
+         * exceeds the minimum, data length procedure needs to occur
+         */
+        if ((connsm->max_tx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
+            (connsm->max_rx_octets > BLE_LL_CONN_SUPP_BYTES_MIN) ||
+            (connsm->max_tx_time > BLE_LL_CONN_SUPP_TIME_MIN) ||
+            (connsm->max_rx_time > BLE_LL_CONN_SUPP_TIME_MIN)) {
+            /* Start the data length update procedure */
+            if (ble_ll_read_supp_features() & BLE_LL_FEAT_DATA_LEN_EXT) {
+                ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
+            }
+        }
+        ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
+    }
 
-    /* Start the scheduler for the first connection event */
-    ble_ll_conn_sched_set(connsm);
+    return rc;
 }
 
 /**
@@ -1243,17 +1315,18 @@ void
 ble_ll_conn_event_end(void *arg)
 {
     uint8_t ble_err;
-    uint16_t latency;
-    uint32_t itvl;
-    uint32_t cur_ww;
-    uint32_t max_ww;
     struct ble_ll_conn_sm *connsm;
 
+    /* Better be a connection state machine! */
     connsm = (struct ble_ll_conn_sm *)arg;
-    assert(connsm && (connsm == g_ble_ll_conn_cur_sm));
+    assert(connsm);
 
-    /* The current state machine is over */
-    ble_ll_conn_current_sm_over();
+    /* Check if we need to resume scanning */
+    ble_ll_scan_chk_resume();
+
+    /* Log event end */
+    ble_ll_log(BLE_LL_LOG_ID_CONN_EV_END, 0, connsm->event_cntr, 
+               connsm->ce_end_time);
 
     /* If we have transmitted the terminate IND successfully, we are done */
     if ((connsm->terminate_ind_txd) || (connsm->terminate_ind_rxd)) {
@@ -1281,79 +1354,30 @@ ble_ll_conn_event_end(void *arg)
         connsm->slave_cur_tx_win_usecs = 0;
     }
 
-    /* 
-     * XXX: not quite sure I am interpreting slave latency correctly here.
-     * The spec says if you applied slave latency and you dont hear a packet,
-     * you dont apply slave latency. Does that mean you dont apply slave
-     * latency until you hear a packet or on the next interval if you listen
-     * and dont hear anything, can you apply slave latency?
-     */
-    /* Set event counter to the next connection event that we will tx/rx in */
-    itvl = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
-    latency = 1;
-    if (connsm->allow_slave_latency) {
-        if (connsm->pkt_rxd) {
-            latency += connsm->slave_latency;
-            itvl = itvl * latency;
-        }
-    }
-    connsm->event_cntr += latency;
-
-    /* Set next connection event start time */
-    connsm->anchor_point += cputime_usecs_to_ticks(itvl);
-
-    /* Calculate data channel index of next connection event */
-    connsm->last_unmapped_chan = connsm->unmapped_chan;
-    while (latency > 0) {
-        --latency;
-        connsm->data_chan_index = ble_ll_conn_calc_dci(connsm);
-    }
-
-    /* We better not be late for the anchor point. If so, skip events */
-    while ((int32_t)(connsm->anchor_point - cputime_get32()) <= 0) {
-        ++connsm->event_cntr;
-        connsm->data_chan_index = ble_ll_conn_calc_dci(connsm);
-        connsm->anchor_point += 
-            cputime_usecs_to_ticks(connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS);
-        ++g_ble_ll_conn_stats.conn_ev_late;
+    /* Move to next connection event */
+    if (ble_ll_conn_next_event(connsm)) {
+        ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL);
+        return;
     }
 
     /* Reset "per connection event" variables */
     connsm->cons_rxd_bad_crc = 0;
     connsm->pkt_rxd = 0;
 
-    /* 
-     * If we are trying to terminate connection, check if next wake time is
-     * passed the termination timeout. If so, no need to continue with
-     * connection as we will time out anyway.
-     */
-    if (connsm->pending_ctrl_procs & (1 << BLE_LL_CTRL_PROC_TERMINATE)) {
-        if ((int32_t)(connsm->terminate_timeout - connsm->anchor_point) <= 0) {
-            ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL);
-            return;
-        }
-    }
+    /* See if we need to start any control procedures */
+    ble_ll_ctrl_chk_proc_start(connsm);
 
-    /* Calculate window widening for next event. If too big, end conn */
-    if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
-        cur_ww = ble_ll_conn_calc_window_widening(connsm);
-        max_ww = (connsm->conn_itvl * (BLE_LL_CONN_ITVL_USECS/2)) - BLE_LL_IFS;
-        if (cur_ww >= max_ww) {
+    /* Set initial schedule callback */
+    connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
+
+    /* Schedule the next connection event */
+    while (ble_ll_sched_conn_reschedule(connsm)) {
+        if (ble_ll_conn_next_event(connsm)) {
             ble_ll_conn_end(connsm, BLE_ERR_CONN_TERM_LOCAL);
             return;
         }
-        connsm->slave_cur_window_widening = cur_ww;
     }
 
-    /* Log event end */
-    ble_ll_log(BLE_LL_LOG_ID_CONN_EV_END, 0, 0, connsm->event_cntr);
-
-    /* See if we need to start any control procedures */
-    ble_ll_ctrl_chk_proc_start(connsm);
-
-    /* Schedule the next connection event */
-    ble_ll_conn_sched_set(connsm);
-
     /* If we have completed packets, send an event */
     if (connsm->completed_pkts) {
         ble_ll_conn_num_comp_pkts_event_send();
@@ -1367,9 +1391,11 @@ ble_ll_conn_event_end(void *arg)
  * @param m 
  * @param adva 
  * @param addr_type 
+ * @param txoffset      The tx window offset for this connection 
  */
-void
-ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type)
+static void
+ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
+                           uint16_t txoffset)
 {
     uint8_t pdu_type;
     uint8_t *dptr;
@@ -1391,7 +1417,8 @@ ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type)
     ble_hdr->txinfo.hdr_byte = pdu_type;
 
     dptr = m->om_data;
-    memcpy(dptr + BLE_DEV_ADDR_LEN, adva, BLE_DEV_ADDR_LEN); 
+    memcpy(dptr + BLE_DEV_ADDR_LEN, adva, BLE_DEV_ADDR_LEN);
+    htole16(dptr + 20, txoffset);
 }
 
 /* Returns true if the address matches the connection peer address */
@@ -1414,6 +1441,19 @@ ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
 }
 
 /**
+ * Called when a connect request transmission is done. 
+ *  
+ * Context: ISR 
+ * 
+ * @param arg 
+ */
+static void
+ble_ll_conn_req_txend(void *arg)
+{
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+}
+
+/**
  * Send a connection requestion to an advertiser 
  *  
  * Context: Interrupt 
@@ -1422,18 +1462,38 @@ ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
  * @param adva Address of advertiser
  */
 static int
-ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva)
+ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva, uint16_t txoffset)
 {
     int rc;
     struct os_mbuf *m;
 
     m = ble_ll_scan_get_pdu();
-    ble_ll_conn_req_pdu_update(m, adva, addr_type);
+    ble_ll_conn_req_pdu_update(m, adva, addr_type, txoffset);
+    ble_phy_set_txend_cb(ble_ll_conn_req_txend, NULL);
     rc = ble_phy_tx(m, BLE_PHY_TRANSITION_RX_TX, BLE_PHY_TRANSITION_NONE);
     return rc;
 }
 
 /**
+ * Called when a schedule item overlaps the currently running connection 
+ * event. This generally should not happen, but if it does we stop the 
+ * current connection event to let the schedule item run. 
+ *  
+ * NOTE: the phy has been disabled as well as the wfr timer before this is 
+ * called. 
+ */
+void
+ble_ll_conn_event_halt(void)
+{
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+    if (g_ble_ll_conn_cur_sm) {
+        g_ble_ll_conn_cur_sm->pkt_rxd = 0;
+        ble_ll_event_send(&g_ble_ll_conn_cur_sm->conn_ev_end);
+        g_ble_ll_conn_cur_sm = NULL;
+    }
+}
+
+/**
  * Process a received PDU while in the initiating state.
  *  
  * Context: Link Layer task. 
@@ -1449,12 +1509,9 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
 
     /* Get the connection state machine we are trying to create */
     connsm = g_ble_ll_conn_create_sm;
-    if (!connsm) {
-        return;
-    }
 
     /* If we have sent a connect request, we need to enter CONNECTION state*/
-    if (ble_hdr->rxinfo.crcok && 
+    if (connsm && BLE_MBUF_HDR_CRC_OK(ble_hdr) && 
         (ble_hdr->rxinfo.flags & BLE_MBUF_HDR_F_CONN_REQ_TXD)) {
         /* Set address of advertiser to which we are connecting. */
         if (!ble_ll_scan_whitelist_enabled()) {
@@ -1477,15 +1534,15 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
 
         /* Connection has been created. Stop scanning */
         g_ble_ll_conn_create_sm = NULL;
-        ble_ll_scan_sm_stop(ble_ll_scan_sm_get(), 1);
+        ble_ll_scan_sm_stop(0);
         ble_ll_conn_created(connsm, ble_hdr->end_cputime);
     } else {
-        ble_ll_scan_resume();
+        ble_ll_scan_chk_resume();
     }
 }
 
 /**
- * Called when a receive PDU has ended. 
+ * Called when a receive PDU has ended and we are in the initiating state.
  *  
  * Context: Interrupt 
  * 
@@ -1497,7 +1554,7 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
  *       > 0: Do not disable PHY as that has already been done.
  */
 int
-ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
+ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok)
 {
     int rc;
     int chk_send_req;
@@ -1508,6 +1565,20 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
     uint8_t *rxbuf;
     struct ble_mbuf_hdr *ble_hdr;
 
+    /* 
+     * We have to restart receive if we cant hand up pdu. We return 0 so that
+     * the phy does not get disabled.
+     */
+    if (!rxpdu) {
+        ble_phy_rx();
+        return 0;
+    }
+
+    rc = -1;
+    if (!crcok) {
+        goto init_rx_isr_exit;
+    }
+
     /* Only interested in ADV IND or ADV DIRECT IND */
     rxbuf = rxpdu->om_data;
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
@@ -1531,7 +1602,6 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
     }
 
     /* Should we send a connect request? */
-    rc = -1;
     if (chk_send_req) {
         /* Check filter policy */
         adv_addr = rxbuf + BLE_LL_PDU_HDR_LEN;
@@ -1560,18 +1630,63 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
             }
         }
 
-        /* Setup to transmit the connect request */
-        rc = ble_ll_conn_request_send(addr_type, adv_addr);
-        if (!rc) {
-            ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_REQ_TXD;
-            ++g_ble_ll_conn_stats.conn_req_txd;
+        /* Attempt to schedule new connection. Possible that this might fail */
+        if (!ble_ll_sched_master_new(g_ble_ll_conn_create_sm, 
+                                   ble_hdr->end_cputime,
+                                   BLE_LL_CFG_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);
+            if (!rc) {
+                ble_hdr->rxinfo.flags |= BLE_MBUF_HDR_F_CONN_REQ_TXD;
+                ++g_ble_ll_conn_stats.conn_req_txd;
+            }
+        } else {
+            /* Count # of times we could not set schedule */
+            ++g_ble_ll_conn_stats.cant_set_sched;
         }
     }
 
+init_rx_isr_exit:
+    if (rc) {
+        ble_ll_state_set(BLE_LL_STATE_STANDBY);
+    }
     return rc;
 }
 
 /**
+ * Function called when a timeout has occurred for a connection. There are 
+ * two types of timeouts: a connection supervision timeout and control 
+ * procedure timeout. 
+ *  
+ * Context: Link Layer task 
+ * 
+ * @param connsm 
+ * @param ble_err 
+ */
+void
+ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
+{
+    int was_current;
+    os_sr_t sr;
+
+    was_current = 0;
+    OS_ENTER_CRITICAL(sr);
+    if (g_ble_ll_conn_cur_sm == connsm) {
+        ble_ll_conn_current_sm_over();
+        was_current = 1;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    /* Check if we need to resume scanning */
+    if (was_current) {
+        ble_ll_scan_chk_resume();
+    }
+
+    ble_ll_conn_end(connsm, ble_err);
+}
+
+/**
  * Connection supervision timeout. When called, it means that the connection 
  * supervision timeout has been reached. If reached, we end the connection. 
  *  
@@ -1582,16 +1697,18 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
 void
 ble_ll_conn_spvn_timeout(void *arg)
 {
-    ble_ll_conn_end((struct ble_ll_conn_sm *)arg, BLE_ERR_CONN_SPVN_TMO);
+    ble_ll_conn_timeout((struct ble_ll_conn_sm *)arg, BLE_ERR_CONN_SPVN_TMO);
 }
 
 /**
  * Called when a data channel PDU has started that matches the access 
  * address of the current connection. Note that the CRC of the PDU has not 
- * been checked yet.
+ * been checked yet. 
+ *  
+ * Context: Interrupt 
  */
 void
-ble_ll_conn_rx_pdu_start(void)
+ble_ll_conn_rx_isr_start(void)
 {
     struct ble_ll_conn_sm *connsm;
 
@@ -1613,10 +1730,11 @@ ble_ll_conn_rx_pdu_start(void)
  *  
  * Context: Link layer task 
  * 
- * @param rxpdu 
+ * @param rxpdu Pointer to received pdu
+ * @param rxpdu Pointer to ble mbuf header of received pdu
  */
 void
-ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
+ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
 {
     uint8_t hdr_byte;
     uint8_t rxd_sn;
@@ -1625,13 +1743,15 @@ ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok)
     uint16_t acl_hdr;
     uint32_t tmo;
     struct ble_ll_conn_sm *connsm;
-
-    if (crcok) {
+    
+    if (BLE_MBUF_HDR_CRC_OK(hdr)) {
         /* Count valid received data pdus */
         ++g_ble_ll_stats.rx_valid_data_pdus;
 
+        /* XXX: there is a chance that the connection was thrown away and
+           re-used before processing packets here. Fix this. */
         /* We better have a connection state machine */
-        connsm = g_ble_ll_conn_cur_sm;
+        connsm = ble_ll_conn_find_active_conn(hdr->rxinfo.handle);
         if (connsm) {
             /* Reset the connection supervision timeout */
             cputime_timer_stop(&connsm->conn_spvn_timer);
@@ -1724,7 +1844,7 @@ conn_rx_data_pdu_end:
  *       > 0: Do not disable PHY as that has already been done.
  */
 int
-ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint32_t aa)
+ble_ll_conn_rx_isr_end(struct os_mbuf *rxpdu, uint32_t aa)
 {
     int rc;
     uint8_t hdr_byte;
@@ -1744,26 +1864,29 @@ ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint32_t aa)
      * We should have a current connection state machine. If we dont, we just
      * hand the packet to the higher layer to count it.
      */
+    rc = -1;
     connsm = g_ble_ll_conn_cur_sm;
     if (!connsm) {
         ++g_ble_ll_conn_stats.rx_data_pdu_no_conn;
-        return -1;
+        goto conn_exit;
     }
 
     /* Double check access address. Better match connection state machine! */
     if (aa != connsm->access_addr) {
         ++g_ble_ll_conn_stats.rx_data_pdu_bad_aa;
-        ble_ll_event_send(&connsm->conn_ev_end);
-        return -1;
+        goto conn_exit;
     }
 
+    /* Set the handle in the ble mbuf header */
+    rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
+    rxhdr->rxinfo.handle = connsm->conn_handle;
+
     /* 
      * Check the packet CRC. A connection event can continue even if the
      * received PDU does not pass the CRC check. If we receive two consecutive
      * CRC errors we end the conection event.
      */
-    rxhdr = BLE_MBUF_HDR_PTR(rxpdu);
-    if (!rxhdr->rxinfo.crcok) {
+    if (!BLE_MBUF_HDR_CRC_OK(rxhdr)) {
         /* 
          * Increment # of consecutively received CRC errors. If more than
          * one we will end the connection event.
@@ -1894,19 +2017,24 @@ ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint32_t aa)
     }
 
 conn_rx_pdu_end:
-    /* Set last anchor point if 1st received frame in connection event */
+    /* Set anchor point (and last) if 1st received frame in connection event */
     if (connsm->slave_set_last_anchor) {
         connsm->slave_set_last_anchor = 0;
         connsm->last_anchor_point = rxhdr->end_cputime - 
             BLE_TX_DUR_USECS_M(rxpdu->om_data[1]);
+        connsm->anchor_point = connsm->last_anchor_point;
     }
 
     /* Send link layer a connection end event if over */
+conn_exit:
     if (rc) {
-        ble_ll_event_send(&connsm->conn_ev_end);
+        ble_ll_conn_current_sm_over();
+        if (connsm) {
+            ble_ll_event_send(&connsm->conn_ev_end);
+        }
     }
 
-    return 0;
+    return rc;
 }
 
 /**
@@ -1999,12 +2127,14 @@ ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t length)
  * Context: Link Layer 
  *  
  * @param rxbuf Pointer to received PDU 
+ * @param conn_req_end receive end time of connect request 
  *  
  * @return 0: connection not started; 1 connecton started 
  */
 int
 ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end)
 {
+    int rc;
     uint32_t temp;
     uint32_t crcinit;
     uint8_t *inita;
@@ -2096,11 +2226,17 @@ ble_ll_conn_slave_start(uint8_t *rxbuf, uint32_t conn_req_end)
 
     /* Start the connection state machine */
     connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
-    ble_ll_conn_sm_start(connsm);
+    ble_ll_conn_sm_new(connsm);
 
-    /* The connection has been created. */
-    ble_ll_conn_created(connsm, conn_req_end);
-    return 1;
+    /* Set initial schedule callback */
+    connsm->conn_sch.sched_cb = ble_ll_conn_event_start_cb;
+
+    rc = ble_ll_conn_created(connsm, conn_req_end);
+    if (!rc) {
+        SLIST_REMOVE(&g_ble_ll_conn_active_list, connsm, ble_ll_conn_sm, act_sle);
+        STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
+    }
+    return rc;
 
 err_slave_start:
     STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
@@ -2109,7 +2245,9 @@ err_slave_start:
 }
 
 /**
- * Called to reset the connection module.
+ * Called to reset the connection module. When this function is called the 
+ * scheduler has been stopped and the phy has been disabled. The LL should 
+ * be in the standby state. 
  *  
  * Context: Link Layer task 
  */
@@ -2121,7 +2259,7 @@ ble_ll_conn_reset(void)
     /* Kill the current one first (if one is running) */
     if (g_ble_ll_conn_cur_sm) {
         connsm = g_ble_ll_conn_cur_sm;
-        ble_ll_conn_current_sm_over();
+        g_ble_ll_conn_cur_sm = NULL;
         ble_ll_conn_end(connsm, BLE_ERR_SUCCESS);
     }
 
@@ -2155,7 +2293,7 @@ ble_ll_conn_module_init(void)
      * the specification allows a handle of zero; we just avoid using it.
      */
     connsm = &g_ble_ll_conn_sm[0];
-    for (i = 0; i < BLE_LL_CONN_CFG_MAX_CONNS; ++i) {
+    for (i = 0; i < BLE_LL_CFG_CONN_MAX_CONNS; ++i) {
         connsm->conn_handle = i + 1;
         STAILQ_INSERT_TAIL(&g_ble_ll_conn_free_list, connsm, free_stqe);
 
@@ -2170,6 +2308,9 @@ ble_ll_conn_module_init(void)
 
         ble_ll_mbuf_init(m, 0, BLE_LL_LLID_DATA_FRAG);
 
+        /* Initialize fixed schedule elements */
+        connsm->conn_sch.sched_type = BLE_LL_SCHED_TYPE_CONN;
+        connsm->conn_sch.cb_arg = connsm;
         ++connsm;
     }
 
@@ -2187,3 +2328,4 @@ ble_ll_conn_module_init(void)
     conn_params->conn_init_max_tx_time = BLE_TX_DUR_USECS_M(maxbytes);
     conn_params->conn_init_max_tx_octets = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES;
 }
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 a4ac46c..a051318 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -358,7 +358,7 @@ ble_ll_conn_create(uint8_t *cmdbuf)
 
     /* Initialize state machine in master role and start state machine */
     ble_ll_conn_master_init(connsm, hcc);
-    ble_ll_conn_sm_start(connsm);
+    ble_ll_conn_sm_new(connsm);
 
     /* Create the connection request */
     ble_ll_conn_req_pdu_make(connsm);
@@ -400,7 +400,7 @@ ble_ll_conn_create_cancel(void)
     if (connsm && (connsm->conn_state == BLE_LL_CONN_STATE_IDLE)) {
         /* stop scanning and end the connection event */
         g_ble_ll_conn_create_sm = NULL;
-        ble_ll_scan_sm_stop(ble_ll_scan_sm_get(), 0);
+        ble_ll_scan_sm_stop(1);
         ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
         rc = BLE_ERR_SUCCESS;
     } else {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/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 48304b2..47015a3 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -32,6 +32,7 @@
 #define BLE_LL_CONN_SUPP_BYTES_MAX          (251)   /* bytes */
 
 /* Connection event timing */
+#define BLE_LL_CONN_INITIAL_OFFSET          (1250)
 #define BLE_LL_CONN_ITVL_USECS              (1250)
 #define BLE_LL_CONN_TX_WIN_USECS            (1250)
 #define BLE_LL_CONN_CE_USECS                (625)
@@ -60,7 +61,7 @@ extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
 struct ble_ll_len_req;
 struct hci_create_conn;
 struct ble_mbuf_hdr;
-void ble_ll_conn_sm_start(struct ble_ll_conn_sm *connsm);
+void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm);
 void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
 void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
                              uint8_t hdr_byte, uint8_t length);
@@ -80,12 +81,15 @@ void ble_ll_conn_reset(void);
 void ble_ll_conn_event_end(void *arg);
 void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
 void ble_ll_conn_spvn_timeout(void *arg);
-void ble_ll_conn_rx_pdu_start(void);
-int ble_ll_conn_rx_pdu_end(struct os_mbuf *rxpdu, uint32_t aa);
-void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, uint8_t crcok);
+void ble_ll_conn_rx_isr_start(void);
+int ble_ll_conn_rx_isr_end(struct os_mbuf *rxpdu, uint32_t aa);
+void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
 void ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr);
-int ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu);
+int ble_ll_init_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);
 void ble_ll_conn_wfr_timer_exp(void);
+int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2);
+uint32_t ble_ll_conn_get_ce_end_time(void);
+void ble_ll_conn_event_halt(void);
 
 /* HCI */
 void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm, 
@@ -96,5 +100,7 @@ int ble_ll_conn_create(uint8_t *cmdbuf);
 int ble_ll_conn_create_cancel(void);
 void ble_ll_conn_num_comp_pkts_event_send(void);
 void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status);
+void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
+
 
 #endif /* H_BLE_LL_CONN_PRIV_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/b6e2b5ff/net/nimble/controller/src/ble_ll_ctrl.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_ctrl.c b/net/nimble/controller/src/ble_ll_ctrl.c
index 2a06265..0e5df2d 100644
--- a/net/nimble/controller/src/ble_ll_ctrl.c
+++ b/net/nimble/controller/src/ble_ll_ctrl.c
@@ -197,7 +197,7 @@ void
 ble_ll_ctrl_proc_rsp_timer_cb(void *arg)
 {
     /* Control procedure has timed out. Kill the connection */
-    ble_ll_conn_end((struct ble_ll_conn_sm *)arg, BLE_ERR_LMP_LL_RSP_TMO);
+    ble_ll_conn_timeout((struct ble_ll_conn_sm *)arg, BLE_ERR_LMP_LL_RSP_TMO);
 }
 
 /**