Bluetooth: Audio: Change lang to 3-byte value from uint32_t

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 <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2024-05-10 16:42:57 +02:00 committed by Anas Nashif
commit be307f8ad9
8 changed files with 96 additions and 65 deletions

View file

@ -514,6 +514,16 @@ Bluetooth Audio
(:github:`72584`)
* 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. (:github:`72584`)
* All occurrences of ``set_sirk`` have been changed to just ``sirk`` as the ``s`` in ``sirk`` stands
for set. (:github:`73413`)

View file

@ -48,6 +48,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
*
@ -383,6 +386,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,
@ -1254,14 +1258,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.
@ -1273,7 +1279,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
*
@ -1776,14 +1783,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.
@ -1795,7 +1804,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
*

View file

@ -2113,7 +2113,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;

View file

@ -804,7 +804,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;
@ -814,36 +814,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,
@ -1255,17 +1259,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;
@ -1581,17 +1587,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;

View file

@ -373,14 +373,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,
@ -732,9 +729,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);
@ -968,9 +965,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);

View file

@ -2000,17 +2000,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;
}

View file

@ -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)
@ -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)

View file

@ -66,7 +66,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;
}