Skip to content

Commit

Permalink
Bluetooth: Audio: Add codec cap set functions
Browse files Browse the repository at this point in the history
Add set functions for codec capability, to set all
assigned number values in the bt_audio_codec_cap
struct.

Signed-off-by: Emil Gydesen <[email protected]>
  • Loading branch information
Thalley committed Oct 3, 2023
1 parent cdebba6 commit 6068316
Show file tree
Hide file tree
Showing 3 changed files with 342 additions and 12 deletions.
85 changes: 76 additions & 9 deletions include/zephyr/bluetooth/audio/audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -936,31 +936,57 @@ uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, u
/**
* @brief Extract the frequency from a codec capability.
*
* @param codec_cap The codec configuration to extract data from.
* @param codec_cap The codec capabilities to extract data from.
*
* @retval Bitfield of supported frequencies if 0 or positive
* @retval Bitfield of supported frequencies (@ref bt_audio_codec_cap_freq) if 0 or positive
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
* @retval -EBADMSG if found value has invalid size or value
*/
int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap);

/**
* @brief Set the supported frequencies of a codec capability.
*
* @param codec_cap The codec capabilities to set data for.
* @param freq The supported frequencies to set.
*
* @retval 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_set_freq(struct bt_audio_codec_cap *codec_cap,
enum bt_audio_codec_cap_freq freq);

/**
* @brief Extract the frequency from a codec capability.
*
* @param codec_cap The codec configuration to extract data from.
* @param codec_cap The codec capabilities to extract data from.
*
* @retval Bitfield of supported frame durations if 0 or positive
* @retval -EINVAL if arguments are invalid
* @retval -ENODATA if not found
* @retval -EBADMSG if found value has invalid size or value
*/
int bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap *codec_cap);
int bt_audio_codec_cap_get_frame_dur(const struct bt_audio_codec_cap *codec_cap);

/**
* @brief Set the frame duration of a codec capability.
*
* @param codec_cap The codec capabilities to set data for.
* @param frame_dur The frame duration to set.
*
* @retval 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_set_frame_dur(struct bt_audio_codec_cap *codec_cap,
enum bt_audio_codec_cap_frame_dur frame_dur);

/**
* @brief Extract the frequency from a codec capability.
*
* @param codec_cap The codec configuration to extract data from.
* @param codec_cap The codec capabilities to extract data from.
*
* @retval Bitfield of supported channel counts if 0 or positive
* @retval -EINVAL if arguments are invalid
Expand All @@ -970,9 +996,22 @@ int bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap *codec
int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap);

/**
* @brief Extract the frequency from a codec capability.
* @brief Set the channel count of a codec capability.
*
* @param codec_cap The codec capabilities to set data for.
* @param chan_count The channel count frequency to set.
*
* @retval 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_set_supported_audio_chan_counts(
struct bt_audio_codec_cap *codec_cap, enum bt_audio_codec_cap_chan_count chan_count);

/**
* @brief Extract the supported octets per codec frame from a codec capability.
*
* @param[in] codec_cap The codec configuration to extract data from.
* @param[in] codec_cap The codec capabilities to extract data from.
* @param[out] codec_frame Struct to place the resulting values in
*
* @retval 0 on success
Expand All @@ -985,9 +1024,23 @@ int bt_audio_codec_cap_get_octets_per_frame(
struct bt_audio_codec_octets_per_codec_frame *codec_frame);

/**
* @brief Extract the frequency from a codec capability.
* @brief Set the octets per codec frame of a codec capability.
*
* @param codec_cap The codec capabilities to set data for.
* @param codec_frame The octets per codec frame to set.
*
* @param codec_cap The codec configuration to extract data from.
* @retval 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_set_octets_per_frame(
struct bt_audio_codec_cap *codec_cap,
const struct bt_audio_codec_octets_per_codec_frame *codec_frame);

/**
* @brief Extract the maximum codec frames per SDU from a codec capability.
*
* @param codec_cap The codec capabilities to extract data from.
*
* @retval Maximum number of codec frames per SDU supported
* @retval -EINVAL if arguments are invalid
Expand All @@ -996,6 +1049,19 @@ int bt_audio_codec_cap_get_octets_per_frame(
*/
int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap);

/**
* @brief Set the maximum codec frames per SDU of a codec capability.
*
* @param codec_cap The codec capabilities to set data for.
* @param codec_frames_per_sdu The maximum codec frames per SDU to set.
*
* @retval 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_set_max_codec_frames_per_sdu(struct bt_audio_codec_cap *codec_cap,
uint8_t codec_frames_per_sdu);

/** @brief Lookup a specific metadata value based on type
*
* @param[in] codec_cap The codec data to search in.
Expand Down Expand Up @@ -1156,6 +1222,7 @@ int bt_audio_codec_cap_meta_get_extended(const struct bt_audio_codec_cap *codec_
*/
int bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap *codec_cap,
const uint8_t **vendor_meta);

/** @} */ /* End of bt_audio_codec_cap */

