You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2020/01/28 17:07:58 UTC

[GitHub] [mynewt-nimble] rymanluk opened a new pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

rymanluk opened a new pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744
 
 
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377697989
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1283,165 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+int
+ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                           uint8_t num, struct os_mbuf *sdu_rx[num],
+                           ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                /* Clear callback to make sure "Disconnected event" to the user */
+                chan[j].cb = NULL;
+                ble_l2cap_chan_free(conn, proc->connect.chan[j]);
+            }
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+        proc->connect.chan[i] = chan;
+    }
+    proc->connect.cids_cnt = num;
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_CONNECT;
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ, proc->id,
+                                sizeof(*req) + num * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    req->psm = htole16(psm);
+    req->mtu = htole16(chan->coc_rx.mtu);
+    req->mps = htole16(chan->my_mtu);
+    req->credits = htole16(chan->coc_rx.credits);
+    for (i = 0; i < num; i++) {
+        req->scids[i] = htole16(proc->connect.chan[i]->scid);
+    }
+
+    ble_hs_unlock();
+
+    rc = ble_l2cap_sig_tx(proc->conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+    }
+
+done:
+    ble_l2cap_sig_process_status(proc, rc);
+
+    return rc;
+}
+
+int
+ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, uint16_t new_mtu,
+                           uint8_t cnt, struct ble_l2cap_chan *chans[])
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    int rc;
+    int i;
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+    if (!proc) {
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    for (i = 0; i < cnt; i++) {
+        if (ble_hs_conn_chan_exist(conn, chans[i])) {
+            proc->reconfig.cids[i] = chans[i]->scid;
+        } else {
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+    }
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_RECONFIG;
+    proc->reconfig.cids_cnt = cnt;
+    proc->reconfig.new_mtu = new_mtu;
+    proc->reconfig.new_mps = MYNEWT_VAL(BLE_L2CAP_COC_MPS);
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_REQ, proc->id,
+                                sizeof(*req) + cnt * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
 
 Review comment:
   goto done

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388136398
 
 

 ##########
 File path: apps/btshell/src/cmd.c
 ##########
 @@ -3540,6 +3543,24 @@ static const struct shell_cmd_help l2cap_disconnect_help = {
     .params = l2cap_disconnect_params,
 };
 
+/*****************************************************************************
+ * $l2cap-reconfig                                                           *
+ *****************************************************************************/
+
+static const struct shell_param l2cap_reconfig_params[] = {
+    {"conn", "connection handle, usage: =<UINT16>"},
+    {"mtu", "new mtu, usage: =<UINT16>, default: 0 (no change)"},
+    {"mps", "new mps, usage: =<UINT16>, default: 0 (no change)"},
+    {"idxs", "list of channel indexes, usage: idxs=01:03"},
 
 Review comment:
   better use comma as separator - we use colon for byte streams already so it will be confusing

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382995938
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -73,11 +82,20 @@ struct ble_l2cap_sig_proc {
             void *cb_arg;
         } update;
         struct {
-            struct ble_l2cap_chan *chan;
+            uint8_t cids_cnt;
 
 Review comment:
   chan_cnt?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377694780
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1283,165 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+int
+ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                           uint8_t num, struct os_mbuf *sdu_rx[num],
+                           ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                /* Clear callback to make sure "Disconnected event" to the user */
+                chan[j].cb = NULL;
+                ble_l2cap_chan_free(conn, proc->connect.chan[j]);
+            }
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+        proc->connect.chan[i] = chan;
+    }
+    proc->connect.cids_cnt = num;
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_CONNECT;
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ, proc->id,
+                                sizeof(*req) + num * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
 
 Review comment:
   goto done?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385730896
 
 

 ##########
 File path: nimble/host/src/ble_l2cap.c
 ##########
 @@ -155,7 +155,61 @@ ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg);
 }
 
-int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
+int
+ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info)
+{
+    if (!chan || !chan_info) {
+        return BLE_HS_EINVAL;
+    }
+
+    memset(chan_info, 0, sizeof(*chan_info));
+    chan_info->dcid = chan->dcid;
+    chan_info->scid = chan->scid;
+    chan_info->our_l2cap_mtu = chan->my_mtu;
+    chan_info->peer_l2cap_mtu = chan->peer_mtu;
+
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
+    chan_info->psm = chan->psm;
+    chan_info->our_coc_mtu = chan->coc_rx.mtu;
+    chan_info->peer_coc_mtu = chan->coc_tx.mtu;
+#endif
+
+    return 0;
+}
+
+int
+ble_l2cap_enhanced_connect(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[],
+                               ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    return ble_l2cap_sig_ecoc_connect(conn_handle, psm, mtu,
+                                      num, sdu_rx, cb, cb_arg);
+}
+
+int
+ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu)
+{
+    int i;
+    uint16_t conn_handle;
+
+    if (num == 0 || !chans) {
+        return BLE_HS_EINVAL;
+    }
+
+    conn_handle = chans[0]->conn_handle;
+
+    for (i = 1; i < num; i++) {
+        if (conn_handle != chans[i]->conn_handle) {
+            return BLE_HS_EINVAL;
 
 Review comment:
   here ok as same error code is returned as above :)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385732728
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,31 +643,456 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
+    bool some_not_connected = false;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (!chan || !chan->cb) {
+            continue;
+        }
+
+        if ((status == 0) && (chan->dcid != 0)) {
+            ble_l2cap_event_coc_connected(chan, status);
+            /* Let's forget about connected channel now.
+             * Not connected will be freed later on.
+             */
+            proc->connect.chan[i] = NULL;
+            continue;
+        }
+        some_not_connected = true;
+        ble_l2cap_event_coc_connected(chan, status ? status : BLE_HS_EREJECT);
+    }
+
+    if (!some_not_connected) {
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    /* Free not connected channels*/
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(chan->conn_handle);
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (chan) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.
+             */
+            chan->cb = NULL;
+            ble_l2cap_chan_free(conn, chan);
+        }
+    }
+    ble_hs_unlock();
+}
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_reconfig_req *req;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        ble_hs_unlock();
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_reconfig_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (cid_cnt > BLE_L2CAP_MAX_COC_CONN_REQ) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_coc_mps > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_coc_mps = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+    }
+
+    ble_hs_unlock();
+
+    for (i = 0; i < proc->reconfig.cid_cnt; i++) {
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+    }
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    ble_hs_lock();
+
+    memset(rsp, 0, len);
+
+    /* Initial dummy values in case of error, just to satisfy PTS */
+    rsp->credits = htole16(1);
+    rsp->mps = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+    rsp->mtu = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if ((req->mtu < BLE_L2CAP_ECOC_MIN_MTU) || (req->mps < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    /* First verify that provided SCIDs are good */
+    for (i = 0; i < num_of_scids; i++) {
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            goto failed;
+        }
+    }
+
+    /* Let us try to connect channels */
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            continue;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            if (i == 0) {
+                /* In case it is very first channel we cannot create it means PSM is incorrect
+                 * or we are out of resources. Just send a response now.
+                 */
+                rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+                goto failed;
+            } else {
+                /* We cannot create number of channels req by peer due to limited resources. */
+                rsp->result = htole16(BLE_L2CAP_COC_ERR_NO_RESOURCES);
+                goto done;
+            }
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_coc_mps = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        /* Sending event to the app. Unlock hs */
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc == 0) {
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            chan_created++;
+            if (chan_created == 1) {
+                /* We need to set it once as there are same initial parameters
+                 * for all the channels
+                 */
+                rsp->credits = htole16(chans[i]->coc_rx.credits);
+                rsp->mps = htole16(chans[i]->my_mtu);
+                rsp->mtu = htole16(chans[i]->coc_rx.mtu);
+            }
+        } else {
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            ble_hs_conn_delete_chan(conn, chans[i]);
+            chans[i] = NULL;
+            rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+            rc = 0;
+            ble_hs_unlock();
+        }
 
-    if (status) {
-        /* Normally in channel free we send disconnected event to application.
-         * However in case on error during creation connection we send connected
-         * event with error status. To avoid additional disconnected event lets
-         * clear callbacks since we don't needed it anymore.*/
-        chan->cb = NULL;
         ble_hs_lock();
-        conn = ble_hs_conn_find(chan->conn_handle);
-        ble_l2cap_chan_free(conn, chan);
+        conn = ble_hs_conn_find_assert(conn_handle);
+    }
+
+done:
+    ble_hs_unlock();
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        for (i = 0; i < num_of_scids; i++) {
+            if (chans[i]) {
+                ble_hs_conn_delete_chan(conn, chans[i]);
+            }
+        }
         ble_hs_unlock();
+        return 0;
+    }
+
+    /* Notify user about connection status */
+    for (i = 0; i < num_of_scids; i++) {
+        if (chans[i]) {
+            ble_l2cap_event_coc_connected(chans[i], rc);
+        }
     }
+
+    return 0;
+
+failed:
+    ble_hs_unlock();
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
 }
 
+static int
+ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+    int i;
+
+#if !BLE_MONITOR
+    BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n");
+#endif
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_CONNECT,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_connect_rsp *)(*om)->om_data;
+
+    if (rsp->result) {
+        rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
+        goto done;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    assert(conn != NULL);
+
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (rsp->dcids[i] == 0) {
+            /* Channel rejected, dont put it on the list.
+             * User will get notified later in that function
+             */
+            chan->dcid = 0;
+            continue;
+        }
+        chan->peer_coc_mps = le16toh(rsp->mps);
+        chan->dcid = le16toh(rsp->dcids[i]);
+        chan->coc_tx.mtu = le16toh(rsp->mtu);
+        chan->coc_tx.credits = le16toh(rsp->credits);
+
+        ble_hs_conn_chan_insert(conn, chan);
+    }
+
+    ble_hs_unlock();
+
+done:
+    ble_l2cap_sig_coc_connect_cb(proc, rc);
+    ble_l2cap_sig_proc_free(proc);
+
+    /* Silently ignore errors as this is response signal */
 
 Review comment:
   Application will get errors in `rc`

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388928497
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2334,6 +2373,43 @@ btshell_l2cap_disconnect(uint16_t conn_handle, uint16_t idx)
 #endif
 }
 
+int
+btshell_l2cap_reconfig(uint16_t conn_handle, uint16_t mtu,
+                       uint8_t num, uint8_t idxs[])
+{
+    struct btshell_conn *conn;
+    struct btshell_l2cap_coc *coc;
+    struct ble_l2cap_chan * chans[5] = {0};
+    int i, j;
+    int cnt;
+
+    conn = btshell_conn_find(conn_handle);
+    if (conn == NULL) {
+        console_printf("conn=%d does not exist\n", conn_handle);
+        return 0;
+    }
+
+    i = 0;
+    j = 0;
+    cnt = 0;
+    SLIST_FOREACH(coc, &conn->coc_list, next) {
+        for (i = 0; i < num; i++) {
+            if (idxs[i] == j) {
+                chans[cnt] = coc->chan;
+                cnt++;
+                break;
+            }
+        }
+        j++;
+    }
+
+    if (cnt != num) {
+        console_printf("Missing coc? (%d!=%d)\n", num, cnt);
 
 Review comment:
   I'd just fail here

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385114846
 
 

 ##########
 File path: nimble/host/syscfg.yml
 ##########
 @@ -118,6 +118,13 @@ syscfg.defs:
             MSYS blocks.
         value: 'MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8'
 
+    BLE_L2CAP_ENHANCED_COC:
 
 Review comment:
   Update syscfg for porting examples

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375267413
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -196,6 +209,28 @@ struct ble_l2cap_event {
              */
             int status;
         } tx_unstalled;
+
+        /**
+         * Represents reconfiguration done. Valid for the following event
+         * types:
+         *      o BLE_L2CAP_EVENT_RECONFIGURE_COMPLETED
 
 Review comment:
   BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377660646
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -224,6 +259,13 @@ int ble_l2cap_send(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_tx);
 int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx);
 int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info);
 
+/* Below API available when BLE_VERSION >= 52 */
+int ble_l2cap_enhanced_connect(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[],
+                               ble_l2cap_event_fn *cb, void *cb_arg);
+int ble_l2cap_reconfig(uint16_t conn_handle, uint16_t new_mtu,
 
 Review comment:
   why do we need conn_handle in this api?
   
   also for this kind of API we usually provide  first pointer, then count
   
   also, why is this   struct ble_l2cap_chan *chans[] and not just *chans?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#issuecomment-584654705
 
 
   When testing I noticed an issue that when we accepted only 2 channels and a peer wanted to connect 3 channels, then we would accept the 2 and then return an error because we couldn't allocate another channel, but we didn't free those allocated channels in app. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375406287
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,30 +640,391 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+        if (!chan || !chan->cb) {
+            return;
+        }
+
+        ble_l2cap_event_coc_connected(chan, status);
+
+        if (status) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.*/
+            chan->cb = NULL;
+            ble_hs_lock();
+            conn = ble_hs_conn_find(chan->conn_handle);
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+        }
+        chan = proc->connect.chan[++i];
+    };
+}
+
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_config_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_CIDS_IN_PACKET);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+        ble_hs_unlock();
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+        ble_hs_lock();
+    }
+
+    ble_hs_unlock();
+
+}
+static int
+ble_l2cap_sig_credit_base_config_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_config_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    int i;
+    int j;
+    uint8_t num_of_scids;
+    uint16_t scid;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, hdr->length , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    memset(rsp, 0, sizeof(*rsp));
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if (req->mtu < 64) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+            rsp->result = htole16(coc_err);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_mtu = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            for (j = 0; j < i; j++) {
+                ble_hs_conn_delete_chan(conn, chans[j]);
+            }
+            ble_hs_unlock();
+            rsp->result = htole16(coc_err);
+            goto failed;
+        }
+        rsp->dcids[i] = htole16(chans[i]->scid);
 
-    if (status) {
-        /* Normally in channel free we send disconnected event to application.
-         * However in case on error during creation connection we send connected
-         * event with error status. To avoid additional disconnected event lets
-         * clear callbacks since we don't needed it anymore.*/
-        chan->cb = NULL;
         ble_hs_lock();
-        conn = ble_hs_conn_find(chan->conn_handle);
-        ble_l2cap_chan_free(conn, chan);
+        conn = ble_hs_conn_find_assert(conn_handle);
+
+    }
+    ble_hs_unlock();
+
+    /* Same initial parameters for all the channels */
+    rsp->credits = htole16(chans[0]->coc_rx.credits);
+    rsp->mps = htole16(chans[0]->my_mtu);
+    rsp->mtu = htole16(chans[0]->coc_rx.mtu);
+    rsp->result = htole16(BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS);
+
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        for (i = 0; i < num_of_scids; i++) {
+            ble_hs_conn_delete_chan(conn, chans[i]);
+        }
         ble_hs_unlock();
+        return 0;
+    }
+
+    /* Notify user about connection status */
+    for (i = 0; i < num_of_scids; i++) {
+        ble_l2cap_event_coc_connected(chans[i], rc);
+    }
+
+    return 0;
+
+failed:
+    memset(rsp->dcids, 0, num_of_scids * sizeof(uint16_t));
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+    int i;
+
+#if !BLE_MONITOR
+    BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n");
+#endif
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_CONNECT,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
     }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_connect_rsp *)(*om)->om_data;
+
+    if (rsp->result) {
+        rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
+        goto done;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    assert(conn != NULL);
+
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+
+        /* Fill up remote configuration
+         * Note MPS is the L2CAP MTU
+         */
+        chan->peer_mtu = le16toh(rsp->mps);
+        chan->dcid = le16toh(rsp->dcids[i]);
+        chan->coc_tx.mtu = le16toh(rsp->mtu);
+        chan->coc_tx.credits = le16toh(rsp->credits);
+
+        ble_hs_conn_chan_insert(conn, chan);
+
+        chan = proc->connect.chan[++i];
 
 Review comment:
   Potential memory corruption.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388137622
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2253,10 +2280,42 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
 
         case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
             btshell_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+            return 0;
+        case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
+
+            if (ble_l2cap_get_chan_info(event->reconfigured.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE CoC reconfigure completed status 0x%02x," \
+                            "chan: 0x%08lx\n",
 
 Review comment:
   use %p for pointers

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375995758
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1261,170 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+int
+ble_l2cap_sig_coc_connect_multiple(uint16_t conn_handle,
+                                   uint16_t psm, uint16_t mtu,
+                                   uint8_t num, struct os_mbuf *sdu_rx[num],
+                                   ble_l2cap_event_fn *cb, void *cb_arg)
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                chan[j].cb = NULL;
 
 Review comment:
   Can you do this in ble_l2cap_chan_free?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on issue #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on issue #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#issuecomment-593476047
 
 
   @andrzej-kaczmarek ping

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382996199
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
 
 Review comment:
   this condition always evaluates to true

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375268931
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -219,11 +254,16 @@ int ble_l2cap_create_server(uint16_t psm, uint16_t mtu,
 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_connect_multiple(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[num],
+                               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);
 int ble_l2cap_recv_ready(struct ble_l2cap_chan *chan, struct os_mbuf *sdu_rx);
 int ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info);
-
+int ble_l2cap_reconfig(uint16_t conn_handle, uint16_t new_mtu,
+                       uint8_t cnt, struct ble_l2cap_chan *chans[]);
 
 Review comment:
   cnt -> num
   
   I think both new APIs should be added below existing APIs and have comment that they require 5.2 feature to work, otherwise one might think that this works using "old" coc sig messages

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382996315
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
 
 Review comment:
   we should not assert on errors in received data...

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382993611
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+        ble_hs_unlock();
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+        ble_hs_lock();
+    }
+
+    ble_hs_unlock();
+
+}
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_config_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    memset(rsp, 0, len);
+
+    /* Initial dummy values in case of error, just to satisfy PTS */
+    rsp->credits = htole16(1);
+    rsp->mps = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+    rsp->mtu = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if ((req->mtu < BLE_L2CAP_ECOC_MIN_MTU) || (req->mps < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    /* First verify that provided SCIDs are good */
+    for (i = 0; i < num_of_scids; i++) {
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            ble_hs_unlock();
+            goto failed;
+        }
+    }
+
+    /* Let us try to connect channels */
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            continue;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            if (i == 0) {
+                /* In case it is very first channel we cannot create it means PSM is incorrect
+                 * or we are out of resources. Just send a response now.
+                 */
+                rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+                ble_hs_unlock();
+                goto failed;
+            } else {
+                /* We cannot create number of channels req by peer due to limited resources. */
+                ble_hs_unlock();
+                rsp->result = htole16(BLE_L2CAP_COC_ERR_NO_RESOURCES);
+                goto done;
+            }
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_mtu = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc == 0) {
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            chan_created++;
+            if (chan_created == 1) {
+                /* We need to set it once as there are same initial parameters
+                 * for all the channels
+                 */
+                rsp->credits = htole16(chans[i]->coc_rx.credits);
+                rsp->mps = htole16(chans[i]->my_mtu);
+                rsp->mtu = htole16(chans[i]->coc_rx.mtu);
+            }
+        } else {
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            ble_hs_conn_delete_chan(conn, chans[i]);
+            chans[i] = NULL;
+            rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+            rc = 0;
+            ble_hs_unlock();
+        }
+
+        ble_hs_lock();
 
 Review comment:
   wouldn't it be just easier to hold lock for the entire duration of loop or at least lock a the beginning of loop? the way this is done now it's just asking for trouble.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377687186
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +672,382 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
 
 Review comment:
   ble_hs_unlock() is missing

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375387077
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2265,35 +2324,53 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
 #endif
 
 int
-btshell_l2cap_create_srv(uint16_t psm, int accept_response)
+btshell_l2cap_create_srv(uint16_t psm, uint16_t mtu, int accept_response)
 {
 #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
     console_printf("BLE L2CAP LE COC not supported.");
     console_printf(" Configure nimble host to enable it\n");
     return 0;
 #else
 
-    return ble_l2cap_create_server(psm, BTSHELL_COC_MTU, btshell_l2cap_event,
+    if (mtu == 0 || mtu > BTSHELL_COC_MTU) {
+        mtu = BTSHELL_COC_MTU;
+    }
+
+    return ble_l2cap_create_server(psm, mtu, btshell_l2cap_event,
                                    INT_TO_PTR(accept_response));
 #endif
 }
 
 int
-btshell_l2cap_connect(uint16_t conn_handle, uint16_t psm)
+btshell_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu, uint8_t num)
 {
 #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) == 0
     console_printf("BLE L2CAP LE COC not supported.");
     console_printf(" Configure nimble host to enable it\n");
     return 0;
 #else
 
-    struct os_mbuf *sdu_rx;
+    struct os_mbuf *sdu_rx[num];
+    int i;
 
-    sdu_rx = os_mbuf_get_pkthdr(&sdu_os_mbuf_pool, 0);
-    assert(sdu_rx != NULL);
+    if (mtu == 0 || mtu > BTSHELL_COC_MTU) {
+        mtu = BTSHELL_COC_MTU;
+    }
+
+    console_printf("L2CAP CoC MTU: %d, max available %d", mtu, BTSHELL_COC_MTU);
 
 Review comment:
   Missing newline

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377063427
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,30 +640,391 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+        if (!chan || !chan->cb) {
+            return;
+        }
+
+        ble_l2cap_event_coc_connected(chan, status);
+
+        if (status) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.*/
+            chan->cb = NULL;
+            ble_hs_lock();
+            conn = ble_hs_conn_find(chan->conn_handle);
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+        }
+        chan = proc->connect.chan[++i];
+    };
+}
+
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_config_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_CIDS_IN_PACKET);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, proc->reconfig.cids[i]);
 
 Review comment:
   you are right, thx

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#issuecomment-584653911
 
 
   We should consider adding a MYNEWT_VAL to enable/disable this feature and make it depend on BLE_VERSION: 52

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388881419
 
 

 ##########
 File path: apps/btshell/src/cmd.c
 ##########
 @@ -3540,6 +3543,24 @@ static const struct shell_cmd_help l2cap_disconnect_help = {
     .params = l2cap_disconnect_params,
 };
 
+/*****************************************************************************
+ * $l2cap-reconfig                                                           *
+ *****************************************************************************/
+
+static const struct shell_param l2cap_reconfig_params[] = {
+    {"conn", "connection handle, usage: =<UINT16>"},
+    {"mtu", "new mtu, usage: =<UINT16>, default: 0 (no change)"},
+    {"mps", "new mps, usage: =<UINT16>, default: 0 (no change)"},
+    {"idxs", "list of channel indexes, usage: idxs=01:03"},
 
 Review comment:
   ok

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375265623
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -54,7 +54,11 @@ struct ble_hs_conn;
 #define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_REQ  0x14
 #define BLE_L2CAP_SIG_OP_LE_CREDIT_CONNECT_RSP  0x15
 #define BLE_L2CAP_SIG_OP_FLOW_CTRL_CREDIT       0x16
-#define BLE_L2CAP_SIG_OP_MAX                    0x17
+#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ     0x17
+#define BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP     0x18
+#define BLE_L2CAP_SIG_OP_CREDIT_CONFIG_REQ      0x19
+#define BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP      0x1A
 
 Review comment:
   config -> reconfig(ure)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388881491
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2253,10 +2280,42 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
 
         case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
             btshell_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+            return 0;
+        case BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED:
+
+            if (ble_l2cap_get_chan_info(event->reconfigured.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE CoC reconfigure completed status 0x%02x," \
+                            "chan: 0x%08lx\n",
 
 Review comment:
   ok

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384461035
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
 
 Review comment:
   fixed

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385730385
 
 

 ##########
 File path: nimble/host/src/ble_l2cap.c
 ##########
 @@ -155,7 +155,61 @@ ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg);
 }
 
-int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
+int
+ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info)
+{
+    if (!chan || !chan_info) {
+        return BLE_HS_EINVAL;
+    }
+
+    memset(chan_info, 0, sizeof(*chan_info));
+    chan_info->dcid = chan->dcid;
+    chan_info->scid = chan->scid;
+    chan_info->our_l2cap_mtu = chan->my_mtu;
+    chan_info->peer_l2cap_mtu = chan->peer_mtu;
+
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
+    chan_info->psm = chan->psm;
+    chan_info->our_coc_mtu = chan->coc_rx.mtu;
+    chan_info->peer_coc_mtu = chan->coc_tx.mtu;
+#endif
+
+    return 0;
+}
+
+int
+ble_l2cap_enhanced_connect(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[],
+                               ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    return ble_l2cap_sig_ecoc_connect(conn_handle, psm, mtu,
+                                      num, sdu_rx, cb, cb_arg);
+}
+
+int
+ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu)
+{
+    int i;
+    uint16_t conn_handle;
+
+    if (num == 0 || !chans) {
+        return BLE_HS_EINVAL;
 
 Review comment:
   I think, application can log error if needed.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384467997
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+        ble_hs_unlock();
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+        ble_hs_lock();
+    }
+
+    ble_hs_unlock();
+
+}
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_config_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    memset(rsp, 0, len);
+
+    /* Initial dummy values in case of error, just to satisfy PTS */
+    rsp->credits = htole16(1);
+    rsp->mps = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+    rsp->mtu = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if ((req->mtu < BLE_L2CAP_ECOC_MIN_MTU) || (req->mps < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    /* First verify that provided SCIDs are good */
+    for (i = 0; i < num_of_scids; i++) {
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            ble_hs_unlock();
+            goto failed;
+        }
+    }
+
+    /* Let us try to connect channels */
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            continue;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            if (i == 0) {
+                /* In case it is very first channel we cannot create it means PSM is incorrect
+                 * or we are out of resources. Just send a response now.
+                 */
+                rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+                ble_hs_unlock();
+                goto failed;
+            } else {
+                /* We cannot create number of channels req by peer due to limited resources. */
+                ble_hs_unlock();
+                rsp->result = htole16(BLE_L2CAP_COC_ERR_NO_RESOURCES);
+                goto done;
+            }
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_mtu = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc == 0) {
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            chan_created++;
+            if (chan_created == 1) {
+                /* We need to set it once as there are same initial parameters
+                 * for all the channels
+                 */
+                rsp->credits = htole16(chans[i]->coc_rx.credits);
+                rsp->mps = htole16(chans[i]->my_mtu);
+                rsp->mtu = htole16(chans[i]->coc_rx.mtu);
+            }
+        } else {
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            ble_hs_conn_delete_chan(conn, chans[i]);
+            chans[i] = NULL;
+            rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+            rc = 0;
+            ble_hs_unlock();
+        }
+
+        ble_hs_lock();
 
 Review comment:
   Issue is that I need to unlock before calling app to accept coc. 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382993943
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -105,7 +123,19 @@ static ble_l2cap_sig_rx_fn ble_l2cap_sig_le_credits_rx;
 #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
+#define ble_l2cap_sig_le_credits_rx                  ble_l2cap_sig_rx_noop
+#endif
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static ble_l2cap_sig_rx_fn ble_l2cap_sig_credit_base_con_req_rx;
+static ble_l2cap_sig_rx_fn ble_l2cap_sig_credit_base_con_rsp_rx;
+static ble_l2cap_sig_rx_fn ble_l2cap_sig_credit_base_reconfig_req_rx;
+static ble_l2cap_sig_rx_fn ble_l2cap_sig_credit_base_reconfig_rsp_rx;
+#else
+#define ble_l2cap_sig_credit_base_con_req_rx      ble_l2cap_sig_rx_noop
+#define ble_l2cap_sig_credit_base_con_rsp_rx      ble_l2cap_sig_rx_noop
+#define ble_l2cap_sig_credit_base_reconfig_req_rx ble_l2cap_sig_rx_noop
+#define ble_l2cap_sig_credit_base_reconfig_rsp_rx ble_l2cap_sig_rx_noop
 
 Review comment:
   redefining function names is really bad, you should do ifdef in dispatch table below instead

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375386467
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2221,14 +2247,15 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
                 return 0;
             }
 
-            console_printf("LE COC connected, conn: %d, chan: 0x%08lx, scid: 0x%04x, "
-                           "dcid: 0x%04x, our_mtu: 0x%04x, peer_mtu: 0x%04x\n",
-                           event->connect.conn_handle,
-                           (uint32_t) event->connect.chan,
-                           ble_l2cap_get_scid(event->connect.chan),
-                           ble_l2cap_get_dcid(event->connect.chan),
-                           ble_l2cap_get_our_mtu(event->connect.chan),
-                           ble_l2cap_get_peer_mtu(event->connect.chan));
+            if (ble_l2cap_get_chan_info(event->connect.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE COC connected, conn: %d, chan: 0x%08lx, psm: 0x%02x, scid: 0x%04x, "
+                           "dcid: 0x%04x, our_mps: %d, our_mtu: %d, peer_mps: 0x%d, peer_mtu: %d\n",
 
 Review comment:
   peer_mps: 0x%d should be peer_mps: %d

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385732827
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,31 +643,456 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
+    bool some_not_connected = false;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (!chan || !chan->cb) {
+            continue;
+        }
+
+        if ((status == 0) && (chan->dcid != 0)) {
+            ble_l2cap_event_coc_connected(chan, status);
+            /* Let's forget about connected channel now.
+             * Not connected will be freed later on.
+             */
+            proc->connect.chan[i] = NULL;
+            continue;
+        }
+        some_not_connected = true;
+        ble_l2cap_event_coc_connected(chan, status ? status : BLE_HS_EREJECT);
+    }
+
+    if (!some_not_connected) {
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    /* Free not connected channels*/
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(chan->conn_handle);
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (chan) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.
+             */
+            chan->cb = NULL;
+            ble_l2cap_chan_free(conn, chan);
+        }
+    }
+    ble_hs_unlock();
+}
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_reconfig_req *req;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        ble_hs_unlock();
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_reconfig_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (cid_cnt > BLE_L2CAP_MAX_COC_CONN_REQ) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_coc_mps > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_coc_mps = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+    }
+
+    ble_hs_unlock();
+
+    for (i = 0; i < proc->reconfig.cid_cnt; i++) {
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+    }
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
 
 Review comment:
   ok

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375385729
 
 

 ##########
 File path: apps/btshell/src/cmd.c
 ##########
 @@ -3540,6 +3543,24 @@ static const struct shell_cmd_help l2cap_disconnect_help = {
     .params = l2cap_disconnect_params,
 };
 
+/*****************************************************************************
+ * $l2cap-reconfig                                                           *
+ *****************************************************************************/
+
+static const struct shell_param l2cap_reconfig_params[] = {
+    {"conn", "connection handle, usage: =<UINT16>"},
+    {"mtu", "new mtu, usage: =<UINT16>, default: 0 (no change)"},
+    {"mps", "new mps, usage: =<UINT16>, default: 0 (no change)"},
+    {"idxs", "list of channel indexes, usage: idx_1:idx_2:...:idx_5"},
 
 Review comment:
   It wasn't clear for me at first how to use this parameter, maybe it could be improved.
   Example usage: idxs=00:11 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377011436
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1261,170 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+int
+ble_l2cap_sig_coc_connect_multiple(uint16_t conn_handle,
+                                   uint16_t psm, uint16_t mtu,
+                                   uint8_t num, struct os_mbuf *sdu_rx[num],
+                                   ble_l2cap_event_fn *cb, void *cb_arg)
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                chan[j].cb = NULL;
 
 Review comment:
   this is done for purpose to make sure host will not send "Disconnected callback" to the app.
   I will put a comment here.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384012599
 
 

 ##########
 File path: nimble/host/src/ble_hs_conn.c
 ##########
 @@ -88,6 +88,24 @@ ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, uint16_t cid)
     return NULL;
 }
 
+bool
+ble_hs_conn_chan_exist(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan)
+{
+#if !NIMBLE_BLE_CONNECT
+    return NULL;
 
 Review comment:
   When you look into this file, all functions does the same, is this reported by static analyzer?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377693392
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1283,165 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+int
+ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                           uint8_t num, struct os_mbuf *sdu_rx[num],
 
 Review comment:
   struct os_mbuf *sdu_rx[num]      ??

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382997167
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
 
 Review comment:
   conn may be invalid here since you unlock in the loop. the same pattern is used in other functions as well.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377674175
 
 

 ##########
 File path: nimble/host/src/ble_hs_conn.c
 ##########
 @@ -88,6 +88,24 @@ ble_hs_conn_chan_find_by_dcid(struct ble_hs_conn *conn, uint16_t cid)
     return NULL;
 }
 
+bool
+ble_hs_conn_chan_exist(struct ble_hs_conn *conn, struct ble_l2cap_chan *chan)
+{
+#if !NIMBLE_BLE_CONNECT
+    return NULL;
 
 Review comment:
   false
   
   also please follow
   
    #ifdef foo
      foo()
    #else 
     return NULL
     #endif
   
   
   otherwise static analysis tools gives false positives

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385099423
 
 

 ##########
 File path: nimble/host/src/ble_l2cap.c
 ##########
 @@ -155,7 +155,61 @@ ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg);
 }
 
-int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
+int
+ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info)
+{
+    if (!chan || !chan_info) {
+        return BLE_HS_EINVAL;
+    }
+
+    memset(chan_info, 0, sizeof(*chan_info));
+    chan_info->dcid = chan->dcid;
+    chan_info->scid = chan->scid;
+    chan_info->our_l2cap_mtu = chan->my_mtu;
+    chan_info->peer_l2cap_mtu = chan->peer_mtu;
+
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
+    chan_info->psm = chan->psm;
+    chan_info->our_coc_mtu = chan->coc_rx.mtu;
+    chan_info->peer_coc_mtu = chan->coc_tx.mtu;
+#endif
+
+    return 0;
+}
+
+int
+ble_l2cap_enhanced_connect(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[],
+                               ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    return ble_l2cap_sig_ecoc_connect(conn_handle, psm, mtu,
+                                      num, sdu_rx, cb, cb_arg);
+}
+
+int
+ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu)
+{
+    int i;
+    uint16_t conn_handle;
+
+    if (num == 0 || !chans) {
+        return BLE_HS_EINVAL;
+    }
+
+    conn_handle = chans[0]->conn_handle;
+
+    for (i = 1; i < num; i++) {
+        if (conn_handle != chans[i]->conn_handle) {
+            return BLE_HS_EINVAL;
 
 Review comment:
   Error log here?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385103458
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,31 +643,456 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
+    bool some_not_connected = false;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (!chan || !chan->cb) {
+            continue;
+        }
+
+        if ((status == 0) && (chan->dcid != 0)) {
+            ble_l2cap_event_coc_connected(chan, status);
+            /* Let's forget about connected channel now.
+             * Not connected will be freed later on.
+             */
+            proc->connect.chan[i] = NULL;
+            continue;
+        }
+        some_not_connected = true;
+        ble_l2cap_event_coc_connected(chan, status ? status : BLE_HS_EREJECT);
+    }
+
+    if (!some_not_connected) {
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    /* Free not connected channels*/
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(chan->conn_handle);
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (chan) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.
+             */
+            chan->cb = NULL;
+            ble_l2cap_chan_free(conn, chan);
+        }
+    }
+    ble_hs_unlock();
+}
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_reconfig_req *req;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
 
 Review comment:
   Typos: `bufor`, `is`, `.`

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382995482
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1308,165 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+int
+ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                           uint8_t num, struct os_mbuf *sdu_rx[num],
+                           ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                /* Clear callback to make sure "Disconnected event" to the user */
+                chan[j].cb = NULL;
+                ble_l2cap_chan_free(conn, proc->connect.chan[j]);
+            }
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+        proc->connect.chan[i] = chan;
+    }
+    proc->connect.cids_cnt = num;
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_CONNECT;
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ, proc->id,
+                                sizeof(*req) + num * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    req->psm = htole16(psm);
+    req->mtu = htole16(chan->coc_rx.mtu);
+    req->mps = htole16(chan->my_mtu);
+    req->credits = htole16(chan->coc_rx.credits);
+    for (i = 0; i < num; i++) {
+        req->scids[i] = htole16(proc->connect.chan[i]->scid);
+    }
+
+    ble_hs_unlock();
+
+    rc = ble_l2cap_sig_tx(proc->conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
 
 Review comment:
   this does not seem to be correct (and it's also used in other APIs).
   if this function is called from non-host task then it's possible that connection gets disconnected in the meantime and we should not assert.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375404384
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,30 +640,391 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+        if (!chan || !chan->cb) {
+            return;
+        }
+
+        ble_l2cap_event_coc_connected(chan, status);
+
+        if (status) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.*/
+            chan->cb = NULL;
+            ble_hs_lock();
+            conn = ble_hs_conn_find(chan->conn_handle);
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+        }
+        chan = proc->connect.chan[++i];
+    };
+}
+
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_config_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_CIDS_IN_PACKET);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+        ble_hs_unlock();
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+        ble_hs_lock();
+    }
+
+    ble_hs_unlock();
+
+}
+static int
+ble_l2cap_sig_credit_base_config_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_config_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    int i;
+    int j;
+    uint8_t num_of_scids;
+    uint16_t scid;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, hdr->length , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    memset(rsp, 0, sizeof(*rsp));
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if (req->mtu < 64) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+            rsp->result = htole16(coc_err);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_mtu = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            for (j = 0; j < i; j++) {
+                ble_hs_conn_delete_chan(conn, chans[j]);
+            }
+            ble_hs_unlock();
+            rsp->result = htole16(coc_err);
+            goto failed;
+        }
+        rsp->dcids[i] = htole16(chans[i]->scid);
 
-    if (status) {
-        /* Normally in channel free we send disconnected event to application.
-         * However in case on error during creation connection we send connected
-         * event with error status. To avoid additional disconnected event lets
-         * clear callbacks since we don't needed it anymore.*/
-        chan->cb = NULL;
         ble_hs_lock();
-        conn = ble_hs_conn_find(chan->conn_handle);
-        ble_l2cap_chan_free(conn, chan);
+        conn = ble_hs_conn_find_assert(conn_handle);
+
+    }
+    ble_hs_unlock();
+
+    /* Same initial parameters for all the channels */
+    rsp->credits = htole16(chans[0]->coc_rx.credits);
+    rsp->mps = htole16(chans[0]->my_mtu);
+    rsp->mtu = htole16(chans[0]->coc_rx.mtu);
+    rsp->result = htole16(BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS);
+
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        for (i = 0; i < num_of_scids; i++) {
+            ble_hs_conn_delete_chan(conn, chans[i]);
+        }
         ble_hs_unlock();
+        return 0;
+    }
+
+    /* Notify user about connection status */
+    for (i = 0; i < num_of_scids; i++) {
+        ble_l2cap_event_coc_connected(chans[i], rc);
+    }
+
+    return 0;
+
+failed:
+    memset(rsp->dcids, 0, num_of_scids * sizeof(uint16_t));
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+    int i;
+
+#if !BLE_MONITOR
+    BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n");
+#endif
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_CONNECT,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
     }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_connect_rsp *)(*om)->om_data;
+
+    if (rsp->result) {
+        rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
+        goto done;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    assert(conn != NULL);
+
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+
+        /* Fill up remote configuration
+         * Note MPS is the L2CAP MTU
+         */
+        chan->peer_mtu = le16toh(rsp->mps);
+        chan->dcid = le16toh(rsp->dcids[i]);
+        chan->coc_tx.mtu = le16toh(rsp->mtu);
+        chan->coc_tx.credits = le16toh(rsp->credits);
+
+        ble_hs_conn_chan_insert(conn, chan);
+
+        chan = proc->connect.chan[++i];
+    } while (chan);
 
 Review comment:
   Unnecessary while.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375386729
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2253,10 +2280,42 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
 
         case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
             btshell_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+            return 0;
+        case BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED:
+
+            if (ble_l2cap_get_chan_info(event->reconfigured.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE CoC reconfigure completed status %0x02x," \
 
 Review comment:
   %0x02x -> 0x%02x

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382996667
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
 
 Review comment:
   perhaps this is correct (comparing MTU with MPS), but in such case field names in chan struct are really confusing

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375266374
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -70,12 +74,21 @@ struct ble_hs_conn;
 #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_COC_ERR_INVALID_PARAMETERS        0x000C
+
+#define BLE_L2CAP_ERR_RECONFIG_SUCCEED                       0x0000
+#define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED     0x0001
+#define BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED     0x0002
+#define BLE_L2CAP_ERR_RECONFIG_INVALID_DCID                  0x0003
+#define BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM              0x0004
 
 #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
 #define BLE_L2CAP_EVENT_COC_TX_UNSTALLED              4
+#define BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED     5
+#define BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED         6
 
 Review comment:
   you should use either reconfig or reconfigure - I do not care which one, but should be consistent everywhere.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384461324
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
 
 Review comment:
   improved so now it should be more clear what mps means.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#issuecomment-583040842
 
 
   There should be a restriction that this feature should be enabled only when BLE_VERSION: 52 is enabled. 
   Moreover if you do not set it, we will crash because of bad memory access. ble_l2cap_sig_dispatch_get() is checking the wrong max value for opcode.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377063252
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1261,170 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+int
+ble_l2cap_sig_coc_connect_multiple(uint16_t conn_handle,
+                                   uint16_t psm, uint16_t mtu,
+                                   uint8_t num, struct os_mbuf *sdu_rx[num],
+                                   ble_l2cap_event_fn *cb, void *cb_arg)
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                chan[j].cb = NULL;
+                ble_l2cap_chan_free(conn, proc->connect.chan[j]);
+            }
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+        proc->connect.chan[i] = chan;
+    }
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_CONNECT;
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ, proc->id,
+                                sizeof(*req) + num * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    req->psm = htole16(psm);
+    req->mtu = htole16(chan->coc_rx.mtu);
+    req->mps = htole16(chan->my_mtu);
+    req->credits = htole16(chan->coc_rx.credits);
+    for (i = 0; i < num; i++) {
+        req->scids[i] = htole16(proc->connect.chan[i]->scid);
+    }
+
+    ble_hs_unlock();
+
+    rc = ble_l2cap_sig_tx(proc->conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+    }
+
+done:
+    ble_l2cap_sig_process_status(proc, rc);
+
+    return rc;
+#else
+    return BLE_HS_ENOTSUP;
+#endif
+}
+
+int
+ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, uint16_t new_mtu,
+                           uint8_t cnt, struct ble_l2cap_chan *chans[])
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    int rc;
+    int i;
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+    if (!proc) {
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    for (i = 0; i < cnt; i++) {
+        if (ble_hs_conn_chan_exist(conn, chans[i])) {
+            proc->reconfig.cids[i] = chans[i]->dcid;
 
 Review comment:
   you are right, thx

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375388111
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,30 +640,391 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+        if (!chan || !chan->cb) {
+            return;
+        }
+
+        ble_l2cap_event_coc_connected(chan, status);
+
+        if (status) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.*/
+            chan->cb = NULL;
+            ble_hs_lock();
+            conn = ble_hs_conn_find(chan->conn_handle);
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+        }
+        chan = proc->connect.chan[++i];
+    };
+}
+
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_config_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_CIDS_IN_PACKET);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, proc->reconfig.cids[i]);
 
 Review comment:
   find_by_scid

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r388928497
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2334,6 +2373,43 @@ btshell_l2cap_disconnect(uint16_t conn_handle, uint16_t idx)
 #endif
 }
 
+int
+btshell_l2cap_reconfig(uint16_t conn_handle, uint16_t mtu,
+                       uint8_t num, uint8_t idxs[])
+{
+    struct btshell_conn *conn;
+    struct btshell_l2cap_coc *coc;
+    struct ble_l2cap_chan * chans[5] = {0};
+    int i, j;
+    int cnt;
+
+    conn = btshell_conn_find(conn_handle);
+    if (conn == NULL) {
+        console_printf("conn=%d does not exist\n", conn_handle);
+        return 0;
+    }
+
+    i = 0;
+    j = 0;
+    cnt = 0;
+    SLIST_FOREACH(coc, &conn->coc_list, next) {
+        for (i = 0; i < num; i++) {
+            if (idxs[i] == j) {
+                chans[cnt] = coc->chan;
+                cnt++;
+                break;
+            }
+        }
+        j++;
+    }
+
+    if (cnt != num) {
+        console_printf("Missing coc? (%d!=%d)\n", num, cnt);
 
 Review comment:
   could be more descriptive :)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on issue #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#issuecomment-584128045
 
 
   @andrzej-kaczmarek @michal-narajowski  thanks for looking into it. PR updated.

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375423796
 
 

 ##########
 File path: apps/btshell/src/main.c
 ##########
 @@ -2253,10 +2280,42 @@ btshell_l2cap_event(struct ble_l2cap_event *event, void *arg)
 
         case BLE_L2CAP_EVENT_COC_DATA_RECEIVED:
             btshell_l2cap_coc_recv(event->receive.chan, event->receive.sdu_rx);
+            return 0;
+        case BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED:
+
+            if (ble_l2cap_get_chan_info(event->reconfigured.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE CoC reconfigure completed status %0x02x," \
+                            "chan: 0x%08lx\n",
+                            event->reconfigured.status,
+                            (uint32_t) event->reconfigured.chan);
+
+            if (event->reconfigured.status == 0) {
+                console_printf("\t our_mps: %d our_mtu %d\n", chan_info.our_mps, chan_info.our_mtu);
+            }
+            return 0;
+        case BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED:
+
+            if (ble_l2cap_get_chan_info(event->reconfigured.chan, &chan_info)) {
+                assert(0);
+            }
+
+            console_printf("LE CoC peer reconfigured status %0x02x," \
 
 Review comment:
   %0x02x -> 0x%02x

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385729565
 
 

 ##########
 File path: nimble/host/syscfg.yml
 ##########
 @@ -118,6 +118,13 @@ syscfg.defs:
             MSYS blocks.
         value: 'MYNEWT_VAL_MSYS_1_BLOCK_SIZE-8'
 
+    BLE_L2CAP_ENHANCED_COC:
 
 Review comment:
   good point

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375388388
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1261,170 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+int
+ble_l2cap_sig_coc_connect_multiple(uint16_t conn_handle,
+                                   uint16_t psm, uint16_t mtu,
+                                   uint8_t num, struct os_mbuf *sdu_rx[num],
+                                   ble_l2cap_event_fn *cb, void *cb_arg)
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+            return BLE_HS_ENOMEM;
+        }
+
+    for (i = 0; i < num; i++) {
+        chan = ble_l2cap_coc_chan_alloc(conn, psm, mtu, sdu_rx[i], cb, cb_arg);
+        if (!chan) {
+            for (j = 0; j < i; j++) {
+                chan[j].cb = NULL;
+                ble_l2cap_chan_free(conn, proc->connect.chan[j]);
+            }
+            ble_hs_unlock();
+            rc = BLE_HS_ENOMEM;
+            goto done;
+        }
+        proc->connect.chan[i] = chan;
+    }
+
+    proc->op = BLE_L2CAP_SIG_PROC_OP_CONNECT;
+    proc->id = ble_l2cap_sig_next_id();
+    proc->conn_handle = conn_handle;
+
+    req = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_REQ, proc->id,
+                                sizeof(*req) + num * sizeof(uint16_t), &txom);
+    if (!req) {
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    req->psm = htole16(psm);
+    req->mtu = htole16(chan->coc_rx.mtu);
+    req->mps = htole16(chan->my_mtu);
+    req->credits = htole16(chan->coc_rx.credits);
+    for (i = 0; i < num; i++) {
+        req->scids[i] = htole16(proc->connect.chan[i]->scid);
+    }
+
+    ble_hs_unlock();
+
+    rc = ble_l2cap_sig_tx(proc->conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        ble_l2cap_chan_free(conn, chan);
+        ble_hs_unlock();
+    }
+
+done:
+    ble_l2cap_sig_process_status(proc, rc);
+
+    return rc;
+#else
+    return BLE_HS_ENOTSUP;
+#endif
+}
+
+int
+ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, uint16_t new_mtu,
+                           uint8_t cnt, struct ble_l2cap_chan *chans[])
+{
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    int rc;
+    int i;
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+    if (!proc) {
+        ble_hs_unlock();
+        return BLE_HS_ENOMEM;
+    }
+
+    for (i = 0; i < cnt; i++) {
+        if (ble_hs_conn_chan_exist(conn, chans[i])) {
+            proc->reconfig.cids[i] = chans[i]->dcid;
 
 Review comment:
   chans[i]->scid;

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385106852
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,31 +643,456 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
+    bool some_not_connected = false;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (!chan || !chan->cb) {
+            continue;
+        }
+
+        if ((status == 0) && (chan->dcid != 0)) {
+            ble_l2cap_event_coc_connected(chan, status);
+            /* Let's forget about connected channel now.
+             * Not connected will be freed later on.
+             */
+            proc->connect.chan[i] = NULL;
+            continue;
+        }
+        some_not_connected = true;
+        ble_l2cap_event_coc_connected(chan, status ? status : BLE_HS_EREJECT);
+    }
+
+    if (!some_not_connected) {
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    /* Free not connected channels*/
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(chan->conn_handle);
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (chan) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.
+             */
+            chan->cb = NULL;
+            ble_l2cap_chan_free(conn, chan);
+        }
+    }
+    ble_hs_unlock();
+}
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_reconfig_req *req;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        ble_hs_unlock();
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_reconfig_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (cid_cnt > BLE_L2CAP_MAX_COC_CONN_REQ) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_coc_mps > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_coc_mps = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+    }
+
+    ble_hs_unlock();
+
+    for (i = 0; i < proc->reconfig.cid_cnt; i++) {
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+    }
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    ble_hs_lock();
+
+    memset(rsp, 0, len);
+
+    /* Initial dummy values in case of error, just to satisfy PTS */
+    rsp->credits = htole16(1);
+    rsp->mps = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+    rsp->mtu = htole16(BLE_L2CAP_ECOC_MIN_MTU);
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if ((req->mtu < BLE_L2CAP_ECOC_MIN_MTU) || (req->mps < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    /* First verify that provided SCIDs are good */
+    for (i = 0; i < num_of_scids; i++) {
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            goto failed;
+        }
+    }
+
+    /* Let us try to connect channels */
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            continue;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            if (i == 0) {
+                /* In case it is very first channel we cannot create it means PSM is incorrect
+                 * or we are out of resources. Just send a response now.
+                 */
+                rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+                goto failed;
+            } else {
+                /* We cannot create number of channels req by peer due to limited resources. */
+                rsp->result = htole16(BLE_L2CAP_COC_ERR_NO_RESOURCES);
+                goto done;
+            }
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_coc_mps = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        /* Sending event to the app. Unlock hs */
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc == 0) {
+            rsp->dcids[i] = htole16(chans[i]->scid);
+            chan_created++;
+            if (chan_created == 1) {
+                /* We need to set it once as there are same initial parameters
+                 * for all the channels
+                 */
+                rsp->credits = htole16(chans[i]->coc_rx.credits);
+                rsp->mps = htole16(chans[i]->my_mtu);
+                rsp->mtu = htole16(chans[i]->coc_rx.mtu);
+            }
+        } else {
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            ble_hs_conn_delete_chan(conn, chans[i]);
+            chans[i] = NULL;
+            rsp->result = htole16(ble_l2cap_sig_ble_hs_err2coc_err(rc));
+            rc = 0;
+            ble_hs_unlock();
+        }
 
-    if (status) {
-        /* Normally in channel free we send disconnected event to application.
-         * However in case on error during creation connection we send connected
-         * event with error status. To avoid additional disconnected event lets
-         * clear callbacks since we don't needed it anymore.*/
-        chan->cb = NULL;
         ble_hs_lock();
-        conn = ble_hs_conn_find(chan->conn_handle);
-        ble_l2cap_chan_free(conn, chan);
+        conn = ble_hs_conn_find_assert(conn_handle);
+    }
+
+done:
+    ble_hs_unlock();
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        for (i = 0; i < num_of_scids; i++) {
+            if (chans[i]) {
+                ble_hs_conn_delete_chan(conn, chans[i]);
+            }
+        }
         ble_hs_unlock();
+        return 0;
+    }
+
+    /* Notify user about connection status */
+    for (i = 0; i < num_of_scids; i++) {
+        if (chans[i]) {
+            ble_l2cap_event_coc_connected(chans[i], rc);
+        }
     }
+
+    return 0;
+
+failed:
+    ble_hs_unlock();
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
 }
 
+static int
+ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+    int i;
+
+#if !BLE_MONITOR
+    BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n");
+#endif
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_CONNECT,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_connect_rsp *)(*om)->om_data;
+
+    if (rsp->result) {
+        rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
+        goto done;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    assert(conn != NULL);
+
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (rsp->dcids[i] == 0) {
+            /* Channel rejected, dont put it on the list.
+             * User will get notified later in that function
+             */
+            chan->dcid = 0;
+            continue;
+        }
+        chan->peer_coc_mps = le16toh(rsp->mps);
+        chan->dcid = le16toh(rsp->dcids[i]);
+        chan->coc_tx.mtu = le16toh(rsp->mtu);
+        chan->coc_tx.credits = le16toh(rsp->credits);
+
+        ble_hs_conn_chan_insert(conn, chan);
+    }
+
+    ble_hs_unlock();
+
+done:
+    ble_l2cap_sig_coc_connect_cb(proc, rc);
+    ble_l2cap_sig_proc_free(proc);
+
+    /* Silently ignore errors as this is response signal */
 
 Review comment:
   Error log here?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385099331
 
 

 ##########
 File path: nimble/host/src/ble_l2cap.c
 ##########
 @@ -155,7 +155,61 @@ ble_l2cap_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg);
 }
 
-int ble_l2cap_disconnect(struct ble_l2cap_chan *chan)
+int
+ble_l2cap_get_chan_info(struct ble_l2cap_chan *chan, struct ble_l2cap_chan_info *chan_info)
+{
+    if (!chan || !chan_info) {
+        return BLE_HS_EINVAL;
+    }
+
+    memset(chan_info, 0, sizeof(*chan_info));
+    chan_info->dcid = chan->dcid;
+    chan_info->scid = chan->scid;
+    chan_info->our_l2cap_mtu = chan->my_mtu;
+    chan_info->peer_l2cap_mtu = chan->peer_mtu;
+
+#if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM)
+    chan_info->psm = chan->psm;
+    chan_info->our_coc_mtu = chan->coc_rx.mtu;
+    chan_info->peer_coc_mtu = chan->coc_tx.mtu;
+#endif
+
+    return 0;
+}
+
+int
+ble_l2cap_enhanced_connect(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[],
+                               ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    return ble_l2cap_sig_ecoc_connect(conn_handle, psm, mtu,
+                                      num, sdu_rx, cb, cb_arg);
+}
+
+int
+ble_l2cap_reconfig(struct ble_l2cap_chan *chans[], uint8_t num, uint16_t new_mtu)
+{
+    int i;
+    uint16_t conn_handle;
+
+    if (num == 0 || !chans) {
+        return BLE_HS_EINVAL;
 
 Review comment:
   Error log here?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375270116
 
 

 ##########
 File path: nimble/host/include/host/ble_l2cap.h
 ##########
 @@ -219,11 +254,16 @@ int ble_l2cap_create_server(uint16_t psm, uint16_t mtu,
 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_connect_multiple(uint16_t conn_handle,
+                               uint16_t psm, uint16_t mtu,
+                               uint8_t num, struct os_mbuf *sdu_rx[num],
 
 Review comment:
   array size is redundant in declaration

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377687904
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +672,382 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
 
 Review comment:
   would it make sense to put unlock under done label?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384013357
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +672,382 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
 
 Review comment:
   thanks for catching that

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382995141
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1308,165 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+int
+ble_l2cap_sig_ecoc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
+                           uint8_t num, struct os_mbuf *sdu_rx[num],
+                           ble_l2cap_event_fn *cb, void *cb_arg)
+{
+    struct ble_hs_conn *conn;
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_chan *chan = NULL;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    int rc;
+    int i;
+    int j;
+
+    if (!sdu_rx || !cb) {
+        return BLE_HS_EINVAL;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+
+    if (!conn) {
+        ble_hs_unlock();
+        return BLE_HS_ENOTCONN;
+    }
+
+    proc = ble_l2cap_sig_proc_alloc();
+        if (!proc) {
 
 Review comment:
   indentation

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375404384
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,30 +640,391 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+        if (!chan || !chan->cb) {
+            return;
+        }
+
+        ble_l2cap_event_coc_connected(chan, status);
+
+        if (status) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.*/
+            chan->cb = NULL;
+            ble_hs_lock();
+            conn = ble_hs_conn_find(chan->conn_handle);
+            ble_l2cap_chan_free(conn, chan);
+            ble_hs_unlock();
+        }
+        chan = proc->connect.chan[++i];
+    };
+}
+
+#if MYNEWT_VAL(BLE_VERSION) >= 52
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIGURE_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_config_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_CIDS_IN_PACKET);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_mtu = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_CIDS_IN_PACKET] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    for (i = 0; i< proc->reconfig.cids_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+        ble_hs_unlock();
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+        ble_hs_lock();
+    }
+
+    ble_hs_unlock();
+
+}
+static int
+ble_l2cap_sig_credit_base_config_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_config_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    int i;
+    int j;
+    uint8_t num_of_scids;
+    uint16_t scid;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, hdr->length , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
+        return 0;
+    }
+
+    memset(rsp, 0, sizeof(*rsp));
+
+    req = (struct ble_l2cap_sig_credit_base_connect_req *)(*om)->om_data;
+
+    num_of_scids = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (num_of_scids > 5) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    if (req->mtu < 64) {
+        rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_PARAMETERS);
+        goto failed;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find_assert(conn_handle);
+
+    for (i = 0; i < num_of_scids; i++) {
+        /* Verify CID. Note, scid in the request is dcid for out local channel */
+        scid = le16toh(req->scids[i]);
+        if (scid < BLE_L2CAP_COC_CID_START || scid > BLE_L2CAP_COC_CID_END) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        chans[i] = ble_hs_conn_chan_find_by_dcid(conn, scid);
+        if (chans[i]) {
+            rsp->result = htole16(BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        rc = ble_l2cap_coc_create_srv_chan(conn, le16toh(req->psm), &chans[i]);
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+            rsp->result = htole16(coc_err);
+            ble_hs_unlock();
+            goto failed;
+        }
+
+        /* Fill up remote configuration. Note MPS is the L2CAP MTU*/
+        chans[i]->dcid = scid;
+        chans[i]->peer_mtu = le16toh(req->mps);
+        chans[i]->coc_tx.credits = le16toh(req->credits);
+        chans[i]->coc_tx.mtu = le16toh(req->mtu);
+
+        ble_hs_conn_chan_insert(conn, chans[i]);
+        ble_hs_unlock();
+
+        rc = ble_l2cap_event_coc_accept(chans[i], le16toh(req->mtu));
+        if (rc != 0) {
+            uint16_t coc_err = ble_l2cap_sig_ble_hs_err2coc_err(rc);
+
+            /* Make sure we do not send disconnect event when removing channel */
+            chans[i]->cb = NULL;
+
+            ble_hs_lock();
+            conn = ble_hs_conn_find_assert(conn_handle);
+            for (j = 0; j < i; j++) {
+                ble_hs_conn_delete_chan(conn, chans[j]);
+            }
+            ble_hs_unlock();
+            rsp->result = htole16(coc_err);
+            goto failed;
+        }
+        rsp->dcids[i] = htole16(chans[i]->scid);
 
-    if (status) {
-        /* Normally in channel free we send disconnected event to application.
-         * However in case on error during creation connection we send connected
-         * event with error status. To avoid additional disconnected event lets
-         * clear callbacks since we don't needed it anymore.*/
-        chan->cb = NULL;
         ble_hs_lock();
-        conn = ble_hs_conn_find(chan->conn_handle);
-        ble_l2cap_chan_free(conn, chan);
+        conn = ble_hs_conn_find_assert(conn_handle);
+
+    }
+    ble_hs_unlock();
+
+    /* Same initial parameters for all the channels */
+    rsp->credits = htole16(chans[0]->coc_rx.credits);
+    rsp->mps = htole16(chans[0]->my_mtu);
+    rsp->mtu = htole16(chans[0]->coc_rx.mtu);
+    rsp->result = htole16(BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS);
+
+    rc = ble_l2cap_sig_tx(conn_handle, txom);
+    if (rc != 0) {
+        ble_hs_lock();
+        conn = ble_hs_conn_find_assert(conn_handle);
+        for (i = 0; i < num_of_scids; i++) {
+            ble_hs_conn_delete_chan(conn, chans[i]);
+        }
         ble_hs_unlock();
+        return 0;
+    }
+
+    /* Notify user about connection status */
+    for (i = 0; i < num_of_scids; i++) {
+        ble_l2cap_event_coc_connected(chans[i], rc);
+    }
+
+    return 0;
+
+failed:
+    memset(rsp->dcids, 0, num_of_scids * sizeof(uint16_t));
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chan;
+    struct ble_hs_conn *conn;
+    int rc;
+    int i;
+
+#if !BLE_MONITOR
+    BLE_HS_LOG(DEBUG, "L2CAP LE COC connection response received\n");
+#endif
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_CONNECT,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
     }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_connect_rsp *)(*om)->om_data;
+
+    if (rsp->result) {
+        rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result));
+        goto done;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    assert(conn != NULL);
+
+    i = 0;
+    chan = proc->connect.chan[i];
+    while (chan) {
+
+        /* Fill up remote configuration
+         * Note MPS is the L2CAP MTU
+         */
+        chan->peer_mtu = le16toh(rsp->mps);
+        chan->dcid = le16toh(rsp->dcids[i]);
+        chan->coc_tx.mtu = le16toh(rsp->mtu);
+        chan->coc_tx.credits = le16toh(rsp->credits);
+
+        ble_hs_conn_chan_insert(conn, chan);
+
+        chan = proc->connect.chan[++i];
+    } while (chan);
 
 Review comment:
   Unnecessary while? 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r384461378
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
 
 Review comment:
   fixed

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r375263111
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig_priv.h
 ##########
 @@ -103,13 +129,24 @@ void *ble_l2cap_sig_cmd_get(uint8_t opcode, uint8_t id, uint16_t len,
 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_coc_connect_multiple(uint16_t conn_handle,
+                                   uint16_t psm, uint16_t mtu,
+                                   uint8_t num, struct os_mbuf *sdu_rx[num],
+                                   ble_l2cap_event_fn *cb, void *cb_arg);
 int ble_l2cap_sig_disconnect(struct ble_l2cap_chan *chan);
 int ble_l2cap_sig_le_credits(uint16_t conn_handle, uint16_t scid,
                              uint16_t credits);
+int ble_l2cap_sig_coc_reconfig(uint16_t conn_handle, uint16_t new_mtu,
+                               uint8_t cnt, struct ble_l2cap_chan *chans[]);
 #else
 #define ble_l2cap_sig_coc_connect(conn_handle, psm, mtu, sdu_rx, cb, cb_arg) \
                                                                 BLE_HS_ENOTSUP
+
+#define ble_l2cap_sig_coc_connect_multiple(conn_handle, psm, mtu, num, sdu_rx, \
+                                           cb, cb_arg) BLE_HS_ENOTSUP
+
 #define ble_l2cap_sig_disconnect(chan)                          BLE_HS_ENOTSUP
+#define ble_l2cap_sig_coc_reconfig(conn_handle, new_mtu, cnt, chans) BLE_HS_ENOTSUP
 
 Review comment:
   `BLE_VERSION` ifdef is done in a different way, we should be consistent. I do not like the one above, so either do as for `BLE_VERSION` or use `static inline` to simply return `BLE_HS_ENOTSUP`

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
sjanc commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377681776
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig_priv.h
 ##########
 @@ -74,6 +74,32 @@ struct ble_l2cap_sig_le_con_rsp {
     uint16_t result;
 } __attribute__((packed));
 
