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/08/24 00:53:23 UTC

[09/50] [abbrv] incubator-mynewt-core git commit: BLE Host - Report updated MTU via GAP event cb.

BLE Host - Report updated MTU via GAP event cb.

Before this commit, MTU changes were only reported when we initiated the
exchange via a GATT procedure.  If the peer initiated the exchange, the
application never learned of an MTU update.

Now all MTU changes are reported through the GAP event callback.  The
callback passed to ble_gattc_exchange_mtu() is not very useful anymore.
Its only real purpose is to inform the user if the peer failed to
respond to the MTU request, which causes the connection to be terminated
anyway.

Relevant additions to the API:

 #define BLE_GAP_EVENT_MTU                   15

 struct ble_gap_event {
     /* [...] */

     /**
      * Represents a change in an L2CAP channel's MTU.
      *
      * Valid for the following event types:
      *     o BLE_GAP_EVENT_MTU
      */
     struct {
         /** The handle of the relevant connection. */
         uint16_t conn_handle;

         /**
          * Indicates the channel whose MTU has been updated; either
          * BLE_L2CAP_CID_ATT or the ID of a connection-oriented
          * channel.
          */
         uint16_t channel_id;

         /* The channel's new MTU. */
         uint16_t value;
     } mtu;
 };


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

Branch: refs/heads/master
Commit: e3750fe0d1e05829b97f6e635d23977369383dd6
Parents: 277edaf
Author: Christopher Collins <cc...@apache.org>
Authored: Fri Aug 12 17:48:00 2016 -0700
Committer: Christopher Collins <cc...@apache.org>
Committed: Fri Aug 12 18:16:35 2016 -0700

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_gap.h      |  21 +++++
 net/nimble/host/src/ble_att_clt.c           |   4 +-
 net/nimble/host/src/ble_att_cmd.c           |  31 +++----
 net/nimble/host/src/ble_att_cmd_priv.h      |   4 +-
 net/nimble/host/src/ble_att_svr.c           |   6 +-
 net/nimble/host/src/ble_gap.c               |  17 ++++
 net/nimble/host/src/ble_gap_priv.h          |   1 +
 net/nimble/host/src/test/ble_att_clt_test.c |  31 +++++++
 net/nimble/host/src/test/ble_att_svr_test.c |   2 +-
 net/nimble/host/src/test/ble_gap_test.c     | 111 +++++++++++++++++------
 net/nimble/host/src/test/ble_hs_test_util.c |  42 ++++++++-
 net/nimble/host/src/test/ble_hs_test_util.h |   5 +-
 12 files changed, 224 insertions(+), 51 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 46854e0..960ad7b 100644
--- a/net/nimble/host/include/host/ble_gap.h
+++ b/net/nimble/host/include/host/ble_gap.h
@@ -107,6 +107,7 @@ struct hci_conn_update;
 #define BLE_GAP_EVENT_NOTIFY_RX             12
 #define BLE_GAP_EVENT_NOTIFY_TX             13
 #define BLE_GAP_EVENT_SUBSCRIBE             14
+#define BLE_GAP_EVENT_MTU                   15
 
 /*** Reason codes for the subscribe GAP event. */
 
@@ -489,6 +490,26 @@ struct ble_gap_event {
             /** Whether the peer is currently subscribed to indications. */
             uint8_t cur_indicate:1;
         } subscribe;
