Bluetooth: Audio: implement the distribute broadcast code procedure

Implemenation of the distribute broadcast code CAP procedure, as well
as unittesting

Signed-off-by: Andries Kruithof <andries.kruithof@nordicsemi.no>
This commit is contained in:
Andries Kruithof 2024-10-31 13:36:10 +01:00 committed by Henrik Brix Andersen
commit bb3bab7a34
10 changed files with 500 additions and 2 deletions

View file

@ -820,6 +820,17 @@ struct bt_cap_commander_cb {
* by bt_cap_commander_cancel(). * by bt_cap_commander_cancel().
*/ */
void (*broadcast_reception_stop)(struct bt_conn *conn, int err); void (*broadcast_reception_stop)(struct bt_conn *conn, int err);
/**
* @brief Callback for bt_cap_commander_distribute_broadcast_code().
*
* @param conn Pointer to the connection where the error
* occurred. NULL if @p err is 0 or if cancelled by
* bt_cap_commander_cancel()
* @param err 0 on success, BT_GATT_ERR() with a
* specific ATT (BT_ATT_ERR_*) error code or -ECANCELED if cancelled
* by bt_cap_commander_cancel().
*/
void (*distribute_broadcast_code)(struct bt_conn *conn, int err);
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
}; };

View file

@ -671,10 +671,185 @@ int bt_cap_commander_broadcast_reception_stop(
return 0; return 0;
} }
static void cap_commander_broadcast_assistant_set_broadcast_code_cb(struct bt_conn *conn, int err)
{
struct bt_cap_common_proc *active_proc = bt_cap_common_get_active_proc();
LOG_DBG("conn %p", (void *)conn);
if (!bt_cap_common_conn_in_active_proc(conn)) {
/* State change happened outside of a procedure; ignore */
return;
}
if (err != 0) {
LOG_DBG("Failed to distribute broadcast code: %d", err);
bt_cap_common_abort_proc(conn, err);
} else {
active_proc->proc_done_cnt++;
LOG_DBG("Conn %p broadcast code set (%zu/%zu done)", (void *)conn,
active_proc->proc_done_cnt, active_proc->proc_cnt);
}
if (bt_cap_common_proc_is_aborted()) {
if (bt_cap_common_proc_all_handled()) {
cap_commander_proc_complete();
}
return;
}
if (!bt_cap_common_proc_is_done()) {
struct bt_cap_commander_proc_param *proc_param;
proc_param = &active_proc->proc_param.commander[active_proc->proc_done_cnt];
conn = proc_param->conn;
active_proc->proc_initiated_cnt++;
err = bt_bap_broadcast_assistant_set_broadcast_code(
conn, proc_param->distribute_broadcast_code.src_id,
proc_param->distribute_broadcast_code.broadcast_code);
if (err != 0) {
LOG_DBG("Failed to perform set broadcast code for conn %p: %d",
(void *)conn, err);
bt_cap_common_abort_proc(conn, err);
cap_commander_proc_complete();
}
} else {
cap_commander_proc_complete();
}
}
static bool valid_distribute_broadcast_code_param(
const struct bt_cap_commander_distribute_broadcast_code_param *param)
{
CHECKIF(param == NULL) {
LOG_DBG("param is NULL");
return false;
}
CHECKIF(param->count == 0) {
LOG_DBG("Invalid param->count: %zu", param->count);
return false;
}
CHECKIF(param->count > CONFIG_BT_MAX_CONN) {
LOG_DBG("param->count (%zu) is larger than CONFIG_BT_MAX_CONN (%d)", param->count,
CONFIG_BT_MAX_CONN);
return false;
}
CHECKIF(param->param == NULL) {
LOG_DBG("param->param is NULL");
return false;
}
for (size_t i = 0; i < param->count; i++) {
const union bt_cap_set_member *member = &param->param[i].member;
const struct bt_conn *member_conn =
bt_cap_common_get_member_conn(param->type, member);
if (member == NULL) {
LOG_DBG("param->param[%zu].member is NULL", i);
return false;
}
if (member_conn == NULL) {
LOG_DBG("Invalid param->param[%zu].member", i);
return false;
}
for (size_t j = 0U; j < i; j++) {
const union bt_cap_set_member *other = &param->param[j].member;
const struct bt_conn *other_conn =
bt_cap_common_get_member_conn(param->type, other);
if (other_conn == member_conn) {
LOG_DBG("param->param[%zu].member.member (%p) is duplicated by "
"param->member[%zu].member.member (%p)",
j, (void *)other_conn, i, (void *)member_conn);
return false;
}
}
}
return true;
}
int bt_cap_commander_distribute_broadcast_code( int bt_cap_commander_distribute_broadcast_code(
const struct bt_cap_commander_distribute_broadcast_code_param *param) const struct bt_cap_commander_distribute_broadcast_code_param *param)
{ {
return -ENOSYS; struct bt_cap_commander_proc_param *proc_param;
struct bt_cap_common_proc *active_proc;
struct bt_conn *conn;
int err;
if (bt_cap_common_proc_is_active()) {
LOG_DBG("A CAP procedure is already in progress");
return -EBUSY;
}
if (!valid_distribute_broadcast_code_param(param)) {
return -EINVAL;
}
bt_cap_common_start_proc(BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE, param->count);
broadcast_assistant_cb.broadcast_code =
cap_commander_broadcast_assistant_set_broadcast_code_cb;
if (!broadcast_assistant_cb_registered &&
cap_commander_register_broadcast_assistant_cb() != 0) {
LOG_DBG("Failed to register broadcast assistant callbacks");
return -ENOEXEC;
}
active_proc = bt_cap_common_get_active_proc();
for (size_t i = 0U; i < param->count; i++) {
const struct bt_cap_commander_distribute_broadcast_code_member_param *member_param =
&param->param[i];
struct bt_cap_commander_proc_param *stored_param;
struct bt_conn *member_conn =
bt_cap_common_get_member_conn(param->type, &member_param->member);
if (member_conn == NULL) {
LOG_DBG("Invalid param->member[%zu]", i);
return -EINVAL;
}
/* Store the necessary parameters as we cannot assume that the
* supplied parameters are kept valid
*/
stored_param = &active_proc->proc_param.commander[i];
stored_param->conn = member_conn;
stored_param->distribute_broadcast_code.src_id = member_param->src_id;
memcpy(stored_param->distribute_broadcast_code.broadcast_code,
param->broadcast_code, BT_ISO_BROADCAST_CODE_SIZE);
}
active_proc->proc_initiated_cnt++;
proc_param = &active_proc->proc_param.commander[0];
conn = proc_param->conn;
err = bt_bap_broadcast_assistant_set_broadcast_code(
conn, proc_param->distribute_broadcast_code.src_id,
proc_param->distribute_broadcast_code.broadcast_code);
if (err != 0) {
LOG_DBG("Failed to start distribute broadcast code for conn %p: %d", (void *)conn,
err);
return -ENOEXEC;
}
return 0;
} }
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
@ -740,6 +915,11 @@ static void cap_commander_proc_complete(void)
cap_cb->broadcast_reception_stop(failed_conn, err); cap_cb->broadcast_reception_stop(failed_conn, err);
} }
break; break;
case BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE:
if (cap_cb->distribute_broadcast_code != NULL) {
cap_cb->distribute_broadcast_code(failed_conn, err);
}
break;
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
case BT_CAP_COMMON_PROC_TYPE_NONE: case BT_CAP_COMMON_PROC_TYPE_NONE:
default: default:

View file

@ -164,6 +164,7 @@ static bool active_proc_is_commander(void)
case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE: case BT_CAP_COMMON_PROC_TYPE_MICROPHONE_MUTE_CHANGE:
case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START: case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START:
case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP: case BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP:
case BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE:
return true; return true;
default: default:
return false; return false;

View file

@ -51,6 +51,7 @@ enum bt_cap_common_proc_type {
BT_CAP_COMMON_PROC_TYPE_STOP, BT_CAP_COMMON_PROC_TYPE_STOP,
BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START, BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_START,
BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP, BT_CAP_COMMON_PROC_TYPE_BROADCAST_RECEPTION_STOP,
BT_CAP_COMMON_PROC_TYPE_DISTRIBUTE_BROADCAST_CODE,
BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE, BT_CAP_COMMON_PROC_TYPE_VOLUME_CHANGE,
BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE, BT_CAP_COMMON_PROC_TYPE_VOLUME_OFFSET_CHANGE,
BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE, BT_CAP_COMMON_PROC_TYPE_VOLUME_MUTE_CHANGE,
@ -109,6 +110,18 @@ struct cap_broadcast_reception_stop {
uint8_t num_subgroups; uint8_t num_subgroups;
struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
}; };
/* Note that although the broadcast_code will be the same for all
* we nevertheless store a separate copy for each sink, for
* consistensy in the struct bt_cap_commander_proc_param
* There is no memory savings by not having broadcast_code part of the
* union: struct cap_broadcast_reception_start uses minimum 20 bytes
* and struct cap_distribute_broadcast_code uses 17 bytes
*/
struct cap_distribute_broadcast_code {
uint8_t src_id;
uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE];
};
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
struct bt_cap_commander_proc_param { struct bt_cap_commander_proc_param {
@ -131,6 +144,7 @@ struct bt_cap_commander_proc_param {
#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) #if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT)
struct cap_broadcast_reception_start broadcast_reception_start; struct cap_broadcast_reception_start broadcast_reception_start;
struct cap_broadcast_reception_stop broadcast_reception_stop; struct cap_broadcast_reception_stop broadcast_reception_stop;
struct cap_distribute_broadcast_code distribute_broadcast_code;
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
#if defined(CONFIG_BT_MICP_MIC_CTLR) #if defined(CONFIG_BT_MICP_MIC_CTLR)
struct { struct {

View file

@ -19,4 +19,5 @@ target_sources(testbinary
src/test_vcp.c src/test_vcp.c
src/test_micp.c src/test_micp.c
src/test_broadcast_reception.c src/test_broadcast_reception.c
src/test_distribute_broadcast_code.c
) )

View file

@ -25,5 +25,6 @@ DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_stop_cb, struct bt_conn *, int); DECLARE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_stop_cb, struct bt_conn *, int);
DECLARE_FAKE_VOID_FUNC(mock_cap_commander_distribute_broadcast_code_cb, struct bt_conn *, int);
#endif /* MOCKS_CAP_COMMANDER_H_ */ #endif /* MOCKS_CAP_COMMANDER_H_ */

View file

@ -6,6 +6,9 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#define BROADCAST_CODE "BroadcastCode"
#define RANDOM_SRC_ID 0x55
void test_mocks_init(void); void test_mocks_init(void);
void test_mocks_cleanup(void); void test_mocks_cleanup(void);

View file

@ -0,0 +1,257 @@
/* test_distribute_broadcast_code.c - unit test for distribute broadcast code */
/*
* Copyright (c) 2024 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdlib.h>
#include <zephyr/bluetooth/audio/cap.h>
#include <zephyr/fff.h>
#include "bluetooth.h"
#include "cap_commander.h"
#include "conn.h"
#include "expects_util.h"
#include "cap_mocks.h"
#include "test_common.h"
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(bt_distribute_broadcast_code, CONFIG_BT_CAP_COMMANDER_LOG_LEVEL);
#define FFF_GLOBALS
struct cap_commander_test_distribute_broadcast_code_fixture {
struct bt_conn conns[CONFIG_BT_MAX_CONN];
struct bt_bap_bass_subgroup subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS];
struct bt_cap_commander_broadcast_reception_start_member_param
start_member_params[CONFIG_BT_MAX_CONN];
struct bt_cap_commander_broadcast_reception_start_param start_param;
struct bt_cap_commander_distribute_broadcast_code_member_param
broadcast_code_member_params[CONFIG_BT_MAX_CONN];
struct bt_cap_commander_distribute_broadcast_code_param distribute_broadcast_code_param;
struct bt_bap_broadcast_assistant_cb broadcast_assistant_cb;
};
static void cap_commander_test_distribute_broadcast_code_fixture_init(
struct cap_commander_test_distribute_broadcast_code_fixture *fixture)
{
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
test_conn_init(&fixture->conns[i]);
fixture->conns[i].index = i;
}
fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_AD_HOC;
fixture->distribute_broadcast_code_param.param = fixture->broadcast_code_member_params;
fixture->distribute_broadcast_code_param.count =
ARRAY_SIZE(fixture->broadcast_code_member_params);
memcpy(fixture->distribute_broadcast_code_param.broadcast_code, BROADCAST_CODE,
sizeof(BROADCAST_CODE));
for (size_t i = 0; i < ARRAY_SIZE(fixture->broadcast_code_member_params); i++) {
fixture->broadcast_code_member_params[i].member.member = &fixture->conns[i];
fixture->broadcast_code_member_params[i].src_id = RANDOM_SRC_ID;
}
}
static void *cap_commander_test_distribute_broadcast_code_setup(void)
{
struct cap_commander_test_distribute_broadcast_code_fixture *fixture;
fixture = malloc(sizeof(*fixture));
zassert_not_null(fixture);
return fixture;
}
static void cap_commander_test_distribute_broadcast_code_before(void *f)
{
int err;
struct cap_commander_test_distribute_broadcast_code_fixture *fixture = f;
memset(f, 0, sizeof(struct cap_commander_test_distribute_broadcast_code_fixture));
cap_commander_test_distribute_broadcast_code_fixture_init(fixture);
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
err = bt_cap_commander_discover(&fixture->conns[i]);
zassert_equal(0, err, "Unexpected return value %d", err);
}
}
static void cap_commander_test_distribute_broadcast_code_after(void *f)
{
struct cap_commander_test_distribute_broadcast_code_fixture *fixture = f;
bt_cap_commander_unregister_cb(&mock_cap_commander_cb);
bt_bap_broadcast_assistant_unregister_cb(&fixture->broadcast_assistant_cb);
/* We need to cleanup since the CAP commander remembers state */
bt_cap_commander_cancel();
for (size_t i = 0; i < ARRAY_SIZE(fixture->conns); i++) {
mock_bt_conn_disconnected(&fixture->conns[i], BT_HCI_ERR_REMOTE_USER_TERM_CONN);
}
}
static void cap_commander_test_distribute_broadcast_code_teardown(void *f)
{
free(f);
}
static void test_distribute_broadcast_code(
struct bt_cap_commander_distribute_broadcast_code_param *distribute_broadcast_code_param)
{
int err;
err = bt_cap_commander_distribute_broadcast_code(distribute_broadcast_code_param);
zassert_equal(0, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 1,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
zassert_equal_ptr(NULL,
mock_cap_commander_distribute_broadcast_code_cb_fake.arg0_history[0]);
zassert_equal(0, mock_cap_commander_distribute_broadcast_code_cb_fake.arg1_history[0]);
}
ZTEST_SUITE(cap_commander_test_distribute_broadcast_code, NULL,
cap_commander_test_distribute_broadcast_code_setup,
cap_commander_test_distribute_broadcast_code_before,
cap_commander_test_distribute_broadcast_code_after,
cap_commander_test_distribute_broadcast_code_teardown);
ZTEST_F(cap_commander_test_distribute_broadcast_code, test_commander_distribute_broadcast_code)
{
int err;
err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
zassert_equal(0, err, "Unexpected return value %d", err);
test_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_reception_distribute_broadcast_code_double)
{
int err;
err = bt_cap_commander_register_cb(&mock_cap_commander_cb);
zassert_equal(0, err, "Unexpected return value %d", err);
test_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
/*
* We can not use test_distribute_broadcast_code because of the check on how often the
* callback function is called
*/
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(0, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 2,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
zassert_equal_ptr(NULL,
mock_cap_commander_distribute_broadcast_code_cb_fake.arg0_history[1]);
zassert_equal(0, mock_cap_commander_distribute_broadcast_code_cb_fake.arg1_history[1]);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_reception_distribute_broadcast_code_param_null)
{
int err;
err = bt_cap_commander_distribute_broadcast_code(NULL);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_param_zero_count)
{
int err;
fixture->distribute_broadcast_code_param.count = 0;
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_param_high_count)
{
int err;
fixture->distribute_broadcast_code_param.count = CONFIG_BT_MAX_CONN + 1;
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.broadcast_distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_inval_param_null_param)
{
int err;
fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_AD_HOC;
fixture->distribute_broadcast_code_param.param = NULL;
fixture->distribute_broadcast_code_param.count = ARRAY_SIZE(fixture->conns);
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_inval_null_member)
{
int err;
fixture->distribute_broadcast_code_param.param[0].member.member = NULL;
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_inval_missing_cas)
{
int err;
fixture->distribute_broadcast_code_param.type = BT_CAP_SET_TYPE_CSIP;
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}
ZTEST_F(cap_commander_test_distribute_broadcast_code,
test_commander_distribute_broadcast_code_double_conn)
{
int err;
for (size_t i = 0; i < ARRAY_SIZE(fixture->broadcast_code_member_params); i++) {
fixture->broadcast_code_member_params[i].member.member = &fixture->conns[0];
}
err = bt_cap_commander_distribute_broadcast_code(&fixture->distribute_broadcast_code_param);
zassert_equal(-EINVAL, err, "Unexpected return value %d", err);
zexpect_call_count("bt_cap_commander_cb.distribute_broadcast_code", 0,
mock_cap_commander_distribute_broadcast_code_cb_fake.call_count);
}

View file

@ -5,6 +5,7 @@
*/ */
#include "zephyr/bluetooth/audio/bap.h" #include "zephyr/bluetooth/audio/bap.h"
#include "test_common.h"
static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs); static sys_slist_t broadcast_assistant_cbs = SYS_SLIST_STATIC_INIT(&broadcast_assistant_cbs);
@ -176,3 +177,29 @@ int bt_bap_broadcast_assistant_rem_src(struct bt_conn *conn, uint8_t src_id)
return 0; return 0;
} }
int bt_bap_broadcast_assistant_set_broadcast_code(
struct bt_conn *conn, uint8_t src_id,
const uint8_t broadcast_code[BT_ISO_BROADCAST_CODE_SIZE])
{
struct bap_broadcast_assistant_instance *inst;
struct bt_bap_broadcast_assistant_cb *listener, *next;
int err;
zassert_not_null(conn, "conn is NULL");
inst = inst_by_conn(conn);
zassert_equal(src_id, RANDOM_SRC_ID, "Invalid src_id");
err = strncmp((const char *)broadcast_code, BROADCAST_CODE, sizeof(BROADCAST_CODE));
zassert_equal(0, err, "Unexpected broadcast code");
SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&broadcast_assistant_cbs, listener, next, _node) {
if (listener->broadcast_code != NULL) {
listener->broadcast_code(conn, 0);
}
}
return 0;
}

