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 2017/02/13 19:31:37 UTC

[02/10] incubator-mynewt-core git commit: nimble/l2cap: Add LE L2CAP COC API

nimble/l2cap: Add LE L2CAP COC API

This patch adds API for LE Connection Oriented Channels.
Note that implementation is hided behind BLE_L2CAP_COC_MAX_NUM flag
which defines maximum number of supported dynamic channels

Overview:
Idea is that credits are hidden from the user and controlled by the
stack. User creates its own memory pool for SDU taking into account
SDU size and number of L2CAP LE COC channels he expect to use.
User profiles SDU (os_mbuf) to the stack when creates or accepts
connection.

Flow overview.

Similar to GAP, L2CAP defines following events:

BLE_L2CAP_EVENT_COC_CONNECTED
BLE_L2CAP_EVENT_COC_DISCONNECT
BLE_L2CAP_EVENT_COC_ACCEPT
BLE_L2CAP_EVENT_COC_DATA_RECEIVED

which application should handle in ble_l2cap_event_fn() called cb in
 description below.

Outgoing connection:
1. *chan = ble_l2cap_connect(conn_handle, psm, mtu, struct os_mbuf *sdu_rx,
                             *cb, *cb_arg);

2. BLE_L2CAP_EVENT_COC_CONNECTED event is sent when channel has been
 established or rejected. If connection has been rejected, event contains
 reason for that.

3. BLE_L2CAP_EVENT_COC_DATA_RECEIVED event is sent  on incoming data.
 Note, it is sent when SDU is completed
3a. User needs to call ble_l2cap_recv_ready(*chan, sdu_rx) where
 sdu_rx is os_mbuf for next SDU.

4. To send data do remote device ble_l2cap_send(*chan, sdu_tx) shall
 be called

5. To drop channel ble_l2cap_disconnect(*chan) shall be called.
6. When disconnected BLE_L2CAP_EVENT_COC_DISCONNECTD event is sent

Incoming connection:
1. ble_l2cap_create_server(psm, mtu, *cb, *cb_arg)
2. BLE_L2CAP_COC_EVENT_ACCEPT event is sent on create connection request
 if there is server for given PSM in the stack.
2a. User might want to check required security and MTU requirements
 before accepts connection.
2b. User needs to call ble_l2cap_recv_ready(*chan, sdu_rx) where
 sdu_rx is os_mbuf for next SDU.
2c. If accept_cb returns 0, connection response is sent
2d. User gets BLE_L2CAP_EVENT_COC_CONNECTED event with a status


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

Branch: refs/heads/develop
Commit: 1afc08a637e0c9b94e78387ef4fe3aeffb1a37f1
Parents: 552adce
Author: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Authored: Tue Jan 17 14:13:24 2017 +0100
Committer: \u0141ukasz Rymanowski <lu...@codecoup.pl>
Committed: Thu Feb 2 12:59:59 2017 +0100

----------------------------------------------------------------------
 net/nimble/host/include/host/ble_l2cap.h | 114 ++++++++++++++++++++++++++
 net/nimble/host/src/ble_l2cap.c          |  47 ++++++++++-
 net/nimble/host/src/ble_l2cap_priv.h     |  18 ++++
 net/nimble/host/syscfg.yml               |   5 ++
 4 files changed, 181 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1afc08a6/net/nimble/host/include/host/ble_l2cap.h
----------------------------------------------------------------------
diff --git a/net/nimble/host/include/host/ble_l2cap.h b/net/nimble/host/include/host/ble_l2cap.h
index 52849af..604d080 100644
--- a/net/nimble/host/include/host/ble_l2cap.h
+++ b/net/nimble/host/include/host/ble_l2cap.h
@@ -56,6 +56,22 @@ struct ble_hs_conn;
 #define BLE_L2CAP_SIG_ERR_MTU_EXCEEDED          0x0001
 #define BLE_L2CAP_SIG_ERR_INVALID_CID           0x0002
 
+#define BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS        0x0000
+#define BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM            0x0002
+#define BLE_L2CAP_COC_ERR_NO_RESOURCES              0x0004
+#define BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN       0x0005
+#define BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR       0x0006
+#define BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ       0x0007
+#define BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC          0x0008
+#define BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID        0x0009
+#define BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED   0x000A
+#define BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS   0x000B
+
+#define BLE_L2CAP_EVENT_COC_CONNECTED                 0
+#define BLE_L2CAP_EVENT_COC_DISCONNECTED              1
+#define BLE_L2CAP_EVENT_COC_ACCEPT                    2
+#define BLE_L2CAP_EVENT_COC_DATA_RECEIVED             3
+
 typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
                                      void *arg);
 
@@ -70,6 +86,104 @@ int ble_l2cap_sig_update(uint16_t conn_handle,
                          struct ble_l2cap_sig_update_params *params,
                          ble_l2cap_sig_update_fn *cb, void *cb_arg);
 
+struct ble_l2cap_chan;
+
+/**
+ * Represents a L2CAP-related event.
+ * When such an event occurs, the host notifies the application by passing an
+ * instance of this structure to an application-specified callback.
+ */
+struct ble_l2cap_event {
+    /**
+     * Indicates the type of L2CAP event that occurred.  This is one of the
+     * BLE_L2CAP_EVENT codes.
+     */
+    uint8_t type;
+
+    /**
+     * A discriminated union containing additional details concerning the L2CAP
+     * event.  The 'type' field indicates which member of the union is valid.
+     */
+    union {
+        /**
+         * Represents a connection attempt. Valid for the following event
+         * types:
+         *     o BLE_L2CAP_EVENT_COC_CONNECTED */
+        struct {
+            /**
+             * The status of the connection attempt;
+             *     o 0: the connection was successfully established.
+             *     o BLE host error code: the connection attempt failed for
+             *       the specified reason.
+             */
+            int status;
+
+            /** Connection handle of the relevant connection */
+            uint16_t conn_handle;
+
+            /** The L2CAP channel of the relevant L2CAP connection. */
+            struct ble_l2cap_chan *chan;
+        } connect;
+
+        /**
+         * Represents a terminated connection. Valid for the following event
+         * types:
+         *     o BLE_L2CAP_EVENT_COC_DISCONNECTED
+         */
+        struct {
+            /** Connection handle of the relevant connection */
+            uint16_t conn_handle;
+
+            /** Information about the L2CAP connection prior to termination. */
+            struct ble_l2cap_chan *chan;
+        } disconnect;
+
+        /**
+         * Represents connection accept. Valid for the following event
+         * types:
+         *     o BLE_L2CAP_EVENT_COC_ACCEPT
+         */
+        struct {
+            /** Connection handle of the relevant connection */
+            uint16_t conn_handle;
+
+            /** MTU supported by peer device on the channel */
+            uint16_t peer_sdu_size;
+
+            /** The L2CAP channel of the relevant L2CAP connection. */
+            struct ble_l2cap_chan *chan;
+        } accept;
+
+        /**
+         * Represents received data. Valid for the following event
+         * types:
+         *     o BLE_L2CAP_EVENT_COC_DATA_RECEIVED
+         */
+        struct {
+            /** Connection handle of the relevant connection */
+            uint16_t conn_handle;
+
+            /** The L2CAP channel of the relevant L2CAP connection. */
+            struct ble_l2cap_chan *chan;
+
+            /** The mbuf with received SDU. */
+            struct os_mbuf *sdu_rx;
+        } receive;
+    };
+};
+
+typedef int ble_l2cap_event_fn(struct ble_l2cap_event *event, void *arg);
+
+int ble_l2cap_create_server(uint16_t psm, uint16_t mtu,
+                            ble_l2cap_event_fn *cb, void *cb_arg);
+
+int ble_l2cap_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_disconnect(struct ble_l2cap_chan *chan);
+int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx);
+void ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1afc08a6/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 a61ada7..bf279de 100644
--- a/net/nimble/host/src/ble_l2cap.c
+++ b/net/nimble/host/src/ble_l2cap.c
@@ -31,8 +31,9 @@ _Static_assert(sizeof (struct ble_l2cap_hdr) == BLE_L2CAP_HDR_SZ,
 struct os_mempool ble_l2cap_chan_pool;
 
 static os_membuf_t ble_l2cap_chan_mem[
-    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_L2CAP_MAX_CHANS),
-                     sizeof (struct ble_l2cap_chan))
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_L2CAP_MAX_CHANS) +
+                    MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM),
+                    sizeof (struct ble_l2cap_chan))
 ];
 
 STATS_SECT_DECL(ble_l2cap_stats) ble_l2cap_stats;
