Skip to content

Commit

Permalink
Bluetooth: Audio: Refactor bt_audio_codec_cap to flat arrays
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
Thalley committed Jun 27, 2023
1 parent f5d90f3 commit 6a4c9be
Show file tree
Hide file tree
Showing 20 changed files with 336 additions and 348 deletions.
64 changes: 43 additions & 21 deletions include/zephyr/bluetooth/audio/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,26 +199,48 @@ 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 @ref bt_audio_codec_cfg
*
* @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(_id, _cid, _vid, _data, _meta) \
{ \
/* 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_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_data)), \
.data = _data, \
.meta_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_meta)), \
.meta = _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, \
.cid = _cid, \
.vid = _vid, \
.data_count = ARRAY_SIZE(((struct bt_audio_codec_data[])_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.
*
Expand Down Expand Up @@ -302,18 +324,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. */
Expand Down
48 changes: 28 additions & 20 deletions include/zephyr/bluetooth/audio/lc3.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,38 +254,46 @@ 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_BYTES_LIST_LE16(_len_min), \
BT_BYTES_LIST_LE16(_len_max)) \
3, BT_AUDIO_CODEC_LC3_FREQ, BT_BYTES_LIST_LE16(_freq), \
2, BT_AUDIO_CODEC_LC3_DURATION, (_duration), \
2, BT_AUDIO_CODEC_LC3_CHAN_COUNT, (_chan_count), \
5, BT_AUDIO_CODEC_LC3_FRAME_LEN, BT_BYTES_LIST_LE16(_len_min), \
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))) \
(2, 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_BYTES_LIST_LE16(_prefer_context)) \
3, BT_AUDIO_METADATA_TYPE_PREF_CONTEXT, BT_BYTES_LIST_LE16(_prefer_context) \
}

/**
* @brief Helper to declare LC3 codec
* @brief Helper to declare LC3 codec
*
* @param _cid Company ID
* @param _vid Vendor ID
* @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(_cid, _vid, _freq, _duration, _chan_count, _len_min, _len_max, \
_max_frames_per_sdu, _prefer_context) \
BT_AUDIO_CODEC_CAP(BT_AUDIO_CODEC_LC3_ID, _cid, _vid, \
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
Expand Down Expand Up @@ -332,7 +340,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))
Expand Down
6 changes: 4 additions & 2 deletions samples/bluetooth/broadcast_audio_sink/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,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(
0x0000, 0x0000, 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
Expand Down
4 changes: 2 additions & 2 deletions samples/bluetooth/hap_ha/src/bap_unicast_sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,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_16KHZ | BT_AUDIO_CODEC_LC3_FREQ_24KHZ,
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
0x0000, 0x0000, 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));

Expand Down
49 changes: 30 additions & 19 deletions samples/bluetooth/tmap_central/src/cap_initiator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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("\n");
}
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)
Expand Down
11 changes: 6 additions & 5 deletions samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
#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_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,
(CONFIG_BT_PACS_SNK_CONTEXT | CONFIG_BT_PACS_SRC_CONTEXT));
BT_AUDIO_CODEC_CAP_LC3(0x0000, 0x0000,
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,
(CONFIG_BT_PACS_SNK_CONTEXT | CONFIG_BT_PACS_SRC_CONTEXT));

static struct bt_conn *default_conn;
static struct bt_bap_stream streams[CONFIG_BT_ASCS_ASE_SNK_COUNT + CONFIG_BT_ASCS_ASE_SRC_COUNT];
Expand Down
47 changes: 32 additions & 15 deletions samples/bluetooth/unicast_audio_client/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,26 +353,43 @@ static void print_hex(const uint8_t *ptr, size_t len)
}
}

static void print_codec_cap(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 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("\n");
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;
}
}

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));
static void print_codec_cap(const struct bt_audio_codec_cap *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 bool check_audio_support_and_connect(struct bt_data *data,
Expand Down
8 changes: 4 additions & 4 deletions samples/bluetooth/unicast_audio_server/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ 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,
BT_AUDIO_CODEC_LC3_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u,
(BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA));
static struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3(
0x0000, 0x0000, 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));

static struct bt_conn *default_conn;
static struct k_work_delayable audio_send_work;
Expand Down
26 changes: 12 additions & 14 deletions subsys/bluetooth/audio/Kconfig.bap
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit 6a4c9be

Please sign in to comment.