Bluetooth: Audio: Add CAP stream
Add a new stream object, bt_cap_stream, which is an extension of the BAP bt_audio_stream. The purpose of this stream is that we can extend the data stored in the BAP stream for CAP usage, as well as making it more explicit what type of stream should be used for CAP. The callbacks will be extended for CAP in specific use cases, e.g. when starting one or more unicast audio streams. Signed-off-by: Emil Gydesen <emil.gydesen@nordicsemi.no>
This commit is contained in:
parent
7a1e827a8b
commit
d5499e6b87
4 changed files with 184 additions and 2 deletions
|
@ -136,6 +136,21 @@ union bt_cap_set_member {
|
|||
struct bt_csis_client_set_member *csip;
|
||||
};
|
||||
|
||||
struct bt_cap_stream {
|
||||
struct bt_audio_stream bap_stream;
|
||||
struct bt_audio_stream_ops *ops;
|
||||
};
|
||||
|
||||
/** @brief Register Audio operations for a Common Audio Profile stream.
|
||||
*
|
||||
* Register Audio operations for a stream.
|
||||
*
|
||||
* @param stream Stream object.
|
||||
* @param ops Stream operations structure.
|
||||
*/
|
||||
void bt_cap_stream_ops_register(struct bt_cap_stream *stream,
|
||||
struct bt_audio_stream_ops *ops);
|
||||
|
||||
struct bt_cap_unicast_audio_start_param {
|
||||
/** The type of the set. */
|
||||
enum bt_cap_set_type type;
|
||||
|
@ -151,7 +166,7 @@ struct bt_cap_unicast_audio_start_param {
|
|||
* stream[i] will be associated with members[i] if not already
|
||||
* initialized, else the stream will be verified against the member.
|
||||
*/
|
||||
struct bt_audio_stream **streams;
|
||||
struct bt_cap_stream **streams;
|
||||
|
||||
/**
|
||||
* @brief Codec configuration.
|
||||
|
@ -233,7 +248,7 @@ struct bt_cap_broadcast_audio_start_param {
|
|||
size_t count;
|
||||
|
||||
/** Streams for broadcast source. */
|
||||
struct bt_audio_stream **streams;
|
||||
struct bt_cap_stream **streams;
|
||||
|
||||
/**
|
||||
* @brief Codec configuration.
|
||||
|
|
|
@ -57,5 +57,6 @@ zephyr_library_sources_ifdef(CONFIG_BT_BASS bass.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_BT_BASS_CLIENT bass_client.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_HAS has.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_HAS_CLIENT has_client.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_CAP cap_stream.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_CAP_ACCEPTOR cap_acceptor.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_BT_CAP_INITIATOR cap_initiator.c)
|
||||
|
|
|
@ -5,6 +5,9 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
config BT_CAP
|
||||
def_bool BT_CAP_ACCEPTOR || BT_CAP_INITIATOR
|
||||
|
||||
config BT_CAP_ACCEPTOR
|
||||
bool "Common Audio Profile Acceptor Role Support [EXPERIMENTAL]"
|
||||
depends on BT_AUDIO_UNICAST_SERVER || (BT_AUDIO_BROADCAST_SINK && BT_BASS)
|
||||
|
|
163
subsys/bluetooth/audio/cap_stream.c
Normal file
163
subsys/bluetooth/audio/cap_stream.c
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/bluetooth/audio/cap.h>
|
||||
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST)
|
||||
static void cap_stream_configured_cb(struct bt_audio_stream *bap_stream,
|
||||
const struct bt_codec_qos_pref *pref)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->configured != NULL) {
|
||||
ops->configured(bap_stream, pref);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_qos_set_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->qos_set != NULL) {
|
||||
ops->qos_set(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_enabled_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->enabled != NULL) {
|
||||
ops->enabled(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_metadata_updated_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->metadata_updated != NULL) {
|
||||
ops->metadata_updated(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_disabled_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->disabled != NULL) {
|
||||
ops->disabled(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_released_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->released != NULL) {
|
||||
ops->released(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST */
|
||||
|
||||
static void cap_stream_started_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->started != NULL) {
|
||||
ops->started(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
static void cap_stream_stopped_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->stopped != NULL) {
|
||||
ops->stopped(bap_stream);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK)
|
||||
static void cap_stream_recv_cb(struct bt_audio_stream *bap_stream,
|
||||
const struct bt_iso_recv_info *info,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->recv != NULL) {
|
||||
ops->recv(bap_stream, info, buf);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SINK */
|
||||
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST) || defined(CONFIG_BT_AUDIO_BROADCAST_SOURCE)
|
||||
static void cap_stream_sent_cb(struct bt_audio_stream *bap_stream)
|
||||
{
|
||||
struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
|
||||
struct bt_cap_stream,
|
||||
bap_stream);
|
||||
struct bt_audio_stream_ops *ops = cap_stream->ops;
|
||||
|
||||
if (ops != NULL && ops->sent != NULL) {
|
||||
ops->sent(bap_stream);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SOURCE */
|
||||
|
||||
static struct bt_audio_stream_ops bap_stream_ops = {
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST)
|
||||
.configured = cap_stream_configured_cb,
|
||||
.qos_set = cap_stream_qos_set_cb,
|
||||
.enabled = cap_stream_enabled_cb,
|
||||
.metadata_updated = cap_stream_metadata_updated_cb,
|
||||
.disabled = cap_stream_disabled_cb,
|
||||
.released = cap_stream_released_cb,
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST */
|
||||
.started = cap_stream_started_cb,
|
||||
.stopped = cap_stream_stopped_cb,
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST) || defined(CONFIG_BT_AUDIO_BROADCAST_SINK)
|
||||
.recv = cap_stream_recv_cb,
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SINK */
|
||||
#if defined(CONFIG_BT_AUDIO_UNICAST) || defined(CONFIG_BT_AUDIO_BROADCAST_SOURCE)
|
||||
.sent = cap_stream_sent_cb,
|
||||
#endif /* CONFIG_BT_AUDIO_UNICAST || CONFIG_BT_AUDIO_BROADCAST_SOURCE */
|
||||
};
|
||||
|
||||
void bt_cap_stream_ops_register(struct bt_cap_stream *stream,
|
||||
struct bt_audio_stream_ops *ops)
|
||||
{
|
||||
stream->ops = ops;
|
||||
bt_audio_stream_cb_register(&stream->bap_stream, &bap_stream_ops);
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue