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 2015/11/18 22:47:07 UTC

incubator-mynewt-larva git commit: ATT MTU exchange.

Repository: incubator-mynewt-larva
Updated Branches:
  refs/heads/master a73a7e819 -> 126f083ec


ATT MTU exchange.


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

Branch: refs/heads/master
Commit: 126f083ecce7a3d0a8b8fb2c0de488099d9236fd
Parents: a73a7e8
Author: Christopher Collins <cc...@gmail.com>
Authored: Wed Nov 18 13:46:39 2015 -0800
Committer: Christopher Collins <cc...@gmail.com>
Committed: Wed Nov 18 13:46:39 2015 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_hs_att.c            | 28 +++++++++++++-------
 net/nimble/host/src/ble_hs_att.h            |  8 +++---
 net/nimble/host/src/ble_hs_conn.c           | 16 ++++++++++--
 net/nimble/host/src/ble_hs_conn.h           | 10 ++++---
 net/nimble/host/src/ble_l2cap.c             | 33 +++++++++++++-----------
 net/nimble/host/src/ble_l2cap.h             |  6 +++--
 net/nimble/host/src/test/ble_hs_att_test.c  |  9 ++++---
 net/nimble/host/src/test/ble_hs_conn_test.c | 16 ++++++++++--
 8 files changed, 86 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/ble_hs_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.c b/net/nimble/host/src/ble_hs_att.c
index fa92da5..be63df7 100644
--- a/net/nimble/host/src/ble_hs_att.c
+++ b/net/nimble/host/src/ble_hs_att.c
@@ -340,15 +340,24 @@ ble_hs_att_rx_mtu_req(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
     uint8_t buf[BLE_HS_ATT_MTU_REQ_SZ];
     int rc;
 
-    rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
-    if (rc != 0) {
-        return rc;
+    /* We should only receive this command as a server. */
+    if (conn->bhc_flags & BLE_HS_CONN_F_CLIENT) {
+        /* XXX: Unspecified what to do in this case. */
+        return EINVAL;
     }
 
+    rc = os_mbuf_copydata(om, 0, sizeof buf, buf);
+    assert(rc == 0);
+
     rc = ble_hs_att_mtu_req_parse(buf, sizeof buf, &req);
     assert(rc == 0);
 
-    /* XXX: Update connection MTU. */
+    if (req.bhamq_mtu < BLE_HS_ATT_MTU_DFLT) {
+        req.bhamq_mtu = BLE_HS_ATT_MTU_DFLT;
+    }
+
+    chan->blc_peer_mtu = req.bhamq_mtu;
+
     /* XXX: Send response. */
 
     return 0;
@@ -466,8 +475,8 @@ ble_hs_att_rx_find_info_req(struct ble_hs_conn *conn,
     rc = ble_hs_att_find_info_req_parse(buf, sizeof buf, &req);
     assert(rc == 0);
 
-    /* Tx error response if start handle is greater than end handle or is 0.
-     * (Vol. 3, Part F, 3.4.3.1).
+    /* Tx error response if start handle is greater than end handle or is equal
+     * to 0 (Vol. 3, Part F, 3.4.3.1).
      */
     if (req.bhafq_start_handle > req.bhafq_end_handle ||
         req.bhafq_start_handle == 0) {
@@ -484,7 +493,7 @@ ble_hs_att_rx_find_info_req(struct ble_hs_conn *conn,
     rc = ble_hs_att_fill_info(
         &req,
         ble_hs_att_tx_buf + BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ,
-        conn->bhc_att_mtu - BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ,
+        ble_l2cap_chan_mtu(chan) - BLE_HS_ATT_FIND_INFO_RSP_MIN_SZ,
         &rsp_sz,
         &rsp.bhafp_format);
     if (rc != 0) {
@@ -527,8 +536,8 @@ ble_hs_att_tx_read_rsp(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan,
     }
 
     /* Vol. 3, part F, 3.2.9; don't send more than ATT_MTU-1 bytes of data. */
-    if (attr_len > conn->bhc_att_mtu - 1) {
-        data_len = conn->bhc_att_mtu - 1;
+    if (attr_len > ble_l2cap_chan_mtu(chan) - 1) {
+        data_len = ble_l2cap_chan_mtu(chan) - 1;
     } else {
         data_len = attr_len;
     }
@@ -695,6 +704,7 @@ ble_hs_att_create_chan(void)
     }
 
     chan->blc_cid = BLE_L2CAP_CID_ATT;
+    chan->blc_default_mtu = BLE_HS_ATT_MTU_DFLT;
     chan->blc_rx_fn = ble_hs_att_rx;
 
     return chan;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/ble_hs_att.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_att.h b/net/nimble/host/src/ble_hs_att.h
index 0323baa..b8b5fe4 100644
--- a/net/nimble/host/src/ble_hs_att.h
+++ b/net/nimble/host/src/ble_hs_att.h
@@ -17,11 +17,13 @@
 #ifndef H_BLE_HS_ATT_
 #define H_BLE_HS_ATT_
 
-#define BLE_HS_ATT_MTU_DFLT         23
+#define BLE_HS_ATT_MTU_DFLT         23  /* Also the minimum. */
 #define BLE_HS_ATT_MTU_MAX          256 /* XXX: I'm making this up! */
 
-#define BLE_HS_ATT_ERR_INVALID_HANDLE   0x01
-#define BLE_HS_ATT_ERR_ATTR_NOT_FOUND   0x0a
+#define BLE_HS_ATT_ERR_INVALID_HANDLE       0x01
+#define BLE_HS_ATT_ERR_REQ_NOT_SUPPORTED    0x06
+#define BLE_HS_ATT_ERR_ATTR_NOT_FOUND       0x0a
+#define BLE_HS_ATT_ERR_INSUFFICIENT_RES     0x11
 
 struct ble_hs_att_entry;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/ble_hs_conn.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.c b/net/nimble/host/src/ble_hs_conn.c
index 23f218d..18fd05c 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -39,8 +39,6 @@ ble_hs_conn_alloc(void)
         goto err;
     }
 
-    conn->bhc_att_mtu = BLE_HS_ATT_MTU_DFLT;
-
     SLIST_INIT(&conn->bhc_channels);
 
     chan = ble_hs_att_create_chan();
@@ -114,6 +112,20 @@ ble_hs_conn_first(void)
     return SLIST_FIRST(&ble_hs_conns);
 }
 
+struct ble_l2cap_chan *
+ble_hs_conn_chan_find(struct ble_hs_conn *conn, uint16_t cid)
+{
+    struct ble_l2cap_chan *chan;
+
+    SLIST_FOREACH(chan, &conn->bhc_channels, blc_next) {
+        if (chan->blc_cid == cid) {
+            return chan;
+        }
+    }
+
+    return NULL;
+}
+
 int 
 ble_hs_conn_init(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/ble_hs_conn.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn.h b/net/nimble/host/src/ble_hs_conn.h
index deb5879..ceb10c3 100644
--- a/net/nimble/host/src/ble_hs_conn.h
+++ b/net/nimble/host/src/ble_hs_conn.h
@@ -21,17 +21,19 @@
 #include "ble_l2cap.h"
 struct hci_le_conn_complete;
 struct hci_create_conn;
+struct ble_l2cap_chan;
 
-struct ble_hs_conn *ble_host_find_connection(uint16_t con_handle);
+typedef uint8_t ble_hs_conn_flags;
+#define BLE_HS_CONN_F_CLIENT        0x01
 
 struct ble_hs_conn {
     SLIST_ENTRY(ble_hs_conn) bhc_next;
     uint16_t bhc_handle;
-    int bhc_fd; // XXX Temporary.
-    uint16_t bhc_att_mtu;
     uint8_t bhc_addr[BLE_DEV_ADDR_LEN];
 
     struct ble_l2cap_chan_list bhc_channels;
+
+    ble_hs_conn_flags bhc_flags;
 };
 
 struct ble_hs_conn *ble_hs_conn_alloc(void);
@@ -40,6 +42,8 @@ void ble_hs_conn_insert(struct ble_hs_conn *conn);
 void ble_hs_conn_remove(struct ble_hs_conn *conn);
 struct ble_hs_conn *ble_hs_conn_find(uint16_t con_handle);
 struct ble_hs_conn *ble_hs_conn_first(void);
+struct ble_l2cap_chan *ble_hs_conn_chan_find(struct ble_hs_conn *conn,
+                                             uint16_t cid);
 int ble_hs_conn_init(void);
 
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/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 6ec8b10..9accbb8 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -67,6 +67,23 @@ ble_l2cap_chan_free(struct ble_l2cap_chan *chan)
     assert(rc == 0);
 }
 
+uint16_t
+ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan)
+{
+    uint16_t mtu;
+
+    /* If either side has not exchanged MTU size, use the default.  Otherwise,
+     * use the lesser of the two exchanged values.
+     */
+    if (chan->blc_my_mtu == 0 || chan->blc_peer_mtu == 0) {
+        mtu = chan->blc_default_mtu;
+    } else {
+        mtu = min(chan->blc_my_mtu, chan->blc_peer_mtu);
+    }
+
+    return mtu;
+}
+
 int
 ble_l2cap_parse_hdr(void *pkt, uint16_t len, struct ble_l2cap_hdr *l2cap_hdr)
 {
@@ -112,20 +129,6 @@ ble_l2cap_write_hdr(void *dst, uint16_t len,
     return 0;
 }
 
-struct ble_l2cap_chan *
-ble_l2cap_chan_find(struct ble_hs_conn *conn, uint16_t cid)
-{
-    struct ble_l2cap_chan *chan;
-
-    SLIST_FOREACH(chan, &conn->bhc_channels, blc_next) {
-        if (chan->blc_cid == cid) {
-            return chan;
-        }
-    }
-
-    return NULL;
-}
-
 /**
  * If the specified pointer points to null, this function attempts to allocate
  * an mbuf from the l2cap mbuf pool and assigns the result to the pointer.  No
@@ -200,7 +203,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
         return EMSGSIZE;
     }
 
-    chan = ble_l2cap_chan_find(conn, l2cap_hdr.blh_cid);
+    chan = ble_hs_conn_chan_find(conn, l2cap_hdr.blh_cid);
     if (chan == NULL) {
         return ENOENT;
     }

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap.h b/net/nimble/host/src/ble_l2cap.h
index 300cd69..c2d0f08 100644
--- a/net/nimble/host/src/ble_l2cap.h
+++ b/net/nimble/host/src/ble_l2cap.h
@@ -47,6 +47,9 @@ struct ble_l2cap_chan
 {
     SLIST_ENTRY(ble_l2cap_chan) blc_next;
     uint16_t blc_cid;
+    uint16_t blc_my_mtu;        /* 0 if not exchanged. */
+    uint16_t blc_peer_mtu;      /* 0 if not exchanged. */
+    uint16_t blc_default_mtu;
 
     struct os_mbuf *blc_rx_buf;
     struct os_mbuf *blc_tx_buf;
@@ -60,8 +63,7 @@ SLIST_HEAD(ble_l2cap_chan_list, ble_l2cap_chan);
 struct ble_l2cap_chan *ble_l2cap_chan_alloc(void);
 void ble_l2cap_chan_free(struct ble_l2cap_chan *chan);
 
-struct ble_l2cap_chan *ble_l2cap_chan_find(struct ble_hs_conn *conn,
-                                           uint16_t cid);
+uint16_t ble_l2cap_chan_mtu(struct ble_l2cap_chan *chan);
 
 int ble_l2cap_parse_hdr(void *pkt, uint16_t len,
                         struct ble_l2cap_hdr *l2cap_hdr);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/test/ble_hs_att_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_att_test.c b/net/nimble/host/src/test/ble_hs_att_test.c
index d267a6d..6b3c493 100644
--- a/net/nimble/host/src/test/ble_hs_att_test.c
+++ b/net/nimble/host/src/test/ble_hs_att_test.c
@@ -214,7 +214,7 @@ TEST_CASE(ble_hs_att_test_read)
     conn = ble_hs_conn_find(2);
     TEST_ASSERT_FATAL(conn != NULL);
 
-    chan = ble_l2cap_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
 
     /*** Nonexistent attribute. */
@@ -277,7 +277,7 @@ TEST_CASE(ble_hs_att_test_write)
     conn = ble_hs_conn_find(2);
     TEST_ASSERT_FATAL(conn != NULL);
 
-    chan = ble_l2cap_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
 
     /*** Nonexistent attribute. */
@@ -332,11 +332,12 @@ TEST_CASE(ble_hs_att_test_find_info)
     conn = ble_hs_conn_find(2);
     TEST_ASSERT_FATAL(conn != NULL);
 
-    chan = ble_l2cap_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
 
     /* Increase the MTU to 128 bytes to allow testing of long responses. */
-    conn->bhc_att_mtu = 128;
+    chan->blc_my_mtu = 128;
+    chan->blc_peer_mtu = 128;
 
     /*** Start handle of 0. */
     req.bhafq_op = BLE_HS_ATT_OP_FIND_INFO_REQ;

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-larva/blob/126f083e/net/nimble/host/src/test/ble_hs_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/test/ble_hs_conn_test.c b/net/nimble/host/src/test/ble_hs_conn_test.c
index e1e4108..8b709d4 100644
--- a/net/nimble/host/src/test/ble_hs_conn_test.c
+++ b/net/nimble/host/src/test/ble_hs_conn_test.c
@@ -32,6 +32,7 @@
 TEST_CASE(ble_hs_conn_test_master_direct_success)
 {
     struct hci_le_conn_complete evt;
+    struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
     uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
     int rc;
@@ -65,8 +66,13 @@ TEST_CASE(ble_hs_conn_test_master_direct_success)
     conn = ble_hs_conn_first();
     TEST_ASSERT_FATAL(conn != NULL);
     TEST_ASSERT(conn->bhc_handle == 2);
-    TEST_ASSERT(conn->bhc_att_mtu == BLE_HS_ATT_MTU_DFLT);
     TEST_ASSERT(memcmp(conn->bhc_addr, addr, 6) == 0);
+
+    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+    TEST_ASSERT_FATAL(chan != NULL);
+    TEST_ASSERT(chan->blc_my_mtu == 0);
+    TEST_ASSERT(chan->blc_peer_mtu == 0);
+    TEST_ASSERT(chan->blc_default_mtu == BLE_HS_ATT_MTU_DFLT);
 }
 
 TEST_CASE(ble_hs_conn_test_master_direct_hci_errors)
@@ -112,6 +118,7 @@ TEST_CASE(ble_hs_conn_test_master_direct_hci_errors)
 TEST_CASE(ble_hs_conn_test_slave_direct_success)
 {
     struct hci_le_conn_complete evt;
+    struct ble_l2cap_chan *chan;
     struct ble_hs_conn *conn;
     uint8_t addr[6] = { 1, 2, 3, 4, 5, 6 };
     int rc;
@@ -154,8 +161,13 @@ TEST_CASE(ble_hs_conn_test_slave_direct_success)
     conn = ble_hs_conn_first();
     TEST_ASSERT_FATAL(conn != NULL);
     TEST_ASSERT(conn->bhc_handle == 2);
-    TEST_ASSERT(conn->bhc_att_mtu == BLE_HS_ATT_MTU_DFLT);
     TEST_ASSERT(memcmp(conn->bhc_addr, addr, 6) == 0);
+
+    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+    TEST_ASSERT_FATAL(chan != NULL);
+    TEST_ASSERT(chan->blc_my_mtu == 0);
+    TEST_ASSERT(chan->blc_peer_mtu == 0);
+    TEST_ASSERT(chan->blc_default_mtu == BLE_HS_ATT_MTU_DFLT);
 }
 
 TEST_SUITE(conn_suite)