You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2016/11/10 19:32:10 UTC

[01/19] incubator-mynewt-core git commit: MYNEWT-374 Code does not build if BLE_LLC_FEAT_LL_PRIVACY=0

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 858f94e10 -> 406eeb0c2


MYNEWT-374 Code does not build if BLE_LLC_FEAT_LL_PRIVACY=0

The code would not compile if this setting was turned off. It
is now possible to set this feature to zero to reduce code
and ram usage of the controller. Also fixed the comment that
said this feature (privacy) was not supported by the nimble
controller.


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

Branch: refs/heads/develop
Commit: 7b5462126e58ea775cfab07f63e71740e0b706f1
Parents: 70987f7
Author: William San Filippo <wi...@runtime.io>
Authored: Mon Aug 29 22:35:40 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Mon Aug 29 22:35:40 2016 -0700

----------------------------------------------------------------------
 apps/bletest/src/main.c                 |  6 ++++--
 net/nimble/controller/src/ble_ll_adv.c  |  4 ++++
 net/nimble/controller/src/ble_ll_conn.c | 15 +++++++++++++--
 net/nimble/controller/src/ble_ll_scan.c | 12 +++++++++---
 net/nimble/include/nimble/nimble_opt.h  |  3 +--
 5 files changed, 31 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b546212/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index b6468a8..d21cc50 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -120,7 +120,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_CFG_SCAN_WINDOW         (700000 / BLE_HCI_SCAN_ITVL)
 #define BLETEST_CFG_SCAN_TYPE           (BLE_HCI_SCAN_TYPE_PASSIVE)
 #define BLETEST_CFG_SCAN_OWN_ADDR_TYPE  (BLE_HCI_ADV_OWN_ADDR_PUBLIC)
-#define BLETEST_CFG_SCAN_FILT_POLICY    (BLE_HCI_SCAN_FILT_USE_WL)
+#define BLETEST_CFG_SCAN_FILT_POLICY    (BLE_HCI_SCAN_FILT_NO_WL)
 #define BLETEST_CFG_FILT_DUP_ADV        (1)
 
 /* Connection config */
@@ -428,7 +428,7 @@ bletest_init_scanner(void)
     rc = ble_hs_hci_cmd_build_le_set_scan_params(BLETEST_CFG_SCAN_TYPE,
                                                BLETEST_CFG_SCAN_ITVL,
                                                BLETEST_CFG_SCAN_WINDOW,
-                                               BLETEST_CFG_SCAN_OWN_ADDR_TYPE,
+                                               own_addr_type,
                                                BLETEST_CFG_SCAN_FILT_POLICY,
                                                buf, sizeof buf);
     assert(rc == 0);
@@ -659,9 +659,11 @@ bletest_execute_advertiser(void)
     int i;
 #if (BLETEST_CONCURRENT_CONN_TEST == 1)
     int j;
+#if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1)
     uint16_t mask;
     uint16_t reply_handle;
 #endif
+#endif
     int rc;
     uint16_t handle;
     uint16_t pktlen;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b546212/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 0c6df3b..ceb5025 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -988,7 +988,9 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
 {
     int valid;
     uint8_t pyld_len;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     uint8_t resolved;
+#endif
     uint8_t addr_type;
     uint8_t *inita;
     uint8_t *ident_addr;
@@ -997,7 +999,9 @@ ble_ll_adv_conn_req_rxd(uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
 
     /* Check filter policy. */
     valid = 0;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     resolved = BLE_MBUF_HDR_RESOLVED(hdr);
+#endif
     advsm = &g_ble_ll_adv_sm;
     inita = rxbuf + BLE_LL_PDU_HDR_LEN;
     if (hdr->rxinfo.flags & BLE_MBUF_HDR_F_DEVMATCH) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b546212/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 e3c40e2..38220ea 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1953,14 +1953,17 @@ static void
 ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
                            uint16_t txoffset, int rpa_index)
 {
-    int is_rpa;
     uint8_t hdr;
     uint8_t *dptr;
     uint8_t *addr;
     struct ble_mbuf_hdr *ble_hdr;
-    struct ble_ll_resolv_entry *rl;
     struct ble_ll_conn_sm *connsm;
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
+    int is_rpa;
+    struct ble_ll_resolv_entry *rl;
+#endif
+
     assert(m != NULL);
 
     /* Retain pdu type but clear txadd/rxadd bits */
@@ -1983,6 +1986,7 @@ ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
     }
 
     /* XXX: do this ahead of time? Calculate the local rpa I mean */
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
         rl = NULL;
         is_rpa = ble_ll_is_rpa(adva, addr_type);
@@ -2002,6 +2006,7 @@ ble_ll_conn_req_pdu_update(struct os_mbuf *m, uint8_t *adva, uint8_t addr_type,
             addr = NULL;
         }
     }
+#endif
 
     if (addr) {
         memcpy(dptr, addr, BLE_DEV_ADDR_LEN);
@@ -2130,7 +2135,9 @@ ble_ll_conn_event_halt(void)
 void
 ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
 {
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     int8_t rpa_index;
+#endif
     uint8_t addr_type;
     uint8_t payload_len;
     uint8_t *addr;
@@ -2151,6 +2158,7 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
                 addr_type = BLE_HCI_CONN_PEER_ADDR_PUBLIC;
             }
 
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
             /*
              * Did we resolve this address? If so, set correct peer address
              * and peer address type.
@@ -2163,6 +2171,9 @@ ble_ll_init_rx_pkt_in(uint8_t *rxbuf, struct ble_mbuf_hdr *ble_hdr)
             } else {
                 addr = rxbuf + BLE_LL_PDU_HDR_LEN;
             }
+#else
+            addr = rxbuf + BLE_LL_PDU_HDR_LEN;
+#endif
 
             connsm->peer_addr_type = addr_type;
             memcpy(connsm->peer_addr, addr, BLE_DEV_ADDR_LEN);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b546212/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 29193dc..4890d18 100644
--- a/net/nimble/controller/src/ble_ll_scan.c
+++ b/net/nimble/controller/src/ble_ll_scan.c
@@ -386,7 +386,9 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
                            struct ble_ll_scan_sm *scansm)
 {
     int rc;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     int index;
+#endif
     uint8_t evtype;
     uint8_t subev;
     uint8_t *evbuf;
@@ -440,6 +442,7 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
             }
 
             rxbuf += BLE_LL_PDU_HDR_LEN;
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
             if (BLE_MBUF_HDR_RESOLVED(hdr)) {
                 index = scansm->scan_rpa_index;
                 adv_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
@@ -449,9 +452,12 @@ ble_ll_hci_send_adv_report(uint8_t pdu_type, uint8_t txadd, uint8_t *rxbuf,
                  * we just add 2 here.
                  */
                 addr_type = g_ble_ll_resolv_list[index].rl_addr_type + 2;
-            } else{
+            } else {
                 adv_addr = rxbuf;
             }
+#else
+            adv_addr = rxbuf;
+#endif
 
             orig_evbuf = evbuf;
             evbuf += 5;
@@ -1098,7 +1104,9 @@ ble_ll_scan_wfr_timer_exp(void)
 void
 ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
 {
+#if (BLE_LL_CFG_FEAT_LL_PRIVACY == 1)
     int index;
+#endif
     uint8_t *adv_addr;
     uint8_t *adva;
     uint8_t *ident_addr;
@@ -1137,8 +1145,6 @@ ble_ll_scan_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
         ident_addr = g_ble_ll_resolv_list[index].rl_identity_addr;
         ident_addr_type = g_ble_ll_resolv_list[index].rl_addr_type;
     }
-#else
-    index = -1;
 #endif
 
     /*

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7b546212/net/nimble/include/nimble/nimble_opt.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/nimble_opt.h b/net/nimble/include/nimble/nimble_opt.h
index c82bcb5..859b0aa 100644
--- a/net/nimble/include/nimble/nimble_opt.h
+++ b/net/nimble/include/nimble/nimble_opt.h
@@ -377,8 +377,7 @@
 #endif
 
 /*
- * This option is used to enable/disable LL privacy. Currently, this feature
- * is not supported by the nimble controller.
+ * This option is used to enable/disable LL privacy.
  */
 #ifndef BLE_LL_CFG_FEAT_LL_PRIVACY
 #define BLE_LL_CFG_FEAT_LL_PRIVACY              (1)


[02/19] incubator-mynewt-core git commit: MYNEWT-347 BLE Host - GAP update; use L2CAP proc.

Posted by cc...@apache.org.
MYNEWT-347 BLE Host - GAP update; use L2CAP proc.

Prior to this change, the host did not failover to the L2CAP connection
parameter update procedure when the GAP update procedure failed.
Rather, it was up to the application to manually do that.

Now, if the host automatically performs the L2CAP procedure if all of
the following are true:
    * We are the slave.
    * Controller reports the following status code in its command
      status event:
        o Unknown HCI command (0x01).
    * Controller reports the following status code in its LE connection
      update complete event:
        o Unsupported remote feature (0x1a).

In addition, there was some missing functionality that this commit fills
in:
    * Timeouts for GAP update procedures (30 seconds).
    * Report and delete outstanding L2CAP sig procedures when the
      connection is broken.


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

Branch: refs/heads/develop
Commit: f77bf7fcc18029dd8fc5c7ae380b40d6d3c67465
Parents: 7b54621
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Sep 5 11:10:30 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Tue Sep 6 13:59:07 2016 -0700

----------------------------------------------------------------------
 apps/bletiny/src/main.c                     |   5 +-
 libs/os/include/os/os_time.h                |   5 +-
 net/nimble/host/include/host/ble_gap.h      |   1 +
 net/nimble/host/include/host/ble_l2cap.h    |   3 +-
 net/nimble/host/src/ble_gap.c               | 394 ++++++++++++++++++++--
 net/nimble/host/src/ble_hs_conn_priv.h      |   1 -
 net/nimble/host/src/ble_l2cap_sig.c         |  34 +-
 net/nimble/host/src/ble_l2cap_sig_priv.h    |   1 +
 net/nimble/host/src/test/ble_gap_test.c     | 411 +++++++++++++++++++----
 net/nimble/host/src/test/ble_hs_test_util.c | 112 +++++-
 net/nimble/host/src/test/ble_hs_test_util.h |  14 +
 net/nimble/host/src/test/ble_l2cap_test.c   | 135 +-------
 12 files changed, 893 insertions(+), 223 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/apps/bletiny/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletiny/src/main.c b/apps/bletiny/src/main.c
index d06fa0a..dfd0aee 100755
--- a/apps/bletiny/src/main.c
+++ b/apps/bletiny/src/main.c
@@ -1044,9 +1044,10 @@ bletiny_gap_event(struct ble_gap_event *event, void *arg)
 }
 
 static void
-bletiny_on_l2cap_update(int status, void *arg)
+bletiny_on_l2cap_update(uint16_t conn_handle, int status, void *arg)
 {
-    console_printf("l2cap update complete; status=%d\n", status);
+    console_printf("l2cap update complete; conn_handle=%d status=%d\n",
+                   conn_handle, status);
 }
 
 static void

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/libs/os/include/os/os_time.h
----------------------------------------------------------------------
diff --git a/libs/os/include/os/os_time.h b/libs/os/include/os/os_time.h
index 7e577eb..38b6bd9 100644
--- a/libs/os/include/os/os_time.h
+++ b/libs/os/include/os/os_time.h
@@ -55,11 +55,12 @@
 #include <stdbool.h>
 #include <stdint.h>
 
-typedef uint32_t os_time_t;
-
 #ifndef UINT32_MAX
 #define UINT32_MAX  0xFFFFFFFFU
 #endif
+
+typedef uint32_t os_time_t;
+#define OS_TIME_MAX UINT32_MAX
  
 /* Used to wait forever for events and mutexs */
 #define OS_TIMEOUT_NEVER    (UINT32_MAX)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/include/host/ble_gap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_gap.h b/net/nimble/host/include/host/ble_gap.h
index 960ad7b..f61324b 100644
--- a/net/nimble/host/include/host/ble_gap.h
+++ b/net/nimble/host/include/host/ble_gap.h
@@ -555,6 +555,7 @@ int ble_gap_wl_set(const struct ble_gap_white_entry *white_list,
                    uint8_t white_list_count);
 int ble_gap_update_params(uint16_t conn_handle,
                           const struct ble_gap_upd_params *params);
+int ble_gap_dbg_update_active(uint16_t conn_handle);
 int ble_gap_security_initiate(uint16_t conn_handle);
 int ble_gap_pair_initiate(uint16_t conn_handle);
 int ble_gap_encryption_initiate(uint16_t conn_handle, const uint8_t *ltk,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/include/host/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_l2cap.h b/net/nimble/host/include/host/ble_l2cap.h
index 620e0eb..ebdfa1c 100644
--- a/net/nimble/host/include/host/ble_l2cap.h
+++ b/net/nimble/host/include/host/ble_l2cap.h
@@ -52,7 +52,8 @@ struct ble_hs_conn;
 #define BLE_L2CAP_SIG_ERR_MTU_EXCEEDED          0x0001
 #define BLE_L2CAP_SIG_ERR_INVALID_CID           0x0002
 
-typedef void ble_l2cap_sig_update_fn(int status, void *arg);
+typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
+                                     void *arg);
 
 struct ble_l2cap_sig_update_params {
     uint16_t itvl_min;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/ble_gap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap.c b/net/nimble/host/src/ble_gap.c
index f53a738..2699e72 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -22,6 +22,7 @@
 #include <errno.h>
 #include "bsp/bsp.h"
 #include "os/os.h"
+#include "util/mem.h"
 #include "nimble/nimble_opt.h"
 #include "host/ble_hs_adv.h"
 #include "ble_hs_priv.h"
@@ -59,16 +60,18 @@
  */
 
 /** GAP procedure op codes. */
-#define BLE_GAP_OP_NULL                                 0
-#define BLE_GAP_OP_M_DISC                               1
-#define BLE_GAP_OP_M_CONN                               2
-#define BLE_GAP_OP_S_ADV                                1
+#define BLE_GAP_OP_NULL                         0
+#define BLE_GAP_OP_M_DISC                       1
+#define BLE_GAP_OP_M_CONN                       2
+#define BLE_GAP_OP_S_ADV                        1
 
 /**
  * If an attempt to cancel an active procedure fails, the attempt is retried
  * at this rate (ms).
  */
-#define BLE_GAP_CANCEL_RETRY_RATE                              100 /* ms */
+#define BLE_GAP_CANCEL_RETRY_RATE               100 /* ms */
+
+#define BLE_GAP_UPDATE_TIMEOUT                  (30 * OS_TICKS_PER_SEC)
 
 /**
  * The maximum amount of user data that can be put into the advertising data.
@@ -78,6 +81,8 @@
 #define BLE_GAP_ADV_DATA_LIMIT_FLAGS    (BLE_HCI_MAX_ADV_DATA_LEN - 3)
 #define BLE_GAP_ADV_DATA_LIMIT_NO_FLAGS BLE_HCI_MAX_ADV_DATA_LEN
 
+#define BLE_GAP_MAX_UPDATE_ENTRIES      1
+
 static const struct ble_gap_conn_params ble_gap_conn_params_dflt = {
     .scan_itvl = 0x0010,
     .scan_window = 0x0010,
@@ -141,9 +146,13 @@ static bssnz_t struct {
     unsigned adv_auto_flags:1;
 } ble_gap_slave;
 
-static int ble_gap_adv_enable_tx(int enable);
-static int ble_gap_conn_cancel_tx(void);
-static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
+struct ble_gap_update_entry {
+    SLIST_ENTRY(ble_gap_update_entry) next;
+    struct ble_gap_upd_params params;
+    os_time_t exp_os_ticks;
+    uint16_t conn_handle;
+};
+SLIST_HEAD(ble_gap_update_entry_list, ble_gap_update_entry);
 
 struct ble_gap_snapshot {
     struct ble_gap_conn_desc *desc;
@@ -151,6 +160,23 @@ struct ble_gap_snapshot {
     void *cb_arg;
 };
 
+static void *ble_gap_update_entry_mem;
+static struct os_mempool ble_gap_update_entry_pool;
+static struct ble_gap_update_entry_list ble_gap_update_entries;
+
+static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry);
+static struct ble_gap_update_entry *
+ble_gap_update_entry_find(uint16_t conn_handle,
+                          struct ble_gap_update_entry **out_prev);
+static struct ble_gap_update_entry *
+ble_gap_update_entry_remove(uint16_t conn_handle);
+static void
+ble_gap_update_l2cap_cb(uint16_t conn_handle, int status, void *arg);
+
+static int ble_gap_adv_enable_tx(int enable);
+static int ble_gap_conn_cancel_tx(void);
+static int ble_gap_disc_enable_tx(int enable, int filter_duplicates);
+
 STATS_SECT_DECL(ble_gap_stats) ble_gap_stats;
 STATS_NAME_START(ble_gap_stats)
     STATS_NAME(ble_gap_stats, wl_set)
@@ -187,6 +213,24 @@ STATS_NAME_START(ble_gap_stats)
 STATS_NAME_END(ble_gap_stats)
 
 /*****************************************************************************
+ * $debug                                                                    *
+ *****************************************************************************/
+
+#if BLE_HS_DEBUG
+int
+ble_gap_dbg_update_active(uint16_t conn_handle)
+{
+    const struct ble_gap_update_entry *entry;
+
+    ble_hs_lock();
+    entry = ble_gap_update_entry_find(conn_handle, NULL);
+    ble_hs_unlock();
+
+    return entry != NULL;
+}
+#endif
+
+/*****************************************************************************
  * $log                                                                      *
  *****************************************************************************/
 
@@ -606,6 +650,11 @@ ble_gap_update_notify(uint16_t conn_handle, int status)
     event.conn_update.status = status;
 
     ble_gap_call_conn_event_cb(&event, conn_handle);
+
+    /* Terminate the connection on procedure timeout. */
+    if (status == BLE_HS_ETIMEOUT) {
+        ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+    }
 }
 
 static uint32_t
@@ -648,16 +697,62 @@ ble_gap_slave_ticks_until_exp(void)
     return 0;
 }
 
+static uint16_t
+ble_gap_update_next_exp(int32_t *out_ticks_from_now)
+{
+    struct ble_gap_update_entry *entry;
+    os_time_t now;
+    uint16_t conn_handle;
+    int32_t best_ticks;
+    int32_t ticks;
+
+    BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
+
+    conn_handle = BLE_HS_CONN_HANDLE_NONE;
+    best_ticks = BLE_HS_FOREVER;
+    now = os_time_get();
+
+    SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
+        ticks = entry->exp_os_ticks - now;
+        if (ticks <= 0) {
+            ticks = 0;
+        }
+
+        if (ticks < best_ticks) {
+            conn_handle = entry->conn_handle;
+            best_ticks = ticks;
+        }
+    }
+
+    if (out_ticks_from_now != NULL) {
+        *out_ticks_from_now = best_ticks;
+    }
+
+    return conn_handle;
+
+}
+
+static uint32_t
+ble_gap_update_ticks_until_exp(void)
+{
+    int32_t ticks;
+
+    ble_gap_update_next_exp(&ticks);
+    return ticks;
+}
+
 static void
 ble_gap_heartbeat_sched(void)
 {
     int32_t mst_ticks;
     int32_t slv_ticks;
+    int32_t upd_ticks;
     int32_t ticks;
 
     mst_ticks = ble_gap_master_ticks_until_exp();
     slv_ticks = ble_gap_slave_ticks_until_exp();
-    ticks = min(mst_ticks, slv_ticks);
+    upd_ticks = ble_gap_update_ticks_until_exp();
+    ticks = min(min(mst_ticks, slv_ticks), upd_ticks);
 
     ble_hs_heartbeat_sched(ticks);
 }
@@ -702,14 +797,23 @@ ble_gap_master_failed(int status)
 static void
 ble_gap_update_failed(uint16_t conn_handle, int status)
 {
+    struct ble_gap_update_entry *entry;
+
     STATS_INC(ble_gap_stats, update_fail);
-    ble_hs_atomic_conn_set_flags(conn_handle, BLE_HS_CONN_F_UPDATE, 0);
+
+    ble_hs_lock();
+    entry = ble_gap_update_entry_remove(conn_handle);
+    ble_hs_unlock();
+
+    ble_gap_update_entry_free(entry);
+
     ble_gap_update_notify(conn_handle, status);
 }
 
 void
 ble_gap_conn_broken(uint16_t conn_handle, int reason)
 {
+    struct ble_gap_update_entry *entry;
     struct ble_gap_snapshot snap;
     struct ble_gap_event event;
     int rc;
@@ -723,10 +827,21 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason)
         return;
     }
 
+    /* If there was a connection update in progress, indicate to the
+     * application that it did not complete.
+     */
+    ble_hs_lock();
+    entry = ble_gap_update_entry_remove(conn_handle);
+    ble_hs_unlock();
+
+    ble_gap_update_notify(conn_handle, reason);
+    ble_gap_update_entry_free(entry);
+
     /* Indicate the connection termination to each module.  The order matters
      * here: gatts must come before gattc to ensure the application does not
      * get informed of spurious notify-tx events.
      */
+    ble_l2cap_sig_conn_broken(conn_handle, reason);
     ble_sm_connection_broken(conn_handle);
     ble_gatts_connection_broken(conn_handle);
     ble_gattc_connection_broken(conn_handle);
@@ -740,6 +855,16 @@ ble_gap_conn_broken(uint16_t conn_handle, int reason)
     STATS_INC(ble_gap_stats, disconnect);
 }
 
+static void
+ble_gap_update_to_l2cap(const struct ble_gap_upd_params *params,
+                        struct ble_l2cap_sig_update_params *l2cap_params)
+{
+    l2cap_params->itvl_min = params->itvl_min;
+    l2cap_params->itvl_max = params->itvl_max;
+    l2cap_params->slave_latency = params->latency;
+    l2cap_params->timeout_multiplier = params->supervision_timeout;
+}
+
 void
 ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt)
 {
@@ -766,36 +891,79 @@ ble_gap_rx_disconn_complete(struct hci_disconn_complete *evt)
 void
 ble_gap_rx_update_complete(struct hci_le_conn_upd_complete *evt)
 {
+    struct ble_gap_update_entry *entry;
+
 #if !NIMBLE_OPT(CONNECT)
     return;
 #endif
 
+    struct ble_l2cap_sig_update_params l2cap_params;
     struct ble_gap_event event;
     struct ble_hs_conn *conn;
+    int cb_status;
+    int call_cb;
+    int rc;
 
     STATS_INC(ble_gap_stats, rx_update_complete);
 
     memset(&event, 0, sizeof event);
+    memset(&l2cap_params, 0, sizeof l2cap_params);
 
     ble_hs_lock();
 
     conn = ble_hs_conn_find(evt->connection_handle);
     if (conn != NULL) {
-        if (evt->status == 0) {
+        switch (evt->status) {
+        case 0:
+            /* Connection successfully updated. */
             conn->bhc_itvl = evt->conn_itvl;
             conn->bhc_latency = evt->conn_latency;
             conn->bhc_supervision_timeout = evt->supervision_timeout;
+            break;
+
+        case BLE_ERR_UNSUPP_REM_FEATURE:
+            /* Peer reports that it doesn't support the procedure.  This should
+             * only happen if our controller sent the 4.1 Connection Parameters
+             * Request Procedure.  If we are the slave, fail over to the L2CAP
+             * update procedure.
+             */
+            entry = ble_gap_update_entry_find(evt->connection_handle, NULL);
+            if (entry != NULL && !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
+                ble_gap_update_to_l2cap(&entry->params, &l2cap_params);
+            }
+            break;
+
+        default:
+            break;
         }
     }
 
-    conn->bhc_flags &= ~BLE_HS_CONN_F_UPDATE;
+    /* We aren't failing over to L2CAP, the update procedure is complete. */
+    if (l2cap_params.itvl_min == 0) {
+        entry = ble_gap_update_entry_remove(evt->connection_handle);
+        ble_gap_update_entry_free(entry);
+    }
 
     ble_hs_unlock();
 
-    event.type = BLE_GAP_EVENT_CONN_UPDATE;
-    event.conn_update.conn_handle = evt->connection_handle;
-    event.conn_update.status = BLE_HS_HCI_ERR(evt->status);
-    ble_gap_call_conn_event_cb(&event, evt->connection_handle);
+    if (l2cap_params.itvl_min != 0) {
+        rc = ble_l2cap_sig_update(evt->connection_handle,
+                                  &l2cap_params,
+                                  ble_gap_update_l2cap_cb, NULL);
+        if (rc == 0) {
+            call_cb = 0;
+        } else {
+            call_cb = 1;
+            cb_status = rc;
+        }
+    } else {
+        call_cb = 1;
+        cb_status = BLE_HS_HCI_ERR(evt->status);
+    }
+
+    if (call_cb) {
+        ble_gap_update_notify(evt->connection_handle, cb_status);
+    }
 }
 
 /**
@@ -1156,6 +1324,34 @@ ble_gap_slave_heartbeat(void)
     return BLE_HS_FOREVER;
 }
 
+static int32_t
+ble_gap_update_heartbeat(void)
+{
+    struct ble_gap_update_entry *entry;
+    int32_t ticks_until_exp;
+    uint16_t conn_handle;
+
+    do {
+        ble_hs_lock();
+
+        conn_handle = ble_gap_update_next_exp(&ticks_until_exp);
+        if (ticks_until_exp == 0) {
+            entry = ble_gap_update_entry_remove(conn_handle);
+        } else {
+            entry = NULL;
+        }
+
+        ble_hs_unlock();
+
+        if (entry != NULL) {
+            ble_gap_update_notify(conn_handle, BLE_HS_ETIMEOUT);
+            ble_gap_update_entry_free(entry);
+        }
+    } while (entry != NULL);
+
+    return ticks_until_exp;
+}
+
 /**
  * Handles timed-out master procedures.
  *
@@ -1167,13 +1363,15 @@ ble_gap_slave_heartbeat(void)
 int32_t
 ble_gap_heartbeat(void)
 {
+    int32_t update_ticks;
     int32_t master_ticks;
     int32_t slave_ticks;
 
     master_ticks = ble_gap_master_heartbeat();
     slave_ticks = ble_gap_slave_heartbeat();
+    update_ticks = ble_gap_update_heartbeat();
 
-    return min(master_ticks, slave_ticks);
+    return min(min(master_ticks, slave_ticks), update_ticks);
 }
 
 /*****************************************************************************
@@ -2450,6 +2648,93 @@ done:
  * $update connection parameters                                             *
  *****************************************************************************/
 
+static struct ble_gap_update_entry *
+ble_gap_update_entry_alloc(void)
+{
+    struct ble_gap_update_entry *entry;
+
+    entry = os_memblock_get(&ble_gap_update_entry_pool);
+    if (entry != NULL) {
+        memset(entry, 0, sizeof *entry);
+    }
+
+    return entry;
+}
+
+static void
+ble_gap_update_entry_free(struct ble_gap_update_entry *entry)
+{
+    int rc;
+
+    if (entry != NULL) {
+        rc = os_memblock_put(&ble_gap_update_entry_pool, entry);
+        BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+    }
+}
+
+static struct ble_gap_update_entry *
+ble_gap_update_entry_find(uint16_t conn_handle,
+                          struct ble_gap_update_entry **out_prev)
+{
+    struct ble_gap_update_entry *entry;
+    struct ble_gap_update_entry *prev;
+
+    BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
+
+    prev = NULL;
+    SLIST_FOREACH(entry, &ble_gap_update_entries, next) {
+        if (entry->conn_handle == conn_handle) {
+            break;
+        }
+
+        prev = entry;
+    }
+
+    if (out_prev != NULL) {
+        *out_prev = prev;
+    }
+
+    return entry;
+}
+
+static struct ble_gap_update_entry *
+ble_gap_update_entry_remove(uint16_t conn_handle)
+{
+    struct ble_gap_update_entry *entry;
+    struct ble_gap_update_entry *prev;
+
+    entry = ble_gap_update_entry_find(conn_handle, &prev);
+    if (entry != NULL) {
+        if (prev == NULL) {
+            SLIST_REMOVE_HEAD(&ble_gap_update_entries, next);
+        } else {
+            SLIST_NEXT(prev, next) = SLIST_NEXT(entry, next);
+        }
+    }
+
+    return entry;
+}
+
+static void
+ble_gap_update_l2cap_cb(uint16_t conn_handle, int status, void *arg)
+{
+    struct ble_gap_update_entry *entry;
+
+    /* Report failures and rejections.  Success gets reported when the
+     * controller sends the connection update complete event.
+     */
+    if (status != 0) {
+        ble_hs_lock();
+        entry = ble_gap_update_entry_remove(conn_handle);
+        ble_hs_unlock();
+
+        if (entry != NULL) {
+            ble_gap_update_entry_free(entry);
+            ble_gap_update_notify(conn_handle, status);
+        }
+    }
+}
+
 static int
 ble_gap_tx_param_pos_reply(uint16_t conn_handle,
                            struct ble_gap_upd_params *params)
@@ -2538,9 +2823,6 @@ ble_gap_rx_param_req(struct hci_le_conn_param_req *evt)
         rc = ble_gap_tx_param_pos_reply(evt->connection_handle, &self_params);
         if (rc != 0) {
             ble_gap_update_failed(evt->connection_handle, rc);
-        } else {
-            ble_hs_atomic_conn_set_flags(evt->connection_handle,
-                                         BLE_HS_CONN_F_UPDATE, 1);
         }
     } else {
         ble_gap_tx_param_neg_reply(evt->connection_handle, reject_reason);
@@ -2600,10 +2882,14 @@ ble_gap_update_params(uint16_t conn_handle,
     return BLE_HS_ENOTSUP;
 #endif
 
+    struct ble_l2cap_sig_update_params l2cap_params;
+    struct ble_gap_update_entry *entry;
     struct ble_hs_conn *conn;
     int rc;
 
     STATS_INC(ble_gap_stats, update);
+    memset(&l2cap_params, 0, sizeof l2cap_params);
+    entry = NULL;
 
     ble_hs_lock();
 
@@ -2613,28 +2899,58 @@ ble_gap_update_params(uint16_t conn_handle,
         goto done;
     }
 
-    if (conn->bhc_flags & BLE_HS_CONN_F_UPDATE) {
+    entry = ble_gap_update_entry_find(conn_handle, NULL);
+    if (entry != NULL) {
         rc = BLE_HS_EALREADY;
         goto done;
     }
 
+    entry = ble_gap_update_entry_alloc();
+    if (entry == NULL) {
+        rc = BLE_HS_ENOMEM;
+        goto done;
+    }
+
+    entry->conn_handle = conn_handle;
+    entry->params = *params;
+    entry->exp_os_ticks = os_time_get() + BLE_GAP_UPDATE_TIMEOUT;
+
     BLE_HS_LOG(INFO, "GAP procedure initiated: ");
     ble_gap_log_update(conn_handle, params);
     BLE_HS_LOG(INFO, "\n");
 
     rc = ble_gap_update_tx(conn_handle, params);
-    if (rc != 0) {
-        goto done;
-    }
 
-    conn->bhc_flags |= BLE_HS_CONN_F_UPDATE;
+    /* If our controller reports that it doesn't support the update procedure,
+     * and we are the slave, fail over to the L2CAP update procedure.
+     */
+    if (rc == BLE_HS_HCI_ERR(BLE_ERR_UNKNOWN_HCI_CMD) &&
+        !(conn->bhc_flags & BLE_HS_CONN_F_MASTER)) {
+
+        ble_gap_update_to_l2cap(params, &l2cap_params);
+    }
 
 done:
     ble_hs_unlock();
 
     if (rc != 0) {
+        ble_gap_update_entry_free(entry);
+
+        if (l2cap_params.itvl_min != 0) {
+            rc = ble_l2cap_sig_update(conn_handle,
+                                      &l2cap_params,
+                                      ble_gap_update_l2cap_cb, NULL);
+        }
+    }
+
+    ble_hs_lock();
+    if (rc == 0) {
+        SLIST_INSERT_HEAD(&ble_gap_update_entries, entry, next);
+    } else {
         STATS_INC(ble_gap_stats, update_fail);
     }
+    ble_hs_unlock();
+
     return rc;
 }
 
@@ -2927,15 +3243,41 @@ ble_gap_init(void)
 {
     int rc;
 
+    free(ble_gap_update_entry_mem);
+
     memset(&ble_gap_master, 0, sizeof ble_gap_master);
     memset(&ble_gap_slave, 0, sizeof ble_gap_slave);
 
+    SLIST_INIT(&ble_gap_update_entries);
+
+    rc = mem_malloc_mempool(&ble_gap_update_entry_pool,
+                            BLE_GAP_MAX_UPDATE_ENTRIES,
+                            sizeof (struct ble_gap_update_entry),
+                            "ble_gap_update",
+                            &ble_gap_update_entry_mem);
+    switch (rc) {
+    case 0:
+        break;
+    case OS_ENOMEM:
+        rc = BLE_HS_ENOMEM;
+        goto err;
+    default:
+        rc = BLE_HS_EOS;
+        goto err;
+    }
+
     rc = stats_init_and_reg(
         STATS_HDR(ble_gap_stats), STATS_SIZE_INIT_PARMS(ble_gap_stats,
         STATS_SIZE_32), STATS_NAME_INIT_PARMS(ble_gap_stats), "ble_gap");
     if (rc != 0) {
-        return BLE_HS_EOS;
+        goto err;
     }
 
     return 0;
+
+err:
+    free(ble_gap_update_entry_mem);
+    ble_gap_update_entry_mem = NULL;
+
+    return rc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/ble_hs_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn_priv.h b/net/nimble/host/src/ble_hs_conn_priv.h
index da8d2fc..ac87ff5 100644
--- a/net/nimble/host/src/ble_hs_conn_priv.h
+++ b/net/nimble/host/src/ble_hs_conn_priv.h
@@ -31,7 +31,6 @@ struct ble_l2cap_chan;
 typedef uint8_t ble_hs_conn_flags_t;
 
 #define BLE_HS_CONN_F_MASTER        0x01
-#define BLE_HS_CONN_F_UPDATE        0x02
 
 struct ble_hs_conn {
     SLIST_ENTRY(ble_hs_conn) bhc_next;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/ble_l2cap_sig.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig.c b/net/nimble/host/src/ble_l2cap_sig.c
index a382b09..7b92e14 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -213,7 +213,7 @@ ble_l2cap_sig_proc_matches(struct ble_l2cap_sig_proc *proc,
         return 0;
     }
 
-    if (id != proc->id) {
+    if (id != 0 && id != proc->id) {
         return 0;
     }
 
@@ -227,7 +227,8 @@ ble_l2cap_sig_proc_matches(struct ble_l2cap_sig_proc *proc,
  *
  * @param conn_handle           The connection handle to match against.
  * @param op                    The op code to match against.
- * @param identifier            The identifier to match against.
+ * @param identifier            The identifier to match against;
+ *                                  0=ignore this criterion.
  *
  * @return                      The matching proc entry on success;
  *                                  null on failure.
@@ -280,7 +281,7 @@ ble_l2cap_sig_update_call_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 
     if (proc->update.cb != NULL) {
-        proc->update.cb(status, proc->update.cb_arg);
+        proc->update.cb(proc->conn_handle, status, proc->update.cb_arg);
     }
 }
 
@@ -561,6 +562,24 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list)
     ble_hs_unlock();
 }
 
+void
+ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason)
+{
+    struct ble_l2cap_sig_proc *proc;
+
+    /* If there was a connection update in progress, indicate to the
+     * application that it did not complete.
+     */
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_UPDATE, 0);
+
+    if (proc != NULL) {
+        ble_l2cap_sig_update_call_cb(proc, reason);
+        ble_l2cap_sig_proc_free(proc);
+    }
+}
+
 /**
  * Applies periodic checks and actions to all active procedures.
  *
@@ -584,10 +603,13 @@ ble_l2cap_sig_heartbeat(void)
      */
     ble_l2cap_sig_extract_expired(&temp_list);
 
-    /* Terminate the connection associated with each timed-out procedure. */
-    STAILQ_FOREACH(proc, &temp_list, next) {
+    /* Report a failure for each timed out procedure. */
+    while ((proc = STAILQ_FIRST(&temp_list)) != NULL) {
         STATS_INC(ble_l2cap_stats, proc_timeout);
-        ble_gap_terminate(proc->conn_handle, BLE_ERR_REM_USER_CONN_TERM);
+        ble_l2cap_sig_update_call_cb(proc, BLE_HS_ETIMEOUT);
+
+        STAILQ_REMOVE_HEAD(&temp_list, next);
+        ble_l2cap_sig_proc_free(proc);
     }
 
     return BLE_HS_FOREVER;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/ble_l2cap_sig_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig_priv.h b/net/nimble/host/src/ble_l2cap_sig_priv.h
index 3477ee1..822b52b 100644
--- a/net/nimble/host/src/ble_l2cap_sig_priv.h
+++ b/net/nimble/host/src/ble_l2cap_sig_priv.h
@@ -80,6 +80,7 @@ int ble_l2cap_sig_reject_invalid_cid_tx(struct ble_hs_conn *conn,
                                         uint8_t id,
                                         uint16_t src_cid, uint16_t dst_cid);
 
+void ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason);
 int32_t ble_l2cap_sig_heartbeat(void);
 struct ble_l2cap_chan *ble_l2cap_sig_create_chan(void);
 int ble_l2cap_sig_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/test/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_gap_test.c b/net/nimble/host/src/test/ble_gap_test.c
index 5dd6532..2bbcfa9 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -41,16 +41,6 @@ static void *ble_gap_test_disc_arg;
  * $misc                                                                     *
  *****************************************************************************/
 
-static int
-ble_gap_test_util_update_in_progress(uint16_t conn_handle)
-{
-    ble_hs_conn_flags_t conn_flags;
-    int rc;
-
-    rc = ble_hs_atomic_conn_flags(conn_handle, &conn_flags);
-    return rc == 0 && conn_flags & BLE_HS_CONN_F_UPDATE;
-}
-
 static void
 ble_gap_test_util_reset_cb_info(void)
 {
@@ -344,7 +334,7 @@ ble_gap_test_util_verify_tx_params_reply_neg(uint8_t reason)
 static void
 ble_gap_test_util_rx_update_complete(
     uint8_t status,
-    struct ble_gap_upd_params *params)
+    const struct ble_gap_upd_params *params)
 {
     struct hci_le_conn_upd_complete evt;
 
@@ -1730,11 +1720,11 @@ TEST_SUITE(ble_gap_test_suite_stop_adv)
  *****************************************************************************/
 
 static void
-ble_gap_test_util_update(struct ble_gap_upd_params *params,
-                         int cmd_fail_idx, uint8_t hci_status,
-                         uint8_t event_status)
+ble_gap_test_util_update_no_l2cap(struct ble_gap_upd_params *params,
+                                  int master,
+                                  uint8_t hci_status, int event_status)
 {
-    int status;
+    struct ble_hs_conn *conn;
     int rc;
 
     uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
@@ -1744,6 +1734,19 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
     ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
                                  NULL);
 
+    if (!master) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find(2);
+        TEST_ASSERT_FATAL(conn != NULL);
+        conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+        ble_hs_unlock();
+    }
+
+    /* Erase callback info reported during connection establishment; we only
+     * care about updates.
+     */
+    ble_gap_test_util_reset_cb_info();
+
     TEST_ASSERT(!ble_gap_master_in_progress());
 
     rc = ble_hs_test_util_conn_update(2, params, hci_status);
@@ -1754,49 +1757,269 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
     ble_gap_test_util_verify_tx_update_conn(params);
 
     if (rc == 0) {
-        TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+        TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+        /* Receive connection update complete event. */
+        ble_gap_test_util_rx_update_complete(event_status, params);
+
+        TEST_ASSERT(!ble_gap_master_in_progress());
+        TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+        TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
+        TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(event_status));
+        if (event_status == 0) {
+            TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
+            TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+                               peer_addr, 6) == 0);
+            TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == params->itvl_max);
+            TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
+                        params->latency);
+            TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
+                        params->supervision_timeout);
+        }
     } else {
-        TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
-        return;
+        TEST_ASSERT(!ble_gap_master_in_progress());
+        TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+        TEST_ASSERT(ble_gap_test_event.type == 0xff);
     }
+}
 
-    /* Receive connection update complete event. */
-    ble_gap_test_util_rx_update_complete(event_status, params);
+static void
+ble_gap_test_util_update_l2cap(struct ble_gap_upd_params *params,
+                               uint8_t hci_status, int event_status,
+                               uint16_t l2cap_result)
+{
+    struct ble_l2cap_sig_update_params l2cap_params;
+    struct ble_hs_conn *conn;
+    uint8_t id;
+    int rc;
+
+    uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
 
-    if (event_status != 0) {
-        status = BLE_HS_HCI_ERR(event_status);
-        goto fail;
+    ble_gap_test_util_init();
+
+    ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+                                 NULL);
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+    ble_hs_unlock();
+
+    /* Erase callback info reported during connection establishment; we only
+     * care about updates.
+     */
+    ble_gap_test_util_reset_cb_info();
+
+    rc = ble_hs_test_util_conn_update(2, params, hci_status);
+    TEST_ASSERT(rc == 0);
+
+    /* Verify tx of connection update command. */
+    ble_gap_test_util_verify_tx_update_conn(params);
+
+    switch (hci_status) {
+    case 0:
+        /* Receive connection update complete event. */
+        ble_gap_test_util_rx_update_complete(event_status, params);
+        break;
+    case BLE_ERR_UNKNOWN_HCI_CMD:
+        break;
+    default:
+        TEST_ASSERT_FATAL(0);
+        break;
     }
 
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+    l2cap_params.itvl_min = params->itvl_min;
+    l2cap_params.itvl_max = params->itvl_max;
+    l2cap_params.slave_latency = params->latency;
+    l2cap_params.timeout_multiplier = params->supervision_timeout;
+    id = ble_hs_test_util_verify_tx_l2cap_update_req(&l2cap_params);
+
+    /* Receive l2cap connection parameter update response. */
+    ble_hs_test_util_rx_l2cap_update_rsp(2, id, l2cap_result);
+    if (l2cap_result == BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT) {
+        TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+        /* Receive connection update complete event. */
+        ble_gap_test_util_rx_update_complete(0, params);
+    }
+
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
+
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
+    if (l2cap_result != BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT) {
+        TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_EREJECT);
+    } else {
+        TEST_ASSERT(ble_gap_test_conn_status == 0);
+        TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == params->itvl_max);
+        TEST_ASSERT(ble_gap_test_conn_desc.conn_latency == params->latency);
+        TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
+                    params->supervision_timeout);
+    }
+
+    TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
+    TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
+                       peer_addr, 6) == 0);
+}
+
+static void
+ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
+                                      int master)
+{
+    struct ble_hs_conn *conn;
+    int rc;
+
+    uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+    ble_gap_test_util_init();
+
+    ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+                                 NULL);
+
+    if (!master) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find(2);
+        TEST_ASSERT_FATAL(conn != NULL);
+        conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+        ble_hs_unlock();
+    }
+
+    /* Erase callback info reported during connection establishment; we only
+     * care about updates.
+     */
+    ble_gap_test_util_reset_cb_info();
+
+    TEST_ASSERT(!ble_gap_master_in_progress());
+
+    rc = ble_hs_test_util_conn_update(2, params, 0);
+    TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
 
+    /* Verify tx of connection update command. */
+    ble_gap_test_util_verify_tx_update_conn(params);
+
+    /* Ensure no update event reported. */
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+    /* Advance 29 seconds; ensure no timeout reported. */
+    os_time_advance(29 * OS_TICKS_PER_SEC);
+    ble_gap_heartbeat();
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+    /* Advance 30th second; ensure timeout reported. */
+    os_time_advance(1 * OS_TICKS_PER_SEC);
+
+    /* Timeout will result in a terminate HCI command being sent; schedule ack
+     * from controller.
+     */
+    ble_hs_test_util_set_ack_disconnect(0);
+
+    ble_gap_heartbeat();
+
+    /* Verify terminate was sent. */
+    ble_gap_test_util_verify_tx_disconnect();
+
     TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
-    TEST_ASSERT(ble_gap_test_conn_status == 0);
+    TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
                        peer_addr, 6) == 0);
-    TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl == params->itvl_max);
-    TEST_ASSERT(ble_gap_test_conn_desc.conn_latency == params->latency);
-    TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
-        params->supervision_timeout);
+}
 
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+static void
+ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
+                                   uint8_t hci_status, uint8_t event_status,
+                                   int rx_l2cap)
+{
+    struct ble_l2cap_sig_update_params l2cap_params;
+    struct ble_hs_conn *conn;
+    uint8_t id;
+    int rc;
 
-    return;
+    uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+
+    ble_gap_test_util_init();
+
+    ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+                                 NULL);
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(2);
+    TEST_ASSERT_FATAL(conn != NULL);
+    conn->bhc_flags &= ~BLE_HS_CONN_F_MASTER;
+    ble_hs_unlock();
+
+    /* Erase callback info reported during connection establishment; we only
+     * care about updates.
+     */
+    ble_gap_test_util_reset_cb_info();
+
+    rc = ble_hs_test_util_conn_update(2, params, hci_status);
+    TEST_ASSERT(rc == 0);
+
+    /* Verify tx of connection update command. */
+    ble_gap_test_util_verify_tx_update_conn(params);
+
+    switch (hci_status) {
+    case 0:
+        /* Receive connection update complete event. */
+        ble_gap_test_util_rx_update_complete(event_status, params);
+        break;
+    case BLE_ERR_UNKNOWN_HCI_CMD:
+        break;
+    default:
+        TEST_ASSERT_FATAL(0);
+        break;
+    }
+
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+    if (rx_l2cap) {
+        l2cap_params.itvl_min = params->itvl_min;
+        l2cap_params.itvl_max = params->itvl_max;
+        l2cap_params.slave_latency = params->latency;
+        l2cap_params.timeout_multiplier = params->supervision_timeout;
+        id = ble_hs_test_util_verify_tx_l2cap_update_req(&l2cap_params);
+
+        /* Receive l2cap connection parameter update response. */
+        ble_hs_test_util_rx_l2cap_update_rsp(
+            2, id, BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+    }
+
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
+
+    /* Ensure no update event reported. */
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+    /* Advance 29 seconds; ensure no timeout reported. */
+    os_time_advance(29 * OS_TICKS_PER_SEC);
+    ble_gap_heartbeat();
+    ble_l2cap_sig_heartbeat();
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
+
+    /* Advance 30th second; ensure timeout reported. */
+    os_time_advance(1 * OS_TICKS_PER_SEC);
+
+    /* Timeout will result in a terminate HCI command being sent; schedule ack
+     * from controller.
+     */
+    ble_hs_test_util_set_ack_disconnect(0);
+
+    ble_gap_heartbeat();
+    ble_l2cap_sig_heartbeat();
+
+    /* Verify terminate was sent. */
+    ble_gap_test_util_verify_tx_disconnect();
 
-fail:
     TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
-    TEST_ASSERT(ble_gap_test_conn_status == status);
+    TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
                        peer_addr, 6) == 0);
-    TEST_ASSERT(ble_gap_test_conn_desc.conn_itvl ==
-                BLE_GAP_INITIAL_CONN_ITVL_MAX);
-    TEST_ASSERT(ble_gap_test_conn_desc.conn_latency ==
-                BLE_GAP_INITIAL_CONN_LATENCY);
-    TEST_ASSERT(ble_gap_test_conn_desc.supervision_timeout ==
-                BLE_GAP_INITIAL_SUPERVISION_TIMEOUT);
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
 }
 
 static void
@@ -1830,7 +2053,7 @@ ble_gap_test_util_update_peer(uint8_t status,
                     params->supervision_timeout);
     }
 
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 }
 
 static void
@@ -1858,19 +2081,21 @@ ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
         goto hci_fail;
     }
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+
+    /* We don't maintain an update entry when the peer initiates. */
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     /* Verify tx of connection parameters reply command. */
     ble_gap_test_util_verify_tx_params_reply_pos();
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     /* Receive connection update complete event. */
     ble_gap_test_util_rx_update_complete(0, self_params);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == 0);
@@ -1916,7 +2141,7 @@ ble_gap_test_util_update_req_neg(struct ble_gap_upd_params *peer_params,
                                  &reason);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     rc = ble_gap_test_util_rx_param_req(peer_params, 0, &cmd_idx, cmd_fail_idx,
                                         hci_status);
@@ -1924,13 +2149,13 @@ ble_gap_test_util_update_req_neg(struct ble_gap_upd_params *peer_params,
         goto hci_fail;
     }
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     /* Verify tx of connection parameters negative reply command. */
     ble_gap_test_util_verify_tx_params_reply_neg(reason);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     return;
 
@@ -1968,7 +2193,7 @@ ble_gap_test_util_update_req_concurrent(
                                  NULL);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     hci_status = cmd_fail_idx == 0 ? fail_status : 0;
     rc = ble_hs_test_util_conn_update(2, init_params, hci_status);
@@ -1980,14 +2205,14 @@ ble_gap_test_util_update_req_concurrent(
     ble_gap_test_util_verify_tx_update_conn(init_params);
 
     if (rc == 0) {
-        TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+        TEST_ASSERT(ble_gap_dbg_update_active(2));
     } else {
-        TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+        TEST_ASSERT(!ble_gap_dbg_update_active(2));
         return;
     }
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
 
     /* Receive connection parameter update request from peer. */
     ble_gap_test_conn_self_params = *self_params;
@@ -1997,19 +2222,19 @@ ble_gap_test_util_update_req_concurrent(
         goto hci_fail;
     }
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
 
     /* Verify tx of connection parameters reply command. */
     ble_gap_test_util_verify_tx_params_reply_pos();
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(ble_gap_dbg_update_active(2));
 
     /* Receive connection update complete event. */
     ble_gap_test_util_rx_update_complete(0, self_params);
 
     TEST_ASSERT(!ble_gap_master_in_progress());
-    TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
+    TEST_ASSERT(!ble_gap_dbg_update_active(2));
 
     TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == 0);
@@ -2039,7 +2264,7 @@ hci_fail:
 
 TEST_CASE(ble_gap_test_case_update_conn_good)
 {
-    ble_gap_test_util_update(
+    ble_gap_test_util_update_no_l2cap(
         ((struct ble_gap_upd_params[]) { {
             .itvl_min = 10,
             .itvl_max = 100,
@@ -2047,9 +2272,9 @@ TEST_CASE(ble_gap_test_case_update_conn_good)
             .min_ce_len = 123,
             .max_ce_len = 456,
         }}),
-        -1, 0, 0);
+        1, 0, 0);
 
-    ble_gap_test_util_update(
+    ble_gap_test_util_update_no_l2cap(
         ((struct ble_gap_upd_params[]) { {
             .itvl_min = 100,
             .itvl_max = 100,
@@ -2057,12 +2282,12 @@ TEST_CASE(ble_gap_test_case_update_conn_good)
             .min_ce_len = 554,
             .max_ce_len = 554,
         }}),
-        -1, 0, 0);
+        1, 0, 0);
 }
 
 TEST_CASE(ble_gap_test_case_update_conn_bad)
 {
-    ble_gap_test_util_update(
+    ble_gap_test_util_update_no_l2cap(
         ((struct ble_gap_upd_params[]) { {
             .itvl_min = 10,
             .itvl_max = 100,
@@ -2070,12 +2295,12 @@ TEST_CASE(ble_gap_test_case_update_conn_bad)
             .min_ce_len = 123,
             .max_ce_len = 456,
         }}),
-        -1, 0, BLE_ERR_LMP_COLLISION);
+        1, 0, BLE_ERR_LMP_COLLISION);
 }
 
 TEST_CASE(ble_gap_test_case_update_conn_hci_fail)
 {
-    ble_gap_test_util_update(
+    ble_gap_test_util_update_no_l2cap(
         ((struct ble_gap_upd_params[]) { {
             .itvl_min = 10,
             .itvl_max = 100,
@@ -2083,7 +2308,39 @@ TEST_CASE(ble_gap_test_case_update_conn_hci_fail)
             .min_ce_len = 123,
             .max_ce_len = 456,
         }}),
-        0, BLE_ERR_UNSUPPORTED, 0);
+        1, BLE_ERR_UNSUPPORTED, 0);
+}
+
+TEST_CASE(ble_gap_test_case_update_conn_l2cap)
+{
+    struct ble_gap_upd_params params = {
+        .itvl_min = 10,
+        .itvl_max = 100,
+        .supervision_timeout = 0,
+        .min_ce_len = 123,
+        .max_ce_len = 456,
+    };
+
+    /* Accepted L2CAP failover; success. */
+    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0,
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+
+    /* Accepted L2CAP failover; failure. */
+    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_ACCEPT);
+
+    /* Rejected L2CAP failovers. */
+    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT);
+    ble_gap_test_util_update_l2cap(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+                                   BLE_L2CAP_SIG_UPDATE_RSP_RESULT_REJECT);
+
+    /* Don't attempt L2CAP failover on other event status. */
+    ble_gap_test_util_update_l2cap(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
 }
 
 TEST_CASE(ble_gap_test_case_update_peer_good)
@@ -2142,7 +2399,6 @@ TEST_CASE(ble_gap_test_case_update_req_good)
             .max_ce_len = 554,
         }}),
         -1, 0);
-
 }
 
 TEST_CASE(ble_gap_test_case_update_req_hci_fail)
@@ -2297,6 +2553,7 @@ TEST_SUITE(ble_gap_test_suite_update_conn)
     ble_gap_test_case_update_conn_good();
     ble_gap_test_case_update_conn_bad();
     ble_gap_test_case_update_conn_hci_fail();
+    ble_gap_test_case_update_conn_l2cap();
     ble_gap_test_case_update_peer_good();
     ble_gap_test_case_update_req_good();
     ble_gap_test_case_update_req_hci_fail();
@@ -2454,6 +2711,34 @@ ble_gap_test_util_disc_timeout(int32_t duration_ms)
     ble_gap_test_util_reset_cb_info();
 }
 
+TEST_CASE(ble_gap_test_case_update_timeout)
+{
+    struct ble_gap_upd_params params = {
+        .itvl_min = 10,
+        .itvl_max = 100,
+        .supervision_timeout = 0,
+        .min_ce_len = 123,
+        .max_ce_len = 456,
+    };
+
+    /* No L2CAP. */
+    ble_gap_test_util_update_no_l2cap_tmo(&params, 1);
+
+    /* L2CAP - Local unsupported; L2CAP timeout. */
+    ble_gap_test_util_update_l2cap_tmo(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 0);
+
+    /* L2CAP - Local unsupported; LL timeout. */
+    ble_gap_test_util_update_l2cap_tmo(&params, BLE_ERR_UNKNOWN_HCI_CMD, 0, 1);
+
+    /* L2CAP - Remote unsupported; L2CAP timeout. */
+    ble_gap_test_util_update_l2cap_tmo(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+                                       0);
+
+    /* L2CAP - Remote unsupported; LL timeout. */
+    ble_gap_test_util_update_l2cap_tmo(&params, 0, BLE_ERR_UNSUPP_REM_FEATURE,
+                                       1);
+}
+
 TEST_CASE(ble_gap_test_case_conn_timeout_conn_forever)
 {
     ble_gap_test_util_init();
@@ -2557,6 +2842,8 @@ TEST_SUITE(ble_gap_test_suite_timeout)
     ble_gap_test_case_disc_forever_disc_timeout();
 
     ble_gap_test_case_conn_timeout_disc_timeout();
+
+    ble_gap_test_case_update_timeout();
 }
 
 TEST_CASE(ble_gap_test_case_mtu_us)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/test/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.c b/net/nimble/host/src/test/ble_hs_test_util.c
index e1acb81..f30f65e 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -548,16 +548,21 @@ ble_hs_test_util_conn_cancel_full(void)
     TEST_ASSERT_FATAL(rc == 0);
 }
 
-int
-ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status)
+void
+ble_hs_test_util_set_ack_disconnect(uint8_t hci_status)
 {
-    int rc;
-
     ble_hs_test_util_set_ack(
         ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LINK_CTRL,
                                     BLE_HCI_OCF_DISCONNECT_CMD),
         hci_status);
+}
 
+int
+ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status)
+{
+    int rc;
+
+    ble_hs_test_util_set_ack_disconnect(hci_status);
     rc = ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM);
     return rc;
 }
@@ -1208,6 +1213,105 @@ ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
     TEST_ASSERT(rsp.baep_error_code == error_code);
 }
 
+static struct os_mbuf *
+ble_hs_test_util_verify_tx_l2cap_sig_hdr(uint8_t op, uint8_t id,
+                                   uint16_t payload_len,
+                                   struct ble_l2cap_sig_hdr *out_hdr)
+{
+    struct ble_l2cap_sig_hdr hdr;
+    struct os_mbuf *om;
+
+    om = ble_hs_test_util_prev_tx_dequeue();
+    TEST_ASSERT_FATAL(om != NULL);
+
+    TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_L2CAP_SIG_HDR_SZ + payload_len);
+    ble_l2cap_sig_hdr_parse(om->om_data, om->om_len, &hdr);
+    TEST_ASSERT(hdr.op == op);
+    if (id != 0) {
+        TEST_ASSERT(hdr.identifier == id);
+    }
+    TEST_ASSERT(hdr.length == payload_len);
+
+    om->om_data += BLE_L2CAP_SIG_HDR_SZ;
+    om->om_len -= BLE_L2CAP_SIG_HDR_SZ;
+
+    if (out_hdr != NULL) {
+        *out_hdr = hdr;
+    }
+
+    return om;
+}
+
+/**
+ * @return                      The L2CAP sig identifier in the request.
+ */
+uint8_t
+ble_hs_test_util_verify_tx_l2cap_update_req(
+    struct ble_l2cap_sig_update_params *params)
+{
+    struct ble_l2cap_sig_update_req req;
+    struct ble_l2cap_sig_hdr hdr;
+    struct os_mbuf *om;
+
+    ble_hs_test_util_tx_all();
+
+    om = ble_hs_test_util_verify_tx_l2cap_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_REQ,
+                                                  0,
+                                                  BLE_L2CAP_SIG_UPDATE_REQ_SZ,
+                                                  &hdr);
+
+    /* Verify payload. */
+    ble_l2cap_sig_update_req_parse(om->om_data, om->om_len, &req);
+    TEST_ASSERT(req.itvl_min == params->itvl_min);
+    TEST_ASSERT(req.itvl_max == params->itvl_max);
+    TEST_ASSERT(req.slave_latency == params->slave_latency);
+    TEST_ASSERT(req.timeout_multiplier == params->timeout_multiplier);
+
+    return hdr.identifier;
+}
+
+int
+ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle,
+                                     uint8_t id, uint16_t result)
+{
+    struct ble_l2cap_sig_update_rsp rsp;
+    struct hci_data_hdr hci_hdr;
+    struct os_mbuf *om;
+    void *v;
+    int rc;
+
+    hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(
+        2, BLE_HCI_PB_FIRST_FLUSH,
+        BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
+
+    rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_UPDATE_RSP, id,
+                                BLE_L2CAP_SIG_UPDATE_RSP_SZ, &om, &v);
+    TEST_ASSERT_FATAL(rc == 0);
+
+    rsp.result = result;
+    ble_l2cap_sig_update_rsp_write(v, BLE_L2CAP_SIG_UPDATE_RSP_SZ, &rsp);
+
+    rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG,
+                                              &hci_hdr, om);
+    return rc;
+}
+
+void
+ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id,
+                                            uint16_t exp_result)
+{
+    struct ble_l2cap_sig_update_rsp rsp;
+    struct os_mbuf *om;
+
+    om = ble_hs_test_util_verify_tx_l2cap_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_RSP,
+                                            exp_id,
+                                            BLE_L2CAP_SIG_UPDATE_RSP_SZ,
+                                            NULL);
+
+    ble_l2cap_sig_update_rsp_parse(om->om_data, om->om_len, &rsp);
+    TEST_ASSERT(rsp.result == exp_result);
+}
+
 void
 ble_hs_test_util_set_static_rnd_addr(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/test/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_test_util.h b/net/nimble/host/src/test/ble_hs_test_util.h
index 7780d4e..0974a9a 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -50,6 +50,13 @@ struct ble_hs_test_util_mbuf_params {
     unsigned prep_list:1;
 };
 
+#define BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(handle, pb, len) \
+    ((struct hci_data_hdr) {                            \
+        .hdh_handle_pb_bc = ((handle)  << 0) |          \
+                            ((pb)      << 12),          \
+        .hdh_len = (len)                                \
+    })
+
 void ble_hs_test_util_prev_tx_enqueue(struct os_mbuf *om);
 struct os_mbuf *ble_hs_test_util_prev_tx_dequeue(void);
 struct os_mbuf *ble_hs_test_util_prev_tx_dequeue_pullup(void);
@@ -87,6 +94,7 @@ int ble_hs_test_util_connect(uint8_t own_addr_type,
                                    uint8_t ack_status);
 int ble_hs_test_util_conn_cancel(uint8_t ack_status);
 void ble_hs_test_util_conn_cancel_full(void);
+void ble_hs_test_util_set_ack_disconnect(uint8_t hci_status);
 int ble_hs_test_util_conn_terminate(uint16_t conn_handle, uint8_t hci_status);
 void ble_hs_test_util_conn_disconnect(uint16_t conn_handle);
 int ble_hs_test_util_exp_hci_status(int cmd_idx, int fail_idx,
@@ -148,6 +156,12 @@ void ble_hs_test_util_verify_tx_write_rsp(void);
 void ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu);
 void ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
                                         uint8_t error_code);