+
+        /**
+         * Represents a change in an L2CAP channel's MTU.
+         *
+         * Valid for the following event types:
+         *     o BLE_GAP_EVENT_MTU
+         */
+        struct {
+            /** The handle of the relevant connection. */
+            uint16_t conn_handle;
+
+            /**
+             * Indicates the channel whose MTU has been updated; either
+             * BLE_L2CAP_CID_ATT or the ID of a connection-oriented channel.
+             */
+            uint16_t channel_id;
+
+            /* The channel's new MTU. */
+            uint16_t value;
+        } mtu;
     };
 };
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/ble_att_clt.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_clt.c b/net/nimble/host/src/ble_att_clt.c
index 8170c6c..735e819 100644
--- a/net/nimble/host/src/ble_att_clt.c
+++ b/net/nimble/host/src/ble_att_clt.c
@@ -173,7 +173,7 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
 
     rc = ble_hs_mbuf_pullup_base(rxom, BLE_ATT_MTU_CMD_SZ);
     if (rc == 0) {
-        ble_att_mtu_cmd_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
+        ble_att_mtu_rsp_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
         BLE_ATT_LOG_CMD(0, "mtu rsp", conn_handle, ble_att_mtu_cmd_log, &cmd);
 
         ble_hs_lock();
@@ -183,6 +183,8 @@ ble_att_clt_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
         mtu = ble_l2cap_chan_mtu(chan);
 
         ble_hs_unlock();
+
+        ble_gap_mtu_event(conn_handle, BLE_L2CAP_CID_ATT, mtu);
     }
 
     ble_gattc_rx_mtu(conn_handle, rc, mtu);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/ble_att_cmd.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd.c b/net/nimble/host/src/ble_att_cmd.c
index b8ca094..05c6874 100644
--- a/net/nimble/host/src/ble_att_cmd.c
+++ b/net/nimble/host/src/ble_att_cmd.c
@@ -40,20 +40,6 @@ ble_att_init_parse(uint8_t op, const void *payload,
     return u8ptr + 1;
 }
 
