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/17 02:31:53 UTC

[1/5] incubator-mynewt-core git commit: BLE Host - Add test for interrupted indicate.

Repository: incubator-mynewt-core
Updated Branches:
  refs/heads/develop 562093f56 -> 50871d1a6


BLE Host - Add test for interrupted indicate.


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

Branch: refs/heads/develop
Commit: 50871d1a6c32dcc0a6725ea2bd44d05adb1c6366
Parents: 85e6f3c
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Nov 16 18:31:10 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 16 18:31:44 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/test/src/ble_gatt_conn_test.c | 44 +++++++++++++++++++---
 1 file changed, 39 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/50871d1a/net/nimble/host/test/src/ble_gatt_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_gatt_conn_test.c b/net/nimble/host/test/src/ble_gatt_conn_test.c
index d4c941b..6a5cba6 100644
--- a/net/nimble/host/test/src/ble_gatt_conn_test.c
+++ b/net/nimble/host/test/src/ble_gatt_conn_test.c
@@ -34,6 +34,28 @@ struct ble_gatt_conn_test_cb_arg {
     int called;
 };
 
+static struct ble_gap_event ble_gatt_conn_test_gap_event;
+
+static void
+ble_gatt_conn_test_util_init(void)
+{
+    ble_hs_test_util_init();
+    memset(&ble_gatt_conn_test_gap_event, -1,
+           sizeof ble_gatt_conn_test_gap_event);
+}
+
+static int
+ble_gatt_conn_test_indicate_cb(struct ble_gap_event *event, void *arg)
+{
+    /* Only record indication failures. */
+    if (event->type == BLE_GAP_EVENT_NOTIFY_TX &&
+        event->notify_tx.status != 0) {
+
+        ble_gatt_conn_test_gap_event = *event;
+    }
+    return 0;
+}
+
 static int
 ble_gatt_conn_test_attr_cb(uint16_t conn_handle, uint16_t attr_handle,
                            uint8_t op, uint16_t offset, struct os_mbuf **om,
@@ -362,7 +384,7 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     uint16_t attr_handle;
     int rc;
 
-    ble_hs_test_util_init();
+    ble_gatt_conn_test_util_init();
 
     /*** Register an attribute to allow indicatations to be sent. */
     rc = ble_att_svr_register(BLE_UUID16(0x1212), BLE_ATT_F_READ,
@@ -372,11 +394,11 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
 
     /* Create three connections. */
     ble_hs_test_util_create_conn(1, ((uint8_t[]){1,2,3,4,5,6,7,8}),
-                                 NULL, NULL);
+                                 ble_gatt_conn_test_indicate_cb, NULL);
     ble_hs_test_util_create_conn(2, ((uint8_t[]){2,3,4,5,6,7,8,9}),
-                                 NULL, NULL);
+                                 ble_gatt_conn_test_indicate_cb, NULL);
     ble_hs_test_util_create_conn(3, ((uint8_t[]){3,4,5,6,7,8,9,10}),
-                                 NULL, NULL);
+                                 ble_gatt_conn_test_indicate_cb, NULL);
 
     /*** Schedule some GATT procedures. */
     /* Connection 1. */
@@ -461,6 +483,9 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
         3, &attr, 1, ble_gatt_conn_test_write_rel_cb, &write_rel_arg);
     TEST_ASSERT_FATAL(rc == 0);
 
+    rc = ble_gattc_indicate(3, attr_handle);
+    TEST_ASSERT_FATAL(rc == 0);
+
     /*** Start the procedures. */
     ble_hs_test_util_tx_all();
 
@@ -481,6 +506,7 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     TEST_ASSERT(write_arg.called == 0);
     TEST_ASSERT(write_long_arg.called == 0);
     TEST_ASSERT(write_rel_arg.called == 0);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255);
 
     /* Connection 2. */
     ble_gattc_connection_broken(2);
@@ -498,6 +524,7 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     TEST_ASSERT(write_arg.called == 0);
     TEST_ASSERT(write_long_arg.called == 0);
     TEST_ASSERT(write_rel_arg.called == 0);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.type == 255);
 
     /* Connection 3. */
     ble_gattc_connection_broken(3);
@@ -515,6 +542,13 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     TEST_ASSERT(write_arg.called == 1);
     TEST_ASSERT(write_long_arg.called == 1);
     TEST_ASSERT(write_rel_arg.called == 1);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.type == BLE_GAP_EVENT_NOTIFY_TX);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.status ==
+                BLE_HS_ENOTCONN);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.conn_handle == 3);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.attr_handle ==
+                attr_handle);
+    TEST_ASSERT(ble_gatt_conn_test_gap_event.notify_tx.indication);
 }
 
 static void
@@ -549,7 +583,7 @@ TEST_CASE(ble_gatt_conn_test_timeout)
     uint16_t attr_handle;
     int rc;
 
-    ble_hs_test_util_init();
+    ble_gatt_conn_test_util_init();
 
     ticks_from_now = ble_gattc_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);


[3/5] incubator-mynewt-core git commit: BLE Host - Compilation error for SC without DEBUG.

Posted by cc...@apache.org.
BLE Host - Compilation error for SC without DEBUG.


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

Branch: refs/heads/develop
Commit: a38b75732363899ab24cf1a47de5aa9a4e778c62
Parents: 562093f
Author: Christopher Collins <cc...@apache.org>
Authored: Mon Nov 14 10:57:52 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 16 18:31:44 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_sm_sc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/a38b7573/net/nimble/host/src/ble_sm_sc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm_sc.c b/net/nimble/host/src/ble_sm_sc.c
index 19a5ca9..11b29a1 100644
--- a/net/nimble/host/src/ble_sm_sc.c
+++ b/net/nimble/host/src/ble_sm_sc.c
@@ -89,12 +89,12 @@ static const uint8_t ble_sm_sc_resp_ioa[5 /*resp*/ ][5 /*init*/ ] =
       {IOACT_INPUT,   IOACT_NUMCMP, IOACT_DISP,  IOACT_NONE, IOACT_NUMCMP},
 };
 
+#if MYNEWT_VAL(BLE_HS_DEBUG)
+
 static uint8_t ble_sm_dbg_sc_pub_key[64];
 static uint8_t ble_sm_dbg_sc_priv_key[32];
 static uint8_t ble_sm_dbg_sc_keys_set;
 
-#if MYNEWT_VAL(BLE_HS_DEBUG)
-
 void
 ble_sm_dbg_set_sc_keys(uint8_t *pubkey, uint8_t *privkey)
 {


[4/5] incubator-mynewt-core git commit: BLE Host - Unit tests for GATT timeouts.

Posted by cc...@apache.org.
BLE Host - Unit tests for GATT timeouts.


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

Branch: refs/heads/develop
Commit: 85e6f3ca290c42ce1893837710676507d9b13746
Parents: d0cc833
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Nov 16 18:11:35 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 16 18:31:44 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_hs_hci_cmd.c          |   2 +-
 net/nimble/host/test/src/ble_gatt_conn_test.c | 159 ++++++++++++++++++++-
 net/nimble/host/test/src/ble_hs_test_util.c   |  32 ++++-
 net/nimble/host/test/src/ble_hs_test_util.h   |   3 +
 4 files changed, 188 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/85e6f3ca/net/nimble/host/src/ble_hs_hci_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_cmd.c b/net/nimble/host/src/ble_hs_hci_cmd.c
index 923bcc9..0f2d981 100644
--- a/net/nimble/host/src/ble_hs_hci_cmd.c
+++ b/net/nimble/host/src/ble_hs_hci_cmd.c
@@ -391,7 +391,7 @@ ble_hs_hci_cmd_build_disconnect(uint16_t handle, uint8_t reason,
         dst_len >= BLE_HCI_CMD_HDR_LEN + BLE_HCI_DISCONNECT_CMD_LEN);
 
     ble_hs_hci_cmd_write_hdr(BLE_HCI_OGF_LINK_CTRL, BLE_HCI_OCF_DISCONNECT_CMD,
-                       BLE_HCI_DISCONNECT_CMD_LEN, dst);
+                             BLE_HCI_DISCONNECT_CMD_LEN, dst);
     dst += BLE_HCI_CMD_HDR_LEN;
 
     ble_hs_hci_cmd_body_disconnect(handle, reason, dst);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/85e6f3ca/net/nimble/host/test/src/ble_gatt_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_gatt_conn_test.c b/net/nimble/host/test/src/ble_gatt_conn_test.c
index 50f661d..d4c941b 100644
--- a/net/nimble/host/test/src/ble_gatt_conn_test.c
+++ b/net/nimble/host/test/src/ble_gatt_conn_test.c
@@ -517,17 +517,172 @@ TEST_CASE(ble_gatt_conn_test_disconnect)
     TEST_ASSERT(write_rel_arg.called == 1);
 }
 
-TEST_SUITE(ble_gatt_break_suite)
+static void
+ble_gatt_conn_test_util_timeout(uint16_t conn_handle)
+{
+    int32_t ticks_from_now;
+
+    ticks_from_now = ble_gattc_timer();
+    TEST_ASSERT(ticks_from_now == 30 * OS_TICKS_PER_SEC);
+
+    os_time_advance(29 * OS_TICKS_PER_SEC);
+    ticks_from_now = ble_gattc_timer();
+    TEST_ASSERT(ticks_from_now == 1 * OS_TICKS_PER_SEC);
+
+    ble_hs_test_util_set_ack_disconnect(0);
+    os_time_advance(1 * OS_TICKS_PER_SEC);
+    ticks_from_now = ble_gattc_timer();
+    TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+    /* Ensure connection was terminated due to proecedure timeout. */
+    ble_hs_test_util_verify_tx_disconnect(conn_handle,
+                                          BLE_ERR_REM_USER_CONN_TERM);
+    ble_hs_test_util_rx_disconn_complete(conn_handle,
+                                         BLE_ERR_REM_USER_CONN_TERM);
+}
+
+TEST_CASE(ble_gatt_conn_test_timeout)
+{
+    static const uint8_t peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
+    struct ble_gatt_attr attr;
+    int32_t ticks_from_now;
+    uint16_t attr_handle;
+    int rc;
+
+    ble_hs_test_util_init();
+
+    ticks_from_now = ble_gattc_timer();
+    TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
+
+    /*** Register an attribute to allow indicatations to be sent. */
+    rc = ble_att_svr_register(BLE_UUID16(0x1212), BLE_ATT_F_READ,
+                              &attr_handle,
+                              ble_gatt_conn_test_attr_cb, NULL);
+    TEST_ASSERT(rc == 0);
+
+    /*** MTU. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_exchange_mtu(1, ble_gatt_conn_test_mtu_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Discover all services. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_disc_all_svcs(1, ble_gatt_conn_test_disc_all_svcs_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Discover services by UUID. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_disc_svc_by_uuid(1, BLE_UUID16(0x1111),
+                                    ble_gatt_conn_test_disc_svc_uuid_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Find included services. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_find_inc_svcs(1, 1, 0xffff,
+                                 ble_gatt_conn_test_find_inc_svcs_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Discover all characteristics. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_disc_all_chrs(1, 1, 0xffff,
+                                 ble_gatt_conn_test_disc_all_chrs_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Discover all descriptors. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_disc_all_dscs(1, 3, 0xffff,
+                                 ble_gatt_conn_test_disc_all_dscs_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Discover characteristics by UUID. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_disc_chrs_by_uuid(1, 2, 0xffff, BLE_UUID16(0x2222),
+                                     ble_gatt_conn_test_disc_chr_uuid_cb,
+                                     NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Read. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_read(1, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+                        ble_gatt_conn_test_read_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Read by UUID. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_read_by_uuid(1, 1, 0xffff, BLE_UUID16(0x3333),
+                                ble_gatt_conn_test_read_uuid_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Read long. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_read_long(1, BLE_GATT_BREAK_TEST_READ_ATTR_HANDLE,
+                             ble_gatt_conn_test_read_long_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Read multiple. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_read_mult(1, ((uint16_t[3]){5,6,7}), 3,
+                             ble_gatt_conn_test_read_mult_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Write. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_hs_test_util_gatt_write_flat(
+        1, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+        ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+        ble_gatt_conn_test_write_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Write long. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_hs_test_util_gatt_write_long_flat(
+        1, BLE_GATT_BREAK_TEST_WRITE_ATTR_HANDLE,
+        ble_gatt_conn_test_write_value, sizeof ble_gatt_conn_test_write_value,
+        ble_gatt_conn_test_write_long_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Write reliable. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    attr.handle = 8;
+    attr.offset = 0;
+    attr.om = os_msys_get_pkthdr(0, 0);
+    rc = ble_gattc_write_reliable(
+        1, &attr, 1, ble_gatt_conn_test_write_rel_cb, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+
+    /*** Indication. */
+    ble_hs_test_util_create_conn(1, peer_addr, NULL, NULL);
+    rc = ble_gattc_indicate(1, attr_handle);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_gatt_conn_test_util_timeout(1);
+}
+
+TEST_SUITE(ble_gatt_conn_suite)
 {
     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
 
     ble_gatt_conn_test_disconnect();
+    ble_gatt_conn_test_timeout();
 }
 
 int
 ble_gatt_conn_test_all(void)
 {
-    ble_gatt_break_suite();
+    ble_gatt_conn_suite();
 
     return tu_any_failed;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/85e6f3ca/net/nimble/host/test/src/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_test_util.c b/net/nimble/host/test/src/ble_hs_test_util.c
index 55528dd..0e9ef43 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.c
+++ b/net/nimble/host/test/src/ble_hs_test_util.c
@@ -445,6 +445,21 @@ ble_hs_test_util_hcc_from_conn_params(
 }
 
 void
+ble_hs_test_util_verify_tx_disconnect(uint16_t handle, uint8_t reason)
+{
+    uint8_t param_len;
+    uint8_t *param;
+
+    param = ble_hs_test_util_verify_tx_hci(BLE_HCI_OGF_LINK_CTRL,
+                                           BLE_HCI_OCF_DISCONNECT_CMD,
+                                           &param_len);
+    TEST_ASSERT(param_len == BLE_HCI_DISCONNECT_CMD_LEN);
+
+    TEST_ASSERT(le16toh(param + 0) == handle);
+    TEST_ASSERT(param[2] == reason);
+}
+
+void
 ble_hs_test_util_verify_tx_create_conn(const struct hci_create_conn *exp)
 {
     uint8_t param_len;
@@ -559,19 +574,26 @@ 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)
+ble_hs_test_util_rx_disconn_complete(uint16_t conn_handle, uint8_t reason)
 {
     struct hci_disconn_complete evt;
+
+    evt.connection_handle = conn_handle;
+    evt.status = 0;
+    evt.reason = BLE_ERR_CONN_TERM_LOCAL;
+    ble_gap_rx_disconn_complete(&evt);
+}
+
+void
+ble_hs_test_util_conn_disconnect(uint16_t conn_handle)
+{
     int rc;
 
     rc = ble_hs_test_util_conn_terminate(conn_handle, 0);
     TEST_ASSERT_FATAL(rc == 0);
 
     /* Receive disconnection complete event. */
-    evt.connection_handle = conn_handle;
-    evt.status = 0;
-    evt.reason = BLE_ERR_CONN_TERM_LOCAL;
-    ble_gap_rx_disconn_complete(&evt);
+    ble_hs_test_util_rx_disconn_complete(conn_handle, BLE_ERR_CONN_TERM_LOCAL);
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/85e6f3ca/net/nimble/host/test/src/ble_hs_test_util.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_test_util.h b/net/nimble/host/test/src/ble_hs_test_util.h
index 923be22..ab9b708 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.h
+++ b/net/nimble/host/test/src/ble_hs_test_util.h
@@ -100,6 +100,8 @@ 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_rx_disconn_complete(uint16_t conn_handle,
+                                          uint8_t reason);
 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,
                                     uint8_t fail_status);
@@ -108,6 +110,7 @@ int ble_hs_test_util_disc(uint8_t own_addr_type, int32_t duration_ms,
                           ble_gap_event_fn *cb, void *cb_arg, int fail_idx,
                           uint8_t fail_status);
 int ble_hs_test_util_disc_cancel(uint8_t ack_status);
+void ble_hs_test_util_verify_tx_disconnect(uint16_t handle, uint8_t reason);
 void ble_hs_test_util_verify_tx_create_conn(const struct hci_create_conn *exp);
 int ble_hs_test_util_adv_set_fields(struct ble_hs_adv_fields *adv_fields,
                                     uint8_t hci_status);


[2/5] incubator-mynewt-core git commit: BLE Host - Eliminate spurious time expirations.

Posted by cc...@apache.org.
BLE Host - Eliminate spurious time expirations.

Prior to this change, the host timer would expire at least once per
second to clean up expired procedures.  This approach was used in lieu
of more diligent bookkeeping.  Functionally, this is OK, since these
timers don't need to be particularly precise.  However, this approach is
bad for power management, as it requires the processor to periodically
wake up from deep sleep when there is no work to do.


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

Branch: refs/heads/develop
Commit: d0cc83304baacb1626a5540323316bf9a6f094ed
Parents: 2fcb28b
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Nov 16 16:29:44 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 16 18:31:44 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_gap.c           |  69 ++++++++---------
 net/nimble/host/src/ble_gap_priv.h      |   2 +-
 net/nimble/host/src/ble_gatt_priv.h     |   2 +-
 net/nimble/host/src/ble_gattc.c         |  46 +++++++-----
 net/nimble/host/src/ble_hs.c            | 106 ++++++++++++++-------------
 net/nimble/host/src/ble_hs_priv.h       |   2 +-
 net/nimble/host/src/ble_l2cap_sig.c     |  10 +--
 net/nimble/host/src/ble_sm.c            |  43 ++++++-----
 net/nimble/host/src/ble_sm_priv.h       |   4 +-
 net/nimble/host/test/src/ble_gap_test.c |  28 +++----
 10 files changed, 161 insertions(+), 151 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/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 ca53187..6d83a9b 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -508,6 +508,8 @@ ble_gap_master_reset_state(void)
     ble_gap_master.op = BLE_GAP_OP_NULL;
     ble_gap_master.exp_set = 0;
     ble_gap_master.conn.cancel = 0;
+
+    ble_hs_timer_resched();
 }
 
 static void
