This is an automated email from the ASF dual-hosted git repository. janc pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git
commit 925e781ee4410af791aa9a4219d0da2e41668657 Author: Szymon Janc <[email protected]> AuthorDate: Wed Dec 10 15:39:30 2025 +0100 nimble/host: Add function to remove L2CAP CoC server This allows application to remove previously registered L2CAP CoC server. --- nimble/host/include/host/ble_l2cap.h | 13 +++++++ nimble/host/src/ble_l2cap.c | 20 +++++++++- nimble/host/src/ble_l2cap_coc.c | 69 +++++++++++++++++++---------------- nimble/host/src/ble_l2cap_coc_priv.h | 16 ++++++-- nimble/host/test/src/ble_l2cap_test.c | 24 ++++++++++++ 5 files changed, 105 insertions(+), 37 deletions(-) diff --git a/nimble/host/include/host/ble_l2cap.h b/nimble/host/include/host/ble_l2cap.h index 32bd41bc8..65329b87a 100644 --- a/nimble/host/include/host/ble_l2cap.h +++ b/nimble/host/include/host/ble_l2cap.h @@ -546,6 +546,19 @@ uint16_t ble_l2cap_get_conn_handle(struct ble_l2cap_chan *chan); int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, ble_l2cap_event_fn *cb, void *cb_arg); +/** + * @brief Removes an L2CAP server. + * + * This function removes an L2CAP server with the specified Protocol/Service + * Multiplexer (PSM). Existing connections for this PSM are not removed. + * + * @param psm The Protocol/Service Multiplexer (PSM) for the server. + * + * @return 0 on success; + * A non-zero value on failure. + */ +int ble_l2cap_remove_server(uint16_t psm); + /** * @brief Initiate an L2CAP connection. * diff --git a/nimble/host/src/ble_l2cap.c b/nimble/host/src/ble_l2cap.c index c79081eec..0d1b4ebc9 100644 --- a/nimble/host/src/ble_l2cap.c +++ b/nimble/host/src/ble_l2cap.c @@ -145,7 +145,25 @@ int ble_l2cap_create_server(uint16_t psm, uint16_t mtu, ble_l2cap_event_fn *cb, void *cb_arg) { - return ble_l2cap_coc_create_server(psm, mtu, cb, cb_arg); + int rc; + + ble_hs_lock(); + rc = ble_l2cap_coc_create_server_nolock(psm, mtu, cb, cb_arg); + ble_hs_unlock(); + + return rc; +} + +int +ble_l2cap_remove_server(uint16_t psm) +{ + int rc; + + ble_hs_lock(); + rc = ble_l2cap_coc_remove_server_nolock(psm); + ble_hs_unlock(); + + return rc; } int diff --git a/nimble/host/src/ble_l2cap_coc.c b/nimble/host/src/ble_l2cap_coc.c index a63e50770..6ed30a98f 100644 --- a/nimble/host/src/ble_l2cap_coc.c +++ b/nimble/host/src/ble_l2cap_coc.c @@ -52,18 +52,6 @@ static os_membuf_t ble_l2cap_coc_srv_mem[ static struct os_mempool ble_l2cap_coc_srv_pool; -static void -ble_l2cap_coc_dbg_assert_srv_not_inserted(struct ble_l2cap_coc_srv *srv) -{ -#if MYNEWT_VAL(BLE_HS_DEBUG) - struct ble_l2cap_coc_srv *cur; - - STAILQ_FOREACH(cur, &ble_l2cap_coc_srvs, next) { - BLE_HS_DBG_ASSERT(cur != srv); - } -#endif -} - static struct ble_l2cap_coc_srv * ble_l2cap_coc_srv_alloc(void) { @@ -77,12 +65,31 @@ ble_l2cap_coc_srv_alloc(void) return srv; } +static struct ble_l2cap_coc_srv * +ble_l2cap_coc_srv_find(uint16_t psm) +{ + struct ble_l2cap_coc_srv *srv; + + STAILQ_FOREACH(srv, &ble_l2cap_coc_srvs, next) { + if (srv->psm == psm) { + return srv; + } + } + + return NULL; +} + int -ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg) +ble_l2cap_coc_create_server_nolock(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg) { struct ble_l2cap_coc_srv *srv; + srv = ble_l2cap_coc_srv_find(psm); + if (srv) { + return BLE_HS_EALREADY; + } + srv = ble_l2cap_coc_srv_alloc(); if (!srv) { return BLE_HS_ENOMEM; @@ -93,13 +100,27 @@ ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, srv->cb = cb; srv->cb_arg = cb_arg; - ble_l2cap_coc_dbg_assert_srv_not_inserted(srv); - STAILQ_INSERT_HEAD(&ble_l2cap_coc_srvs, srv, next); return 0; } +int +ble_l2cap_coc_remove_server_nolock(uint16_t psm) +{ + struct ble_l2cap_coc_srv *srv; + + srv = ble_l2cap_coc_srv_find(psm); + if (!srv) { + return BLE_HS_ENOENT; + } + + STAILQ_REMOVE(&ble_l2cap_coc_srvs, srv, ble_l2cap_coc_srv, next); + + os_memblock_put(&ble_l2cap_coc_srv_pool, srv); + return 0; +} + static inline void ble_l2cap_set_used_cid(uint32_t *cid_mask, int bit) { @@ -152,22 +173,6 @@ ble_l2cap_coc_get_cid(uint32_t *cid_mask) return BLE_L2CAP_COC_CID_START + bit; } -static struct ble_l2cap_coc_srv * -ble_l2cap_coc_srv_find(uint16_t psm) -{ - struct ble_l2cap_coc_srv *cur, *srv; - - srv = NULL; - STAILQ_FOREACH(cur, &ble_l2cap_coc_srvs, next) { - if (cur->psm == psm) { - srv = cur; - break; - } - } - - return srv; -} - static void ble_l2cap_event_coc_received_data(struct ble_l2cap_chan *chan, struct os_mbuf *om) diff --git a/nimble/host/src/ble_l2cap_coc_priv.h b/nimble/host/src/ble_l2cap_coc_priv.h index 8a87303fb..673530324 100644 --- a/nimble/host/src/ble_l2cap_coc_priv.h +++ b/nimble/host/src/ble_l2cap_coc_priv.h @@ -58,8 +58,9 @@ struct ble_l2cap_coc_srv { #if MYNEWT_VAL(BLE_L2CAP_COC_MAX_NUM) != 0 int ble_l2cap_coc_init(void); -int ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_coc_create_server_nolock(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg); +int ble_l2cap_coc_remove_server_nolock(uint16_t psm); int ble_l2cap_coc_create_srv_chan(struct ble_hs_conn *conn, uint16_t psm, struct ble_l2cap_chan **chan); struct ble_l2cap_chan * ble_l2cap_coc_chan_alloc(struct ble_hs_conn *conn, @@ -81,8 +82,15 @@ ble_l2cap_coc_init(void) { } static inline int -ble_l2cap_coc_create_server(uint16_t psm, uint16_t mtu, - ble_l2cap_event_fn *cb, void *cb_arg) { +ble_l2cap_coc_create_server_nolock(uint16_t psm, uint16_t mtu, + ble_l2cap_event_fn *cb, void *cb_arg) +{ + return BLE_HS_ENOTSUP; +} + +static inline int +ble_l2cap_coc_remove_server_nolock(uint16_t psm) +{ return BLE_HS_ENOTSUP; } diff --git a/nimble/host/test/src/ble_l2cap_test.c b/nimble/host/test/src/ble_l2cap_test.c index 5d7729a86..839ac430a 100644 --- a/nimble/host/test/src/ble_l2cap_test.c +++ b/nimble/host/test/src/ble_l2cap_test.c @@ -1531,6 +1531,29 @@ TEST_CASE_SELF(ble_l2cap_test_case_sig_coc_conn_multi) ble_hs_test_util_assert_mbufs_freed(NULL); } +TEST_CASE_SELF(ble_l2cap_test_case_server_create_remove) +{ + int rc; + + /* Register server */ + rc = ble_l2cap_create_server(BLE_L2CAP_TEST_PSM, BLE_L2CAP_TEST_COC_MTU, + ble_l2cap_test_event, NULL); + TEST_ASSERT(rc == 0); + + /* Register second server with same PSM */ + rc = ble_l2cap_create_server(BLE_L2CAP_TEST_PSM, BLE_L2CAP_TEST_COC_MTU, + ble_l2cap_test_event, NULL); + TEST_ASSERT(rc == BLE_HS_EALREADY); + + /* remove success */ + rc = ble_l2cap_remove_server(BLE_L2CAP_TEST_PSM); + TEST_ASSERT(rc == 0); + + /* second remove shall fail */ + rc = ble_l2cap_remove_server(BLE_L2CAP_TEST_PSM); + TEST_ASSERT(rc == BLE_HS_ENOENT); +} + TEST_SUITE(ble_l2cap_test_suite) { ble_l2cap_test_case_bad_header(); @@ -1562,4 +1585,5 @@ TEST_SUITE(ble_l2cap_test_suite) ble_l2cap_test_case_coc_send_data_failed_too_big_sdu(); ble_l2cap_test_case_coc_recv_data_succeed(); ble_l2cap_test_case_sig_coc_conn_multi(); + ble_l2cap_test_case_server_create_remove(); }