-static const void *
-ble_att_init_parse_2op(uint8_t op1, uint8_t op2, const void *payload,
-                       int min_len, int actual_len)
-{
-    const uint8_t *u8ptr;
-
-    BLE_HS_DBG_ASSERT(actual_len >= min_len);
-
-    u8ptr = payload;
-    BLE_HS_DBG_ASSERT(u8ptr[0] == op1 || u8ptr[0] == op2);
-
-    return u8ptr + 1;
-}
-
 static void *
 ble_att_init_write(uint8_t op, void *payload, int min_len, int actual_len)
 {
@@ -113,13 +99,24 @@ ble_att_mtu_cmd_swap(struct ble_att_mtu_cmd *dst,
 }
 
 void
-ble_att_mtu_cmd_parse(const void *payload, int len,
+ble_att_mtu_req_parse(const void *payload, int len,
+                      struct ble_att_mtu_cmd *dst)
+{
+    const struct ble_att_mtu_cmd *src;
+
+    src = ble_att_init_parse(BLE_ATT_OP_MTU_REQ, payload, BLE_ATT_MTU_CMD_SZ,
+                             len);
+    ble_att_mtu_cmd_swap(dst, src);
+}
+
+void
+ble_att_mtu_rsp_parse(const void *payload, int len,
                       struct ble_att_mtu_cmd *dst)
 {
     const struct ble_att_mtu_cmd *src;
 
-    src = ble_att_init_parse_2op(BLE_ATT_OP_MTU_REQ, BLE_ATT_OP_MTU_RSP,
-                                 payload, BLE_ATT_MTU_CMD_SZ, len);
+    src = ble_att_init_parse(BLE_ATT_OP_MTU_RSP, payload, BLE_ATT_MTU_CMD_SZ,
+                             len);
     ble_att_mtu_cmd_swap(dst, src);
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/ble_att_cmd_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_cmd_priv.h b/net/nimble/host/src/ble_att_cmd_priv.h
index 44989a1..bfeb28f 100644
--- a/net/nimble/host/src/ble_att_cmd_priv.h
+++ b/net/nimble/host/src/ble_att_cmd_priv.h
@@ -309,10 +309,12 @@ void ble_att_error_rsp_parse(const void *payload, int len,
 void ble_att_error_rsp_write(void *payload, int len,
                              const struct ble_att_error_rsp *rsp);
 void ble_att_error_rsp_log(const struct ble_att_error_rsp *cmd);
-void ble_att_mtu_cmd_parse(const void *payload, int len,
+void ble_att_mtu_req_parse(const void *payload, int len,
                            struct ble_att_mtu_cmd *cmd);
 void ble_att_mtu_req_write(void *payload, int len,
                            const struct ble_att_mtu_cmd *cmd);
+void ble_att_mtu_rsp_parse(const void *payload, int len,
+                           struct ble_att_mtu_cmd *cmd);
 void ble_att_mtu_rsp_write(void *payload, int len,
                            const struct ble_att_mtu_cmd *cmd);
 void ble_att_mtu_cmd_log(const struct ble_att_mtu_cmd *cmd);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/ble_att_svr.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att_svr.c b/net/nimble/host/src/ble_att_svr.c
index f224094..710db20 100644
--- a/net/nimble/host/src/ble_att_svr.c
+++ b/net/nimble/host/src/ble_att_svr.c
@@ -659,6 +659,7 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
     struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
     struct os_mbuf *txom;
+    uint16_t mtu;
     uint8_t att_err;
     int rc;
 
@@ -669,7 +670,7 @@ ble_att_svr_rx_mtu(uint16_t conn_handle, struct os_mbuf **rxom)
         goto done;
     }
 
-    ble_att_mtu_cmd_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
+    ble_att_mtu_req_parse((*rxom)->om_data, (*rxom)->om_len, &cmd);
     BLE_ATT_LOG_CMD(0, "mtu req", conn_handle, ble_att_mtu_cmd_log, &cmd);
 
     rc = ble_att_svr_build_mtu_rsp(conn_handle, &txom, &att_err);
@@ -688,8 +689,11 @@ done:
         ble_att_conn_chan_find(conn_handle, &conn, &chan);
         ble_att_set_peer_mtu(chan, cmd.bamc_mtu);
         chan->blc_flags |= BLE_L2CAP_CHAN_F_TXED_MTU;
+        mtu = ble_l2cap_chan_mtu(chan);
 
         ble_hs_unlock();
+
+        ble_gap_mtu_event(conn_handle, BLE_L2CAP_CID_ATT, mtu);
     }
     return rc;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 9717125..f53a738 100644
--- a/net/nimble/host/src/ble_gap.c
+++ b/net/nimble/host/src/ble_gap.c
@@ -2902,6 +2902,23 @@ ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
 }
 
 /*****************************************************************************
+ * $mtu                                                                      *
+ *****************************************************************************/
+
+void
+ble_gap_mtu_event(uint16_t conn_handle, uint16_t cid, uint16_t mtu)
+{
+    struct ble_gap_event event;
+
+    memset(&event, 0, sizeof event);
+    event.type = BLE_GAP_EVENT_MTU;
+    event.mtu.conn_handle = conn_handle;
+    event.mtu.channel_id = cid;
+    event.mtu.value = mtu;
+    ble_gap_call_conn_event_cb(&event, conn_handle);
+}
+
+/*****************************************************************************
  * $init                                                                     *
  *****************************************************************************/
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 c2abbf3..eed5a18 100644
--- a/net/nimble/host/src/ble_gap_priv.h
+++ b/net/nimble/host/src/ble_gap_priv.h
@@ -89,6 +89,7 @@ void ble_gap_subscribe_event(uint16_t conn_handle, uint16_t attr_handle,
                              uint8_t reason,
                              uint8_t prev_notify, uint8_t cur_notify,
                              uint8_t prev_indicate, uint8_t cur_indicate);
+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);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/test/ble_att_clt_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_clt_test.c b/net/nimble/host/src/test/ble_att_clt_test.c
index ab89e9d..14d66f6 100644
--- a/net/nimble/host/src/test/ble_att_clt_test.c
+++ b/net/nimble/host/src/test/ble_att_clt_test.c
@@ -275,6 +275,22 @@ ble_att_clt_test_misc_prep_bad(uint16_t handle, uint16_t offset,
     TEST_ASSERT(rc == status);
 }
 
+static void
+ble_att_clt_test_misc_tx_mtu(uint16_t conn_handle, uint16_t mtu, int status)
+{
+    struct ble_att_mtu_cmd req;
+    int rc;
+
+    req.bamc_mtu = mtu;
+    rc = ble_att_clt_tx_mtu(conn_handle, &req);
+    TEST_ASSERT(rc == status);
+
+    if (rc == 0) {
+        ble_hs_test_util_verify_tx_mtu_cmd(1, mtu);
+    }
+}
+
+
 TEST_CASE(ble_att_clt_test_tx_write)
 {
     ble_att_clt_test_case_tx_write_req_or_cmd(0);
@@ -509,6 +525,20 @@ TEST_CASE(ble_att_clt_test_tx_exec_write)
     TEST_ASSERT(rc == BLE_HS_EINVAL);
 }
 
+TEST_CASE(ble_att_clt_test_tx_mtu)
+{
+    uint16_t conn_handle;
+
+    conn_handle = ble_att_clt_test_misc_init();
+
+    /*** Success. */
+    ble_att_clt_test_misc_tx_mtu(conn_handle, 50, 0);
+
+    /*** Error: repeated sends. */
+    ble_att_clt_test_misc_tx_mtu(conn_handle, 50, BLE_HS_EALREADY);
+    ble_att_clt_test_misc_tx_mtu(conn_handle, 60, BLE_HS_EALREADY);
+}
+
 TEST_SUITE(ble_att_clt_suite)
 {
     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
@@ -525,6 +555,7 @@ TEST_SUITE(ble_att_clt_suite)
     ble_att_clt_test_tx_prep_write();
     ble_att_clt_test_rx_prep_write();
     ble_att_clt_test_tx_exec_write();
+    ble_att_clt_test_tx_mtu();
 }
 
 int

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/net/nimble/host/src/test/ble_att_svr_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_att_svr_test.c b/net/nimble/host/src/test/ble_att_svr_test.c
index d8dfb27..52a5669 100644
--- a/net/nimble/host/src/test/ble_att_svr_test.c
+++ b/net/nimble/host/src/test/ble_att_svr_test.c
@@ -475,7 +475,7 @@ ble_att_svr_test_misc_verify_tx_mtu_rsp(uint16_t conn_handle)
     rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
     TEST_ASSERT(rc == 0);
 
-    ble_att_mtu_cmd_parse(buf, sizeof buf, &rsp);
+    ble_att_mtu_rsp_parse(buf, sizeof buf, &rsp);
 
     ble_hs_lock();
     rc = ble_hs_misc_conn_chan_find(conn_handle, BLE_L2CAP_CID_ATT,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 1943d01..5dd6532 100644
--- a/net/nimble/host/src/test/ble_gap_test.c
+++ b/net/nimble/host/src/test/ble_gap_test.c
@@ -26,7 +26,7 @@
 #include "host/ble_hs_test.h"
 #include "ble_hs_test_util.h"
 
-static int ble_gap_test_conn_event_type;
+static struct ble_gap_event ble_gap_test_event;
 static int ble_gap_test_conn_status;
 static struct ble_gap_conn_desc ble_gap_test_conn_desc;
 static void *ble_gap_test_conn_arg;
@@ -54,7 +54,7 @@ ble_gap_test_util_update_in_progress(uint16_t conn_handle)
 static void
 ble_gap_test_util_reset_cb_info(void)
 {
-    ble_gap_test_conn_event_type = -1;
+    memset(&ble_gap_test_event, 0xff, sizeof ble_gap_test_event);
     ble_gap_test_conn_status = -1;
     memset(&ble_gap_test_conn_desc, 0xff, sizeof ble_gap_test_conn_desc);
     ble_gap_test_conn_arg = (void *)-1;
@@ -90,7 +90,7 @@ ble_gap_test_util_connect_cb(struct ble_gap_event *event, void *arg)
 {
     int *fail_reason;
 
-    ble_gap_test_conn_event_type = event->type;
+    ble_gap_test_event = *event;
     ble_gap_test_conn_arg = arg;
 
     switch (event->type) {
@@ -137,6 +137,9 @@ ble_gap_test_util_connect_cb(struct ble_gap_event *event, void *arg)
         }
         break;
 
+    case BLE_GAP_EVENT_MTU:
+        break;
+
     default:
         TEST_ASSERT_FATAL(0);
         break;
@@ -855,7 +858,7 @@ TEST_CASE(ble_gap_test_case_conn_gen_good)
 
     TEST_ASSERT(!ble_gap_master_in_progress());
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONNECT);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
     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);
@@ -989,7 +992,7 @@ ble_gap_test_util_conn_cancel(uint8_t hci_status)
     TEST_ASSERT(rc == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_CANCEL);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
 }
 
 static void
@@ -1029,7 +1032,7 @@ TEST_CASE(ble_gap_test_case_conn_cancel_good)
 
     ble_gap_test_util_conn_and_cancel(peer_addr, 0);
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_CANCEL);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_CANCEL);
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == BLE_HS_CONN_HANDLE_NONE);
 }
 
@@ -1045,7 +1048,7 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
     /* Make sure the host didn't invoke the application callback.  The cancel
      * failure was indicated via the return code from the gap call.
      */
-    TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
 
     /* Allow connection complete to succeed. */
     memset(&evt, 0, sizeof evt);
@@ -1059,7 +1062,7 @@ TEST_CASE(ble_gap_test_case_conn_cancel_ctlr_fail)
 
     TEST_ASSERT(!ble_gap_master_in_progress());
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONNECT);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
     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);
@@ -1095,7 +1098,7 @@ ble_gap_test_util_terminate(uint8_t *peer_addr, uint8_t hci_status)
     /* Reset the callback event code; we don't care about the successful
      * connection in this test.
      */
-    ble_gap_test_conn_event_type = -1;
+    ble_gap_test_event.type = -1;
 
     /* Terminate the connection. */
     rc = ble_hs_test_util_conn_terminate(2, hci_status);
@@ -1131,7 +1134,7 @@ TEST_CASE(ble_gap_test_case_conn_terminate_good)
 
     ble_gap_test_util_terminate(peer_addr, 0);
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_DISCONNECT);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_DISCONNECT);
     TEST_ASSERT(ble_gap_test_conn_status ==
                 BLE_HS_HCI_ERR(BLE_ERR_CONN_TERM_LOCAL));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