+uint8_t ble_hs_test_util_verify_tx_l2cap_update_req(
+    struct ble_l2cap_sig_update_params *params);
+int ble_hs_test_util_rx_l2cap_update_rsp(uint16_t conn_handle,
+                                         uint8_t id, uint16_t result);
+void ble_hs_test_util_verify_tx_l2cap_update_rsp(uint8_t exp_id,
+                                                 uint16_t exp_result);
 void ble_hs_test_util_set_static_rnd_addr(void);
 struct os_mbuf *ble_hs_test_util_om_from_flat(const void *buf, uint16_t len);
 int ble_hs_test_util_flat_attr_cmp(const struct ble_hs_test_util_flat_attr *a,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/f77bf7fc/net/nimble/host/src/test/ble_l2cap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_l2cap_test.c b/net/nimble/host/src/test/ble_l2cap_test.c
index 69db2f8..9410b3d 100644
--- a/net/nimble/host/src/test/ble_l2cap_test.c
+++ b/net/nimble/host/src/test/ble_l2cap_test.c
@@ -26,6 +26,7 @@
 
 #define BLE_L2CAP_TEST_CID  99
 
+static uint16_t ble_l2cap_test_update_conn_handle;
 static int ble_l2cap_test_update_status;
 static void *ble_l2cap_test_update_arg;
 
@@ -33,17 +34,11 @@ static void *ble_l2cap_test_update_arg;
  * $util                                                                     *
  *****************************************************************************/
 
-#define BLE_L2CAP_TEST_UTIL_HCI_HDR(handle, pb, len)    \
-    ((struct hci_data_hdr) {                            \
-        .hdh_handle_pb_bc = ((handle)  << 0) |          \
-                            ((pb)      << 12),          \
-        .hdh_len = (len)                                \
-    })
-
 static void
 ble_l2cap_test_util_init(void)
 {
     ble_hs_test_util_init();
+    ble_l2cap_test_update_conn_handle = BLE_HS_CONN_HANDLE_NONE;
     ble_l2cap_test_update_status = -1;
     ble_l2cap_test_update_arg = (void *)(uintptr_t)-1;
 }
@@ -58,7 +53,7 @@ ble_l2cap_test_util_rx_update_req(uint16_t conn_handle, uint8_t id,
     void *v;
     int rc;
 
-    hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(
+    hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(
         2, BLE_HCI_PB_FIRST_FLUSH,
         BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_REQ_SZ);
 
@@ -80,102 +75,6 @@ ble_l2cap_test_util_rx_update_req(uint16_t conn_handle, uint8_t id,
     TEST_ASSERT_FATAL(rc == 0);
 }
 
-static int
-ble_l2cap_test_util_rx_update_rsp(uint16_t conn_handle,
-                                  uint8_t id, uint16_t result)
-{
-    struct ble_l2cap_sig_update_rsp rsp;
-    struct hci_data_hdr hci_hdr;
-    struct os_mbuf *om;
-    void *v;
-    int rc;
-
-    hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(
-        2, BLE_HCI_PB_FIRST_FLUSH,
-        BLE_L2CAP_HDR_SZ + BLE_L2CAP_SIG_HDR_SZ + BLE_L2CAP_SIG_UPDATE_RSP_SZ);
-
-    rc = ble_l2cap_sig_init_cmd(BLE_L2CAP_SIG_OP_UPDATE_RSP, id,
-                                BLE_L2CAP_SIG_UPDATE_RSP_SZ, &om, &v);
-    TEST_ASSERT_FATAL(rc == 0);
-
-    rsp.result = result;
-    ble_l2cap_sig_update_rsp_write(v, BLE_L2CAP_SIG_UPDATE_RSP_SZ, &rsp);
-
-    rc = ble_hs_test_util_l2cap_rx_first_frag(conn_handle, BLE_L2CAP_CID_SIG,
-                                              &hci_hdr, om);
-    return rc;
-}
-
-
-static struct os_mbuf *
-ble_l2cap_test_util_verify_tx_sig_hdr(uint8_t op, uint8_t id,
-                                      uint16_t payload_len,
-                                      struct ble_l2cap_sig_hdr *out_hdr)
-{
-    struct ble_l2cap_sig_hdr hdr;
-    struct os_mbuf *om;
-
-    om = ble_hs_test_util_prev_tx_dequeue();
-    TEST_ASSERT_FATAL(om != NULL);
-
-    TEST_ASSERT(OS_MBUF_PKTLEN(om) == BLE_L2CAP_SIG_HDR_SZ + payload_len);
-    ble_l2cap_sig_hdr_parse(om->om_data, om->om_len, &hdr);
-    TEST_ASSERT(hdr.op == op);
-    if (id != 0) {
-        TEST_ASSERT(hdr.identifier == id);
-    }
-    TEST_ASSERT(hdr.length == payload_len);
-
-    om->om_data += BLE_L2CAP_SIG_HDR_SZ;
-    om->om_len -= BLE_L2CAP_SIG_HDR_SZ;
-
-    if (out_hdr != NULL) {
-        *out_hdr = hdr;
-    }
-
-    return om;
-}
-
-/**
- * @return                      The L2CAP sig identifier in the request.
- */
-static uint8_t
-ble_l2cap_test_util_verify_tx_update_req(
-    struct ble_l2cap_sig_update_params *params)
-{
-    struct ble_l2cap_sig_update_req req;
-    struct ble_l2cap_sig_hdr hdr;
-    struct os_mbuf *om;
-
-    om = ble_l2cap_test_util_verify_tx_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_REQ, 0,
-                                               BLE_L2CAP_SIG_UPDATE_REQ_SZ,
-                                               &hdr);
-
-    /* Verify payload. */
-    ble_l2cap_sig_update_req_parse(om->om_data, om->om_len, &req);
-    TEST_ASSERT(req.itvl_min == params->itvl_min);
-    TEST_ASSERT(req.itvl_max == params->itvl_max);
-    TEST_ASSERT(req.slave_latency == params->slave_latency);
-    TEST_ASSERT(req.timeout_multiplier == params->timeout_multiplier);
-
-    return hdr.identifier;
-}
-
-static void
-ble_l2cap_test_util_verify_tx_update_rsp(uint8_t exp_id, uint16_t exp_result)
-{
-    struct ble_l2cap_sig_update_rsp rsp;
-    struct os_mbuf *om;
-
-    om = ble_l2cap_test_util_verify_tx_sig_hdr(BLE_L2CAP_SIG_OP_UPDATE_RSP,
-                                               exp_id,
-                                               BLE_L2CAP_SIG_UPDATE_RSP_SZ,
-                                               NULL);
-
-    ble_l2cap_sig_update_rsp_parse(om->om_data, om->om_len, &rsp);
-    TEST_ASSERT(rsp.result == exp_result);
-}
-
 static void
 ble_l2cap_test_util_verify_tx_update_conn(
     struct ble_gap_upd_params *params)
@@ -252,7 +151,7 @@ ble_l2cap_test_util_rx_first_frag(uint16_t conn_handle,
     TEST_ASSERT_FATAL(om != NULL);
 
     hci_len = sizeof hci_hdr + l2cap_frag_len;
-    hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(conn_handle,
+    hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle,
                                           BLE_HCI_PB_FIRST_FLUSH, hci_len);
     rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om);
     return rc;
@@ -272,7 +171,7 @@ ble_l2cap_test_util_rx_next_frag(uint16_t conn_handle, uint16_t hci_len)
     v = os_mbuf_extend(om, hci_len);
     TEST_ASSERT_FATAL(v != NULL);
 
-    hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(conn_handle,
+    hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(conn_handle,
                                           BLE_HCI_PB_MIDDLE, hci_len);
     rc = ble_hs_test_util_l2cap_rx(conn_handle, &hci_hdr, om);
     return rc;
@@ -372,7 +271,7 @@ TEST_CASE(ble_l2cap_test_case_frag_single)
                                     NULL, NULL);
 
     /*** HCI header specifies middle fragment without start. */
-    hci_hdr = BLE_L2CAP_TEST_UTIL_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
+    hci_hdr = BLE_HS_TEST_UTIL_L2CAP_HCI_HDR(2, BLE_HCI_PB_MIDDLE, 10);
 
     om = ble_hs_mbuf_l2cap_pkt();
     TEST_ASSERT_FATAL(om != NULL);
@@ -467,7 +366,7 @@ TEST_CASE(ble_l2cap_test_case_sig_unsol_rsp)
                                     NULL, NULL);
 
     /* Receive an unsolicited response. */
-    rc = ble_l2cap_test_util_rx_update_rsp(2, 100, 0);
+    rc = ble_hs_test_util_rx_l2cap_update_rsp(2, 100, 0);
     TEST_ASSERT(rc == BLE_HS_ENOENT);
 
     /* Ensure we did not send anything in return. */
@@ -499,8 +398,6 @@ ble_l2cap_test_util_peer_updates(int accept)
 {
     struct ble_l2cap_sig_update_params l2cap_params;
     struct ble_gap_upd_params params;
-    ble_hs_conn_flags_t conn_flags;
-    int rc;
 
     ble_l2cap_test_util_init();
 
@@ -516,7 +413,7 @@ ble_l2cap_test_util_peer_updates(int accept)
 
     /* Ensure an update response command got sent. */
     ble_hs_process_tx_data_queue();
-    ble_l2cap_test_util_verify_tx_update_rsp(1, !accept);
+    ble_hs_test_util_verify_tx_l2cap_update_rsp(1, !accept);
 
     if (accept) {
         params.itvl_min = 0x200;
@@ -528,14 +425,14 @@ ble_l2cap_test_util_peer_updates(int accept)
         ble_l2cap_test_util_verify_tx_update_conn(&params);
     } else {
         /* Ensure no update got scheduled. */
-        rc = ble_hs_atomic_conn_flags(2, &conn_flags);
-        TEST_ASSERT(rc == 0 && !(conn_flags & BLE_HS_CONN_F_UPDATE));
+        TEST_ASSERT(!ble_gap_dbg_update_active(2));
     }
 }
 
 static void
-ble_l2cap_test_util_update_cb(int status, void *arg)
+ble_l2cap_test_util_update_cb(uint16_t conn_handle, int status, void *arg)
 {
+    ble_l2cap_test_update_conn_handle = conn_handle;
     ble_l2cap_test_update_status = status;
     ble_l2cap_test_update_arg = arg;
 }
@@ -565,10 +462,10 @@ ble_l2cap_test_util_we_update(int peer_accepts)
     ble_hs_test_util_tx_all();
 
     /* Ensure an update request got sent. */
-    id = ble_l2cap_test_util_verify_tx_update_req(&params);
+    id = ble_hs_test_util_verify_tx_l2cap_update_req(&params);
 
     /* Receive response from peer. */
-    rc = ble_l2cap_test_util_rx_update_rsp(2, id, !peer_accepts);
+    rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, !peer_accepts);
     TEST_ASSERT(rc == 0);
 
     /* Ensure callback got called. */
@@ -646,17 +543,17 @@ TEST_CASE(ble_l2cap_test_case_sig_update_init_fail_bad_id)
     ble_hs_test_util_tx_all();
 
     /* Ensure an update request got sent. */
-    id = ble_l2cap_test_util_verify_tx_update_req(&params);
+    id = ble_hs_test_util_verify_tx_l2cap_update_req(&params);
 
     /* Receive response from peer with incorrect ID. */
-    rc = ble_l2cap_test_util_rx_update_rsp(2, id + 1, 0);
+    rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id + 1, 0);
     TEST_ASSERT(rc == BLE_HS_ENOENT);
 
     /* Ensure callback did not get called. */
     TEST_ASSERT(ble_l2cap_test_update_status == -1);
 
     /* Receive response from peer with correct ID. */
-    rc = ble_l2cap_test_util_rx_update_rsp(2, id, 0);
+    rc = ble_hs_test_util_rx_l2cap_update_rsp(2, id, 0);
     TEST_ASSERT(rc == 0);
 
     /* Ensure callback got called. */


[03/19] incubator-mynewt-core git commit: MYNEWT-385: Controller not sending connection update complete event

Posted by cc...@apache.org.
MYNEWT-385: Controller not sending connection update complete event

The nimble controller was not sending the connection update
complete event if the connection was a slave, the host initiated
the connection parameter request and only an anchor point move was
requested. The spec is not perfectly clear but it seems this was a
bug and that the host should always be notified if it initiates
the connection update or connection parameter request.


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

Branch: refs/heads/develop
Commit: 97189e716b11ab59599a7693e838f9ccf51c071f
Parents: f77bf7f
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Sep 6 14:15:28 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Tue Sep 6 14:17:28 2016 -0700

----------------------------------------------------------------------
 net/nimble/controller/src/ble_ll_conn.c | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/97189e71/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 38220ea..f8d21cd 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1663,6 +1663,8 @@ ble_ll_conn_next_event(struct ble_ll_conn_sm *connsm)
         /* Set flag so we send connection update event */
         upd = &connsm->conn_update_req;
         if ((connsm->conn_role == BLE_LL_CONN_ROLE_MASTER)  ||
+            ((connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) &&
+             IS_PENDING_CTRL_PROC(connsm, BLE_LL_CTRL_PROC_CONN_PARAM_REQ)) ||
             (connsm->conn_itvl != upd->interval)            ||
             (connsm->slave_latency != upd->latency)         ||
             (connsm->supervision_tmo != upd->timeout)) {


[04/19] incubator-mynewt-core git commit: MYNEWT-382: Controller number of completed packets event changes

Posted by cc...@apache.org.
MYNEWT-382: Controller number of completed packets event changes

The controller will now send a completed packets event when a
connection event ends and there is at least one completed
packet. The NIMBLE_OPT_NUM_COMP_PKT_RATE is still in the code but
its only real purpose now is to periodically send the number of
completed packet events when a connection has data buffers in its
transmit queue but the packets are not completing. The spec
requires the controller to periodically inform the host in this
case.


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

Branch: refs/heads/develop
Commit: 8559e07f83c48d4749a5f1e710d7843fcd8a83fe
Parents: 97189e7
Author: William San Filippo <wi...@runtime.io>
Authored: Fri Sep 9 12:38:38 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Fri Sep 9 12:51:08 2016 -0700

----------------------------------------------------------------------
 net/nimble/controller/src/ble_ll_conn.c      |  4 +--
 net/nimble/controller/src/ble_ll_conn_hci.c  | 38 ++++++++++++++++++-----
 net/nimble/controller/src/ble_ll_conn_priv.h |  2 +-
 net/nimble/include/nimble/nimble_opt.h       | 18 +++++++++--
 4 files changed, 47 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8559e07f/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 f8d21cd..642e8c6 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -1937,9 +1937,7 @@ ble_ll_conn_event_end(void *arg)
     }
 
     /* If we have completed packets, send an event */
-    if (connsm->completed_pkts) {
-        ble_ll_conn_num_comp_pkts_event_send();
-    }
+    ble_ll_conn_num_comp_pkts_event_send(connsm);
 }
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8559e07f/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 d7001f8..5d44d27 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -38,7 +38,7 @@
  * Used to limit the rate at which we send the number of completed packets
  * event to the host. This is the os time at which we can send an event.
  */
-static uint32_t g_ble_ll_next_num_comp_pkt_evt;
+static uint32_t g_ble_ll_last_num_comp_pkt_evt;
 
 /**
  * Called to check that the connection parameters are within range
@@ -216,7 +216,7 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
  * to make it contiguous with the handles.
  */
 void
-ble_ll_conn_num_comp_pkts_event_send(void)
+ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm)
 {
     /** The maximum number of handles that will fit in an event buffer. */
     static const int max_handles =
@@ -227,11 +227,33 @@ ble_ll_conn_num_comp_pkts_event_send(void)
     uint8_t *handle_ptr;
     uint8_t *comp_pkt_ptr;
     uint8_t handles;
-    struct ble_ll_conn_sm *connsm;
 
-    /* Check rate limit */
-    if ((uint32_t)(g_ble_ll_next_num_comp_pkt_evt - os_time_get()) <
-         NIMBLE_OPT_NUM_COMP_PKT_RATE) {
+    /*
+     * At some periodic rate, make sure we go through all active connections
+     * and send the number of completed packet events. We do this mainly
+     * because the spec says we must update the host even though no packets
+     * have completed by there are data packets in the controller buffers
+     * (i.e. enqueued in a connection state machine).
+     */
+    if ((uint32_t)(g_ble_ll_last_num_comp_pkt_evt - os_time_get()) <
+         (NIMBLE_OPT_NUM_COMP_PKT_RATE * OS_TICKS_PER_SEC)) {
+        /*
+         * If this connection has completed packets, send an event right away.
+         * We do this to increase throughput but we dont want to search the
+         * entire active list every time.
+         */
+        if (connsm->completed_pkts) {
+            evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+            if (evbuf) {
+                evbuf[0] = BLE_HCI_EVCODE_NUM_COMP_PKTS;
+                evbuf[1] = (2 * sizeof(uint16_t)) + 1;
+                evbuf[2] = 1;
+                htole16(evbuf + 3, connsm->conn_handle);
+                htole16(evbuf + 5, connsm->completed_pkts);
+                ble_ll_hci_event_send(evbuf);
+                connsm->completed_pkts = 0;
+            }
+        }
         return;
     }
 
@@ -294,8 +316,8 @@ ble_ll_conn_num_comp_pkts_event_send(void)
     }
 
     if (event_sent) {
-        g_ble_ll_next_num_comp_pkt_evt = os_time_get() +
-            NIMBLE_OPT_NUM_COMP_PKT_RATE;
+        g_ble_ll_last_num_comp_pkt_evt = os_time_get() +
+            (NIMBLE_OPT_NUM_COMP_PKT_RATE * OS_TICKS_PER_SEC);
     }
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8559e07f/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 fc06e5f..b8c4fa1 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -132,7 +132,7 @@ int ble_ll_conn_hci_update(uint8_t *cmdbuf);
 int ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf);
 int ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int negative_reply);
 int ble_ll_conn_create_cancel(void);
-void ble_ll_conn_num_comp_pkts_event_send(void);
+void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
 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);
 int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/8559e07f/net/nimble/include/nimble/nimble_opt.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/nimble_opt.h b/net/nimble/include/nimble/nimble_opt.h
index 859b0aa..db4f38b 100644
--- a/net/nimble/include/nimble/nimble_opt.h
+++ b/net/nimble/include/nimble/nimble_opt.h
@@ -253,11 +253,23 @@
 #endif
 
 /*
- * Determines the maximum rate at which the controller will send the
- * number of completed packets event to the host. Rate is in os time ticks
+ * Timeout used by the controller when determining if a number of completed
+ * packets event should be sent to the host if there are data buffers in the
+ * controller that have not completed.
+ *
+ * NOTE:  the controller attempts to send the number of completed packets
+ * event after each connection event in which a packet was completed. This
+ * means that the host should expect that event at a rate much faster than
+ * defined here (assuming packets are being sent and the connection interval
+ * is shorter than the rate defined here). Thus, this definition exists in
+ * order to satisfy the spec requirement to notify the host (at some
+ * manufacturer specified rate) when the controller has data buffers that
+ * have not completed.
+ *
+ * This rate is in seconds.
  */
 #ifndef NIMBLE_OPT_NUM_COMP_PKT_RATE
-#define NIMBLE_OPT_NUM_COMP_PKT_RATE    ((2000 * OS_TICKS_PER_SEC) / 1000)
+#define NIMBLE_OPT_NUM_COMP_PKT_RATE            (10)
 #endif
 
 /* Manufacturer ID. Should be set to unique ID per manufacturer */


[06/19] incubator-mynewt-core git commit: MYNEWT-386: Controller should always send connection complete event

Posted by cc...@apache.org.
MYNEWT-386: Controller should always send connection complete event

The following changes were made to insure that the controller will
always send a connection complete event to the host. When either
a connection create command is sent or a start advertising command
is sent, the controller will attempt to allocate an event buffer
with which to send the connection complete event. If this fails,
the controller will return an error: BLE_ERR_MEM_CAPACITY. If
this succeeds, the controller will then be able to send the
connection complete event to the host.


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

Branch: refs/heads/develop
Commit: 840bb64710b0f576fd39f21ad9dcd62c6fcb322b
Parents: 20e2f38
Author: William San Filippo <wi...@runtime.io>
Authored: Mon Sep 12 11:20:13 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Mon Sep 12 11:25:21 2016 -0700

----------------------------------------------------------------------
 apps/bletest/src/main.c                         |  20 ++-
 .../controller/include/controller/ble_ll_adv.h  |   3 +
 net/nimble/controller/src/ble_ll_adv.c          |  51 +++++++-
 net/nimble/controller/src/ble_ll_conn.c         |  40 +++++-
 net/nimble/controller/src/ble_ll_conn_hci.c     | 130 +++++++++++--------
 net/nimble/controller/src/ble_ll_conn_priv.h    |   3 +-
 6 files changed, 186 insertions(+), 61 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index d21cc50..066d52e 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -113,7 +113,7 @@ os_membuf_t g_mbuf_buffer[MBUF_MEMPOOL_SIZE];
 #define BLETEST_CFG_ADV_ITVL            (60000 / BLE_HCI_ADV_ITVL)
 #define BLETEST_CFG_ADV_TYPE            BLE_HCI_ADV_TYPE_ADV_IND
 #define BLETEST_CFG_ADV_FILT_POLICY     (BLE_HCI_ADV_FILT_NONE)
-#define BLETEST_CFG_ADV_ADDR_RES_EN     (1)
+#define BLETEST_CFG_ADV_ADDR_RES_EN     (0)
 
 /* Scan config */
 #define BLETEST_CFG_SCAN_ITVL           (700000 / BLE_HCI_SCAN_ITVL)
@@ -170,6 +170,7 @@ uint16_t g_bletest_completed_pkts;
 uint16_t g_bletest_outstanding_pkts;
 uint16_t g_bletest_ltk_reply_handle;
 uint32_t g_bletest_hw_id[4];
+struct hci_create_conn g_cc;
 
 /* --- For LE encryption testing --- */
 /* Key: 0x4C68384139F574D836BCF34E9DFB01BF */
@@ -482,11 +483,10 @@ bletest_init_initiator(void)
 {
     int rc;
     uint8_t rand_addr[BLE_DEV_ADDR_LEN];
-    struct hci_create_conn cc;
     struct hci_create_conn *hcc;
 
     /* Enable initiating */
-    hcc = &cc;
+    hcc = &g_cc;
     hcc->conn_itvl_max = BLETEST_CFG_CONN_ITVL;
     hcc->conn_itvl_min = BLETEST_CFG_CONN_ITVL;
     hcc->conn_latency = BLETEST_CFG_SLAVE_LATENCY;
@@ -529,8 +529,7 @@ bletest_init_initiator(void)
         }
 #endif
 
-    rc = bletest_hci_le_create_connection(hcc);
-    assert(rc == 0);
+    bletest_hci_le_create_connection(hcc);
 }
 
 void
@@ -573,6 +572,10 @@ bletest_execute_initiator(void)
                     bletest_init_initiator();
                 }
             }
+        } else {
+            if (ble_ll_scan_enabled() == 0) {
+                bletest_hci_le_create_connection(&g_cc);
+            }
         }
     } else {
         if ((int32_t)(os_time_get() - g_next_os_time) >= 0) {
@@ -716,7 +719,12 @@ bletest_execute_advertiser(void)
                 g_bletest_cur_peer_addr[5] += 1;
                 g_dev_addr[5] += 1;
                 bletest_init_advertising();
-                rc = bletest_hci_le_set_adv_enable(1);
+                bletest_hci_le_set_adv_enable(1);
+            }
+        } else {
+            /* If we failed to start advertising we should keep trying */
+            if (ble_ll_adv_enabled() == 0) {
+                bletest_hci_le_set_adv_enable(1);
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/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 33a73ab..8d9a16d 100644
--- a/net/nimble/controller/include/controller/ble_ll_adv.h
+++ b/net/nimble/controller/include/controller/ble_ll_adv.h
@@ -116,6 +116,9 @@ int ble_ll_adv_set_adv_params(uint8_t *cmd);
 int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen);
 
 /*---- API used by BLE LL ----*/
+/* Returns the event allocated to send the connection complete event */
+uint8_t *ble_ll_adv_get_conn_comp_ev(void);
+
 /* Returns local resolvable private address */
 uint8_t *ble_ll_adv_get_local_rpa(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/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 ceb5025..3e2ce1f 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -25,6 +25,7 @@
 #include "nimble/ble.h"
 #include "nimble/nimble_opt.h"
 #include "nimble/hci_common.h"
+#include "nimble/ble_hci_trans.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "controller/ble_ll.h"
@@ -94,6 +95,7 @@ struct ble_ll_adv_sm
     uint8_t initiator_addr[BLE_DEV_ADDR_LEN];
     uint8_t adv_data[BLE_ADV_DATA_MAX_LEN];
     uint8_t scan_rsp_data[BLE_SCAN_RSP_DATA_MAX_LEN];
+    uint8_t *conn_comp_ev;
     struct os_event adv_txdone_ev;
     struct ble_ll_sched_item adv_sch;
 };
@@ -658,6 +660,12 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
         }
         OS_EXIT_CRITICAL(sr);
 
+        /* If there is an event buf we need to free it */
+        if (advsm->conn_comp_ev) {
+            ble_hci_trans_buf_free(advsm->conn_comp_ev);
+            advsm->conn_comp_ev = NULL;
+        }
+
         /* Disable advertising */
         advsm->enabled = 0;
     }
@@ -679,6 +687,7 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
 {
     uint8_t adv_chan;
     uint8_t *addr;
+    uint8_t *evbuf;
 
     /*
      * This is not in the specification. I will reject the command with a
@@ -693,6 +702,27 @@ ble_ll_adv_sm_start(struct ble_ll_adv_sm *advsm)
         }
     }
 
+    /*
+     * Get an event with which to send the connection complete event if
+     * this is connectable
+     */
+    switch (advsm->adv_type) {
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_HD:
+    case BLE_HCI_ADV_TYPE_ADV_DIRECT_IND_LD:
+    case BLE_HCI_ADV_TYPE_ADV_IND:
+        /* We expect this to be NULL but if not we wont allocate one... */
+        if (advsm->conn_comp_ev == NULL) {
+            evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+            if (!evbuf) {
+                return BLE_ERR_MEM_CAPACITY;
+            }
+            advsm->conn_comp_ev = evbuf;
+        }
+        break;
+    default:
+        break;
+    }
+
     /* Set advertising address */
     if ((advsm->own_addr_type & 1) == 0) {
         addr = g_dev_addr;
@@ -1310,7 +1340,9 @@ ble_ll_adv_event_done(void *arg)
         if (advsm->adv_pdu_start_time >= advsm->adv_dir_hd_end_time) {
             /* Disable advertising */
             advsm->enabled = 0;
-            ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO);
+            ble_ll_conn_comp_event_send(NULL, BLE_ERR_DIR_ADV_TMO,
+                                        advsm->conn_comp_ev);
+            advsm->conn_comp_ev = NULL;
             ble_ll_scan_chk_resume();
             return;
         }
@@ -1357,6 +1389,23 @@ ble_ll_adv_can_chg_whitelist(void)
 }
 
 /**
+ * Returns the event allocated to send the connection complete event
+ *
+ * @return uint8_t* Pointer to event buffer
+ */
+uint8_t *
+ble_ll_adv_get_conn_comp_ev(void)
+{
+    uint8_t *evbuf;
+
+    evbuf = g_ble_ll_adv_sm.conn_comp_ev;
+    assert(evbuf != NULL);
+    g_ble_ll_adv_sm.conn_comp_ev = NULL;
+
+    return evbuf;
+}
+
+/**
  * Returns the local resolvable private address currently being using by
  * the advertiser
  *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/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 642e8c6..43944a8 100644
--- a/net/nimble/controller/src/ble_ll_conn.c
+++ b/net/nimble/controller/src/ble_ll_conn.c
@@ -34,6 +34,7 @@
 #include "controller/ble_ll_sched.h"
 #include "controller/ble_ll_ctrl.h"
 #include "controller/ble_ll_resolv.h"
+#include "controller/ble_ll_adv.h"
 #include "controller/ble_phy.h"
 #include "controller/ble_hw.h"
 #include "ble_ll_conn_priv.h"
@@ -134,6 +135,9 @@ static const uint16_t g_ble_sca_ppm_tbl[8] =
     500, 250, 150, 100, 75, 50, 30, 20
 };
 
+/* Global connection complete event. Used when initiating */
+uint8_t *g_ble_ll_conn_comp_ev;
+
 /* Global LL connection parameters */
 struct ble_ll_conn_global_params g_ble_ll_conn_params;
 
@@ -211,6 +215,24 @@ STATS_NAME_START(ble_ll_conn_stats)
     STATS_NAME(ble_ll_conn_stats, mic_failures)
 STATS_NAME_END(ble_ll_conn_stats)
 
+/**
+ * Get the event buffer allocated to send the connection complete event
+ * when we are initiating.
+ *
+ * @return uint8_t*
+ */
+static uint8_t *
+ble_ll_init_get_conn_comp_ev(void)
+{
+    uint8_t *evbuf;
+
+    evbuf = g_ble_ll_conn_comp_ev;
+    assert(evbuf != NULL);
+    g_ble_ll_conn_comp_ev = NULL;
+
+    return evbuf;
+}
+
 #if (BLE_LL_CFG_FEAT_LE_ENCRYPTION == 1)
 /**
  * Called to determine if the received PDU is an empty PDU or not.
@@ -1548,6 +1570,7 @@ ble_ll_conn_datalen_update(struct ble_ll_conn_sm *connsm,
 void
 ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
 {
+    uint8_t *evbuf;
     struct os_mbuf *m;
     struct os_mbuf_pkthdr *pkthdr;
 
@@ -1602,7 +1625,8 @@ ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err)
      */
     if (ble_err) {
         if (ble_err == BLE_ERR_UNK_CONN_ID) {
-            ble_ll_conn_comp_event_send(connsm, ble_err);
+            evbuf = ble_ll_init_get_conn_comp_ev();
+            ble_ll_conn_comp_event_send(connsm, ble_err, evbuf);
         } else {
             ble_ll_disconn_comp_event_send(connsm, ble_err);
         }
@@ -1779,6 +1803,7 @@ static int
 ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
 {
     int rc;
+    uint8_t *evbuf;
     uint32_t usecs;
 
     /* Set state to created */
@@ -1837,7 +1862,12 @@ ble_ll_conn_created(struct ble_ll_conn_sm *connsm, uint32_t endtime)
                 ble_ll_ctrl_proc_start(connsm, BLE_LL_CTRL_PROC_DATA_LEN_UPD);
             }
         }
-        ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS);
+        if (connsm->conn_role == BLE_LL_CONN_ROLE_SLAVE) {
+            evbuf = ble_ll_adv_get_conn_comp_ev();
+        } else {
+            evbuf = ble_ll_init_get_conn_comp_ev();
+        }
+        ble_ll_conn_comp_event_send(connsm, BLE_ERR_SUCCESS, evbuf);
     }
 
     return rc;
@@ -3140,6 +3170,12 @@ ble_ll_conn_module_reset(void)
         ble_ll_conn_end(connsm, BLE_ERR_SUCCESS);
     }
 
+    /* Free the global connection complete event if there is one */
+    if (g_ble_ll_conn_comp_ev) {
+        ble_hci_trans_buf_free(g_ble_ll_conn_comp_ev);
+        g_ble_ll_conn_comp_ev = NULL;
+    }
+
     /* Now go through and end all the connections */
     while (1) {
         connsm = SLIST_FIRST(&g_ble_ll_conn_active_list);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/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 5d44d27..1242cc4 100644
--- a/net/nimble/controller/src/ble_ll_conn_hci.c
+++ b/net/nimble/controller/src/ble_ll_conn_hci.c
@@ -39,6 +39,32 @@
  * event to the host. This is the os time at which we can send an event.
  */
 static uint32_t g_ble_ll_last_num_comp_pkt_evt;
+extern uint8_t *g_ble_ll_conn_comp_ev;
+
+/**
+ * Allocate an event to send a connection complete event when initiating
+ *
+ * @return int 0: success -1: failure
+ */
+static int
+ble_ll_init_alloc_conn_comp_ev(void)
+{
+    int rc;
+    uint8_t *evbuf;
+
+    rc = 0;
+    evbuf = g_ble_ll_conn_comp_ev;
+    if (evbuf == NULL) {
+        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+        if (!evbuf) {
+            rc = -1;
+        } else {
+            g_ble_ll_conn_comp_ev = evbuf;
+        }
+    }
+
+    return rc;
+}
 
 /**
  * Called to check that the connection parameters are within range
@@ -128,12 +154,12 @@ ble_ll_conn_req_pdu_make(struct ble_ll_conn_sm *connsm)
  * @param status The BLE error code associated with the event
  */
 void
-ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
+ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
+                            uint8_t *evbuf)
 {
     uint8_t peer_addr_type;
     uint8_t enabled;
     uint8_t enh_enabled;
-    uint8_t *evbuf;
     uint8_t *evdata;
     uint8_t *rpa;
 
@@ -141,65 +167,62 @@ ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status)
     enh_enabled = ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE);
 
     if (enabled || enh_enabled) {
-        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
-        if (evbuf) {
-            /* Put common elements in event */
-            evbuf[0] = BLE_HCI_EVCODE_LE_META;
-            if (enh_enabled) {
-                evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
-                evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
-            } else {
-                evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
-                evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
-            }
-            evbuf[3] = status;
+        /* Put common elements in event */
+        evbuf[0] = BLE_HCI_EVCODE_LE_META;
+        if (enh_enabled) {
+            evbuf[1] = BLE_HCI_LE_ENH_CONN_COMPLETE_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE;
+        } else {
+            evbuf[1] = BLE_HCI_LE_CONN_COMPLETE_LEN;
+            evbuf[2] = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
+        }
+        evbuf[3] = status;
 
-            if (connsm) {
-                htole16(evbuf + 4, connsm->conn_handle);
-                evbuf[6] = connsm->conn_role - 1;
-                peer_addr_type = connsm->peer_addr_type;
+        if (connsm) {
+            htole16(evbuf + 4, connsm->conn_handle);
+            evbuf[6] = connsm->conn_role - 1;
+            peer_addr_type = connsm->peer_addr_type;
 
-                evdata = evbuf + 14;
-                if (enh_enabled) {
-                    memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
-                    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-                        if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
-                            rpa = ble_ll_scan_get_local_rpa();
-                        } else {
-                            rpa = NULL;
-                        }
+            evdata = evbuf + 14;
+            if (enh_enabled) {
+                memset(evdata, 0, 2 * BLE_DEV_ADDR_LEN);
+                if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                    if (connsm->own_addr_type > BLE_HCI_ADV_OWN_ADDR_RANDOM) {
+                        rpa = ble_ll_scan_get_local_rpa();
                     } else {
-                        rpa = ble_ll_adv_get_local_rpa();
-                    }
-                    if (rpa) {
-                        memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
+                        rpa = NULL;
                     }
-
-                    if (connsm->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
-                        if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
-                            rpa = ble_ll_scan_get_peer_rpa();
-                        } else {
-                            rpa = ble_ll_adv_get_peer_rpa();
-                        }
-                        memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
-                    }
-                    evdata += 12;
                 } else {
-                    if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
-                        peer_addr_type -= 2;
+                    rpa = ble_ll_adv_get_local_rpa();
+                }
+                if (rpa) {
+                    memcpy(evdata, rpa, BLE_DEV_ADDR_LEN);
+                }
+
+                if (connsm->peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                    if (connsm->conn_role == BLE_LL_CONN_ROLE_MASTER) {
+                        rpa = ble_ll_scan_get_peer_rpa();
+                    } else {
+                        rpa = ble_ll_adv_get_peer_rpa();
                     }
+                    memcpy(evdata + 6, rpa, BLE_DEV_ADDR_LEN);
                 }
+                evdata += 12;
+            } else {
+                if (peer_addr_type > BLE_HCI_CONN_PEER_ADDR_RANDOM) {
+                    peer_addr_type -= 2;
+                }
+            }
 
-                evbuf[7] = peer_addr_type;
-                memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
+            evbuf[7] = peer_addr_type;
+            memcpy(evbuf + 8, connsm->peer_addr, BLE_DEV_ADDR_LEN);
 
-                htole16(evdata, connsm->conn_itvl);
-                htole16(evdata + 2, connsm->slave_latency);
-                htole16(evdata + 4, connsm->supervision_tmo);
-                evdata[6] = connsm->master_sca;
-            }
-            ble_ll_hci_event_send(evbuf);
+            htole16(evdata, connsm->conn_itvl);
+            htole16(evdata + 2, connsm->slave_latency);
+            htole16(evdata + 4, connsm->supervision_tmo);
+            evdata[6] = connsm->master_sca;
         }
+        ble_ll_hci_event_send(evbuf);
     }
 }
 
@@ -462,6 +485,11 @@ ble_ll_conn_create(uint8_t *cmdbuf)
         return BLE_ERR_CONN_LIMIT;
     }
 
+    /* Make sure we can allocate an event to send the connection complete */
+    if (ble_ll_init_alloc_conn_comp_ev()) {
+        return BLE_ERR_MEM_CAPACITY;
+    }
+
     /* Initialize state machine in master role and start state machine */
     ble_ll_conn_master_init(connsm, hcc);
     ble_ll_conn_sm_new(connsm);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/840bb647/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 b8c4fa1..2ccd38e 100644
--- a/net/nimble/controller/src/ble_ll_conn_priv.h
+++ b/net/nimble/controller/src/ble_ll_conn_priv.h
@@ -133,7 +133,8 @@ int ble_ll_conn_hci_set_chan_class(uint8_t *cmdbuf);
 int ble_ll_conn_hci_param_reply(uint8_t *cmdbuf, int negative_reply);
 int ble_ll_conn_create_cancel(void);
 void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
-void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status);
+void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
+                                 uint8_t *evbuf);
 void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
 int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
                                     uint16_t latency, uint16_t spvn_tmo);


[18/19] incubator-mynewt-core git commit: Added NUCLEO-F401RE to README.md. This abandons and closes #53, abandons and closes #57, and abandons and closes #60

Posted by cc...@apache.org.
Added NUCLEO-F401RE to README.md. This abandons and closes #53, abandons and closes #57, and abandons and closes #60


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

Branch: refs/heads/develop
Commit: 7aee85161dcba7dfa963cdba44fec94d891bc5bc
Parents: 1e52394
Author: aditihilbert <ad...@runtime.io>
Authored: Fri Oct 7 14:07:43 2016 -0700
Committer: aditihilbert <ad...@runtime.io>
Committed: Fri Oct 7 14:07:43 2016 -0700

----------------------------------------------------------------------
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7aee8516/README.md
----------------------------------------------------------------------
diff --git a/README.md b/README.md
index 3f44d43..0abd616 100644
--- a/README.md
+++ b/README.md
@@ -38,7 +38,7 @@ It currently supports the following hardware platforms:
 * Arduino Zero (Cortex-M0)
 * Arduino Zero Pro (Cortex-M0)
 * Arduino M0 Pro (Cortex-M0)
-
+* NUCLEO-F401RE from STMicroelectronics (Cortex-M4)
 
 Apache Mynewt uses the
 [Newt](https://www.github.com/apache/incubator-mynewt-newt) build and package


[13/19] incubator-mynewt-core git commit: MYNEWT-390: NRF hal_gpio_read does not return 1 when pin high

Posted by cc...@apache.org.
MYNEWT-390: NRF hal_gpio_read does not return 1 when pin high

This API is supposed to return 1 but was returning 1 << pin. This
has now been fixed so if the pin is high, 1 is returned.


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

Branch: refs/heads/develop
Commit: ee3cd755b8a96c93af1580fd0b2270355ad037d9
Parents: 0ec0bc4
Author: William San Filippo <wi...@runtime.io>
Authored: Wed Sep 21 21:53:07 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Wed Sep 21 21:55:06 2016 -0700

----------------------------------------------------------------------
 hw/mcu/nordic/nrf51xxx/src/hal_gpio.c | 2 +-
 hw/mcu/nordic/nrf52xxx/src/hal_gpio.c | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ee3cd755/hw/mcu/nordic/nrf51xxx/src/hal_gpio.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf51xxx/src/hal_gpio.c b/hw/mcu/nordic/nrf51xxx/src/hal_gpio.c
index bd8414a..dfbe9f7 100644
--- a/hw/mcu/nordic/nrf51xxx/src/hal_gpio.c
+++ b/hw/mcu/nordic/nrf51xxx/src/hal_gpio.c
@@ -414,7 +414,7 @@ void hal_gpio_write(int pin, int val)
  */
 int hal_gpio_read(int pin)
 {
-    return (NRF_GPIO->IN & GPIO_MASK(pin));
+    return ((NRF_GPIO->IN & GPIO_MASK(pin)) != 0);
 }
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/ee3cd755/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
----------------------------------------------------------------------
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c b/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
index 490b8a3..0fbb5a3 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_gpio.c
@@ -160,7 +160,7 @@ void hal_gpio_write(int pin, int val)
  */
 int hal_gpio_read(int pin)
 {
-    return (NRF_P0->IN & HAL_GPIO_MASK(pin));
+    return ((NRF_P0->IN & HAL_GPIO_MASK(pin)) != 0);
 }
 
 /**


[16/19] incubator-mynewt-core git commit: apache-mynewt-core: point 0-dev at master branch.

Posted by cc...@apache.org.
apache-mynewt-core: point 0-dev at master branch.


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

Branch: refs/heads/develop
Commit: cc05bf2fc7f43c39dd1ff601577ce03c288e83f3
Parents: 08ffff8
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Sep 26 12:45:30 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Mon Sep 26 12:45:30 2016 -0700

----------------------------------------------------------------------
 repository.yml | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/cc05bf2f/repository.yml
----------------------------------------------------------------------
diff --git a/repository.yml b/repository.yml
index fd1ee6d..615004f 100644
--- a/repository.yml
+++ b/repository.yml
@@ -23,8 +23,7 @@ repo.versions:
     "0.7.9": "mynewt_0_8_0_b2_tag"
     "0.8.0": "mynewt_0_8_0_tag"
     "0.9.0": "mynewt_0_9_0_tag"
-    # develop branch, pre-sterly_refactor merge.
-    "0.9.1": "12ef82c64f072d79bcffd417ad803b503dac6431"
+    "0.9.1": "master"
     "0-latest": "0.9.0"
     "0-dev": "0.9.1"
     "0.8-latest": "0.8.0"


[15/19] incubator-mynewt-core git commit: repository.yml tag requires level of indirection.

Posted by cc...@apache.org.
repository.yml tag requires level of indirection.


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

Branch: refs/heads/develop
Commit: 08ffff8c1dd8b1adaaddf941e0d62a6e21e83fb1
Parents: a34f672
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Sep 21 22:49:06 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Sep 21 22:49:06 2016 -0700

----------------------------------------------------------------------
 repository.yml | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/08ffff8c/repository.yml
----------------------------------------------------------------------
diff --git a/repository.yml b/repository.yml
index 71423d5..fd1ee6d 100644
--- a/repository.yml
+++ b/repository.yml
@@ -23,7 +23,9 @@ repo.versions:
     "0.7.9": "mynewt_0_8_0_b2_tag"
     "0.8.0": "mynewt_0_8_0_tag"
     "0.9.0": "mynewt_0_9_0_tag"
+    # develop branch, pre-sterly_refactor merge.
+    "0.9.1": "12ef82c64f072d79bcffd417ad803b503dac6431"
     "0-latest": "0.9.0"
-    "0-dev": "12ef82c64f072d79bcffd417ad803b503dac6431"
+    "0-dev": "0.9.1"
     "0.8-latest": "0.8.0"
     "0.9-latest": "0.9.0"


[07/19] incubator-mynewt-core git commit: MYNEWT-387: Separate ACL buffer pool for controller only

Posted by cc...@apache.org.
MYNEWT-387: Separate ACL buffer pool for controller only

The controller (for the controller only implementation) now uses
a separate pool of buffers for ACL data. This pool is only used
by the host to send ACL data; the controller will never grab a
buffer from this pool for any other reason. This was done so that
the controller and host will stay in sync regarding reported
total ACL buffers and the number of completed packets. By default,
4 ACL buffers are allocated. This is quite an arbitrary number
and should be modified based on memory available and application
requirements.


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

Branch: refs/heads/develop
Commit: 6773301d2fd3f66faed1f466e0235bb65681d510
Parents: 840bb64
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Sep 13 08:42:45 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Tue Sep 13 12:34:49 2016 -0700

----------------------------------------------------------------------
 apps/blehci/src/main.c                          |  9 ++--
 .../uart/include/transport/uart/ble_hci_uart.h  |  1 +
 net/nimble/transport/uart/src/ble_hci_uart.c    | 50 +++++++++++++++++++-
 3 files changed, 54 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6773301d/apps/blehci/src/main.c
----------------------------------------------------------------------
diff --git a/apps/blehci/src/main.c b/apps/blehci/src/main.c
index e95f402..0dd77e8 100755
--- a/apps/blehci/src/main.c
+++ b/apps/blehci/src/main.c
@@ -51,7 +51,7 @@ struct os_mempool default_mbuf_mpool;
 int
 main(void)
 {
-    struct ble_hci_uart_cfg hci_cfg;
+    const struct ble_hci_uart_cfg *hci_cfg;
     int rc;
 
     /* Initialize OS */
@@ -74,11 +74,12 @@ main(void)
     assert(rc == 0);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    hci_cfg = &ble_hci_uart_cfg_dflt;
+    rc = ble_ll_init(BLE_LL_TASK_PRI, hci_cfg->num_acl_bufs,
+                     BLE_MBUF_PAYLOAD_SIZE);
     assert(rc == 0);
 
-    hci_cfg = ble_hci_uart_cfg_dflt;
-    rc = ble_hci_uart_init(&hci_cfg);
+    rc = ble_hci_uart_init(hci_cfg);
     assert(rc == 0);
 
     /* Start the OS */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6773301d/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
----------------------------------------------------------------------
diff --git a/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h b/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
index 1fbaa74..de84ada 100644
--- a/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
+++ b/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
@@ -5,6 +5,7 @@ struct ble_hci_uart_cfg {
     uint32_t baud;
     uint16_t num_evt_bufs;
     uint16_t evt_buf_sz;
+    uint16_t num_acl_bufs;
     uint8_t uart_port;
     uint8_t flow_ctrl;
     uint8_t data_bits;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/6773301d/net/nimble/transport/uart/src/ble_hci_uart.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/uart/src/ble_hci_uart.c b/net/nimble/transport/uart/src/ble_hci_uart.c
index 0fa982a..98e3eb2 100755
--- a/net/nimble/transport/uart/src/ble_hci_uart.c
+++ b/net/nimble/transport/uart/src/ble_hci_uart.c
@@ -59,6 +59,8 @@ const struct ble_hci_uart_cfg ble_hci_uart_cfg_dflt = {
 
     .num_evt_bufs = 8,
     .evt_buf_sz = BLE_HCI_TRANS_CMD_SZ,
+
+    .num_acl_bufs = 4
 };
 
 static ble_hci_trans_rx_cmd_fn *ble_hci_uart_rx_cmd_cb;
@@ -73,6 +75,10 @@ static void *ble_hci_uart_evt_buf;
 static struct os_mempool ble_hci_uart_pkt_pool;
 static void *ble_hci_uart_pkt_buf;
 
+static struct os_mbuf_pool ble_hci_uart_acl_mbuf_pool;
+static struct os_mempool ble_hci_uart_acl_pool;
+static void *ble_hci_uart_acl_buf;
+
 /**
  * An incoming or outgoing command or event.
  */
@@ -119,6 +125,21 @@ static struct {
 
 static struct ble_hci_uart_cfg ble_hci_uart_cfg;
 
+/**
+ * Allocates a buffer (mbuf) for ACL operation.
+ *
+ * @return                      The allocated buffer on success;
+ *                              NULL on buffer exhaustion.
+ */
+static struct os_mbuf *
+ble_hci_trans_acl_buf_alloc(void)
+{
+    struct os_mbuf *m;
+
+    m = os_mbuf_get_pkthdr(&ble_hci_uart_acl_mbuf_pool, 0);
+    return m;
+}
+
 static int
 ble_hci_uart_acl_tx(struct os_mbuf *om)
 {
@@ -296,8 +317,7 @@ ble_hci_uart_rx_pkt_type(uint8_t data)
         break;
 
     case BLE_HCI_UART_H4_ACL:
-        ble_hci_uart_state.rx_acl.buf =
-            os_msys_get_pkthdr(BLE_HCI_DATA_HDR_SZ, 0);
+        ble_hci_uart_state.rx_acl.buf = ble_hci_trans_acl_buf_alloc();
         assert(ble_hci_uart_state.rx_acl.buf != NULL);
 
         ble_hci_uart_state.rx_acl.len = 0;
@@ -456,6 +476,9 @@ ble_hci_uart_free_mem(void)
 
     free(ble_hci_uart_pkt_buf);
     ble_hci_uart_pkt_buf = NULL;
+
+    free(ble_hci_uart_acl_buf);
+    ble_hci_uart_acl_buf = NULL;
 }
 
 static int
@@ -700,11 +723,34 @@ int
 ble_hci_uart_init(const struct ble_hci_uart_cfg *cfg)
 {
     int rc;
+    int acl_block_size;
 
     ble_hci_uart_free_mem();
 
     ble_hci_uart_cfg = *cfg;
 
+    /*
+     * XXX: For now, we will keep the ACL buffer size such that it can
+     * accommodate BLE_MBUF_PAYLOAD_SIZE. It should be possible to make this
+     * user defined but more testing would need to be done in that case.
+     */
+    acl_block_size = BLE_MBUF_PAYLOAD_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD;
+    acl_block_size = OS_ALIGN(acl_block_size, OS_ALIGNMENT);
+    rc = mem_malloc_mempool(&ble_hci_uart_acl_pool,
+                            cfg->num_acl_bufs,
+                            acl_block_size,
+                            "ble_hci_uart_acl_pool",
+                            &ble_hci_uart_acl_buf);
+    if (rc != 0) {
+        rc = ble_err_from_os(rc);
+        goto err;
+    }
+
+    rc = os_mbuf_pool_init(&ble_hci_uart_acl_mbuf_pool, &ble_hci_uart_acl_pool,
+                           acl_block_size, cfg->num_acl_bufs);
+    assert(rc == 0);
+
+
     /* Create memory pool of HCI command / event buffers */
     rc = mem_malloc_mempool(&ble_hci_uart_evt_pool,
                             cfg->num_evt_bufs,


[05/19] incubator-mynewt-core git commit: Add .gdbinit to ignored git files.

Posted by cc...@apache.org.
Add .gdbinit to ignored git files.


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

Branch: refs/heads/develop
Commit: 20e2f38f1ac7aa4fd17cfdc910be307ea6ef9af5
Parents: 8559e07
Author: William San Filippo <wi...@runtime.io>
Authored: Fri Sep 9 13:00:49 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Fri Sep 9 13:00:49 2016 -0700

----------------------------------------------------------------------
 .gitignore | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/20e2f38f/.gitignore
----------------------------------------------------------------------
diff --git a/.gitignore b/.gitignore
index d8910f3..27a10ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,6 +25,7 @@ tags
 .gdb_history
 .gdb_out
 .gdb_cmds
+.gdbinit
 *~
 .DS_Store
 *.swp


[11/19] incubator-mynewt-core git commit: No jira ticket for this commit. In the case of the combined host/controller, the length of the ACL data packet (as reported by read buffer size) was technically incorrect (although there are no issues with it bec

Posted by cc...@apache.org.
No jira ticket for this commit. In the case of the combined host/controller, the length of the ACL data
packet (as reported by read buffer size) was technically incorrect (although there are no issues with
it because the host will only use the available mbuf and the controller does nothing with the ACL
data packet size). The code did not account for the 4 byte HCI header. Now we do account for it so it
is consistent with the controller only code.


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

Branch: refs/heads/develop
Commit: e3cdc2b2ff627dbcf5428b0db3ef39c97226a016
Parents: 473e050
Author: William San Filippo <wi...@runtime.io>
Authored: Mon Sep 19 09:52:41 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Mon Sep 19 09:57:00 2016 -0700

----------------------------------------------------------------------
 apps/blecent/src/main.c | 3 ++-
 apps/bleprph/src/main.c | 3 ++-
 apps/bletest/src/main.c | 3 ++-
 apps/bletiny/src/main.c | 3 ++-
 apps/bleuart/src/main.c | 3 ++-
 5 files changed, 10 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3cdc2b2/apps/blecent/src/main.c
----------------------------------------------------------------------
diff --git a/apps/blecent/src/main.c b/apps/blecent/src/main.c
index 7056cc6..d92a848 100755
--- a/apps/blecent/src/main.c
+++ b/apps/blecent/src/main.c
@@ -571,7 +571,8 @@ main(void)
                  blecent_stack, BLECENT_STACK_SIZE);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
     /* Initialize the RAM HCI transport. */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3cdc2b2/apps/bleprph/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bleprph/src/main.c b/apps/bleprph/src/main.c
index 0233bc1..f497d25 100755
--- a/apps/bleprph/src/main.c
+++ b/apps/bleprph/src/main.c
@@ -395,7 +395,8 @@ main(void)
                  bleprph_stack, BLEPRPH_STACK_SIZE);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
     /* Initialize the RAM HCI transport. */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3cdc2b2/apps/bletest/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletest/src/main.c b/apps/bletest/src/main.c
index 066d52e..ffc0b92 100755
--- a/apps/bletest/src/main.c
+++ b/apps/bletest/src/main.c
@@ -1170,7 +1170,8 @@ main(void)
     os_eventq_init(&g_bletest_evq);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
     /* Initialize host */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3cdc2b2/apps/bletiny/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bletiny/src/main.c b/apps/bletiny/src/main.c
index dfd0aee..561604e 100755
--- a/apps/bletiny/src/main.c
+++ b/apps/bletiny/src/main.c
@@ -1702,7 +1702,8 @@ main(void)
     assert(rc == 0);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
     /* Initialize the RAM HCI transport. */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3cdc2b2/apps/bleuart/src/main.c
----------------------------------------------------------------------
diff --git a/apps/bleuart/src/main.c b/apps/bleuart/src/main.c
index 8ff7d82..2c54929 100755
--- a/apps/bleuart/src/main.c
+++ b/apps/bleuart/src/main.c
@@ -293,7 +293,8 @@ main(void)
                  bleuart_stack, bleuart_STACK_SIZE);
 
     /* Initialize the BLE LL */
-    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS, BLE_MBUF_PAYLOAD_SIZE);
+    rc = ble_ll_init(BLE_LL_TASK_PRI, MBUF_NUM_MBUFS,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
     /* Initialize the RAM HCI transport. */


[12/19] incubator-mynewt-core git commit: Make 0-dev point to master (was: develop).

Posted by cc...@apache.org.
Make 0-dev point to master (was: develop).

This is a temporary change.  0-dev will be pointed back at develop once
the sterly_refactor merge is complete and the obvious problems are
fixed.


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

Branch: refs/heads/develop
Commit: 0ec0bc4504bd2cb6ad9f87eb3afe8ce59706f933
Parents: e3cdc2b
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Sep 21 14:04:10 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Sep 21 14:04:10 2016 -0700

----------------------------------------------------------------------
 repository.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/0ec0bc45/repository.yml
----------------------------------------------------------------------
diff --git a/repository.yml b/repository.yml
index d4d1c64..425df70 100644
--- a/repository.yml
+++ b/repository.yml
@@ -24,6 +24,6 @@ repo.versions:
     "0.8.0": "mynewt_0_8_0_tag"
     "0.9.0": "mynewt_0_9_0_tag"
     "0-latest": "0.9.0"
-    "0-dev": "0.0.0"
+    "0-dev": "master"
     "0.8-latest": "0.8.0"
     "0.9-latest": "0.9.0"


[14/19] incubator-mynewt-core git commit: 0-dev -> develop prior to sterly_refactor merge.

Posted by cc...@apache.org.
0-dev -> develop prior to sterly_refactor merge.


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

Branch: refs/heads/develop
Commit: a34f6721c1a42b50e6fff609de2d619facfb96b5
Parents: ee3cd75
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Sep 21 22:32:16 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Sep 21 22:32:16 2016 -0700

----------------------------------------------------------------------
 repository.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/a34f6721/repository.yml
----------------------------------------------------------------------
diff --git a/repository.yml b/repository.yml
index 425df70..71423d5 100644
--- a/repository.yml
+++ b/repository.yml
@@ -24,6 +24,6 @@ repo.versions:
     "0.8.0": "mynewt_0_8_0_tag"
     "0.9.0": "mynewt_0_9_0_tag"
     "0-latest": "0.9.0"
-    "0-dev": "master"
+    "0-dev": "12ef82c64f072d79bcffd417ad803b503dac6431"
     "0.8-latest": "0.8.0"
     "0.9-latest": "0.9.0"


[19/19] incubator-mynewt-core git commit: Merge remote-tracking branch 'apache/master' into develop

Posted by cc...@apache.org.
Merge remote-tracking branch 'apache/master' into develop


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

Branch: refs/heads/develop
Commit: 406eeb0c2fc736f3a13c8d7320c0b65eb44474c4
Parents: 858f94e 7aee851
Author: Christopher Collins <cc...@apache.org>
Authored: Thu Nov 10 11:06:24 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Thu Nov 10 11:06:24 2016 -0800

----------------------------------------------------------------------
 README.md                                    | 2 +-
 net/nimble/transport/uart/src/ble_hci_uart.c | 8 ++++++--
 repository.yml                               | 3 ++-
 3 files changed, 9 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/406eeb0c/net/nimble/transport/uart/src/ble_hci_uart.c
----------------------------------------------------------------------
diff --cc net/nimble/transport/uart/src/ble_hci_uart.c
index 530c5e4,663c817..13b32d3
--- a/net/nimble/transport/uart/src/ble_hci_uart.c
+++ b/net/nimble/transport/uart/src/ble_hci_uart.c
@@@ -38,17 -36,8 +38,21 @@@
  
  #include "transport/uart/ble_hci_uart.h"
  
 +#define BLE_HCI_UART_EVT_COUNT  \
 +    (MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT) + MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT))
 +
 +/***
-  * NOTE:
++ * NOTES:
 + * The UART HCI transport doesn't use event buffer priorities.  All incoming
-  * and outgoing events and commands use buffers from the same pool.
++ * and outgoing events use buffers from the same pool.
++ *
++ * The "skip" definitions are here so that when buffers cannot be allocated,
++ * the command or acl packets are simply skipped so that the HCI interface
++ * does not lose synchronization and resets dont (necessarily) occur.
 + */
 +
  /* XXX: for now, define this here */
 -#ifdef FEATURE_BLE_DEVICE
 +#if MYNEWT_VAL(BLE_DEVICE)
  extern void ble_ll_data_buffer_overflow(void);
  extern void ble_ll_hw_error(uint8_t err);
  


[10/19] incubator-mynewt-core git commit: MYNEWT-388: HCI uart should not assert if a command, event or ACL buffer not available

Posted by cc...@apache.org.
MYNEWT-388: HCI uart should not assert if a command, event or ACL buffer not available

There were a number of changes committed to fix a few BLE HCI issues
1) On HCI sync loss, the controller will now send a HW error and wait
to find a reset command in the byyte stream in order to re-sync.
2) If no ACL data buffer available, the ACL packet is skipped and a
data buffer overflow event is sent.
3) If no command buffer is available, the current command is simply
skipped. No response is sent in this case. The spec was not clear
and since this should never happen we simply decided to skip the
command.


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

Branch: refs/heads/develop
Commit: 473e050f7fde744ad198d9ce3234115fa5940750
Parents: dd79d93
Author: William San Filippo <wi...@runtime.io>
Authored: Fri Sep 16 16:39:43 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Fri Sep 16 16:39:43 2016 -0700

----------------------------------------------------------------------
 apps/blehci/src/main.c                          |  20 +-
 .../controller/include/controller/ble_ll.h      |  13 +
 .../controller/include/controller/ble_ll_ctrl.h |   3 +
 net/nimble/controller/src/ble_ll.c              |  53 +++
 net/nimble/controller/src/ble_ll_hci_ev.c       |  44 +++
 net/nimble/include/nimble/ble.h                 |   4 +
 net/nimble/include/nimble/hci_common.h          |   4 +
 .../uart/include/transport/uart/ble_hci_uart.h  |   4 +-
 net/nimble/transport/uart/src/ble_hci_uart.c    | 377 ++++++++++++++++---
 9 files changed, 465 insertions(+), 57 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/apps/blehci/src/main.c
----------------------------------------------------------------------
diff --git a/apps/blehci/src/main.c b/apps/blehci/src/main.c
index 0dd77e8..52aab99 100755
--- a/apps/blehci/src/main.c
+++ b/apps/blehci/src/main.c
@@ -23,6 +23,7 @@
 
 /* BLE */
 #include "nimble/ble.h"
+#include "nimble/hci_common.h"
 #include "controller/ble_ll.h"
 #include "transport/uart/ble_hci_uart.h"
 
@@ -41,8 +42,6 @@ uint8_t g_dev_addr[BLE_DEV_ADDR_LEN] = { 0 };
 /* Our random address (in case we need it) */
 uint8_t g_random_addr[BLE_DEV_ADDR_LEN] = { 0 };
 
-#define HCI_MAX_BUFS        (5)
-
 os_membuf_t default_mbuf_mpool_data[MBUF_MEMPOOL_SIZE];
 
 struct os_mbuf_pool default_mbuf_pool;
@@ -51,7 +50,7 @@ struct os_mempool default_mbuf_mpool;
 int
 main(void)
 {
-    const struct ble_hci_uart_cfg *hci_cfg;
+    struct ble_hci_uart_cfg hci_cfg;
     int rc;
 
     /* Initialize OS */
@@ -74,12 +73,19 @@ main(void)
     assert(rc == 0);
 
     /* Initialize the BLE LL */
-    hci_cfg = &ble_hci_uart_cfg_dflt;
-    rc = ble_ll_init(BLE_LL_TASK_PRI, hci_cfg->num_acl_bufs,
-                     BLE_MBUF_PAYLOAD_SIZE);
+    hci_cfg = ble_hci_uart_cfg_dflt;
+    rc = ble_ll_init(BLE_LL_TASK_PRI, hci_cfg.num_acl_bufs,
+                     BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ);
     assert(rc == 0);
 
-    rc = ble_hci_uart_init(hci_cfg);
+    /*
+     * XXX: for now, the developer MUST configure the number of msys buffers
+     * and not rely on the default value. The number of msys buffers must
+     * be >= to the number of pool elements registered to os_msys. In this
+     * project, we only register the default mbuf pool.
+     */
+    hci_cfg.num_msys_bufs = MBUF_NUM_MBUFS;
+    rc = ble_hci_uart_init(&hci_cfg);
     assert(rc == 0);
 
     /* Start the OS */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/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 7865cf8..ee4fe24 100644
--- a/net/nimble/controller/include/controller/ble_ll.h
+++ b/net/nimble/controller/include/controller/ble_ll.h
@@ -76,6 +76,12 @@ struct ble_ll_obj
     /* Packet transmit queue */
     struct os_event ll_tx_pkt_ev;
     struct ble_ll_pkt_q ll_tx_pkt_q;
+
+    /* Data buffer overflow event */
+    struct os_event ll_dbuf_overflow_ev;
+
+    /* HW error callout */
+    struct os_callout_func ll_hw_err_timer;
 };
 extern struct ble_ll_obj g_ble_ll_data;
 
@@ -130,6 +136,7 @@ extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
 #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)
+#define BLE_LL_EVENT_DBUF_OVERFLOW  (OS_EVENT_T_PERUSER + 7)
 
 /* LL Features */
 #define BLE_LL_FEAT_LE_ENCRYPTION   (0x01)
@@ -323,6 +330,12 @@ void ble_ll_acl_data_in(struct os_mbuf *txpkt);
  */
 struct os_mbuf *ble_ll_rxpdu_alloc(uint16_t len);
 
+/* Tell the Link Layer there has been a data buffer overflow */
+void ble_ll_data_buffer_overflow(void);
+
+/* Tell the link layer there has been a hardware error */
+void ble_ll_hw_error(void);
+
 /*--- PHY interfaces ---*/
 struct ble_mbuf_hdr;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/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
index f652faf..1d30749 100644
--- a/net/nimble/controller/include/controller/ble_ll_ctrl.h
+++ b/net/nimble/controller/include/controller/ble_ll_ctrl.h
@@ -244,6 +244,9 @@ void ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm,
 void ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status);
 void ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status);
 int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm);
+int ble_ll_hci_ev_hw_err(uint8_t hw_err);
+void ble_ll_hci_ev_databuf_overflow(void);
+
 
 void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/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 3beb28e..117d7fa 100644
--- a/net/nimble/controller/src/ble_ll.c
+++ b/net/nimble/controller/src/ble_ll.c
@@ -716,6 +716,49 @@ ble_ll_acl_data_in(struct os_mbuf *txpkt)
 }
 
 /**
+ * Called to post event to Link Layer when a data buffer overflow has
+ * occurred.
+ *
+ * Context: Interrupt
+ *
+ */
+void
+ble_ll_data_buffer_overflow(void)
+{
+    os_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_data.ll_dbuf_overflow_ev);
+}
+
+/**
+ * Called when a HW error occurs.
+ *
+ * Context: Interrupt
+ */
+void
+ble_ll_hw_error(void)
+{
+    os_callout_reset(&g_ble_ll_data.ll_hw_err_timer.cf_c, 0);
+}
+
+/**
+ * Called when the HW error timer expires.
+ *
+ * @param arg
+ */
+static void
+ble_ll_hw_err_timer_cb(void *arg)
+{
+    if (ble_ll_hci_ev_hw_err(BLE_HW_ERR_HCI_SYNC_LOSS)) {
+        /*
+         * Restart callout if failed to allocate event. Try to allocate an
+         * event every 50 milliseconds (or each OS tick if a tick is longer
+         * than 100 msecs).
+         */
+        os_callout_reset(&g_ble_ll_data.ll_hw_err_timer.cf_c,
+                         OS_TICKS_PER_SEC / 20);
+    }
+}
+
+/**
  * Called upon start of received PDU
  *
  * Context: Interrupt
@@ -951,6 +994,9 @@ ble_ll_task(void *arg)
         case BLE_LL_EVENT_TX_PKT_IN:
             ble_ll_tx_pkt_in();
             break;
+        case BLE_LL_EVENT_DBUF_OVERFLOW:
+            ble_ll_hci_ev_databuf_overflow();
+            break;
         case BLE_LL_EVENT_CONN_SPVN_TMO:
             ble_ll_conn_spvn_timeout(ev->ev_arg);
             break;
@@ -1175,6 +1221,13 @@ ble_ll_init(uint8_t ll_task_prio, uint8_t num_acl_pkts, uint16_t acl_pkt_size)
     /* Initialize transmit (from host) and receive packet (from phy) event */
     lldata->ll_rx_pkt_ev.ev_type = BLE_LL_EVENT_RX_PKT_IN;
     lldata->ll_tx_pkt_ev.ev_type = BLE_LL_EVENT_TX_PKT_IN;
+    lldata->ll_dbuf_overflow_ev.ev_type = BLE_LL_EVENT_DBUF_OVERFLOW;
+
+    /* Initialize the HW error timer */
+    os_callout_func_init(&g_ble_ll_data.ll_hw_err_timer,
+                         &g_ble_ll_data.ll_evq,
+                         ble_ll_hw_err_timer_cb,
+                         NULL);
 
     /* Initialize wait for response timer */
     cputime_timer_init(&g_ble_ll_data.ll_wfr_timer, ble_ll_wfr_timer_exp,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/net/nimble/controller/src/ble_ll_hci_ev.c
----------------------------------------------------------------------
diff --git a/net/nimble/controller/src/ble_ll_hci_ev.c b/net/nimble/controller/src/ble_ll_hci_ev.c
index 2548bdc..8e1f468 100644
--- a/net/nimble/controller/src/ble_ll_hci_ev.c
+++ b/net/nimble/controller/src/ble_ll_hci_ev.c
@@ -222,3 +222,47 @@ ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status)
         }
     }
 }
