Bluetooth: Audio: Add BAP unicast server support

Add the Basic Audio Profile (BAP) unicast server
functionality. This allows a device to act as the
unicast server role, which can accept unicast streams
initiated by a unicast client.

Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
Emil Gydesen 2022-01-07 17:23:45 +01:00 committed by Johan Hedberg
commit 03862b3db5
20 changed files with 6460 additions and 38 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,264 @@
/* @file
* @brief Internal APIs for Audio Capabilities handling
*
* Copyright (c) 2021 Intel Corporation
* Copyright (c) 2021-2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_CAPABILITIES_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_CAPABILITIES_H_
#include <bluetooth/audio/audio.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Get list of capabilities by type */
sys_slist_t *bt_audio_capability_get(uint8_t type);
/** @brief Audio Capability type */
enum bt_audio_capability_framing {
BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED = 0x00,
BT_AUDIO_CAPABILITY_UNFRAMED_NOT_SUPPORTED = 0x01,
};
/** @def BT_AUDIO_CAPABILITY_PREF
* @brief Helper to declare elements of @ref bt_audio_capability_pref
*
* @param _framing Framing Support
* @param _phy Preferred Target PHY
* @param _rtn Preferred Retransmission number
* @param _latency Preferred Maximum Transport Latency (msec)
* @param _pd_min Minimum Presentation Delay (usec)
* @param _pd_max Maximum Presentation Delay (usec)
* @param _pref_pd_min Preferred Minimum Presentation Delay (usec)
* @param _pref_pd_max Preferred Maximum Presentation Delay (usec)
*/
#define BT_AUDIO_CAPABILITY_PREF(_framing, _phy, _rtn, _latency, _pd_min, \
_pd_max, _pref_pd_min, _pref_pd_max) \
{ \
.framing = _framing, \
.phy = _phy, \
.rtn = _rtn, \
.latency = _latency, \
.pd_min = _pd_min, \
.pd_max = _pd_max, \
.pref_pd_min = _pref_pd_min, \
.pref_pd_max = _pref_pd_max, \
}
/** @brief Audio Capability Preference structure. */
struct bt_audio_capability_pref {
/** @brief Framing support value
*
* Unlike the other fields, this is not a preference but whether
* the capability supports unframed ISOAL PDUs.
*
* Possible values: BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED and
* BT_AUDIO_CAPABILITY_UNFRAMED_NOT_SUPPORTED.
*/
uint8_t framing;
/** Preferred PHY */
uint8_t phy;
/** Preferred Retransmission Number */
uint8_t rtn;
/** Preferred Transport Latency in ms */
uint16_t latency;
/** @brief Minimun Presentation Delay in us
*
* Unlike the other fields, this is not a preference but a minimum
* requirement.
*/
uint32_t pd_min;
/** @brief Maximum Presentation Delay in us
*
* Unlike the other fields, this is not a preference but a maximum
* requirement.
*/
uint32_t pd_max;
/** @brief Preferred minimun Presentation Delay in us*/
uint32_t pref_pd_min;
/** @brief Preferred maximum Presentation Delay in us */
uint32_t pref_pd_max;
};
struct bt_audio_capability; /* Handle circular dependency */
/** @brief Capability operations structure.
*
* These are only used for unicast streams and broadcast sink streams.
*/
struct bt_audio_capability_ops {
/** @brief Capability config callback
*
* Config callback is called whenever a new Audio Stream needs to be
* allocated.
*
* @param conn Connection object
* @param ep Remote Audio Endpoint being configured
* @param cap Local Audio Capability being configured
* @param codec Codec configuration
*
* @return Allocated Audio Stream object or NULL in case of error.
*/
struct bt_audio_stream *(*config)(struct bt_conn *conn,
struct bt_audio_ep *ep,
struct bt_audio_capability *cap,
struct bt_codec *codec);
/** @brief Capability reconfig callback
*
* Reconfig callback is called whenever an Audio Stream needs to be
* reconfigured with different codec configuration.
*
* @param stream Stream object being reconfigured.
* @param cap Local Audio Capability being reconfigured
* @param codec Codec configuration
*
* @return 0 in case of success or negative value in case of error.
*/
int (*reconfig)(struct bt_audio_stream *stream,
struct bt_audio_capability *cap,
struct bt_codec *codec);
/** @brief Capability QoS callback
*
* QoS callback is called whenever an Audio Stream Quality of
* Service needs to be configured.
*
* @param stream Stream object being reconfigured.
* @param QoS Quality of Service configuration
*
* @return 0 in case of success or negative value in case of error.
*/
int (*qos)(struct bt_audio_stream *stream, struct bt_codec_qos *qos);
/** @brief Capability Enable callback
*
* Enable callback is called whenever an Audio Stream is about to be
* enabled.
*
* @param stream Stream object being enabled.
* @param meta_count Number of metadata entries
* @param meta Metadata entries
*
* @return 0 in case of success or negative value in case of error.
*/
int (*enable)(struct bt_audio_stream *stream, uint8_t meta_count,
struct bt_codec_data *meta);
/** @brief Capability Start callback
*
* Start callback is called whenever an Audio Stream is about to
* start streaming.
*
* @param stream Stream object.
*
* @return 0 in case of success or negative value in case of error.
*/
int (*start)(struct bt_audio_stream *stream);
/** @brief Capability Metadata callback
*
* Metadata callback is called whenever an Audio Stream needs to
* update its metadata.
*
* @param stream Stream object.
* @param meta_count Number of metadata entries
* @param meta Metadata entries
*
* @return 0 in case of success or negative value in case of error.
*/
int (*metadata)(struct bt_audio_stream *stream, uint8_t meta_count,
struct bt_codec_data *meta);
/** @brief Capability Disable callback
*
* Disable callback is called whenever an Audio Stream is about to be
* disabled.
*
* @param stream Stream object being disabled.
*
* @return 0 in case of success or negative value in case of error.
*/
int (*disable)(struct bt_audio_stream *stream);
/** @brief Capability Stop callback
*
* Stop callback is called whenever an Audio Stream is about to
* stop streaming.
*
* @param stream Stream object.
*
* @return 0 in case of success or negative value in case of error.
*/
int (*stop)(struct bt_audio_stream *stream);
/** @brief Capability release callback
*
* Release callback is called whenever a new Audio Stream needs to be
* deallocated.
*
* @param stream Stream object.
*
* @return 0 in case of success or negative value in case of error.
*/
int (*release)(struct bt_audio_stream *stream);
};
/** @brief Audio Capability structure.
*
* Audio Capability represents a Local Codec including its preferrable
* Quality of service.
*
*/
struct bt_audio_capability {
/** Capability type */
uint8_t type;
/** Supported Audio Contexts */
uint16_t context;
/** Capability codec reference */
struct bt_codec *codec;
/** Capability preferences */
struct bt_audio_capability_pref pref;
/** Capability operations reference */
struct bt_audio_capability_ops *ops;
sys_snode_t node;
};
/** @brief Register Audio Capability.
*
* Register Audio Local Capability.
*
* @param cap Capability structure.
*
* @return 0 in case of success or negative value in case of error.
*/
int bt_audio_capability_register(struct bt_audio_capability *cap);
/** @brief Unregister Audio Capability.
*
* Unregister Audio Local Capability.
*
* @param cap Capability structure.
*
* @return 0 in case of success or negative value in case of error.
*/
int bt_audio_capability_unregister(struct bt_audio_capability *cap);
#ifdef __cplusplus
}
#endif
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_CAPABILITIES_H_ */

View file

@ -0,0 +1,423 @@
/** @file
* @brief Bluetooth LC3 codec handling
*/
/*
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_LC3_H_
#define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_LC3_H_
/**
* @brief LC3
* @defgroup bt_codec_lc3 AUDIO
* @ingroup bluetooth
* @{
*/
#ifdef __cplusplus
extern "C" {
#endif
/** @def BT_CODEC_LC3_ID
* @brief LC3 codec ID
*/
#define BT_CODEC_LC3_ID 0x06
/* TODO: Remove base once LTV types are defined */
#define BT_CODEC_LC3_CAP_BASE 0x01
/** @def BT_CODEC_LC3_FREQ
* @brief LC3 sample frequency capability type
*/
#define BT_CODEC_LC3_FREQ (BT_CODEC_LC3_CAP_BASE)
/** @def BT_CODEC_LC3_FREQ_8KHZ
* @brief LC3 8 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_8KHZ BIT(0)
/** @def BT_CODEC_LC3_FREQ_11KHZ
* @brief LC3 11.025 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_11KHZ BIT(1)
/** @def BT_CODEC_LC3_FREQ_16KHZ
* @brief LC3 16 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_16KHZ BIT(2)
/** @def BT_CODEC_LC3_FREQ_22KHZ
* @brief LC3 22.05 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_22KHZ BIT(3)
/** @def BT_CODEC_LC3_FREQ_24KHZ
* @brief LC3 24 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_24KHZ BIT(4)
/** @def BT_CODEC_LC3_FREQ_32KHZ
* @brief LC3 32 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_32KHZ BIT(5)
/** @def BT_CODEC_LC3_FREQ_44KHZ
* @brief LC3 44.1 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_44KHZ BIT(6)
/** @def BT_CODEC_LC3_FREQ_48KHZ
* @brief LC3 48 Khz frequency capability
*/
#define BT_CODEC_LC3_FREQ_48KHZ BIT(7)
/** @def BT_CODEC_LC3_FREQ_ANY
* @brief LC3 any frequency capability
*/
#define BT_CODEC_LC3_FREQ_ANY (BT_CODEC_LC3_FREQ_8KHZ | \
BT_CODEC_LC3_FREQ_16KHZ | \
BT_CODEC_LC3_FREQ_24KHZ | \
BT_CODEC_LC3_FREQ_32KHZ | \
BT_CODEC_LC3_FREQ_44KHZ | \
BT_CODEC_LC3_FREQ_48KHZ)
/** @def BT_CODEC_LC3_DURATION
* @brief LC3 frame duration capability type
*/
#define BT_CODEC_LC3_DURATION (BT_CODEC_LC3_CAP_BASE + 1)
/** @def BT_CODEC_LC3_DURATION_7_5
* @brief LC3 7.5 msec frame duration capability
*/
#define BT_CODEC_LC3_DURATION_7_5 BIT(0)
/** @def BT_CODEC_LC3_DURATION_10
* @brief LC3 10 msec frame duration capability
*/
#define BT_CODEC_LC3_DURATION_10 BIT(1)
/** @def BT_CODEC_LC3_DURATION_ANY
* @brief LC3 any frame duration capability
*/
#define BT_CODEC_LC3_DURATION_ANY (BT_CODEC_LC3_DURATION_7_5 | \
BT_CODEC_LC3_DURATION_10)
/** @def BT_CODEC_LC3_DURATION_PREFER_7_5
* @brief LC3 7.5 msec preferred frame duration capability
*/
#define BT_CODEC_LC3_DURATION_PREFER_7_5 BIT(4)
/** @def BT_CODEC_LC3_DURATION_PREFER_10
* @brief LC3 10 msec preferred frame duration capability
*/
#define BT_CODEC_LC3_DURATION_PREFER_10 BIT(5)
/** @def BT_CODEC_LC3_CHAN_COUNT
* @brief LC3 channel count capability type
*/
#define BT_CODEC_LC3_CHAN_COUNT (BT_CODEC_LC3_CAP_BASE + 2)
/** @def BT_CODEC_LC3_CHAN_COUNT_SUPPORT
* @brief LC3 channel count support capability
*/
#define BT_CODEC_LC3_CHAN_COUNT_SUPPORT BIT(0)
/** @def BT_CODEC_LC3_FRAME_LEN
* @brief LC3 frame length capability type
*/
#define BT_CODEC_LC3_FRAME_LEN (BT_CODEC_LC3_CAP_BASE + 3)
/** @def BT_CODEC_LC3_FRAME_COUNT
* @brief LC3 frame count capability type
*/
#define BT_CODEC_LC3_FRAME_COUNT (BT_CODEC_LC3_CAP_BASE + 4)
/* TODO: Remove base once LTV types are defined */
#define BT_CODEC_LC3_CONFIG_BASE 0x01
struct bt_codec_lc3_frame_len {
uint16_t min;
uint16_t max;
};
/** @def BT_CODEC_CONFIG_LC3_FREQ
* @brief LC3 Sample Frequency configuration type
*/
#define BT_CODEC_CONFIG_LC3_FREQ (BT_CODEC_LC3_CONFIG_BASE)
/** @def BT_CODEC_CONFIG_LC3_FREQ_8KHZ
* @brief LC3 8 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_8KHZ 0x01
/** @def BT_CODEC_CONFIG_LC3_FREQ_11KHZ
* @brief LC3 11.025 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_11KHZ 0x02
/** @def BT_CODEC_CONFIG_LC3_FREQ_16KHZ
* @brief LC3 16 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_16KHZ 0x03
/** @def BT_CODEC_CONFIG_LC3_FREQ_22KHZ
* @brief LC3 22.05 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_22KHZ 0x04
/** @def BT_CODEC_CONFIG_LC3_FREQ_24KHZ
* @brief LC3 24 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_24KHZ 0x05
/** @def BT_CODEC_CONFIG_LC3_FREQ_32KHZ
* @brief LC3 32 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_32KHZ 0x06
/** @def BT_CODEC_CONFIG_LC3_FREQ_44KHZ
* @brief LC3 44.1 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_44KHZ 0x07
/** @def BT_CODEC_CONFIG_LC3_FREQ_48KHZ
* @brief LC3 48 Khz Sample Frequency configuration
*/
#define BT_CODEC_CONFIG_LC3_FREQ_48KHZ 0x08
/** @def BT_CODEC_CONFIG_LC3_DURATION
* @brief LC3 Frame Duration configuration type
*/
#define BT_CODEC_CONFIG_LC3_DURATION (BT_CODEC_LC3_CONFIG_BASE + 1)
/** @def BT_CODEC_CONFIG_LC3_DURATION_7_5
* @brief LC3 7.5 msec Frame Duration configuration
*/
#define BT_CODEC_CONFIG_LC3_DURATION_7_5 0x00
/** @def BT_CODEC_CONFIG_LC3_DURATION_10
* @brief LC3 10 msec Frame Duration configuration
*/
#define BT_CODEC_CONFIG_LC3_DURATION_10 0x01
/** @def BT_CODEC_CONFIG_LC3_CHAN_ALLOC
* @brief LC3 channel Allocation configuration type
*/
#define BT_CODEC_CONFIG_LC3_CHAN_ALLOC (BT_CODEC_LC3_CONFIG_BASE + 2)
/** @def BT_CODEC_CONFIG_LC3_FRAME_LEN
* @brief LC3 Frame Length configuration type
*/
#define BT_CODEC_CONFIG_LC3_FRAME_LEN (BT_CODEC_LC3_CONFIG_BASE + 3)
/** @def BT_CODEC_LC3_DATA
* @brief Helper to declare LC3 codec capability
*/
#define BT_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, _len_max) \
{ \
BT_CODEC_DATA(BT_CODEC_LC3_FREQ, _freq, _freq >> 8), \
BT_CODEC_DATA(BT_CODEC_LC3_DURATION, _duration), \
BT_CODEC_DATA(BT_CODEC_LC3_CHAN_COUNT, _chan_count), \
BT_CODEC_DATA(BT_CODEC_LC3_FRAME_LEN, _len_min, _len_min >> 8, \
_len_max, _len_max >> 8,) \
}
/** @def BT_CODEC_LC3_META
* @brief Helper to declare LC3 codec metadata
*/
#define BT_CODEC_LC3_META(_prefer_context, _context) \
{ \
BT_CODEC_DATA(BT_CODEC_META_PREFER_CONTEXT, _prefer_context & 0xff, \
_prefer_context >> 8), \
BT_CODEC_DATA(BT_CODEC_META_CONTEXT, _context & 0xff, _context >> 8) \
}
/** @def BT_CODEC_LC3
* @brief Helper to declare LC3 codec
*/
#define BT_CODEC_LC3(_freq, _duration, _chan_count, _len_min, _len_max, \
_frames, _prefer_context, _context) \
BT_CODEC(BT_CODEC_LC3_ID, 0x0000, 0x0000, \
BT_CODEC_LC3_DATA(_freq, _duration, _chan_count, _len_min, \
_len_max), \
BT_CODEC_LC3_META(_prefer_context, _context))
/** @def BT_CODEC_LC3_CONFIG_DATA
* @brief Helper to declare LC3 codec data configuration
*/
#define BT_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len) \
{ \
BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FREQ, _freq), \
BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_DURATION, _duration), \
BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_CHAN_ALLOC, _loc, _loc >> 8, \
_loc >> 16, _loc >> 24), \
BT_CODEC_DATA(BT_CODEC_CONFIG_LC3_FRAME_LEN, _len, _len >> 8) \
}
/** @def BT_CODEC_LC3_CONFIG_DATA
* @brief Helper to declare LC3 codec metadata configuration
*/
#define BT_CODEC_LC3_CONFIG_META(_context) \
{ \
BT_CODEC_DATA(BT_CODEC_META_CONTEXT, _context, _context >> 8), \
}
/** @def BT_CODEC_LC3_CONFIG_N
* @brief Helper to declare LC3 codec configuration for multiple channels.
*/
#define BT_CODEC_LC3_CONFIG_N(_freq, _duration, _loc, _len, _context) \
BT_CODEC(BT_CODEC_LC3_ID, 0x0000, 0x0000, \
BT_CODEC_LC3_CONFIG_DATA(_freq, _duration, _loc, _len), \
BT_CODEC_LC3_CONFIG_META(_context))
/** @def BT_CODEC_LC3_CONFIG
* @brief Helper to declare LC3 codec configuration
*/
#define BT_CODEC_LC3_CONFIG(_freq, _duration, _len, _context) \
BT_CODEC_LC3_CONFIG_N(_freq, _duration, 0x000000000, _len, _context)
/** @def BT_CODEC_LC3_CONFIG_8_1
* @brief Helper to declare LC3 8.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_8_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_8KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 26u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_8_2
* @brief Helper to declare LC3 8.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_8_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_8KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 30u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_16_1
* @brief Helper to declare LC3 16.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_16_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_16KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 30u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_16_2
* @brief Helper to declare LC3 16.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_16_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_16KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 40u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_24_1
* @brief Helper to declare LC3 24.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_24_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_24KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 45u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_24_2
* @brief Helper to declare LC3 24.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_24_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_24KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 60u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_32_1
* @brief Helper to declare LC3 32.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_32_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_32KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 60u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_32_2
* @brief Helper to declare LC3 32.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_32_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_32KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 80u, \
BT_CODEC_META_CONTEXT_VOICE)
/** @def BT_CODEC_LC3_CONFIG_441_1
* @brief Helper to declare LC3 441.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_441_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_44KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 98u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_441_2
* @brief Helper to declare LC3 441.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_441_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_44KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 130u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_1
* @brief Helper to declare LC3 48.1 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_1 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 75u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_2
* @brief Helper to declare LC3 48.2 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_2 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 100u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_3
* @brief Helper to declare LC3 48.3 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_3 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_LC3_DURATION_7_5, 90u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_4
* @brief Helper to declare LC3 48.4 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_4 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 120u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_5
* @brief Helper to declare LC3 48.5 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_5 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_7_5, 117u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_CONFIG_48_6
* @brief Helper to declare LC3 48.6 codec configuration
*/
#define BT_CODEC_LC3_CONFIG_48_6 \
BT_CODEC_LC3_CONFIG(BT_CODEC_CONFIG_LC3_FREQ_48KHZ, \
BT_CODEC_CONFIG_LC3_DURATION_10, 155u, \
BT_CODEC_META_CONTEXT_MEDIA)
/** @def BT_CODEC_LC3_QOS_7_5
* @brief Helper to declare LC3 codec QoS for 7.5ms interval
*/
#define BT_CODEC_LC3_QOS_7_5(_dir, _framing, _sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS(_dir, 7500u, _framing, BT_CODEC_QOS_2M, _sdu, _rtn, \
_latency, _pd)
/** @def BT_CODEC_LC3_QOS_7_5_IN_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 7.5ms interval unframed input
*/
#define BT_CODEC_LC3_QOS_7_5_IN_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_IN_UNFRAMED(7500u, _sdu, _rtn, _latency, _pd)
/** @def BT_CODEC_LC3_QOS_7_5_OUT_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 7.5ms interval unframed output
*/
#define BT_CODEC_LC3_QOS_7_5_OUT_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_OUT_UNFRAMED(7500u, _sdu, _rtn, _latency, _pd)
/** @def BT_CODEC_LC3_QOS_7_5_INOUT_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 7.5ms interval unframed in/out
*/
#define BT_CODEC_LC3_QOS_7_5_INOUT_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_INOUT_UNFRAMED(7500u, _sdu, _rtn, _latency, _pd)
/** @def BT_CODEC_LC3_QOS_10
* @brief Helper to declare LC3 codec QoS for 10ms frame internal
*/
#define BT_CODEC_LC3_QOS_10(_dir, _framing, _sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS(_dir, 10000u, _framing, BT_CODEC_QOS_2M, _sdu, _rtn, \
_latency, _pd)
/** @def BT_CODEC_LC3_QOS_10_IN_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 10ms interval unframed input
*/
#define BT_CODEC_LC3_QOS_10_IN_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_IN_UNFRAMED(10000u, _sdu, _rtn, _latency, _pd)
/** @def BT_CODEC_LC3_QOS_10_OUT_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 10ms interval unframed output
*/
#define BT_CODEC_LC3_QOS_10_OUT_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_OUT_UNFRAMED(10000u, _sdu, _rtn, _latency, _pd)
/** @def BT_CODEC_LC3_QOS_10_INOUT_UNFRAMED
* @brief Helper to declare LC3 codec QoS for 10ms interval unframed in/out
*/
#define BT_CODEC_LC3_QOS_10_INOUT_UNFRAMED(_sdu, _rtn, _latency, _pd) \
BT_CODEC_QOS_INOUT_UNFRAMED(10000u, _sdu, _rtn, _latency, _pd)
#ifdef __cplusplus
}
#endif
/**
* @}
*/
#endif /* ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_LC3_H_ */