@@ -515,6 +517,8 @@ ble_gap_slave_reset_state(void)
 {
     ble_gap_slave.op = BLE_GAP_OP_NULL;
     ble_gap_slave.exp_set = 0;
+
+    ble_hs_timer_resched();
 }
 
 static void
@@ -697,6 +701,17 @@ ble_gap_slave_ticks_until_exp(void)
     return 0;
 }
 
+/**
+ * Finds the update procedure that expires soonest.
+ *
+ * @param out_ticks_from_now    On success, the ticks until the update
+ *                                  procedure's expiry time gets written here.
+ *
+ * @return                      The connection handle of the update procedure
+ *                                  that expires soonest, or
+ *                                  BLE_HS_CONN_HANDLE_NONE if there are no
+ *                                  active update procedures.
+ */
 static uint16_t
 ble_gap_update_next_exp(int32_t *out_ticks_from_now)
 {
@@ -732,38 +747,13 @@ ble_gap_update_next_exp(int32_t *out_ticks_from_now)
 
 }
 
-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();
-    upd_ticks = ble_gap_update_ticks_until_exp();
-    ticks = min(min(mst_ticks, slv_ticks), upd_ticks);
-
-    ble_hs_heartbeat_sched(ticks);
-}
-
 static void
 ble_gap_master_set_timer(uint32_t ticks_from_now)
 {
     ble_gap_master.exp_os_ticks = os_time_get() + ticks_from_now;
     ble_gap_master.exp_set = 1;
 
-    ble_gap_heartbeat_sched();
+    ble_hs_timer_resched();
 }
 
 static void
@@ -772,7 +762,7 @@ ble_gap_slave_set_timer(uint32_t ticks_from_now)
     ble_gap_slave.exp_os_ticks = os_time_get() + ticks_from_now;
     ble_gap_slave.exp_set = 1;
 
-    ble_gap_heartbeat_sched();
+    ble_hs_timer_resched();
 }
 
 /**
@@ -1251,7 +1241,7 @@ ble_gap_rx_l2cap_update_req(uint16_t conn_handle,
 }
 
 static int32_t
-ble_gap_master_heartbeat(void)
+ble_gap_master_timer(void)
 {
     uint32_t ticks_until_exp;
     int rc;
@@ -1303,7 +1293,7 @@ ble_gap_master_heartbeat(void)
 }
 
 static int32_t
-ble_gap_slave_heartbeat(void)
+ble_gap_slave_timer(void)
 {
     uint32_t ticks_until_exp;
     int rc;
@@ -1333,7 +1323,7 @@ ble_gap_slave_heartbeat(void)
 }
 
 static int32_t
-ble_gap_update_heartbeat(void)
+ble_gap_update_timer(void)
 {
     struct ble_gap_update_entry *entry;
     int32_t ticks_until_exp;
@@ -1361,23 +1351,21 @@ ble_gap_update_heartbeat(void)
 }
 
 /**
- * Handles timed-out master procedures.
- *
- * Called by the heartbeat timer; executed at least once a second.
+ * Handles timed-out GAP procedures.
  *
  * @return                      The number of ticks until this function should
  *                                  be called again.
  */
 int32_t
-ble_gap_heartbeat(void)
+ble_gap_timer(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();
+    master_ticks = ble_gap_master_timer();
+    slave_ticks = ble_gap_slave_timer();
+    update_ticks = ble_gap_update_timer();
 
     return min(min(master_ticks, slave_ticks), update_ticks);
 }
@@ -1569,6 +1557,7 @@ done:
     if (rc != 0) {
         STATS_INC(ble_gap_stats, adv_set_fields_fail);
     }
+
     return rc;
 }
 
@@ -2167,6 +2156,7 @@ done:
     if (rc != 0) {
         STATS_INC(ble_gap_stats, discover_cancel_fail);
     }
+
     return rc;
 }
 
@@ -2718,6 +2708,7 @@ ble_gap_update_entry_remove(uint16_t conn_handle)
         } else {
             SLIST_NEXT(prev, next) = SLIST_NEXT(entry, next);
         }
+        ble_hs_timer_resched();
     }
 
     return entry;
@@ -2941,7 +2932,9 @@ ble_gap_update_params(uint16_t conn_handle,
 done:
     ble_hs_unlock();
 
-    if (rc != 0) {
+    if (rc == 0) {
+        ble_hs_timer_resched();
+    } else {
         ble_gap_update_entry_free(entry);
 
         if (l2cap_params.itvl_min != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_gap_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gap_priv.h b/net/nimble/host/src/ble_gap_priv.h
index 8b73d4c..a1f7429 100644
--- a/net/nimble/host/src/ble_gap_priv.h
+++ b/net/nimble/host/src/ble_gap_priv.h
@@ -97,7 +97,7 @@ void ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu);
 int ble_gap_master_in_progress(void);
 
 void ble_gap_conn_broken(uint16_t conn_handle, int reason);
-int32_t ble_gap_heartbeat(void);
+int32_t ble_gap_timer(void);
 
 int ble_gap_init(void);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_gatt_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gatt_priv.h b/net/nimble/host/src/ble_gatt_priv.h
index e14cf2c..110ced8 100644
--- a/net/nimble/host/src/ble_gatt_priv.h
+++ b/net/nimble/host/src/ble_gatt_priv.h
@@ -129,7 +129,7 @@ void ble_gattc_rx_find_info_idata(uint16_t conn_handle,
 void ble_gattc_rx_find_info_complete(uint16_t conn_handle, int status);
 void ble_gattc_connection_txable(uint16_t conn_handle);
 void ble_gattc_connection_broken(uint16_t conn_handle);
-int32_t ble_gattc_heartbeat(void);
+int32_t ble_gattc_timer(void);
 
 int ble_gattc_any_jobs(void);
 int ble_gattc_init(void);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_gattc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_gattc.c b/net/nimble/host/src/ble_gattc.c
index 360299d..1e93841 100644
--- a/net/nimble/host/src/ble_gattc.c
+++ b/net/nimble/host/src/ble_gattc.c
@@ -316,13 +316,14 @@ static const struct ble_gattc_rx_exec_entry {
     { BLE_GATT_OP_WRITE_RELIABLE,   ble_gattc_write_reliable_rx_exec },
 };
 
-/* Maintains the list of active GATT client procedures. */
 static os_membuf_t ble_gattc_proc_mem[
     OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_GATT_MAX_PROCS),
                     sizeof (struct ble_gattc_proc))
 ];
 
 static struct os_mempool ble_gattc_proc_pool;
+
+/* The list of active GATT client procedures. */
 static struct ble_gattc_proc_list ble_gattc_procs;
 
 /* Statistics. */
@@ -646,6 +647,7 @@ static void
 ble_gattc_proc_set_timer(struct ble_gattc_proc *proc)
 {
     proc->exp_os_ticks = os_time_get() + BLE_GATT_UNRESPONSIVE_TIMEOUT;
+    ble_hs_timer_resched();
 }
 
 static void
@@ -781,13 +783,18 @@ ble_gattc_extract_by_conn_op(uint16_t conn_handle, uint8_t op,
     ble_hs_unlock();
 }
 
-static void
+/**
+ * @return                      The number of ticks until the next expiration
+ *                                  occurs.
+ */
+static int32_t
 ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list)
 {
     struct ble_gattc_proc *proc;
     struct ble_gattc_proc *prev;
     struct ble_gattc_proc *next;
     uint32_t now;
+    int32_t next_exp_in;
     int32_t time_diff;
 
     /* Only the parent task is allowed to remove entries from the list. */
@@ -796,6 +803,9 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list)
     now = os_time_get();
     STAILQ_INIT(dst_list);
 
+    /* Assume each event is either expired or has infinite duration. */
+    next_exp_in = BLE_HS_FOREVER;
+
     ble_hs_lock();
 
     prev = NULL;
@@ -803,14 +813,19 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list)
     while (proc != NULL) {
         next = STAILQ_NEXT(proc, next);
 
-        time_diff = now - proc->exp_os_ticks;
-        if (time_diff >= 0) {
+        time_diff = proc->exp_os_ticks - now;
+        if (time_diff <= 0) {
+            /* Procedure has expired; move it to the destination list. */
             if (prev == NULL) {
                 STAILQ_REMOVE_HEAD(&ble_gattc_procs, next);
             } else {
                 STAILQ_REMOVE_AFTER(&ble_gattc_procs, prev, next);
             }
             STAILQ_INSERT_TAIL(dst_list, proc, next);
+        } else {
+            if (time_diff < next_exp_in) {
+                next_exp_in = time_diff;
+            }
         }
 
         prev = proc;
@@ -818,6 +833,8 @@ ble_gattc_extract_expired(struct ble_gattc_proc_list *dst_list)
     }
 
     ble_hs_unlock();
+
+    return next_exp_in;
 }
 
 static struct ble_gattc_proc *
@@ -909,28 +926,23 @@ ble_gattc_fail_procs(uint16_t conn_handle, uint8_t op, int status)
 }
 
 /**
- * Applies periodic checks and actions to all active procedures.
- *
- * All procedures that have been expecting a response for longer than 30
- * seconds are aborted and their corresponding connection is terminated.
- *
- * Called by the heartbeat timer; executed at least once a second.
+ * Times out expired GATT client procedures.
  *
  * @return                      The number of ticks until this function should
- *                                  be called again; currently always
- *                                  UINT32_MAX.
+ *                                  be called again.
  */
 int32_t
-ble_gattc_heartbeat(void)
+ble_gattc_timer(void)
 {
     struct ble_gattc_proc_list exp_list;
     struct ble_gattc_proc *proc;
+    int32_t ticks_until_exp;
 
     /* Remove timed-out procedures from the main list and insert them into a
-     * temporary list.  For any stalled procedures, set their pending bit so
-     * they can be retried.
+     * temporary list.  This function also calculates the number of ticks until
+     * the next expiration will occur.
      */
-    ble_gattc_extract_expired(&exp_list);
+    ticks_until_exp = ble_gattc_extract_expired(&exp_list);
 
     /* Terminate the connection associated with each timed-out procedure. */
     while ((proc = STAILQ_FIRST(&exp_list)) != NULL) {
@@ -941,7 +953,7 @@ ble_gattc_heartbeat(void)
         ble_gattc_proc_free(proc);
     }
 
-    return BLE_HS_FOREVER;
+    return ticks_until_exp;
 }
 
 /**

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_hs.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs.c b/net/nimble/host/src/ble_hs.c
index 7f7383b..fd45511 100644
--- a/net/nimble/host/src/ble_hs.c
+++ b/net/nimble/host/src/ble_hs.c
@@ -25,6 +25,7 @@
 #include "bsp/bsp.h"
 #include "stats/stats.h"
 #include "os/os.h"
+#include "console/console.h"
 #include "nimble/ble_hci_trans.h"
 #include "ble_hs_priv.h"
 
@@ -36,6 +37,7 @@ static void ble_hs_event_rx_hci_ev(struct os_event *ev);
 static void ble_hs_event_tx_notify(struct os_event *ev);
 static void ble_hs_event_reset(struct os_event *ev);
 static void ble_hs_event_start(struct os_event *ev);
+static void ble_hs_timer_sched(int32_t ticks_from_now);
 
 struct os_mempool ble_hs_hci_ev_pool;
 static os_membuf_t ble_hs_hci_os_event_buf[
@@ -70,7 +72,7 @@ static struct os_task *ble_hs_parent_task;
  * Handles unresponsive timeouts and periodic retries in case of resource
  * shortage.
  */
-static struct os_callout ble_hs_heartbeat_timer;
+static struct os_callout ble_hs_timer_timer;
 
 /* Shared queue that the host uses for work items. */
 static struct os_eventq *ble_hs_evq;
@@ -208,36 +210,6 @@ ble_hs_clear_data_queue(struct os_mqueue *mqueue)
     }
 }
 
-
-static void
-ble_hs_heartbeat_timer_reset(uint32_t ticks)
-{
-    int rc;
-
-    rc = os_callout_reset(&ble_hs_heartbeat_timer, ticks);
-    BLE_HS_DBG_ASSERT_EVAL(rc == 0);
-}
-
-void
-ble_hs_heartbeat_sched(int32_t ticks_from_now)
-{
-    os_time_t abs_time;
-
-    if (ticks_from_now == BLE_HS_FOREVER) {
-        return;
-    }
-
-    /* Reset heartbeat timer if it is not currently scheduled or if the
-     * specified time is sooner than the current expiration time.
-     */
-    abs_time = os_time_get() + ticks_from_now;
-    if (!os_callout_queued(&ble_hs_heartbeat_timer) ||
-        OS_TIME_TICK_LT(abs_time, ble_hs_heartbeat_timer.c_ticks)) {
-
-        ble_hs_heartbeat_timer_reset(ticks_from_now);
-    }
-}
-
 /**
  * Indicates whether the host has synchronized with the controller.
  * Synchronization must occur before any host procedures can be performed.
@@ -272,7 +244,7 @@ ble_hs_sync(void)
         ble_hs_sync_state = BLE_HS_SYNC_STATE_BAD;
     }
 
-    ble_hs_heartbeat_sched(BLE_HS_SYNC_RETRY_RATE);
+    ble_hs_timer_sched(BLE_HS_SYNC_RETRY_RATE);
 
     if (rc == 0) {
         STATS_INC(ble_hs_stats, sync);
@@ -318,11 +290,11 @@ ble_hs_reset(void)
 }
 
 /**
- * Called once a second by the ble_hs heartbeat timer.  Handles unresponsive
- * timeouts and periodic retries in case of resource shortage.
+ * Called when the host timer expires.  Handles unresponsive timeouts and
+ * periodic retries in case of resource shortage.
  */
 static void
-ble_hs_heartbeat(struct os_event *ev)
+ble_hs_timer_exp(struct os_event *ev)
 {
     int32_t ticks_until_next;
 
@@ -331,24 +303,56 @@ ble_hs_heartbeat(struct os_event *ev)
         return;
     }
 
-    /* Ensure the timer expires at least once in the next second.
-     * XXX: This is not very power efficient.  We will need separate timers for
-     * each module.
-     */
-    ticks_until_next = BLE_HS_HEARTBEAT_OS_TICKS;
-    ble_hs_heartbeat_sched(ticks_until_next);
+    ticks_until_next = ble_gattc_timer();
+    ble_hs_timer_sched(ticks_until_next);
+
+    ticks_until_next = ble_gap_timer();
+    ble_hs_timer_sched(ticks_until_next);
 
-    ticks_until_next = ble_gattc_heartbeat();
-    ble_hs_heartbeat_sched(ticks_until_next);
+    ticks_until_next = ble_l2cap_sig_timer();
+    ble_hs_timer_sched(ticks_until_next);
 
-    ticks_until_next = ble_gap_heartbeat();
-    ble_hs_heartbeat_sched(ticks_until_next);
+    ticks_until_next = ble_sm_timer();
+    ble_hs_timer_sched(ticks_until_next);
+}
+
+static void
+ble_hs_timer_timer_reset(uint32_t ticks)
+{
+    int rc;
+
+    rc = os_callout_reset(&ble_hs_timer_timer, ticks);
+    BLE_HS_DBG_ASSERT_EVAL(rc == 0);
+}
+
+static void
+ble_hs_timer_sched(int32_t ticks_from_now)
+{
+    os_time_t abs_time;
 
-    ticks_until_next = ble_l2cap_sig_heartbeat();
-    ble_hs_heartbeat_sched(ticks_until_next);
+    if (ticks_from_now == BLE_HS_FOREVER) {
+        return;
+    }
+
+    /* Reset timer if it is not currently scheduled or if the specified time is
+     * sooner than the previous expiration time.
+     */
+    abs_time = os_time_get() + ticks_from_now;
+    if (!os_callout_queued(&ble_hs_timer_timer) ||
+        OS_TIME_TICK_LT(abs_time, ble_hs_timer_timer.c_ticks)) {
 
-    ticks_until_next = ble_sm_heartbeat();
-    ble_hs_heartbeat_sched(ticks_until_next);
+        ble_hs_timer_timer_reset(ticks_from_now);
+        console_printf("TICKS_UNTIL_NEXT: %d\n", (int)ticks_from_now);
+    }
+}
+
+void
+ble_hs_timer_resched(void)
+{
+    /* Reschedule the timer to run immediately.  The timer callback will query
+     * each module for an up-to-date expiration time.
+     */
+    ble_hs_timer_timer_reset(0);
 }
 
 static void
@@ -457,8 +461,8 @@ ble_hs_start(void)
 
     ble_hs_parent_task = os_sched_get_current_task();
 
-    os_callout_init(&ble_hs_heartbeat_timer, ble_hs_evq_get(),
-                    ble_hs_heartbeat, NULL);
+    os_callout_init(&ble_hs_timer_timer, ble_hs_evq_get(),
+                    ble_hs_timer_exp, NULL);
 
     rc = ble_att_svr_start();
     if (rc != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_hs_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_priv.h b/net/nimble/host/src/ble_hs_priv.h
index 3ac8388..905386b 100644
--- a/net/nimble/host/src/ble_hs_priv.h
+++ b/net/nimble/host/src/ble_hs_priv.h
@@ -109,7 +109,7 @@ void ble_hs_lock(void);
 void ble_hs_unlock(void);
 void ble_hs_sched_reset(int reason);
 void ble_hs_hw_error(uint8_t hw_code);
-void ble_hs_heartbeat_sched(int32_t ticks);
+void ble_hs_timer_resched(void);
 void ble_hs_notifications_sched(void);
 
 #if MYNEWT_VAL(LOG_LEVEL) <= LOG_LEVEL_DEBUG

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/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 7954be9..3b548c0 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -601,16 +601,10 @@ ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason)
 }
 
 /**
- * Applies periodic checks and actions to all active procedures.
- *
- * All procedures that have been expecting a response for longer than 30
- * seconds are aborted and their corresponding connection is terminated.
- *
- * Called by the timer timer; executed at least once a second.
+ * Terminates expired procedures.
  *
  * @return                      The number of ticks until this function should
- *                                  be called again; currently always
- *                                  UINT32_MAX.
+ *                                  be called again.
  */
 int32_t
 ble_l2cap_sig_timer(void)

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_sm.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm.c b/net/nimble/host/src/ble_sm.c
index c561315..3421b06 100644
--- a/net/nimble/host/src/ble_sm.c
+++ b/net/nimble/host/src/ble_sm.c
@@ -349,6 +349,7 @@ ble_sm_proc_set_timer(struct ble_sm_proc *proc)
 {
     /* Set a timeout of 30 seconds. */
     proc->exp_os_ticks = os_time_get() + BLE_SM_TIMEOUT_OS_TICKS;
+    ble_hs_timer_resched();
 }
 
 static ble_sm_rx_fn *
@@ -601,18 +602,22 @@ ble_sm_insert(struct ble_sm_proc *proc)
     STAILQ_INSERT_HEAD(&ble_sm_procs, proc, next);
 }
 
-static void
+static int32_t
 ble_sm_extract_expired(struct ble_sm_proc_list *dst_list)
 {
     struct ble_sm_proc *proc;
     struct ble_sm_proc *prev;
     struct ble_sm_proc *next;
     uint32_t now;
+    int32_t next_exp_in;
     int32_t time_diff;
 
     now = os_time_get();
     STAILQ_INIT(dst_list);
 
+    /* Assume each event is either expired or has infinite duration. */
+    next_exp_in = BLE_HS_FOREVER;
+
     ble_hs_lock();
 
     prev = NULL;
@@ -620,14 +625,19 @@ ble_sm_extract_expired(struct ble_sm_proc_list *dst_list)
     while (proc != NULL) {
         next = STAILQ_NEXT(proc, next);
 
-        time_diff = now - proc->exp_os_ticks;
-        if (time_diff >= 0) {
+        time_diff = proc->exp_os_ticks - now;
+        if (time_diff <= 0) {
+            /* Procedure has expired; move it to the destination list. */
             if (prev == NULL) {
                 STAILQ_REMOVE_HEAD(&ble_sm_procs, next);
             } else {
                 STAILQ_REMOVE_AFTER(&ble_sm_procs, prev, next);
             }
             STAILQ_INSERT_HEAD(dst_list, proc, next);
+        } else {
+            if (time_diff < next_exp_in) {
+                next_exp_in = time_diff;
+            }
         }
 
         prev = proc;
@@ -637,6 +647,8 @@ ble_sm_extract_expired(struct ble_sm_proc_list *dst_list)
     ble_sm_dbg_assert_no_cycles();
 
     ble_hs_unlock();
+
+    return next_exp_in;
 }
 
 static void
@@ -1980,27 +1992,23 @@ ble_sm_fail_rx(uint16_t conn_handle, uint8_t op, struct os_mbuf **om,
  *****************************************************************************/
 
 /**
- * Applies periodic checks and actions to all active procedures.
- *
- * All procedures that have been expecting a response for longer than 30
- * seconds are aborted.
- *
- * Called by the heartbeat timer; executed at least once a second.
+ * Times out expired SM procedures.
  *
  * @return                      The number of ticks until this function should
- *                                  be called again; currently always
- *                                  UINT32_MAX.
+ *                                  be called again.
  */
 int32_t
-ble_sm_heartbeat(void)
+ble_sm_timer(void)
 {
     struct ble_sm_proc_list exp_list;
     struct ble_sm_proc *proc;
+    int32_t ticks_until_exp;
 
-    /* Remove all timed out procedures and insert them into a temporary
-     * list.
+    /* Remove timed-out procedures from the main list and insert them into a
+     * temporary list.  This function also calculates the number of ticks until
+     * the next expiration will occur.
      */
-    ble_sm_extract_expired(&exp_list);
+    ticks_until_exp = ble_sm_extract_expired(&exp_list);
 
     /* Notify application of each failure and free the corresponding procedure
      * object.
@@ -2014,7 +2022,7 @@ ble_sm_heartbeat(void)
         ble_sm_proc_free(proc);
     }
 
-    return BLE_HS_FOREVER;
+    return ticks_until_exp;
 }
 
 /**
@@ -2028,8 +2036,7 @@ ble_sm_pair_initiate(uint16_t conn_handle)
 
     /* Make sure a procedure isn't already in progress for this connection. */
     ble_hs_lock();
-    proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE,
-                                  -1, NULL);
+    proc = ble_sm_proc_find(conn_handle, BLE_SM_PROC_STATE_NONE, -1, NULL);
     if (proc != NULL) {
         res.app_status = BLE_HS_EALREADY;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/src/ble_sm_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_sm_priv.h b/net/nimble/host/src/ble_sm_priv.h
index 1b9ff55..ba8a0be 100644
--- a/net/nimble/host/src/ble_sm_priv.h
+++ b/net/nimble/host/src/ble_sm_priv.h
@@ -456,7 +456,7 @@ void ble_sm_ia_ra(struct ble_sm_proc *proc,
                   uint8_t *out_iat, uint8_t *out_ia,
                   uint8_t *out_rat, uint8_t *out_ra);
 
-int32_t ble_sm_heartbeat(void);
+int32_t ble_sm_timer(void);
 void ble_sm_connection_broken(uint16_t conn_handle);
 int ble_sm_pair_initiate(uint16_t conn_handle);
 int ble_sm_slave_initiate(uint16_t conn_handle);
@@ -475,7 +475,7 @@ int ble_sm_init(void);
 #define ble_sm_ltk_req_rx(evt) ((void)(evt))
 #define ble_sm_enc_key_refresh_rx(evt) ((void)(evt))
 
-#define ble_sm_heartbeat() BLE_HS_FOREVER
+#define ble_sm_timer() BLE_HS_FOREVER
 #define ble_sm_connection_broken(conn_handle)
 #define ble_sm_pair_initiate(conn_handle)   BLE_HS_ENOTSUP
 #define ble_sm_slave_initiate(conn_handle)  BLE_HS_ENOTSUP

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/d0cc8330/net/nimble/host/test/src/ble_gap_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_gap_test.c b/net/nimble/host/test/src/ble_gap_test.c
index 8acf2f2..994b2a1 100644
--- a/net/nimble/host/test/src/ble_gap_test.c
+++ b/net/nimble/host/test/src/ble_gap_test.c
@@ -1907,7 +1907,7 @@ ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
 
     /* Advance 29 seconds; ensure no timeout reported. */
     os_time_advance(29 * OS_TICKS_PER_SEC);
-    ble_gap_heartbeat();
+    ble_gap_timer();
     TEST_ASSERT(ble_gap_test_event.type == 0xff);
 
     /* Advance 30th second; ensure timeout reported. */
@@ -1918,7 +1918,7 @@ ble_gap_test_util_update_no_l2cap_tmo(struct ble_gap_upd_params *params,
      */
     ble_hs_test_util_set_ack_disconnect(0);
 
-    ble_gap_heartbeat();
+    ble_gap_timer();
 
     /* Verify terminate was sent. */
     ble_gap_test_util_verify_tx_disconnect();
@@ -1997,8 +1997,8 @@ ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
 
     /* Advance 29 seconds; ensure no timeout reported. */
     os_time_advance(29 * OS_TICKS_PER_SEC);
-    ble_gap_heartbeat();
-    ble_l2cap_sig_heartbeat();
+    ble_gap_timer();
+    ble_l2cap_sig_timer();
     TEST_ASSERT(ble_gap_test_event.type == 0xff);
 
     /* Advance 30th second; ensure timeout reported. */
@@ -2009,8 +2009,8 @@ ble_gap_test_util_update_l2cap_tmo(struct ble_gap_upd_params *params,
      */
     ble_hs_test_util_set_ack_disconnect(0);
 
-    ble_gap_heartbeat();
-    ble_l2cap_sig_heartbeat();
+    ble_gap_timer();
+    ble_l2cap_sig_timer();
 
     /* Verify terminate was sent. */
     ble_gap_test_util_verify_tx_disconnect();
@@ -2579,12 +2579,12 @@ ble_gap_test_util_conn_forever(void)
                              NULL, 0);
 
     /* Ensure no pending GAP event. */
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
 
     /* Advance 100 seconds; ensure no timeout reported. */
     os_time_advance(100 * OS_TICKS_PER_SEC);
-    ble_gap_heartbeat();
+    ble_gap_timer();
     TEST_ASSERT(ble_gap_test_event.type == 0xff);
     TEST_ASSERT(ble_gap_conn_active());
 }
@@ -2609,7 +2609,7 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
     /* Ensure next GAP event is at the expected time. */
     rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
     TEST_ASSERT_FATAL(rc == 0);
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == duration_ticks);
 
     /* Advance duration ms; ensure timeout event does not get reported before
@@ -2624,14 +2624,14 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
 
     TEST_ASSERT(ble_gap_test_event.type == 0xff);
 
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
 
     /* Ensure cancel create connection command was sent. */
     ble_hs_test_util_verify_tx_create_conn_cancel();
 
     /* Ensure timer has been stopped. */
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
 
     /* Receive the connection complete event indicating a successful cancel. */
@@ -2663,7 +2663,7 @@ ble_gap_test_util_disc_forever(void)
                           NULL, -1, 0);
 
     /* Ensure no pending GAP event. */
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
 
     /* Advance 100 seconds; ensure no timeout reported. */
@@ -2692,7 +2692,7 @@ ble_gap_test_util_disc_timeout(int32_t duration_ms)
     /* Ensure next GAP event is at the expected time. */
     rc = os_time_ms_to_ticks(duration_ms, &duration_ticks);
     TEST_ASSERT_FATAL(rc == 0);
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == duration_ticks);
 
     /* Advance duration ms; ensure timeout event was reported. */
@@ -2702,7 +2702,7 @@ ble_gap_test_util_disc_timeout(int32_t duration_ms)
         ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
                                     BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
         0);
