1 /*
2 * Copyright (c) 2022-2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/bluetooth/audio/cap.h>
8 #include <zephyr/sys/check.h>
9
10 #include "cap_internal.h"
11
12 #include <zephyr/logging/log.h>
13
14 LOG_MODULE_REGISTER(bt_cap_stream, CONFIG_BT_CAP_STREAM_LOG_LEVEL);
15
16 #if defined(CONFIG_BT_BAP_UNICAST)
cap_stream_configured_cb(struct bt_bap_stream * bap_stream,const struct bt_audio_codec_qos_pref * pref)17 static void cap_stream_configured_cb(struct bt_bap_stream *bap_stream,
18 const struct bt_audio_codec_qos_pref *pref)
19 {
20 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
21 struct bt_cap_stream,
22 bap_stream);
23 struct bt_bap_stream_ops *ops = cap_stream->ops;
24
25 LOG_DBG("%p", cap_stream);
26
27 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
28 bt_cap_initiator_codec_configured(cap_stream);
29 }
30
31 if (ops != NULL && ops->configured != NULL) {
32 ops->configured(bap_stream, pref);
33 }
34 }
35
cap_stream_qos_set_cb(struct bt_bap_stream * bap_stream)36 static void cap_stream_qos_set_cb(struct bt_bap_stream *bap_stream)
37 {
38 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
39 struct bt_cap_stream,
40 bap_stream);
41 struct bt_bap_stream_ops *ops = cap_stream->ops;
42
43 LOG_DBG("%p", cap_stream);
44
45 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
46 bt_cap_initiator_qos_configured(cap_stream);
47 }
48
49 if (ops != NULL && ops->qos_set != NULL) {
50 ops->qos_set(bap_stream);
51 }
52 }
53
cap_stream_enabled_cb(struct bt_bap_stream * bap_stream)54 static void cap_stream_enabled_cb(struct bt_bap_stream *bap_stream)
55 {
56 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
57 struct bt_cap_stream,
58 bap_stream);
59 struct bt_bap_stream_ops *ops = cap_stream->ops;
60
61 LOG_DBG("%p", cap_stream);
62
63 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
64 bt_cap_initiator_enabled(cap_stream);
65 }
66
67 if (ops != NULL && ops->enabled != NULL) {
68 ops->enabled(bap_stream);
69 }
70 }
71
cap_stream_metadata_updated_cb(struct bt_bap_stream * bap_stream)72 static void cap_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream)
73 {
74 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
75 struct bt_cap_stream,
76 bap_stream);
77 struct bt_bap_stream_ops *ops = cap_stream->ops;
78
79 LOG_DBG("%p", cap_stream);
80
81 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
82 bt_cap_initiator_metadata_updated(cap_stream);
83 }
84
85 if (ops != NULL && ops->metadata_updated != NULL) {
86 ops->metadata_updated(bap_stream);
87 }
88 }
89
cap_stream_disabled_cb(struct bt_bap_stream * bap_stream)90 static void cap_stream_disabled_cb(struct bt_bap_stream *bap_stream)
91 {
92 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
93 struct bt_cap_stream,
94 bap_stream);
95 struct bt_bap_stream_ops *ops = cap_stream->ops;
96
97 LOG_DBG("%p", cap_stream);
98
99 if (ops != NULL && ops->disabled != NULL) {
100 ops->disabled(bap_stream);
101 }
102 }
103
cap_stream_released_cb(struct bt_bap_stream * bap_stream)104 static void cap_stream_released_cb(struct bt_bap_stream *bap_stream)
105 {
106 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
107 struct bt_cap_stream,
108 bap_stream);
109 struct bt_bap_stream_ops *ops = cap_stream->ops;
110
111 LOG_DBG("%p", cap_stream);
112
113 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR)) {
114 bt_cap_initiator_released(cap_stream);
115 }
116
117 if (ops != NULL && ops->released != NULL) {
118 ops->released(bap_stream);
119 }
120 }
121
122 #endif /* CONFIG_BT_BAP_UNICAST */
123
cap_stream_started_cb(struct bt_bap_stream * bap_stream)124 static void cap_stream_started_cb(struct bt_bap_stream *bap_stream)
125 {
126 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
127 struct bt_cap_stream,
128 bap_stream);
129 struct bt_bap_stream_ops *ops = cap_stream->ops;
130
131 LOG_DBG("%p", cap_stream);
132
133 if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR) && IS_ENABLED(CONFIG_BT_BAP_UNICAST)) {
134 bt_cap_initiator_started(cap_stream);
135 }
136
137 if (ops != NULL && ops->started != NULL) {
138 ops->started(bap_stream);
139 }
140 }
141
cap_stream_stopped_cb(struct bt_bap_stream * bap_stream,uint8_t reason)142 static void cap_stream_stopped_cb(struct bt_bap_stream *bap_stream, uint8_t reason)
143 {
144 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
145 struct bt_cap_stream,
146 bap_stream);
147 struct bt_bap_stream_ops *ops = cap_stream->ops;
148
149 LOG_DBG("%p", cap_stream);
150
151 if (ops != NULL && ops->stopped != NULL) {
152 ops->stopped(bap_stream, reason);
153 }
154 }
155
156 #if defined(CONFIG_BT_AUDIO_RX)
cap_stream_recv_cb(struct bt_bap_stream * bap_stream,const struct bt_iso_recv_info * info,struct net_buf * buf)157 static void cap_stream_recv_cb(struct bt_bap_stream *bap_stream,
158 const struct bt_iso_recv_info *info, struct net_buf *buf)
159 {
160 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
161 struct bt_cap_stream,
162 bap_stream);
163 struct bt_bap_stream_ops *ops = cap_stream->ops;
164
165 if (ops != NULL && ops->recv != NULL) {
166 ops->recv(bap_stream, info, buf);
167 }
168 }
169 #endif /* CONFIG_BT_AUDIO_RX */
170
171 #if defined(CONFIG_BT_AUDIO_TX)
cap_stream_sent_cb(struct bt_bap_stream * bap_stream)172 static void cap_stream_sent_cb(struct bt_bap_stream *bap_stream)
173 {
174 struct bt_cap_stream *cap_stream = CONTAINER_OF(bap_stream,
175 struct bt_cap_stream,
176 bap_stream);
177 struct bt_bap_stream_ops *ops = cap_stream->ops;
178
179 if (ops != NULL && ops->sent != NULL) {
180 ops->sent(bap_stream);
181 }
182 }
183 #endif /* CONFIG_BT_AUDIO_TX */
184
185 static struct bt_bap_stream_ops bap_stream_ops = {
186 #if defined(CONFIG_BT_BAP_UNICAST)
187 .configured = cap_stream_configured_cb,
188 .qos_set = cap_stream_qos_set_cb,
189 .enabled = cap_stream_enabled_cb,
190 .metadata_updated = cap_stream_metadata_updated_cb,
191 .disabled = cap_stream_disabled_cb,
192 .released = cap_stream_released_cb,
193 #endif /* CONFIG_BT_BAP_UNICAST */
194 .started = cap_stream_started_cb,
195 .stopped = cap_stream_stopped_cb,
196 #if defined(CONFIG_BT_AUDIO_RX)
197 .recv = cap_stream_recv_cb,
198 #endif /* CONFIG_BT_AUDIO_RX */
199 #if defined(CONFIG_BT_AUDIO_TX)
200 .sent = cap_stream_sent_cb,
201 #endif /* CONFIG_BT_AUDIO_TX */
202 };
203
bt_cap_stream_ops_register_bap(struct bt_cap_stream * cap_stream)204 void bt_cap_stream_ops_register_bap(struct bt_cap_stream *cap_stream)
205 {
206 bt_bap_stream_cb_register(&cap_stream->bap_stream, &bap_stream_ops);
207 }
208
bt_cap_stream_ops_register(struct bt_cap_stream * stream,struct bt_bap_stream_ops * ops)209 void bt_cap_stream_ops_register(struct bt_cap_stream *stream,
210 struct bt_bap_stream_ops *ops)
211 {
212 stream->ops = ops;
213
214 /* CAP basically just forwards the BAP callbacks after doing what it (CAP) needs to do,
215 * so we can just always register the BAP callbacks here
216 *
217 * It is, however, only the CAP Initiator Unicast that depend on the callbacks being set in
218 * order to work, so for the CAP Initiator Unicast we need an additional register to ensure
219 * correctness.
220 */
221
222 bt_cap_stream_ops_register_bap(stream);
223 }
224
225 #if defined(CONFIG_BT_AUDIO_TX)
bt_cap_stream_send(struct bt_cap_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts)226 int bt_cap_stream_send(struct bt_cap_stream *stream, struct net_buf *buf, uint16_t seq_num,
227 uint32_t ts)
228 {
229 CHECKIF(stream == NULL) {
230 LOG_DBG("stream is NULL");
231
232 return -EINVAL;
233 }
234
235 return bt_bap_stream_send(&stream->bap_stream, buf, seq_num, ts);
236 }
237
bt_cap_stream_get_tx_sync(struct bt_cap_stream * stream,struct bt_iso_tx_info * info)238 int bt_cap_stream_get_tx_sync(struct bt_cap_stream *stream, struct bt_iso_tx_info *info)
239 {
240 CHECKIF(stream == NULL) {
241 LOG_DBG("stream is NULL");
242
243 return -EINVAL;
244 }
245
246 return bt_bap_stream_get_tx_sync(&stream->bap_stream, info);
247 }
248 #endif /* CONFIG_BT_AUDIO_TX */
249