Bluetooth: Audio: Refactor bt_audio_codec_cap to flat arrays

Refactor the bt_audio_codec_cap to use flat arrays to store
metadata and codec specific capabilities.

The purpose of this is to make it easier to copy the data
between layers, but also to support non-LTV data for non-LC3
codec capabilities.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2023-05-18 17:37:19 +02:00 committed by Fabio Baltieri
commit aa990ae6dc
21 changed files with 356 additions and 351 deletions

View file

@ -199,7 +199,18 @@ struct bt_audio_codec_data {
}
/**
* @brief Helper to declare @ref bt_audio_codec_cfg or @ref bt_audio_codec_cap structure
* @brief Helper to declare elements of bt_audio_codec_cap arrays
*
* This macro is mainly for creating an array of struct bt_audio_codec_cap data arrays.
*
* @param _type Type of advertising data field
* @param _bytes Variable number of single-byte parameters
*/
#define BT_AUDIO_CODEC_CAP_DATA(_type, _bytes...) \
(sizeof((uint8_t)_type) + sizeof((uint8_t[]){_bytes})), (_type), _bytes
/**
* @brief Helper to declare @ref bt_audio_codec_cfg
*
* @param _id Codec ID
* @param _cid Company ID
@ -207,8 +218,8 @@ struct bt_audio_codec_data {
* @param _data Codec Specific Data in LVT format
* @param _meta Codec Specific Metadata in LVT format
*/
#define BT_AUDIO_CODEC(_id, _cid, _vid, _data, _meta) \
{ \
#define BT_AUDIO_CODEC_CFG(_id, _cid, _vid, _data, _meta) \
((struct bt_audio_codec_cfg){ \
/* Use HCI data path as default, can be overwritten by application */ \
.path_id = BT_ISO_DATA_PATH_HCI, \
.id = _id, \
@ -218,7 +229,29 @@ struct bt_audio_codec_data {
.data = _data, \
.meta_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_meta)), \
.meta = _meta, \
}
})
/**
* @brief Helper to declare @ref bt_audio_codec_cap structure
*
* @param _id Codec ID
* @param _cid Company ID
* @param _vid Vendor ID
* @param _data Codec Specific Data in LVT format
* @param _meta Codec Specific Metadata in LVT format
*/
#define BT_AUDIO_CODEC_CAP(_id, _cid, _vid, _data, _meta) \
((struct bt_audio_codec_cap){ \
/* Use HCI data path as default, can be overwritten by application */ \
.path_id = BT_ISO_DATA_PATH_HCI, \
.id = (_id), \
.cid = (_cid), \
.vid = (_vid), \
.data_len = sizeof((uint8_t[])_data), \
.data = _data, \
.meta_len = sizeof((uint8_t[])_meta), \
.meta = _meta, \
})
/** @brief Location values for BT Audio.
*
@ -302,18 +335,18 @@ struct bt_audio_codec_cap {
uint16_t cid;
/** Codec Company Vendor ID */
uint16_t vid;
#if defined(CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT)
#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0
/** Codec Specific Capabilities Data count */
size_t data_count;
size_t data_len;
/** Codec Specific Capabilities Data */
struct bt_audio_codec_data data[CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT];
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT */
#if defined(CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT)
uint8_t data[CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE];
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 */
#if defined(CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE)
/** Codec Specific Capabilities Metadata count */
size_t meta_count;
size_t meta_len;
/** Codec Specific Capabilities Metadata */
struct bt_audio_codec_data meta[CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT];
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT */
uint8_t meta[CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE];
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE */
};
/** @brief Codec specific configuration structure. */

View file