View file

@ -482,6 +482,51 @@ struct bt_uuid_128 {
*/
#define BT_UUID_MICS \
BT_UUID_DECLARE_16(BT_UUID_MICS_VAL)
/** @def BT_UUID_ASCS_VAL
* @brief Audio Stream Control Service value
*/
#define BT_UUID_ASCS_VAL 0x184E
/** @def BT_UUID_ASCS
* @brief Audio Stream Control Service
*/
#define BT_UUID_ASCS \
BT_UUID_DECLARE_16(BT_UUID_ASCS_VAL)
/** @def BT_UUID_BASS_VAL
* @brief Broadcast Audio Scan Service value
*/
#define BT_UUID_BASS_VAL 0x184F
/** @def BT_UUID_BASS
* @brief Broadcast Audio Scan Service
*/
#define BT_UUID_BASS \
BT_UUID_DECLARE_16(BT_UUID_BASS_VAL)
/** @def BT_UUID_PACS_VAL
* @brief Published Audio Capabilities Service value
*/
#define BT_UUID_PACS_VAL 0x1850
/** @def BT_UUID_PACS
* @brief Published Audio Capabilities Service
*/
#define BT_UUID_PACS \
BT_UUID_DECLARE_16(BT_UUID_PACS_VAL)
/** @def BT_UUID_BASIC_AUDIO_VAL
* @brief Basic Audio Announcement Service value
*/
#define BT_UUID_BASIC_AUDIO_VAL 0x1851
/** @def BT_UUID_BASIC_AUDIO
* @brief Basic Audio Announcement Service
*/
#define BT_UUID_BASIC_AUDIO \
BT_UUID_DECLARE_16(BT_UUID_BASIC_AUDIO_VAL)
/** @def BT_UUID_BROADCAST_AUDIO_VAL
* @brief Broadcast Audio Announcement Service value
*/
#define BT_UUID_BROADCAST_AUDIO_VAL 0x1852
/** @def BT_UUID_BROADCAST_AUDIO
* @brief Broadcast Audio Announcement Service
*/
#define BT_UUID_BROADCAST_AUDIO \
BT_UUID_DECLARE_16(BT_UUID_BROADCAST_AUDIO_VAL)
/** @def BT_UUID_GATT_PRIMARY_VAL
* @brief GATT Primary Service UUID value
*/
@ -1790,6 +1835,105 @@ struct bt_uuid_128 {
*/
#define BT_UUID_MICS_MUTE \
BT_UUID_DECLARE_16(BT_UUID_MICS_MUTE_VAL)
/** @def BT_UUID_ASCS_ASE_SNK_VAL
* @brief Audio Stream Endpoint Sink Characteristic value
*/
#define BT_UUID_ASCS_ASE_SNK_VAL 0x2BC4
/** @def BT_UUID_ASCS_ASE_SNK
* @brief Audio Stream Endpoint Sink Characteristic
*/
#define BT_UUID_ASCS_ASE_SNK \
BT_UUID_DECLARE_16(BT_UUID_ASCS_ASE_SNK_VAL)
/** @def BT_UUID_ASCS_ASE_SRC_VAL
* @brief Audio Stream Endpoint Source Characteristic value
*/
#define BT_UUID_ASCS_ASE_SRC_VAL 0x2BC5
/** @def BT_UUID_ASCS_ASE_SNK
* @brief Audio Stream Endpoint Source Characteristic
*/
#define BT_UUID_ASCS_ASE_SRC \
BT_UUID_DECLARE_16(BT_UUID_ASCS_ASE_SRC_VAL)
/** @def BT_UUID_ASCS_ASE_CP_VAL
* @brief Audio Stream Endpoint Control Point Characteristic value
*/
#define BT_UUID_ASCS_ASE_CP_VAL 0x2BC6
/** @def BT_UUID_ASCS_ASE_CP
* @brief Audio Stream Endpoint Control Point Characteristic
*/
#define BT_UUID_ASCS_ASE_CP \
BT_UUID_DECLARE_16(BT_UUID_ASCS_ASE_CP_VAL)
/** @def BT_UUID_BASS_CONTROL_POINT_VAL
* @brief Broadcast Audio Scan Service Scan State value
*/
#define BT_UUID_BASS_CONTROL_POINT_VAL 0x2BC7
/** @def BT_UUID_BASS_CONTROL_POINT
* @brief Broadcast Audio Scan Service Scan State
*/
#define BT_UUID_BASS_CONTROL_POINT \
BT_UUID_DECLARE_16(BT_UUID_BASS_CONTROL_POINT_VAL)
/** @def BT_UUID_BASS_RECV_STATE_VAL
* @brief Broadcast Audio Scan Service Receive State value
*/
#define BT_UUID_BASS_RECV_STATE_VAL 0x2BC8
/** @def BT_UUID_BASS_RECV_STATE
* @brief Broadcast Audio Scan Service Receive State
*/
#define BT_UUID_BASS_RECV_STATE \
BT_UUID_DECLARE_16(BT_UUID_BASS_RECV_STATE_VAL)
/** @def BT_UUID_PACS_SNK_VAL
* @brief Sink PAC Characteristic value
*/
#define BT_UUID_PACS_SNK_VAL 0x2BC9
/** @def BT_UUID_PACS_SNK
* @brief Sink PAC Characteristic
*/
#define BT_UUID_PACS_SNK \
BT_UUID_DECLARE_16(BT_UUID_PACS_SNK_VAL)
/** @def BT_UUID_PACS_SNK_LOC_VAL
* @brief Sink PAC Locations Characteristic value
*/
#define BT_UUID_PACS_SNK_LOC_VAL 0x2BCA
/** @def BT_UUID_PACS_SNK_LOC
* @brief Sink PAC Locations Characteristic
*/
#define BT_UUID_PACS_SNK_LOC \
BT_UUID_DECLARE_16(BT_UUID_PACS_SNK_LOC_VAL)
/** @def BT_UUID_PACS_SRC_VAL
* @brief Source PAC Characteristic value
*/
#define BT_UUID_PACS_SRC_VAL 0x2BCB
/** @def BT_UUID_PACS_SRC
* @brief Source PAC Characteristic
*/
#define BT_UUID_PACS_SRC \
BT_UUID_DECLARE_16(BT_UUID_PACS_SRC_VAL)
/** @def BT_UUID_PACS_SRC_LOC_VAL
* @brief Source PAC Locations Characteristic value
*/
#define BT_UUID_PACS_SRC_LOC_VAL 0x2BCC
/** @def BT_UUID_PACS_SRC_LOC
* @brief Source PAC Locations Characteristic
*/
#define BT_UUID_PACS_SRC_LOC \
BT_UUID_DECLARE_16(BT_UUID_PACS_SRC_LOC_VAL)
/** @def BT_UUID_PACS_CONTEXT_VAL
* @brief Available Audio Contexts Characteristic value
*/
#define BT_UUID_PACS_CONTEXT_VAL 0x2BCD
/** @def BT_UUID_PACS_CONTEXT
* @brief Available Audio Contexts Characteristic
*/
#define BT_UUID_PACS_CONTEXT \
BT_UUID_DECLARE_16(BT_UUID_PACS_CONTEXT_VAL)
/** @def BT_UUID_PACS_SUPPORTED_CONTEXT_VAL
* @brief Supported Audio Context Characteristic value
*/
#define BT_UUID_PACS_SUPPORTED_CONTEXT_VAL 0x2BCE
/** @def BT_UUID_PACS_SUPPORTED_CONTEXT
* @brief Supported Audio Context Characteristic
*/
#define BT_UUID_PACS_SUPPORTED_CONTEXT \
BT_UUID_DECLARE_16(BT_UUID_PACS_SUPPORTED_CONTEXT_VAL)
/*
* Protocol UUIDs
*/

View file

@ -41,3 +41,9 @@ zephyr_library_sources_ifdef(CONFIG_BT_MCS mcs.c)
zephyr_library_sources_ifdef(CONFIG_BT_MCS mpl.c)
zephyr_library_sources_ifdef(CONFIG_BT_MCS media_proxy.c)
zephyr_library_sources_ifdef(CONFIG_BT_ASCS ascs.c)
zephyr_library_sources_ifdef(CONFIG_BT_PACS pacs.c)
zephyr_library_sources_ifdef(CONFIG_BT_AUDIO_STREAM stream.c)
zephyr_library_sources_ifdef(CONFIG_BT_AUDIO_UNICAST_SERVER unicast_server.c)
zephyr_library_sources_ifdef(CONFIG_BT_AUDIO_CAPABILITIES capabilities.c)

View file

@ -2,6 +2,7 @@
#
# Copyright (c) 2020 Intel Corporation
# Copyright (c) 2022 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
#
@ -24,39 +25,7 @@ config BT_CCID
This hidden option is enabled when any of the content control
features are enabled.
if BT_CONN
config BT_AUDIO_UNICAST
bool "Bluetooth Unicast Audio Support"
select BT_SMP
select BT_L2CAP_DYNAMIC_CHANNEL
select BT_ISO_UNICAST
select BT_GATT_DYNAMIC_DB
select BT_GATT_CACHING
select BT_L2CAP_ECRED
select BT_EATT
help
This option enables support for Bluetooth Unicast Audio using
Isochronous channels.
# TODO: Make BT_AUDIO_BROADCAST not depend on BT_CONN
config BT_AUDIO_BROADCAST
bool "Bluetooth Broadcast Audio Support"
select BT_ISO_BROADCASTER
select BT_ISO_SYNC_RECEIVER
help
This option enables support for Bluetooth Broadcast Audio using
Isochronous channels.
endif # BT_CONN
config BT_AUDIO_DEBUG
bool "Enable debug logs"
depends on BT_DEBUG
help
Use this option to enable debug logs for the Bluetooth
Audio functionality.
rsource "Kconfig.baps"
rsource "Kconfig.vocs"
rsource "Kconfig.aics"
rsource "Kconfig.vcs"

View file

@ -0,0 +1,32 @@
# Bluetooth Audio - Audio Stream Control configuration options
#
# Copyright (c) 2020 Intel Corporation
# Copyright (c) 2022 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
config BT_ASCS
bool "Audio Stream Control Service Support"
depends on BT_PACS
select BT_SMP_SC_PAIR_ONLY
help
This option enables support for Audio Stream Control Service.
if BT_ASCS
config BT_ASCS_ASE_SNK_COUNT
int "Number of Audio Stream Endpoint Sink Characteristics"
default 2
range 0 2
help
An ASE Sink characteristic represents the state of an ASE, which is
coupled to a single direction of a unicast Audio Stream.
config BT_ASCS_ASE_SRC_COUNT
int "Number of Audio Stream Endpoint Source Characteristics"
default 2
range 0 2
help
An ASE Source characteristic represents the state of an ASE, which is
coupled to a single direction of a unicast Audio Stream.
endif # BT_ASCS

View file

@ -0,0 +1,132 @@
# Bluetooth Audio - Basic Audio Profile configuration options
#
# Copyright (c) 2020 Intel Corporation
# Copyright (c) 2022 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
config BT_AUDIO_UNICAST
bool
depends on BT_CONN
select BT_SMP
select BT_L2CAP_DYNAMIC_CHANNEL
select BT_ISO_UNICAST
select BT_L2CAP_ECRED
select BT_EATT
config BT_AUDIO_UNICAST_SERVER
bool "Bluetooth Unicast Audio Server Support [EXPERIMENTAL]"
select EXPERIMENTAL
select BT_PERIPHERAL
select BT_AUDIO_UNICAST
select BT_GATT_DYNAMIC_DB
select BT_GATT_CACHING
select BT_PACS
select BT_ASCS
help
This option enables support for Bluetooth Unicast Audio Server
using Isochronous channels.
if BT_AUDIO_UNICAST
config BT_CODEC_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_CODEC_MAX_DATA_LEN
int "Codec Capabilities Data Length"
default 4
range 1 128
help
This option defines the maximum value length of an LTV entry a codec
can store.
config BT_CODEC_MAX_METADATA_COUNT
int "Codec Metadata Count"
default 2
range 1 128
help
This option defines the maximum number of LTV entries a metadata can
store.
config BT_CODEC_MAX_METADATA_LEN
int "Codec Metadata Length"
default 4
range 1 128
help
This option defines the maximum value length of an LTV entry a
metadata can store.
endif # BT_AUDIO_UNICAST
config BT_AUDIO_BROADCAST
bool "Bluetooth Broadcast Audio Support"
select BT_ISO_BROADCASTER
select BT_ISO_SYNC_RECEIVER
help
This option enables support for Bluetooth Broadcast Audio using
Isochronous channels.
config BT_AUDIO_DEBUG
bool "Enable debug logs"
depends on BT_DEBUG
help
Use this option to enable debug logs for the Bluetooth
Audio functionality.
if BT_AUDIO_DEBUG
config BT_DEBUG_PACS
bool "Published Audio Capabilities Service debug"
depends on BT_PACS
help
Use this option to enable Published Audio Capabilities Service debug
logs for the Bluetooth Audio functionality.
config BT_AUDIO_DEBUG_STREAM
bool "Bluetooth Audio Stream debug"
depends on BT_AUDIO_STREAM
help
Use this option to enable Bluetooth Audio Stream debug logs for the
Bluetooth Audio functionality.
config BT_AUDIO_DEBUG_CAPABILITIES
bool "Bluetooth Audio Capabilities debug"
depends on BT_AUDIO_CAPABILITIES
help
Use this option to enable Bluetooth Audio Capabilities debug logs for
the Bluetooth Audio functionality.
config BT_DEBUG_ASCS
bool "Audio Stream Control Service debug"
depends on BT_ASCS
help
Use this option to enable Audio Stream Control Service debug logs for
the Bluetooth Audio functionality.
config BT_AUDIO_DEBUG_UNICAST_SERVER
bool "Bluetooth Audio Unicast Server debug"
depends on BT_AUDIO_UNICAST_SERVER
help
Use this option to enable Bluetooth Audio Unicast Server debug logs
for the Bluetooth Audio functionality.
endif # BT_AUDIO_DEBUG
config BT_AUDIO_STREAM
# Virtual/hidden option
bool
default y if BT_ASCS
config BT_AUDIO_CAPABILITIES
# Virtual/hidden option
bool
default y if BT_ASCS
rsource "Kconfig.pacs"
rsource "Kconfig.ascs"

View file

@ -0,0 +1,145 @@
# Bluetooth Audio - Published Audio Capabilities configuration options
#
# Copyright (c) 2022 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
#
config BT_PACS
bool "Published Audio Capabilities Service Support"
select BT_SMP_SC_PAIR_ONLY
help
This option enables support for Published Audio Capabilities Service.
if BT_PACS
config BT_PAC_SNK
bool "Sink PAC Characteristic Support"
default y if BT_ASCS
help
This option enables support for Sink PAC Characteristic.
if BT_PAC_SNK
config BT_PAC_SNK_LOC
hex "Sink PAC Locations Characteristic Support"
default 0x00000000
range 0x00000000 0x0ffffff
help
This option enables support for Sink PAC Locations Characteristic.
Bitmap of Audio Location values for PAC records where the server acts
as an Audio Sink:
0x00000000: Mono/Unespecified
0x00000001: Front Left
0x00000002: Front Right
0x00000004: Front Center
0x00000008: Low Frequency Effects 1
0x00000010: Back Left
0x00000020: Back Right
0x00000040: Front Left of Center
0x00000080: Front Right of Center
0x00000100: Back Center
0x00000200: Low Frequency Effects 2
0x00000400: Side Left
0x00000800: Side Right
0x00001000: Top Front Left
0x00002000: Top Front Right
0x00004000: Top Front Center
0x00008000: Top Center
0x00010000: Top Back Left
0x00020000: Top Back Right
0x00040000: Top Side Left
0x00080000: Top Side Right
0x00100000: Top Back Center
0x00200000: Bottom Front Center
0x00400000: Bottom Front Left
0x00800000: Bottom Front Right
0x01000000: Front Left Wide
0x02000000: Front Right Wide
0x01000000: Left Surround
0x02000000: Right Surround
config BT_PACS_SNK_CONTEXT
hex "Supported Sink Contexts"
default 0x03ff
range 0x0000 0x03ff
help
The Supported Sink Contexts exposes the servers support for
reception of audio data associated with specific Context Types:
0x0001: Unspecified
0x0002: Conversational
0x0004: Media
0x0008: Instructional
0x0010: AttentionSeeking
0x0020: ImmediateAlert
0x0040: ManMachine
0x0080: EmergencyAlert
0x0100: Ringtone
0x0200: TV
endif # BT_PACS_SNK
config BT_PAC_SRC
bool "Source PAC Characteristic Support"
default y if BT_ASCS
default y
help
This option enables support for Source PAC Characteristic.
if BT_PAC_SRC
config BT_PAC_SRC_LOC
hex "Source PAC Locations Characteristic Support"
default 0x00000000
range 0x00000000 0x0ffffff
help
This option enables support for Source PAC Locations Characteristic.
Bitmap of Audio Location values for PAC records where the server acts
as an Audio Source:
0x00000000: Mono/Unespecified
0x00000001: Front Left
0x00000002: Front Right
0x00000004: Front Center
0x00000008: Low Frequency Effects 1
0x00000010: Back Left
0x00000020: Back Right
0x00000040: Front Left of Center
0x00000080: Front Right of Center
0x00000100: Back Center
0x00000200: Low Frequency Effects 2
0x00000400: Side Left
0x00000800: Side Right
0x00001000: Top Front Left
0x00002000: Top Front Right
0x00004000: Top Front Center
0x00008000: Top Center
0x00010000: Top Back Left
0x00020000: Top Back Right
0x00040000: Top Side Left
0x00080000: Top Side Right
0x00100000: Top Back Center
0x00200000: Bottom Front Center
0x00400000: Bottom Front Left
0x00800000: Bottom Front Right
0x01000000: Front Left Wide
0x02000000: Front Right Wide
0x01000000: Left Surround
0x02000000: Right Surround
config BT_PACS_SRC_CONTEXT
hex "Supported Source Contexts"
default 0x03ff
range 0x0000 0x03ff
help
The Supported Source Contexts exposes the servers support for
transmission of audio data associated with specific Context Types:
0x0001: Unspecified
0x0002: Conversational
0x0004: Media
0x0008: Instructional
0x0010: AttentionSeeking
0x0020: ImmediateAlert
0x0040: ManMachine
0x0080: EmergencyAlert
0x0100: Ringtone
0x0200: TV
endif # BT_PAC_SRC
endif # BT_PACS

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,344 @@
/* @file
* @brief Internal APIs for ASCS handling
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Response Status Code */
#define BT_ASCS_RSP_SUCCESS 0x00
#define BT_ASCS_RSP_NOT_SUPPORTED 0x01
#define BT_ASCS_RSP_TRUNCATED 0x02
#define BT_ASCS_RSP_INVALID_ASE 0x03
#define BT_ASCS_RSP_INVALID_ASE_STATE 0x04
#define BT_ASCS_RSP_INVALID_DIR 0x05
#define BT_ASCS_RSP_CAP_UNSUPPORTED 0x06
#define BT_ASCS_RSP_CONF_UNSUPPORTED 0x07
#define BT_ASCS_RSP_CONF_REJECTED 0x08
#define BT_ASCS_RSP_CONF_INVALID 0x09
#define BT_ASCS_RSP_METADATA_UNSUPPORTED 0x0a
#define BT_ASCS_RSP_METADATA_REJECTED 0x0b
#define BT_ASCS_RSP_METADATA_INVALID 0x0c
#define BT_ASCS_RSP_NO_MEM 0x0d
#define BT_ASCS_RSP_UNSPECIFIED 0x0e
/* Response Reasons */
#define BT_ASCS_REASON_NONE 0x00
#define BT_ASCS_REASON_CODEC 0x01
#define BT_ASCS_REASON_CODEC_DATA 0x02
#define BT_ASCS_REASON_INTERVAL 0x03
#define BT_ASCS_REASON_FRAMING 0x04
#define BT_ASCS_REASON_PHY 0x05
#define BT_ASCS_REASON_SDU 0x06
#define BT_ASCS_REASON_RTN 0x07
#define BT_ASCS_REASON_LATENCY 0x08
#define BT_ASCS_REASON_PD 0x09
#define BT_ASCS_REASON_CIS 0x0a
/* Transport QoS Packing */
#define BT_ASCS_QOS_PACKING_SEQ 0x00
#define BT_ASCS_QOS_PACKING_INT 0x01
/* Transport QoS Framing */
#define BT_ASCS_QOS_FRAMING_UNFRAMED 0x00
#define BT_ASCS_QOS_FRAMING_FRAMED 0x01
/* Format of the ASE characteristic, defined in Table 4.6 */
struct bt_ascs_ase_status {
uint8_t id;
uint8_t state;
uint8_t params[0];
} __packed;
struct bt_ascs_codec_config {
uint8_t len;
uint8_t type;
uint8_t data[0];
} __packed;
struct bt_ascs_codec {
uint8_t id;
uint16_t cid;
uint16_t vid;
} __packed;
#define BT_ASCS_PD_NO_PREF 0x00000000
/* ASE_State = 0x01 (Codec Configured), defined in Table 4.7. */
struct bt_ascs_ase_status_config {
uint8_t framing;
uint8_t phy;
uint8_t rtn;
uint16_t latency;
uint8_t pd_min[3];
uint8_t pd_max[3];
uint8_t prefer_pd_min[3];
uint8_t prefer_pd_max[3];
struct bt_ascs_codec codec;
uint8_t cc_len;
/* LTV-formatted Codec-Specific Configuration */
struct bt_ascs_codec_config cc[0];
} __packed;
/* ASE_State = 0x02 (QoS Configured), defined in Table 4.8. */
struct bt_ascs_ase_status_qos {
uint8_t cig_id;
uint8_t cis_id;
uint8_t interval[3];
uint8_t framing;
uint8_t phy;
uint16_t sdu;
uint8_t rtn;
uint16_t latency;
uint8_t pd[3];
} __packed;
/* ASE_Status = 0x03 (Enabling), 0x04 (Streaming), or 0x05 (Disabling) as
* defined in Table 4.9.
*/
struct bt_ascs_ase_status_enable {
uint8_t cig_id;
uint8_t cis_id;
uint8_t metadata_len;
uint8_t metadata[0];
} __packed;
/* ASE Control Point Protocol */
struct bt_ascs_ase_cp {
/* Request/Notification opcode */
uint8_t op;
uint8_t pdu[0];
} __packed;
/* Opcodes */
#define BT_ASCS_CONFIG_OP 0x01
#define BT_ASCS_CONFIG_LATENCY_LOW 0x01
#define BT_ASCS_CONFIG_LATENCY_MEDIUM 0x02
#define BT_ASCS_CONFIG_LATENCY_HIGH 0x03
#define BT_ASCS_CONFIG_PHY_LE_1M 0x01
#define BT_ASCS_CONFIG_PHY_LE_2M 0x02
#define BT_ASCS_CONFIG_PHY_LE_CODED 0x03
struct bt_ascs_config {
/* ASE ID */
uint8_t ase;
/* Target latency */
uint8_t latency;
/* Target PHY */
uint8_t phy;
/* Codec ID */
struct bt_ascs_codec codec;
/* Codec Specific Config Length */
uint8_t cc_len;
/* LTV-formatted Codec-Specific Configuration */
struct bt_ascs_codec_config cc[0];
} __packed;
struct bt_ascs_config_op {
/* Number of ASEs */
uint8_t num_ases;
/* Config Parameters */
struct bt_ascs_config cfg[0];
} __packed;
#define BT_ASCS_QOS_OP 0x02
struct bt_ascs_qos {
/* ASE ID */
uint8_t ase;
/* CIG ID*/
uint8_t cig;
/* CIG ID*/
uint8_t cis;
/* Frame interval */
uint8_t interval[3];
/* Frame framing */
uint8_t framing;
/* PHY */
uint8_t phy;
/* Maximum SDU Size */
uint16_t sdu;
/* Retransmission Effort */
uint8_t rtn;
/* Transport Latency */
uint16_t latency;
/* Presentation Delay */
uint8_t pd[3];
} __packed;
struct bt_ascs_qos_op {
/* Number of ASEs */
uint8_t num_ases;
/* QoS Parameters */
struct bt_ascs_qos qos[0];
} __packed;
#define BT_ASCS_ENABLE_OP 0x03
struct bt_ascs_metadata {
/* ASE ID */
uint8_t ase;
/* Metadata length */
uint8_t len;
/* LTV-formatted Metadata */
uint8_t data[0];
} __packed;
struct bt_ascs_enable_op {
/* Number of ASEs */
uint8_t num_ases;
/* Metadata */
struct bt_ascs_metadata metadata[0];
} __packed;
#define BT_ASCS_START_OP 0x04
struct bt_ascs_start_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_DISABLE_OP 0x05
struct bt_ascs_disable_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_STOP_OP 0x06
struct bt_ascs_stop_op {
/* Number of ASEs */
uint8_t num_ases;
/* ASE IDs */
uint8_t ase[0];
} __packed;
#define BT_ASCS_METADATA_OP 0x07
struct bt_ascs_metadata_op {
/* Number of ASEs */
uint8_t num_ases;
/* Metadata */
struct bt_ascs_metadata metadata[0];
} __packed;
#define BT_ASCS_RELEASE_OP 0x08
struct bt_ascs_release_op {
/* Number of ASEs */
uint8_t num_ases;
/* Ase IDs */
uint8_t ase[0];
} __packed;
struct bt_ascs_cp_ase_rsp {
/* ASE ID */
uint8_t id;
/* Response code */
uint8_t code;
/* Response reason */
uint8_t reason;
} __packed;
struct bt_ascs_cp_rsp {
/* Opcode */
uint8_t op;
/* Number of ASEs */
uint8_t num_ase;
/* ASE response */
struct bt_ascs_cp_ase_rsp ase_rsp[0];
} __packed;
static inline const char *bt_ascs_op_str(uint8_t op)
{
switch (op) {
case BT_ASCS_CONFIG_OP:
return "Config Codec";
case BT_ASCS_QOS_OP:
return "Config QoS";
case BT_ASCS_ENABLE_OP:
return "Enable";
case BT_ASCS_START_OP:
return "Receiver Start Ready";
case BT_ASCS_DISABLE_OP:
return "Disable";
case BT_ASCS_STOP_OP:
return "Receiver Stop Ready";
case BT_ASCS_METADATA_OP:
return "Update Metadata";
case BT_ASCS_RELEASE_OP:
return "Release";
}
return "Unknown";
}
static inline const char *bt_ascs_rsp_str(uint8_t code)
{
switch (code) {
case BT_ASCS_RSP_SUCCESS:
return "Success";
case BT_ASCS_RSP_NOT_SUPPORTED:
return "Unsupported Opcode";
case BT_ASCS_RSP_TRUNCATED:
return "Truncated Operation";
case BT_ASCS_RSP_INVALID_ASE:
return "Invalid ASE_ID";
case BT_ASCS_RSP_INVALID_ASE_STATE:
return "Invalid ASE State";
case BT_ASCS_RSP_INVALID_DIR:
return "Invalid ASE Direction";
case BT_ASCS_RSP_CAP_UNSUPPORTED:
return "Unsupported Capabilities";
case BT_ASCS_RSP_CONF_UNSUPPORTED:
return "Unsupported Configuration Value";
case BT_ASCS_RSP_CONF_REJECTED:
return "Rejected Configuration Value";
case BT_ASCS_RSP_CONF_INVALID:
return "Invalid Configuration Value";
case BT_ASCS_RSP_METADATA_UNSUPPORTED:
return "Unsupported Metadata";
case BT_ASCS_RSP_METADATA_REJECTED:
return "Rejected Metadata";
case BT_ASCS_RSP_METADATA_INVALID:
return "Invalid Metadata";
case BT_ASCS_RSP_NO_MEM:
return "Insufficient Resources";
case BT_ASCS_RSP_UNSPECIFIED:
return "Unspecified Error";
}
return "Unknown";
}
static inline const char *bt_ascs_reason_str(uint8_t reason)
{
switch (reason) {
case BT_ASCS_REASON_NONE:
return "None";
case BT_ASCS_REASON_CODEC:
return "Codec ID";
case BT_ASCS_REASON_CODEC_DATA:
return "Codec Specific Configuration";
case BT_ASCS_REASON_INTERVAL:
return "SDU Interval";
case BT_ASCS_REASON_FRAMING:
return "Framing";
case BT_ASCS_REASON_PHY:
return "PHY";
case BT_ASCS_REASON_SDU:
return "Maximum SDU Size";
case BT_ASCS_REASON_RTN:
return "Retransmission Number";
case BT_ASCS_REASON_LATENCY:
return "Maximum Transport Delay";
case BT_ASCS_REASON_PD:
return "Presentation Delay";
case BT_ASCS_REASON_CIS:
return "Invalid ASE CIS Mapping";
}
return "Unknown";
}

View file

@ -0,0 +1,377 @@
/* Bluetooth Audio Capabilities */
/*
* Copyright (c) 2021 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <sys/byteorder.h>
#include <device.h>
#include <init.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include <bluetooth/audio/audio.h>
#include <bluetooth/audio/capabilities.h>
#include "pacs_internal.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_AUDIO_DEBUG_CAPABILITIES)
#define LOG_MODULE_NAME bt_audio_capability
#include "common/log.h"
static sys_slist_t snks;
static sys_slist_t srcs;
#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS)
/* TODO: The unicast server callbacks uses `const` for many of the pointers,
* wheras the capabilities callbacks do no. The latter should be updated to use
* `const` where possible.
*/
static int unicast_server_config_cb(struct bt_conn *conn,
const struct bt_audio_ep *ep,
uint8_t type,
const struct bt_codec *codec,
struct bt_audio_stream **stream,
struct bt_codec_qos_pref *const pref)
{
struct bt_audio_capability *cap;
sys_slist_t *lst;
if (type == BT_AUDIO_SINK) {
lst = &snks;
} else if (type == BT_AUDIO_SOURCE) {
lst = &srcs;
} else {
BT_ERR("Invalid endpoint type: %u", type);
return -EINVAL;
}
SYS_SLIST_FOR_EACH_CONTAINER(lst, cap, node) {
/* Skip if capabilities don't match */
if (codec->id != cap->codec->id) {
continue;
}
if (cap->ops == NULL || cap->ops->config == NULL) {
return -EACCES;
}
*stream = cap->ops->config(conn, (struct bt_audio_ep *)ep,
cap, (struct bt_codec *)codec);
if (*stream == NULL) {
return -ENOMEM;
}
pref->unframed_supported =
cap->pref.framing == BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED;
pref->phy = cap->pref.phy;
pref->rtn = cap->pref.rtn;
pref->latency = cap->pref.latency;
pref->pd_min = cap->pref.pd_min;
pref->pd_max = cap->pref.pd_max;
pref->pref_pd_min = cap->pref.pref_pd_min;
pref->pref_pd_max = cap->pref.pref_pd_max;
(*stream)->user_data = cap;
return 0;
}
BT_ERR("No capability for type %u and codec ID %u", type, codec->id);
return -EOPNOTSUPP;
}
static int unicast_server_reconfig_cb(struct bt_audio_stream *stream,
uint8_t type,
const struct bt_codec *codec,
struct bt_codec_qos_pref *const pref)
{
struct bt_audio_capability *cap;
sys_slist_t *lst;
if (type == BT_AUDIO_SINK) {
lst = &snks;
} else if (type == BT_AUDIO_SOURCE) {
lst = &srcs;
} else {
BT_ERR("Invalid endpoint type: %u", type);
return -EINVAL;
}
SYS_SLIST_FOR_EACH_CONTAINER(lst, cap, node) {
int err;
if (codec->id != cap->codec->id) {
continue;
}
if (cap->ops == NULL || cap->ops->reconfig == NULL) {
return -EACCES;
}
pref->unframed_supported =
cap->pref.framing == BT_AUDIO_CAPABILITY_UNFRAMED_SUPPORTED;
pref->phy = cap->pref.phy;
pref->rtn = cap->pref.rtn;
pref->latency = cap->pref.latency;
pref->pd_min = cap->pref.pd_min;
pref->pd_max = cap->pref.pd_max;
pref->pref_pd_min = cap->pref.pref_pd_min;
pref->pref_pd_max = cap->pref.pref_pd_max;
err = cap->ops->reconfig(stream, cap,
(struct bt_codec *)codec);
if (err != 0) {
return err;
}
stream->user_data = cap;
return 0;
}
BT_ERR("No capability for type %u and codec ID %u", type, codec->id);
return -EOPNOTSUPP;
}
static int unicast_server_qos_cb(struct bt_audio_stream *stream,
const struct bt_codec_qos *qos)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->qos == NULL) {
return -EACCES;
}
return cap->ops->qos(stream, (struct bt_codec_qos *)qos);
}
static int unicast_server_enable_cb(struct bt_audio_stream *stream,
uint8_t meta_count,
const struct bt_codec_data *meta)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->enable == NULL) {
return -EACCES;
}
return cap->ops->enable(stream, meta_count,
(struct bt_codec_data *)meta);
}
static int unicast_server_start_cb(struct bt_audio_stream *stream)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->start == NULL) {
return -EACCES;
}
return cap->ops->start(stream);
}
static int unicast_server_metadata_cb(struct bt_audio_stream *stream,
uint8_t meta_count,
const struct bt_codec_data *meta)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->metadata == NULL) {
return -EACCES;
}
return cap->ops->metadata(stream, meta_count,
(struct bt_codec_data *)meta);
}
static int unicast_server_disable_cb(struct bt_audio_stream *stream)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->disable == NULL) {
return -EACCES;
}
return cap->ops->disable(stream);
}
static int unicast_server_stop_cb(struct bt_audio_stream *stream)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->stop == NULL) {
return -EACCES;
}
return cap->ops->stop(stream);
}
static int unicast_server_release_cb(struct bt_audio_stream *stream)
{
struct bt_audio_capability *cap = stream->user_data;
if (cap->ops == NULL || cap->ops->release == NULL) {
return -EACCES;
}
return cap->ops->release(stream);
}
static int publish_capability_cb(struct bt_conn *conn, uint8_t type,
uint8_t index, struct bt_codec *codec)
{
struct bt_audio_capability *cap;
sys_slist_t *lst;
uint8_t i;
if (type == BT_AUDIO_SINK) {
lst = &snks;
} else if (type == BT_AUDIO_SOURCE) {
lst = &srcs;
} else {
BT_ERR("Invalid endpoint type: %u", type);
return -EINVAL;
}
i = 0;
SYS_SLIST_FOR_EACH_CONTAINER(lst, cap, node) {
if (i != index) {
i++;
continue;
}
(void)memcpy(codec, cap->codec, sizeof(*codec));
return 0;
}
return -ENOENT;
}
static struct bt_audio_unicast_server_cb unicast_server_cb = {
.config = unicast_server_config_cb,
.reconfig = unicast_server_reconfig_cb,
.qos = unicast_server_qos_cb,
.enable = unicast_server_enable_cb,
.start = unicast_server_start_cb,
.metadata = unicast_server_metadata_cb,
.disable = unicast_server_disable_cb,
.stop = unicast_server_stop_cb,
.release = unicast_server_release_cb,
.publish_capability = publish_capability_cb,
};
#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */
sys_slist_t *bt_audio_capability_get(uint8_t type)
{
switch (type) {
case BT_AUDIO_SINK:
return &snks;
case BT_AUDIO_SOURCE:
return &srcs;
}
return NULL;
}
/* Register Audio Capability */
int bt_audio_capability_register(struct bt_audio_capability *cap)
{
sys_slist_t *lst;
if (!cap || !cap->codec) {
return -EINVAL;
}
lst = bt_audio_capability_get(cap->type);
if (!lst) {
return -EINVAL;
}
BT_DBG("cap %p type 0x%02x codec 0x%02x codec cid 0x%04x "
"codec vid 0x%04x", cap, cap->type, cap->codec->id,
cap->codec->cid, cap->codec->vid);
#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS)
/* Using the capabilities instead of the unicast server directly will
* require the capabilities to register the callbacks, which not only
* will forward the unicast server callbacks, but also ensure that the
* unicast server callbacks are not registered elsewhere
*/
static bool unicast_server_cb_registered;
if (!unicast_server_cb_registered) {
int err;
err = bt_audio_unicast_server_register_cb(&unicast_server_cb);
if (err != 0) {
BT_DBG("Failed to register unicast server callbacks: %d",
err);
return err;
}
unicast_server_cb_registered = true;
}
#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */
sys_slist_append(lst, &cap->node);
#if defined(CONFIG_BT_PACS)
bt_pacs_add_capability(cap->type);
#endif /* CONFIG_BT_PACS */
return 0;
}
/* Unregister Audio Capability */
int bt_audio_capability_unregister(struct bt_audio_capability *cap)
{
sys_slist_t *lst;
if (!cap) {
return -EINVAL;
}
lst = bt_audio_capability_get(cap->type);
if (!lst) {
return -EINVAL;
}
BT_DBG("cap %p type 0x%02x", cap, cap->type);
if (!sys_slist_find_and_remove(lst, &cap->node)) {
return -ENOENT;
}
#if defined(CONFIG_BT_AUDIO_UNICAST_SERVER) && defined(CONFIG_BT_ASCS)
/* If we are removing the last audio capability as the unicast
* server, we unregister the callbacks.
*/
if (sys_slist_is_empty(&snks) && sys_slist_is_empty(&srcs)) {
int err;
err = bt_audio_unicast_server_unregister_cb(&unicast_server_cb);
if (err != 0) {
BT_DBG("Failed to register unicast server callbacks: %d",
err);
return err;
}
}
#endif /* CONFIG_BT_AUDIO_UNICAST_SERVER && CONFIG_BT_ASCS */
#if defined(CONFIG_BT_PACS)
bt_pacs_remove_capability(cap->type);
#endif /* CONFIG_BT_PACS */
return 0;
}

View file

@ -0,0 +1,119 @@
/* @file
* @brief Internal APIs for Audio Endpoint handling
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ascs_internal.h"
#include "stream.h"
#define UNICAST_GROUP_CNT 0
#define UNICAST_GROUP_STREAM_CNT 0
#define BROADCAST_STREAM_CNT 0
#define BT_AUDIO_EP_LOCAL 0x00
#define BT_AUDIO_EP_REMOTE 0x01
/* Temp struct declarations to handle circular dependencies */
struct bt_audio_unicast_group;
struct bt_audio_broadcast_source;
struct bt_audio_broadcast_sink;
struct bt_audio_ep {
uint8_t type;
uint16_t handle;
uint16_t cp_handle;
uint8_t cig_id;
uint8_t cis_id;
struct bt_ascs_ase_status status;
struct bt_audio_stream *stream;
struct bt_codec codec;
struct bt_codec_qos qos;
struct bt_codec_qos_pref qos_pref;
/* TODO: Remove iso from this struct. The reason is that a ASE
* (endpoint) may only be unidirectional, but a single bidirectional CIS
* may used for a sink ASE and a source ASE, so there is not a 1:1
* relationship between ISO and ASEs.
*/
struct bt_iso_chan iso;
struct bt_iso_chan_qos iso_qos;
struct bt_iso_chan_io_qos iso_tx;
struct bt_iso_chan_io_qos iso_rx;
struct bt_gatt_subscribe_params subscribe;
struct bt_gatt_discover_params discover;
/* TODO: Create a union to reduce memory usage */
struct bt_audio_unicast_group *unicast_group;
struct bt_audio_broadcast_source *broadcast_source;
struct bt_audio_broadcast_sink *broadcast_sink;
};
struct bt_audio_unicast_group {
/* QoS used to create the CIG */
struct bt_codec_qos *qos;
struct bt_iso_cig *cig;
/* The ISO API for CIG creation requires an array of pointers to ISO channels */
struct bt_iso_chan *cis[UNICAST_GROUP_STREAM_CNT];
sys_slist_t streams;
};
struct bt_audio_broadcast_source {
uint8_t stream_count;
uint8_t subgroup_count;
uint32_t pd; /** QoS Presentation Delay */
uint32_t broadcast_id; /* 24 bit */
struct bt_le_ext_adv *adv;
struct bt_iso_big *big;
struct bt_iso_chan *bis[BROADCAST_STREAM_CNT];
struct bt_codec_qos *qos;
/* The streams used to create the broadcast source */
struct bt_audio_stream *streams;
};
struct bt_audio_broadcast_sink {
uint8_t index; /* index of broadcast_snks array */
uint8_t stream_count;
uint8_t subgroup_count;
uint16_t pa_interval;
uint16_t iso_interval;
uint16_t biginfo_num_bis;
bool biginfo_received;
bool syncing;
bool big_encrypted;
uint32_t broadcast_id; /* 24 bit */
struct bt_le_per_adv_sync *pa_sync;
struct bt_codec *codec;
struct bt_iso_big *big;
struct bt_iso_chan *bis[BROADCAST_SNK_STREAM_CNT];
/* The streams used to create the broadcast sink */
struct bt_audio_stream *streams;
};
static inline const char *bt_audio_ep_state_str(uint8_t state)
{
switch (state) {
case BT_AUDIO_EP_STATE_IDLE:
return "idle";
case BT_AUDIO_EP_STATE_CODEC_CONFIGURED:
return "codec-configured";
case BT_AUDIO_EP_STATE_QOS_CONFIGURED:
return "qos-configured";
case BT_AUDIO_EP_STATE_ENABLING:
return "enabling";
case BT_AUDIO_EP_STATE_STREAMING:
return "streaming";
case BT_AUDIO_EP_STATE_DISABLING:
return "disabling";
case BT_AUDIO_EP_STATE_RELEASING:
return "releasing";
default:
return "unknown";
}
}
bool bt_audio_ep_is_broadcast_snk(const struct bt_audio_ep *ep);
bool bt_audio_ep_is_broadcast_src(const struct bt_audio_ep *ep);

View file

@ -0,0 +1,390 @@
/* @file
* @brief Bluetooth PACS
*/
/*
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <sys/byteorder.h>
#include <device.h>
#include <init.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include <bluetooth/audio/audio.h>
#include <bluetooth/audio/capabilities.h>
#include "../host/conn_internal.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_PACS)
#define LOG_MODULE_NAME bt_pacs
#include "common/log.h"
#include "pacs_internal.h"
#include "unicast_server.h"
#define PAC_INDICATE_TIMEOUT K_MSEC(10)
#if defined(CONFIG_BT_PAC_SNK) || defined(CONFIG_BT_PAC_SRC)
NET_BUF_SIMPLE_DEFINE_STATIC(read_buf, CONFIG_BT_L2CAP_TX_MTU);
static void pac_data_add(struct net_buf_simple *buf, uint8_t num,
struct bt_codec_data *data)
{
struct bt_pac_codec_capability *cc;
int i;
for (i = 0; i < num; i++) {
struct bt_data *d = &data[i].data;
cc = net_buf_simple_add(buf, sizeof(*cc));
cc->len = d->data_len + sizeof(cc->type);
cc->type = d->type;
net_buf_simple_add_mem(buf, d->data, d->data_len);
}
}
static ssize_t pac_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
struct bt_pacs_read_rsp *rsp;
uint8_t type;
int err;
/* Reset if buffer before using */
net_buf_simple_reset(&read_buf);
rsp = net_buf_simple_add(&read_buf, sizeof(*rsp));
rsp->num_pac = 0;
if (!bt_uuid_cmp(attr->uuid, BT_UUID_PACS_SNK)) {
type = BT_AUDIO_SINK;
} else {
type = BT_AUDIO_SOURCE;
}
if (unicast_server_cb == NULL ||
unicast_server_cb->publish_capability == NULL) {
return bt_gatt_attr_read(conn, attr, buf, len, offset,
read_buf.data, read_buf.len);
}
while (true) {
struct bt_codec codec;
struct bt_pac *pac;
struct bt_pac_meta *meta;
err = unicast_server_cb->publish_capability(conn, type,
rsp->num_pac,
&codec);
if (err != 0) {
break;
}
pac = net_buf_simple_add(&read_buf, sizeof(*pac));
pac->codec.id = codec.id;
pac->codec.cid = sys_cpu_to_le16(codec.cid);
pac->codec.vid = sys_cpu_to_le16(codec.vid);
pac->cc_len = read_buf.len;
pac_data_add(&read_buf, codec.data_count, codec.data);
/* Buffer size shall never be below PAC len since we are just
* append data.
*/
__ASSERT_NO_MSG(read_buf.len >= pac->cc_len);
pac->cc_len = read_buf.len - pac->cc_len;
meta = net_buf_simple_add(&read_buf, sizeof(*meta));
meta->len = read_buf.len;
pac_data_add(&read_buf, codec.meta_count, codec.meta);
meta->len = read_buf.len - meta->len;
BT_DBG("pac #%u: codec capability len %u metadata len %u",
rsp->num_pac, pac->cc_len, meta->len);
rsp->num_pac++;
}
return bt_gatt_attr_read(conn, attr, buf, len, offset, read_buf.data,
read_buf.len);
}
static void context_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
static ssize_t context_read(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
struct bt_pacs_context context = {
/* TODO: This should reflect the ongoing channel contexts */
.snk = 0x0001,
.src = 0x0001,
};
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &context,
sizeof(context));
}
static void supported_context_cfg_changed(const struct bt_gatt_attr *attr,
uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
static ssize_t supported_context_read(struct bt_conn *conn,
const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
struct bt_pacs_context context = {
#if defined(CONFIG_BT_PAC_SNK)
.snk = sys_cpu_to_le16(CONFIG_BT_PACS_SNK_CONTEXT),
#endif
#if defined(CONFIG_BT_PAC_SRC)
.src = sys_cpu_to_le16(CONFIG_BT_PACS_SRC_CONTEXT),
#endif
};
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &context,
sizeof(context));
}
#endif /* CONFIG_BT_PAC_SNK || CONFIG_BT_PAC_SRC */
#if defined(CONFIG_BT_PAC_SNK)
static struct k_work_delayable snks_work;
static uint32_t snk_loc = CONFIG_BT_PAC_SNK_LOC;
static ssize_t snk_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return pac_read(conn, attr, buf, len, offset);
}
static ssize_t snk_loc_read(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &snk_loc,
sizeof(snk_loc));
}
static ssize_t snk_loc_write(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const void *data,
uint16_t len, uint16_t offset, uint8_t flags)
{
if (offset) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (len != sizeof(snk_loc)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
snk_loc = sys_get_le32(data);
return len;
}
static void snk_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
static void snk_loc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SRC)
static struct k_work_delayable srcs_work;
static uint32_t src_loc = CONFIG_BT_PAC_SRC_LOC;
static ssize_t src_read(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return pac_read(conn, attr, buf, len, offset);
}
static ssize_t src_loc_read(struct bt_conn *conn,
const struct bt_gatt_attr *attr, void *buf,
uint16_t len, uint16_t offset)
{
BT_DBG("conn %p attr %p buf %p len %u offset %u", conn, attr, buf, len,
offset);
return bt_gatt_attr_read(conn, attr, buf, len, offset, &src_loc,
sizeof(src_loc));
}
static ssize_t src_loc_write(struct bt_conn *conn,
const struct bt_gatt_attr *attr, const void *data,
uint16_t len, uint16_t offset, uint8_t flags)
{
if (offset) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
if (len != sizeof(src_loc)) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
src_loc = sys_get_le32(data);
return len;
}
static void src_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
static void src_loc_cfg_changed(const struct bt_gatt_attr *attr, uint16_t value)
{
BT_DBG("attr %p value 0x%04x", attr, value);
}
#endif /* CONFIG_BT_PAC_SRC */
#if defined(CONFIG_BT_PAC_SNK) || defined(CONFIG_BT_PAC_SRC)
BT_GATT_SERVICE_DEFINE(pacs_svc,
BT_GATT_PRIMARY_SERVICE(BT_UUID_PACS),
#if defined(CONFIG_BT_PAC_SNK)
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SNK,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT,
snk_read, NULL, NULL),
BT_GATT_CCC(snk_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SNK_LOC,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE |
BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT |
BT_GATT_PERM_WRITE_ENCRYPT,
snk_loc_read, snk_loc_write, NULL),
BT_GATT_CCC(snk_loc_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT),
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SRC)
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SRC,
BT_GATT_CHRC_READ | BT_GATT_CHRC_INDICATE,
BT_GATT_PERM_READ_ENCRYPT,
src_read, NULL, NULL),
BT_GATT_CCC(src_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SRC_LOC,
BT_GATT_CHRC_READ | BT_GATT_CHRC_WRITE |
BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT |
BT_GATT_PERM_WRITE_ENCRYPT,
src_loc_read, src_loc_write, NULL),
BT_GATT_CCC(src_loc_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT),
#endif /* CONFIG_BT_PAC_SNK */
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_CONTEXT,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT,
context_read, NULL, NULL),
BT_GATT_CCC(context_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT),
BT_GATT_CHARACTERISTIC(BT_UUID_PACS_SUPPORTED_CONTEXT,
BT_GATT_CHRC_READ | BT_GATT_CHRC_NOTIFY,
BT_GATT_PERM_READ_ENCRYPT,
supported_context_read, NULL, NULL),
BT_GATT_CCC(supported_context_cfg_changed,
BT_GATT_PERM_READ | BT_GATT_PERM_WRITE_ENCRYPT)
);
#endif /* CONFIG_BT_PAC_SNK || CONFIG_BT_PAC_SRC */
static struct k_work_delayable *bt_pacs_get_work(uint8_t type)
{
switch (type) {
#if defined(CONFIG_BT_PAC_SNK)
case BT_AUDIO_SINK:
return &snks_work;
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SRC)
case BT_AUDIO_SOURCE:
return &srcs_work;
#endif /* CONFIG_BT_PAC_SNK */
}
return NULL;
}
static void pac_indicate(struct k_work *work)
{
#if defined(CONFIG_BT_PAC_SNK) || defined(CONFIG_BT_PAC_SRC)
struct bt_gatt_indicate_params params;
#if defined(CONFIG_BT_PAC_SNK)
if (work == &snks_work.work) {
params.uuid = BT_UUID_PACS_SNK;
}
#endif /* CONFIG_BT_PAC_SNK */
#if defined(CONFIG_BT_PAC_SRC)
if (work == &srcs_work.work) {
params.uuid = BT_UUID_PACS_SRC;
}
#endif /* CONFIG_BT_PAC_SRC */
params.attr = pacs_svc.attrs;
bt_gatt_indicate(NULL, &params);
#endif /* CONFIG_BT_PAC_SNK || CONFIG_BT_PAC_SRC */
}
void bt_pacs_add_capability(uint8_t type)
{
struct k_work_delayable *work;
work = bt_pacs_get_work(type);
if (!work) {
return;
}
/* Initialize handler if it hasn't been initialized */
if (!work->work.handler) {
k_work_init_delayable(work, pac_indicate);
}
k_work_reschedule(work, PAC_INDICATE_TIMEOUT);
}
void bt_pacs_remove_capability(uint8_t type)
{
struct k_work_delayable *work;
work = bt_pacs_get_work(type);
if (!work) {
return;
}
k_work_reschedule(work, PAC_INDICATE_TIMEOUT);
}

View file

@ -0,0 +1,50 @@
/* @file
* @brief Internal APIs for PACS handling
*
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
struct bt_pac_codec {
uint8_t id; /* Codec ID */
uint16_t cid; /* Company ID */
uint16_t vid; /* Vendor specific Codec ID */
} __packed;
/* TODO: Figure out the capabilities types */
#define BT_CODEC_CAP_PARAMS 0x01
#define BT_CODEC_CAP_DRM 0x0a
#define BT_CODEC_CAP_DRM_VALUE 0x0b
struct bt_pac_codec_capability {
uint8_t len; /* Codec Capability length */
uint8_t type; /* Codec Capability type */
uint8_t data[0]; /* Codec Capability data */
} __packed;
struct bt_pac_meta {
uint8_t len; /* Metadata Length */
uint8_t value[0]; /* Metadata Value */
} __packed;
struct bt_pac {
struct bt_pac_codec codec; /* Codec ID */
uint8_t cc_len; /* Codec Capabilities Length */
struct bt_pac_codec_capability cc[0]; /* Codec Specific Capabilities */
struct bt_pac_meta meta[0]; /* Metadata */
} __packed;
struct bt_pacs_read_rsp {
uint8_t num_pac; /* Number of PAC Records*/
struct bt_pac pac[0];
} __packed;
struct bt_pacs_context {
uint16_t snk;
uint16_t src;
} __packed;
void bt_pacs_add_capability(uint8_t type);
void bt_pacs_remove_capability(uint8_t type);

View file

@ -0,0 +1,269 @@
/* Bluetooth Audio Stream */
/*
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2021-2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <sys/byteorder.h>
#include <sys/check.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/conn.h>
#include <bluetooth/gatt.h>
#include <bluetooth/audio/audio.h>
#include "../host/conn_internal.h"
#include "../host/iso_internal.h"
#include "endpoint.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_AUDIO_DEBUG_STREAM)
#define LOG_MODULE_NAME bt_audio_stream
#include "common/log.h"
#if defined(CONFIG_BT_AUDIO_UNICAST)
static struct bt_audio_stream *enabling[CONFIG_BT_ISO_MAX_CHAN];
void bt_audio_stream_attach(struct bt_conn *conn,
struct bt_audio_stream *stream,
struct bt_audio_ep *ep,
struct bt_codec *codec)
{
BT_DBG("conn %p stream %p ep %p codec %p", conn, stream, ep, codec);
stream->conn = conn;
stream->codec = codec;
stream->ep = ep;
ep->stream = stream;
if (stream->iso == NULL) {
stream->iso = &ep->iso;
}
}
#define IN_RANGE(_min, _max, _value) \
(_value >= _min && _value <= _max)
static int bt_audio_stream_iso_accept(const struct bt_iso_accept_info *info,
struct bt_iso_chan **iso_chan)
{
int i;
BT_DBG("acl %p", info->acl);
for (i = 0; i < ARRAY_SIZE(enabling); i++) {
struct bt_audio_stream *c = enabling[i];
if (c && c->ep->cig_id == info->cig_id &&
c->ep->cis_id == info->cis_id) {
*iso_chan = enabling[i]->iso;
enabling[i] = NULL;
return 0;
}
}
BT_ERR("No channel listening");
return -EPERM;
}
static struct bt_iso_server iso_server = {
.sec_level = BT_SECURITY_L2,
.accept = bt_audio_stream_iso_accept,
};
int bt_audio_stream_iso_listen(struct bt_audio_stream *stream)
{
static bool server;
int err, i;
struct bt_audio_stream **free_stream = NULL;
BT_DBG("stream %p conn %p", stream, stream->conn);
if (server) {
goto done;
}
err = bt_iso_server_register(&iso_server);
if (err) {
BT_ERR("bt_iso_server_register: %d", err);
return err;
}
server = true;
done:
for (i = 0; i < ARRAY_SIZE(enabling); i++) {
if (enabling[i] == stream) {
return 0;
}
if (enabling[i] == NULL && free_stream == NULL) {
free_stream = &enabling[i];
}
}
if (free_stream != NULL) {
*free_stream = stream;
return 0;
}
BT_ERR("Unable to listen: no slot left");
return -ENOSPC;
}
int bt_audio_codec_qos_to_iso_qos(struct bt_iso_chan_qos *qos,
struct bt_codec_qos *codec)
{
struct bt_iso_chan_io_qos *io;
switch (codec->dir) {
case BT_CODEC_QOS_IN:
io = qos->rx;
break;
case BT_CODEC_QOS_OUT:
io = qos->tx;
break;
case BT_CODEC_QOS_INOUT:
io = qos->rx = qos->tx;
break;
default:
return -EINVAL;
}
io->sdu = codec->sdu;
io->phy = codec->phy;
io->rtn = codec->rtn;
return 0;
}
bool bt_audio_valid_qos(const struct bt_codec_qos *qos)
{
if (qos->interval < BT_ISO_INTERVAL_MIN ||
qos->interval > BT_ISO_INTERVAL_MAX) {
BT_DBG("Interval not within allowed range: %u (%u-%u)",
qos->interval, BT_ISO_INTERVAL_MIN, BT_ISO_INTERVAL_MAX);
return false;
}
if (qos->framing > BT_CODEC_QOS_FRAMED) {
BT_DBG("Invalid Framing 0x%02x", qos->framing);
return false;
}
if (qos->phy != BT_CODEC_QOS_1M &&
qos->phy != BT_CODEC_QOS_2M &&
qos->phy != BT_CODEC_QOS_CODED) {
BT_DBG("Invalid PHY 0x%02x", qos->phy);
return false;
}
if (qos->sdu > BT_ISO_MAX_SDU) {
BT_DBG("Invalid SDU %u", qos->sdu);
return false;
}
if (qos->latency < BT_ISO_LATENCY_MIN ||
qos->latency > BT_ISO_LATENCY_MAX) {
BT_DBG("Invalid Latency %u", qos->latency);
return false;
}
return true;
}
static bool bt_audio_stream_is_broadcast(const struct bt_audio_stream *stream)
{
/* TODO: Implement */
return false;
}
bool bt_audio_valid_stream_qos(const struct bt_audio_stream *stream,
const struct bt_codec_qos *qos)
{
const struct bt_codec_qos_pref *qos_pref = &stream->ep->qos_pref;
if (qos_pref->latency < qos->latency) {
BT_DBG("Latency %u higher than preferred max %u",
qos->latency, qos_pref->latency);
return false;
}
if (!IN_RANGE(qos_pref->pd_min, qos_pref->pd_max, qos->pd)) {
BT_DBG("Presentation Delay not within range: min %u max %u pd %u",
qos_pref->pd_min, qos_pref->pd_max, qos->pd);
return false;
}
return true;
}
void bt_audio_stream_detach(struct bt_audio_stream *stream)
{
const bool is_broadcast = bt_audio_stream_is_broadcast(stream);
BT_DBG("stream %p", stream);
stream->conn = NULL;
stream->codec = NULL;
stream->ep->stream = NULL;
stream->ep = NULL;
if (!is_broadcast) {
bt_audio_stream_disconnect(stream);
}
}
int bt_audio_stream_disconnect(struct bt_audio_stream *stream)
{
int i;
BT_DBG("stream %p iso %p", stream, stream->iso);
if (stream == NULL) {
return -EINVAL;
}
/* Stop listening */
for (i = 0; i < ARRAY_SIZE(enabling); i++) {
if (enabling[i] == stream) {
enabling[i] = NULL;
break;
}
}
if (stream->iso == NULL || stream->iso->iso == NULL) {
return -ENOTCONN;
}
return bt_iso_chan_disconnect(stream->iso);
}
int bt_audio_stream_send(struct bt_audio_stream *stream, struct net_buf *buf)
{
if (stream == NULL || stream->ep == NULL) {
return -EINVAL;
}
if (stream->ep->status.state != BT_AUDIO_EP_STATE_STREAMING) {
BT_DBG("Channel not ready for streaming");
return -EBADMSG;
}
/* TODO: Add checks for broadcast sink */
return bt_iso_chan_send(stream->iso, buf);
}
void bt_audio_stream_cb_register(struct bt_audio_stream *stream,
struct bt_audio_stream_ops *ops)
{
stream->ops = ops;
}
#endif /* CONFIG_BT_AUDIO_UNICAST */

View file

@ -0,0 +1,58 @@
/* @file
* @brief Internal APIs for Audio Stream handling
* Copyright (c) 2020 Intel Corporation
* Copyright (c) 2021-2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Life-span states of ASE. Used only by internal APIs
* dealing with setting ASE to proper state depending on operational
* context.
*
* The values are defined by the ASCS spec and shall not be changed.
*/
enum bt_audio_state {
/** Audio Stream Endpoint Idle state */
BT_AUDIO_EP_STATE_IDLE = 0x00,
/** Audio Stream Endpoint Codec Configured state */
BT_AUDIO_EP_STATE_CODEC_CONFIGURED = 0x01,
/** Audio Stream Endpoint QoS Configured state */
BT_AUDIO_EP_STATE_QOS_CONFIGURED = 0x02,
/** Audio Stream Endpoint Enabling state */
BT_AUDIO_EP_STATE_ENABLING = 0x03,
/** Audio Stream Endpoint Streaming state */
BT_AUDIO_EP_STATE_STREAMING = 0x04,
/** Audio Stream Endpoint Disabling state */
BT_AUDIO_EP_STATE_DISABLING = 0x05,
/** Audio Stream Endpoint Streaming state */
BT_AUDIO_EP_STATE_RELEASING = 0x06,
};
/* Unbind ISO channel */
int bt_audio_cig_terminate(struct bt_audio_stream *stream);
/* Connect ISO channel */
int bt_audio_stream_connect(struct bt_audio_stream *stream);
/* Disconnect ISO channel */
int bt_audio_stream_disconnect(struct bt_audio_stream *stream);
void bt_audio_stream_reset(struct bt_audio_stream *stream);
void bt_audio_stream_attach(struct bt_conn *conn, struct bt_audio_stream *stream,
struct bt_audio_ep *ep,
struct bt_codec *codec);
int bt_audio_codec_qos_to_iso_qos(struct bt_iso_chan_qos *qos,
struct bt_codec_qos *codec);
void bt_audio_stream_detach(struct bt_audio_stream *stream);
bool bt_audio_valid_qos(const struct bt_codec_qos *qos);
bool bt_audio_valid_stream_qos(const struct bt_audio_stream *stream,
const struct bt_codec_qos *qos);
int bt_audio_stream_iso_listen(struct bt_audio_stream *stream);

View file

@ -0,0 +1,51 @@
/* Bluetooth Audio Unicast Server */
/*
* Copyright (c) 2021-2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/check.h>
#include <bluetooth/audio/audio.h>
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_AUDIO_DEBUG_UNICAST_SERVER)
#define LOG_MODULE_NAME bt_unicast_server
#include "common/log.h"
const struct bt_audio_unicast_server_cb *unicast_server_cb;
int bt_audio_unicast_server_register_cb(const struct bt_audio_unicast_server_cb *cb)
{
CHECKIF(cb == NULL) {
BT_DBG("cb is NULL");
return -EINVAL;
}
if (unicast_server_cb != NULL) {
BT_DBG("callback structure already registered");
return -EALREADY;
}
unicast_server_cb = cb;
return 0;
}
int bt_audio_unicast_server_unregister_cb(const struct bt_audio_unicast_server_cb *cb)
{
CHECKIF(cb == NULL) {
BT_DBG("cb is NULL");
return -EINVAL;
}
if (unicast_server_cb != cb) {
BT_DBG("callback structure not registered");
return -EINVAL;
}
unicast_server_cb = NULL;
return 0;
}

View file

@ -0,0 +1,11 @@
/* Bluetooth Audio Unicast Server */
/*
* Copyright (c) 2021-2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <bluetooth/audio/audio.h>
extern const struct bt_audio_unicast_server_cb *unicast_server_cb;

View file

@ -36,7 +36,7 @@ CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_AUTO_PHY_UPDATE=y
CONFIG_BT_AUDIO=y
CONFIG_BT_AUDIO_UNICAST=y
CONFIG_BT_AUDIO_UNICAST_SERVER=y
CONFIG_BT_AUDIO_BROADCAST=y
CONFIG_BT_ISO_TX_BUF_COUNT=5
CONFIG_BT_VOCS_MAX_INSTANCE_COUNT=1
@ -95,3 +95,7 @@ CONFIG_BT_DEBUG_MCC=y
CONFIG_BT_OTS_LOG_LEVEL_DBG=y
CONFIG_BT_DEBUG_OTC=y
CONFIG_BT_DEBUG_MEDIA_PROXY=y
CONFIG_BT_DEBUG_ASCS=y
CONFIG_BT_DEBUG_PACS=y
CONFIG_BT_AUDIO_DEBUG_UNICAST_SERVER=y