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:
parent
5de473782e
commit
03862b3db5
20 changed files with 6460 additions and 38 deletions
File diff suppressed because it is too large
Load diff
264
include/bluetooth/audio/capabilities.h
Normal file
264
include/bluetooth/audio/capabilities.h
Normal 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_ */
|
423
include/bluetooth/audio/lc3.h
Normal file
423
include/bluetooth/audio/lc3.h
Normal 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_ */
|
|
@ -482,6 +482,51 @@ struct bt_uuid_128 {
|
||||||
*/
|
*/
|
||||||
#define BT_UUID_MICS \
|
#define BT_UUID_MICS \
|
||||||
BT_UUID_DECLARE_16(BT_UUID_MICS_VAL)
|
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
|
/** @def BT_UUID_GATT_PRIMARY_VAL
|
||||||
* @brief GATT Primary Service UUID value
|
* @brief GATT Primary Service UUID value
|
||||||
*/
|
*/
|
||||||
|
@ -1790,6 +1835,105 @@ struct bt_uuid_128 {
|
||||||
*/
|
*/
|
||||||
#define BT_UUID_MICS_MUTE \
|
#define BT_UUID_MICS_MUTE \
|
||||||
BT_UUID_DECLARE_16(BT_UUID_MICS_MUTE_VAL)
|
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
|
* Protocol UUIDs
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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 mpl.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_BT_MCS media_proxy.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)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Intel Corporation
|
# Copyright (c) 2020 Intel Corporation
|
||||||
|
# Copyright (c) 2022 Nordic Semiconductor ASA
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
@ -24,39 +25,7 @@ config BT_CCID
|
||||||
This hidden option is enabled when any of the content control
|
This hidden option is enabled when any of the content control
|
||||||
features are enabled.
|
features are enabled.
|
||||||
|
|
||||||
if BT_CONN
|
rsource "Kconfig.baps"
|
||||||
|
|
||||||
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.vocs"
|
rsource "Kconfig.vocs"
|
||||||
rsource "Kconfig.aics"
|
rsource "Kconfig.aics"
|
||||||
rsource "Kconfig.vcs"
|
rsource "Kconfig.vcs"
|
||||||
|
|
32
subsys/bluetooth/audio/Kconfig.ascs
Normal file
32
subsys/bluetooth/audio/Kconfig.ascs
Normal 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
|
132
subsys/bluetooth/audio/Kconfig.baps
Normal file
132
subsys/bluetooth/audio/Kconfig.baps
Normal 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"
|
145
subsys/bluetooth/audio/Kconfig.pacs
Normal file
145
subsys/bluetooth/audio/Kconfig.pacs
Normal 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 server’s 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 server’s 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
|
1955
subsys/bluetooth/audio/ascs.c
Normal file
1955
subsys/bluetooth/audio/ascs.c
Normal file
File diff suppressed because it is too large
Load diff
344
subsys/bluetooth/audio/ascs_internal.h
Normal file
344
subsys/bluetooth/audio/ascs_internal.h
Normal 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";
|
||||||
|
}
|
377
subsys/bluetooth/audio/capabilities.c
Normal file
377
subsys/bluetooth/audio/capabilities.c
Normal 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;
|
||||||
|
}
|
119
subsys/bluetooth/audio/endpoint.h
Normal file
119
subsys/bluetooth/audio/endpoint.h
Normal 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);
|
390
subsys/bluetooth/audio/pacs.c
Normal file
390
subsys/bluetooth/audio/pacs.c
Normal 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, ¶ms);
|
||||||
|
#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);
|
||||||
|
}
|
50
subsys/bluetooth/audio/pacs_internal.h
Normal file
50
subsys/bluetooth/audio/pacs_internal.h
Normal 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);
|
269
subsys/bluetooth/audio/stream.c
Normal file
269
subsys/bluetooth/audio/stream.c
Normal 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 */
|
58
subsys/bluetooth/audio/stream.h
Normal file
58
subsys/bluetooth/audio/stream.h
Normal 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);
|
51
subsys/bluetooth/audio/unicast_server.c
Normal file
51
subsys/bluetooth/audio/unicast_server.c
Normal 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;
|
||||||
|
}
|
11
subsys/bluetooth/audio/unicast_server.h
Normal file
11
subsys/bluetooth/audio/unicast_server.h
Normal 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;
|
|
@ -36,7 +36,7 @@ CONFIG_BT_USER_PHY_UPDATE=y
|
||||||
CONFIG_BT_AUTO_PHY_UPDATE=y
|
CONFIG_BT_AUTO_PHY_UPDATE=y
|
||||||
|
|
||||||
CONFIG_BT_AUDIO=y
|
CONFIG_BT_AUDIO=y
|
||||||
CONFIG_BT_AUDIO_UNICAST=y
|
CONFIG_BT_AUDIO_UNICAST_SERVER=y
|
||||||
CONFIG_BT_AUDIO_BROADCAST=y
|
CONFIG_BT_AUDIO_BROADCAST=y
|
||||||
CONFIG_BT_ISO_TX_BUF_COUNT=5
|
CONFIG_BT_ISO_TX_BUF_COUNT=5
|
||||||
CONFIG_BT_VOCS_MAX_INSTANCE_COUNT=1
|
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_OTS_LOG_LEVEL_DBG=y
|
||||||
CONFIG_BT_DEBUG_OTC=y
|
CONFIG_BT_DEBUG_OTC=y
|
||||||
CONFIG_BT_DEBUG_MEDIA_PROXY=y
|
CONFIG_BT_DEBUG_MEDIA_PROXY=y
|
||||||
|
|
||||||
|
CONFIG_BT_DEBUG_ASCS=y
|
||||||
|
CONFIG_BT_DEBUG_PACS=y
|
||||||
|
CONFIG_BT_AUDIO_DEBUG_UNICAST_SERVER=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue