Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 13 additions & 4 deletions include/zephyr/bluetooth/audio/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,16 @@ extern "C" {
#define BT_AUDIO_PD_MAX 0xFFFFFFU
/** Indicates that the unicast server does not have a preference for any retransmission number */
#define BT_AUDIO_RTN_PREF_NONE 0xFFU
/** The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */
/** The minimum size in octets of a Broadcast Name as defined by Bluetooth Assigned Numbers */
#define BT_AUDIO_BROADCAST_NAME_LEN_MIN 4
/** The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */
/** The maximum size in octets of a Broadcast Name as defined by Bluetooth Assigned Numbers */
#define BT_AUDIO_BROADCAST_NAME_LEN_MAX 128

/** The minimum amount of characters of a Broadcast Name as defined by Bluetooth Assigned Numbers */
#define BT_AUDIO_BROADCAST_NAME_CHAR_MIN 4
/** The maximum amount of characters of a Broadcast Name as defined by Bluetooth Assigned Numbers */
#define BT_AUDIO_BROADCAST_NAME_CHAR_MAX 32

/** Size of the stream language value, e.g. "eng" */
#define BT_AUDIO_LANG_SIZE 3

Expand Down Expand Up @@ -1456,7 +1461,9 @@ int bt_audio_codec_cfg_meta_get_broadcast_name(const struct bt_audio_codec_cfg *
*
* @param codec_cfg The codec configuration to set data for.
* @param broadcast_name The broadcast name to set.
* @param broadcast_name_len The length of @p broadcast_name.
* @param broadcast_name_len The length of @p broadcast_name. Shall be between
* @ref BT_AUDIO_BROADCAST_NAME_LEN_MIN and
* @ref BT_AUDIO_BROADCAST_NAME_LEN_MAX.
*
* @retval data_len The @p codec_cfg.data_len on success
* @retval -EINVAL Arguments are invalid
Expand Down Expand Up @@ -2058,7 +2065,9 @@ int bt_audio_codec_cap_meta_get_broadcast_name(const struct bt_audio_codec_cap *
*
* @param codec_cap The codec capability to set data for.
* @param broadcast_name The broadcast name to set.
* @param broadcast_name_len The length of @p broadcast_name.
* @param broadcast_name_len The length of @p broadcast_name. Shall be between
* @ref BT_AUDIO_BROADCAST_NAME_LEN_MIN and
* @ref BT_AUDIO_BROADCAST_NAME_LEN_MAX.
*
* @retval data_len The @p codec_cap.data_len on success
* @retval -EINVAL Arguments are invalid
Expand Down
4 changes: 4 additions & 0 deletions subsys/bluetooth/audio/Kconfig.bap
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ config BT_BAP_UNICAST_SERVER
depends on BT_ISO_PERIPHERAL
depends on BT_ASCS
depends on BT_BONDABLE
depends on UTF8
select BT_PAC_SRC if BT_ASCS_ASE_SNK
select BT_PAC_SNK if BT_ASCS_ASE_SRC
help
Expand All @@ -30,6 +31,7 @@ config BT_BAP_UNICAST_CLIENT
depends on BT_CENTRAL
depends on BT_ISO_CENTRAL
depends on BT_BONDABLE
depends on UTF8
help
This option enables support for Bluetooth Unicast Audio Client
using Isochronous channels.
Expand Down Expand Up @@ -121,6 +123,7 @@ endif # BT_BAP_UNICAST_CLIENT
config BT_BAP_BROADCAST_SOURCE
bool "Bluetooth Broadcast Source Audio Support"
depends on BT_ISO_BROADCASTER
depends on UTF8
help
This option enables support for Bluetooth Broadcast Source Audio using
Isochronous channels.
Expand Down Expand Up @@ -162,6 +165,7 @@ config BT_BAP_BROADCAST_SINK
depends on BT_PAC_SNK
depends on BT_PERIPHERAL
depends on BT_BAP_SCAN_DELEGATOR
depends on UTF8
help
This option enables support for Bluetooth Broadcast Sink Audio using
Isochronous channels.
Expand Down
22 changes: 21 additions & 1 deletion subsys/bluetooth/audio/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>

#include <zephyr/autoconf.h>
#include <zephyr/bluetooth/audio/audio.h>
Expand Down Expand Up @@ -1057,7 +1058,8 @@ static int codec_meta_get_broadcast_name(const uint8_t meta[], size_t meta_len,
}

ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, &data);
if (data == NULL) {
if (data == NULL ||
!IN_RANGE(ret, BT_AUDIO_BROADCAST_NAME_LEN_MIN, BT_AUDIO_BROADCAST_NAME_LEN_MAX)) {
return -ENODATA;
}

Expand All @@ -1069,6 +1071,9 @@ static int codec_meta_get_broadcast_name(const uint8_t meta[], size_t meta_len,
static int codec_meta_set_broadcast_name(uint8_t meta[], size_t meta_len, size_t meta_size,
const uint8_t *broadcast_name, size_t broadcast_name_len)
{
char broadcast_name_str[BT_AUDIO_BROADCAST_NAME_LEN_MAX + sizeof('\0')];
ssize_t char_cnt;

CHECKIF(meta == NULL) {
LOG_DBG("meta is NULL");
return -EINVAL;
Expand All @@ -1079,6 +1084,21 @@ static int codec_meta_set_broadcast_name(uint8_t meta[], size_t meta_len, size_t
return -EINVAL;
}

if (!IN_RANGE(broadcast_name_len, BT_AUDIO_BROADCAST_NAME_LEN_MIN,
BT_AUDIO_BROADCAST_NAME_LEN_MAX)) {
LOG_DBG("Invalid broadcast name len %zu", broadcast_name_len);
return -EINVAL;
}

(void)memcpy(broadcast_name_str, broadcast_name, broadcast_name_len);
broadcast_name_str[broadcast_name_len] = '\0';
char_cnt = utf8_count_chars(broadcast_name_str);
if (!IN_RANGE(char_cnt, BT_AUDIO_BROADCAST_NAME_CHAR_MIN,
BT_AUDIO_BROADCAST_NAME_CHAR_MAX)) {
LOG_DBG("Invalid broadcast name %s", broadcast_name_str);
return -EINVAL;
}

return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_BROADCAST_NAME,
broadcast_name, broadcast_name_len);
}
Expand Down
1 change: 1 addition & 0 deletions tests/bluetooth/audio/codec/prj.conf
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
CONFIG_ZTEST=y
CONFIG_UTF8=y

CONFIG_BT=y
CONFIG_BT_SMP=y
Expand Down
91 changes: 91 additions & 0 deletions tests/bluetooth/audio/codec/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,66 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_broadcast_name)
zassert_mem_equal(new_expected_data, broadcast_name, ARRAY_SIZE(new_expected_data));
}

static ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_broadcast_name_inval_min_len)
{
const uint8_t new_data[] = {'n', 'e', 'w'};
struct bt_audio_codec_cfg codec_cfg =
BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cfg_meta_set_broadcast_name(&codec_cfg, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

static ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_broadcast_name_inval_max_len)
{
const uint8_t new_data[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'v',
'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 's', 't',
'r', 'i', 'n', 'g', ' ', 't', 'o', ' ', 'r', 'e', 't',
'u', 'r', 'n', ' ', 'e', 'r', 'r', 'o', 'r'};
struct bt_audio_codec_cfg codec_cfg =
BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cfg_meta_set_broadcast_name(&codec_cfg, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

static ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_broadcast_name_inval_utf8)
{
const uint8_t new_data[] = {0x80, 0x80, 0x80, 0x80, 0x80};
struct bt_audio_codec_cfg codec_cfg =
BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cfg_meta_set_broadcast_name(&codec_cfg, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

static ZTEST(audio_codec_test_suite,
test_bt_audio_codec_cfg_meta_set_broadcast_name_inval_char_cnt_min)
{
const uint8_t new_data[] = "𠜎𠜎𠜎𠜎𠜎𠜎"; /* 2 4-octet characters */
struct bt_audio_codec_cfg codec_cfg =
BT_AUDIO_CODEC_CFG(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cfg_meta_set_broadcast_name(&codec_cfg, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_extended)
{
const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03};
Expand Down Expand Up @@ -1950,6 +2010,37 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_broadcast_name)
zassert_mem_equal(new_expected_data, broadcast_name, ARRAY_SIZE(new_expected_data));
}

static ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_broadcast_name_inval_min_len)
{
const uint8_t new_data[] = {'n', 'e', 'w'};
struct bt_audio_codec_cap codec_cap =
BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cap_meta_set_broadcast_name(&codec_cap, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

static ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_broadcast_name_inval_max_len)
{
const uint8_t new_data[] = {'T', 'h', 'i', 's', ' ', 'i', 's', ' ', 'a', ' ', 'v',
'e', 'r', 'y', ' ', 'l', 'o', 'n', 'g', ' ', 's', 't',
'r', 'i', 'n', 'g', ' ', 't', 'o', ' ', 'r', 'e', 't',
'u', 'r', 'n', ' ', 'e', 'r', 'r', 'o', 'r'};
struct bt_audio_codec_cap codec_cap =
BT_AUDIO_CODEC_CAP(BT_HCI_CODING_FORMAT_LC3, 0x0000, 0x0000, {},
{BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, 'm',
'y', ' ', 'b', 'c', 'a', 's', 't')});
int ret;

ret = bt_audio_codec_cap_meta_set_broadcast_name(&codec_cap, new_data,
ARRAY_SIZE(new_data));
zassert_equal(ret, -EINVAL, "Unexpected return value %d", ret);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_extended)
{
const uint8_t expected_data[] = {0x00, 0x01, 0x02, 0x03};
Expand Down
Loading