From 59cd171c661d10a2d8532bc72caa588455582de4 Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Mon, 20 Oct 2025 10:18:38 +0200 Subject: [PATCH 1/9] [nrf fromtree] tests: bluetooth: Recycle ext_adv_sets when stopping adv - We want to reuse ext_advs when first stopped and restarted - This ensures SID is the same - Fixes CAP/CL/ADV/BV-03-C Signed-off-by: Alexander Svensen (cherry picked from commit 4896194be8d77cebde07ebaaf37a0540fb013ba4) --- tests/bluetooth/tester/src/btp/btp_gap.h | 1 + tests/bluetooth/tester/src/btp_gap.c | 42 +++++++++++++++++++++++- 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/btp/btp_gap.h b/tests/bluetooth/tester/src/btp/btp_gap.h index 924859c461c2..071c72f40b02 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -585,6 +585,7 @@ struct bt_le_adv_param; struct bt_data; struct bt_le_ext_adv *tester_gap_ext_adv_get(uint8_t ext_adv_idx); struct bt_le_per_adv_sync *tester_gap_padv_get(void); +int tester_gap_clear_adv_instance(struct bt_le_ext_adv *ext_adv); int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len, diff --git a/tests/bluetooth/tester/src/btp_gap.c b/tests/bluetooth/tester/src/btp_gap.c index 1344933eec52..80b30467bd9d 100644 --- a/tests/bluetooth/tester/src/btp_gap.c +++ b/tests/bluetooth/tester/src/btp_gap.c @@ -600,6 +600,21 @@ static int tester_gap_ext_adv_idx_free_get(void) return -ENOMEM; } +static int tester_gap_ext_adv_idx_get(struct bt_le_ext_adv *ext_adv) +{ + if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { + return -ENOTSUP; + } + + for (int i = 0; i < ARRAY_SIZE(ext_adv_sets); i++) { + if (ext_adv_sets[i] == ext_adv) { + return i; + } + } + + return -EINVAL; +} + int tester_gap_start_ext_adv(struct bt_le_ext_adv *ext_adv) { if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { @@ -644,6 +659,8 @@ int tester_gap_stop_ext_adv(struct bt_le_ext_adv *ext_adv) return -EINVAL; } + tester_gap_clear_adv_instance(ext_adv); + atomic_clear_bit(¤t_settings, BTP_GAP_SETTINGS_ADVERTISING); return 0; @@ -750,6 +767,29 @@ static uint8_t set_bondable(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +int tester_gap_clear_adv_instance(struct bt_le_ext_adv *ext_adv) +{ + if (!IS_ENABLED(CONFIG_BT_EXT_ADV)) { + return -ENOTSUP; + } + + if (ext_adv == NULL) { + LOG_ERR("Invalid ext_adv"); + return -EINVAL; + } + + int index = tester_gap_ext_adv_idx_get(ext_adv); + + if (index < 0) { + LOG_ERR("Failed to get ext_adv index"); + return -EINVAL; + } + + ext_adv_sets[index] = NULL; + + return 0; +} + int tester_gap_create_adv_instance(struct bt_le_adv_param *param, uint8_t own_addr_type, const struct bt_data *ad, size_t ad_len, const struct bt_data *sd, size_t sd_len, uint32_t *settings, @@ -973,7 +1013,7 @@ static uint8_t stop_advertising(const void *cmd, uint16_t cmd_len, if (IS_ENABLED(CONFIG_BT_EXT_ADV) && atomic_test_bit(¤t_settings, BTP_GAP_SETTINGS_EXTENDED_ADVERTISING)) { - err = bt_le_ext_adv_stop(gap_ext_adv); + err = tester_gap_stop_ext_adv(gap_ext_adv); } else { err = bt_le_adv_stop(); } From 4c7631bdf3f037ebb342152eda89cdcbe1009a3d Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Tue, 11 Nov 2025 13:26:35 +0100 Subject: [PATCH 2/9] [nrf fromtree] tests: bluetooth: tester: Add ASE ID when configuring codec - We want to add the ASE ID to a stream as early as possible to make sure the events coming from BTTester to Auto-PTS contains the correct information. - Previously the events that came before stream_configured would contain ASE ID 0, regardless of actual value. Signed-off-by: Alexander Svensen (cherry picked from commit c4ab06b9c4864f33e1d5225fc53610f03060e9bf) --- tests/bluetooth/tester/src/audio/btp_bap_unicast.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/bluetooth/tester/src/audio/btp_bap_unicast.c b/tests/bluetooth/tester/src/audio/btp_bap_unicast.c index e839a0ddb767..c06795e8267a 100644 --- a/tests/bluetooth/tester/src/audio/btp_bap_unicast.c +++ b/tests/bluetooth/tester/src/audio/btp_bap_unicast.c @@ -511,7 +511,6 @@ static void stream_configured_cb(struct bt_bap_stream *stream, u_stream->conn_id = bt_conn_index(stream->conn); u_conn = &connections[u_stream->conn_id]; - u_stream->ase_id = info.id; stream_state_changed(stream); } @@ -1272,6 +1271,12 @@ static int client_configure_codec(struct btp_bap_unicast_connection *u_conn, str memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg)); err = bt_bap_stream_config(conn, stream_unicast_to_bap(stream), ep, &stream->codec_cfg); + + if (err == 0) { + stream->ase_id = ase_id; + } else { + stream->in_use = false; + } } else { /* Reconfigure a stream */ memcpy(&stream->codec_cfg, codec_cfg, sizeof(*codec_cfg)); From 9cd49d0a05f06fe05b5143c97f2940a54a4ec2ac Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Tue, 28 Oct 2025 13:46:15 +0100 Subject: [PATCH 3/9] [nrf fromtree] tests: bluetooth: tester: Fix bis_sink_sync - Allows the tester to match on either ID or addr - Previously required that both needed to match, but Auto-PTS is sending the wrong address Signed-off-by: Alexander Svensen (cherry picked from commit fa7d9bf09cd14941bc06f1331230be7107fb9dc0) --- .../tester/src/audio/btp_bap_broadcast.c | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c index e26046d2b083..3733ab36440a 100644 --- a/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c +++ b/tests/bluetooth/tester/src/audio/btp_bap_broadcast.c @@ -1162,6 +1162,8 @@ static int pa_sync_req_cb(struct bt_conn *conn, bt_addr_le_copy(&broadcaster->address, &recv_state->addr); } + broadcast_source_to_sync = broadcaster; + broadcaster->sink_recv_state = recv_state; btp_send_pas_sync_req_ev(conn, recv_state->src_id, recv_state->adv_sid, @@ -1380,20 +1382,6 @@ uint8_t btp_bap_broadcast_sink_sync(const void *cmd, uint16_t cmd_len, void *rsp LOG_DBG(""); - broadcaster = remote_broadcaster_find(&cp->address, broadcast_id); - if (broadcaster == NULL) { - broadcaster = remote_broadcaster_alloc(); - if (broadcaster == NULL) { - LOG_ERR("Failed to allocate broadcast source"); - return BTP_STATUS_FAILED; - } - - broadcaster->broadcast_id = broadcast_id; - bt_addr_le_copy(&broadcaster->address, &cp->address); - } - - broadcast_source_to_sync = broadcaster; - if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && cp->past_avail) { /* The Broadcast Assistant supports PAST transfer, and it has found * a Broadcaster for us. Let's sync to the Broadcaster PA with the PAST. @@ -1421,7 +1409,22 @@ uint8_t btp_bap_broadcast_sink_sync(const void *cmd, uint16_t cmd_len, void *rsp create_params.sid = cp->advertiser_sid; create_params.skip = cp->skip; create_params.timeout = cp->sync_timeout; + err = tester_gap_padv_create_sync(&create_params); + + broadcaster = remote_broadcaster_find(&cp->address, broadcast_id); + if (broadcaster == NULL) { + broadcaster = remote_broadcaster_alloc(); + if (broadcaster == NULL) { + LOG_ERR("Failed to allocate broadcast source"); + return BTP_STATUS_FAILED; + } + + broadcaster->broadcast_id = broadcast_id; + bt_addr_le_copy(&broadcaster->address, &cp->address); + } + + broadcast_source_to_sync = broadcaster; } if (err != 0) { From e096e51e801098ea863c993b5d0026b4b888ba94 Mon Sep 17 00:00:00 2001 From: Frode van der Meeren Date: Thu, 13 Nov 2025 15:02:55 +0100 Subject: [PATCH 4/9] [nrf fromtree] tests: bluetooth: tester: Fix CSIS/SR/SP/BV-07-C This particular test-case requires bttester to respond with an OOB procedure SIRK only error. To enable this response, the BTP command to set SIRK mode has been extended with a new selection. Signed-off-by: Frode van der Meeren (cherry picked from commit 03bfafe05e1d5ec716d9a15dced0e143dc9de6db) --- .../bluetooth/tester/src/audio/btp/btp_csis.h | 10 +++-- tests/bluetooth/tester/src/audio/btp_csis.c | 42 ++++++++++++------- tests/bsim/bluetooth/tester/src/bsim_btp.c | 2 +- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/tests/bluetooth/tester/src/audio/btp/btp_csis.h b/tests/bluetooth/tester/src/audio/btp/btp_csis.h index f007a6a938a2..0f1255301281 100644 --- a/tests/bluetooth/tester/src/audio/btp/btp_csis.h +++ b/tests/bluetooth/tester/src/audio/btp/btp_csis.h @@ -12,6 +12,10 @@ #include /* CSIS commands */ +#define BTP_CSIS_SIRK_TYPE_PLAINTEXT 0x00 +#define BTP_CSIS_SIRK_TYPE_ENCRYPTED 0x01 +#define BTP_CSIS_SIRK_TYPE_OOB_ONLY 0x02 + #define BTP_CSIS_READ_SUPPORTED_COMMANDS 0x01 struct btp_csis_read_supported_commands_rp { uint8_t data[0]; @@ -33,7 +37,7 @@ struct btp_csis_get_member_rsi_rp { uint8_t rsi[BT_CSIP_RSI_SIZE]; } __packed; -#define BTP_CSIS_ENC_SIRK_TYPE 0x04 -struct btp_csis_sirk_type_cmd { - uint8_t encrypted; +#define BTP_CSIS_SET_SIRK_TYPE 0x04 +struct btp_csis_sirk_set_type_cmd { + uint8_t type; } __packed; diff --git a/tests/bluetooth/tester/src/audio/btp_csis.c b/tests/bluetooth/tester/src/audio/btp_csis.c index cd62adf6f5eb..c80242b4e7a6 100644 --- a/tests/bluetooth/tester/src/audio/btp_csis.c +++ b/tests/bluetooth/tester/src/audio/btp_csis.c @@ -24,7 +24,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL); #define BTP_STATUS_VAL(err) (err) ? BTP_STATUS_FAILED : BTP_STATUS_SUCCESS static struct bt_csip_set_member_svc_inst *csis_svc_inst; -static bool enc_sirk; +static uint8_t sirk_read_response; static uint8_t csis_supported_commands(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) @@ -65,13 +65,27 @@ static uint8_t csis_get_member_rsi(const void *cmd, uint16_t cmd_len, return BTP_STATUS_VAL(err); } -static uint8_t csis_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +static uint8_t csis_set_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) { - const struct btp_csis_sirk_type_cmd *cp = cmd; - - enc_sirk = cp->encrypted != 0U; - - LOG_DBG("SIRK type: %s", enc_sirk ? "encrypted" : "plain text"); + const struct btp_csis_sirk_set_type_cmd *cp = cmd; + + switch (cp->type) { + case BTP_CSIS_SIRK_TYPE_PLAINTEXT: + LOG_DBG("SIRK type: plain text"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; + break; + case BTP_CSIS_SIRK_TYPE_ENCRYPTED: + LOG_DBG("SIRK type: encrypted"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC; + break; + case BTP_CSIS_SIRK_TYPE_OOB_ONLY: + LOG_DBG("SIRK type: OOB procedure only"); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY; + break; + default: + LOG_ERR("Unknown SIRK type: %u", cp->type); + return BTP_STATUS_FAILED; + } return BTP_STATUS_SUCCESS; } @@ -94,9 +108,9 @@ static const struct btp_handler csis_handlers[] = { .func = csis_get_member_rsi, }, { - .opcode = BTP_CSIS_ENC_SIRK_TYPE, - .expect_len = sizeof(struct btp_csis_sirk_type_cmd), - .func = csis_sirk_type, + .opcode = BTP_CSIS_SET_SIRK_TYPE, + .expect_len = sizeof(struct btp_csis_sirk_set_type_cmd), + .func = csis_set_sirk_type, }, }; @@ -108,11 +122,7 @@ static void lock_changed_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_ static uint8_t sirk_read_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_inst *svc_inst) { - if (enc_sirk) { - return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT_ENC; - } else { - return BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; - } + return sirk_read_response; } static struct bt_csip_set_member_cb csis_cb = { @@ -132,6 +142,8 @@ uint8_t tester_init_csis(void) }; int err = bt_csip_set_member_register(®ister_params, &csis_svc_inst); + sirk_read_response = BT_CSIP_READ_SIRK_REQ_RSP_ACCEPT; + tester_register_command_handlers(BTP_SERVICE_ID_CSIS, csis_handlers, ARRAY_SIZE(csis_handlers)); diff --git a/tests/bsim/bluetooth/tester/src/bsim_btp.c b/tests/bsim/bluetooth/tester/src/bsim_btp.c index a5b2c7000dc8..d0516cfcaab5 100644 --- a/tests/bsim/bluetooth/tester/src/bsim_btp.c +++ b/tests/bsim/bluetooth/tester/src/bsim_btp.c @@ -1236,7 +1236,7 @@ static bool is_valid_csis_packet_len(const struct btp_hdr *hdr, struct net_buf_s return buf_simple->len == 0U; case BTP_CSIS_GET_MEMBER_RSI: return buf_simple->len == sizeof(struct btp_csis_get_member_rsi_rp); - case BTP_CSIS_ENC_SIRK_TYPE: + case BTP_CSIS_SET_SIRK_TYPE: return buf_simple->len == 0U; /* No events */ From 30c12de9729afc121ae417f178417bd5dff8731a Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Thu, 30 Oct 2025 16:00:32 +0100 Subject: [PATCH 5/9] [nrf fromtree] Bluetooth: Audio: CSIS: Check all pending notifications - When a bonded device is reconnected, check flags for pending notifications for: - Lock - SIRK - Size Previously only lock was checked Signed-off-by: Alexander Svensen (cherry picked from commit fa8c244313c823d093ccaaf0a7d13aa75085c55a) --- subsys/bluetooth/audio/csip_set_member.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/subsys/bluetooth/audio/csip_set_member.c b/subsys/bluetooth/audio/csip_set_member.c index cfeb6ac6e45f..5656728f4e5d 100644 --- a/subsys/bluetooth/audio/csip_set_member.c +++ b/subsys/bluetooth/audio/csip_set_member.c @@ -520,8 +520,10 @@ static void csip_security_changed(struct bt_conn *conn, bt_security_t level, return; } - /* Check if client is set with FLAG_NOTIFY_LOCK */ - if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK)) { + /* Check if client has pending notifications */ + if (atomic_test_bit(client->flags, FLAG_NOTIFY_LOCK) || + atomic_test_bit(client->flags, FLAG_NOTIFY_SIRK) || + atomic_test_bit(client->flags, FLAG_NOTIFY_SIZE)) { notify_work_reschedule(K_NO_WAIT); break; } From 18f74928e6c980b601af9c3f892ebfde7c189645 Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Thu, 30 Oct 2025 16:03:16 +0100 Subject: [PATCH 6/9] [nrf fromtree] tests: bluetooth: tester: CSIS: Add more commands - Add command for setting the set size - Add command for setting the SIRK - Allows the following tests to pass: - CSIS/SR/CN/BV-01-C - CSIS/SR/CN/BV-02-C - CSIS/SR/CN/BV-03-C - CSIS/SR/CN/BV-04-C Signed-off-by: Alexander Svensen (cherry picked from commit 52f2686de67817f3ac5aa9ef16c89a0faf110d0b) --- tests/bluetooth/tester/overlay-le-audio.conf | 2 + .../bluetooth/tester/src/audio/btp/btp_csis.h | 11 +++++ tests/bluetooth/tester/src/audio/btp_csis.c | 42 +++++++++++++++++++ 3 files changed, 55 insertions(+) diff --git a/tests/bluetooth/tester/overlay-le-audio.conf b/tests/bluetooth/tester/overlay-le-audio.conf index 30f609b9ace5..f6fb0e9c4094 100644 --- a/tests/bluetooth/tester/overlay-le-audio.conf +++ b/tests/bluetooth/tester/overlay-le-audio.conf @@ -130,6 +130,8 @@ CONFIG_BT_HAS_CLIENT=y # CSIS CONFIG_BT_CSIP_SET_MEMBER=y CONFIG_BT_CSIP_SET_MEMBER_ENC_SIRK_SUPPORT=y +CONFIG_BT_CSIP_SET_MEMBER_SIRK_NOTIFIABLE=y +CONFIG_BT_CSIP_SET_MEMBER_SIZE_NOTIFIABLE=y # CSIP CONFIG_BT_CSIP_SET_COORDINATOR=y diff --git a/tests/bluetooth/tester/src/audio/btp/btp_csis.h b/tests/bluetooth/tester/src/audio/btp/btp_csis.h index 0f1255301281..3f28e942414d 100644 --- a/tests/bluetooth/tester/src/audio/btp/btp_csis.h +++ b/tests/bluetooth/tester/src/audio/btp/btp_csis.h @@ -41,3 +41,14 @@ struct btp_csis_get_member_rsi_rp { struct btp_csis_sirk_set_type_cmd { uint8_t type; } __packed; + +#define BTP_CSIS_SET_SIRK 0x05 +struct btp_csis_set_sirk_cmd { + uint8_t sirk[BT_CSIP_SIRK_SIZE]; +} __packed; + +#define BTP_CSIS_SET_SET_SIZE 0x06 +struct btp_csis_set_set_size_cmd { + uint8_t set_size; + uint8_t rank; +} __packed; diff --git a/tests/bluetooth/tester/src/audio/btp_csis.c b/tests/bluetooth/tester/src/audio/btp_csis.c index c80242b4e7a6..4e3662487684 100644 --- a/tests/bluetooth/tester/src/audio/btp_csis.c +++ b/tests/bluetooth/tester/src/audio/btp_csis.c @@ -90,6 +90,38 @@ static uint8_t csis_set_sirk_type(const void *cmd, uint16_t cmd_len, void *rsp, return BTP_STATUS_SUCCESS; } +static uint8_t csis_set_sirk(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_csis_set_sirk_cmd *cp = cmd; + int err = -ENOENT; + + LOG_DBG("Setting new SIRK"); + + if (csis_svc_inst != NULL) { + err = bt_csip_set_member_sirk(csis_svc_inst, cp->sirk); + } else { + LOG_DBG("No CSIS instance registered"); + } + + return BTP_STATUS_VAL(err); +} + +static uint8_t csis_set_set_size(const void *cmd, uint16_t cmd_len, void *rsp, uint16_t *rsp_len) +{ + const struct btp_csis_set_set_size_cmd *cp = cmd; + int err = -ENOENT; + + LOG_DBG("Setting new set size %u and rank %u", cp->set_size, cp->rank); + + if (csis_svc_inst != NULL) { + err = bt_csip_set_member_set_size_and_rank(csis_svc_inst, cp->set_size, cp->rank); + } else { + LOG_DBG("No CSIS instance registered"); + } + + return BTP_STATUS_VAL(err); +} + static const struct btp_handler csis_handlers[] = { { .opcode = BTP_CSIS_READ_SUPPORTED_COMMANDS, @@ -112,6 +144,16 @@ static const struct btp_handler csis_handlers[] = { .expect_len = sizeof(struct btp_csis_sirk_set_type_cmd), .func = csis_set_sirk_type, }, + { + .opcode = BTP_CSIS_SET_SIRK, + .expect_len = sizeof(struct btp_csis_set_sirk_cmd), + .func = csis_set_sirk, + }, + { + .opcode = BTP_CSIS_SET_SET_SIZE, + .expect_len = sizeof(struct btp_csis_set_set_size_cmd), + .func = csis_set_set_size, + }, }; static void lock_changed_cb(struct bt_conn *conn, struct bt_csip_set_member_svc_inst *svc_inst, From ec5a5235772ab8fc6e3c9b48bce123c5df42779d Mon Sep 17 00:00:00 2001 From: Frode van der Meeren Date: Thu, 6 Nov 2025 17:55:04 +0100 Subject: [PATCH 7/9] [nrf fromtree] tests: bluetooth: tester: Fix VCS tests Zephyr automatically sets the persisted flag for VCS if the volume is changed after the service is registered. As some of these PTS tests require a set volume with the flag cleared, the initial volume needs to be set before registering VCS. Signed-off-by: Frode van der Meeren (cherry picked from commit 48f82d1e34621ed245037d23ce6077059a6a24fa) --- .../bluetooth/tester/src/audio/btp/btp_vcs.h | 9 +++ tests/bluetooth/tester/src/audio/btp_vcp.c | 72 +++++++++++++------ .../tester/src/audio/vcp_peripheral.c | 1 + tests/bsim/bluetooth/tester/src/bsim_btp.c | 2 + tests/bsim/bluetooth/tester/src/bsim_btp.h | 21 ++++++ 5 files changed, 84 insertions(+), 21 deletions(-) diff --git a/tests/bluetooth/tester/src/audio/btp/btp_vcs.h b/tests/bluetooth/tester/src/audio/btp/btp_vcs.h index 6f31afe020c8..069b562c03d4 100644 --- a/tests/bluetooth/tester/src/audio/btp/btp_vcs.h +++ b/tests/bluetooth/tester/src/audio/btp/btp_vcs.h @@ -8,6 +8,8 @@ #include +#define BTP_VCS_REGISTER_FLAG_MUTED BIT(0) + #define BTP_VCS_READ_SUPPORTED_COMMANDS 0x01 struct btp_vcs_read_supported_commands_rp { uint8_t data[0]; @@ -22,3 +24,10 @@ struct btp_vcs_set_vol_cmd { #define BTP_VCS_VOL_DOWN 0x04 #define BTP_VCS_MUTE 0x05 #define BTP_VCS_UNMUTE 0x06 + +#define BTP_VCS_REGISTER 0x07 +struct btp_vcs_register_cmd { + uint8_t step; + uint8_t flags; + uint8_t volume; +} __packed; diff --git a/tests/bluetooth/tester/src/audio/btp_vcp.c b/tests/bluetooth/tester/src/audio/btp_vcp.c index 9205181a0db9..ec78de2c0435 100644 --- a/tests/bluetooth/tester/src/audio/btp_vcp.c +++ b/tests/bluetooth/tester/src/audio/btp_vcp.c @@ -140,6 +140,43 @@ static uint8_t unmute(const void *cmd, uint16_t cmd_len, return BTP_STATUS_SUCCESS; } +static void set_register_params(uint8_t gain_mode, uint8_t step, + bool muted, uint8_t volume); + +static uint8_t register_vcs(const void *cmd, uint16_t cmd_len, + void *rsp, uint16_t *rsp_len) +{ + static bool vcs_registered_flag; + const struct btp_vcs_register_cmd *cp = cmd; + int err; + + LOG_DBG("Registering VCS"); + + if (vcs_registered_flag) { + return BTP_STATUS_FAILED; + } + + bool muted = (cp->flags & BTP_VCS_REGISTER_FLAG_MUTED) != 0; + + set_register_params(BT_AICS_MODE_MANUAL, cp->step, muted, cp->volume); + + err = bt_vcp_vol_rend_register(&vcp_register_param); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + err = bt_vcp_vol_rend_included_get(&included); + if (err != 0) { + return BTP_STATUS_FAILED; + } + + aics_server_instance.aics_cnt = included.aics_cnt; + aics_server_instance.aics = included.aics; + vcs_registered_flag = true; + + return BTP_STATUS_SUCCESS; +} + static void vcs_state_cb(struct bt_conn *conn, int err, uint8_t volume, uint8_t mute) { LOG_DBG("VCP state cb err (%d)", err); @@ -187,6 +224,11 @@ static const struct btp_handler vcs_handlers[] = { .expect_len = 0, .func = unmute, }, + { + .opcode = BTP_VCS_REGISTER, + .expect_len = sizeof(struct btp_vcs_register_cmd), + .func = register_vcs, + }, }; /* Volume Offset Control Service */ @@ -463,7 +505,8 @@ struct bt_aics_cb aics_server_cb = { }; /* General profile handling */ -static void set_register_params(uint8_t gain_mode) +static void set_register_params(uint8_t gain_mode, uint8_t step, + bool muted, uint8_t volume) { char input_desc[CONFIG_BT_VCP_VOL_REND_AICS_INSTANCE_COUNT] [BT_AICS_MAX_INPUT_DESCRIPTION_SIZE]; @@ -495,31 +538,18 @@ static void set_register_params(uint8_t gain_mode) vcp_register_param.aics_param[i].cb = &aics_server_cb; } - vcp_register_param.step = 1; - vcp_register_param.mute = BT_VCP_STATE_UNMUTED; - vcp_register_param.volume = 100; + vcp_register_param.step = step; + if (muted) { + vcp_register_param.mute = BT_VCP_STATE_MUTED; + } else { + vcp_register_param.mute = BT_VCP_STATE_UNMUTED; + } + vcp_register_param.volume = volume; vcp_register_param.cb = &vcs_cb; } uint8_t tester_init_vcs(void) { - int err; - - set_register_params(BT_AICS_MODE_MANUAL); - - err = bt_vcp_vol_rend_register(&vcp_register_param); - if (err) { - return BTP_STATUS_FAILED; - } - - err = bt_vcp_vol_rend_included_get(&included); - if (err) { - return BTP_STATUS_FAILED; - } - - aics_server_instance.aics_cnt = included.aics_cnt; - aics_server_instance.aics = included.aics; - tester_register_command_handlers(BTP_SERVICE_ID_VCS, vcs_handlers, ARRAY_SIZE(vcs_handlers)); diff --git a/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c b/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c index 9fdfbcaf50ef..ef5a0efc2f1d 100644 --- a/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c +++ b/tests/bsim/bluetooth/tester/src/audio/vcp_peripheral.c @@ -35,6 +35,7 @@ static void test_vcp_peripheral(void) bsim_btp_core_register(BTP_SERVICE_ID_AICS); bsim_btp_gap_set_discoverable(BTP_GAP_GENERAL_DISCOVERABLE); + bsim_btp_vcs_register(1U, 0U, 100U); bsim_btp_gap_start_advertising(0U, 0U, NULL, BT_HCI_OWN_ADDR_PUBLIC); bsim_btp_wait_for_gap_device_connected(&remote_addr); bt_addr_le_to_str(&remote_addr, addr_str, sizeof(addr_str)); diff --git a/tests/bsim/bluetooth/tester/src/bsim_btp.c b/tests/bsim/bluetooth/tester/src/bsim_btp.c index d0516cfcaab5..2e24514b6606 100644 --- a/tests/bsim/bluetooth/tester/src/bsim_btp.c +++ b/tests/bsim/bluetooth/tester/src/bsim_btp.c @@ -873,6 +873,8 @@ static bool is_valid_vcs_packet_len(const struct btp_hdr *hdr, struct net_buf_si return buf_simple->len == 0U; case BTP_VCS_UNMUTE: return buf_simple->len == 0U; + case BTP_VCS_REGISTER: + return buf_simple->len == 0U; /* no events */ default: diff --git a/tests/bsim/bluetooth/tester/src/bsim_btp.h b/tests/bsim/bluetooth/tester/src/bsim_btp.h index 75198bf498eb..2480076bc069 100644 --- a/tests/bsim/bluetooth/tester/src/bsim_btp.h +++ b/tests/bsim/bluetooth/tester/src/bsim_btp.h @@ -563,6 +563,27 @@ static inline void bsim_btp_wait_for_tmap_discovery_complete(void) net_buf_unref(buf); } +static inline void bsim_btp_vcs_register(uint8_t step, uint8_t flags, uint8_t vol) +{ + struct btp_vcs_register_cmd *cmd; + struct btp_hdr *cmd_hdr; + + NET_BUF_SIMPLE_DEFINE(cmd_buffer, BTP_MTU); + + cmd_hdr = net_buf_simple_add(&cmd_buffer, sizeof(*cmd_hdr)); + cmd_hdr->service = BTP_SERVICE_ID_VCS; + cmd_hdr->opcode = BTP_VCS_REGISTER; + cmd_hdr->index = BTP_INDEX; + cmd = net_buf_simple_add(&cmd_buffer, sizeof(*cmd)); + cmd->step = step; + cmd->flags = flags; + cmd->volume = vol; + + cmd_hdr->len = sys_cpu_to_le16(cmd_buffer.len - sizeof(*cmd_hdr)); + + bsim_btp_send_to_tester(cmd_buffer.data, cmd_buffer.len); +} + static inline void bsim_btp_vcp_discover(const bt_addr_le_t *address) { struct btp_vcp_discover_cmd *cmd; From cc233f1473c03f78f0074424320effff63123a2c Mon Sep 17 00:00:00 2001 From: Alexander Svensen Date: Mon, 17 Nov 2025 16:02:17 +0100 Subject: [PATCH 8/9] [nrf fromtree] bluetooth: audio: scan_delegator: Fix validation - Fixes bug where bis_sync_requests were wrongfully validated. - Two BISes across subgroups should not have the same bits set - Remove use of internal->bis_syncs before it's updated in mod_src. Signed-off-by: Alexander Svensen (cherry picked from commit 78729f4ff0ce66392efb87315161f8e5677d3046) --- subsys/bluetooth/audio/bap_scan_delegator.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/subsys/bluetooth/audio/bap_scan_delegator.c b/subsys/bluetooth/audio/bap_scan_delegator.c index da07fab411c8..8c21b806900f 100644 --- a/subsys/bluetooth/audio/bap_scan_delegator.c +++ b/subsys/bluetooth/audio/bap_scan_delegator.c @@ -149,7 +149,7 @@ static bool bis_syncs_unique_or_no_pref(uint32_t requested_bis_syncs, return true; } - return (requested_bis_syncs & aggregated_bis_syncs) != 0U; + return (requested_bis_syncs & aggregated_bis_syncs) == 0U; } static bool valid_bis_sync_request(uint32_t requested_bis_syncs, uint32_t aggregated_bis_syncs) @@ -938,8 +938,7 @@ static int scan_delegator_mod_src(struct bt_conn *conn, bis_sync_change_requested = true; } - if (!valid_bis_sync_request(internal_state->requested_bis_sync[i], - aggregated_bis_syncs)) { + if (!valid_bis_sync_request(requested_bis_sync[i], aggregated_bis_syncs)) { LOG_DBG("Invalid BIS Sync request[%d]", i); ret = BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED); goto unlock_return; From 0d9a0cb69adfad7a7c7b25a764fde3d67d379f0a Mon Sep 17 00:00:00 2001 From: Emil Gydesen Date: Thu, 20 Nov 2025 10:02:42 +0100 Subject: [PATCH 9/9] [nrf fromtree] tests: Bluetooth: tester: Removed bad guard in btp_gap.h As per the Zephyr coding guidelines, functions declarations in header files should not be conditionally compiled. This fixes an issue with tester_gap_clear_adv_instance where btp_gap.c always expect it to be available. Signed-off-by: Emil Gydesen (cherry picked from commit 318067ec6c38ae156e09d2767c0905f08947aeb8) --- tests/bluetooth/tester/src/btp/btp_gap.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/bluetooth/tester/src/btp/btp_gap.h b/tests/bluetooth/tester/src/btp/btp_gap.h index 071c72f40b02..81c7ba723b6c 100644 --- a/tests/bluetooth/tester/src/btp/btp_gap.h +++ b/tests/bluetooth/tester/src/btp/btp_gap.h @@ -578,7 +578,6 @@ struct btp_gap_periodic_biginfo_ev { uint8_t encryption; } __packed; -#if defined(CONFIG_BT_EXT_ADV) struct bt_le_per_adv_param; struct bt_le_per_adv_sync_param; struct bt_le_adv_param; @@ -599,4 +598,3 @@ int tester_gap_padv_start(struct bt_le_ext_adv *ext_adv); int tester_gap_padv_stop(struct bt_le_ext_adv *ext_adv); int tester_gap_padv_create_sync(struct bt_le_per_adv_sync_param *create_params); int tester_gap_padv_stop_sync(void); -#endif /* defined(CONFIG_BT_EXT_ADV) */