From e73bfb92c7cf78c2a14870dab9c2faa864ae3ca8 Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Mon, 18 Nov 2024 12:51:47 +0100 Subject: [PATCH] tests: Bluetooth: ASCS: Fix various issues in ASCS unit tests The ASCS unit tests had various errors after adding support for dynamic registration. Several tests did not properly clean up after failure, causing other tests to fail when they shouldn't. Moved the register tests to their own file as they should not do the register in the "before" function. The test_ascs_unregister_with_ases_in_config_state test was also removed, as it had both issues and the state that it wants to test cannot be reached with the current API - It is not possible to put an ASE in the configured state without callbacks, and registered callbacks prevents us from calling bt_bap_unicast_server_unregister to trigger the case as that can only be done if callbacks are unregistered. Since unregistering callbacks also puts all ASEs to the idle state, it is not possible to call bt_bap_unicast_server_unregister for a non-idle ASE. The testcase.yaml was also missing some Kconfig options to properly enable the client tests. Signed-off-by: Emil Gydesen --- subsys/bluetooth/audio/ascs.c | 2 + tests/bluetooth/audio/ascs/CMakeLists.txt | 1 + tests/bluetooth/audio/ascs/src/main.c | 190 ++---------------- .../audio/ascs/src/test_ase_control_params.c | 10 +- .../audio/ascs/src/test_ase_register.c | 163 +++++++++++++++ .../ascs/src/test_ase_state_transition.c | 11 +- .../src/test_ase_state_transition_invalid.c | 10 +- tests/bluetooth/audio/ascs/testcase.yaml | 2 + 8 files changed, 199 insertions(+), 190 deletions(-) create mode 100644 tests/bluetooth/audio/ascs/src/test_ase_register.c diff --git a/subsys/bluetooth/audio/ascs.c b/subsys/bluetooth/audio/ascs.c index 51ba19b2350..ae94530214c 100644 --- a/subsys/bluetooth/audio/ascs.c +++ b/subsys/bluetooth/audio/ascs.c @@ -3283,6 +3283,8 @@ int bt_ascs_unregister(void) for (size_t i = 0; i < ARRAY_SIZE(ascs.ase_pool); i++) { if (ascs.ase_pool[i].ep.status.state != BT_BAP_EP_STATE_IDLE) { + LOG_DBG("[%zu] ase %p not in idle state: %s", i, &ascs.ase_pool[i].ep, + bt_bap_ep_state_str(ascs.ase_pool[i].ep.status.state)); return -EBUSY; } } diff --git a/tests/bluetooth/audio/ascs/CMakeLists.txt b/tests/bluetooth/audio/ascs/CMakeLists.txt index 5fb4df5f683..6b4b0311daa 100644 --- a/tests/bluetooth/audio/ascs/CMakeLists.txt +++ b/tests/bluetooth/audio/ascs/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(testbinary PRIVATE src/main.c src/test_ase_control_params.c + src/test_ase_register.c src/test_ase_state_transition_invalid.c src/test_ase_state_transition.c src/test_common.c diff --git a/tests/bluetooth/audio/ascs/src/main.c b/tests/bluetooth/audio/ascs/src/main.c index 77f6f32ec2a..aca746650a2 100644 --- a/tests/bluetooth/audio/ascs/src/main.c +++ b/tests/bluetooth/audio/ascs/src/main.c @@ -3,10 +3,12 @@ /* * Copyright (c) 2023 Codecoup * Copyright (c) 2024 Demant A/S + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -34,6 +36,7 @@ #include "pacs.h" #include "test_common.h" +#include "ztest_assert.h" DEFINE_FFF_GLOBALS; @@ -70,6 +73,7 @@ static void ascs_test_suite_fixture_init(struct ascs_test_suite_fixture *fixture memset(fixture, 0, sizeof(*fixture)); err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, 0, "Unexpected err response %d", err); fixture->ase_cp = test_ase_control_point_get(); @@ -109,11 +113,17 @@ static void ascs_test_suite_teardown(void *f) static void ascs_test_suite_after(void *f) { - /* We skip error-checking this, as somehow this breaks the tests, due to seemingly - * memory corruption, causing incorrect lookup of attributes in following 'before' calls - */ - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); - bt_bap_unicast_server_unregister(); + int err; + + /* If any of these fails, it's a fatal error for any tests running afterwards */ + err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); + zassert_true(err == 0 || err == -EALREADY, "Unexpected err response %d", err); + + /* Sleep to trigger any pending state changes from unregister_cb */ + k_sleep(K_SECONDS(1)); + + err = bt_bap_unicast_server_unregister(); + zassert_equal(err, 0, "Unexpected err response %d", err); } ZTEST_SUITE(ascs_test_suite, NULL, ascs_test_suite_setup, ascs_test_suite_before, @@ -153,158 +163,6 @@ ZTEST_F(ascs_test_suite, test_sink_ase_read_state_idle) zassert_equal(0x00, hdr.ase_state, "unexpected ASE_State 0x%02x", hdr.ase_state); } -ZTEST_F(ascs_test_suite, test_cb_register_without_ascs_registered) -{ - int err; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb); - zassert_equal(err, -ENOTSUP, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_with_null_param) -{ - int err; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register(NULL); - zassert_equal(err, -EINVAL, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_twice) -{ - int err; - struct bt_bap_unicast_server_register_param param = { - CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, - CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT - }; - - /* Setup already registered once, so calling once here should be sufficient */ - err = bt_bap_unicast_server_register(¶m); - zassert_equal(err, -EALREADY, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_too_many_sinks) -{ - int err; - struct bt_bap_unicast_server_register_param param = { - CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT + 1, - CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT - }; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register(¶m); - zassert_equal(err, -EINVAL, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_too_many_sources) -{ - int err; - struct bt_bap_unicast_server_register_param param = { - CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, - CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT + 1 - }; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register(¶m); - zassert_equal(err, -EINVAL, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_zero_ases) -{ - int err; - struct bt_bap_unicast_server_register_param param = { - 0, - 0 - }; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register(¶m); - zassert_equal(err, -EINVAL, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_register_fewer_than_max_ases) -{ - int err; - struct bt_bap_unicast_server_register_param param = { - CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0 ? CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT - 1 : 0, - CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0 ? CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT - 1 : 0 - }; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_register(¶m); - zassert_equal(err, 0, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_unregister_without_register) -{ - int err; - - /* Unregister ASCS, as its registered through setup */ - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_unregister(); - zassert_equal(err, -EALREADY, "unexpected err response %d", err); -} - -ZTEST_F(ascs_test_suite, test_ascs_unregister_with_ases_in_config_state) -{ - const struct test_ase_chrc_value_hdr *hdr; - const struct bt_gatt_attr *ase; - struct bt_bap_stream *stream = &fixture->stream; - struct bt_conn *conn = &fixture->conn; - struct bt_gatt_notify_params *notify_params; - uint8_t ase_id; - int err; - - if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) { - ase = fixture->ase_snk.attr; - ase_id = fixture->ase_snk.id; - } else { - ase = fixture->ase_src.attr; - ase_id = fixture->ase_src.id; - } - - zexpect_not_null(ase); - zexpect_true(ase_id != 0x00); - - err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb); - zassert_equal(err, 0, "unexpected err response %d", err); - - /* Set ASE to non-idle state */ - test_ase_control_client_config_codec(conn, ase_id, stream); - - err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); - zassert_equal(err, 0, "unexpected err response %d", err); - - err = bt_bap_unicast_server_unregister(); - - /* Expected to notify the upper layers */ - expect_bt_bap_unicast_server_cb_release_called_once(stream); - expect_bt_bap_stream_ops_released_called_once(stream); - - zassert_equal(err, 0, "unexpected err response %d", err); -} - ZTEST_F(ascs_test_suite, test_release_ase_on_callback_unregister) { const struct test_ase_chrc_value_hdr *hdr; @@ -424,8 +282,6 @@ ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection) /* Mock CIS disconnection */ mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_release_ase_pair_on_acl_disconnection) @@ -486,8 +342,6 @@ ZTEST_F(ascs_test_suite, test_release_ase_pair_on_acl_disconnection) /* Mock CIS disconnection */ mock_bt_iso_disconnected(chan, BT_HCI_ERR_CONN_TIMEOUT); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_recv_in_streaming_state) @@ -514,8 +368,6 @@ ZTEST_F(ascs_test_suite, test_recv_in_streaming_state) /* Verification */ expect_bt_bap_stream_ops_recv_called_once(stream, &info, &buf); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_recv_in_enabling_state) @@ -547,8 +399,6 @@ ZTEST_F(ascs_test_suite, test_recv_in_enabling_state) /* Verification */ expect_bt_bap_stream_ops_recv_not_called(); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_cis_link_loss_in_streaming_state) @@ -584,8 +434,6 @@ ZTEST_F(ascs_test_suite, test_cis_link_loss_in_streaming_state) expect_bt_bap_stream_ops_disabled_called_once(stream); expect_bt_bap_stream_ops_released_not_called(); expect_bt_bap_stream_ops_disconnected_called_once(stream); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } static void test_cis_link_loss_in_disabling_state(struct ascs_test_suite_fixture *fixture, @@ -630,8 +478,6 @@ static void test_cis_link_loss_in_disabling_state(struct ascs_test_suite_fixture expect_bt_bap_stream_ops_disabled_not_called(); expect_bt_bap_stream_ops_released_not_called(); expect_bt_bap_stream_ops_disconnected_called_once(stream); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_cis_link_loss_in_disabling_state_v1) @@ -690,8 +536,6 @@ ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state) /* Server-initiated disable operation that shall not cause transition to QoS */ expect_bt_bap_stream_ops_qos_set_not_called(); } - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state_client_retries) @@ -741,8 +585,6 @@ ZTEST_F(ascs_test_suite, test_cis_link_loss_in_enabling_state_client_retries) expect_bt_bap_stream_ops_connected_called_twice(stream); expect_bt_bap_stream_ops_started_called_once(stream); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } static struct bt_bap_stream *stream_allocated; @@ -823,6 +665,4 @@ ZTEST_F(ascs_test_suite, test_ase_state_notification_retry) k_sleep(K_MSEC(BT_CONN_INTERVAL_TO_MS(info.le.interval))); expect_bt_bap_stream_ops_configured_called_once(stream, EMPTY); - - bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); } diff --git a/tests/bluetooth/audio/ascs/src/test_ase_control_params.c b/tests/bluetooth/audio/ascs/src/test_ase_control_params.c index a4090da02e2..4f7d2a4c649 100644 --- a/tests/bluetooth/audio/ascs/src/test_ase_control_params.c +++ b/tests/bluetooth/audio/ascs/src/test_ase_control_params.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -80,12 +81,11 @@ static void test_ase_control_params_after(void *f) err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); zassert_equal(err, 0, "unexpected err response %d", err); + /* Sleep to trigger any pending state changes from unregister_cb */ + k_sleep(K_SECONDS(1)); + err = bt_bap_unicast_server_unregister(); - while (err != 0) { - zassert_equal(err, -EBUSY, "unexpected err response %d", err); - k_sleep(K_MSEC(10)); - err = bt_bap_unicast_server_unregister(); - } + zassert_equal(err, 0, "Unexpected err response %d", err); } static void test_ase_control_params_teardown(void *f) diff --git a/tests/bluetooth/audio/ascs/src/test_ase_register.c b/tests/bluetooth/audio/ascs/src/test_ase_register.c new file mode 100644 index 00000000000..b784d62a5b8 --- /dev/null +++ b/tests/bluetooth/audio/ascs/src/test_ase_register.c @@ -0,0 +1,163 @@ +/* main.c - Application main entry point */ + +/* + * Copyright (c) 2024 Demant A/S + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "assert.h" +#include "bap_unicast_server.h" +#include "bap_unicast_server_expects.h" +#include "bap_stream.h" +#include "bap_stream_expects.h" +#include "conn.h" + +#include "test_common.h" + +static void ascs_register_test_suite_after(void *f) +{ + /* Attempt to clean up failing tests */ + (void)bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); + + /* Sleep to trigger any pending state changes */ + k_sleep(K_SECONDS(1)); + + (void)bt_bap_unicast_server_unregister(); +} + +ZTEST_SUITE(ascs_register_test_suite, NULL, NULL, NULL, ascs_register_test_suite_after, NULL); + +static ZTEST(ascs_register_test_suite, test_cb_register_without_ascs_registered) +{ + int err; + + err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb); + zassert_equal(err, -ENOTSUP, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_with_null_param) +{ + int err; + + err = bt_bap_unicast_server_register(NULL); + zassert_equal(err, -EINVAL, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_twice) +{ + int err; + struct bt_bap_unicast_server_register_param param = { + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT, + }; + + /* Setup already registered once, so calling once here should be sufficient */ + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, 0, "Unexpected err response %d", err); + + /* Setup already registered once, so calling once here should be sufficient */ + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, -EALREADY, "Unexpected err response %d", err); + + err = bt_bap_unicast_server_unregister(); + zassert_equal(err, 0, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_too_many_sinks) +{ + int err; + struct bt_bap_unicast_server_register_param param = { + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT + 1, + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT, + }; + + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, -EINVAL, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_too_many_sources) +{ + int err; + struct bt_bap_unicast_server_register_param param = { + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT + 1, + }; + + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, -EINVAL, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_zero_ases) +{ + int err; + struct bt_bap_unicast_server_register_param param = {0, 0}; + + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, -EINVAL, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_register_fewer_than_max_ases) +{ + int err; + struct bt_bap_unicast_server_register_param param = { + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT > 0 ? CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT - 1 : 0, + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT > 0 ? CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT - 1 : 0, + }; + + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, 0, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_unregister_without_register) +{ + int err; + + err = bt_bap_unicast_server_unregister(); + zassert_equal(err, -EALREADY, "Unexpected err response %d", err); +} + +static ZTEST(ascs_register_test_suite, test_ascs_unregister_with_cbs_registered) +{ + struct bt_bap_unicast_server_register_param param = { + CONFIG_BT_ASCS_MAX_ASE_SNK_COUNT, + CONFIG_BT_ASCS_MAX_ASE_SRC_COUNT, + }; + int err; + + err = bt_bap_unicast_server_register(¶m); + zassert_equal(err, 0, "Unexpected err response %d", err); + + err = bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb); + zassert_equal(err, 0, "Unexpected err response %d", err); + + /* Not valid to unregister while callbacks are still registered */ + err = bt_bap_unicast_server_unregister(); + zassert_equal(err, -EAGAIN, "Unexpected err response %d", err); + + err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); + zassert_equal(err, 0, "Unexpected err response %d", err); + + err = bt_bap_unicast_server_unregister(); + zassert_equal(err, 0, "Unexpected err response %d", err); +} diff --git a/tests/bluetooth/audio/ascs/src/test_ase_state_transition.c b/tests/bluetooth/audio/ascs/src/test_ase_state_transition.c index d91af834c52..763c5075f4e 100644 --- a/tests/bluetooth/audio/ascs/src/test_ase_state_transition.c +++ b/tests/bluetooth/audio/ascs/src/test_ase_state_transition.c @@ -8,12 +8,14 @@ */ #include +#include #include #include #include #include #include #include +#include #include "bap_unicast_server.h" #include "bap_unicast_server_expects.h" @@ -110,12 +112,11 @@ static void test_ase_state_transition_after(void *f) err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); zassert_equal(err, 0, "unexpected err response %d", err); + /* Sleep to trigger any pending state changes from unregister_cb */ + k_sleep(K_SECONDS(1)); + err = bt_bap_unicast_server_unregister(); - while (err != 0) { - zassert_equal(err, -EBUSY, "unexpected err response %d", err); - k_sleep(K_MSEC(10)); - err = bt_bap_unicast_server_unregister(); - } + zassert_equal(err, 0, "Unexpected err response %d", err); } static void test_ase_state_transition_teardown(void *f) diff --git a/tests/bluetooth/audio/ascs/src/test_ase_state_transition_invalid.c b/tests/bluetooth/audio/ascs/src/test_ase_state_transition_invalid.c index 454a3d85ac4..4bfb6ac6fe0 100644 --- a/tests/bluetooth/audio/ascs/src/test_ase_state_transition_invalid.c +++ b/tests/bluetooth/audio/ascs/src/test_ase_state_transition_invalid.c @@ -8,6 +8,7 @@ */ #include +#include #include #include #include @@ -75,12 +76,11 @@ static void test_ase_state_transition_invalid_after(void *f) err = bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb); zassert_equal(err, 0, "unexpected err response %d", err); + /* Sleep to trigger any pending state changes from unregister_cb */ + k_sleep(K_SECONDS(1)); + err = bt_bap_unicast_server_unregister(); - while (err != 0) { - zassert_equal(err, -EBUSY, "unexpected err response %d", err); - k_sleep(K_MSEC(10)); - err = bt_bap_unicast_server_unregister(); - } + zassert_equal(err, 0, "Unexpected err response %d", err); } static void test_ase_state_transition_invalid_teardown(void *f) diff --git a/tests/bluetooth/audio/ascs/testcase.yaml b/tests/bluetooth/audio/ascs/testcase.yaml index 63663c81773..f0501d65cc8 100644 --- a/tests/bluetooth/audio/ascs/testcase.yaml +++ b/tests/bluetooth/audio/ascs/testcase.yaml @@ -16,6 +16,8 @@ tests: bluetooth.audio.ascs.test_unicast_client_enabled: type: unit extra_configs: + - CONFIG_BT_CENTRAL=y + - CONFIG_BT_ISO_CENTRAL=y - CONFIG_BT_BAP_UNICAST_CLIENT=y - CONFIG_BT_GATT_CLIENT=y - CONFIG_BT_GATT_AUTO_DISCOVER_CCC=y