@@ -1172,7 +1175,7 @@ TEST_CASE(ble_gap_test_case_conn_terminate_ctlr_fail)
     evt.reason = 0;
     ble_gap_rx_disconn_complete(&evt);
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_TERM_FAILURE);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_TERM_FAILURE);
     TEST_ASSERT(ble_gap_test_conn_status ==
                 BLE_HS_HCI_ERR(BLE_ERR_UNSUPPORTED));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
@@ -1192,7 +1195,7 @@ TEST_CASE(ble_gap_test_case_conn_terminate_hci_fail)
 
     ble_gap_test_util_terminate(peer_addr, BLE_ERR_REPEATED_ATTEMPTS);
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
     TEST_ASSERT(ble_hs_atomic_conn_flags(2, NULL) == 0);
     TEST_ASSERT(!ble_gap_master_in_progress());
 }
@@ -1574,7 +1577,7 @@ TEST_CASE(ble_gap_test_case_adv_good)
 
             if (c != BLE_GAP_CONN_MODE_NON) {
                 TEST_ASSERT(!ble_gap_adv_active());
-                TEST_ASSERT(ble_gap_test_conn_event_type ==
+                TEST_ASSERT(ble_gap_test_event.type ==
                                 BLE_GAP_EVENT_CONNECT);
                 TEST_ASSERT(ble_gap_test_conn_status == 0);
                 TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
@@ -1598,7 +1601,7 @@ TEST_CASE(ble_gap_test_case_adv_ctlr_fail)
                                   peer_addr, c, d, BLE_ERR_DIR_ADV_TMO, -1, 0);
 
             TEST_ASSERT(!ble_gap_adv_active());
-            TEST_ASSERT(ble_gap_test_conn_event_type ==
+            TEST_ASSERT(ble_gap_test_event.type ==
                         BLE_GAP_EVENT_ADV_COMPLETE);
             TEST_ASSERT(ble_gap_test_conn_desc.conn_handle ==
                         BLE_HS_CONN_HANDLE_NONE);
@@ -1629,7 +1632,7 @@ TEST_CASE(ble_gap_test_case_adv_hci_fail)
                                       c, d, 0, fail_idx, BLE_ERR_UNSUPPORTED);
 
                 TEST_ASSERT(!ble_gap_adv_active());
-                TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+                TEST_ASSERT(ble_gap_test_event.type == 0xff);
             }
         }
     }
@@ -1687,7 +1690,7 @@ TEST_CASE(ble_gap_test_case_stop_adv_good)
             ble_gap_test_util_stop_adv(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
                                        -1, 0);
             TEST_ASSERT(!ble_gap_adv_active());
-            TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+            TEST_ASSERT(ble_gap_test_event.type == 0xff);
             TEST_ASSERT(ble_gap_test_conn_status == -1);
             TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == (uint16_t)-1);
             TEST_ASSERT(ble_gap_test_conn_arg == (void *)-1);
@@ -1706,7 +1709,7 @@ TEST_CASE(ble_gap_test_case_stop_adv_hci_fail)
             ble_gap_test_util_stop_adv(BLE_ADDR_TYPE_PUBLIC, peer_addr, c, d,
                                        0, BLE_ERR_UNSUPPORTED);
             TEST_ASSERT(ble_gap_adv_active());
-            TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+            TEST_ASSERT(ble_gap_test_event.type == 0xff);
             TEST_ASSERT(ble_gap_test_conn_status == -1);
             TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == (uint16_t)-1);
             TEST_ASSERT(ble_gap_test_conn_arg == (void *)-1);
@@ -1767,7 +1770,7 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
 
     TEST_ASSERT(!ble_gap_master_in_progress());
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    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_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1782,7 +1785,7 @@ ble_gap_test_util_update(struct ble_gap_upd_params *params,
     return;
 
 fail:
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    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_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1814,7 +1817,7 @@ ble_gap_test_util_update_peer(uint8_t status,
 
     TEST_ASSERT(!ble_gap_master_in_progress());
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(status));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1869,7 +1872,7 @@ ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
     TEST_ASSERT(!ble_gap_master_in_progress());
     TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    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_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1882,7 +1885,7 @@ ble_gap_test_util_update_req_pos(struct ble_gap_upd_params *peer_params,
     return;
 
 hci_fail:
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(hci_status));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -1932,7 +1935,7 @@ ble_gap_test_util_update_req_neg(struct ble_gap_upd_params *peer_params,
     return;
 
 hci_fail:
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(hci_status));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -2008,7 +2011,7 @@ ble_gap_test_util_update_req_concurrent(
     TEST_ASSERT(!ble_gap_master_in_progress());
     TEST_ASSERT(!ble_gap_test_util_update_in_progress(2));
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    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_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -2021,7 +2024,7 @@ ble_gap_test_util_update_req_concurrent(
     return;
 
 hci_fail:
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONN_UPDATE);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONN_UPDATE);
     TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_HCI_ERR(fail_status));
     TEST_ASSERT(ble_gap_test_conn_desc.conn_handle == 2);
     TEST_ASSERT(memcmp(ble_gap_test_conn_desc.peer_id_addr,
@@ -2325,7 +2328,7 @@ ble_gap_test_util_conn_forever(void)
     /* Advance 100 seconds; ensure no timeout reported. */
     os_time_advance(100 * OS_TICKS_PER_SEC);
     ble_gap_heartbeat();
-    TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
     TEST_ASSERT(ble_gap_conn_active());
 }
 
@@ -2362,7 +2365,7 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
                                     BLE_HCI_OCF_LE_CREATE_CONN_CANCEL),
         0);
 
