Skip to content

Commit

Permalink
Bluetooth: Audio: Add helpers for broadcast name
Browse files Browse the repository at this point in the history
Added helper functions to set and get broadcast name
for codec capabilities and codec configs.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
  • Loading branch information
Thalley authored and carlescufi committed Oct 23, 2024
1 parent 67db7fb commit fb6c442
Show file tree
Hide file tree
Showing 4 changed files with 247 additions and 2 deletions.
8 changes: 8 additions & 0 deletions doc/releases/release-notes-4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@ Bluetooth
* :c:func:`bt_audio_codec_cap_meta_get_assisted_listening_stream`
* :c:func:`bt_audio_codec_cap_meta_set_assisted_listening_stream`

* Added APIs for getting and setting the broadcast name in codec capabilities
and codec configuration:

* :c:func:`bt_audio_codec_cfg_meta_get_broadcast_name`
* :c:func:`bt_audio_codec_cfg_meta_set_broadcast_name`
* :c:func:`bt_audio_codec_cap_meta_get_broadcast_name`
* :c:func:`bt_audio_codec_cap_meta_set_broadcast_name`

* Host

* Added API :c:func:`bt_gatt_get_uatt_mtu` to get current Unenhanced ATT MTU of a given
Expand Down
66 changes: 64 additions & 2 deletions include/zephyr/bluetooth/audio/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -496,11 +496,14 @@ enum bt_audio_metadata_type {
*/
BT_AUDIO_METADATA_TYPE_ASSISTED_LISTENING_STREAM = 0x0A,

/** UTF-8 encoded Broadcast name */
BT_AUDIO_METADATA_TYPE_BROADCAST_NAME = 0x0B,

/** Extended metadata */
BT_AUDIO_METADATA_TYPE_EXTENDED = 0xFE,
BT_AUDIO_METADATA_TYPE_EXTENDED = 0xFE,

/** Vendor specific metadata */
BT_AUDIO_METADATA_TYPE_VENDOR = 0xFF,
BT_AUDIO_METADATA_TYPE_VENDOR = 0xFF,
};

/**
Expand Down Expand Up @@ -1367,6 +1370,36 @@ int bt_audio_codec_cfg_meta_get_assisted_listening_stream(
int bt_audio_codec_cfg_meta_set_assisted_listening_stream(
struct bt_audio_codec_cfg *codec_cfg, enum bt_audio_assisted_listening_stream val);

/**
* @brief Extract broadcast name
*
* See @ref BT_AUDIO_METADATA_TYPE_BROADCAST_NAME for more information about this value.
*
* @param[in] codec_cfg The codec data to search in.
* @param[out] broadcast_name Pointer to the UTF-8 formatted broadcast name.
*
* @retval length The length of the @p broadcast_name (may be 0)
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
*/
int bt_audio_codec_cfg_meta_get_broadcast_name(const struct bt_audio_codec_cfg *codec_cfg,
const uint8_t **broadcast_name);

/**
* @brief Set the broadcast name of a codec configuration metadata.
*
* @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.
*
* @retval length The data_len of @p codec_cfg on success
* @retval -EINVAL if arguments are invalid
* @retval -ENOMEM if the new value could not set or added due to memory
*/
int bt_audio_codec_cfg_meta_set_broadcast_name(struct bt_audio_codec_cfg *codec_cfg,
const uint8_t *broadcast_name,
size_t broadcast_name_len);

/**
* @brief Extract extended metadata
*
Expand Down Expand Up @@ -1938,6 +1971,35 @@ int bt_audio_codec_cap_meta_get_assisted_listening_stream(
int bt_audio_codec_cap_meta_set_assisted_listening_stream(
struct bt_audio_codec_cap *codec_cap, enum bt_audio_assisted_listening_stream val);

/**
* @brief Extract broadcast name
*
* See @ref BT_AUDIO_METADATA_TYPE_BROADCAST_NAME for more information about this value.
*
* @param[in] codec_cap The codec data to search in.
* @param[out] broadcast_name Pointer to the UTF-8 formatted broadcast name.
*
* @retval length The length of the @p broadcast_name (may be 0)
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
*/
int bt_audio_codec_cap_meta_get_broadcast_name(const struct bt_audio_codec_cap *codec_cap,
const uint8_t **broadcast_name);

/**
* @brief Set the broadcast name of a codec capability metadata.
*
* @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.
*
* @retval length The data_len of @p codec_cap on success
* @retval -EINVAL if arguments are invalid
* @retval -ENOMEM if the new value could not set or added due to memory
*/
int bt_audio_codec_cap_meta_set_broadcast_name(struct bt_audio_codec_cap *codec_cap,
const uint8_t *broadcast_name,
size_t broadcast_name_len);
/**
* @brief Extract extended metadata
*
Expand Down
97 changes: 97 additions & 0 deletions subsys/bluetooth/audio/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1102,6 +1102,49 @@ static int codec_meta_set_assisted_listening_stream(uint8_t meta[], size_t meta_
sizeof(val_u8));
}

static int codec_meta_get_broadcast_name(const uint8_t meta[], size_t meta_len,
const uint8_t **broadcast_name)
{
const uint8_t *data;
int ret;

CHECKIF(meta == NULL) {
LOG_DBG("meta is NULL");
return -EINVAL;
}

CHECKIF(broadcast_name == NULL) {
LOG_DBG("broadcast_name is NULL");
return -EINVAL;
}

ret = codec_meta_get_val(meta, meta_len, BT_AUDIO_METADATA_TYPE_BROADCAST_NAME, &data);
if (data == NULL) {
return -ENODATA;
}

*broadcast_name = data;

return ret;
}

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)
{
CHECKIF(meta == NULL) {
LOG_DBG("meta is NULL");
return -EINVAL;
}

CHECKIF(broadcast_name == NULL) {
LOG_DBG("broadcast_name is NULL");
return -EINVAL;
}

return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_BROADCAST_NAME,
broadcast_name, broadcast_name_len);
}

static int codec_meta_get_extended(const uint8_t meta[], size_t meta_len,
const uint8_t **extended_meta)
{
Expand Down Expand Up @@ -1547,6 +1590,33 @@ int bt_audio_codec_cfg_meta_set_vendor(struct bt_audio_codec_cfg *codec_cfg,

return ret;
}

int bt_audio_codec_cfg_meta_get_broadcast_name(const struct bt_audio_codec_cfg *codec_cfg,
const uint8_t **broadcast_name)
{
CHECKIF(codec_cfg == NULL) {
LOG_DBG("codec_cfg is NULL");
return -EINVAL;
}

return codec_meta_get_broadcast_name(codec_cfg->meta, codec_cfg->meta_len, broadcast_name);
}

int bt_audio_codec_cfg_meta_set_broadcast_name(struct bt_audio_codec_cfg *codec_cfg,
const uint8_t *broadcast_name,
size_t broadcast_name_len)
{
int ret;

ret = codec_meta_set_broadcast_name(codec_cfg->meta, codec_cfg->meta_len,
ARRAY_SIZE(codec_cfg->meta), broadcast_name,
broadcast_name_len);
if (ret >= 0) {
codec_cfg->meta_len = ret;
}

return ret;
}
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 */

#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0
Expand Down Expand Up @@ -1900,6 +1970,33 @@ int bt_audio_codec_cap_meta_set_vendor(struct bt_audio_codec_cap *codec_cap,

return ret;
}

int bt_audio_codec_cap_meta_get_broadcast_name(const struct bt_audio_codec_cap *codec_cap,
const uint8_t **broadcast_name)
{
CHECKIF(codec_cap == NULL) {
LOG_DBG("codec_cap is NULL");
return -EINVAL;
}

return codec_meta_get_broadcast_name(codec_cap->meta, codec_cap->meta_len, broadcast_name);
}

int bt_audio_codec_cap_meta_set_broadcast_name(struct bt_audio_codec_cap *codec_cap,
const uint8_t *broadcast_name,
size_t broadcast_name_len)
{
int ret;

ret = codec_meta_set_broadcast_name(codec_cap->meta, codec_cap->meta_len,
ARRAY_SIZE(codec_cap->meta), broadcast_name,
broadcast_name_len);
if (ret >= 0) {
codec_cap->meta_len = ret;
}

return ret;
}
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 */
#endif /* CONFIG_BT_AUDIO_CODEC_CFG_MAX_METADATA_SIZE > 0 || \
* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 \
Expand Down
78 changes: 78 additions & 0 deletions tests/bluetooth/audio/codec/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,45 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_assisted_listenin
zassert_equal(ret, 0x00, "Unexpected return value %d", ret);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_broadcast_name)
{
const uint8_t expected_data[] = {'m', 'y', ' ', 'b', 'c', 'a', 's', 't'};
const 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')});
const uint8_t *broadcast_name;
int ret;

ret = bt_audio_codec_cfg_meta_get_broadcast_name(&codec_cfg, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, broadcast_name, ARRAY_SIZE(expected_data));
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_broadcast_name)
{
const uint8_t expected_data[] = {'m', 'y', ' ', 'b', 'c', 'a', 's', 't'};
const uint8_t new_expected_data[] = {'n', 'e', 'w', ' ', 'b', 'c', 'a', 's', 't'};
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')});
const uint8_t *broadcast_name;
int ret;

ret = bt_audio_codec_cfg_meta_get_broadcast_name(&codec_cfg, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, broadcast_name, ARRAY_SIZE(expected_data));

ret = bt_audio_codec_cfg_meta_set_broadcast_name(&codec_cfg, new_expected_data,
ARRAY_SIZE(new_expected_data));
zassert_true(ret > 0, "Unexpected return value %d", ret);

ret = bt_audio_codec_cfg_meta_get_broadcast_name(&codec_cfg, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(new_expected_data, broadcast_name, ARRAY_SIZE(new_expected_data));
}

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 @@ -1873,6 +1912,45 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_assisted_listenin
zassert_equal(ret, 0x00, "Unexpected return value %d", ret);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_broadcast_name)
{
const uint8_t expected_data[] = {'m', 'y', ' ', 'b', 'c', 'a', 's', 't'};
const 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')});
const uint8_t *broadcast_name;
int ret;

ret = bt_audio_codec_cap_meta_get_broadcast_name(&codec_cap, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, broadcast_name, ARRAY_SIZE(expected_data));
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_broadcast_name)
{
const uint8_t expected_data[] = {'m', 'y', ' ', 'b', 'c', 'a', 's', 't'};
const uint8_t new_expected_data[] = {'n', 'e', 'w', ' ', 'b', 'c', 'a', 's', 't'};
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')});
const uint8_t *broadcast_name;
int ret;

ret = bt_audio_codec_cap_meta_get_broadcast_name(&codec_cap, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, broadcast_name, ARRAY_SIZE(expected_data));

ret = bt_audio_codec_cap_meta_set_broadcast_name(&codec_cap, new_expected_data,
ARRAY_SIZE(new_expected_data));
zassert_true(ret > 0, "Unexpected return value %d", ret);

ret = bt_audio_codec_cap_meta_get_broadcast_name(&codec_cap, &broadcast_name);
zassert_equal(ret, ARRAY_SIZE(new_expected_data), "Unexpected return value %d", ret);
zassert_mem_equal(new_expected_data, broadcast_name, ARRAY_SIZE(new_expected_data));
}

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

0 comments on commit fb6c442

Please sign in to comment.