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:
us...@infra.apache.org


With regards,
Apache Git Services

Reply via email to