Skip to content

Commit

Permalink
Bluetooth: Audio: Change lang to 3-byte value from uint32_t
Browse files Browse the repository at this point in the history
The 3-byte value suits the assigned number much better,
and also allows for less memory copies when getting and
setting the values.

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Jun 3, 2024
1 parent 28cd518 commit 7c8b771
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 65 deletions.
9 changes: 9 additions & 0 deletions doc/releases/migration-guide-3.7.rst
Original file line number Diff line number Diff line change
Expand Up @@ -454,6 +454,15 @@ Bluetooth Audio
:c:func:`bt_audio_codec_cfg_meta_set_lang`
:c:func:`bt_audio_codec_cfg_meta_get_lang`

* Changed ``lang`` from ``uint32_t`` to ``uint8_t [3]``. This modifies the following functions
- :c:func:`bt_audio_codec_cap_meta_set_lang`
- :c:func:`bt_audio_codec_cap_meta_get_lang`
- :c:func:`bt_audio_codec_cfg_meta_set_lang`
- :c:func:`bt_audio_codec_cfg_meta_get_lang`

The result of this is that string values such as ``"eng"`` and ``"deu"`` can now be used to set
new values, and to prevent unnecessary copies of data when getting the values.

* All occurrences of ``set_sirk`` have been changed to just ``sirk`` as the ``s`` in ``sirk`` stands
for set. (:github:`73413`)

Expand Down
24 changes: 17 additions & 7 deletions include/zephyr/bluetooth/audio/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ extern "C" {

#define BT_AUDIO_BROADCAST_CODE_SIZE 16

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

/**
* @brief Codec capability types
*
Expand Down Expand Up @@ -376,6 +379,7 @@ enum bt_audio_metadata_type {
/** @brief Language
*
* 3 octet lower case language code defined by ISO 639-3
* Possible values can be found at https://iso639-3.sil.org/code_tables/639/data
*/
BT_AUDIO_METADATA_TYPE_LANG = 0x04,

Expand Down Expand Up @@ -1212,14 +1216,16 @@ int bt_audio_codec_cfg_meta_set_program_info(struct bt_audio_codec_cfg *codec_cf
*
* See @ref BT_AUDIO_METADATA_TYPE_LANG for more information about this value.
*
* @param codec_cfg The codec data to search in.
* @param[in] codec_cfg The codec data to search in.
* @param[out] lang Pointer to the language bytes (of length BT_AUDIO_LANG_SIZE)
*
* @retval The language if positive or 0
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
* @retval -EBADMSG if found value has invalid size
*/
int bt_audio_codec_cfg_meta_get_lang(const struct bt_audio_codec_cfg *codec_cfg);
int bt_audio_codec_cfg_meta_get_lang(const struct bt_audio_codec_cfg *codec_cfg,
const uint8_t **lang);

/**
* @brief Set the language of a codec configuration metadata.
Expand All @@ -1231,7 +1237,8 @@ int bt_audio_codec_cfg_meta_get_lang(const struct bt_audio_codec_cfg *codec_cfg)
* @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_lang(struct bt_audio_codec_cfg *codec_cfg, uint32_t lang);
int bt_audio_codec_cfg_meta_set_lang(struct bt_audio_codec_cfg *codec_cfg,
const uint8_t lang[BT_AUDIO_LANG_SIZE]);

/** @brief Extract CCID list
*
Expand Down Expand Up @@ -1734,14 +1741,16 @@ int bt_audio_codec_cap_meta_set_program_info(struct bt_audio_codec_cap *codec_ca
*
* See @ref BT_AUDIO_METADATA_TYPE_LANG for more information about this value.
*
* @param codec_cap The codec data to search in.
* @param[in] codec_cap The codec data to search in.
* @param[out] lang Pointer to the language bytes (of length BT_AUDIO_LANG_SIZE)
*
* @retval The language if positive or 0
* @retval 0 On success
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
* @retval -EBADMSG if found value has invalid size
*/
int bt_audio_codec_cap_meta_get_lang(const struct bt_audio_codec_cap *codec_cap);
int bt_audio_codec_cap_meta_get_lang(const struct bt_audio_codec_cap *codec_cap,
const uint8_t **lang);

/**
* @brief Set the language of a codec capability metadata.
Expand All @@ -1753,7 +1762,8 @@ int bt_audio_codec_cap_meta_get_lang(const struct bt_audio_codec_cap *codec_cap)
* @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_lang(struct bt_audio_codec_cap *codec_cap, uint32_t lang);
int bt_audio_codec_cap_meta_set_lang(struct bt_audio_codec_cap *codec_cap,
const uint8_t lang[BT_AUDIO_LANG_SIZE]);

/** @brief Extract CCID list
*
Expand Down
2 changes: 1 addition & 1 deletion subsys/bluetooth/audio/ascs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2098,7 +2098,7 @@ static bool ascs_parse_metadata(struct bt_data *data, void *user_data)
break;
}
case BT_AUDIO_METADATA_TYPE_LANG:
if (data_len != 3) {
if (data_len != BT_AUDIO_LANG_SIZE) {
*result->rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_INVALID,
data_type);
result->err = -EBADMSG;
Expand Down
44 changes: 26 additions & 18 deletions subsys/bluetooth/audio/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,7 @@ static int codec_meta_set_program_info(uint8_t meta[], size_t meta_len, size_t m
program_info, program_info_len);
}

static int codec_meta_get_lang(const uint8_t meta[], size_t meta_len)
static int codec_meta_get_lang(const uint8_t meta[], size_t meta_len, const uint8_t **lang)
{
const uint8_t *data;
int ret;
Expand All @@ -806,36 +806,40 @@ static int codec_meta_get_lang(const uint8_t meta[], size_t meta_len)
return -EINVAL;
}

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

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

if (ret != 3) { /* Language is 3 octets */
if (ret != BT_AUDIO_LANG_SIZE) {
return -EBADMSG;
}

return sys_get_le24(data);
*lang = data;

return 0;
}

static int codec_meta_set_lang(uint8_t meta[], size_t meta_len, size_t meta_size, uint32_t lang)
static int codec_meta_set_lang(uint8_t meta[], size_t meta_len, size_t meta_size,
const uint8_t lang[BT_AUDIO_LANG_SIZE])
{
uint8_t lang_le[3];

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

if ((lang & 0xFFFFFFU) != lang) {
LOG_DBG("Invalid lang value: %d", lang);
CHECKIF(lang == NULL) {
LOG_DBG("lang is NULL");
return -EINVAL;
}

sys_put_le24(lang, lang_le);

return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_LANG, lang_le,
sizeof(lang_le));
return codec_meta_set_val(meta, meta_len, meta_size, BT_AUDIO_METADATA_TYPE_LANG, lang,
BT_AUDIO_LANG_SIZE);
}

static int codec_meta_get_ccid_list(const uint8_t meta[], size_t meta_len,
Expand Down Expand Up @@ -1247,17 +1251,19 @@ int bt_audio_codec_cfg_meta_set_program_info(struct bt_audio_codec_cfg *codec_cf
return ret;
}

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

return codec_meta_get_lang(codec_cfg->meta, codec_cfg->meta_len);
return codec_meta_get_lang(codec_cfg->meta, codec_cfg->meta_len, lang);
}

int bt_audio_codec_cfg_meta_set_lang(struct bt_audio_codec_cfg *codec_cfg, uint32_t lang)
int bt_audio_codec_cfg_meta_set_lang(struct bt_audio_codec_cfg *codec_cfg,
const uint8_t lang[BT_AUDIO_LANG_SIZE])
{
int ret;

Expand Down Expand Up @@ -1573,17 +1579,19 @@ int bt_audio_codec_cap_meta_set_program_info(struct bt_audio_codec_cap *codec_ca
return ret;
}

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

return codec_meta_get_lang(codec_cap->meta, codec_cap->meta_len);
return codec_meta_get_lang(codec_cap->meta, codec_cap->meta_len, lang);
}

int bt_audio_codec_cap_meta_set_lang(struct bt_audio_codec_cap *codec_cap, uint32_t lang)
int bt_audio_codec_cap_meta_set_lang(struct bt_audio_codec_cap *codec_cap,
const uint8_t lang[BT_AUDIO_LANG_SIZE])
{
int ret;

Expand Down
19 changes: 8 additions & 11 deletions subsys/bluetooth/audio/shell/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -361,14 +361,11 @@ static inline void print_codec_meta_program_info(const struct shell *sh, size_t
shell_fprintf(sh, SHELL_NORMAL, "\n");
}

static inline void print_codec_meta_language(const struct shell *sh, size_t indent, uint32_t lang)
static inline void print_codec_meta_language(const struct shell *sh, size_t indent,
const uint8_t lang[BT_AUDIO_LANG_SIZE])
{
uint8_t lang_array[3];

sys_put_be24(lang, lang_array);

shell_print(sh, "%*sLanguage: %c%c%c", indent, "", (char)lang_array[0], (char)lang_array[1],
(char)lang_array[2]);
shell_print(sh, "%*sLanguage: %c%c%c", indent, "", (char)lang[0], (char)lang[1],
(char)lang[2]);
}

static inline void print_codec_meta_ccid_list(const struct shell *sh, size_t indent,
Expand Down Expand Up @@ -720,9 +717,9 @@ static inline void print_codec_cap(const struct shell *sh, size_t indent,
print_codec_meta_program_info(sh, indent, data, (uint8_t)ret);
}

ret = bt_audio_codec_cap_meta_get_lang(codec_cap);
ret = bt_audio_codec_cap_meta_get_lang(codec_cap, &data);
if (ret >= 0) {
print_codec_meta_language(sh, indent, (uint32_t)ret);
print_codec_meta_language(sh, indent, data);
}

ret = bt_audio_codec_cap_meta_get_ccid_list(codec_cap, &data);
Expand Down Expand Up @@ -956,9 +953,9 @@ static inline void print_codec_cfg(const struct shell *sh, size_t indent,
print_codec_meta_program_info(sh, indent, data, (uint8_t)ret);
}

ret = bt_audio_codec_cfg_meta_get_lang(codec_cfg);
ret = bt_audio_codec_cfg_meta_get_lang(codec_cfg, &data);
if (ret >= 0) {
print_codec_meta_language(sh, indent, (uint32_t)ret);
print_codec_meta_language(sh, indent, data);
}

ret = bt_audio_codec_cfg_meta_get_ccid_list(codec_cfg, &data);
Expand Down
8 changes: 3 additions & 5 deletions subsys/bluetooth/audio/shell/bap.c
Original file line number Diff line number Diff line change
Expand Up @@ -1948,17 +1948,15 @@ static ssize_t parse_config_meta_args(const struct shell *sh, size_t argn, size_

arg = argv[argn];

if (strlen(arg) != 3) {
if (strlen(arg) != BT_AUDIO_LANG_SIZE) {
shell_error(sh, "Failed to parse lang from %s", arg);

return -1;
}

val = sys_get_le24(arg);

err = bt_audio_codec_cfg_meta_set_lang(codec_cfg, (uint32_t)val);
err = bt_audio_codec_cfg_meta_set_lang(codec_cfg, arg);
if (err < 0) {
shell_error(sh, "Failed to set lang with value %lu: %d", val, err);
shell_error(sh, "Failed to set lang with value %s: %d", arg, err);

return -1;
}
Expand Down
52 changes: 30 additions & 22 deletions tests/bluetooth/audio/codec/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -517,34 +517,38 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_program_info)

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_lang)
{
const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'});
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_LANG, 'e', 'n', 'g')});
char expected_data[] = "eng";
const uint8_t *lang;
int ret;

ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg);
zassert_equal(ret, expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, lang, BT_AUDIO_LANG_SIZE);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_set_lang)
{
const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'});
const uint32_t new_expected_data = sys_get_le24((uint8_t[]){'d', 'e', 'u'});
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_LANG, 'e', 'n', 'g')});
const uint32_t new_lang = sys_le32_to_cpu(new_expected_data);
char new_expected_data[] = "deu";
char expected_data[] = "eng";
const uint8_t *lang;
int ret;

ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg);
zassert_equal(ret, expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, lang, BT_AUDIO_LANG_SIZE);

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

ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg);
zassert_equal(ret, new_expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cfg_meta_get_lang(&codec_cfg, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(new_expected_data, lang, BT_AUDIO_LANG_SIZE);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cfg_meta_get_ccid_list)
Expand Down Expand Up @@ -1410,34 +1414,38 @@ ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_program_info)

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_lang)
{
const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'});
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_LANG, 'e', 'n', 'g')});
char expected_data[] = "eng";
const uint8_t *lang;
int ret;

ret = bt_audio_codec_cap_meta_get_lang(&codec_cap);
zassert_equal(ret, expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cap_meta_get_lang(&codec_cap, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, lang, BT_AUDIO_LANG_SIZE);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_set_lang)
{
const uint32_t expected_data = sys_get_le24((uint8_t[]){'e', 'n', 'g'});
const uint32_t new_expected_data = sys_get_le24((uint8_t[]){'d', 'e', 'u'});
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_LANG, 'e', 'n', 'g')});
const uint32_t new_lang = sys_le32_to_cpu(new_expected_data);
char new_expected_data[] = "deu";
char expected_data[] = "eng";
const uint8_t *lang;
int ret;

ret = bt_audio_codec_cap_meta_get_lang(&codec_cap);
zassert_equal(ret, expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cap_meta_get_lang(&codec_cap, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(expected_data, lang, BT_AUDIO_LANG_SIZE);

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

ret = bt_audio_codec_cap_meta_get_lang(&codec_cap);
zassert_equal(ret, new_expected_data, "Unexpected return value %d", ret);
ret = bt_audio_codec_cap_meta_get_lang(&codec_cap, &lang);
zassert_equal(ret, 0, "Unexpected return value %d", ret);
zassert_mem_equal(new_expected_data, lang, BT_AUDIO_LANG_SIZE);
}

ZTEST(audio_codec_test_suite, test_bt_audio_codec_cap_meta_get_ccid_list)
Expand Down
2 changes: 1 addition & 1 deletion tests/bsim/bluetooth/audio/src/bap_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ static inline bool valid_metadata_type(uint8_t type, uint8_t len)

return true;
case BT_AUDIO_METADATA_TYPE_LANG:
if (len != 3) {
if (len != BT_AUDIO_LANG_SIZE) {
return false;
}

Expand Down

0 comments on commit 7c8b771

Please sign in to comment.