From 0d3efa925095ca45816bd2554f50f7f84eac2bd4 Mon Sep 17 00:00:00 2001 From: Piotr Narajowski Date: Fri, 13 Mar 2026 14:57:41 +0100 Subject: [PATCH 1/2] nimble/l2cap: remove unnecessary error base conversion This removes ble_l2cap_sig_coc_err2ble_hs_err method and it's usages. There is no need to convert an L2CAP connection response result to Host error code. L2CAP coc conn unit tests are updated accordingly - expected app status has l2cap base now. --- nimble/host/src/ble_l2cap_sig.c | 33 ++------------------------- nimble/host/test/src/ble_l2cap_test.c | 12 +++++----- 2 files changed, 8 insertions(+), 37 deletions(-) diff --git a/nimble/host/src/ble_l2cap_sig.c b/nimble/host/src/ble_l2cap_sig.c index 2325909be1..ba69df64e1 100644 --- a/nimble/host/src/ble_l2cap_sig.c +++ b/nimble/host/src/ble_l2cap_sig.c @@ -646,35 +646,6 @@ ble_l2cap_sig_update(uint16_t conn_handle, struct ble_l2cap_sig_update_params *p #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 -static int -ble_l2cap_sig_coc_err2ble_hs_err(uint16_t l2cap_coc_err) -{ - switch (l2cap_coc_err) { - case BLE_L2CAP_COC_ERR_CONNECTION_SUCCESS: - return 0; - case BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM: - return BLE_HS_ENOTSUP; - case BLE_L2CAP_COC_ERR_NO_RESOURCES: - return BLE_HS_ENOMEM; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN: - return BLE_HS_EAUTHEN; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR: - return BLE_HS_EAUTHOR; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_KEY_SZ: - return BLE_HS_EENCRYPT_KEY_SZ; - case BLE_L2CAP_COC_ERR_INSUFFICIENT_ENC: - return BLE_HS_EENCRYPT; - case BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID: - return BLE_HS_EREJECT; - case BLE_L2CAP_COC_ERR_SOURCE_CID_ALREADY_USED: - return BLE_HS_EALREADY; - case BLE_L2CAP_COC_ERR_UNACCEPTABLE_PARAMETERS: - return BLE_HS_EINVAL; - default: - return BLE_HS_EUNKNOWN; - } -} - static int ble_l2cap_sig_ble_hs_err2coc_err(uint16_t ble_hs_err) { @@ -1153,7 +1124,7 @@ ble_l2cap_sig_credit_base_con_rsp_rx(uint16_t conn_handle, 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)); + rc = BLE_HS_L2C_ERR(le16toh(rsp->result)); /* Below results means that some of the channels has not been created * and we have to look closer into the response. * Any other results means that all the connections has been refused. @@ -1346,7 +1317,7 @@ ble_l2cap_sig_coc_rsp_rx(uint16_t conn_handle, struct ble_l2cap_sig_hdr *hdr, chan = proc->connect.chan[0]; if (rsp->result) { - rc = ble_l2cap_sig_coc_err2ble_hs_err(le16toh(rsp->result)); + rc = BLE_HS_L2C_ERR(le16toh(rsp->result)); goto done; } diff --git a/nimble/host/test/src/ble_l2cap_test.c b/nimble/host/test/src/ble_l2cap_test.c index 839ac430ab..d2eb662dc2 100644 --- a/nimble/host/test/src/ble_l2cap_test.c +++ b/nimble/host/test/src/ble_l2cap_test.c @@ -719,7 +719,7 @@ ble_l2cap_test_event(struct ble_l2cap_event *event, void *arg) ev->handled = 1; switch(event->type) { case BLE_L2CAP_EVENT_COC_CONNECTED: - assert(ev->app_status == event->connect.status); + assert(ev->app_status == (uint8_t)event->connect.status); t->chan[0] = event->connect.chan; return 0; case BLE_L2CAP_EVENT_COC_DISCONNECTED: @@ -1154,7 +1154,7 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_invalid_psm) t.expected_num_iters = 1; t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; - t.event[0].app_status = BLE_HS_ENOTSUP; + t.event[0].app_status = BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM; t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_UNKNOWN_LE_PSM; ble_l2cap_test_coc_connect(&t); @@ -1177,7 +1177,7 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_out_of_resource) t.expected_num_iters = 1; t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; - t.event[0].app_status = BLE_HS_ENOMEM; + t.event[0].app_status = BLE_L2CAP_COC_ERR_NO_RESOURCES; t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_NO_RESOURCES; ble_l2cap_test_coc_connect(&t); @@ -1199,7 +1199,7 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_invalid_cid) t.expected_num_of_ev = 1; t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; - t.event[0].app_status = BLE_HS_EREJECT; + t.event[0].app_status = BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID; t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INVALID_SOURCE_CID; ble_l2cap_test_coc_connect(&t); @@ -1220,7 +1220,7 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_insuff_authen) t.expected_num_of_ev = 1; t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; - t.event[0].app_status = BLE_HS_EAUTHEN; + t.event[0].app_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN; t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHEN; ble_l2cap_test_coc_connect(&t); @@ -1241,7 +1241,7 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_insuff_author) t.expected_num_of_ev = 1; t.event[0].type = BLE_L2CAP_EVENT_COC_CONNECTED; - t.event[0].app_status = BLE_HS_EAUTHOR; + t.event[0].app_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR; t.event[0].l2cap_status = BLE_L2CAP_COC_ERR_INSUFFICIENT_AUTHOR; ble_l2cap_test_coc_connect(&t); From 27a5379f1eaf5401ad8aa2210ea8d7779d20b0e6 Mon Sep 17 00:00:00 2001 From: Piotr Narajowski Date: Fri, 13 Mar 2026 15:04:42 +0100 Subject: [PATCH 2/2] apps/bttester: send disconnected event in case of l2cap conn req failure This change allows sending a BTP_L2CAP_EV_DISCONNECTED event containing an error code when L2CAP Connection request is rejected. Previously, no tester event was triggered in this scenario, which made it impossible to determine the reason for the connection failure. --- apps/bttester/src/btp_l2cap.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/bttester/src/btp_l2cap.c b/apps/bttester/src/btp_l2cap.c index e11c54de3c..6a7ff856b9 100644 --- a/apps/bttester/src/btp_l2cap.c +++ b/apps/bttester/src/btp_l2cap.c @@ -207,7 +207,7 @@ connected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, static void disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, - struct ble_l2cap_chan_info *chan_info, void *arg) + struct ble_l2cap_chan_info *chan_info, int status, void *arg) { struct btp_l2cap_disconnected_ev ev; struct ble_gap_conn_desc desc; @@ -215,9 +215,15 @@ disconnected_cb(uint16_t conn_handle, struct ble_l2cap_chan *chan, memset(&ev, 0, sizeof(struct btp_l2cap_disconnected_ev)); - channel = find_channel(chan); - assert(channel != NULL); + if (status != 0 && status != BLE_L2CAP_EVENT_COC_DISCONNECTED) { + /* Conection request failed */ + channel = get_free_channel(); + } else { + channel = find_channel(chan); + assert(channel != NULL); + } + ev.result = status; ev.chan_id = channel->chan_id; ev.psm = chan_info->psm; @@ -266,6 +272,8 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg) if (event->connect.status) { console_printf("LE COC error: %d\n", event->connect.status); + disconnected_cb(event->connect.conn_handle, event->connect.chan, + &chan_info, (uint8_t)event->connect.status, arg); return 0; } @@ -290,8 +298,8 @@ tester_l2cap_event(struct ble_l2cap_event *event, void *arg) console_printf("LE CoC disconnected, chan: 0x%08lx\n", (uint32_t) event->disconnect.chan); - disconnected_cb(event->disconnect.conn_handle, - event->disconnect.chan, &chan_info, arg); + disconnected_cb(event->disconnect.conn_handle, event->disconnect.chan, + &chan_info, (uint8_t)event->connect.status, arg); return 0; case BLE_L2CAP_EVENT_COC_ACCEPT: ble_l2cap_get_chan_info(event->accept.chan,