@ -254,38 +254,48 @@ enum bt_audio_codec_config_type {
* If the flags argument is != 1 it will evaluate to the third argument which inserts a LTV
* entry for the max_frames_per_sdu value.
*/
#define BT_AUDIO_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, \
#define BT_AUDIO_CODEC_CAP_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, \
_max_frames_per_sdu) \
{ \
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FREQ, BT_BYTES_LIST_LE16(_freq)), \
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_DURATION, _duration), \
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_CHAN_COUNT, _chan_count), \
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_LEN, \
BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_CODEC_LC3_FREQ, BT_BYTES_LIST_LE16(_freq)), \
BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_CODEC_LC3_DURATION, (_duration)), \
BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_CODEC_LC3_CHAN_COUNT, (_chan_count)), \
BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_CODEC_LC3_FRAME_LEN, \
BT_BYTES_LIST_LE16(_len_min), \
BT_BYTES_LIST_LE16(_len_max)) \
BT_BYTES_LIST_LE16(_len_max)), \
COND_CODE_1(_max_frames_per_sdu, (), \
(, BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_COUNT, \
_max_frames_per_sdu))) \
(BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_CODEC_LC3_FRAME_COUNT, \
(_max_frames_per_sdu)))), \
}
/**
* @brief Helper to declare LC3 codec metadata
*/
#define BT_AUDIO_CODEC_LC3_META(_prefer_context) \
#define BT_AUDIO_CODEC_CAP_LC3_META(_prefer_context) \
{ \
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, \
BT_AUDIO_CODEC_CAP_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, \
BT_BYTES_LIST_LE16(_prefer_context)) \
}
/**
* @brief Helper to declare LC3 codec
*
* @param _freq Supported Sampling Frequencies bitfield (see BT_AUDIO_CODEC_LC3_FREQ_*)
* @param _duration Supported Frame Durations bitfield (see BT_AUDIO_CODEC_LC3_DURATION_*)
* @param _chan_count Supported channels (see @ref BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT)
* @param _len_min Minimum number of octets supported per codec frame
* @param _len_max Maximum number of octets supported per codec frame
* @param _max_frames_per_sdu Supported maximum codec frames per SDU
* @param _prefer_context Preferred contexts (@ref bt_audio_context)
*
*/
#define BT_AUDIO_CODEC_LC3(_freq, _duration, _chan_count, _len_min, _len_max, _max_frames_per_sdu, \
_prefer_context) \
BT_AUDIO_CODEC(BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \
BT_AUDIO_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max, \
_max_frames_per_sdu), \
BT_AUDIO_CODEC_LC3_META(_prefer_context))
#define BT_AUDIO_CODEC_CAP_LC3(_freq, _duration, _chan_count, _len_min, _len_max, \
_max_frames_per_sdu, _prefer_context) \
BT_AUDIO_CODEC_CAP(BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \
BT_AUDIO_CODEC_CAP_LC3_DATA(_freq, _duration, _chan_count, _len_min, \
_len_max, _max_frames_per_sdu), \
BT_AUDIO_CODEC_CAP_LC3_META(_prefer_context))
/**
* @brief Helper to declare LC3 codec data configuration
@ -332,7 +342,7 @@ enum bt_audio_codec_config_type {
* @param _stream_context Stream context (BT_AUDIO_CONTEXT_*)
*/
#define BT_AUDIO_CODEC_LC3_CONFIG(_freq, _duration, _loc, _len, _frames_per_sdu, _stream_context) \
BT_AUDIO_CODEC( \
BT_AUDIO_CODEC_CFG( \
BT_AUDIO_CODEC_LC3_ID, 0x0000, 0x0000, \
BT_AUDIO_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len, _frames_per_sdu), \
BT_AUDIO_CODEC_LC3_CONFIG_META(_stream_context))

View file

@ -51,8 +51,10 @@ static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)];
static struct bt_conn *broadcast_assistant_conn;
static struct bt_le_ext_adv *ext_adv;
static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_LC3_CONFIG_16_2(
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_24KHZ,
BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
/* Create a mask for the maximum BIS we can sync to using the number of streams
* we have. We add an additional 1 since the bis indexes start from 1 and not

View file

@ -21,7 +21,7 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT,
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_LC3(
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_24KHZ,
BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));

View file

@ -55,10 +55,9 @@ static struct bt_le_per_adv_sync *bcast_pa_sync;
static struct bt_bap_stream streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)];
static struct bt_audio_codec_cap codec = BT_AUDIO_CODEC_LC3(
BT_AUDIO_CODEC_LC3_FREQ_48KHZ,
BT_AUDIO_CODEC_LC3_DURATION_10, BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u,
(BT_AUDIO_CONTEXT_TYPE_MEDIA));
static struct bt_audio_codec_cap codec = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_48KHZ, BT_AUDIO_CODEC_LC3_DURATION_10,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 60u, 1u, (BT_AUDIO_CONTEXT_TYPE_MEDIA));
/* Create a mask for the maximum BIS we can sync to using the number of streams
* we have. We add an additional 1 since the bis indexes start from 1 and not

View file

@ -180,32 +180,43 @@ static void print_hex(const uint8_t *ptr, size_t len)
}
}
static void print_codec_capabilities(const struct bt_audio_codec_cap *codec_cap)
static void print_ltv_elem(const char *str, uint8_t type, uint8_t value_len, const uint8_t *value,
size_t cnt)
{
printk("codec_cap 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
codec_cap->vid, codec_cap->data_count);
for (size_t i = 0; i < codec_cap->data_count; i++) {
printk("data #%zu: type 0x%02x len %u\n", i, codec_cap->data[i].data.type,
codec_cap->data[i].data.data_len);
print_hex(codec_cap->data[i].data.data,
codec_cap->data[i].data.data_len - sizeof(codec_cap->data[i].data.type));
printk("%s #%zu: type 0x%02x value_len %u\n", str, cnt, type, value_len);
print_hex(value, value_len);
printk("\n");
}
for (size_t i = 0; i < codec_cap->meta_count; i++) {
printk("meta #%zu: type 0x%02x len %u\n", i, codec_cap->meta[i].data.type,
codec_cap->meta[i].data.data_len);
print_hex(codec_cap->meta[i].data.data,
codec_cap->meta[i].data.data_len - sizeof(codec_cap->meta[i].data.type));
printk("\n");
static void print_ltv_array(const char *str, const uint8_t *ltv_data, size_t ltv_data_len)
{
size_t cnt = 0U;
for (size_t i = 0U; i < ltv_data_len; i++) {
const uint8_t len = ltv_data[i++];
const uint8_t type = ltv_data[i++];
const uint8_t *value = &ltv_data[i];
const uint8_t value_len = len - sizeof(type);
print_ltv_elem(str, type, value_len, value, cnt++);
i += value_len;
}
}
static void print_remote_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir)
{
printk("codec_cap %p dir 0x%02x\n", codec_cap, dir);
print_codec_capabilities(codec_cap);
printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
codec_cap->vid, codec_cap->data_len);
if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) {
print_ltv_array("data", codec_cap->data, codec_cap->data_len);
} else { /* If not LC3, we cannot assume it's LTV */
printk("data: ");
print_hex(codec_cap->data, codec_cap->data_len);
printk("\n");
}
print_ltv_array("meta", codec_cap->meta, codec_cap->meta_len);
}
static void add_remote_sink(struct bt_bap_ep *ep)

View file

@ -24,7 +24,7 @@
#define AVAILABLE_SOURCE_CONTEXT CONFIG_BT_PACS_SRC_CONTEXT
static struct bt_audio_codec_cap lc3_codec_cap =
BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ |
BT_AUDIO_CODEC_CAP_LC3(BT_AUDIO_CODEC_LC3_FREQ_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_32KHZ |
BT_AUDIO_CODEC_LC3_FREQ_48KHZ,
BT_AUDIO_CODEC_LC3_DURATION_7_5 | BT_AUDIO_CODEC_LC3_DURATION_10,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(2), 30, 155u, 1u,

View file

@ -353,26 +353,43 @@ static void print_hex(const uint8_t *ptr, size_t len)
}
}
static void print_ltv_elem(const char *str, uint8_t type, uint8_t value_len, const uint8_t *value,
size_t cnt)
{
printk("%s #%zu: type 0x%02x value_len %u\n", str, cnt, type, value_len);
print_hex(value, value_len);
printk("\n");
}
static void print_ltv_array(const char *str, const uint8_t *ltv_data, size_t ltv_data_len)
{
size_t cnt = 0U;
for (size_t i = 0U; i < ltv_data_len; i++) {
const uint8_t len = ltv_data[i++];
const uint8_t type = ltv_data[i++];
const uint8_t *value = &ltv_data[i];
const uint8_t value_len = len - sizeof(type);
print_ltv_elem(str, type, value_len, value, cnt++);
i += value_len;
}
}
static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap)
{
printk("codec 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
codec_cap->vid, codec_cap->data_count);
printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid,
codec_cap->vid, codec_cap->data_len);
for (size_t i = 0; i < codec_cap->data_count; i++) {
printk("data #%zu: type 0x%02x len %u\n", i, codec_cap->data[i].data.type,
codec_cap->data[i].data.data_len);
print_hex(codec_cap->data[i].data.data,
codec_cap->data[i].data.data_len - sizeof(codec_cap->data[i].data.type));
if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) {
print_ltv_array("data", codec_cap->data, codec_cap->data_len);
} else { /* If not LC3, we cannot assume it's LTV */
printk("data: ");
print_hex(codec_cap->data, codec_cap->data_len);
printk("\n");
}
for (size_t i = 0; i < codec_cap->meta_count; i++) {
printk("meta #%zu: type 0x%02x len %u\n", i, codec_cap->meta[i].data.type,
codec_cap->meta[i].data.data_len);
print_hex(codec_cap->meta[i].data.data,
codec_cap->meta[i].data.data_len - sizeof(codec_cap->meta[i].data.type));
printk("\n");
}
print_ltv_array("meta", codec_cap->meta, codec_cap->meta_len);
}
static bool check_audio_support_and_connect(struct bt_data *data,

View file

@ -33,8 +33,8 @@ NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT,
BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
static struct bt_audio_codec_cap lc3_codec_cap =
BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));

View file

@ -46,14 +46,6 @@ config BT_AUDIO_CODEC_CFG_MAX_DATA_COUNT
This option defines the maximum number of LTV entries a codec can
store.
config BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT
int "Codec Capabilities Data Count"
default 5
range 1 128
help
This option defines the maximum number of LTV entries a codec can
store.
config BT_AUDIO_CODEC_MAX_DATA_LEN
int "Codec Capabilities Data Length"
default 4
@ -70,13 +62,19 @@ config BT_AUDIO_CODEC_CFG_MAX_METADATA_COUNT
This option defines the maximum number of LTV entries a metadata can
store.
config BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT
int "Codec Capabilities Metadata Count"
default 2
range 1 128
config BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE
int "Codec Capabilities Data Size"
default 19
range 0 255
help
This option defines the maximum number of LTV entries a metadata can
store.
Number of octets to support for Codec Specific Capabilities data.
config BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE
int "Codec Capabilities Metadata Size"
default 4
range 0 255
help
Number of octets to support for Codec Specific Capabilities metadata.
if BT_BAP_UNICAST_CLIENT
config BT_BAP_UNICAST_CLIENT_GROUP_COUNT

View file

@ -1208,29 +1208,12 @@ static bool unicast_client_codec_config_cfg_store(struct bt_data *data, void *us
return false;
}
static bool unicast_client_codec_config_cap_store(struct bt_data *data, void *user_data)
static bool valid_ltv_cb(struct bt_data *data, void *user_data)
{
struct bt_audio_codec_cap *codec_cap = user_data;
struct bt_audio_codec_data *cdata;
if (codec_cap->data_count >= ARRAY_SIZE(codec_cap->data)) {
LOG_ERR("No slot available for Codec Config");
return false;
}
cdata = &codec_cap->data[codec_cap->data_count];
LOG_DBG("#%u type 0x%02x len %u", codec_cap->data_count, data->type, data->data_len);
if (unicast_client_codec_data_store(data, cdata)) {
codec_cap->data_count++;
/* just return true to continue parsing as bt_data_parse will validate for us */
return true;
}
return false;
}
static int unicast_client_ep_set_codec_cfg(struct bt_bap_ep *ep, uint8_t id, uint16_t cid,
uint16_t vid, void *data, uint8_t len,
struct bt_audio_codec_cfg *codec_cfg)
@ -1278,44 +1261,66 @@ fail:
}
static int unicast_client_set_codec_cap(uint8_t id, uint16_t cid, uint16_t vid, void *data,
uint8_t len, struct bt_audio_codec_cap *codec_cap)
uint8_t data_len, void *meta, uint8_t meta_len,
struct bt_audio_codec_cap *codec_cap)
{
struct net_buf_simple ad;
struct net_buf_simple buf;
if (!codec_cap) {
return -EINVAL;
}
LOG_DBG("codec id 0x%02x cid 0x%04x vid 0x%04x len %u", id, cid, vid, len);
LOG_DBG("codec id 0x%02x cid 0x%04x vid 0x%04x data_len %u meta_len %u", id, cid, vid,
data_len, meta_len);
/* Reset current data */
(void)memset(codec_cap, 0, sizeof(*codec_cap));
codec_cap->id = id;
codec_cap->cid = cid;
codec_cap->vid = vid;
/* Reset current metadata */
codec_cap->data_count = 0;
(void)memset(codec_cap->data, 0, sizeof(codec_cap->data));
if (!len) {
return 0;
if (data_len > 0U) {
if (data_len > sizeof(codec_cap->data)) {
return -ENOMEM;
}
net_buf_simple_init_with_data(&ad, data, len);
net_buf_simple_init_with_data(&buf, data, data_len);
/* Parse LTV entries */
bt_data_parse(&ad, unicast_client_codec_config_cap_store, codec_cap);
/* If codec is LC3, then it shall be LTV encoded - We verify this before storing the
* data For any non-LC3 codecs, we cannot verify anything
*/
if (id == BT_AUDIO_CODEC_LC3_ID) {
bt_data_parse(&buf, valid_ltv_cb, codec_cap);
/* Check if all entries could be parsed */
if (ad.len) {
LOG_ERR("Unable to parse Codec Config: len %u", ad.len);
goto fail;
if (buf.len) {
LOG_ERR("Unable to parse Codec capabilities: len %u", buf.len);
return -EINVAL;
}
}
memcpy(codec_cap->data, data, data_len);
}
if (meta_len > 0U) {
if (meta_len > sizeof(codec_cap->meta)) {
return -ENOMEM;
}
net_buf_simple_init_with_data(&buf, meta, meta_len);
bt_data_parse(&buf, valid_ltv_cb, codec_cap);
/* Check if all entries could be parsed */
if (buf.len) {
LOG_ERR("Unable to parse Codec metadata: len %u", buf.len);
return -EINVAL;
}
memcpy(codec_cap->meta, meta, meta_len);
}
return 0;
fail:
(void)memset(codec_cap, 0, sizeof(*codec_cap));
return -EINVAL;
}
static bool unicast_client_codec_cfg_metadata_store(struct bt_data *data, void *user_data)
@ -1391,75 +1396,6 @@ fail:
return err;
}
static bool unicast_client_codec_cap_metadata_store(struct bt_data *data, void *user_data)
{
struct bt_audio_codec_cap *codec_cap = user_data;
struct bt_audio_codec_data *meta;
if (codec_cap->meta_count >= ARRAY_SIZE(codec_cap->meta)) {
LOG_ERR("No slot available for Codec Config");
return false;
}
meta = &codec_cap->meta[codec_cap->meta_count];
LOG_DBG("#%u type 0x%02x len %u", codec_cap->meta_count, data->type, data->data_len);
if (unicast_client_codec_data_store(data, meta)) {
codec_cap->meta_count++;
return true;
}
return false;
}
static int unicast_client_set_codec_cap_metadata(void *data, uint8_t len,
struct bt_audio_codec_cap *codec_cap)
{
struct net_buf_simple meta;
int err;
if (!codec_cap) {
return -EINVAL;
}
LOG_DBG("len %u codec_cap %p", len, codec_cap);
/* Reset current metadata */
codec_cap->meta_count = 0;
(void)memset(codec_cap->meta, 0, sizeof(codec_cap->meta));
if (!len) {
return 0;
}
net_buf_simple_init_with_data(&meta, data, len);
/* Parse LTV entries */
bt_data_parse(&meta, unicast_client_codec_cap_metadata_store, codec_cap);
/* Check if all entries could be parsed */
if (meta.len) {
LOG_ERR("Unable to parse Metadata: len %u", meta.len);
err = -EINVAL;
if (meta.len > 2) {
/* Value of the Metadata Type field in error */
err = meta.data[2];
}
goto fail;
}
return 0;
fail:
codec_cap->meta_count = 0;
(void)memset(codec_cap->meta, 0, sizeof(codec_cap->meta));
return err;
}
static uint8_t unicast_client_cp_notify(struct bt_conn *conn,
struct bt_gatt_subscribe_params *params, const void *data,
uint16_t length)
@ -4075,18 +4011,13 @@ static uint8_t unicast_client_read_func(struct bt_conn *conn, uint8_t err,
if (unicast_client_set_codec_cap(pac_codec->id, sys_le16_to_cpu(pac_codec->cid),
sys_le16_to_cpu(pac_codec->vid), cc_ltv, cc->len,
&codec_cap)) {
meta_ltv, meta->len, &codec_cap)) {
LOG_ERR("Unable to parse Codec");
break;
}
if (unicast_client_set_codec_cap_metadata(meta_ltv, meta->len, &codec_cap)) {
LOG_ERR("Unable to parse Codec Metadata");
break;
}
LOG_DBG("codec 0x%02x config count %u meta count %u ", codec_cap.id,
codec_cap.data_count, codec_cap.meta_count);
LOG_DBG("codec 0x%02x capabilities len %u meta len %u ", codec_cap.id,
codec_cap.data_len, codec_cap.meta_len);
pac_record_cb(conn, &codec_cap);
}

View file

@ -66,31 +66,6 @@ static uint16_t src_supported_contexts = BT_AUDIO_CONTEXT_TYPE_PROHIBITED;
static K_SEM_DEFINE(read_buf_sem, 1, 1);
NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, BT_ATT_MAX_ATTRIBUTE_LEN);
static ssize_t pac_data_add(struct net_buf_simple *buf, size_t count,
struct bt_audio_codec_data *data)
{
size_t len = 0;
for (size_t i = 0; i < count; i++) {
struct bt_pac_ltv *ltv;
struct bt_data *d = &data[i].data;
const size_t ltv_len = sizeof(*ltv) + d->data_len;
if (net_buf_simple_tailroom(buf) < ltv_len) {
return -ENOMEM;
}
ltv = net_buf_simple_add(buf, sizeof(*ltv));
ltv->len = d->data_len + sizeof(ltv->type);
ltv->type = d->type;
net_buf_simple_add_mem(buf, d->data, d->data_len);
len += ltv_len;
}
return len;
}
struct pac_records_build_data {
struct bt_pacs_read_rsp *rsp;
struct net_buf_simple *buf;
@ -102,9 +77,7 @@ static bool build_pac_records(const struct bt_pacs_cap *cap, void *user_data)
struct bt_audio_codec_cap *codec_cap = cap->codec_cap;
struct net_buf_simple *buf = data->buf;
struct net_buf_simple_state state;
struct bt_pac_ltv_data *cc, *meta;
struct bt_pac_codec *pac_codec;
ssize_t len;
net_buf_simple_save(buf, &state);
@ -117,31 +90,19 @@ static bool build_pac_records(const struct bt_pacs_cap *cap, void *user_data)
pac_codec->cid = sys_cpu_to_le16(codec_cap->cid);
pac_codec->vid = sys_cpu_to_le16(codec_cap->vid);
if (net_buf_simple_tailroom(buf) < sizeof(*cc)) {
if (net_buf_simple_tailroom(buf) < (sizeof(struct bt_pac_ltv_data) + codec_cap->data_len)) {
goto fail;
}
cc = net_buf_simple_add(buf, sizeof(*cc));
net_buf_simple_add_u8(buf, codec_cap->data_len);
net_buf_simple_add_mem(buf, codec_cap->data, codec_cap->data_len);
len = pac_data_add(buf, codec_cap->data_count, codec_cap->data);
if (len < 0 || len > UINT8_MAX) {
if (net_buf_simple_tailroom(buf) < (sizeof(struct bt_pac_ltv_data) + codec_cap->meta_len)) {
goto fail;
}
cc->len = len;
if (net_buf_simple_tailroom(buf) < sizeof(*meta)) {
goto fail;
}
meta = net_buf_simple_add(buf, sizeof(*meta));
len = pac_data_add(buf, codec_cap->meta_count, codec_cap->meta);
if (len < 0 || len > UINT8_MAX) {
goto fail;
}
meta->len = len;
net_buf_simple_add_u8(buf, codec_cap->meta_len);
net_buf_simple_add_mem(buf, codec_cap->meta, codec_cap->meta_len);
data->rsp->num_pac++;

View file

@ -147,33 +147,49 @@ static inline void print_qos(const struct shell *sh, const struct bt_audio_codec
#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_UNICAST */
}
static void print_ltv_elem(const struct shell *sh, const char *str, uint8_t type, uint8_t value_len,
const uint8_t *value, size_t cnt)
{
shell_print(sh, "%s #%zu: type 0x%02x value_len %u", str, cnt, type, value_len);
shell_hexdump(sh, value, value_len);
}
static void print_ltv_array(const struct shell *sh, const char *str, const uint8_t *ltv_data,
size_t ltv_data_len)
{
size_t cnt = 0U;
for (size_t i = 0U; i < ltv_data_len;) {
const uint8_t len = ltv_data[i++];
const uint8_t type = ltv_data[i++];
const uint8_t *value = &ltv_data[i];
const uint8_t value_len = len - sizeof(type);
print_ltv_elem(sh, str, type, value_len, value, cnt++);
/* Since we are incrementing i by the value_len, we don't need to increment it
* further in the `for` statement
*/
i += value_len;
}
}
static inline void print_codec_cap(const struct shell *sh,
const struct bt_audio_codec_cap *codec_cap)
{
shell_print(sh, "codec cap id 0x%02x cid 0x%04x vid 0x%04x", codec_cap->id, codec_cap->cid,
codec_cap->vid);
shell_print(sh, "codec id 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cap->id,
codec_cap->cid, codec_cap->vid, codec_cap->data_len);
#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT > 0
shell_print(sh, "data_count %u", codec_cap->data_count);
for (size_t i = 0U; i < codec_cap->data_count; i++) {
shell_print(sh, "data #%u: type 0x%02x len %u", i, codec_cap->data[i].data.type,
codec_cap->data[i].data.data_len);
shell_hexdump(sh, codec_cap->data[i].data.data,
codec_cap->data[i].data.data_len -
sizeof(codec_cap->data[i].data.type));
#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0
if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) {
print_ltv_array(sh, "data", codec_cap->data, codec_cap->data_len);
} else { /* If not LC3, we cannot assume it's LTV */
shell_hexdump(sh, codec_cap->data, codec_cap->data_len);
}
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_COUNT > 0 */
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 */
#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT > 0
shell_print(sh, "meta_count %u", codec_cap->data_count);
for (size_t i = 0U; i < codec_cap->meta_count; i++) {
shell_print(sh, "meta #%u: type 0x%02x len %u", i, codec_cap->meta[i].data.type,
codec_cap->meta[i].data.data_len);
shell_hexdump(sh, codec_cap->meta[i].data.data,
codec_cap->meta[i].data.data_len -
sizeof(codec_cap->meta[i].data.type));
}
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_COUNT > 0 */
#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0
print_ltv_array(sh, "meta", codec_cap->meta, codec_cap->meta_len);
#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE > 0 */
}
static inline void print_codec_cfg(const struct shell *sh,

View file

@ -609,8 +609,8 @@ static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp
return 0;
}
static struct bt_audio_codec_cap lc3_codec_cap =
BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY,
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));

View file

@ -10,11 +10,10 @@
#include "pacs.h"
/* List of fakes used by this unit tester */
#define PACS_FFF_FAKES_LIST(FAKE) \
FAKE(bt_pacs_cap_foreach) \
#define PACS_FFF_FAKES_LIST(FAKE) FAKE(bt_pacs_cap_foreach)
static struct bt_audio_codec_cap lc3_codec =
BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
static struct bt_audio_codec_cap lc3_codec = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));

View file

@ -40,8 +40,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, CONFIG_BTTESTER_LOG_LEVEL);
#define AVAILABLE_SINK_CONTEXT SUPPORTED_SINK_CONTEXT
#define AVAILABLE_SOURCE_CONTEXT SUPPORTED_SOURCE_CONTEXT
static struct bt_audio_codec_cap default_codec_cap =
BT_AUDIO_CODEC_LC3(BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
static struct bt_audio_codec_cap default_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_10,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));

View file

@ -28,6 +28,7 @@ CONFIG_BT_ASCS_ASE_SRC_COUNT=2
CONFIG_BT_BAP_BROADCAST_SOURCE=y
CONFIG_BT_BAP_BROADCAST_SINK=y
CONFIG_BT_AUDIO_CODEC_MAX_DATA_LEN=128
CONFIG_BT_AUDIO_CODEC_CAP_MAX_METADATA_SIZE=196
CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT=1
CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT=1
CONFIG_BT_BAP_BROADCAST_SNK_SUBGROUP_COUNT=1

View file

@ -31,8 +31,11 @@ static struct bt_le_per_adv_sync *pa_sync;
static uint32_t broadcaster_broadcast_id;
static struct bt_bap_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
static struct bt_bap_stream *streams[ARRAY_SIZE(broadcast_sink_streams)];
static struct bt_audio_codec_cap codec_cap_16_2_1 = BT_AUDIO_CODEC_LC3_CONFIG_16_2(
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams));
static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams));
@ -179,7 +182,7 @@ static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = {
};
static struct bt_pacs_cap cap = {
.codec_cap = &codec_cap_16_2_1,
.codec_cap = &codec_cap,
};
static void started_cb(struct bt_bap_stream *stream)

View file

@ -14,26 +14,46 @@ void print_hex(const uint8_t *ptr, size_t len)
}
}
static void print_ltv_elem(const char *str, uint8_t type, uint8_t value_len, const uint8_t *value,
size_t cnt)
{
printk("%s #%zu: type 0x%02x value_len %u\n", str, cnt, type, value_len);
print_hex(value, value_len);
printk("\n");
}
static void print_ltv_array(const char *str, const uint8_t *ltv_data, size_t ltv_data_len)
{
size_t cnt = 0U;
for (size_t i = 0U; i < ltv_data_len;) {
const uint8_t len = ltv_data[i++];
const uint8_t type = ltv_data[i++];
const uint8_t *value = &ltv_data[i];
const uint8_t value_len = len - sizeof(type);
print_ltv_elem(str, type, value_len, value, cnt++);
/* Since we are incrementing i by the value_len, we don't need to increment it
* further in the `for` statement
*/
i += value_len;
}
}
void print_codec_cap(const struct bt_audio_codec_cap *codec_cap)
{
printk("codec_cfg ID 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id,
codec_cap->cid, codec_cap->vid, codec_cap->data_count);
printk("codec_cap ID 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id,
codec_cap->cid, codec_cap->vid, codec_cap->data_len);
for (uint8_t i = 0; i < codec_cap->data_count; i++) {
printk("data #%u: type 0x%02x len %u\n", i, codec_cap->data[i].data.type,
codec_cap->data[i].data.data_len);
print_hex(codec_cap->data[i].data.data,
codec_cap->data[i].data.data_len - sizeof(codec_cap->data[i].data.type));
if (codec_cap->id == BT_AUDIO_CODEC_LC3_ID) {
print_ltv_array("data", codec_cap->data, codec_cap->data_len);
} else { /* If not LC3, we cannot assume it's LTV */
printk("data: ");
print_hex(codec_cap->data, codec_cap->data_len);
printk("\n");
}
for (uint8_t i = 0; i < codec_cap->meta_count; i++) {
printk("meta #%u: type 0x%02x len %u\n", i, codec_cap->meta[i].data.type,
codec_cap->meta[i].data.data_len);
print_hex(codec_cap->meta[i].data.data,
codec_cap->meta[i].data.data_len - sizeof(codec_cap->meta[i].data.type));
printk("\n");
}
print_ltv_array("meta", codec_cap->meta, codec_cap->meta_len);
}
void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg)

View file

@ -17,45 +17,46 @@ extern enum bst_result_t bst_result;
#define CHANNEL_COUNT_1 BIT(0)
#define PREF_CONTEXT \
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)
#define PREF_CONTEXT (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)
#define LONG_META 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, \
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, \
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, \
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, \
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, \
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, \
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, \
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, \
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, \
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, \
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, \
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, \
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, \
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f
#define LONG_META_LEN (sizeof((uint8_t []){LONG_META}) + 1U) /* Size of data + type */
static struct bt_audio_codec_cap lc3_codec_cap = {
.path_id = BT_ISO_DATA_PATH_HCI,
.id = BT_AUDIO_CODEC_LC3_ID,
.cid = 0x0000U,
.vid = 0x0000U,
.data_count = 5U,
.data_len = (3 + 1) + (2 + 1) + (2 + 1) + (5 + 1) + (2 + 1),
.data = {
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FREQ,
BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_LC3_FREQ_16KHZ)),
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_DURATION,
BT_AUDIO_CODEC_LC3_DURATION_10),
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_CHAN_COUNT, CHANNEL_COUNT_1),
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_LEN, BT_BYTES_LIST_LE32(40U)),
BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_LC3_FRAME_COUNT, 1U),
3, BT_AUDIO_CODEC_LC3_FREQ,
BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_LC3_FREQ_16KHZ),
2, BT_AUDIO_CODEC_LC3_DURATION, BT_AUDIO_CODEC_LC3_DURATION_10,
2, BT_AUDIO_CODEC_LC3_CHAN_COUNT, CHANNEL_COUNT_1,
5, BT_AUDIO_CODEC_LC3_FRAME_LEN, BT_BYTES_LIST_LE16(40U),
BT_BYTES_LIST_LE16(40U),
2, BT_AUDIO_CODEC_LC3_FRAME_COUNT, 1U,
},
.meta_count = 2,
.meta_len = (5 + 1) + (LONG_META_LEN + 1U),
.meta = {
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PREF_CONTEXT,
BT_BYTES_LIST_LE32(PREF_CONTEXT)),
BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_VENDOR,
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f),
5, BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, BT_BYTES_LIST_LE32(PREF_CONTEXT),
LONG_META_LEN, BT_AUDIO_METADATA_TYPE_VENDOR, LONG_META,
},
};

View file

@ -34,8 +34,11 @@ static bt_addr_le_t broadcaster_addr;
static struct bt_le_per_adv_sync *pa_sync;
static uint32_t broadcaster_broadcast_id;
static struct bt_cap_stream broadcast_sink_streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT];
static struct bt_audio_codec_cap codec_cap_16_2_1 = BT_AUDIO_CODEC_LC3_CONFIG_16_2(
BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED);
static struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3(
BT_AUDIO_CODEC_LC3_FREQ_ANY, BT_AUDIO_CODEC_LC3_DURATION_ANY,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1, 2), 30, 240, 2,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
static const struct bt_audio_codec_qos_pref unicast_qos_pref =
BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0u, 60u, 20000u, 40000u, 20000u, 40000u);
@ -558,7 +561,7 @@ static void init(void)
if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) {
static struct bt_pacs_cap unicast_cap = {
.codec_cap = &codec_cap_16_2_1,
.codec_cap = &codec_cap,
};
err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &unicast_cap);
@ -598,7 +601,7 @@ static void init(void)
if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SINK)) {
static struct bt_pacs_cap broadcast_cap = {
.codec_cap = &codec_cap_16_2_1,
.codec_cap = &codec_cap,
};
err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &broadcast_cap);