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/07 00:05:31 UTC

[36/50] incubator-mynewt-core git commit: nimble/l2cap: Add handling receiving SDU over L2CAP LE CoC

nimble/l2cap: Add handling receiving SDU over L2CAP LE CoC

With this patch nimble can receive full SDU from remote device.
Once it is done, callback with SDU is called to application.


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

Branch: refs/heads/1_0_0_dev
Commit: 7870412b4eb22a337c03ace234e63de81d117d3e
Parents: 2ce91be
Author: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Authored: Sun Feb 12 15:20:50 2017 +0100
Committer: Marko Kiiskila <ma...@runtime.io>
Committed: Mon Mar 6 15:52:35 2017 -0800

----------------------------------------------------------------------
 net/nimble/host/src/ble_l2cap.c          |   2 +-
 net/nimble/host/src/ble_l2cap_coc.c      | 136 ++++++++++++++++++++++++++
 net/nimble/host/src/ble_l2cap_coc_priv.h |   4 +
 3 files changed, 141 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7870412b/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 e048ce9..b0ab23d 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -166,7 +166,7 @@ ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
 void
 ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx)
 {
-    /*TODO In here we going to update sdu_rx buffer */
+    ble_l2cap_coc_recv_ready(chan, sdu_rx);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7870412b/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 8d5f71f..b549ba7 100644
--- a/net/nimble/host/src/ble_l2cap_coc.c
+++ b/net/nimble/host/src/ble_l2cap_coc.c
@@ -28,6 +28,8 @@
 
 #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0
 
+#define BLE_L2CAP_SDU_SIZE              2
+
 STAILQ_HEAD(ble_l2cap_coc_srv_list, ble_l2cap_coc_srv);
 
 static struct ble_l2cap_coc_srv_list ble_l2cap_coc_srvs;
@@ -116,9 +118,115 @@ ble_l2cap_coc_srv_find(uint16_t psm)
     return srv;
 }
 
+static void
+ble_l2cap_event_coc_received_data(struct ble_l2cap_chan *chan,
+                                  struct os_mbuf *om)
+{
+    struct ble_l2cap_event event;
+
+    event.type = BLE_L2CAP_EVENT_COC_DATA_RECEIVED;
+    event.receive.chan = chan;
+    event.receive.sdu_rx = om;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
 static int
 ble_l2cap_coc_rx_fn(struct ble_l2cap_chan *chan)
 {
+    int rc;
+    struct os_mbuf **om;
+    struct ble_l2cap_coc_endpoint *rx;
+    uint16_t om_total;
+
+    /* Create a shortcut to rx_buf */
+    om = &chan->rx_buf;
+    BLE_HS_DBG_ASSERT(*om != NULL);
+
+    /* Create a shortcut to rx endpoint */
+    rx = &chan->coc_rx;
+
+    om_total = OS_MBUF_PKTLEN(*om);
+    rc = ble_hs_mbuf_pullup_base(om, om_total);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Fist LE frame */
+    if (OS_MBUF_PKTLEN(rx->sdu) == 0) {
+        uint16_t sdu_len;
+
+        sdu_len = get_le16((*om)->om_data);
+        if (sdu_len > rx->mtu) {
+            /* TODO Disconnect?*/
+            BLE_HS_LOG(INFO, "error: sdu_len > rx->mtu (%d>%d)\n",
+                       sdu_len, rx->mtu);
+            return BLE_HS_EBADDATA;
+        }
+
+        BLE_HS_LOG(DEBUG, "sdu_len=%d, received LE frame=%d, credits=%d\n",
+                   sdu_len, om_total, rx->credits);
+
+        os_mbuf_adj(*om , BLE_L2CAP_SDU_SIZE);
+
+        rc = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total - BLE_L2CAP_SDU_SIZE);
+        if (rc != 0) {
+            /* FIXME: User shall give us big enough buffer.
+             * need to handle it better
+             */
+            BLE_HS_LOG(INFO, "Could not append data rc=%d\n", rc);
+            assert(0);
+        }
+
+        /* In RX case data_offset keeps incoming SDU len */
+        rx->data_offset = sdu_len;
+
+    } else {
+        BLE_HS_LOG(DEBUG, "Continuation...received %d\n", (*om)->om_len);
+
+        rc  = os_mbuf_appendfrom(rx->sdu, *om, 0, om_total);
+        if (rc != 0) {
+            /* FIXME: need to handle it better */
+            BLE_HS_LOG(DEBUG, "Could not append data rc=%d\n", rc);
+            assert(0);
+        }
+    }
+
+    rx->credits--;
+
+    if (OS_MBUF_PKTLEN(rx->sdu) == rx->data_offset) {
+        struct os_mbuf *sdu_rx = rx->sdu;
+
+        /* Lets get back control to os_mbuf to application.
+         * Since it this callback application might want to set new sdu
+         * we need to prepare space for this. Therefore we need sdu_rx
+         */
+
+        rx->sdu = NULL;
+        rx->data_offset = 0;
+
+        ble_l2cap_event_coc_received_data(chan, sdu_rx);
+
+        goto done;
+    }
+
+    /* If we did not received full SDU and credits are 0 it means
+     * that remote was sending us not fully filled up LE frames.
+     * However, we still have buffer to for next LE Frame so lets give one more
+     * credit to peer so it can send us full SDU
+     */
+    if (rx->credits == 0 && rx->sdu) {
+        /* Remote did not send full SDU. Lets give him one more credits to do
+         * so since we have still buffer to handle it
+         */
+        rx->credits = 1;
+        ble_l2cap_sig_le_credits(chan, rx->credits);
+    }
+
+done:
+    BLE_HS_LOG(DEBUG, "Received sdu_len=%d, credits left=%d\n",
+               OS_MBUF_PKTLEN(rx->sdu), rx->credits);
+
     return 0;
 }
 
@@ -200,6 +308,34 @@ ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
     ble_hs_unlock();
 }
 
+void
+ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_chan *c;
+
+    chan->coc_rx.sdu = sdu_rx;
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(chan->conn_handle);
+    c = ble_hs_conn_chan_find_by_scid(conn, chan->scid);
+    if (!c) {
+        ble_hs_unlock();
+        return;
+    }
+
+    /* FIXME 10 is hardcoded - make it better.
+     * We want to back only that much credits which remote side is missing
+     * to be able to send complete SDU.
+     */
+    if (chan->coc_rx.credits < 10) {
+        ble_l2cap_sig_le_credits(chan, 10 - chan->coc_rx.credits);
+        chan->coc_rx.credits = 10;
+    }
+
+    ble_hs_unlock();
+}
+
 int
 ble_l2cap_coc_init(void)
 {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/7870412b/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 21f9ec2..88380ea 100644
--- a/net/nimble/host/src/ble_l2cap_coc_priv.h
+++ b/net/nimble/host/src/ble_l2cap_coc_priv.h
@@ -39,6 +39,7 @@ struct ble_l2cap_chan;
 struct ble_l2cap_coc_endpoint {
     uint16_t mtu;
     uint16_t credits;
+    uint16_t data_offset;
     struct os_mbuf *sdu;
 };
 
@@ -63,9 +64,12 @@ struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(uint16_t conn_handle,
                                                  void *cb_arg);
 void ble_l2cap_coc_le_credits_update(uint16_t conn_handle, uint16_t dcid,
                                     uint16_t credits);
+void ble_l2cap_coc_recv_ready(struct ble_l2cap_chan *chan,
+                              struct os_mbuf *sdu_rx);
 #else
 #define ble_l2cap_coc_init()                                    0
 #define ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg)       BLE_HS_ENOTSUP
+#define ble_l2cap_coc_recv_ready(chan, sdu_rx)
 #endif
 
 #ifdef __cplusplus