-    ticks_from_now = ble_gap_heartbeat();
+    ticks_from_now = ble_gap_timer();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
 
     TEST_ASSERT(ble_gap_test_disc_event_type == BLE_GAP_EVENT_DISC_COMPLETE);


[5/5] incubator-mynewt-core git commit: BLE Host - L2CAP intrnl API chg: handle, not ptrs.

Posted by cc...@apache.org.
BLE Host - L2CAP intrnl API chg: handle, not ptrs.

This addresses a glaring inconsistency in the NimBLE host.  All other
transmit functions accepted a connection handle and a payload.  The
L2CAP tx functions were different; rather than taking a connection
handle, they took pointers to a connection and L2CAP channel.

A related difference was that the L2CAP tx functions required the caller
to lock the host mutex, while the other tx functions locked the mutex
themselves.

Now the L2CAP tx functions resemble the others:
    * they take a connection handle.
    * they lock the host mutex themselves.


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

Branch: refs/heads/develop
Commit: 2fcb28b27637886d7884e1f38dfc305f791aa665
Parents: a38b757
Author: Christopher Collins <cc...@apache.org>
Authored: Wed Nov 16 16:16:27 2016 -0800
Committer: Christopher Collins <cc...@apache.org>
Committed: Wed Nov 16 18:31:44 2016 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_hs_hci_evt.c        | 18 +++--
 net/nimble/host/src/ble_l2cap.c             | 44 ++++++++++--
 net/nimble/host/src/ble_l2cap_priv.h        |  3 +-
 net/nimble/host/src/ble_l2cap_sig.c         | 92 ++++++++++++++----------
 net/nimble/host/src/ble_l2cap_sig_cmd.c     | 37 ++++++----
 net/nimble/host/src/ble_l2cap_sig_priv.h    | 15 ++--
 net/nimble/host/test/src/ble_hs_test_util.c |  7 +-
 7 files changed, 140 insertions(+), 76 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/net/nimble/host/src/ble_hs_hci_evt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_hci_evt.c b/net/nimble/host/src/ble_hs_hci_evt.c
index 911954a..d185a64 100644
--- a/net/nimble/host/src/ble_hs_hci_evt.c
+++ b/net/nimble/host/src/ble_hs_hci_evt.c
@@ -615,7 +615,8 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
     struct ble_hs_conn *conn;
     ble_l2cap_rx_fn *rx_cb;
     struct os_mbuf *rx_buf;
-    uint16_t handle;
+    uint16_t conn_handle;
+    int reject_cid;
     int rc;
 
     rc = ble_hs_hci_util_data_hdr_strip(om, &hci_hdr);
@@ -624,8 +625,8 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
     }
 
 #if (BLETEST_THROUGHPUT_TEST == 0)
-    BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): handle=%u pb=%x len=%u "
-                      "data=",
+    BLE_HS_LOG(DEBUG, "ble_hs_hci_evt_acl_process(): conn_handle=%u pb=%x "
+                      "len=%u data=",
                BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc), 
                BLE_HCI_DATA_PB(hci_hdr.hdh_handle_pb_bc), 
                hci_hdr.hdh_len);
@@ -638,15 +639,15 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
         goto err;
     }
 
-    handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);
+    conn_handle = BLE_HCI_DATA_HANDLE(hci_hdr.hdh_handle_pb_bc);
 
     ble_hs_lock();
 
-    conn = ble_hs_conn_find(handle);
+    conn = ble_hs_conn_find(conn_handle);
     if (conn == NULL) {
         rc = BLE_HS_ENOTCONN;
     } else {
-        rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf);
+        rc = ble_l2cap_rx(conn, &hci_hdr, om, &rx_cb, &rx_buf, &reject_cid);
         om = NULL;
     }
 
@@ -657,7 +658,7 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
         /* Final fragment received. */
         BLE_HS_DBG_ASSERT(rx_cb != NULL);
         BLE_HS_DBG_ASSERT(rx_buf != NULL);
-        rc = rx_cb(handle, &rx_buf);
+        rc = rx_cb(conn_handle, &rx_buf);
         os_mbuf_free_chain(rx_buf);
         break;
 
@@ -666,6 +667,9 @@ ble_hs_hci_evt_acl_process(struct os_mbuf *om)
         break;
 
     default:
+        if (reject_cid != -1) {
+            ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, 0, 0, reject_cid);
+        }
         goto err;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/net/nimble/host/src/ble_l2cap.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_l2cap.c
index ddc7a78..66701b1 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -186,18 +186,53 @@ ble_l2cap_rx_payload(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
     return rc;
 }
 
+/**
+ * Processes an incoming L2CAP fragment.
+ *
+ * @param conn                  The connection the L2CAP fragment was sent
+ *                                  over.
+ * @param hci_hdr               The ACL data header that was at the start of
+ *                                  the L2CAP fragment.  This header has been
+ *                                  stripped from the mbuf parameter.
+ * @param om                    An mbuf containing the L2CAP data.  If this is
+ *                                  the first fragment, the L2CAP header is at
+ *                                  the start of the mbuf.  For subsequent
+ *                                  fragments, the mbuf starts with L2CAP
+ *                                  payload data.
+ * @param out_rx_cb             If a full L2CAP packet has been received, a
+ *                                  pointer to the appropriate handler gets
+ *                                  written here.  The caller should pass the
+ *                                  receive buffer to this callback.
+ * @param out_rx_buf            If a full L2CAP packet has been received, this
+ *                                  will point to the entire L2CAP packet.  To
+ *                                  process the packet, pass this buffer to the
+ *                                  receive handler (out_rx_cb).
+ * @param out_reject_cid        Indicates whether an L2CAP Command Reject
+ *                                  command should be sent.  If this equals -1,
+ *                                  no reject should get sent.  Otherwise, the
+ *                                  value indicates the CID that the outgoing
+ *                                  reject should specify.
+ *
+ * @return                      0 if a complete L2CAP packet has been received.
+ *                              BLE_HS_EAGAIN if a partial L2CAP packet has
+ *                                  been received; more fragments are expected.
+ *                              Other value on error.
+ */
 int
 ble_l2cap_rx(struct ble_hs_conn *conn,
              struct hci_data_hdr *hci_hdr,
              struct os_mbuf *om,
              ble_l2cap_rx_fn **out_rx_cb,
-             struct os_mbuf **out_rx_buf)
+             struct os_mbuf **out_rx_buf,
+             int *out_reject_cid)
 {
     struct ble_l2cap_chan *chan;
     struct ble_l2cap_hdr l2cap_hdr;
     uint8_t pb;
     int rc;
 
+    *out_reject_cid = -1;
+
     pb = BLE_HCI_DATA_PB(hci_hdr->hdh_handle_pb_bc);
     switch (pb) {
     case BLE_HCI_PB_FIRST_FLUSH:
@@ -221,12 +256,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
             if (l2cap_hdr.blh_cid != BLE_L2CAP_CID_BLACK_HOLE) {
                 BLE_HS_LOG(DEBUG, "rx on unknown L2CAP channel: %d\n",
                            l2cap_hdr.blh_cid);
-
-                chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_SIG);
-                if (chan != NULL) {
-                    ble_l2cap_sig_reject_invalid_cid_tx(conn, chan, 0, 0,
-                                                        l2cap_hdr.blh_cid);
-                }
+                *out_reject_cid = l2cap_hdr.blh_cid;
             }
             goto err;
         }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/net/nimble/host/src/ble_l2cap_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_priv.h b/net/nimble/host/src/ble_l2cap_priv.h
index 016d291..79d58a7 100644
--- a/net/nimble/host/src/ble_l2cap_priv.h
+++ b/net/nimble/host/src/ble_l2cap_priv.h
@@ -104,7 +104,8 @@ int ble_l2cap_rx(struct ble_hs_conn *conn,
                  struct hci_data_hdr *hci_hdr,
                  struct os_mbuf *om,
                  ble_l2cap_rx_fn **out_rx_cb,
-                 struct os_mbuf **out_rx_buf);
+                 struct os_mbuf **out_rx_buf,
+                 int *out_reject_cid);
 int ble_l2cap_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
                  struct os_mbuf *txom);
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/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 805b696..7954be9 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -190,8 +190,9 @@ ble_l2cap_sig_proc_insert(struct ble_l2cap_sig_proc *proc)
 {
     ble_l2cap_sig_dbg_assert_proc_not_inserted(proc);
 
-    BLE_HS_DBG_ASSERT(ble_hs_locked_by_cur_task());
+    ble_hs_lock();
     STAILQ_INSERT_HEAD(&ble_l2cap_sig_procs, proc, next);
+    ble_hs_unlock();
 }
 
 /**
@@ -271,6 +272,24 @@ ble_l2cap_sig_rx_noop(uint16_t conn_handle,
     return BLE_HS_ENOTSUP;
 }
 
+static void
+ble_l2cap_sig_proc_set_timer(struct ble_l2cap_sig_proc *proc)
+{
+    proc->exp_os_ticks = os_time_get() + BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT;
+    ble_hs_timer_resched();
+}
+
+static void
+ble_l2cap_sig_process_status(struct ble_l2cap_sig_proc *proc, int status)
+{
+    if (status == 0) {
+        ble_l2cap_sig_proc_set_timer(proc);
+        ble_l2cap_sig_proc_insert(proc);
+    } else {
+        ble_l2cap_sig_proc_free(proc);
+    }
+}
+
 /*****************************************************************************
  * $update                                                                   *
  *****************************************************************************/
@@ -296,9 +315,7 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle,
 {
     struct ble_l2cap_sig_update_req req;
     struct ble_gap_upd_params params;
-    struct ble_l2cap_chan *chan;
     ble_hs_conn_flags_t conn_flags;
-    struct ble_hs_conn *conn;
     uint16_t l2cap_result;
     int sig_err;
     int rc;
@@ -342,19 +359,15 @@ ble_l2cap_sig_update_req_rx(uint16_t conn_handle,
     }
 
     /* Send L2CAP response. */
-    ble_hs_lock();
-    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
-                                    &conn, &chan);
     if (!sig_err) {
-        rc = ble_l2cap_sig_update_rsp_tx(conn, chan, hdr->identifier,
+        rc = ble_l2cap_sig_update_rsp_tx(conn_handle, hdr->identifier,
                                          l2cap_result);
     } else {
-        ble_l2cap_sig_reject_tx(conn, chan, hdr->identifier,
+        ble_l2cap_sig_reject_tx(conn_handle, hdr->identifier,
                                 BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
                                 NULL, 0);
         rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
     }
-    ble_hs_unlock();
 
     return rc;
 }
@@ -416,6 +429,7 @@ ble_l2cap_sig_update(uint16_t conn_handle,
     struct ble_l2cap_sig_proc *proc;
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
+    int master;
     int rc;
 
     proc = NULL;
@@ -423,10 +437,12 @@ ble_l2cap_sig_update(uint16_t conn_handle,
     STATS_INC(ble_l2cap_stats, update_init);
 
     ble_hs_lock();
-
     ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
                                     &conn, &chan);
-    if (conn->bhc_flags & BLE_HS_CONN_F_MASTER) {
+    master = conn->bhc_flags & BLE_HS_CONN_F_MASTER;
+    ble_hs_unlock();
+
+    if (master) {
         /* Only the slave can initiate the L2CAP connection update
          * procedure.
          */
@@ -444,7 +460,6 @@ ble_l2cap_sig_update(uint16_t conn_handle,
     proc->op = BLE_L2CAP_SIG_PROC_OP_UPDATE;
     proc->id = ble_l2cap_sig_next_id();
     proc->conn_handle = conn_handle;
-    proc->exp_os_ticks = os_time_get() + BLE_L2CAP_SIG_UNRESPONSIVE_TIMEOUT;
     proc->update.cb = cb;
     proc->update.cb_arg = cb_arg;
 
@@ -453,18 +468,10 @@ ble_l2cap_sig_update(uint16_t conn_handle,
     req.slave_latency = params->slave_latency;
     req.timeout_multiplier = params->timeout_multiplier;
 
-    rc = ble_l2cap_sig_update_req_tx(conn, chan, proc->id, &req);
-    if (rc == 0) {
-        ble_l2cap_sig_proc_insert(proc);
-    }
+    rc = ble_l2cap_sig_update_req_tx(conn_handle, proc->id, &req);
 
 done:
-    ble_hs_unlock();
-
-    if (rc != 0) {
-        ble_l2cap_sig_proc_free(proc);
-    }
-
+    ble_l2cap_sig_process_status(proc, rc);
     return rc;
 }
 
@@ -472,8 +479,6 @@ static int
 ble_l2cap_sig_rx(uint16_t conn_handle, struct os_mbuf **om)
 {
     struct ble_l2cap_sig_hdr hdr;
-    struct ble_l2cap_chan *chan;
-    struct ble_hs_conn *conn;
     ble_l2cap_sig_rx_fn *rx_cb;
     int rc;
 
@@ -498,14 +503,10 @@ ble_l2cap_sig_rx(uint16_t conn_handle, struct os_mbuf **om)
 
     rx_cb = ble_l2cap_sig_dispatch_get(hdr.op);
     if (rx_cb == NULL) {
-        ble_hs_lock();
-        ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
-                                        &conn, &chan);
-        ble_l2cap_sig_reject_tx(conn, chan, hdr.identifier,
+        ble_l2cap_sig_reject_tx(conn_handle, hdr.identifier,
                                 BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD,
                                 NULL, 0);
         rc = BLE_HS_L2C_ERR(BLE_L2CAP_SIG_ERR_CMD_NOT_UNDERSTOOD);
-        ble_hs_unlock();
     } else {
         rc = rx_cb(conn_handle, &hdr, om);
     }
@@ -531,18 +532,26 @@ ble_l2cap_sig_create_chan(void)
     return chan;
 }
 
-static void
+/**
+ * @return                      The number of ticks until the next expiration
+ *                                  occurs.
+ */
+static int32_t
 ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list)
 {
     struct ble_l2cap_sig_proc *proc;
     struct ble_l2cap_sig_proc *prev;
     struct ble_l2cap_sig_proc *next;
     uint32_t now;
+    int32_t next_exp_in;
     int32_t time_diff;
 
     now = os_time_get();
     STAILQ_INIT(dst_list);
 
+    /* Assume each event is either expired or has infinite duration. */
+    next_exp_in = BLE_HS_FOREVER;
+
     ble_hs_lock();
 
     prev = NULL;
@@ -550,20 +559,27 @@ ble_l2cap_sig_extract_expired(struct ble_l2cap_sig_proc_list *dst_list)
     while (proc != NULL) {
         next = STAILQ_NEXT(proc, next);
     
-        time_diff = now - proc->exp_os_ticks;
-        if (time_diff >= 0) {
+        time_diff = proc->exp_os_ticks - now;
+        if (time_diff <= 0) {
+            /* Procedure has expired; move it to the destination list. */
             if (prev == NULL) {
                 STAILQ_REMOVE_HEAD(&ble_l2cap_sig_procs, next);
             } else {
                 STAILQ_REMOVE_AFTER(&ble_l2cap_sig_procs, prev, next);
             }
             STAILQ_INSERT_TAIL(dst_list, proc, next);
+        } else {
+            if (time_diff < next_exp_in) {
+                next_exp_in = time_diff;
+            }
         }
 
         proc = next;
     }
 
     ble_hs_unlock();
+
+    return next_exp_in;
 }
 
 void
@@ -590,22 +606,24 @@ ble_l2cap_sig_conn_broken(uint16_t conn_handle, int reason)
  * All procedures that have been expecting a response for longer than 30
  * seconds are aborted and their corresponding connection is terminated.
  *
- * Called by the heartbeat timer; executed at least once a second.
+ * Called by the timer timer; executed at least once a second.
  *
  * @return                      The number of ticks until this function should
  *                                  be called again; currently always
  *                                  UINT32_MAX.
  */
 int32_t
-ble_l2cap_sig_heartbeat(void)
+ble_l2cap_sig_timer(void)
 {
     struct ble_l2cap_sig_proc_list temp_list;
     struct ble_l2cap_sig_proc *proc;
+    int32_t ticks_until_exp;
 
     /* Remove timed-out procedures from the main list and insert them into a
-     * temporary list.
+     * temporary list.  This function also calculates the number of ticks until
+     * the next expiration will occur.
      */
-    ble_l2cap_sig_extract_expired(&temp_list);
+    ticks_until_exp = ble_l2cap_sig_extract_expired(&temp_list);
 
     /* Report a failure for each timed out procedure. */
     while ((proc = STAILQ_FIRST(&temp_list)) != NULL) {
@@ -616,7 +634,7 @@ ble_l2cap_sig_heartbeat(void)
         ble_l2cap_sig_proc_free(proc);
     }
 
-    return BLE_HS_FOREVER;
+    return ticks_until_exp;
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/net/nimble/host/src/ble_l2cap_sig_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_sig_cmd.c b/net/nimble/host/src/ble_l2cap_sig_cmd.c
index a2bc91a..b8ab12b 100644
--- a/net/nimble/host/src/ble_l2cap_sig_cmd.c
+++ b/net/nimble/host/src/ble_l2cap_sig_cmd.c
@@ -60,6 +60,22 @@ err:
     return rc;
 }
 
+static int
+ble_l2cap_sig_tx(uint16_t conn_handle, struct os_mbuf *txom)
+{
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+
+    ble_hs_lock();
+    ble_hs_misc_conn_chan_find_reqd(conn_handle, BLE_L2CAP_CID_SIG,
+                                    &conn, &chan);
+    rc = ble_l2cap_tx(conn, chan, txom);
+    ble_hs_unlock();
+
+    return rc;
+}
+
 static void
 ble_l2cap_sig_hdr_swap(struct ble_l2cap_sig_hdr *dst,
                        struct ble_l2cap_sig_hdr *src)
@@ -108,8 +124,7 @@ ble_l2cap_sig_reject_write(void *payload, uint16_t len,
 }
 
 int
-ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
-                        uint8_t id, uint16_t reason,
+ble_l2cap_sig_reject_tx(uint16_t conn_handle, uint8_t id, uint16_t reason,
                         void *data, int data_len)
 {
     struct ble_l2cap_sig_reject cmd;
@@ -129,7 +144,7 @@ ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
                                data, data_len);
 
     STATS_INC(ble_l2cap_stats, sig_rx);
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
     if (rc != 0) {
         return rc;
     }
@@ -138,8 +153,7 @@ ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
 }
 
 int
-ble_l2cap_sig_reject_invalid_cid_tx(struct ble_hs_conn *conn,
-                                    struct ble_l2cap_chan *chan, uint8_t id,
+ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, uint8_t id,
                                     uint16_t src_cid, uint16_t dst_cid)
 {
     int rc;
@@ -152,7 +166,7 @@ ble_l2cap_sig_reject_invalid_cid_tx(struct ble_hs_conn *conn,
         .remote_cid = src_cid,
     };
 
-    rc = ble_l2cap_sig_reject_tx(conn, chan, id,
+    rc = ble_l2cap_sig_reject_tx(conn_handle, id,
                                  BLE_L2CAP_SIG_ERR_INVALID_CID,
                                  &data, sizeof data);
     return rc;
@@ -185,8 +199,7 @@ ble_l2cap_sig_update_req_write(void *payload, int len,
 }
 
 int
-ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
-                            struct ble_l2cap_chan *chan, uint8_t id,
+ble_l2cap_sig_update_req_tx(uint16_t conn_handle, uint8_t id,
                             struct ble_l2cap_sig_update_req *req)
 {
     struct os_mbuf *txom;
@@ -203,7 +216,7 @@ ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
     ble_l2cap_sig_update_req_write(payload_buf, BLE_L2CAP_SIG_UPDATE_REQ_SZ,
                                    req);
 
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
     if (rc != 0) {
         return rc;
     }
@@ -235,9 +248,7 @@ ble_l2cap_sig_update_rsp_write(void *payload, int len,
 }
 
 int
-ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
-                            struct ble_l2cap_chan *chan, uint8_t id,
-                            uint16_t result)
+ble_l2cap_sig_update_rsp_tx(uint16_t conn_handle, uint8_t id, uint16_t result)
 {
     struct ble_l2cap_sig_update_rsp rsp;
     struct os_mbuf *txom;
@@ -255,7 +266,7 @@ ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
     ble_l2cap_sig_update_rsp_write(payload_buf, BLE_L2CAP_SIG_UPDATE_RSP_SZ,
                                    &rsp);
 
-    rc = ble_l2cap_tx(conn, chan, txom);
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
     if (rc != 0) {
         return rc;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/2fcb28b2/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 4646fc2..72819de 100644
--- a/net/nimble/host/src/ble_l2cap_sig_priv.h
+++ b/net/nimble/host/src/ble_l2cap_sig_priv.h
@@ -60,32 +60,27 @@ void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len,
                              struct ble_l2cap_sig_hdr *hdr);
 void ble_l2cap_sig_hdr_write(void *payload, uint16_t len,
                              struct ble_l2cap_sig_hdr *hdr);
-int ble_l2cap_sig_reject_tx(struct ble_hs_conn *conn,
-                            struct ble_l2cap_chan *chan,
+int ble_l2cap_sig_reject_tx(uint16_t conn_handle,
                             uint8_t id, uint16_t reason,
                             void *data, int data_len);
 void ble_l2cap_sig_update_req_parse(void *payload, int len,
                                     struct ble_l2cap_sig_update_req *req);
 void ble_l2cap_sig_update_req_write(void *payload, int len,
                                     struct ble_l2cap_sig_update_req *src);
-int ble_l2cap_sig_update_req_tx(struct ble_hs_conn *conn,
-                                struct ble_l2cap_chan *chan, uint8_t id,
+int ble_l2cap_sig_update_req_tx(uint16_t conn_handle, uint8_t id,
                                 struct ble_l2cap_sig_update_req *req);
 void ble_l2cap_sig_update_rsp_parse(void *payload, int len,
                                     struct ble_l2cap_sig_update_rsp *cmd);
 void ble_l2cap_sig_update_rsp_write(void *payload, int len,
                                     struct ble_l2cap_sig_update_rsp *src);
-int ble_l2cap_sig_update_rsp_tx(struct ble_hs_conn *conn,
-                                struct ble_l2cap_chan *chan, uint8_t id,
+int ble_l2cap_sig_update_rsp_tx(uint16_t conn_handle, uint8_t id,
                                 uint16_t result);
 
-int ble_l2cap_sig_reject_invalid_cid_tx(struct ble_hs_conn *conn,
-                                        struct ble_l2cap_chan *chan,
-                                        uint8_t id,
+int ble_l2cap_sig_reject_invalid_cid_tx(uint16_t conn_handle, 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);
+int32_t ble_l2cap_sig_timer(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/2fcb28b2/net/nimble/host/test/src/ble_hs_test_util.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_test_util.c b/net/nimble/host/test/src/ble_hs_test_util.c
index 58e3345..55528dd 100644
--- a/net/nimble/host/test/src/ble_hs_test_util.c
+++ b/net/nimble/host/test/src/ble_hs_test_util.c
@@ -839,13 +839,14 @@ ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
     struct ble_hs_conn *conn;
     ble_l2cap_rx_fn *rx_cb;
     struct os_mbuf *rx_buf;
+    int reject_cid;
     int rc;
 
     ble_hs_lock();
 
     conn = ble_hs_conn_find(conn_handle);
     if (conn != NULL) {
-        rc = ble_l2cap_rx(conn, hci_hdr, om, &rx_cb, &rx_buf);
+        rc = ble_l2cap_rx(conn, hci_hdr, om, &rx_cb, &rx_buf, &reject_cid);
     } else {
         os_mbuf_free_chain(om);
     }
@@ -862,6 +863,10 @@ ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
     } else if (rc == BLE_HS_EAGAIN) {
         /* More fragments on the way. */
         rc = 0;
+    } else {
+        if (reject_cid != -1) {
+            ble_l2cap_sig_reject_invalid_cid_tx(conn_handle, 0, 0, reject_cid);
+        }
     }
 
     return rc;