+struct ble_l2cap_sig_credit_base_connect_req {
+    uint16_t psm;
+    uint16_t mtu;
+    uint16_t mps;
+    uint16_t credits;
+    uint16_t scids[0];
+} __attribute__((packed));
+
+struct ble_l2cap_sig_credit_base_connect_rsp {
+    uint16_t mtu;
+    uint16_t mps;
+    uint16_t credits;
+    uint16_t result;
+    uint16_t dcids[0];
+} __attribute__((packed));
+
+struct ble_l2cap_sig_credit_base_config_req {
 
 Review comment:
   _reconfig

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] rymanluk merged pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
rymanluk merged pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744
 
 
   

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
andrzej-kaczmarek commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r382996199
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -634,6 +674,405 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
     }
 }
 
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_config_req *req;
+    struct ble_l2cap_sig_credit_base_config_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_config_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    assert(cid_cnt <= BLE_L2CAP_MAX_COC_CONN_REQ);
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_mtu > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
 
 Review comment:
   this condition always evaluates to true

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: [WIP] Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r377579945
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -869,6 +1267,164 @@ ble_l2cap_sig_coc_connect(uint16_t conn_handle, uint16_t psm, uint16_t mtu,
     return rc;
 }
 
+int
+ble_l2cap_sig_coc_connect_multiple(uint16_t conn_handle,
 
 Review comment:
   Maybe this should be named ble_l2cap_sig_coc_enhanced_connect()? I think this would be more clear as connect multiple could mean creating multiple legacy channels. And you can still use this API to create only one channel, so... :) 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services

[GitHub] [mynewt-nimble] michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2

Posted by GitBox <gi...@apache.org>.
michal-narajowski commented on a change in pull request #744: Add support for Enhanced LE CoC as per BT 5.2 
URL: https://github.com/apache/mynewt-nimble/pull/744#discussion_r385104347
 
 

 ##########
 File path: nimble/host/src/ble_l2cap_sig.c
 ##########
 @@ -609,31 +643,456 @@ ble_l2cap_sig_coc_connect_cb(struct ble_l2cap_sig_proc *proc, int status)
 {
     struct ble_hs_conn *conn;
     struct ble_l2cap_chan *chan;
+    int i;
+    bool some_not_connected = false;
 
     if (!proc) {
             return;
     }
 
-    chan = proc->connect.chan;
-    if (!chan || !chan->cb) {
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (!chan || !chan->cb) {
+            continue;
+        }
+
+        if ((status == 0) && (chan->dcid != 0)) {
+            ble_l2cap_event_coc_connected(chan, status);
+            /* Let's forget about connected channel now.
+             * Not connected will be freed later on.
+             */
+            proc->connect.chan[i] = NULL;
+            continue;
+        }
+        some_not_connected = true;
+        ble_l2cap_event_coc_connected(chan, status ? status : BLE_HS_EREJECT);
+    }
+
+    if (!some_not_connected) {
         return;
     }
 
-    ble_l2cap_event_coc_connected(chan, status);
+    /* Free not connected channels*/
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(chan->conn_handle);
+    for (i = 0; i < proc->connect.chan_cnt; i++) {
+        chan = proc->connect.chan[i];
+        if (chan) {
+            /* Normally in channel free we send disconnected event to application.
+             * However in case on error during creation connection we send connected
+             * event with error status. To avoid additional disconnected event lets
+             * clear callbacks since we don't needed it anymore.
+             */
+            chan->cb = NULL;
+            ble_l2cap_chan_free(conn, chan);
+        }
+    }
+    ble_hs_unlock();
+}
+
+#if MYNEWT_VAL(BLE_L2CAP_ENHANCED_COC)
+static void
+ble_l2cap_event_coc_reconfigured(uint16_t conn_handle, uint16_t status,
+                                 struct ble_l2cap_chan *chan, bool peer)
+{
+    struct ble_l2cap_event event = { };
+
+    if (peer) {
+        event.type = BLE_L2CAP_EVENT_COC_PEER_RECONFIGURED;
+    } else {
+        event.type = BLE_L2CAP_EVENT_COC_RECONFIG_COMPLETED;
+    }
+    event.reconfigured.conn_handle = conn_handle;
+    event.reconfigured.chan = chan;
+    event.reconfigured.status = status;
+
+    chan->cb(&event, chan->cb_arg);
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_l2cap_sig_credit_base_reconfig_req *req;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    struct ble_hs_conn *conn;
+    struct os_mbuf *txom;
+    int i;
+    int rc;
+    uint8_t cid_cnt;
+    uint8_t reduction_mps = 0;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    ble_hs_lock();
+    conn = ble_hs_conn_find(conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return 0;
+    }
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_RECONFIG_RSP,
+                                    hdr->identifier, sizeof(*rsp) , &txom);
+    if (!rsp) {
+        /* TODO: Reuse req bufor for the response. For now is such a case.
+         * remote will timeout.
+         */
+        ble_hs_unlock();
+        return 0;
+    }
+
+    if (hdr->length <= sizeof(*req)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    req = (struct ble_l2cap_sig_credit_base_reconfig_req *)(*om)->om_data;
+
+    if ((req->mps < BLE_L2CAP_ECOC_MIN_MTU) || (req->mtu < BLE_L2CAP_ECOC_MIN_MTU)) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    /* Assume request will succeed. If not, result will be updated */
+    rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_SUCCEED);
+
+    cid_cnt = (hdr->length - sizeof(*req)) / sizeof(uint16_t);
+    if (cid_cnt > BLE_L2CAP_MAX_COC_CONN_REQ) {
+        rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_UNACCAPTED_PARAM);
+        goto done;
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_dcid(conn, req->dcids[i]);
+        if (!chan[i]) {
+             rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_INVALID_DCID);
+             ble_hs_unlock();
+             goto done;
+        }
+
+        if (chan[i]->peer_coc_mps > req->mps) {
+            reduction_mps++;
+            if (reduction_mps > 1) {
+                rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MPS_NOT_ALLOWED);
+                ble_hs_unlock();
+                goto done;
+            }
+        }
+
+        if (chan[i]->coc_tx.mtu > req->mtu) {
+            rsp->result = htole16(BLE_L2CAP_ERR_RECONFIG_REDUCTION_MTU_NOT_ALLOWED);
+            ble_hs_unlock();
+            goto done;
+        }
+    }
+
+    for (i = 0; i < cid_cnt; i++) {
+        chan[i]->coc_tx.mtu = req->mtu;
+        chan[i]->peer_coc_mps = req->mps;
+        ble_l2cap_event_coc_reconfigured(conn_handle, 0, chan[i], true);
+    }
+
+    ble_hs_unlock();
+done:
+    ble_l2cap_sig_tx(conn_handle, txom);
+    return 0;
+}
+
+static void
+ble_l2cap_sig_coc_reconfig_cb(struct ble_l2cap_sig_proc *proc, int status)
+{
+    int i;
+    struct ble_l2cap_chan *chan[BLE_L2CAP_MAX_COC_CONN_REQ] = {0};
+    struct ble_hs_conn *conn;
+
+    ble_hs_lock();
+
+    conn = ble_hs_conn_find(proc->conn_handle);
+    if (!conn) {
+        ble_hs_unlock();
+        return;
+    }
+
+    for (i = 0; i< proc->reconfig.cid_cnt; i++) {
+        chan[i] = ble_hs_conn_chan_find_by_scid(conn, proc->reconfig.cids[i]);
+        if (status == 0) {
+            ble_l2cap_coc_set_new_mtu_mps(chan[i], proc->reconfig.new_mtu, proc->reconfig.new_mps);
+        }
+    }
+
+    ble_hs_unlock();
+
+    for (i = 0; i < proc->reconfig.cid_cnt; i++) {
+        ble_l2cap_event_coc_reconfigured(proc->conn_handle, status, chan[i], false);
+    }
+}
+
+static int
+ble_l2cap_sig_credit_base_reconfig_rsp_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    struct ble_l2cap_sig_proc *proc;
+    struct ble_l2cap_sig_credit_base_reconfig_rsp *rsp;
+    int rc;
+
+    proc = ble_l2cap_sig_proc_extract(conn_handle,
+                                      BLE_L2CAP_SIG_PROC_OP_RECONFIG,
+                                      hdr->identifier);
+    if (!proc) {
+        return 0;
+    }
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rsp = (struct ble_l2cap_sig_credit_base_reconfig_rsp *)(*om)->om_data;
+    ble_l2cap_sig_coc_reconfig_cb(proc, (rsp->result > 0) ? BLE_HS_EREJECT : 0);
+
+    return 0;
+}
+
+static int
+ble_l2cap_sig_credit_base_con_req_rx(uint16_t conn_handle,
+                                     struct ble_l2cap_sig_hdr *hdr,
+                                     struct os_mbuf **om)
+{
+    int rc;
+    struct ble_l2cap_sig_credit_base_connect_req *req;
+    struct os_mbuf *txom;
+    struct ble_l2cap_sig_credit_base_connect_rsp *rsp;
+    struct ble_l2cap_chan *chans[5] = { 0 };
+    struct ble_hs_conn *conn;
+    uint16_t scid;
+    uint8_t num_of_scids;
+    uint8_t chan_created = 0;
+    int i;
+    uint8_t len;
+
+    rc = ble_hs_mbuf_pullup_base(om, hdr->length);
+    if (rc != 0) {
+        return rc;
+    }
+
+    len = (hdr->length > sizeof(*req)) ? hdr->length : sizeof(*req);
+
+    rsp = ble_l2cap_sig_cmd_get(BLE_L2CAP_SIG_OP_CREDIT_CONNECT_RSP,
+                                hdr->identifier, len , &txom);
+    if (!rsp) {
+        /* Well, nothing smart we can do if there is no memory for response.
+         * Remote will timeout.
+         */
 
 Review comment:
   Error log here? :)

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services