Hi,

On 17 January 2017 at 14:28, Łukasz Rymanowski <
lukasz.rymanow...@codecoup.pl> wrote:

> 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_COC_EVENT_CONNECT
> BLE_L2CAP_COC_EVENT_DISCONNECT
> BLE_L2CAP_COC_EVENT_ACCEPT
> BLE_L2CAP_COC_EVENT_RECEIVE
>
>
Events shall be as follow:
BLE_L2CAP_EVENT_COC_CONNECT
BLE_L2CAP_EVENT_COC_DISCONNECT
BLE_L2CAP_EVENT_COC_ACCEPT
BLE_L2CAP_EVENT_COC_RECEIVE

This is something I changed just before sending RFC and forgot to update
commit message :)

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_COC_EVENT_CONNECT event is sent when channel has been
> established or rejected. If connection has
> been rejected, event contains reason for that.
> 3. BLE_L2CAP_COC_EVENT_RECEIVE 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_COC_EVENT_DISCONNECT 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 is considered established.
>
> --
>
> Hi all,
>
> Please have a look on fixed API after Chris comments.
>
> Best Regards
> Łukasz
> ---
>  net/nimble/host/include/host/ble_l2cap.h | 107
> +++++++++++++++++++++++++++++++
>  net/nimble/host/src/ble_l2cap.c          |  67 ++++++++++++++++++-
>  net/nimble/host/src/ble_l2cap_priv.h     |  21 ++++++
>  net/nimble/host/syscfg.yml               |   5 ++
>  4 files changed, 197 insertions(+), 3 deletions(-)
>
> diff --git a/net/nimble/host/include/host/ble_l2cap.h
> b/net/nimble/host/include/host/ble_l2cap.h
> index 52849af..081c655 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_CONNECT                 0
> +#define BLE_L2CAP_EVENT_COC_DISCONNECT              1
> +#define BLE_L2CAP_EVENT_COC_ACCEPT                  2
> +#define BLE_L2CAP_EVENT_COC_RECEIVE                 3
> +
>  typedef void ble_l2cap_sig_update_fn(uint16_t conn_handle, int status,
>                                       void *arg);
>
> @@ -70,6 +86,97 @@ 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_CONNECT */
> +        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;
> +
> +            /** 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_DISCONNECT
> +         */
> +        struct {
> +            /** 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_mtu;
> +
> +            /** 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_RECEIVE
> +         */
> +        struct {
> +            /** 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);
> +
> +struct ble_l2cap_chan *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
> diff --git a/net/nimble/host/src/ble_l2cap.c b/net/nimble/host/src/ble_
> l2cap.c
> index 7f66b57..db99445 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;
> @@ -137,6 +138,64 @@ 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)
> +{
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
> +    return BLE_HS_ENOTSUP;
> +#endif
> +
> +    /*TODO: Create server object and put it on the queue */
> +    return BLE_HS_ENOTSUP;
> +}
> +
> +struct ble_l2cap_chan *
> +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)
> +{
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
> +    return NULL;
> +#endif
> +
> +    /*
> +     * TODO In here we are going to create l2cap channel and send
> +     * BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ
> +     */
> +    return NULL;
> +}
> +
> +int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
> +{
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
> +    return BLE_HS_ENOTSUP;
> +#endif
> +
> +    /*TODO Implement */
> +    return BLE_HS_ENOTSUP;
> +}
> +
> +int
> +ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu)
> +{
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
> +    return BLE_HS_ENOTSUP;
> +#endif
> +
> +    /*TODO Implement */
> +    return BLE_HS_ENOTSUP;
> +}
> +
> +void
> +ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx)
> +{
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
> +    return;
> +#endif
> +
> +    /*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)
>  {
> @@ -337,7 +396,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) {
> diff --git a/net/nimble/host/src/ble_l2cap_priv.h
> b/net/nimble/host/src/ble_l2cap_priv.h
> index 79d58a7..99ee9e9 100644
> --- a/net/nimble/host/src/ble_l2cap_priv.h
> +++ b/net/nimble/host/src/ble_l2cap_priv.h
> @@ -63,6 +63,22 @@ 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)
> +struct ble_l2cap_coc_endpoint {
> +    uint16_t cid;
> +    uint16_t mtu;
> +    uint16_t mps;
> +    uint16_t credits;
> +    struct os_mbuf *sdu;
> +};
> +
> +struct ble_l2cap_coc_chan {
> +    struct ble_l2cap_coc_endpoint rx;
> +    struct ble_l2cap_coc_endpoint tx;
> +};
> +
> +#endif
> +
>  struct ble_l2cap_chan {
>      SLIST_ENTRY(ble_l2cap_chan) blc_next;
>      uint16_t blc_cid;
> @@ -75,6 +91,11 @@ struct ble_l2cap_chan {
>      uint16_t blc_rx_len;        /* Length of current reassembled rx
> packet. */
>
>      ble_l2cap_rx_fn *blc_rx_fn;
> +
> +#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
> +    struct ble_l2cap_coc_chan blc_coc;
> +    struct ble_l2cap_coc_chan_ops *blc_coc_ops;
> +#endif
>  };
>
>  struct ble_l2cap_hdr {
> diff --git a/net/nimble/host/syscfg.yml b/net/nimble/host/syscfg.yml
> index a2504bf..62ca6f6 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: 1
>
>      # Security manager settings.
>      BLE_SM_LEGACY:
> --
> 2.9.3
>
>
Best
Łukasz

Reply via email to