#ifdef __cplusplus
Expand Down
163 changes: 162 additions & 1 deletion subsys/bluetooth/audio/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,15 @@ int bt_audio_codec_cap_meta_get_vendor(const struct bt_audio_codec_cap *codec_ca

#if CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0

static void init_net_buf_simple_from_codec_cap(struct net_buf_simple *buf,
struct bt_audio_codec_cap *codec_cap)
{
buf->__buf = codec_cap->data;
buf->data = codec_cap->data;
buf->size = sizeof(codec_cap->data);
buf->len = codec_cap->data_len;
}

uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, uint8_t type,
const uint8_t **data)
{
Expand Down Expand Up @@ -1070,6 +1079,37 @@ uint8_t bt_audio_codec_cap_get_val(const struct bt_audio_codec_cap *codec_cap, u
return param.data_len;
}

int bt_audio_codec_cap_set_val(struct bt_audio_codec_cap *codec_cap, uint8_t type,
const uint8_t *data, size_t data_len)
{
struct net_buf_simple buf;
int ret;

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

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

CHECKIF(data_len == 0U || data_len > UINT8_MAX) {
LOG_DBG("Invalid data_len %zu", data_len);
return -EINVAL;
}

init_net_buf_simple_from_codec_cap(&buf, codec_cap);

ret = ltv_set_val(&buf, type, data, data_len);
if (ret >= 0) {
codec_cap->data_len = ret;
}

return ret;
}

int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap)
{
const uint8_t *data;
Expand All @@ -1092,7 +1132,28 @@ int bt_audio_codec_cap_get_freq(const struct bt_audio_codec_cap *codec_cap)
return sys_get_le16(data);
}

int bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap *codec_cap)
int bt_audio_codec_cap_set_freq(struct bt_audio_codec_cap *codec_cap,
enum bt_audio_codec_cap_freq freq)
{
uint16_t freq_le16;

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

if ((freq & BT_AUDIO_CODEC_LC3_FREQ_ANY) != freq) {
LOG_DBG("Invalid freq value: %d", freq);
return -EINVAL;
}

freq_le16 = sys_cpu_to_le16((uint16_t)freq);

return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FREQ, (uint8_t *)&freq_le16,
sizeof(freq_le16));
}

int bt_audio_codec_cap_get_frame_dur(const struct bt_audio_codec_cap *codec_cap)
{
const uint8_t *data;
uint8_t data_len;
Expand All @@ -1114,6 +1175,45 @@ int bt_audio_codec_cap_get_frame_duration(const struct bt_audio_codec_cap *codec
return data[0];
}

int bt_audio_codec_cap_set_frame_dur(struct bt_audio_codec_cap *codec_cap,
enum bt_audio_codec_cap_frame_dur frame_dur)
{
uint8_t frame_dur_u8;

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

if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_ANY) == 0) {
LOG_DBG("Invalid frame_dur value: %d", frame_dur);
return -EINVAL;
}

if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_7_5) != 0) {
if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_10) != 0) {
LOG_DBG("Cannot prefer both 7.5 and 10ms: %d", frame_dur);
return -EINVAL;
}

if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_7_5) == 0) {
LOG_DBG("Cannot prefer 7.5ms when not supported: %d", frame_dur);
return -EINVAL;
}
}

if ((frame_dur & BT_AUDIO_CODEC_LC3_DURATION_PREFER_10) != 0 &&
(frame_dur & BT_AUDIO_CODEC_LC3_DURATION_10) == 0) {
LOG_DBG("Cannot prefer 10ms when not supported: %d", frame_dur);
return -EINVAL;
}

frame_dur_u8 = (uint8_t)frame_dur;

return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_DURATION, &frame_dur_u8,
sizeof(frame_dur_u8));
}

int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap)
{
const uint8_t *data;
Expand All @@ -1136,6 +1236,27 @@ int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_cod
return data[0];
}

int bt_audio_codec_cap_set_supported_audio_chan_counts(
struct bt_audio_codec_cap *codec_cap, enum bt_audio_codec_cap_chan_count chan_count)
{
uint8_t chan_count_u8;

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

if ((chan_count & BT_AUDIO_CODEC_CAP_CHAN_COUNT_ALL) != chan_count) {
LOG_DBG("Invalid chan_count value: %d", chan_count);
return -EINVAL;
}

chan_count_u8 = (uint8_t)chan_count;

return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_CHAN_COUNT, &chan_count_u8,
sizeof(chan_count_u8));
}

int bt_audio_codec_cap_get_octets_per_frame(
const struct bt_audio_codec_cap *codec_cap,
struct bt_audio_codec_octets_per_codec_frame *codec_frame)
Expand Down Expand Up @@ -1168,6 +1289,34 @@ int bt_audio_codec_cap_get_octets_per_frame(
return 0;
}

int bt_audio_codec_cap_set_octets_per_frame(
struct bt_audio_codec_cap *codec_cap,
const struct bt_audio_codec_octets_per_codec_frame *codec_frame)
{
uint8_t codec_frame_le32[4];

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

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

if (codec_frame->min > codec_frame->max) {
LOG_DBG("Invalid codec_frame values: %u/%u", codec_frame->min, codec_frame->max);
return -EINVAL;
}

sys_put_le16(codec_frame->min, codec_frame_le32);
sys_put_le16(codec_frame->max, codec_frame_le32 + 2);

return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_LEN, codec_frame_le32,
sizeof(codec_frame_le32));
}

int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap)
{
const uint8_t *data;
Expand All @@ -1190,4 +1339,16 @@ int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_
return data[0];
}

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

return bt_audio_codec_cap_set_val(codec_cap, BT_AUDIO_CODEC_LC3_FRAME_COUNT,
&codec_frames_per_sdu, sizeof(codec_frames_per_sdu));
}

#endif /* CONFIG_BT_AUDIO_CODEC_CAP_MAX_DATA_SIZE > 0 */
Loading

0 comments on commit 6068316

Please sign in to comment.