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/19 20:33:24 UTC

[1/3] incubator-mynewt-larva git commit: Additional connection code: supervision timeout, connection scheduling, start/end event processing

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master 9504907f2 -> c9d16694d


Additional connection code: supervision timeout, connection scheduling, start/end event processing


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

Branch: refs/heads/master
Commit: 47dff3ec49a857efa192706c8175eacdb0073c5c
Parents: c7cc3d0
Author: wes3 <wi...@micosa.io>
Authored: Thu Nov 19 11:30:58 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Thu Nov 19 11:31:04 2015 -0800

----------------------------------------------------------------------
 libs/os/include/os/os_mbuf.h                    |   6 +-
 .../controller/include/controller/ble_ll.h      |  74 +-
 .../controller/include/controller/ble_ll_conn.h |   7 +-
 .../include/controller/ble_ll_sched.h           |   3 +-
 .../controller/include/controller/ble_phy.h     |   2 +-
 net/nimble/controller/src/ble_ll.c              | 127 +--
 net/nimble/controller/src/ble_ll_adv.c          |   5 +-
 net/nimble/controller/src/ble_ll_conn.c         | 926 ++++++++++++++++---
 net/nimble/controller/src/ble_ll_scan.c         |  17 +-
 net/nimble/controller/src/ble_ll_sched.c        |  15 +-
 net/nimble/controller/src/ble_ll_whitelist.c    |   1 -
 net/nimble/drivers/native/src/ble_phy.c         |   4 +-
 net/nimble/drivers/nrf52/src/ble_phy.c          |  34 +-
 net/nimble/host/src/host_hci_cmd.c              |   2 +-
 net/nimble/include/nimble/ble.h                 |   6 +-
 project/bletest/src/main.c                      |  82 +-
 16 files changed, 996 insertions(+), 315 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/libs/os/include/os/os_mbuf.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_mbuf.h b/libs/os/include/os/os_mbuf.h
index 8edbe89..a4d4075 100644
--- a/libs/os/include/os/os_mbuf.h
+++ b/libs/os/include/os/os_mbuf.h
@@ -111,10 +111,14 @@ struct os_mbuf {
 #define OS_MBUF_IS_PKTHDR(__om) \
     ((__om)->om_flags & OS_MBUF_F_MASK(OS_MBUF_F_PKTHDR))
 
-
+/* Get a packet header pointer given an mbuf pointer */
 #define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)     \
     ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
 
+/* Given a mbuf packet header pointer, return a pointer to the mbuf */
+#define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
+     (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
+
 /*
  * Access the data of a mbuf, and cast it to type
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 317cb2c..91ff4cf 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -17,33 +17,28 @@
 #ifndef H_BLE_LL_
 #define H_BLE_LL_
 
-/* XXX: Not sure this should go here, but whatever */
 /* 
- * ble ll global parameters
- * 
- * NOTES:
- *  1) Controller should not change value of supported max tx and rx time and
- *  octets.
+ * Global Link Layer data object. There is only one Link Layer data object
+ * per controller although there may be many instances of the link layer state
+ * machine running.
  */
-struct ble_ll_global_params
-{
-    int conn_init_max_tx_octets;
-    int conn_init_max_tx_time;
-    int supp_max_tx_octets;
-    int supp_max_tx_time;
-    int supp_max_rx_octets;
-    int supp_max_rx_time;
-};
-
 struct ble_ll_obj
 {
+    /* Current Link Layer state */
     uint8_t ll_state;
+
+    /* Task event queue */
     struct os_eventq ll_evq;
-    struct ble_ll_global_params ll_params;
+
+    /* Receive packet (from phy) event */
     struct os_event ll_rx_pkt_ev;
+
+    /* Packet receive queue */
     STAILQ_HEAD(ll_rxpkt_qh, os_mbuf_pkthdr) ll_rx_pkt_q;
 };
+extern struct ble_ll_obj g_ble_ll_data;
 
+/* Link layer statistics */
 struct ble_ll_stats
 {
     uint32_t rx_crc_ok;
@@ -61,10 +56,9 @@ struct ble_ll_stats
     uint32_t hci_cmds;
     uint32_t hci_cmd_errs;
     uint32_t hci_events_sent;
+    uint32_t bad_ll_state;
 };
-
 extern struct ble_ll_stats g_ble_ll_stats;
-extern struct ble_ll_obj g_ble_ll_data;
 
 /* States */
 #define BLE_LL_STATE_STANDBY        (0)
@@ -78,6 +72,8 @@ extern struct ble_ll_obj g_ble_ll_data;
 #define BLE_LL_EVENT_ADV_TXDONE     (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_CONN_SPVN_TMO  (OS_EVENT_T_PERUSER + 4)
+#define BLE_LL_EVENT_CONN_EV_END    (OS_EVENT_T_PERUSER + 5)
 
 /* LL Features */
 #define BLE_LL_FEAT_LE_ENCRYPTION   (0x01)
@@ -162,7 +158,7 @@ struct ble_dev_addr
 /*
  * Data Channel format
  * 
- *  -> Header (2 bytes.
+ *  -> Header (2 bytes)
  *      -> LSB contains llid, nesn, sn and md
  *      -> MSB contains length (8 bits)
  *  -> Payload (0 to 251)
@@ -173,6 +169,7 @@ struct ble_dev_addr
 #define BLE_LL_DATA_HDR_SN_MASK         (0x08)
 #define BLE_LL_DATA_HDR_MD_MASK         (0x10)
 #define BLE_LL_DATA_HDR_RSRVD_MASK      (0xE0)
+#define BLE_LL_DATA_MAX_OVERHEAD        (6)
 
 /* LLID definitions */
 #define BLE_LL_LLID_RSRVD               (0)
@@ -383,39 +380,8 @@ struct ble_ll_len_req
  *      hop_inc: Hop increment used for frequency hopping. Random value in
  *               range of 5 to 16.
  */
-#define BLE_CONNECT_REQ_LEN             (34)
-
-struct ble_conn_req_data
-{
-    uint32_t    aa;
-    uint8_t     crc_init[3];
-    uint8_t     winsize;
-    uint16_t    winoffset;
-    uint16_t    interval;
-    uint16_t    latency;
-    uint16_t    timeout;
-    uint8_t     chanmap[5];
-    uint8_t     hop_inc;
-    uint8_t     master_sca;
-};
-
-#define BLE_CONN_REQ_HOP_MASK           (0x1F)
-#define BLE_CONN_REQ_SCA_MASK           (0xE0)
-
-/*
- * Initiator filter policy 
- * 
- * Determines how the initiator's Link Layer processes advertisements.
- * 
- *  LIST: process connectable advertisements only from devices in white list.
- *  SINGLE: do not use white list; process connectable advertisements from
- *      a single specific device specified by the host.
- */
-enum ble_ll_init_filt_policy
-{
-    BLE_LL_INIT_FILT_LIST = 0,
-    BLE_LL_INIT_FILT_SINGLE,
-};
+#define BLE_CONNECT_REQ_LEN         (34)
+#define BLE_CONNECT_REQ_PDU_LEN     (BLE_CONNECT_REQ_LEN + BLE_LL_PDU_HDR_LEN)
 
 /*--- External API ---*/
 /* Initialize the Link Layer */
@@ -435,7 +401,7 @@ int ble_ll_is_our_devaddr(uint8_t *addr, int addr_type);
 
 /*--- PHY interfaces ---*/
 /* Called by the PHY when a packet has started */
-int ble_ll_rx_start(struct os_mbuf *rxpdu);
+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 crcok);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 ff62ff6..4c3d535 100644
--- a/net/nimble/controller/include/controller/ble_ll_conn.h
+++ b/net/nimble/controller/include/controller/ble_ll_conn.h
@@ -31,9 +31,12 @@ 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);
+void ble_ll_init_rx_pdu_proc(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_pdu_start(uint8_t pdu_type);
 void ble_ll_conn_slave_start(uint8_t *rxbuf);
+void ble_ll_conn_spvn_timeout(void *arg);
+void ble_ll_conn_event_end(void *arg);
+void ble_ll_conn_init(void);
+void ble_ll_conn_rsp_rxd(void);
 
 #endif /* H_BLE_LL_CONN_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 eae0cc5..48914ae 100644
--- a/net/nimble/controller/include/controller/ble_ll_sched.h
+++ b/net/nimble/controller/include/controller/ble_ll_sched.h
@@ -25,6 +25,7 @@
 #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)
 
 /* Return values for schedule callback. */
 #define BLE_LL_SCHED_STATE_RUNNING  (0)
@@ -49,7 +50,7 @@ struct ble_ll_sched_item
 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);
+int ble_ll_sched_rmv(uint8_t sched_type, void *cb_arg);
 
 /* Initialize the scheduler */
 int ble_ll_sched_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/controller/include/controller/ble_phy.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_phy.h b/net/nimble/controller/include/controller/ble_phy.h
index 0119b44..2a2103f 100644
--- a/net/nimble/controller/include/controller/ble_phy.h
+++ b/net/nimble/controller/include/controller/ble_phy.h
@@ -82,7 +82,7 @@ int ble_phy_init(void);
 int ble_phy_reset(void);
 
 /* Set the PHY channel */
-int ble_phy_setchan(uint8_t chan);
+int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit);
 
 /* Place the PHY into transmit mode */
 int ble_phy_tx(struct os_mbuf *, uint8_t beg_trans, uint8_t end_trans);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 645fdde..691a057 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -33,7 +33,17 @@
  * 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. */
+ * additional whitelist checks at the upper layer.
+ */
+
+/* 
+ * 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:
  * 
@@ -44,10 +54,6 @@
  * 
  */
 
-/* Connection related define */
-#define BLE_LL_CONN_INIT_MAX_REMOTE_OCTETS  (27)
-#define BLE_LL_CONN_INIT_MAX_REMOTE_TIME    (238)
-
 /* The global BLE LL data object */
 struct ble_ll_obj g_ble_ll_data;
 
@@ -60,47 +66,11 @@ struct ble_ll_stats g_ble_ll_stats;
 struct os_task g_ble_ll_task;
 os_stack_t g_ble_ll_stack[BLE_LL_STACK_SIZE];
 
-/* XXX: this is just temporary; used to calculate the channel index */
-struct ble_ll_sm_connection
-{
-    /* Flow control */
-    uint8_t tx_seq;
-    uint8_t next_exp_seq;
-
-    /* Parameters kept by the link-layer per connection */
-    uint8_t max_tx_octets;
-    uint8_t max_rx_octets;
-    uint8_t max_tx_time;
-    uint8_t max_rx_time;
-    uint8_t remote_max_tx_octets;
-    uint8_t remote_max_rx_octets;
-    uint8_t remote_max_tx_time;
-    uint8_t remote_max_rx_time;
-    uint8_t effective_max_tx_octets;
-    uint8_t effective_max_rx_octets;
-    uint8_t effective_max_tx_time;
-    uint8_t effective_max_rx_time;
-
-    /* The connection request data */
-    struct ble_conn_req_data req_data; 
-};
-
-/* Called when a connection gets initialized */
-int
-ble_init_conn_sm(struct ble_ll_sm_connection *cnxn)
-{
-    cnxn->max_tx_time = g_ble_ll_data.ll_params.conn_init_max_tx_time;
-    cnxn->max_rx_time = g_ble_ll_data.ll_params.supp_max_rx_time;
-    cnxn->max_tx_octets = g_ble_ll_data.ll_params.conn_init_max_tx_octets;
-    cnxn->max_rx_octets = g_ble_ll_data.ll_params.supp_max_rx_octets;
-    cnxn->remote_max_rx_octets = BLE_LL_CONN_INIT_MAX_REMOTE_OCTETS;
-    cnxn->remote_max_tx_octets = BLE_LL_CONN_INIT_MAX_REMOTE_OCTETS;
-    cnxn->remote_max_rx_time = BLE_LL_CONN_INIT_MAX_REMOTE_TIME;
-    cnxn->remote_max_tx_time = BLE_LL_CONN_INIT_MAX_REMOTE_TIME;
-
-    return 0;
-}
-
+/**
+ * Counts received packets by type 
+ * 
+ * @param pdu_type 
+ */
 static void
 ble_ll_count_rx_pkts(uint8_t pdu_type)
 {
@@ -134,6 +104,8 @@ ble_ll_count_rx_pkts(uint8_t pdu_type)
         ++g_ble_ll_stats.rx_unk_pdu;
         break;
     }
+
+    /* XXX: what about data packets? */
 }
 
 int
@@ -330,7 +302,7 @@ ble_ll_rx_pkt_in_proc(void)
             }
             break;
         case BLE_LL_STATE_INITIATING:
-            ble_ll_init_rx_pdu_proc(pdu_type, rxbuf, ble_hdr->crcok);
+            ble_ll_init_rx_pdu_proc(rxbuf, ble_hdr);
             break;
         case BLE_LL_STATE_CONNECTION:
             /* XXX: implement */
@@ -341,7 +313,7 @@ ble_ll_rx_pkt_in_proc(void)
             break;
         }
 
-        /* XXX: Free the mbuf for now */
+        /* Free the packet buffer */
         os_mbuf_free(&g_mbuf_pool, m);
     }
 }
@@ -365,14 +337,15 @@ ble_ll_rx_pdu_in(struct os_mbuf *rxpdu)
  * Called upon start of received PDU 
  * 
  * @param rxpdu 
+ *        chan 
  * 
  * @return int 
  *   < 0: A frame we dont want to receive.
  *   = 0: Continue to receive frame. Dont go from rx to tx
- *   > 1: Continue to receive frame and go from rx to idle when done
+ *   > 0: Continue to receive frame and go from rx to tx when done
  */
 int
-ble_ll_rx_start(struct os_mbuf *rxpdu)
+ble_ll_rx_start(struct os_mbuf *rxpdu, uint8_t chan)
 {
     int rc;
     uint8_t pdu_type;
@@ -380,6 +353,26 @@ ble_ll_rx_start(struct os_mbuf *rxpdu)
 
     /* XXX: need to check if this is an adv channel or data channel */
     rxbuf = rxpdu->om_data;
+    if (chan < BLE_PHY_NUM_DATA_CHANS) {
+        /* 
+         * Data channel pdu. We should be in CONNECTION state with an
+         * ongoing connection
+         */
+        /* XXX: check access address for surety? What to do... */
+        if (g_ble_ll_data.ll_state == BLE_LL_STATE_CONNECTION) {
+            /* Set flag in connection noting we have received a response */
+            ble_ll_conn_rsp_rxd();
+
+            /* Set up to go from rx to tx */
+            rc = 1;
+        } else {
+            ++g_ble_ll_stats.bad_ll_state;
+            rc = 0;
+        }
+        return rc;
+    } 
+
+    /* Advertising channel PDU */
     pdu_type = rxbuf[0] & BLE_ADV_PDU_HDR_TYPE_MASK;
 
     switch (g_ble_ll_data.ll_state) {
@@ -395,16 +388,24 @@ ble_ll_rx_start(struct os_mbuf *rxpdu)
         }
         break;
     case BLE_LL_STATE_INITIATING:
-        rc = ble_ll_init_rx_pdu_start(pdu_type);
+        if ((pdu_type == BLE_ADV_PDU_TYPE_ADV_IND) ||
+            (pdu_type == BLE_ADV_PDU_TYPE_ADV_DIRECT_IND)) {
+            rc = 1;
+        } else {
+            rc = 0;
+        }
         break;
     case BLE_LL_STATE_SCANNING:
         rc = ble_ll_scan_rx_pdu_start(pdu_type, rxpdu);
         break;
     case BLE_LL_STATE_CONNECTION:
+        /* XXX: This should not happen. What to do? */
+        rc = 0;
+        break;
     default:
-        /* XXX: should we really assert here? What to do... */
+        /* Should not be in this state */
         rc = -1;
-        assert(0);
+        ++g_ble_ll_stats.bad_ll_state;
         break;
     }
 
@@ -543,6 +544,12 @@ ble_ll_task(void *arg)
         case BLE_LL_EVENT_RX_PKT_IN:
             ble_ll_rx_pkt_in_proc();
             break;
+        case BLE_LL_EVENT_CONN_SPVN_TMO:
+            ble_ll_conn_spvn_timeout(ev->ev_arg);
+            break;
+        case BLE_LL_EVENT_CONN_EV_END:
+            ble_ll_conn_event_end(ev->ev_arg);
+            break;
         default:
             assert(0);
             break;
@@ -589,14 +596,19 @@ ble_ll_event_send(struct os_event *ev)
 int
 ble_ll_init(void)
 {
+    struct ble_ll_obj *lldata;
+
+    /* Get pointer to global data object */
+    lldata = &g_ble_ll_data;
+
     /* Initialize the receive queue */
-    STAILQ_INIT(&g_ble_ll_data.ll_rx_pkt_q);
+    STAILQ_INIT(&lldata->ll_rx_pkt_q);
 
     /* Initialize eventq */
-    os_eventq_init(&g_ble_ll_data.ll_evq);
+    os_eventq_init(&lldata->ll_evq);
 
     /* Initialize receive packet (from phy) event */
-    g_ble_ll_data.ll_rx_pkt_ev.ev_type = BLE_LL_EVENT_RX_PKT_IN;
+    lldata->ll_rx_pkt_ev.ev_type = BLE_LL_EVENT_RX_PKT_IN;
 
     /* Initialize LL HCI */
     ble_ll_hci_init();
@@ -610,6 +622,9 @@ ble_ll_init(void)
     /* Initialize a scanner */
     ble_ll_scan_init();
 
+    /* Initialize the connection module */
+    ble_ll_conn_init();
+
     /* Initialize the LL task */
     os_task_init(&g_ble_ll_task, "ble_ll", ble_ll_task, NULL, BLE_LL_TASK_PRI, 
                  OS_WAIT_FOREVER, g_ble_ll_stack, BLE_LL_STACK_SIZE);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 67acf8f..08eee0e 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -65,6 +65,7 @@
  * 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.
+ * 13) Implement high duty cycle advertising timeout.
  */
 
 /* 
@@ -381,7 +382,7 @@ ble_ll_adv_tx_start_cb(struct ble_ll_sched_item *sch)
     gpio_toggle(LED_BLINK_PIN);
 
     /* Set channel */
-    rc = ble_phy_setchan(advsm->adv_chan);
+    rc = ble_phy_setchan(advsm->adv_chan, 0, 0);
     assert(rc == 0);
 
     /* Set phy mode based on type of advertisement */
@@ -575,7 +576,7 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
     ble_ll_whitelist_disable();
 
     /* Remove any scheduled advertising items */
-    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_ADV);
+    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_ADV, NULL);
 
     /* Disable advertising */
     advsm->enabled = 0;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 58b2097..474af09 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -26,10 +26,13 @@
 #include "controller/ble_ll_conn.h"
 #include "controller/ble_ll_scan.h"
 #include "controller/ble_ll_whitelist.h"
+#include "controller/ble_ll_sched.h"
 #include "controller/ble_phy.h"
+#include "hal/hal_cputime.h"
 
 /* XXX TODO
  * 1) Implemement connection supervisor timeout.
+ *  -> Need to re-start when we receive a packet and set the proper timeout.
  * 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
@@ -37,79 +40,187 @@
  * 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.
+ * 8) Set up later connection schedule events.
+ * 8.5) How do we set the end event? Especially if we are receiving? Need
+ * to figure this out.
  * 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.
+ * 12) Data channel index and all that code. Must make sure we are setting this
+ * correctly. Set for 1st connection event but not for other events.
+ * 13) Add more statistics
+ * 14) Update event counter with each event!
+ * 15) Link layer control procedures and timers
+ * 16) Did we implement what happens if we receive a connection request from
+ * a device we are already connected to? We also need to check to see if we
+ * were asked to create a connection when one already exists. Note that
+ * an initiator should only send connection requests to devices it is not
+ * already connected to. Make sure this cant happen.
+ * 17) Dont forget to set pkt_rxd flag for slave latency. Needs to get reset
+ * after each M-S transaction.
+ * 18) Make sure we check incoming data packets for size and all that. You
+ * know, supported octets and all that. For both rx and tx.
+ * 19) Make sure we handle rsp_rxd and pkt_rxd correctly (clearing/checking
+ * setting them).
  */
 
-/* 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
- */
+/* Connection event timing */
+#define BLE_LL_CONN_ITVL_USECS              (1250)
+#define BLE_LL_CONN_TX_WIN_USECS            (1250)
+#define BLE_LL_CONN_CE_USECS                (625)
+
+/* XXX: probably should be moved and made more accurate */
+#define BLE_LL_WFR_USECS                    (100)
 
 /* Channel map size */
-#define BLE_LL_CONN_CHMAP_LEN           (5)
+#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)
+#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)
+
+/* LL configuration definitions */
+#define BLE_LL_CFG_SUPP_MAX_RX_BYTES        (27)
+#define BLE_LL_CFG_SUPP_MAX_TX_BYTES        (27)
+#define BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES   (27)
 
 /* Roles */
-#define BLE_LL_CONN_ROLE_NONE           (0)
-#define BLE_LL_CONN_ROLE_MASTER         (1)
-#define BLE_LL_CONN_ROLE_SLAVE          (2)
+#define BLE_LL_CONN_ROLE_NONE               (0)
+#define BLE_LL_CONN_ROLE_MASTER             (1)
+#define BLE_LL_CONN_ROLE_SLAVE              (2)
+
+/* Connection states */
+#define BLE_LL_CONN_STATE_IDLE              (0)
+#define BLE_LL_CONN_STATE_CREATED           (1)
+#define BLE_LL_CONN_STATE_ESTABLISHED       (2)
+
+/* Data Lenth Procedure */
+#define BLE_LL_CONN_SUPP_TIME_MIN           (328)   /* usecs */
+#define BLE_LL_CONN_SUPP_BYTES_MIN          (27)    /* bytes */
 
 /* Connection request */
-#define BLE_LL_CONN_REQ_ADVA_OFF        (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
+#define BLE_LL_CONN_REQ_ADVA_OFF    (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
+
+/* 
+ * XXX: I just had a thought. Why do I need to allocate connection handles?
+ * For every connection state machine I have I should just give it a handle
+ * inside it. They can sit on the pool and I can use them in round robin
+ * order. This might save some code! This works only if I create the pool
+ * of connections to start.
+ */
+
+/* Global Link Layer connection parameters */
+struct ble_ll_conn_global_params
+{
+    uint8_t supp_max_tx_octets;
+    uint8_t supp_max_rx_octets;
+    uint8_t conn_init_max_tx_octets;
+    uint16_t conn_init_max_tx_time;
+    uint16_t supp_max_tx_time;
+    uint16_t supp_max_rx_time;
+};
 
-/* Scanning state machine */
+struct ble_ll_conn_global_params g_ble_ll_conn_params;
+
+/* Connection state machine */
 struct ble_ll_conn_sm
 {
+    /* Current connection state and role */
+    uint8_t conn_state;
+    uint8_t conn_role;
+
+    /* Connection data length management */
+    uint8_t max_tx_octets;
+    uint8_t max_rx_octets;
+    uint8_t rem_max_tx_octets;
+    uint8_t rem_max_rx_octets;
+    uint8_t eff_max_tx_octets;
+    uint8_t eff_max_rx_octets;
+    uint16_t max_tx_time;
+    uint16_t max_rx_time;
+    uint16_t rem_max_tx_time;
+    uint16_t rem_max_rx_time;
+    uint16_t eff_max_tx_time;
+    uint16_t eff_max_rx_time;
+
     /* Used to calculate data channel index for connection */
+    uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
+    uint8_t hop_inc;
+    uint8_t data_chan_index;
     uint8_t unmapped_chan;
     uint8_t last_unmapped_chan;
     uint8_t num_used_chans;
-    uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
-    uint8_t hop_inc;
-    uint8_t conn_state;
-    uint8_t conn_role;
+
+    /* connection event timing/mgmt */
+    uint8_t rsp_rxd;
+    uint8_t pkt_rxd;
     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;
+    uint8_t tx_win_size;
     uint16_t conn_itvl;
-    uint16_t conn_slave_latency;
-    uint16_t conn_event_cntr;
+    uint16_t slave_latency;
+    uint16_t tx_win_off;
+    uint16_t min_ce_len;
+    uint16_t max_ce_len;
+    uint16_t event_cntr;
+    uint16_t supervision_tmo;
     uint16_t conn_handle;
-    uint16_t conn_tx_win_off;
     uint32_t access_addr;
     uint32_t crcinit;       /* only low 24 bits used */
+    uint32_t anchor_point;
+
+    /* address information */
+    uint8_t own_addr_type;
+    uint8_t peer_addr_type;
+    uint8_t peer_addr[BLE_DEV_ADDR_LEN];
+
+    /* connection supervisor timer */
+    struct cpu_timer conn_spvn_timer;
+
+    /* connection supervision timeout event */
+    struct os_event conn_spvn_ev;
+
+    /* Connection end event */
+    struct os_event conn_ev_end;
+
+    /* Packet transmit queue */
+    STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq;
 };
 
-struct ble_ll_conn_sm g_ble_ll_conn_sm;
+/* Pointer to connection state machine we are trying to create */
+struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
 
-/* Connection states */
-#define BLE_LL_CONN_STATE_IDLE          (0)
-#define BLE_LL_CONN_STATE_CREATED       (1)
-#define BLE_LL_CONN_STATE_ESTABLISHED   (2)
+/* Pointer to current connection */
+struct ble_ll_conn_sm *g_ble_ll_conn_cur_sm;
 
 /* 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;
 
+/* Connection pool elements */
 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))];
 
+/* List of active connections */
+static SLIST_HEAD(, ble_hs_conn) g_ble_ll_conn_active_list;
+
+/* Statistics */
+struct ble_ll_conn_stats
+{
+    uint32_t cant_set_sched;
+    uint32_t conn_ev_late;
+    uint32_t wfr_expirations;
+};
+struct ble_ll_conn_stats g_ble_ll_conn_stats;
+
+/* "Dummy" mbuf containing an "Empty PDU" */
+#define BLE_LL_DUMMY_EMPTY_PDU_SIZE     \
+    ((sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr) + 4) / 4)
+
+static uint32_t g_ble_ll_empty_pdu[BLE_LL_DUMMY_EMPTY_PDU_SIZE];
+
 /**
  * Calculates the number of used channels in the channel map 
  * 
@@ -146,15 +257,45 @@ ble_ll_conn_calc_used_chans(uint8_t *chmap)
     return used_channels;
 }
 
+/**
+ * Free an allocated connection handle 
+ * 
+ * @param handle The connection handle to free.
+ */
+static void
+ble_ll_conn_handle_free(uint16_t handle)
+{
+    uint8_t bytepos;
+    uint8_t mask;
 
+    /* Make sure handle is valid */
+    assert(handle < BLE_LL_CONN_CFG_MAX_CONNS);
+    assert(g_ble_ll_conn_handles_out != 0);
+
+    /* Get byte position and bit position */
+    bytepos = handle / 8;
+    mask = 1 << (handle & 0x7);
+
+    assert((g_ble_ll_conn_handles[bytepos] & mask) != 0);
+
+    g_ble_ll_conn_handles[bytepos] &= ~mask;
+    --g_ble_ll_conn_handles_out;
+}
+
+/**
+ * Allocate a connection handle. This will allocate an unused connection 
+ * handle. 
+ * 
+ * @return uint16_t 
+ */
 static uint16_t
-ble_ll_conn_get_unused_handle(void)
+ble_ll_conn_handle_alloc(void)
 {
     uint8_t bytepos;
     uint8_t bitpos;
     int handle;
 
-    /* Keep track of total number so you can deny it! */
+    /* Make sure there is a handle that exists */
     if (g_ble_ll_conn_handles_out == BLE_LL_CONN_CFG_MAX_CONNS) {
         /* Handles can only be in range 0 to 0x0EFF */
         return 0xFFFF;
@@ -267,14 +408,15 @@ ble_ll_conn_calc_access_addr(void)
 }
 
 /**
- * Determine the next data channel to be used for the connection. 
+ * Determine data channel index to be used for the upcoming/current 
+ * connection event 
  * 
  * @param conn 
  * 
  * @return uint8_t 
  */
 uint8_t
-ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
+ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn)
 {
     int     i;
     int     j;
@@ -285,9 +427,11 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
     uint8_t mask;
     uint8_t usable_chans;
 
-    /* Get next un mapped channel */
-    curchan = (conn->last_unmapped_chan + conn->hop_inc) % 
-               BLE_PHY_NUM_DATA_CHANS;
+    /* Get next unmapped channel */
+    curchan = conn->last_unmapped_chan + conn->hop_inc;
+    if (curchan > BLE_PHY_NUM_DATA_CHANS) {
+        curchan -= BLE_PHY_NUM_DATA_CHANS;
+    }
 
     /* Set the current unmapped channel */
     conn->unmapped_chan = curchan;
@@ -324,6 +468,287 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
 }
 
 /**
+ * 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)
+{
+    int rc;
+    struct ble_ll_conn_sm *connsm;
+
+    connsm = (struct ble_ll_conn_sm *)sch->cb_arg;
+    ble_ll_event_send(&connsm->conn_ev_end);
+    rc = BLE_LL_SCHED_STATE_DONE;
+    return rc;
+}
+
+/**
+ * Callback for connection wait for response timer. 
+ *  
+ * Context: Interrupt 
+ *
+ * @param sch 
+ * 
+ * @return int 
+ */
+static int
+ble_ll_conn_wfr_sched_cb(struct ble_ll_sched_item *sch)
+{
+    int rc;
+    struct ble_ll_conn_sm *connsm;
+
+    connsm = (struct ble_ll_conn_sm *)sch->cb_arg;
+    if (connsm->rsp_rxd) {
+        /* For now just set to end time */
+        sch->next_wakeup = sch->end_time;
+        sch->sched_cb = ble_ll_conn_ev_end_sched_cb;
+        rc = BLE_LL_SCHED_STATE_RUNNING;
+    } else {
+        ble_ll_event_send(&connsm->conn_ev_end);
+        rc = BLE_LL_SCHED_STATE_DONE;
+        ++g_ble_ll_conn_stats.wfr_expirations;
+    }
+    return rc;
+}
+
+/**
+ * Schedule callback for start of connection event 
+ *  
+ * Context: Interrupt 
+ * 
+ * @param sch 
+ * 
+ * @return int 
+ */
+static int
+ble_ll_conn_event_start_cb(struct ble_ll_sched_item *sch)
+{
+    int rc;
+    struct os_mbuf *m;
+    struct os_mbuf_pkthdr *pkthdr;
+    struct ble_ll_conn_sm *connsm;
+
+    /* Set current connection state machine */
+    connsm = (struct ble_ll_conn_sm *)sch->cb_arg;
+    g_ble_ll_conn_cur_sm = connsm;
+
+    /* Set LL state */
+    ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+
+    /* Set channel */
+    rc = ble_phy_setchan(connsm->data_chan_index, connsm->access_addr, 
+                         connsm->crcinit);
+    assert(rc == 0);
+
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+        /* Get packet off transmit queue. If none there, what to do? */
+        pkthdr = STAILQ_FIRST(&connsm->conn_txq);
+        if (pkthdr) {
+            /* Remove from queue */
+            m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
+            STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next);
+        } else {
+            /* Send empty pdu */
+            m = (struct os_mbuf *)&g_ble_ll_empty_pdu;
+        }
+
+        /* WWW: must modify the header */
+
+        rc = ble_phy_tx(m, BLE_PHY_TRANSITION_NONE, BLE_PHY_TRANSITION_RX_TX);
+        if (!rc) {
+            /* Set next schedule wakeup to check for wait for response */
+            sch->next_wakeup = cputime_get32() + 
+                cputime_usecs_to_ticks(XCVR_TX_START_DELAY_USECS +
+                                       ble_ll_pdu_tx_time_get(m->om_len) +
+                                       BLE_LL_IFS +
+                                       BLE_LL_WFR_USECS);
+            sch->sched_cb = ble_ll_conn_wfr_sched_cb;
+            rc = BLE_LL_SCHED_STATE_RUNNING;
+        } else {
+            /* Error transmitting! Put back on transmit queue */
+            STAILQ_INSERT_HEAD(&connsm->conn_txq, pkthdr, omp_next);
+
+            /* Inform LL task of connection event end */
+            ble_ll_event_send(&connsm->conn_ev_end);
+            rc = BLE_LL_SCHED_STATE_DONE;
+
+            /* XXX: Is there anything else we need to do on failure? */
+        }
+    } else {
+        rc = ble_phy_rx();
+        if (rc) {
+            /* XXX: what happens if this fails? */
+        }
+    }
+
+    /* XXX: set state to connection here? */
+
+    /* XXX: make sure we set the end time of the event (if needed) not sure
+     * it is for master role. Have to think about it.
+     */
+
+    /* XXX: The return code here tells the scheduler whether
+     * to use the next wakeup time or determines if the scheduled event is
+       over. */
+    return rc;
+}
+
+/**
+ * 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 {
+            /* XXX: account for window widening/drift */
+            sch->start_time = connsm->anchor_point - 
+                cputime_usecs_to_ticks(XCVR_RX_SCHED_DELAY_USECS);
+
+            /* XXX: what to do for slave? Not sure how much to schedule here.
+               For now, just schedule entire connection interval */
+            usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS;
+        }
+        sch->end_time = connsm->anchor_point + cputime_usecs_to_ticks(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);
+    } 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;
+}
+
+/* WWW:
+ *  -> deal with data channel index (calculation it).
+ *  -> deal with slave latency                      .
+ */
+
+/**
+ * Called upon end of connection event
+ *  
+ * Context: Link-layer task 
+ * 
+ * @param void *arg Pointer to connection state machine
+ * 
+ */
+void
+ble_ll_conn_event_end(void *arg)
+{
+    uint16_t latency;
+    uint32_t itvl;
+    struct ble_ll_conn_sm *connsm;
+
+    /* 
+     * XXX: if we received a response we can apply slave latency. I am not
+     * sure how this applies to the master. I guess the master could possibly 
+     * keep sending each anchor if it does not receive a reply. Possible that
+     * slave receives master but master does not get reply. This would cause
+     * master to re-transmit every connection event even though slave was
+     * asleep.
+     */
+    connsm = (struct ble_ll_conn_sm *)arg;
+
+    /* 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->pkt_rxd) {
+        latency += connsm->slave_latency;
+        itvl = itvl * latency;
+        connsm->pkt_rxd = 0;
+    }
+    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 */
+    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;
+    }
+
+    /* XXX: window widening for slave */
+
+    /* Link-layer is in standby state now */
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+
+    /* Set current LL connection to NULL */
+    g_ble_ll_conn_cur_sm = NULL;
+
+    /* Schedule the next connection event */
+    ble_ll_conn_sched_set(connsm);
+}
+
+/**
+ * Connection supervision timer callback; means that the connection supervision
+ * timeout has been reached and we should perform the appropriate actions. 
+ *  
+ * Context: Interrupt (cputimer)
+ * 
+ * @param arg Pointer to connection state machine.
+ */
+void
+ble_ll_conn_spvn_timer_cb(void *arg)
+{
+    struct ble_ll_conn_sm *connsm;
+
+    /* 
+     * WWW: What should we do with the PHY here? We could be transmitting or
+     * receiving. Need to figure out what to do.
+     */
+
+    connsm = (struct ble_ll_conn_sm *)arg;
+    ble_ll_event_send(&connsm->conn_spvn_ev);
+}
+
+/**
  * Initialize 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, 
@@ -333,26 +758,30 @@ ble_ll_next_data_channel(struct ble_ll_conn_sm *conn)
 static void
 ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
 {
+    struct ble_ll_conn_global_params *conn_params;
+
     /* 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();
+    connsm->event_cntr = 0;
+    connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
+
+    /* We better have an unused handle or we are in trouble! */
+    connsm->conn_handle = ble_ll_conn_handle_alloc();
+    assert(connsm->conn_handle < BLE_LL_CONN_CFG_MAX_CONNS);
 
     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->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;
 
         /* 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 slave latency and supervision timeout */
+        connsm->slave_latency = hcc->conn_latency;
+        connsm->supervision_tmo = hcc->supervision_timeout;
 
         /* Set own address type and peer address if needed */
         connsm->own_addr_type = hcc->own_addr_type;
@@ -361,11 +790,27 @@ ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
             connsm->peer_addr_type = hcc->peer_addr_type;
         }
 
-        /* XXX: what to do with min/max connection event length? */
+        /* XXX: for now, just make connection interval equal to max */
+        connsm->conn_itvl = hcc->conn_itvl_max;
 
-        /* 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;
+        /* Check the min/max CE lengths are less than connection interval */
+        if (hcc->min_ce_len > (connsm->conn_itvl * 2)) {
+            connsm->min_ce_len = connsm->conn_itvl * 2;
+        } else {
+            connsm->min_ce_len = hcc->min_ce_len;
+        }
+
+        if (hcc->max_ce_len > (connsm->conn_itvl * 2)) {
+            connsm->max_ce_len = connsm->conn_itvl * 2;
+        } else {
+            connsm->max_ce_len = hcc->max_ce_len;
+        }
+
+        /* 
+         * 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 = BLE_PHY_NUM_DATA_CHANS;
         memset(connsm->chanmap, 0xff, BLE_LL_CONN_CHMAP_LEN - 1);
         connsm->chanmap[4] = 0x1f;
 
@@ -375,6 +820,45 @@ ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
     } else {
         connsm->conn_role = BLE_LL_CONN_ROLE_SLAVE;
     }
+
+    /* Initialize connection supervision timer */
+    cputime_timer_init(&connsm->conn_spvn_timer, ble_ll_conn_spvn_timer_cb, 
+                       connsm);
+
+    /* Calculate the next data channel */
+    connsm->data_chan_index = ble_ll_conn_calc_dci(connsm);
+
+    /* Initialize event */
+    connsm->conn_spvn_ev.ev_arg = connsm;
+    connsm->conn_spvn_ev.ev_queued = 0;
+    connsm->conn_spvn_ev.ev_type = BLE_LL_EVENT_CONN_SPVN_TMO;
+
+    /* Connection end event */
+    connsm->conn_ev_end.ev_arg = connsm;
+    connsm->conn_ev_end.ev_queued = 0;
+    connsm->conn_ev_end.ev_type = BLE_LL_EVENT_CONN_EV_END;
+
+    /* Initialize transmit queue */
+    STAILQ_INIT(&connsm->conn_txq);
+
+    /* XXX: 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 */
+    /* initialize data length mgmt */
+    conn_params = &g_ble_ll_conn_params;
+    connsm->max_tx_octets = conn_params->conn_init_max_tx_octets;
+    connsm->max_rx_octets = conn_params->supp_max_rx_octets;
+    connsm->max_tx_time = conn_params->conn_init_max_tx_octets;
+    connsm->max_rx_time = conn_params->supp_max_rx_time;
+    connsm->rem_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN;
+    connsm->rem_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN;
+    connsm->eff_max_tx_time = BLE_LL_CONN_SUPP_TIME_MIN;
+    connsm->eff_max_rx_time = BLE_LL_CONN_SUPP_TIME_MIN;
+    connsm->rem_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
+    connsm->rem_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
+    connsm->eff_max_tx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
+    connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN;
+
+    /* XXX: Controller notifies host of changes to effective tx/rx time/bytes*/
 }
 
 /**
@@ -383,15 +867,13 @@ ble_ll_conn_sm_init(struct ble_ll_conn_sm *connsm, struct hci_create_conn *hcc)
  * @param status The BLE error code associated with the event
  */
 static void
-ble_ll_conn_comp_event_send(uint8_t status)
+ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, 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;
@@ -402,17 +884,123 @@ ble_ll_conn_comp_event_send(uint8_t status)
                 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);
+                htole16(evbuf + 16, connsm->slave_latency);
                 evbuf[18] = connsm->master_sca;
             }
 
-            /* XXX: what to do if we fail to send event? */
             ble_ll_hci_event_send(evbuf);
         }
     }
 }
 
 /**
+ * Called when a connection is terminated 
+ *  
+ * Context: Link Layer task. 
+ * 
+ * @param connsm 
+ * @param ble_err 
+ */
+static void
+ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
+{
+    struct os_mbuf *m;
+    struct os_mbuf_pkthdr *pkthdr;
+
+    /* XXX: stop any connection schedule timers we created */
+    /* XXX: make sure phy interrupts are off and all that. We want to
+     * make sure that if a scheduled event fires off here we dont care;
+     * we just need to clean up properly
+     */
+
+    /* Free all packets on transmit queue */
+    while (1) {
+        /* Get mbuf pointer from packet header pointer */
+        pkthdr = STAILQ_FIRST(&connsm->conn_txq);
+        if (!pkthdr) {
+            break;
+        }
+        STAILQ_REMOVE_HEAD(&connsm->conn_txq, omp_next);
+
+        m = (struct os_mbuf *)((uint8_t *)pkthdr - sizeof(struct os_mbuf));
+        os_mbuf_free(&g_mbuf_pool, m);
+    }
+
+    /* Remove scheduler events just in case */
+    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_CONN, connsm);
+
+    /* Make sure events off queue and connection supervison timer stopped */
+    cputime_timer_stop(&connsm->conn_spvn_timer);
+    os_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_spvn_ev);
+    os_eventq_remove(&g_ble_ll_data.ll_evq, &connsm->conn_ev_end);
+
+    /* Connection state machine is now idle */
+    connsm->conn_state = BLE_LL_CONN_STATE_IDLE;
+
+    /* Set Link Layer state to standby */
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
+
+    /* Send connection complete event */
+    ble_ll_conn_comp_event_send(connsm, ble_err);
+
+    /* Free up the handle */
+    ble_ll_conn_handle_free(connsm->conn_handle);
+
+    /* Free the connection state machine */
+    os_memblock_put(&g_ble_ll_conn_pool, connsm);
+}
+
+/**
+ * Called when a connection has been created. This function will 
+ *  -> Set the connection state to created.
+ *  -> Start the connection supervision timer
+ *  -> Set the Link Layer state to connection.
+ *  -> Send a connection complete event.
+ *  
+ *  See Section 4.5.2 Vol 6 Part B
+ *  
+ *  Context: Link Layer
+ * 
+ * @param connsm 
+ */
+static void
+ble_ll_conn_created(struct ble_ll_conn_sm *connsm)
+{
+    uint32_t usecs;
+
+    /* Set state to created */
+    connsm->conn_state = BLE_LL_CONN_STATE_CREATED;
+
+    /* Set supervision timeout */
+    usecs = connsm->conn_itvl * BLE_LL_CONN_ITVL_USECS * 6;
+    cputime_timer_relative(&connsm->conn_spvn_timer, usecs);
+
+    /* Clear packet received flag and response rcvd flag*/
+    connsm->rsp_rxd = 0;
+    connsm->pkt_rxd = 0;
+
+    /* XXX: get real end timing. By this I mean the real packet rx end time
+     * For now, we will just use time we got here as the start and hope we hit
+       the tx window */
+
+    /* Set first connection event time */
+    usecs = 1250 + (connsm->tx_win_off * BLE_LL_CONN_TX_WIN_USECS);
+    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+        usecs += ble_ll_pdu_tx_time_get(BLE_CONNECT_REQ_PDU_LEN) + BLE_LL_IFS;
+    } else {
+        /* XXX: need to deal with drift/window widening here */
+        usecs += 0;
+    }
+    connsm->anchor_point = cputime_get32() + cputime_usecs_to_ticks(usecs);
+
+    /* Send connection complete event to inform host of connection */
+    ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
+
+    /* Start the scheduler for the first connection event */
+    ble_ll_conn_sched_set(connsm);
+}
+
+/**
  * Update the connection request PDU with the address type and address of 
  * advertiser we are going to send connect request to. 
  * 
@@ -488,11 +1076,11 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
     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);
+    dptr[7] = connsm->tx_win_size;
+    htole16(dptr + 8, connsm->tx_win_off);
     htole16(dptr + 10, connsm->conn_itvl);
-    htole16(dptr + 12, connsm->conn_slave_latency);
-    htole16(dptr + 14, connsm->conn_spvn_tmo);
+    htole16(dptr + 12, connsm->slave_latency);
+    htole16(dptr + 14, connsm->supervision_tmo);
     memcpy(dptr + 16, &connsm->chanmap, BLE_LL_CONN_CHMAP_LEN);
     dptr[21] = connsm->hop_inc | connsm->master_sca;
 }
@@ -507,22 +1095,20 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
 int
 ble_ll_conn_create(uint8_t *cmdbuf)
 {
+    int rc;
     uint32_t spvn_tmo_msecs;
     uint32_t min_spvn_tmo_msecs;
     struct hci_create_conn ccdata;
     struct hci_create_conn *hcc;
     struct ble_ll_conn_sm *connsm;
 
-    /* XXX: what happens if we have too many! Do something about this */
+    /* If we are already creating a connection we should leave */
+    if (g_ble_ll_conn_create_sm) {
+        return BLE_ERR_CMD_DISALLOWED;
+    }
 
-    /* 
-     * 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)) {
+    if (ble_ll_scan_enabled()) {
         return BLE_ERR_CMD_DISALLOWED;
     }
 
@@ -591,12 +1177,19 @@ ble_ll_conn_create(uint8_t *cmdbuf)
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+    /* Min/max connection event lengths */
     hcc->min_ce_len = le16toh(cmdbuf + 21);
     hcc->max_ce_len = le16toh(cmdbuf + 23);
     if (hcc->min_ce_len > hcc->max_ce_len) {
         return BLE_ERR_INV_HCI_CMD_PARMS;
     }
 
+    /* Make sure we can accept a connection! */
+    connsm = (struct ble_ll_conn_sm *)os_memblock_get(&g_ble_ll_conn_pool);
+    if (connsm == NULL) {
+        return BLE_ERR_CONN_LIMIT;
+    }
+
     /* Initialize the connection sm */
     ble_ll_conn_sm_init(connsm, hcc);
 
@@ -604,7 +1197,15 @@ ble_ll_conn_create(uint8_t *cmdbuf)
     ble_ll_conn_req_pdu_make(connsm);
 
     /* Start scanning */
-    return ble_ll_scan_initiator_start(hcc);
+    rc = ble_ll_scan_initiator_start(hcc);
+    if (rc) {
+        os_memblock_put(&g_ble_ll_conn_pool, connsm);
+    } else {
+        /* Set the connection state machine we are trying to create. */
+        g_ble_ll_conn_create_sm = connsm;
+    }
+
+    return rc;
 }
 
 /**
@@ -619,23 +1220,23 @@ int
 ble_ll_conn_create_cancel(void)
 {
     int rc;
+    struct ble_ll_conn_sm *connsm;
 
     /* 
      * 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.
+     * what happens if the connection has already been established. We
+     * return disallowed as well
      */
-    if (ble_ll_scan_enabled()) {
-        /* stop scanning */
+    connsm = g_ble_ll_conn_create_sm;
+    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());
-
-        /* XXX: what to do with connection state machine? */
-
-        /* Send connection complete event */
-        ble_ll_conn_comp_event_send(BLE_ERR_UNK_CONN_ID);
+        ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
         rc = BLE_ERR_SUCCESS;
     } else {
-        /* If we have established connection or we are idle do not allow */
+        /* If we are not attempting to create a connection*/
         rc = BLE_ERR_CMD_DISALLOWED;
     }
 
@@ -649,11 +1250,12 @@ 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) &&
+    connsm = g_ble_ll_conn_create_sm;
+    if (connsm && (connsm->peer_addr_type == addr_type) &&
         !memcmp(adva, connsm->peer_addr, BLE_DEV_ADDR_LEN)) {
         rc = 1;
+    } else {
+        rc = 0;
     }
 
     return rc;
@@ -661,6 +1263,8 @@ ble_ll_conn_is_peer_adv(uint8_t addr_type, uint8_t *adva)
 
 /**
  * Send a connection requestion to an advertiser 
+ *  
+ * Context: Interrupt 
  * 
  * @param addr_type Address type of advertiser
  * @param adva Address of advertiser
@@ -670,18 +1274,10 @@ 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;
 }
 
@@ -694,30 +1290,42 @@ ble_ll_conn_request_send(uint8_t addr_type, uint8_t *adva)
  * @param rxbuf 
  */
 void
-ble_ll_init_rx_pdu_proc(uint8_t pdu_type, uint8_t *rxbuf, uint8_t crcok)
+ble_ll_init_rx_pdu_proc(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
 {
-    struct ble_ll_scan_sm *scansm;
+    uint8_t addr_type;
     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. */
+    /* Get the connection state machine we are trying to create */
+    connsm = g_ble_ll_conn_create_sm;
+    if (!connsm) {
+        return;
+    }
 
-    /* 
-     * 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);
+    /* If we have sent a connect request, we need to enter CONNECTION state*/
+    if (ble_hdr->crcok && (ble_hdr->flags & BLE_MBUF_HDR_F_CONN_REQ_TXD)) {
+        /* Set address of advertiser to which we are connecting. */
+        if (!ble_ll_scan_whitelist_enabled()) {
+            /* 
+             * XXX: need to see if the whitelist tells us exactly what peer
+             * addr type we should use? Not sure it matters. If whitelisting
+             * is not used the peer addr and type already set
+             */ 
+            /* Get address type of advertiser */
+            if (rxbuf[0] & BLE_ADV_PDU_HDR_TXADD_MASK) {
+                addr_type = BLE_ADDR_TYPE_RANDOM;
+            } else {
+                addr_type = BLE_ADDR_TYPE_PUBLIC;
+            }
 
-        /* We are now in connection state */
-        ble_ll_state_set(BLE_LL_STATE_CONNECTION);
+            connsm->peer_addr_type = addr_type;
+            memcpy(connsm->peer_addr, rxbuf + BLE_LL_PDU_HDR_LEN, 
+                   BLE_DEV_ADDR_LEN);
+        }
 
-        /* Send connection complete event */
-        ble_ll_conn_comp_event_send(BLE_ERR_SUCCESS);
+        /* Connection has been created. Stop scanning */
+        g_ble_ll_conn_create_sm = NULL;
+        ble_ll_scan_sm_stop(ble_ll_scan_sm_get());
+        ble_ll_conn_created(connsm);
     } else {
         /* We need to re-enable the PHY if we are in idle state */
         if (ble_phy_state_get() == BLE_PHY_STATE_IDLE) {
@@ -786,6 +1394,7 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
         }
 
         /* Check filter policy */
+        ble_hdr = BLE_MBUF_HDR_PTR(rxpdu);
         if (ble_ll_scan_whitelist_enabled()) {
             /* Check if device is on whitelist. If not, leave */
             if (!ble_ll_whitelist_match(adv_addr, addr_type)) {
@@ -793,7 +1402,6 @@ ble_ll_init_rx_pdu_end(struct os_mbuf *rxpdu)
             }
 
             /* 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 */
@@ -806,6 +1414,9 @@ 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->flags |= BLE_MBUF_HDR_F_CONN_REQ_TXD;
+        }
     }
 
     return rc;
@@ -834,10 +1445,39 @@ ble_ll_init_rx_pdu_start(uint8_t pdu_type)
 }
 
 /**
+ * Connection supervision timeout. When called, it means that the connection 
+ * supervision timeout has been reached. If reached, we end the connection. 
+ *  
+ * Context: Link Layer 
+ * 
+ * @param arg Pointer to connection state machine.
+ */
+void
+ble_ll_conn_spvn_timeout(void *arg)
+{
+    ble_ll_conn_end((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.
+ */
+void
+ble_ll_conn_rsp_rxd(void)
+{
+    if (g_ble_ll_conn_cur_sm) {
+        g_ble_ll_conn_cur_sm->rsp_rxd = 1;
+    }
+}
+
+/**
  * 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. 
- * 
+ *  
+ * Context: Link Layer 
+ *  
  * @param rxbuf Pointer to received PDU
  */
 void
@@ -849,10 +1489,15 @@ ble_ll_conn_slave_start(uint8_t *rxbuf)
 
     /* XXX: Should we error check the parameters? */
 
+    /* Allocate a connection. If none available, dont do anything */
+    connsm = (struct ble_ll_conn_sm *)os_memblock_get(&g_ble_ll_conn_pool);
+    if (!connsm) {
+        return;
+    }
+
     /* 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;
@@ -860,15 +1505,16 @@ ble_ll_conn_slave_start(uint8_t *rxbuf)
     crcinit <<= 8;
     crcinit |= dptr[6];
     connsm->crcinit = crcinit;
-    connsm->conn_tx_win_size = dptr[7];
-    connsm->conn_tx_win_off = le16toh(dptr + 8);
+    connsm->tx_win_size = dptr[7];
+    connsm->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);
+    connsm->slave_latency = le16toh(dptr + 12);
+    connsm->supervision_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;
 
+    /* XXX: might want to set this differently based on adv. filter policy! */
     /* 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) {
@@ -882,26 +1528,48 @@ ble_ll_conn_slave_start(uint8_t *rxbuf)
     /* 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);
+    /* The connection has been created. */
+    ble_ll_conn_created(connsm);
 }
 
-/* Initializet the connection module */
+/* Initialize the connection module */
 void
 ble_ll_conn_init(void)
 {
     int rc;
+    uint16_t maxbytes;
+    struct os_mbuf *m;
+    struct ble_ll_conn_global_params *conn_params;
 
     /* 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);
+
+    /* Initialize list of active conections */
+    SLIST_INIT(&g_ble_ll_conn_active_list);
+
+    /* Configure the global LL parameters */
+    conn_params = &g_ble_ll_conn_params;
+    maxbytes = BLE_LL_CFG_SUPP_MAX_RX_BYTES + BLE_LL_DATA_MAX_OVERHEAD;
+    conn_params->supp_max_rx_time = ble_ll_pdu_tx_time_get(maxbytes);
+    conn_params->supp_max_rx_octets = BLE_LL_CFG_SUPP_MAX_RX_BYTES;
+
+    maxbytes = BLE_LL_CFG_SUPP_MAX_TX_BYTES + BLE_LL_DATA_MAX_OVERHEAD;
+    conn_params->supp_max_tx_time = ble_ll_pdu_tx_time_get(maxbytes);
+    conn_params->supp_max_tx_octets = BLE_LL_CFG_SUPP_MAX_TX_BYTES;
+
+    maxbytes = BLE_LL_CFG_CONN_INIT_MAX_TX_BYTES + BLE_LL_DATA_MAX_OVERHEAD;
+    conn_params->conn_init_max_tx_time = ble_ll_pdu_tx_time_get(maxbytes);
+    conn_params->conn_init_max_tx_octets = BLE_LL_CFG_SUPP_MAX_TX_BYTES;
+
+    /* Initialize dummy empty pdu */
+    m = (struct os_mbuf *)&g_ble_ll_empty_pdu;
+    m->om_data = (uint8_t *)&g_ble_ll_empty_pdu[0];
+    m->om_data += sizeof(struct os_mbuf) + sizeof(struct os_mbuf_pkthdr);
+    m->om_len = 2;
+    m->om_flags = OS_MBUF_F_MASK(OS_MBUF_F_PKTHDR);
+    OS_MBUF_PKTHDR(m)->omp_len = 2;
 }
+

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 aaeab1b..6e97f26 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -501,6 +501,15 @@ ble_ll_scan_win_end_cb(struct ble_ll_sched_item *sch)
     return BLE_LL_SCHED_STATE_DONE;
 }
 
+/**
+ * Schedule callback for the start of a scan window 
+ *  
+ * Context: Interrupt 
+ * 
+ * @param sch 
+ * 
+ * @return int 
+ */
 static int
 ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
 {
@@ -514,7 +523,7 @@ ble_ll_scan_start_cb(struct ble_ll_sched_item *sch)
     scansm = (struct ble_ll_scan_sm *)sch->cb_arg;
 
     /* Set channel */
-    rc = ble_phy_setchan(scansm->scan_chan);
+    rc = ble_phy_setchan(scansm->scan_chan, 0, 0);
     assert(rc == 0);
 
     /* Start receiving */
@@ -549,7 +558,7 @@ ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
     /* XXX: Stop any timers we may have started */
 
     /* Remove any scheduled advertising items */
-    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_SCAN);
+    ble_ll_sched_rmv(BLE_LL_SCHED_TYPE_SCAN, NULL);
 
     /* Disable whitelisting (just in case) */
     ble_ll_whitelist_disable();
@@ -559,6 +568,10 @@ ble_ll_scan_sm_stop(struct ble_ll_scan_sm *scansm)
 
     /* Count # of times stopped */
     ++g_ble_ll_scan_stats.scan_stops;
+
+    /* XXX: Not sure this is correct. The LL might not actually be scanning */
+    /* Set LL state to standby */
+    ble_ll_state_set(BLE_LL_STATE_STANDBY);
 }
 
 static struct ble_ll_sched_item *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/controller/src/ble_ll_sched.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_sched.c b/net/nimble/controller/src/ble_ll_sched.c
index d0b3920..e131dff 100644
--- a/net/nimble/controller/src/ble_ll_sched.c
+++ b/net/nimble/controller/src/ble_ll_sched.c
@@ -141,14 +141,17 @@ ble_ll_sched_add(struct ble_ll_sched_item *sch)
 }
 
 /**
- * Remove a schedule item 
+ * Remove a schedule item. You can use this function to: 
+ *  1) Remove all schedule items of type 'sched_type' (cb_arg = NULL)
+ *  2) Remove schedule items of type 'sched_type' and matching callback args
+ * 
  * 
  * @param sched_type 
  * 
  * @return int 
  */
 int
-ble_ll_sched_rmv(uint8_t sched_type)
+ble_ll_sched_rmv(uint8_t sched_type, void *cb_arg)
 {
     os_sr_t sr;
     struct ble_ll_sched_item *entry;
@@ -162,8 +165,10 @@ ble_ll_sched_rmv(uint8_t sched_type)
         while (entry) {
             next = TAILQ_NEXT(entry, link);
             if (entry->sched_type == sched_type) {
-                TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link);
-                os_memblock_put(&g_ble_ll_sched_pool, entry);
+                if ((cb_arg == NULL) || (cb_arg == entry->cb_arg)) {
+                    TAILQ_REMOVE(&g_ble_ll_sched_q, entry, link);
+                    os_memblock_put(&g_ble_ll_sched_pool, entry);
+                }
             } 
             entry = next;
         }
@@ -230,7 +235,7 @@ ble_ll_sched_init(void)
                           g_ble_ll_sched_mem, "ll_sched");
     assert(err == OS_OK);
 
-    /* Start cputimer for the scheduler */
+    /* Initialize cputimer for the scheduler */
     cputime_timer_init(&g_ble_ll_sched_timer, ble_ll_sched_run, NULL);
 
     return err;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/controller/src/ble_ll_whitelist.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_whitelist.c b/net/nimble/controller/src/ble_ll_whitelist.c
index 1cb15e8..c4a0e04 100644
--- a/net/nimble/controller/src/ble_ll_whitelist.c
+++ b/net/nimble/controller/src/ble_ll_whitelist.c
@@ -40,7 +40,6 @@ ble_ll_whitelist_chg_allowed(void)
 {
     int rc;
 
-    /* XXX: add initiating to this */
     /* 
      * This command is not allowed if:
      *  -> advertising uses the whitelist and we are currently advertising.

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/drivers/native/src/ble_phy.c
----------------------------------------------------------------------
diff --git a/net/nimble/drivers/native/src/ble_phy.c b/net/nimble/drivers/native/src/ble_phy.c
index cf6ccbb..aa91a14 100644
--- a/net/nimble/drivers/native/src/ble_phy.c
+++ b/net/nimble/drivers/native/src/ble_phy.c
@@ -152,7 +152,7 @@ ble_phy_isr(void)
         assert(g_ble_phy_data.rxpdu != NULL);
 
         /* Call Link Layer receive start function */
-        rc = ble_ll_rx_start(g_ble_phy_data.rxpdu);
+        rc = ble_ll_rx_start(g_ble_phy_data.rxpdu, g_ble_phy_data.phy_chan);
         if (rc >= 0) {
             /* XXX: set rx end enable isr */
         } else {
@@ -349,7 +349,7 @@ ble_phy_txpwr_get(void)
  * @return int 0: success; PHY error code otherwise
  */
 int
-ble_phy_setchan(uint8_t chan)
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
 {
     assert(chan < BLE_PHY_NUM_CHANS);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/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 cd5549d..43bde94 100644
--- a/net/nimble/drivers/nrf52/src/ble_phy.c
+++ b/net/nimble/drivers/nrf52/src/ble_phy.c
@@ -26,6 +26,7 @@
 /* 
  * XXX: TODO
  * 1) make phy rx start and end function pointers to call?
+ * 2) How to set access address for data channel pdu's and crcinit
  */
 
 /* To disable all radio interrupts */
@@ -212,7 +213,7 @@ ble_phy_isr(void)
         }
 
         /* Call Link Layer receive start function */
-        rc = ble_ll_rx_start(g_ble_phy_data.rxpdu);
+        rc = ble_ll_rx_start(g_ble_phy_data.rxpdu, g_ble_phy_data.phy_chan);
         if (rc >= 0) {
             if (rc > 0) {
                 /* We need to go from disabled to TXEN */
@@ -426,19 +427,6 @@ ble_phy_tx(struct os_mbuf *txpdu, uint8_t beg_trans, uint8_t end_trans)
         return BLE_PHY_ERR_RADIO_STATE;
     }
 
-    /* Select tx address */
-    if (g_ble_phy_data.phy_chan < BLE_PHY_NUM_DATA_CHANS) {
-        /* XXX: fix this */
-        assert(0);
-        NRF_RADIO->TXADDRESS = 0;
-        NRF_RADIO->RXADDRESSES = 0;
-        NRF_RADIO->CRCINIT = 0;
-    } else {
-        NRF_RADIO->TXADDRESS = 0;
-        NRF_RADIO->RXADDRESSES = 1;
-        NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV;
-    }
-
     /* Set radio transmit data pointer */
     NRF_RADIO->PACKETPTR = (uint32_t)txpdu->om_data;
 
@@ -546,9 +534,10 @@ ble_phy_txpwr_get(void)
  * @return int 0: success; PHY error code otherwise
  */
 int
-ble_phy_setchan(uint8_t chan)
+ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit)
 {
     uint8_t freq;
+    uint32_t prefix;
 
     assert(chan < BLE_PHY_NUM_CHANS);
 
@@ -573,6 +562,16 @@ ble_phy_setchan(uint8_t chan)
             freq = (BLE_PHY_DATA_CHAN0_FREQ_MHZ - 2400) + 
                    (BLE_PHY_CHAN_SPACING_MHZ * (chan + 1));
         }
+
+        /* Configure logical address 1 and crcinit */
+        prefix = NRF_RADIO->PREFIX0;
+        prefix &= 0xffff00ff;
+        prefix |= ((access_addr >> 24) & 0xFF) << 8;
+        NRF_RADIO->BASE1 = (access_addr << 8) & 0xFFFFFF00;
+        NRF_RADIO->PREFIX0 = prefix;
+        NRF_RADIO->TXADDRESS = 1;
+        NRF_RADIO->RXADDRESSES = (1 << 1);
+        NRF_RADIO->CRCINIT = crcinit;
     } else {
         if (chan == 37) {
             freq = BLE_PHY_CHAN_SPACING_MHZ;
@@ -583,6 +582,11 @@ ble_phy_setchan(uint8_t chan)
             /* This advertising channel is at 2480 MHz */
             freq = BLE_PHY_CHAN_SPACING_MHZ * 40;
         }
+
+        /* Logical adddress 0 preconfigured */
+        NRF_RADIO->TXADDRESS = 0;
+        NRF_RADIO->RXADDRESSES = (1 << 0);
+        NRF_RADIO->CRCINIT = BLE_LL_CRCINIT_ADV;
     }
 
     /* Set the frequency and the data whitening initial value */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
index 2b4fd36..138eec0 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -60,7 +60,7 @@ host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
         }
         rc = host_hci_cmd_send(cmd);
         if (rc == 0) {
-            host_hci_outstanding_opcode = opcode;
+            //host_hci_outstanding_opcode = opcode;
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/net/nimble/include/nimble/ble.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/ble.h b/net/nimble/include/nimble/ble.h
index 8df8d9d..71229f2 100644
--- a/net/nimble/include/nimble/ble.h
+++ b/net/nimble/include/nimble/ble.h
@@ -37,6 +37,7 @@ extern struct os_mempool g_hci_os_event_pool;
  * The BLE mbuf header contains the following:
  *  flags: bitfield with the following values
  *      0x01:   Set if there was a match on the whitelist
+ *      0x02:   Set if a connect request was transmitted upon receiving pdu
  *  channel: The logical BLE channel PHY channel # (0 - 39)
  *  crcok: flag denoting CRC check passed (1) or failed (0).
  *  rssi: RSSI, in dBm.
@@ -50,7 +51,8 @@ struct ble_mbuf_hdr
 };
 
 /* Flag definitions */
-#define BLE_MBUF_HDR_F_DEVMATCH     (0x01)
+#define BLE_MBUF_HDR_F_DEVMATCH         (0x01)
+#define BLE_MBUF_HDR_F_CONN_REQ_TXD     (0x02)
 
 #define BLE_MBUF_HDR_PTR(om)    \
     (struct ble_mbuf_hdr *)((uint8_t *)om + sizeof(struct os_mbuf) + \
@@ -80,7 +82,7 @@ enum ble_error_codes
     BLE_ERR_AUTH_FAIL           = 5,
     BLE_ERR_PINKEY_MISSING      = 6,
     BLE_ERR_MEM_CAPACITY        = 7,
-    BLE_ERR_CONN_TMO            = 8,
+    BLE_ERR_CONN_SPVN_TMO       = 8,
     BLE_ERR_CONN_LIMIT          = 9,
     BLE_ERR_SYNCH_CONN_LIMIT    = 10,
     BLE_ERR_ACL_CONN_EXISTS     = 11,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/47dff3ec/project/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/project/bletest/src/main.c b/project/bletest/src/main.c
index db19665..9cbdcd8 100755
--- a/project/bletest/src/main.c
+++ b/project/bletest/src/main.c
@@ -30,7 +30,6 @@
 
 /* Init all tasks */
 volatile int tasks_initialized;
-int init_tasks(void);
 
 /* Task 1 */
 #define HOST_TASK_PRIO      (1)
@@ -75,7 +74,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_CFG_SCAN_FILT_POLICY    (BLE_HCI_SCAN_FILT_USE_WL)
 
 /* BLETEST variables */
-#define BLETEST_STACK_SIZE              (64)
+#define BLETEST_STACK_SIZE              (256)
 #define BLETEST_TASK_PRIO               (HOST_TASK_PRIO + 1)
 uint32_t g_next_os_time;
 int g_bletest_state;
@@ -214,42 +213,6 @@ bletest_init_scanner(void)
     }
 }
 
-void 
-host_task_handler(void *arg)
-{
-    int rc;
-
-    /* Init the console */
-    rc = console_init(NULL);
-    assert(rc == 0);
-
-    /* Initialize host HCI */
-    ble_hs_init(HOST_TASK_PRIO);
-
-    /* Initialize the BLE LL */
-    ble_ll_init();
-
-#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
-    /* Initialize the advertiser */
-    bletest_init_advertising();
-#endif
-
-#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
-    /* Initialize the scanner */
-    bletest_init_scanner();
-#endif
-
-    /* Init bletest varibles */
-    g_bletest_state = 0;
-    g_next_os_time = os_time_get();
-
-    /* We are initialized */
-    console_printf("Nimble stack initialized");
-
-    /* Call the host hci task */
-    ble_hs_task_handler(arg);
-}
-
 void
 bletest_execute(void)
 {
@@ -287,6 +250,11 @@ bletest_execute(void)
 #endif
 }
 
+/**
+ * Callback when BLE test timer expires. 
+ * 
+ * @param arg 
+ */
 void
 bletest_timer_cb(void *arg)
 {
@@ -297,18 +265,40 @@ bletest_timer_cb(void *arg)
     os_callout_reset(&g_bletest_timer.cf_c, OS_TICKS_PER_SEC);
 }
 
+/**
+ * BLE test task 
+ * 
+ * @param arg 
+ */
 void
 bletest_task_handler(void *arg)
 {
     struct os_event *ev;
     struct os_callout_func *cf;
 
+    /* We are initialized */
+    console_printf("Starting BLE test task");
+
+    /* Initialize eventq */
+    os_eventq_init(&g_bletest_evq);
+
     /* Initialize the host timer */
     os_callout_func_init(&g_bletest_timer, &g_bletest_evq, bletest_timer_cb,
                          NULL);
 
-    /* Initialize eventq */
-    os_eventq_init(&g_bletest_evq);
+#if (BLETEST_CFG_ROLE == BLETEST_ROLE_ADVERTISER)
+    /* Initialize the advertiser */
+    bletest_init_advertising();
+#endif
+
+#if (BLETEST_CFG_ROLE == BLETEST_ROLE_SCANNER)
+    /* Initialize the scanner */
+    bletest_init_scanner();
+#endif
+
+    /* Init bletest variables */
+    g_bletest_state = 0;
+    g_next_os_time = os_time_get();
 
     bletest_timer_cb(NULL);
 
@@ -335,7 +325,7 @@ bletest_task_handler(void *arg)
  *  
  * @return int 0 success; error otherwise.
  */
-int
+static int
 init_tasks(void)
 {
     os_task_init(&bletest_task, "bletest", bletest_task_handler, NULL, 
@@ -344,6 +334,12 @@ init_tasks(void)
 
     tasks_initialized = 1;
 
+    /* Initialize host HCI */
+    ble_hs_init(HOST_TASK_PRIO);
+
+    /* Initialize the BLE LL */
+    ble_ll_init();
+
     return 0;
 }
 
@@ -410,6 +406,10 @@ main(void)
     g_led_pin = LED_BLINK_PIN;
     gpio_init_out(g_led_pin, 1);
 
+    /* Init the console */
+    rc = console_init(NULL);
+    assert(rc == 0);
+
     /* Init tasks */
     init_tasks();
 


[2/3] incubator-mynewt-larva git commit: Fix type in hal for cputime

Posted by we...@apache.org.
Fix type in hal for cputime


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

Branch: refs/heads/master
Commit: c7cc3d0355eba61bc0fc0196d5a1aba6e6162c97
Parents: 9504907
Author: wes3 <wi...@micosa.io>
Authored: Tue Nov 17 13:05:02 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Thu Nov 19 11:31:04 2015 -0800

----------------------------------------------------------------------
 hw/hal/include/hal/hal_cputime.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/c7cc3d03/hw/hal/include/hal/hal_cputime.h
----------------------------------------------------------------------
diff --git a/hw/hal/include/hal/hal_cputime.h b/hw/hal/include/hal/hal_cputime.h
index 286736c..97d8709 100644
--- a/hw/hal/include/hal/hal_cputime.h
+++ b/hw/hal/include/hal/hal_cputime.h
@@ -170,7 +170,7 @@ void cputime_timer_relative(struct cpu_timer *timer, uint32_t usecs);
  *  
  * Stops a cputimer from running. The timer is removed from the timer queue 
  * and interrupts are disabled if no timers are left on the queue. Can be 
- * called even if timer is running. 
+ * called even if timer is not running. 
  * 
  * @param timer Pointer to cputimer to stop. Cannot be NULL.
  */


[3/3] incubator-mynewt-larva git commit: Remove erroneous debug commit and add ble_ll_ctrl header file

Posted by we...@apache.org.
Remove erroneous debug commit and add ble_ll_ctrl header file


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

Branch: refs/heads/master
Commit: c9d16694d3080cfd7ef9225d4fdcf24e930a37ba
Parents: 47dff3e
Author: wes3 <wi...@micosa.io>
Authored: Thu Nov 19 11:33:10 2015 -0800
Committer: wes3 <wi...@micosa.io>
Committed: Thu Nov 19 11:33:10 2015 -0800

----------------------------------------------------------------------
 .../controller/include/controller/ble_ll_ctrl.h | 190 +++++++++++++++++++
 net/nimble/host/src/host_hci_cmd.c              |   2 +-
 2 files changed, 191 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/c9d16694/net/nimble/controller/include/controller/ble_ll_ctrl.h
----------------------------------------------------------------------
diff --git a/net/nimble/controller/include/controller/ble_ll_ctrl.h b/net/nimble/controller/include/controller/ble_ll_ctrl.h
new file mode 100644
index 0000000..044ed81
--- /dev/null
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -0,0 +1,190 @@
+/**
+ * Copyright (c) 2015 Runtime Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef H_BLE_LL_CTRL_
+#define H_BLE_LL_CTRL_
+
+/* 
+ * LL CTRL PDU format
+ *  -> Opcode   (1 byte)
+ *  -> Data     (0 - 26 bytes)
+ */
+#define BLE_LL_CTRL_CONN_UPDATE_REQ     (0)
+#define BLE_LL_CTRL_CHANNEL_MAP_REQ     (1)
+#define BLE_LL_CTRL_TERMINATE_IND       (2)
+#define BLE_LL_CTRL_ENC_REQ             (3)
+#define BLE_LL_CTRL_ENC_RSP             (4)
+#define BLE_LL_CTRL_START_ENC_REQ       (5)
+#define BLE_LL_CTRL_START_ENC_RSP       (6)
+#define BLE_LL_CTRL_UNKNOWN_RSP         (7)
+#define BLE_LL_CTRL_FEATURE_REQ         (8)
+#define BLE_LL_CTRL_FEATURE_RSP         (9)
+#define BLE_LL_CTRL_PAUSE_ENC_REQ       (10)
+#define BLE_LL_CTRL_PAUSE_ENC_RSP       (11)
+#define BLE_LL_CTRL_VERSION_IND         (12)
+#define BLE_LL_CTRL_REJECT_IND          (13)
+#define BLE_LL_CTRL_SLAVE_FEATURE_REQ   (14)
+#define BLE_LL_CTRL_CONN_PARM_REQ       (15)
+#define BLE_LL_CTRL_CONN_PARM_RSP       (16)
+#define BLE_LL_CTRL_REJECT_IND_EXT      (17)
+#define BLE_LL_CTRL_PING_REQ            (18)
+#define BLE_LL_CTRL_PING_RSP            (19)
+#define BLE_LL_CTRL_LENGTH_REQ          (20)
+#define BLE_LL_CTRL_LENGTH_RSP          (21)
+
+/* LL control connection update request */
+struct ble_ll_conn_upd_req
+{
+    uint8_t winsize;
+    uint16_t winoffset;
+    uint16_t interval;
+    uint16_t latency;
+    uint16_t timeout;
+    uint16_t instant;
+};
+#define BLE_LL_CTRL_CONN_UPD_REQ_LEN        (11)
+
+/* LL control channel map request */
+struct ble_ll_chan_map_req
+{
+    uint8_t chmap[5];
+    uint16_t instant;
+};
+#define BLE_LL_CTRL_CHAN_MAP_LEN            (7)
+
+/* 
+ * LL control terminate ind
+ *  -> error code (1 byte)                         
+ */
+#define BLE_LL_CTRL_TERMINATE_IND_LEN      (1)
+
+/* LL control enc req */
+struct ble_ll_enc_req
+{
+    uint8_t rand[8];
+    uint16_t ediv;
+    uint8_t skdm[8];
+    uint32_t ivm;
+};
+
+#define BLE_LL_CTRL_ENC_REQ_LEN             (22)
+
+/* LL control enc rsp */
+struct ble_ll_enc_rsp
+{
+    uint8_t skds[8];
+    uint32_t ivs;
+};
+
+#define BLE_LL_CTRL_ENC_RSP_LEN             (12)
+
+/* LL control start enc req and start enc rsp have no data */ 
+#define BLE_LL_CTRL_START_ENC_LEN           (0)
+
+/* 
+ * LL control unknown response
+ *  -> 1 byte which contains the unknown or un-supported opcode.
+ */
+#define BLE_LL_CTRL_UNK_RSP_LEN             (1)
+
+/*
+ * LL control feature req and LL control feature rsp 
+ *  -> 8 bytes of data containing features supported by device.
+ */
+#define BLE_LL_CTRL_FEATURE_LEN             (8)
+
+/* LL control pause enc req and pause enc rsp have no data */
+#define BLE_LL_CTRL_PAUSE_ENC_LEN           (0)
+
+/* 
+ * LL control version ind 
+ *  -> version (1 byte):
+ *      Contains the version number of the bluetooth controller specification.
+ *  -> comp_id (2 bytes)
+ *      Contains the company identifier of the manufacturer of the controller.
+ *  -> sub_ver_num: Contains a unique value for implementation or revision of
+ *      the bluetooth controller.
+ */
+struct ble_ll_version_ind
+{
+    uint8_t ble_ctrlr_ver;
+    uint16_t company_id;
+    uint16_t sub_ver_num;
+};
+
+#define BLE_LL_CTRL_VERSION_IND_LEN         (5)
+
+/* 
+ * LL control reject ind
+ *  -> error code (1 byte): contains reason why request was rejected.
+ */
+#define BLE_LL_CTRL_REJ_IND_LEN             (1)
+
+/*
+ * LL control slave feature req
+ *  -> 8 bytes of data containing features supported by device.
+ */
+#define BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN   (8)
+
+/* LL control connection param req and connection param rsp */
+struct ble_ll_conn_params
+{
+    uint16_t interval_min;
+    uint16_t interval_max;
+    uint16_t latency;
+    uint16_t timeout;
+    uint16_t pref_periodicity;
+    uint16_t ref_conn_event_cnt;
+    uint16_t offset0;
+    uint16_t offset1;
+    uint16_t offset2;
+    uint16_t offset3;
+    uint16_t offset4;
+    uint16_t offset5;
+};
+
+#define BLE_LL_CTRL_CONN_PARAMS_LEN     (24)
+
+/* LL control reject ind ext */
+struct ble_ll_reject_ind_ext
+{
+    uint8_t reject_opcode;
+    uint8_t err_code;
+};
+
+#define BLE_LL_CTRL_REJECT_IND_EXT_LEN  (2)
+
+/* LL control ping req and ping rsp (contain no data) */
+#define BLE_LL_CTRL_PING_LEN            (0)
+
+/* 
+ * LL control length req and length rsp
+ *  -> max_rx_bytes (2 bytes): defines connMaxRxOctets. Range 27 to 251
+ *  -> max_rx_time (2 bytes): defines connMaxRxTime. Range 328 to 2120 usecs.
+ *  -> max_tx_bytes (2 bytes): defines connMaxTxOctets. Range 27 to 251
+ *  -> max_tx_time (2 bytes): defines connMaxTxTime. Range 328 to 2120 usecs.
+ */
+struct ble_ll_len_req
+{
+    uint16_t max_rx_bytes;
+    uint16_t max_rx_time;
+    uint16_t max_tx_bytes;
+    uint16_t max_tx_time;
+};
+
+#define BLE_LL_CTRL_LENGTH_REQ_LEN      (8)
+
+#endif /* H_BLE_LL_CTRL_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/c9d16694/net/nimble/host/src/host_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/host_hci_cmd.c b/net/nimble/host/src/host_hci_cmd.c
index 138eec0..2b4fd36 100644
--- a/net/nimble/host/src/host_hci_cmd.c
+++ b/net/nimble/host/src/host_hci_cmd.c
@@ -60,7 +60,7 @@ host_hci_le_cmd_send(uint16_t ocf, uint8_t len, void *cmddata)
         }
         rc = host_hci_cmd_send(cmd);
         if (rc == 0) {
-            //host_hci_outstanding_opcode = opcode;
+            host_hci_outstanding_opcode = opcode;
         }
     }