View file

@ -17,7 +17,8 @@
FAKE(mock_cap_commander_microphone_mute_changed_cb) \ FAKE(mock_cap_commander_microphone_mute_changed_cb) \
FAKE(mock_cap_commander_microphone_gain_changed_cb) \ FAKE(mock_cap_commander_microphone_gain_changed_cb) \
FAKE(mock_cap_commander_broadcast_reception_start_cb) \ FAKE(mock_cap_commander_broadcast_reception_start_cb) \
FAKE(mock_cap_commander_broadcast_reception_stop_cb) FAKE(mock_cap_commander_broadcast_reception_stop_cb) \
FAKE(mock_cap_commander_distribute_broadcast_code_cb)
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int, DEFINE_FAKE_VOID_FUNC(mock_cap_commander_discovery_complete_cb, struct bt_conn *, int,
const struct bt_csip_set_coordinator_set_member *, const struct bt_csip_set_coordinator_set_member *,
@ -30,6 +31,7 @@ DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_mute_changed_cb, struct bt_c
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_microphone_gain_changed_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_start_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_stop_cb, struct bt_conn *, int); DEFINE_FAKE_VOID_FUNC(mock_cap_commander_broadcast_reception_stop_cb, struct bt_conn *, int);
DEFINE_FAKE_VOID_FUNC(mock_cap_commander_distribute_broadcast_code_cb, struct bt_conn *, int);
const struct bt_cap_commander_cb mock_cap_commander_cb = { const struct bt_cap_commander_cb mock_cap_commander_cb = {
.discovery_complete = mock_cap_commander_discovery_complete_cb, .discovery_complete = mock_cap_commander_discovery_complete_cb,
@ -49,6 +51,7 @@ const struct bt_cap_commander_cb mock_cap_commander_cb = {
#if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT) #if defined(CONFIG_BT_BAP_BROADCAST_ASSISTANT)
.broadcast_reception_start = mock_cap_commander_broadcast_reception_start_cb, .broadcast_reception_start = mock_cap_commander_broadcast_reception_start_cb,
.broadcast_reception_stop = mock_cap_commander_broadcast_reception_stop_cb, .broadcast_reception_stop = mock_cap_commander_broadcast_reception_stop_cb,
.distribute_broadcast_code = mock_cap_commander_distribute_broadcast_code_cb,
#endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */ #endif /* CONFIG_BT_BAP_BROADCAST_ASSISTANT */
}; };