-    TEST_ASSERT(ble_gap_test_conn_event_type == -1);
+    TEST_ASSERT(ble_gap_test_event.type == 0xff);
 
     ticks_from_now = ble_gap_heartbeat();
     TEST_ASSERT(ticks_from_now == BLE_HS_FOREVER);
@@ -2382,7 +2385,7 @@ ble_gap_test_util_conn_timeout(int32_t duration_ms)
     TEST_ASSERT_FATAL(rc == 0);
 
     /* Ensure the GAP event was triggered. */
-    TEST_ASSERT(ble_gap_test_conn_event_type == BLE_GAP_EVENT_CONNECT);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_CONNECT);
     TEST_ASSERT(ble_gap_test_conn_status == BLE_HS_ETIMEOUT);
 
     /* Clear GAP event for remainder of test. */
@@ -2556,6 +2559,57 @@ TEST_SUITE(ble_gap_test_suite_timeout)
     ble_gap_test_case_conn_timeout_disc_timeout();
 }
 
+TEST_CASE(ble_gap_test_case_mtu_us)
+{
+    const uint8_t peer_addr[6] = { 1,2,3,4,5,6 };
+    int rc;
+
+    ble_gap_test_util_init();
+
+    ble_hs_test_util_create_conn(2, peer_addr, ble_gap_test_util_connect_cb,
+                                 NULL);
+
+    ble_att_set_preferred_mtu(200);
+
+    rc = ble_gattc_exchange_mtu(2, NULL, NULL);
+    TEST_ASSERT_FATAL(rc == 0);
+    ble_hs_test_util_verify_tx_mtu_cmd(1, 200);
+
+    ble_hs_test_util_rx_att_mtu_cmd(2, 0, 123);
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_MTU);
+    TEST_ASSERT(ble_gap_test_event.mtu.conn_handle == 2);
+    TEST_ASSERT(ble_gap_test_event.mtu.channel_id == BLE_L2CAP_CID_ATT);
+    TEST_ASSERT(ble_gap_test_event.mtu.value == 123);
+}
+
+TEST_CASE(ble_gap_test_case_mtu_peer)
+{
+    const 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_att_set_preferred_mtu(200);
+
+    ble_hs_test_util_rx_att_mtu_cmd(2, 1, 123);
+    ble_hs_test_util_verify_tx_mtu_cmd(0, 200);
+
+    TEST_ASSERT(ble_gap_test_event.type == BLE_GAP_EVENT_MTU);
+    TEST_ASSERT(ble_gap_test_event.mtu.conn_handle == 2);
+    TEST_ASSERT(ble_gap_test_event.mtu.channel_id == BLE_L2CAP_CID_ATT);
+    TEST_ASSERT(ble_gap_test_event.mtu.value == 123);
+}
+
+TEST_SUITE(ble_gap_test_suite_mtu)
+{
+    tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
+
+    ble_gap_test_case_mtu_us();
+    ble_gap_test_case_mtu_peer();
+}
+
 /*****************************************************************************
  * $all                                                                      *
  *****************************************************************************/
@@ -2573,6 +2627,7 @@ ble_gap_test_all(void)
     ble_gap_test_suite_stop_adv();
     ble_gap_test_suite_update_conn();
     ble_gap_test_suite_timeout();
+    ble_gap_test_suite_mtu();
 
     return tu_any_failed;
 }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 b5148e3..0ced75a 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.c
+++ b/net/nimble/host/src/test/ble_hs_test_util.c
@@ -407,7 +407,7 @@ ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
 }
 
 void
-ble_hs_test_util_create_conn(uint16_t handle, uint8_t *peer_id_addr,
+ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *peer_id_addr,
                              ble_gap_event_fn *cb, void *cb_arg)
 {
     static uint8_t null_addr[6];
@@ -897,6 +897,26 @@ ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
 }
 
 void
+ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req, uint16_t mtu)
+{
+    struct ble_att_mtu_cmd cmd;
+    uint8_t buf[BLE_ATT_MTU_CMD_SZ];
+    int rc;
+
+    cmd.bamc_mtu = mtu;
+
+    if (is_req) {
+        ble_att_mtu_req_write(buf, sizeof buf, &cmd);
+    } else {
+        ble_att_mtu_rsp_write(buf, sizeof buf, &cmd);
+    }
+
+    rc = ble_hs_test_util_l2cap_rx_payload_flat(conn_handle, BLE_L2CAP_CID_ATT,
+                                                buf, sizeof buf);
+    TEST_ASSERT(rc == 0);
+}
+
+void
 ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op,
                                 uint8_t error_code, uint16_t err_handle)
 {
@@ -1149,6 +1169,26 @@ ble_hs_test_util_verify_tx_write_rsp(void)
 }
 
 void
+ble_hs_test_util_verify_tx_mtu_cmd(int is_req, uint16_t mtu)
+{
+    struct ble_att_mtu_cmd cmd;
+    struct os_mbuf *om;
+
+    ble_hs_test_util_tx_all();
+
+    om = ble_hs_test_util_prev_tx_dequeue_pullup();
+    TEST_ASSERT_FATAL(om != NULL);
+
+    if (is_req) {
+        ble_att_mtu_req_parse(om->om_data, om->om_len, &cmd);
+    } else {
+        ble_att_mtu_rsp_parse(om->om_data, om->om_len, &cmd);
+    }
+
+    TEST_ASSERT(cmd.bamc_mtu == mtu);
+}
+
+void
 ble_hs_test_util_verify_tx_err_rsp(uint8_t req_op, uint16_t handle,
                                    uint8_t error_code)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/e3750fe0/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 fa3b5e0..7780d4e 100644
--- a/net/nimble/host/src/test/ble_hs_test_util.h
+++ b/net/nimble/host/src/test/ble_hs_test_util.h
@@ -75,7 +75,7 @@ void ble_hs_test_util_create_rpa_conn(uint16_t handle, uint8_t own_addr_type,
                                       const uint8_t *peer_id_addr,
                                       const uint8_t *peer_rpa,
                                       ble_gap_event_fn *cb, void *cb_arg);
-void ble_hs_test_util_create_conn(uint16_t handle, uint8_t *addr,
+void ble_hs_test_util_create_conn(uint16_t handle, const uint8_t *addr,
                                   ble_gap_event_fn *cb, void *cb_arg);
 int ble_hs_test_util_connect(uint8_t own_addr_type,
                                    uint8_t peer_addr_type,
@@ -125,6 +125,8 @@ int ble_hs_test_util_l2cap_rx(uint16_t conn_handle,
 int ble_hs_test_util_l2cap_rx_payload_flat(uint16_t conn_handle, uint16_t cid,
                                            const void *data, int len);
 void ble_hs_test_util_rx_hci_buf_size_ack(uint16_t buf_size);
+void ble_hs_test_util_rx_att_mtu_cmd(uint16_t conn_handle, int is_req,
+                                     uint16_t mtu);
 void ble_hs_test_util_rx_att_err_rsp(uint16_t conn_handle, uint8_t req_op,
                                      uint8_t error_code, uint16_t err_handle);
 void ble_hs_test_util_set_startup_acks(void);
@@ -143,6 +145,7 @@ void ble_hs_test_util_verify_tx_read_rsp(uint8_t *attr_data, int attr_len);
 void ble_hs_test_util_verify_tx_read_blob_rsp(uint8_t *attr_data,
                                               int attr_len);
 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);
 void ble_hs_test_util_set_static_rnd_addr(void);