+
+/**
+ * Send a HW error to the host.
+ *
+ * @param hw_err
+ *
+ * @return int 0: event masked or event sent, -1 otherwise
+ */
+int
+ble_ll_hci_ev_hw_err(uint8_t hw_err)
+{
+    int rc;
+    uint8_t *evbuf;
+
+    rc = 0;
+    if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_HW_ERROR)) {
+        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+        if (evbuf) {
+            evbuf[0] = BLE_HCI_EVCODE_HW_ERROR;
+            evbuf[1] = BLE_HCI_EVENT_HW_ERROR_LEN;
+            evbuf[2] = hw_err;
+            ble_ll_hci_event_send(evbuf);
+        } else {
+            rc = -1;
+        }
+    }
+    return rc;
+}
+
+void
+ble_ll_hci_ev_databuf_overflow(void)
+{
+    uint8_t *evbuf;
+
+    if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DATA_BUF_OVERFLOW)) {
+        evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
+        if (evbuf) {
+            evbuf[0] = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW;
+            evbuf[1] = BLE_HCI_EVENT_DATABUF_OVERFLOW_LEN;
+            evbuf[2] = BLE_HCI_EVENT_ACL_BUF_OVERFLOW;
+            ble_ll_hci_event_send(evbuf);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/net/nimble/include/nimble/ble.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/ble.h b/net/nimble/include/nimble/ble.h
index 6c4c90e..1ad6f29 100644
--- a/net/nimble/include/nimble/ble.h
+++ b/net/nimble/include/nimble/ble.h
@@ -229,4 +229,8 @@ enum ble_error_codes
 
 int ble_err_from_os(int os_err);
 
+/* HW error codes */
+#define BLE_HW_ERR_DO_NOT_USE           (0) /* XXX: reserve this one for now */
+#define BLE_HW_ERR_HCI_SYNC_LOSS        (1)
+
 #endif /* H_BLE_ */

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/net/nimble/include/nimble/hci_common.h
----------------------------------------------------------------------
diff --git a/net/nimble/include/nimble/hci_common.h b/net/nimble/include/nimble/hci_common.h
index f094cc7..5bf7156 100644
--- a/net/nimble/include/nimble/hci_common.h
+++ b/net/nimble/include/nimble/hci_common.h
@@ -500,6 +500,10 @@
 /* Read remote version informaton */
 #define BLE_HCI_EVENT_RD_RM_VER_LEN         (8)
 
+/* Data buffer overflow event */
+#define BLE_HCI_EVENT_DATABUF_OVERFLOW_LEN  (1)
+#define BLE_HCI_EVENT_ACL_BUF_OVERFLOW      (0x01)
+
 /* Advertising report */
 #define BLE_HCI_ADV_RPT_EVTYPE_ADV_IND      (0)
 #define BLE_HCI_ADV_RPT_EVTYPE_DIR_IND      (1)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
----------------------------------------------------------------------
diff --git a/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h b/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
index de84ada..7b6a817 100644
--- a/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
+++ b/net/nimble/transport/uart/include/transport/uart/ble_hci_uart.h
@@ -3,9 +3,11 @@
 
 struct ble_hci_uart_cfg {
     uint32_t baud;
-    uint16_t num_evt_bufs;
+    uint16_t num_evt_hi_bufs;
+    uint16_t num_evt_lo_bufs;
     uint16_t evt_buf_sz;
     uint16_t num_acl_bufs;
+    uint16_t num_msys_bufs;
     uint8_t uart_port;
     uint8_t flow_ctrl;
     uint8_t data_bits;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/473e050f/net/nimble/transport/uart/src/ble_hci_uart.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/uart/src/ble_hci_uart.c b/net/nimble/transport/uart/src/ble_hci_uart.c
index 8cf5b9e..663c817 100755
--- a/net/nimble/transport/uart/src/ble_hci_uart.c
+++ b/net/nimble/transport/uart/src/ble_hci_uart.c
@@ -36,17 +36,31 @@
 
 #include "transport/uart/ble_hci_uart.h"
 
+/* XXX: for now, define this here */
+#ifdef FEATURE_BLE_DEVICE
+extern void ble_ll_data_buffer_overflow(void);
+extern void ble_ll_hw_error(uint8_t err);
+
+static const uint8_t ble_hci_uart_reset_cmd[4] = { 0x01, 0x03, 0x0C, 0x00 };
+#endif
+
 /***
- * NOTE:
+ * NOTES:
  * The UART HCI transport doesn't use event buffer priorities.  All incoming
- * and outgoing events and commands use buffers from the same pool.
+ * and outgoing events use buffers from the same pool.
+ *
+ * The "skip" definitions are here so that when buffers cannot be allocated,
+ * the command or acl packets are simply skipped so that the HCI interface
+ * does not lose synchronization and resets dont (necessarily) occur.
  */
-
 #define BLE_HCI_UART_H4_NONE        0x00
 #define BLE_HCI_UART_H4_CMD         0x01
 #define BLE_HCI_UART_H4_ACL         0x02
 #define BLE_HCI_UART_H4_SCO         0x03
 #define BLE_HCI_UART_H4_EVT         0x04
+#define BLE_HCI_UART_H4_SYNC_LOSS   0x80
+#define BLE_HCI_UART_H4_SKIP_CMD    0x81
+#define BLE_HCI_UART_H4_SKIP_ACL    0x82
 
 /** Default configuration. */
 const struct ble_hci_uart_cfg ble_hci_uart_cfg_dflt = {
@@ -57,8 +71,11 @@ const struct ble_hci_uart_cfg ble_hci_uart_cfg_dflt = {
     .stop_bits = 1,
     .parity = HAL_UART_PARITY_NONE,
 
-    .num_evt_bufs = 8,
-    .evt_buf_sz = BLE_HCI_TRANS_CMD_SZ,
+    .num_evt_hi_bufs = 8,
+    .num_evt_lo_bufs = 8,
+
+    /* The largest event the nimble controller will send is 70 bytes. */
+    .evt_buf_sz = 70,
 
     .num_acl_bufs = 4
 };
@@ -69,8 +86,13 @@ static void *ble_hci_uart_rx_cmd_arg;
 static ble_hci_trans_rx_acl_fn *ble_hci_uart_rx_acl_cb;
 static void *ble_hci_uart_rx_acl_arg;
 
-static struct os_mempool ble_hci_uart_evt_pool;
-static void *ble_hci_uart_evt_buf;
+static struct os_mempool ble_hci_uart_evt_hi_pool;
+static void *ble_hci_uart_evt_hi_buf;
+static struct os_mempool ble_hci_uart_evt_lo_pool;
+static void *ble_hci_uart_evt_lo_buf;
+
+static struct os_mempool ble_hci_uart_cmd_pool;
+static void *ble_hci_uart_cmd_buf;
 
 static struct os_mempool ble_hci_uart_pkt_pool;
 static void *ble_hci_uart_pkt_buf;
@@ -93,7 +115,9 @@ struct ble_hci_uart_cmd {
  */
 struct ble_hci_uart_acl {
     struct os_mbuf *buf; /* Buffer containing the data */
+    uint8_t *dptr;       /* Pointer to where bytes should be placed */
     uint16_t len;        /* Target size when buf is considered complete */
+    uint16_t rxd_bytes;  /* current count of bytes received for packet */
 };
 
 /**
@@ -124,6 +148,7 @@ static struct {
 } ble_hci_uart_state;
 
 static struct ble_hci_uart_cfg ble_hci_uart_cfg;
+static uint16_t ble_hci_uart_max_acl_datalen;
 
 /**
  * Allocates a buffer (mbuf) for ACL operation.
@@ -286,6 +311,26 @@ ble_hci_uart_tx_char(void *arg)
     return rc;
 }
 
+#ifdef FEATURE_BLE_DEVICE
+/**
+ * HCI uart sync loss.
+ *
+ * This occurs when the controller receives an invalid packet type or a length
+ * field that is out of range. The controller needs to send a HW error to the
+ * host and wait to find a LL reset command.
+ */
+static void
+ble_hci_uart_sync_lost(void)
+{
+    ble_hci_uart_state.rx_cmd.len = 0;
+    ble_hci_uart_state.rx_cmd.cur = 0;
+    ble_hci_uart_state.rx_cmd.data =
+        ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+    ble_ll_hw_error(BLE_HW_ERR_HCI_SYNC_LOSS);
+    ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SYNC_LOSS;
+}
+#endif
+
 /**
  * @return                      The type of packet to follow success;
  *                              -1 if there is no valid packet to receive.
@@ -293,26 +338,31 @@ ble_hci_uart_tx_char(void *arg)
 static int
 ble_hci_uart_rx_pkt_type(uint8_t data)
 {
+    struct os_mbuf *m;
+
     ble_hci_uart_state.rx_type = data;
 
-    /* XXX: For now we assert that buffer allocation succeeds.  The correct
-     * thing to do is return -1 on allocation failure so that flow control is
-     * engaged.  Then, we will need to tell the UART to start receiving again
-     * as follows:
-     *     o flat buf: when we free a buffer.
-     *     o mbuf: periodically? (which task executes the callout?)
-     */
     switch (ble_hci_uart_state.rx_type) {
+    /* Host should never receive a command! */
+#ifdef FEATURE_BLE_DEVICE
     case BLE_HCI_UART_H4_CMD:
-        ble_hci_uart_state.rx_cmd.data =
-            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
-        assert(ble_hci_uart_state.rx_cmd.data != NULL);
-
         ble_hci_uart_state.rx_cmd.len = 0;
         ble_hci_uart_state.rx_cmd.cur = 0;
+        ble_hci_uart_state.rx_cmd.data =
+            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+        if (ble_hci_uart_state.rx_cmd.data == NULL) {
+            ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_CMD;
+        }
         break;
+#endif
 
+        /* Controller should never receive an event */
+#ifdef FEATURE_BLE_HOST
     case BLE_HCI_UART_H4_EVT:
+        /*
+         * XXX: we should not assert if host cannot allocate an event. Need
+         * to determine what to do here.
+         */
         ble_hci_uart_state.rx_cmd.data =
             ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
         assert(ble_hci_uart_state.rx_cmd.data != NULL);
@@ -320,22 +370,97 @@ ble_hci_uart_rx_pkt_type(uint8_t data)
         ble_hci_uart_state.rx_cmd.len = 0;
         ble_hci_uart_state.rx_cmd.cur = 0;
         break;
+#endif
 
     case BLE_HCI_UART_H4_ACL:
-        ble_hci_uart_state.rx_acl.buf = ble_hci_trans_acl_buf_alloc();
-        assert(ble_hci_uart_state.rx_acl.buf != NULL);
-
         ble_hci_uart_state.rx_acl.len = 0;
+        ble_hci_uart_state.rx_acl.rxd_bytes = 0;
+        m = ble_hci_trans_acl_buf_alloc();
+        if (m) {
+            ble_hci_uart_state.rx_acl.dptr = m->om_data;
+        } else {
+            ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_SKIP_ACL;
+        }
+        ble_hci_uart_state.rx_acl.buf = m;
         break;
 
     default:
+#ifdef FEATURE_BLE_DEVICE
+        /*
+         * If we receive an unknown HCI packet type this is considered a loss
+         * of sync.
+         */
+        ble_hci_uart_sync_lost();
+#else
+        /*
+         * XXX: not sure what to do about host in this case. Just go back to
+         * none for now.
+         */
         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
-        return -1;
+#endif
+        break;
     }
 
     return 0;
 }
 
+#ifdef FEATURE_BLE_DEVICE
+/**
+ * HCI uart sync loss.
+ *
+ * Find a LL reset command in the byte stream. The LL reset command is a
+ * sequence of 4 bytes:
+ *  0x01    HCI Packet Type = HCI CMD
+ *  0x03    OCF for reset command
+ *  0x0C    OGF for reset command (0x03 shifted left by two bits as the OGF
+ *          occupies the uopper 6 bits of this byte.
+ *  0x00    Parameter length of reset command (no parameters).
+ *
+ * @param data Byte received over serial port
+ */
+void
+ble_hci_uart_rx_sync_loss(uint8_t data)
+{
+    int rc;
+    int index;
+
+    /*
+     * If we couldnt allocate a command buffer (should not occur but
+     * possible) try to allocate one on each received character. If we get
+     * a reset and buffer is not available we have to ignore reset.
+     */
+    if (ble_hci_uart_state.rx_cmd.data == NULL) {
+        ble_hci_uart_state.rx_cmd.data =
+            ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_CMD);
+    }
+
+    index = ble_hci_uart_state.rx_cmd.cur;
+    if (data == ble_hci_uart_reset_cmd[index]) {
+        if (index == 3) {
+            if (ble_hci_uart_state.rx_cmd.data == NULL) {
+                index = 0;
+            } else {
+                assert(ble_hci_uart_rx_cmd_cb != NULL);
+                ble_hci_uart_state.rx_cmd.data[0] = 0x03;
+                ble_hci_uart_state.rx_cmd.data[1] = 0x0C;
+                ble_hci_uart_state.rx_cmd.data[2] = 0x00;
+                rc = ble_hci_uart_rx_cmd_cb(ble_hci_uart_state.rx_cmd.data,
+                                            ble_hci_uart_rx_cmd_arg);
+                if (rc != 0) {
+                    ble_hci_trans_buf_free(ble_hci_uart_state.rx_cmd.data);
+                }
+                ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
+            }
+        } else {
+            ++index;
+        }
+    } else {
+        index = 0;
+    }
+
+    ble_hci_uart_state.rx_cmd.cur = index;
+}
+
 static void
 ble_hci_uart_rx_cmd(uint8_t data)
 {
@@ -364,6 +489,33 @@ ble_hci_uart_rx_cmd(uint8_t data)
 }
 
 static void
+ble_hci_uart_rx_skip_cmd(uint8_t data)
+{
+    ble_hci_uart_state.rx_cmd.cur++;
+
+    if (ble_hci_uart_state.rx_cmd.cur < BLE_HCI_CMD_HDR_LEN) {
+        return;
+    }
+
+    if (ble_hci_uart_state.rx_cmd.cur == BLE_HCI_CMD_HDR_LEN) {
+        ble_hci_uart_state.rx_cmd.len = data + BLE_HCI_CMD_HDR_LEN;
+    }
+
+    if (ble_hci_uart_state.rx_cmd.cur == ble_hci_uart_state.rx_cmd.len) {
+        /*
+         * XXX: for now we simply skip the command and do nothing. This
+         * should not happen but at least we retain HCI synch. The host
+         * can decide what to do in this case. It may be appropriate for
+         * the controller to attempt to send back a command complete or
+         * command status in this case.
+         */
+        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
+    }
+}
+#endif
+
+#ifdef FEATURE_BLE_HOST
+static void
 ble_hci_uart_rx_evt(uint8_t data)
 {
     int rc;
@@ -389,53 +541,111 @@ ble_hci_uart_rx_evt(uint8_t data)
         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
     }
 }
+#endif
 
 static void
 ble_hci_uart_rx_acl(uint8_t data)
 {
+    uint16_t rxd_bytes;
     uint16_t pktlen;
 
-    os_mbuf_append(ble_hci_uart_state.rx_acl.buf, &data, 1);
-
-    pktlen = OS_MBUF_PKTLEN(ble_hci_uart_state.rx_acl.buf);
+    rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
+    ble_hci_uart_state.rx_acl.dptr[rxd_bytes] = data;
+    ++rxd_bytes;
+    ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
 
-    if (pktlen < BLE_HCI_DATA_HDR_SZ) {
+    if (rxd_bytes < BLE_HCI_DATA_HDR_SZ) {
         return;
     }
 
-    if (pktlen == BLE_HCI_DATA_HDR_SZ) {
-        os_mbuf_copydata(ble_hci_uart_state.rx_acl.buf, 2,
-                         sizeof(ble_hci_uart_state.rx_acl.len),
-                         &ble_hci_uart_state.rx_acl.len);
-        ble_hci_uart_state.rx_acl.len =
-            le16toh(&ble_hci_uart_state.rx_acl.len) + BLE_HCI_DATA_HDR_SZ;
+    if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
+        pktlen = ble_hci_uart_state.rx_acl.dptr[3];
+        pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.dptr[2];
+        ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
+
+        /*
+         * Data portion cannot exceed data length of acl buffer. If it does
+         * this is considered to be a loss of sync.
+         */
+        if (pktlen > ble_hci_uart_max_acl_datalen) {
+            os_mbuf_free_chain(ble_hci_uart_state.rx_acl.buf);
+            ble_hci_uart_sync_lost();
+        }
     }
 
-    if (pktlen == ble_hci_uart_state.rx_acl.len) {
-        assert(ble_hci_uart_rx_cmd_cb != NULL);
+    if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
+        assert(ble_hci_uart_rx_acl_cb != NULL);
+        /* XXX: can this callback fail? What if it does? */
+        OS_MBUF_PKTLEN(ble_hci_uart_state.rx_acl.buf) = rxd_bytes;
+        ble_hci_uart_state.rx_acl.buf->om_len = rxd_bytes;
         ble_hci_uart_rx_acl_cb(ble_hci_uart_state.rx_acl.buf,
                                ble_hci_uart_rx_acl_arg);
         ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
     }
 }
 
+static void
+ble_hci_uart_rx_skip_acl(uint8_t data)
+{
+    uint16_t rxd_bytes;
+    uint16_t pktlen;
+
+    rxd_bytes = ble_hci_uart_state.rx_acl.rxd_bytes;
+    ++rxd_bytes;
+    ble_hci_uart_state.rx_acl.rxd_bytes = rxd_bytes;
+
+    if (rxd_bytes == (BLE_HCI_DATA_HDR_SZ - 1)) {
+        ble_hci_uart_state.rx_acl.len = data;
+        return;
+    }
+
+    if (rxd_bytes == BLE_HCI_DATA_HDR_SZ) {
+        pktlen = data;
+        pktlen = (pktlen << 8) + ble_hci_uart_state.rx_acl.len;
+        ble_hci_uart_state.rx_acl.len = pktlen + BLE_HCI_DATA_HDR_SZ;
+    }
+
+    if (rxd_bytes == ble_hci_uart_state.rx_acl.len) {
+/* XXX: I dont like this but for now this denotes controller only */
+#ifdef FEATURE_BLE_DEVICE
+        ble_ll_data_buffer_overflow();
+#endif
+        ble_hci_uart_state.rx_type = BLE_HCI_UART_H4_NONE;
+    }
+}
+
 static int
 ble_hci_uart_rx_char(void *arg, uint8_t data)
 {
     switch (ble_hci_uart_state.rx_type) {
     case BLE_HCI_UART_H4_NONE:
         return ble_hci_uart_rx_pkt_type(data);
+#ifdef FEATURE_BLE_DEVICE
     case BLE_HCI_UART_H4_CMD:
         ble_hci_uart_rx_cmd(data);
         return 0;
+    case BLE_HCI_UART_H4_SKIP_CMD:
+        ble_hci_uart_rx_skip_cmd(data);
+        return 0;
+    case BLE_HCI_UART_H4_SYNC_LOSS:
+        ble_hci_uart_rx_sync_loss(data);
+        return 0;
+#endif
+#ifdef FEATURE_BLE_HOST
     case BLE_HCI_UART_H4_EVT:
         ble_hci_uart_rx_evt(data);
         return 0;
+#endif
     case BLE_HCI_UART_H4_ACL:
         ble_hci_uart_rx_acl(data);
         return 0;
+    case BLE_HCI_UART_H4_SKIP_ACL:
+        ble_hci_uart_rx_skip_acl(data);
+        return 0;
     default:
-        return -1;
+        /* This should never happen! */
+        assert(0);
+        return 0;
     }
 }
 
@@ -476,14 +686,20 @@ ble_hci_uart_free_pkt(uint8_t type, uint8_t *cmdevt, struct os_mbuf *acl)
 static void
 ble_hci_uart_free_mem(void)
 {
-    free(ble_hci_uart_evt_buf);
-    ble_hci_uart_evt_buf = NULL;
+    free(ble_hci_uart_evt_hi_buf);
+    ble_hci_uart_evt_hi_buf = NULL;
+
+    free(ble_hci_uart_evt_lo_buf);
+    ble_hci_uart_evt_lo_buf = NULL;
 
     free(ble_hci_uart_pkt_buf);
     ble_hci_uart_pkt_buf = NULL;
 
     free(ble_hci_uart_acl_buf);
     ble_hci_uart_acl_buf = NULL;
+
+    free(ble_hci_uart_cmd_buf);
+    ble_hci_uart_cmd_buf = NULL;
 }
 
 static int
@@ -642,9 +858,20 @@ ble_hci_trans_buf_alloc(int type)
 
     switch (type) {
     case BLE_HCI_TRANS_BUF_CMD:
-    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_uart_cmd_pool);
+        break;
     case BLE_HCI_TRANS_BUF_EVT_HI:
-        buf = os_memblock_get(&ble_hci_uart_evt_pool);
+        buf = os_memblock_get(&ble_hci_uart_evt_hi_pool);
+        if (buf == NULL) {
+            /* If no high-priority event buffers remain, try to grab a
+             * low-priority one.
+             */
+            buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
+        }
+        break;
+
+    case BLE_HCI_TRANS_BUF_EVT_LO:
+        buf = os_memblock_get(&ble_hci_uart_evt_lo_pool);
         break;
 
     default:
@@ -666,8 +893,25 @@ ble_hci_trans_buf_free(uint8_t *buf)
 {
     int rc;
 
-    rc = os_memblock_put(&ble_hci_uart_evt_pool, buf);
-    assert(rc == 0);
+    /*
+     * XXX: this may look a bit odd, but the controller uses the command
+     * buffer to send back the command complete/status as an immediate
+     * response to the command. This was done to insure that the controller
+     * could always send back one of these events when a command was received.
+     * Thus, we check to see which pool the buffer came from so we can free
+     * it to the appropriate pool
+     */
+    if (os_memblock_from(&ble_hci_uart_evt_hi_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_uart_evt_hi_pool, buf);
+        assert(rc == 0);
+    } else if (os_memblock_from(&ble_hci_uart_evt_lo_pool, buf)) {
+        rc = os_memblock_put(&ble_hci_uart_evt_lo_pool, buf);
+        assert(rc == 0);
+    } else {
+        assert(os_memblock_from(&ble_hci_uart_cmd_pool, buf));
+        rc = os_memblock_put(&ble_hci_uart_cmd_pool, buf);
+        assert(rc == 0);
+    }
 }
 
 /**
@@ -737,10 +981,15 @@ ble_hci_uart_init(const struct ble_hci_uart_cfg *cfg)
     /*
      * XXX: For now, we will keep the ACL buffer size such that it can
      * accommodate BLE_MBUF_PAYLOAD_SIZE. It should be possible to make this
-     * user defined but more testing would need to be done in that case.
+     * user defined but more testing would need to be done in that case. The
+     * MBUF payload size must accommodate the HCI data header size plus the
+     * maximum ACL data packet length.
+     *
+     * XXX: Should the max acl data length be part of config?
      */
     acl_block_size = BLE_MBUF_PAYLOAD_SIZE + BLE_MBUF_MEMBLOCK_OVERHEAD;
     acl_block_size = OS_ALIGN(acl_block_size, OS_ALIGNMENT);
+    ble_hci_uart_max_acl_datalen = BLE_MBUF_PAYLOAD_SIZE - BLE_HCI_DATA_HDR_SZ;
     rc = mem_malloc_mempool(&ble_hci_uart_acl_pool,
                             cfg->num_acl_bufs,
                             acl_block_size,
@@ -755,21 +1004,51 @@ ble_hci_uart_init(const struct ble_hci_uart_cfg *cfg)
                            acl_block_size, cfg->num_acl_bufs);
     assert(rc == 0);
 
+    /*
+     * Create memory pool of HCI command buffers. NOTE: we currently dont
+     * allow this to be configured. The controller will only allow one
+     * outstanding command. We decided to keep this a pool in case we allow
+     * allow the controller to handle more than one outstanding command.
+     */
+    rc = mem_malloc_mempool(&ble_hci_uart_cmd_pool,
+                            1,
+                            BLE_HCI_TRANS_CMD_SZ,
+                            "ble_hci_uart_cmd_pool",
+                            &ble_hci_uart_cmd_buf);
+    if (rc != 0) {
+        rc = ble_err_from_os(rc);
+        goto err;
+    }
 
-    /* Create memory pool of HCI command / event buffers */
-    rc = mem_malloc_mempool(&ble_hci_uart_evt_pool,
-                            cfg->num_evt_bufs,
+    rc = mem_malloc_mempool(&ble_hci_uart_evt_hi_pool,
+                            cfg->num_evt_hi_bufs,
                             cfg->evt_buf_sz,
-                            "ble_hci_uart_evt_pool",
-                            &ble_hci_uart_evt_buf);
+                            "ble_hci_uart_evt_hi_pool",
+                            &ble_hci_uart_evt_hi_buf);
     if (rc != 0) {
         rc = ble_err_from_os(rc);
         goto err;
     }
 
-    /* Create memory pool of packet list nodes. */
+    rc = mem_malloc_mempool(&ble_hci_uart_evt_lo_pool,
+                            cfg->num_evt_lo_bufs,
+                            cfg->evt_buf_sz,
+                            "ble_hci_uart_evt_lo_pool",
+                            &ble_hci_uart_evt_lo_buf);
+    if (rc != 0) {
+        rc = ble_err_from_os(rc);
+        goto err;
+    }
+
+    /*
+     * Create memory pool of packet list nodes. NOTE: the number of these
+     * buffers should be, at least, the total number of event buffers (hi
+     * and lo), the number of command buffers (currently 1) and the total
+     * number of buffers that the controller could possibly hand to the host.
+     */
     rc = mem_malloc_mempool(&ble_hci_uart_pkt_pool,
-                            cfg->num_evt_bufs,
+                            cfg->num_evt_hi_bufs + cfg->num_evt_lo_bufs + 1 +
+                            cfg->num_msys_bufs,
                             sizeof (struct ble_hci_uart_pkt),
                             "ble_hci_uart_pkt_pool",
                             &ble_hci_uart_pkt_buf);


[09/19] incubator-mynewt-core git commit: Add Apache License header. Not sure why this was omitted.

Posted by cc...@apache.org.
Add Apache License header. Not sure why this was omitted.


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

Branch: refs/heads/develop
Commit: dd79d9310ae84e9f7090ab09141f9916f2c2e102
Parents: 959b389
Author: William San Filippo <wi...@runtime.io>
Authored: Fri Sep 16 15:43:47 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Fri Sep 16 15:43:47 2016 -0700

----------------------------------------------------------------------
 net/nimble/transport/ram/src/ble_hci_ram.c | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/dd79d931/net/nimble/transport/ram/src/ble_hci_ram.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/ram/src/ble_hci_ram.c b/net/nimble/transport/ram/src/ble_hci_ram.c
index e3d236e..3a4ef54 100644
--- a/net/nimble/transport/ram/src/ble_hci_ram.c
+++ b/net/nimble/transport/ram/src/ble_hci_ram.c
@@ -1,3 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
 #include <assert.h>
 #include <errno.h>
 #include <stddef.h>


[08/19] incubator-mynewt-core git commit: MYNEWT-387: Separate ACL data buffer pool for controller only

Posted by cc...@apache.org.
MYNEWT-387: Separate ACL data buffer pool for controller only

This change insures that there is the proper user header on the
mbufs that the HCI interface hands to the controller. It worked
before as the controller was using the bytes that were stripped
from the hci header.


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

Branch: refs/heads/develop
Commit: 959b389154a3f65e4347642d624bceca6479622f
Parents: 6773301
Author: William San Filippo <wi...@runtime.io>
Authored: Tue Sep 13 12:27:44 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Tue Sep 13 12:34:59 2016 -0700

----------------------------------------------------------------------
 net/nimble/transport/uart/src/ble_hci_uart.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/959b3891/net/nimble/transport/uart/src/ble_hci_uart.c
----------------------------------------------------------------------
diff --git a/net/nimble/transport/uart/src/ble_hci_uart.c b/net/nimble/transport/uart/src/ble_hci_uart.c
index 98e3eb2..8cf5b9e 100755
--- a/net/nimble/transport/uart/src/ble_hci_uart.c
+++ b/net/nimble/transport/uart/src/ble_hci_uart.c
@@ -136,7 +136,12 @@ ble_hci_trans_acl_buf_alloc(void)
 {
     struct os_mbuf *m;
 
-    m = os_mbuf_get_pkthdr(&ble_hci_uart_acl_mbuf_pool, 0);
+    /*
+     * XXX: note that for host only there would be no need to allocate
+     * a user header. Address this later.
+     */
+    m = os_mbuf_get_pkthdr(&ble_hci_uart_acl_mbuf_pool,
+                           sizeof(struct ble_mbuf_hdr));
     return m;
 }
 


[17/19] incubator-mynewt-core git commit: MYNEWT-397: Nimble controller assert if advertising started/stopped frequently

Posted by cc...@apache.org.
MYNEWT-397: Nimble controller assert if advertising started/stopped frequently

There was an assert in the advertising code in the nimble controller that
would assert if the advertising state machine was not enabled and an
advertising event finished. The code contained a race condition where
it was possible that the advertising state machine was stopped but
an advertising end event was processed by the Link Layer. The code will
now ignore advertising packets that are processed after advertising has
been stopped as these events are asynchronous to the controller.


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

Branch: refs/heads/develop
Commit: 1e5239485af3c056b9a053b60b778a30b2635e44
Parents: cc05bf2
Author: William San Filippo <wi...@runtime.io>
Authored: Thu Sep 29 10:45:57 2016 -0700
Committer: William San Filippo <wi...@runtime.io>
Committed: Fri Sep 30 15:42:33 2016 -0700

----------------------------------------------------------------------
 net/nimble/controller/src/ble_ll_adv.c | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1e523948/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 3e2ce1f..24a8416 100644
--- a/net/nimble/controller/src/ble_ll_adv.c
+++ b/net/nimble/controller/src/ble_ll_adv.c
@@ -650,16 +650,18 @@ ble_ll_adv_sm_stop(struct ble_ll_adv_sm *advsm)
     if (advsm->enabled) {
         /* Remove any scheduled advertising items */
         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_phy_disable();
             ble_ll_wfr_disable();
             ble_ll_state_set(BLE_LL_STATE_STANDBY);
         }
         OS_EXIT_CRITICAL(sr);
 
+        os_eventq_remove(&g_ble_ll_data.ll_evq, &advsm->adv_txdone_ev);
+
         /* If there is an event buf we need to free it */
         if (advsm->conn_comp_ev) {
             ble_hci_trans_buf_free(advsm->conn_comp_ev);
@@ -1161,6 +1163,15 @@ ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf, struct ble_mbuf_hdr *hdr)
     int adv_event_over;
 
     /*
+     * It is possible that advertising was stopped and a packet plcaed on the
+     * LL receive packet queue. In this case, just ignore the received packet
+     * as the advertising state machine is no longer "valid"
+     */
+    if (!g_ble_ll_adv_sm.enabled) {
+        return;
+    }
+
+    /*
      * 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