You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by ma...@apache.org on 2017/03/06 21:19:02 UTC

[26/50] incubator-mynewt-core git commit: nimble/l2cap: Add LE credits update handling

nimble/l2cap: Add LE credits update handling

This patch add support to send singaling request to update LE creadits
as well as handle remote device sending us LE credits update.

Note, that this patch introduces also helper function to find channel
by scid and dcid


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

Branch: refs/heads/master
Commit: 754c4456a022f89135bedc80807c755950d2d201
Parents: 9b3899a
Author: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Authored: Sun Feb 12 15:30:21 2017 +0100
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Fri Mar 3 12:40:42 2017 +0100

----------------------------------------------------------------------
 net/nimble/host/src/ble_att.c               |  2 +-
 net/nimble/host/src/ble_hs_conn.c           | 23 ++++++++++-
 net/nimble/host/src/ble_hs_conn_priv.h      |  4 +-
 net/nimble/host/src/ble_hs_misc.c           |  2 +-
 net/nimble/host/src/ble_l2cap.c             |  2 +-
 net/nimble/host/src/ble_l2cap_coc.c         | 32 +++++++++++++++
 net/nimble/host/src/ble_l2cap_coc_priv.h    |  2 +
 net/nimble/host/src/ble_l2cap_sig.c         | 50 +++++++++++++++++++++++-
 net/nimble/host/src/ble_l2cap_sig_priv.h    |  6 +++
 net/nimble/host/test/src/ble_hs_conn_test.c |  6 +--
 10 files changed, 119 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/src/ble_att.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_att.c b/net/nimble/host/src/ble_att.c
index 7fe095b..0eaed34 100644
--- a/net/nimble/host/src/ble_att.c
+++ b/net/nimble/host/src/ble_att.c
@@ -545,7 +545,7 @@ ble_att_set_preferred_mtu(uint16_t mtu)
 
     i = 0;
     while ((conn = ble_hs_conn_find_by_idx(i)) != NULL) {
-        chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+        chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
         BLE_HS_DBG_ASSERT(chan != NULL);
 
         if (!(chan->flags & BLE_L2CAP_CHAN_F_TXED_MTU)) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/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 a371ace..cef0e3a 100644
--- a/net/nimble/host/src/ble_hs_conn.c
+++ b/net/nimble/host/src/ble_hs_conn.c
@@ -50,7 +50,7 @@ ble_hs_conn_can_alloc(void)
 }
 
 struct ble_l2cap_chan *
-ble_hs_conn_chan_find(struct ble_hs_conn *conn, uint16_t cid)
+ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn, uint16_t cid)
 {
 #if !NIMBLE_BLE_CONNECT
     return NULL;
@@ -70,6 +70,27 @@ ble_hs_conn_chan_find(struct ble_hs_conn *conn, uint16_t cid)
     return NULL;
 }
 
+struct ble_l2cap_chan *
+ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, uint16_t cid)
+{
+#if !NIMBLE_BLE_CONNECT
+    return NULL;
+#endif
+
+    struct ble_l2cap_chan *chan;
+
+    SLIST_FOREACH(chan, &conn->bhc_channels, next) {
+        if (chan->dcid == cid) {
+            return chan;
+        }
+        if (chan->dcid > cid) {
+            return NULL;
+        }
+    }
+
+    return NULL;
+}
+
 int
 ble_hs_conn_chan_insert(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/src/ble_hs_conn_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_conn_priv.h b/net/nimble/host/src/ble_hs_conn_priv.h
index 24e2e48..4c51646 100644
--- a/net/nimble/host/src/ble_hs_conn_priv.h
+++ b/net/nimble/host/src/ble_hs_conn_priv.h
@@ -84,7 +84,9 @@ struct ble_hs_conn *ble_hs_conn_find_by_addr(const ble_addr_t *addr);
 struct ble_hs_conn *ble_hs_conn_find_by_idx(int idx);
 int ble_hs_conn_exists(uint16_t conn_handle);
 struct ble_hs_conn *ble_hs_conn_first(void);
-struct ble_l2cap_chan *ble_hs_conn_chan_find(struct ble_hs_conn *conn,
+struct ble_l2cap_chan *ble_hs_conn_chan_find_by_scid(struct ble_hs_conn *conn,
+                                             uint16_t cid);
+struct ble_l2cap_chan *ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn,
                                              uint16_t cid);
 int ble_hs_conn_chan_insert(struct ble_hs_conn *conn,
                             struct ble_l2cap_chan *chan);

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/src/ble_hs_misc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_hs_misc.c b/net/nimble/host/src/ble_hs_misc.c
index 578c7e4..f06bfae 100644
--- a/net/nimble/host/src/ble_hs_misc.c
+++ b/net/nimble/host/src/ble_hs_misc.c
@@ -39,7 +39,7 @@ ble_hs_misc_conn_chan_find(uint16_t conn_handle, uint16_t cid,
         chan = NULL;
         rc = BLE_HS_ENOTCONN;
     } else {
-        chan = ble_hs_conn_chan_find(conn, cid);
+        chan = ble_hs_conn_chan_find_by_scid(conn, cid);
         if (chan == NULL) {
             rc = BLE_HS_ENOTCONN;
         } else {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/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 306eac1..e048ce9 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -320,7 +320,7 @@ ble_l2cap_rx(struct ble_hs_conn *conn,
         /* Strip L2CAP header from the front of the mbuf. */
         os_mbuf_adj(om, BLE_L2CAP_HDR_SZ);
 
-        chan = ble_hs_conn_chan_find(conn, l2cap_hdr.cid);
+        chan = ble_hs_conn_chan_find_by_scid(conn, l2cap_hdr.cid);
         if (chan == NULL) {
             rc = BLE_HS_ENOENT;
 

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/src/ble_l2cap_coc.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_coc.c b/net/nimble/host/src/ble_l2cap_coc.c
index ac1b6fa..8d5f71f 100644
--- a/net/nimble/host/src/ble_l2cap_coc.c
+++ b/net/nimble/host/src/ble_l2cap_coc.c
@@ -168,6 +168,38 @@ ble_l2cap_coc_create_srv_chan(uint16_t conn_handle, uint16_t psm,
     return 0;
 }
 
+void
+ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
+                                uint16_t credits)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_chan *chan;
+
+    /* remote updated its credits */
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    chan = ble_hs_conn_chan_find_by_dcid(conn, dcid);
+    if (!chan) {
+        ble_hs_unlock();
+        return;
+    }
+
+    if (chan->coc_tx.credits + credits > 0xFFFF) {
+        BLE_HS_LOG(INFO, "LE CoC credits overflow...disconnecting\n");
+        ble_l2cap_sig_disconnect(chan);
+        ble_hs_unlock();
+        return;
+    }
+
+    chan->coc_tx.credits += credits;
+    ble_hs_unlock();
+}
+
 int
 ble_l2cap_coc_init(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/src/ble_l2cap_coc_priv.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/src/ble_l2cap_coc_priv.h b/net/nimble/host/src/ble_l2cap_coc_priv.h
index 63c593e..21f9ec2 100644
--- a/net/nimble/host/src/ble_l2cap_coc_priv.h
+++ b/net/nimble/host/src/ble_l2cap_coc_priv.h
@@ -61,6 +61,8 @@ struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(uint16_t conn_handle,
                                                  struct os_mbuf *sdu_rx,
                                                  ble_l2cap_event_fn *cb,
                                                  void *cb_arg);
+void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
+                                    uint16_t credits);
 #else
 #define ble_l2cap_coc_init()                                    0
 #define ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg)       BLE_HS_ENOTSUP

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/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 abc00ae..8da2dad 100644
--- a/net/nimble/host/src/ble_l2cap_sig.c
+++ b/net/nimble/host/src/ble_l2cap_sig.c
@@ -98,11 +98,13 @@ static ble_l2cap_sig_rx_fn ble_l2cap_sig_coc_req_rx;
 static ble_l2cap_sig_rx_fn ble_l2cap_sig_coc_rsp_rx;
 static ble_l2cap_sig_rx_fn ble_l2cap_sig_disc_rsp_rx;
 static ble_l2cap_sig_rx_fn ble_l2cap_sig_disc_req_rx;
+static ble_l2cap_sig_rx_fn ble_l2cap_sig_le_credits_rx;
 #else
 #define ble_l2cap_sig_coc_req_rx    ble_l2cap_sig_rx_noop
 #define ble_l2cap_sig_coc_rsp_rx    ble_l2cap_sig_rx_noop
 #define ble_l2cap_sig_disc_rsp_rx   ble_l2cap_sig_rx_noop
 #define ble_l2cap_sig_disc_req_rx   ble_l2cap_sig_rx_noop
+#define ble_l2cap_sig_le_credits_rx   ble_l2cap_sig_rx_noop
 #endif
 
 static ble_l2cap_sig_rx_fn * const ble_l2cap_sig_dispatch[] = {
@@ -120,7 +122,7 @@ static ble_l2cap_sig_rx_fn * const ble_l2cap_sig_dispatch[] = {
     [BLE_L2CAP_SIG_OP_UPDATE_RSP]           = ble_l2cap_sig_update_rsp_rx,
     [BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ]   = ble_l2cap_sig_coc_req_rx,
     [BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP]   = ble_l2cap_sig_coc_rsp_rx,
-    [BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT]     = ble_l2cap_sig_rx_noop,
+    [BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT]     = ble_l2cap_sig_le_credits_rx,
 };
 
 static uint8_t ble_l2cap_sig_cur_id;
@@ -876,7 +878,7 @@ ble_l2cap_sig_disc_req_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr,
     /* Let's find matching channel. Note that destination CID in the request
      * is from peer perspective. It is source CID from nimble perspective 
      */
-    chan = ble_hs_conn_chan_find(conn, le16toh(req->dcid));
+    chan = ble_hs_conn_chan_find_by_scid(conn, le16toh(req->dcid));
     if (!chan || (le16toh(req->scid) != chan->dcid)) {
         os_mbuf_free_chain(txom);
         ble_hs_unlock();
@@ -1006,6 +1008,50 @@ ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan)
 
     return rc;
 }
+
+static int
+ble_l2cap_sig_le_credits_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr,
+                            struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_le_credits *req;
+    int rc;
+
+    rc = ble_hs_mbuf_pullup_base(om, sizeof(*req));
+    if (rc != 0) {
+        return 0;
+    }
+
+    req = (struct ble_l2cap_sig_le_credits *) (*om)->om_data;
+
+    /* Ignore when peer sends zero credits */
+    if (req->credits == 0) {
+            return 0;
+    }
+
+    ble_l2cap_coc_le_credits_update(conn_handle, le16toh(req->scid),
+                                    le16toh(req->credits));
+
+    return 0;
+}
+
+int
+ble_l2cap_sig_le_credits(struct ble_l2cap_chan *chan, uint16_t credits)
+{
+    struct ble_l2cap_sig_le_credits *cmd;
+    struct os_mbuf *txom;
+
+    cmd = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT,
+                                ble_l2cap_sig_next_id(), sizeof(*cmd), &txom);
+
+    if (!cmd) {
+        return BLE_HS_ENOMEM;
+    }
+
+    cmd->scid = htole16(chan->scid);
+    cmd->credits = htole16(credits);
+
+    return ble_l2cap_sig_tx(chan->conn_handle, txom);
+}
 #endif
 /*****************************************************************************
  * $misc                                                                     *

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/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 0677405..49d096c 100644
--- a/net/nimble/host/src/ble_l2cap_sig_priv.h
+++ b/net/nimble/host/src/ble_l2cap_sig_priv.h
@@ -84,6 +84,11 @@ struct ble_l2cap_sig_disc_rsp {
     uint16_t scid;
 } __attribute__((packed));
 
+struct ble_l2cap_sig_le_credits {
+    uint16_t scid;
+    uint16_t credits;
+} __attribute__((packed));
+
 int ble_l2cap_sig_init_cmd(uint8_t op, uint8_t id, uint8_t payload_len,
                            struct os_mbuf **out_om, void **out_payload_buf);
 void ble_l2cap_sig_hdr_parse(void *payload, uint16_t len,
@@ -103,6 +108,7 @@ int ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
                               struct os_mbuf *sdu_rx,
                               ble_l2cap_event_fn *cb, void *cb_arg);
 int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan);
+int ble_l2cap_sig_le_credits(struct ble_l2cap_chan *chan, uint16_t credits);
 #else
 #define ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg) \
                                                                 BLE_HS_ENOTSUP

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/754c4456/net/nimble/host/test/src/ble_hs_conn_test.c
----------------------------------------------------------------------
diff --git a/net/nimble/host/test/src/ble_hs_conn_test.c b/net/nimble/host/test/src/ble_hs_conn_test.c
index 8ae4971..87f9b46 100644
--- a/net/nimble/host/test/src/ble_hs_conn_test.c
+++ b/net/nimble/host/test/src/ble_hs_conn_test.c
@@ -77,7 +77,7 @@ TEST_CASE(ble_hs_conn_test_direct_connect_success)
     TEST_ASSERT(conn->bhc_handle == 2);
     TEST_ASSERT(memcmp(conn->bhc_peer_addr.val, addr.val, 6) == 0);
 
-    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
     TEST_ASSERT(chan->my_mtu == BLE_ATT_MTU_PREFERRED_DFLT);
     TEST_ASSERT(chan->peer_mtu == 0);
@@ -131,7 +131,7 @@ TEST_CASE(ble_hs_conn_test_direct_connectable_success)
     TEST_ASSERT(conn->bhc_handle == 2);
     TEST_ASSERT(memcmp(conn->bhc_peer_addr.val, addr.val, 6) == 0);
 
-    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
     TEST_ASSERT(chan->my_mtu == BLE_ATT_MTU_PREFERRED_DFLT);
     TEST_ASSERT(chan->peer_mtu == 0);
@@ -192,7 +192,7 @@ TEST_CASE(ble_hs_conn_test_undirect_connectable_success)
     TEST_ASSERT(conn->bhc_handle == 2);
     TEST_ASSERT(memcmp(conn->bhc_peer_addr.val, addr.val, 6) == 0);
 
-    chan = ble_hs_conn_chan_find(conn, BLE_L2CAP_CID_ATT);
+    chan = ble_hs_conn_chan_find_by_scid(conn, BLE_L2CAP_CID_ATT);
     TEST_ASSERT_FATAL(chan != NULL);
     TEST_ASSERT(chan->my_mtu == BLE_ATT_MTU_PREFERRED_DFLT);
     TEST_ASSERT(chan->peer_mtu == 0);