diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index cfa841afb85d..046002318dbf 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -542,7 +542,12 @@ struct bt_cap_initiator_broadcast_create_param { * @param[in] param Parameters to start the audio streams. * @param[out] broadcast_source Pointer to the broadcast source created. * - * @return 0 on success or negative error value on failure. + * @retval 0 Success + * @retval -EINVAL @p param is invalid or @p broadcast_source is NULL + * @retval -ENOMEM Could not allocate more broadcast sources, subgroups or ISO streams, or the + * provided codec configuration data is too large when merging the BIS and subgroup + * configuration data. + * @retval -ENOEXEC The broadcast source failed to be created for other reasons */ int bt_cap_initiator_broadcast_audio_create( const struct bt_cap_initiator_broadcast_create_param *param, diff --git a/subsys/bluetooth/audio/cap_initiator.c b/subsys/bluetooth/audio/cap_initiator.c index 92716c84c24a..849cc99ed147 100644 --- a/subsys/bluetooth/audio/cap_initiator.c +++ b/subsys/bluetooth/audio/cap_initiator.c @@ -228,6 +228,7 @@ int bt_cap_initiator_broadcast_audio_create( struct bt_bap_broadcast_source_stream_param bap_stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; struct bt_bap_broadcast_source_param bap_create_param = {0}; + int err; CHECKIF(param == NULL) { LOG_DBG("param is NULL"); @@ -243,6 +244,7 @@ int bt_cap_initiator_broadcast_audio_create( return -EINVAL; } + *broadcast_source = NULL; for (size_t i = 0; i < ARRAY_SIZE(broadcast_sources); i++) { if (broadcast_sources[i].bap_broadcast == NULL) { *broadcast_source = &broadcast_sources[i]; @@ -250,11 +252,28 @@ int bt_cap_initiator_broadcast_audio_create( } } + if (*broadcast_source == NULL) { + LOG_DBG("Failed to allocate a new broadcast source"); + return -ENOMEM; + } + cap_initiator_broadcast_to_bap_broadcast_param(param, &bap_create_param, bap_subgroup_params, bap_stream_params); - return bt_bap_broadcast_source_create(&bap_create_param, - &(*broadcast_source)->bap_broadcast); + err = bt_bap_broadcast_source_create(&bap_create_param, + &(*broadcast_source)->bap_broadcast); + if (err != 0) { + /* Return known errors */ + if (err == -EINVAL || err == -ENOMEM) { + return err; + } + + LOG_DBG("Unexpected error from bt_bap_broadcast_source_create: %d", err); + + return -ENOEXEC; + } + + return 0; } static struct bt_cap_broadcast_source *get_cap_broadcast_source_by_bap_broadcast_source( diff --git a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c index c84fc83742ff..369a9544f54e 100644 --- a/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c +++ b/tests/bsim/bluetooth/audio/src/cap_initiator_broadcast_test.c @@ -299,7 +299,7 @@ static void test_broadcast_audio_create_inval(void) stream_params[ARRAY_SIZE(broadcast_source_streams)]; struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; struct bt_cap_initiator_broadcast_create_param create_param; - struct bt_cap_broadcast_source *broadcast_source; + struct bt_cap_broadcast_source *broadcast_sources[CONFIG_BT_BAP_BROADCAST_SRC_COUNT + 1]; struct bt_audio_codec_cfg invalid_codec = BT_AUDIO_CODEC_LC3_CONFIG( BT_AUDIO_CODEC_CFG_FREQ_16KHZ, BT_AUDIO_CODEC_CFG_DURATION_10, BT_AUDIO_LOCATION_FRONT_LEFT, 40U, 1, BT_AUDIO_CONTEXT_TYPE_MEDIA); @@ -323,7 +323,7 @@ static void test_broadcast_audio_create_inval(void) create_param.encryption = false; /* Test NULL parameters */ - err = bt_cap_initiator_broadcast_audio_create(NULL, &broadcast_source); + err = bt_cap_initiator_broadcast_audio_create(NULL, &broadcast_sources[0]); if (err == 0) { FAIL("bt_cap_initiator_broadcast_audio_create with NULL param did not fail\n"); return; @@ -345,6 +345,38 @@ static void test_broadcast_audio_create_inval(void) "fail\n"); return; } + subgroup_param.codec_cfg = &broadcast_preset_16_2_1.codec_cfg; + + /* Test allocating too many sources */ + ARRAY_FOR_EACH(broadcast_sources, i) { + err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_sources[i]); + if (i < CONFIG_BT_BAP_BROADCAST_SRC_COUNT) { + if (err != 0) { + FAIL("[%zu]: bt_cap_initiator_broadcast_audio_create failed: %d\n", + i, err); + return; + } + } else { + if (err != -ENOMEM) { + FAIL("bt_cap_initiator_broadcast_audio_create did not fail with " + "-ENOMEM when allocating too many sources: %d\n", + err); + return; + } + } + } + + /* Cleanup the created broadcast sources */ + ARRAY_FOR_EACH(broadcast_sources, i) { + if (i < CONFIG_BT_BAP_BROADCAST_SRC_COUNT) { + err = bt_cap_initiator_broadcast_audio_delete(broadcast_sources[i]); + if (err != 0) { + FAIL("[%zu]: bt_cap_initiator_broadcast_audio_delete failed: %d\n", + i, err); + return; + } + } + } /* Since we are just casting the CAP parameters to BAP parameters, * we can rely on the BAP tests to verify the values