@@ -122,6 +123,44 @@ ble_l2cap_prepend_hdr(struct os_mbuf *om, uint16_t cid, uint16_t len)
     return om;
 }
 
+int
+ble_l2cap_create_server(uint16_t psm, uint16_t mtu,
+                        ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    /*TODO: Create server object and put it on the queue */
+    return BLE_HS_ENOTSUP;
+}
+
+int
+ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                  struct os_mbuf *sdu_rx, ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    /*
+     * TODO In here we are going to create l2cap channel and send
+     * BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ
+     */
+    return BLE_HS_ENOTSUP;
+}
+
+int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
+{
+    /*TODO Implement */
+    return BLE_HS_ENOTSUP;
+}
+
+int
+ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
+{
+    /*TODO Implement */
+    return BLE_HS_ENOTSUP;
+}
+
+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 */
+}
+
 static void
 ble_l2cap_forget_rx(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan)
 {
@@ -322,7 +361,9 @@ ble_l2cap_init(void)
 {
     int rc;
 
-    rc = os_mempool_init(&ble_l2cap_chan_pool, MYNEWT_VAL(BLE_L2CAP_MAX_CHANS),
+    rc = os_mempool_init(&ble_l2cap_chan_pool,
+                         MYNEWT_VAL(BLE_L2CAP_MAX_CHANS) +
+                         MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM),
                          sizeof (struct ble_l2cap_chan),
                          ble_l2cap_chan_mem, "ble_l2cap_chan_pool");
     if (rc != 0) {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1afc08a6/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 7733c20..900d749 100644
--- a/net/nimble/host/src/ble_l2cap_priv.h
+++ b/net/nimble/host/src/ble_l2cap_priv.h
@@ -63,6 +63,14 @@ typedef uint8_t ble_l2cap_chan_flags;
 
 typedef int ble_l2cap_rx_fn(uint16_t conn_handle, struct os_mbuf **rxom);
 
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0
+struct ble_l2cap_coc_endpoint {
+    uint16_t mtu;
+    uint16_t credits;
+    struct os_mbuf *sdu;
+};
+#endif
+
 struct ble_l2cap_chan {
     SLIST_ENTRY(ble_l2cap_chan) next;
     uint16_t scid;
@@ -74,6 +82,16 @@ struct ble_l2cap_chan {
     uint16_t rx_len;        /* Length of current reassembled rx packet. */
 
     ble_l2cap_rx_fn *rx_fn;
+
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0
+    uint16_t conn_handle;
+    uint16_t dcid;
+    uint16_t psm;
+    struct ble_l2cap_coc_endpoint coc_rx;
+    struct ble_l2cap_coc_endpoint coc_tx;
+    ble_l2cap_event_fn *cb;
+    void *cb_arg;
+#endif
 };
 
 struct ble_l2cap_hdr {

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-core/blob/1afc08a6/net/nimble/host/syscfg.yml
----------------------------------------------------------------------
diff --git a/net/nimble/host/syscfg.yml b/net/nimble/host/syscfg.yml
index 9b3ba66..dd42ed8 100644
--- a/net/nimble/host/syscfg.yml
+++ b/net/nimble/host/syscfg.yml
@@ -52,6 +52,11 @@ syscfg.defs:
             passes since the previous fragment was received, the connection is
             terminated.  A value of 0 means no timeout.
         value: 30000
+    BLE_L2CAP_COC_MAX_NUM:
+        description: >
+            Defines maximum number of LE Connection Oriented Channels channels.
+            When set to (0), LE COC is not compiled in.
+        value: 0
 
     # Security manager settings.
     BLE_SM_LEGACY: