1 /** @file
2 * @brief Advance Audio Distribution Profile.
3 */
4
5 /*
6 * Copyright (c) 2015-2016 Intel Corporation
7 * Copyright 2021,2024 NXP
8 *
9 * SPDX-License-Identifier: Apache-2.0
10 */
11
12 #include <zephyr/kernel.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <zephyr/sys/atomic.h>
16 #include <zephyr/sys/byteorder.h>
17 #include <zephyr/sys/util.h>
18 #include <zephyr/sys/printk.h>
19
20 #include <zephyr/bluetooth/bluetooth.h>
21 #include <zephyr/bluetooth/l2cap.h>
22 #include <zephyr/bluetooth/classic/avdtp.h>
23 #include <zephyr/bluetooth/classic/a2dp_codec_sbc.h>
24 #include <zephyr/bluetooth/classic/a2dp.h>
25
26 #include "common/assert.h"
27
28 #define A2DP_SBC_PAYLOAD_TYPE (0x60U)
29
30 #define A2DP_AVDTP(_avdtp) CONTAINER_OF(_avdtp, struct bt_a2dp, session)
31 #define DISCOVER_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_discover_params, req)
32 #define DISCOVER_PARAM(_discover_param) \
33 CONTAINER_OF(_discover_param, struct bt_a2dp, discover_param)
34 #define GET_CAP_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_get_capabilities_params, req)
35 #define GET_CAP_PARAM(_get_cap_param) \
36 CONTAINER_OF(_get_cap_param, struct bt_a2dp, get_capabilities_param)
37 #define SET_CONF_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_set_configuration_params, req)
38 #define SET_CONF_PARAM(_set_conf_param) \
39 CONTAINER_OF(_set_conf_param, struct bt_a2dp, set_config_param)
40 #define CTRL_REQ(_req) CONTAINER_OF(_req, struct bt_avdtp_ctrl_params, req)
41 #define CTRL_PARAM(_ctrl_param) CONTAINER_OF(_ctrl_param, struct bt_a2dp, ctrl_param)
42
43 #include "host/hci_core.h"
44 #include "host/conn_internal.h"
45 #include "host/l2cap_internal.h"
46 #include "avdtp_internal.h"
47 #include "a2dp_internal.h"
48
49 #define LOG_LEVEL CONFIG_BT_A2DP_LOG_LEVEL
50 #include <zephyr/logging/log.h>
51 LOG_MODULE_REGISTER(bt_a2dp);
52
53 #define A2DP_NO_SPACE (-1)
54
55 enum bt_a2dp_internal_state {
56 INTERNAL_STATE_IDLE = 0,
57 INTERNAL_STATE_AVDTP_CONNECTED,
58 };
59
60 struct bt_a2dp {
61 struct bt_avdtp session;
62 struct bt_avdtp_discover_params discover_param;
63 struct bt_a2dp_discover_param *discover_cb_param;
64 struct bt_avdtp_get_capabilities_params get_capabilities_param;
65 struct bt_avdtp_set_configuration_params set_config_param;
66 struct bt_avdtp_ctrl_params ctrl_param;
67 uint8_t get_cap_index;
68 enum bt_a2dp_internal_state a2dp_state;
69 uint8_t peer_seps_count;
70 };
71
72 static struct bt_a2dp_cb *a2dp_cb;
73 /* Connections */
74 static struct bt_a2dp connection[CONFIG_BT_MAX_CONN];
75
76 static int bt_a2dp_get_sep_caps(struct bt_a2dp *a2dp);
77
a2dp_get_connection(struct bt_conn * conn)78 static struct bt_a2dp *a2dp_get_connection(struct bt_conn *conn)
79 {
80 struct bt_a2dp *a2dp = &connection[bt_conn_index(conn)];
81
82 if (a2dp->session.br_chan.chan.conn == NULL) {
83 /* Clean the memory area before returning */
84 (void)memset(a2dp, 0, sizeof(struct bt_a2dp));
85 }
86
87 return a2dp;
88 }
89
90 /* The AVDTP L2CAP signal channel established */
a2dp_connected(struct bt_avdtp * session)91 static void a2dp_connected(struct bt_avdtp *session)
92 {
93 struct bt_a2dp *a2dp = A2DP_AVDTP(session);
94
95 a2dp->a2dp_state = INTERNAL_STATE_AVDTP_CONNECTED;
96
97 /* notify a2dp app the connection. */
98 if ((a2dp_cb != NULL) && (a2dp_cb->connected != NULL)) {
99 a2dp_cb->connected(a2dp, 0);
100 }
101 }
102
103 /* The AVDTP L2CAP signal channel released */
a2dp_disconnected(struct bt_avdtp * session)104 static void a2dp_disconnected(struct bt_avdtp *session)
105 {
106 struct bt_a2dp *a2dp = A2DP_AVDTP(session);
107
108 /* notify a2dp app the disconnection. */
109 if ((a2dp_cb != NULL) && (a2dp_cb->disconnected != NULL)) {
110 a2dp_cb->disconnected(a2dp);
111 }
112 }
113
114 /* avdtp alloc buf from upper layer */
a2dp_alloc_buf(struct bt_avdtp * session)115 static struct net_buf *a2dp_alloc_buf(struct bt_avdtp *session)
116 {
117 return NULL;
118 }
119
a2dp_discovery_ind(struct bt_avdtp * session,uint8_t * errcode)120 static int a2dp_discovery_ind(struct bt_avdtp *session, uint8_t *errcode)
121 {
122 *errcode = 0;
123 return 0;
124 }
125
a2dp_get_capabilities_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,struct net_buf * rsp_buf,uint8_t * errcode)126 static int a2dp_get_capabilities_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep,
127 struct net_buf *rsp_buf, uint8_t *errcode)
128 {
129 struct bt_a2dp_ep *ep;
130
131 __ASSERT(sep, "Invalid sep");
132 *errcode = 0;
133 /* Service Category: Media Transport */
134 net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_TRANSPORT);
135 net_buf_add_u8(rsp_buf, 0);
136 /* Service Category: Media Codec */
137 net_buf_add_u8(rsp_buf, BT_AVDTP_SERVICE_MEDIA_CODEC);
138 ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
139 /* Length Of Service Capability */
140 net_buf_add_u8(rsp_buf, ep->codec_cap->len + 2U);
141 /* Media Type */
142 net_buf_add_u8(rsp_buf, sep->sep_info.media_type << 4U);
143 /* Media Codec Type */
144 net_buf_add_u8(rsp_buf, ep->codec_type);
145 /* Codec Info Element */
146 net_buf_add_mem(rsp_buf, &ep->codec_cap->codec_ie[0], ep->codec_cap->len);
147 return 0;
148 }
149
a2dp_process_config_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t int_seid,struct net_buf * buf,uint8_t * errcode,bool reconfig)150 static int a2dp_process_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep,
151 uint8_t int_seid, struct net_buf *buf, uint8_t *errcode,
152 bool reconfig)
153 {
154 struct bt_a2dp *a2dp = A2DP_AVDTP(session);
155 struct bt_a2dp_ep *ep;
156 struct bt_a2dp_stream *stream = NULL;
157 struct bt_a2dp_stream_ops *ops;
158 uint8_t codec_type;
159 uint8_t *codec_info_element;
160 uint16_t codec_info_element_len;
161 struct bt_a2dp_codec_cfg cfg;
162 struct bt_a2dp_codec_ie codec_config;
163 uint8_t rsp_err_code;
164 int err;
165
166 *errcode = 0;
167
168 __ASSERT(sep, "Invalid sep");
169
170 ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
171
172 /* parse the configuration */
173 codec_info_element_len = 4U;
174 err = bt_avdtp_parse_capability_codec(buf, &codec_type, &codec_info_element,
175 &codec_info_element_len);
176 if (err) {
177 *errcode = BT_AVDTP_BAD_ACP_SEID;
178 return -EINVAL;
179 }
180
181 if (codec_type == BT_A2DP_SBC) {
182 struct bt_a2dp_codec_sbc_params *sbc_set;
183 struct bt_a2dp_codec_sbc_params *sbc;
184
185 if (codec_info_element_len != 4U) {
186 *errcode = BT_AVDTP_BAD_ACP_SEID;
187 return -EINVAL;
188 }
189
190 sbc_set = (struct bt_a2dp_codec_sbc_params *)codec_info_element;
191 sbc = (struct bt_a2dp_codec_sbc_params *)&ep->codec_cap->codec_ie[0];
192 if (((BT_A2DP_SBC_SAMP_FREQ(sbc_set) & BT_A2DP_SBC_SAMP_FREQ(sbc)) == 0) ||
193 ((BT_A2DP_SBC_CHAN_MODE(sbc_set) & BT_A2DP_SBC_CHAN_MODE(sbc)) == 0) ||
194 ((BT_A2DP_SBC_BLK_LEN(sbc_set) & BT_A2DP_SBC_BLK_LEN(sbc)) == 0) ||
195 ((BT_A2DP_SBC_SUB_BAND(sbc_set) & BT_A2DP_SBC_SUB_BAND(sbc)) == 0) ||
196 ((BT_A2DP_SBC_ALLOC_MTHD(sbc_set) & BT_A2DP_SBC_ALLOC_MTHD(sbc)) == 0)) {
197 *errcode = BT_AVDTP_BAD_ACP_SEID;
198 return -EINVAL;
199 }
200 }
201
202 /* For reconfig, ep->stream must already be valid, callback can be NULL as default accept.
203 * For !reconfig, config_req must be set to get stream from upper layer
204 */
205 if (reconfig) {
206 stream = ep->stream;
207 if (stream == NULL) {
208 *errcode = BT_AVDTP_BAD_ACP_SEID;
209 return -EINVAL;
210 }
211
212 if (a2dp_cb == NULL || a2dp_cb->reconfig_req == NULL) {
213 goto process_done;
214 }
215 } else if (a2dp_cb == NULL || a2dp_cb->config_req == NULL) {
216 *errcode = BT_AVDTP_BAD_ACP_SEID;
217 return -EINVAL;
218 }
219
220 cfg.codec_config = &codec_config;
221 cfg.codec_config->len = codec_info_element_len;
222 memcpy(&cfg.codec_config->codec_ie[0], codec_info_element,
223 (codec_info_element_len > BT_A2DP_MAX_IE_LENGTH ? BT_A2DP_MAX_IE_LENGTH
224 : codec_info_element_len));
225 if (!reconfig) {
226 err = a2dp_cb->config_req(a2dp, ep, &cfg, &stream, &rsp_err_code);
227 if (!err && stream) {
228 stream->a2dp = a2dp;
229 stream->local_ep = ep;
230 stream->remote_ep_id = int_seid;
231 stream->remote_ep = NULL;
232 stream->codec_config = *cfg.codec_config;
233 ep->stream = stream;
234 } else {
235 *errcode = rsp_err_code != 0 ? rsp_err_code : BT_AVDTP_BAD_ACP_SEID;
236 }
237 } else {
238 err = a2dp_cb->reconfig_req(stream, &cfg, &rsp_err_code);
239 if (err) {
240 *errcode = rsp_err_code;
241 }
242 }
243
244 process_done:
245 if (*errcode == 0) {
246 ops = stream->ops;
247 if ((ops != NULL) && (ops->configured != NULL)) {
248 ops->configured(stream);
249 }
250 }
251
252 return (*errcode == 0) ? 0 : -EINVAL;
253 }
254
a2dp_set_config_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t int_seid,struct net_buf * buf,uint8_t * errcode)255 static int a2dp_set_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t int_seid,
256 struct net_buf *buf, uint8_t *errcode)
257 {
258 __ASSERT(sep, "Invalid sep");
259 return a2dp_process_config_ind(session, sep, int_seid, buf, errcode, false);
260 }
261
a2dp_re_config_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t int_seid,struct net_buf * buf,uint8_t * errcode)262 static int a2dp_re_config_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t int_seid,
263 struct net_buf *buf, uint8_t *errcode)
264 {
265 __ASSERT(sep, "Invalid sep");
266 return a2dp_process_config_ind(session, sep, int_seid, buf, errcode, true);
267 }
268
269 #if defined(CONFIG_BT_A2DP_SINK)
bt_a2dp_media_data_callback(struct bt_avdtp_sep * sep,struct net_buf * buf)270 static void bt_a2dp_media_data_callback(struct bt_avdtp_sep *sep, struct net_buf *buf)
271 {
272 struct bt_avdtp_media_hdr *media_hdr;
273 struct bt_a2dp_ep *ep;
274 struct bt_a2dp_stream *stream;
275
276 __ASSERT(sep, "Invalid sep");
277 ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
278 if (ep->stream == NULL || buf->len < sizeof(*media_hdr)) {
279 return;
280 }
281
282 stream = ep->stream;
283 media_hdr = net_buf_pull_mem(buf, sizeof(*media_hdr));
284
285 stream->ops->recv(stream, buf, sys_get_be16((uint8_t *)&media_hdr->sequence_number),
286 sys_get_be32((uint8_t *)&media_hdr->time_stamp));
287 }
288 #endif
289
290 typedef int (*bt_a2dp_ctrl_req_cb)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code);
291 typedef void (*bt_a2dp_ctrl_done_cb)(struct bt_a2dp_stream *stream);
292
a2dp_ctrl_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode,bt_a2dp_ctrl_req_cb req_cb,bt_a2dp_ctrl_done_cb done_cb,bool clear_stream)293 static int a2dp_ctrl_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode,
294 bt_a2dp_ctrl_req_cb req_cb, bt_a2dp_ctrl_done_cb done_cb,
295 bool clear_stream)
296 {
297 struct bt_a2dp_ep *ep;
298 struct bt_a2dp_stream *stream;
299
300 *errcode = 0;
301 ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
302 if (ep->stream == NULL) {
303 *errcode = BT_AVDTP_BAD_ACP_SEID;
304 return -EINVAL;
305 }
306
307 stream = ep->stream;
308
309 if (req_cb != NULL) {
310 uint8_t rsp_err_code;
311 int err;
312
313 err = req_cb(stream, &rsp_err_code);
314 if (err) {
315 *errcode = rsp_err_code;
316 }
317 }
318
319 if (*errcode == 0) {
320 if (clear_stream) {
321 ep->stream = NULL;
322 }
323
324 if (done_cb != NULL) {
325 done_cb(stream);
326 }
327 }
328
329 return (*errcode == 0) ? 0 : -EINVAL;
330 }
331
a2dp_open_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode)332 static int a2dp_open_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode)
333 {
334 struct bt_a2dp_ep *ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
335 bt_a2dp_ctrl_req_cb req_cb;
336 bt_a2dp_ctrl_done_cb done_cb;
337
338 __ASSERT(sep, "Invalid sep");
339 req_cb = a2dp_cb != NULL ? a2dp_cb->establish_req : NULL;
340 done_cb = (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->established
341 : NULL;
342 return a2dp_ctrl_ind(session, sep, errcode, req_cb, done_cb, false);
343 }
344
a2dp_start_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode)345 static int a2dp_start_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode)
346 {
347 struct bt_a2dp_ep *ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
348 bt_a2dp_ctrl_req_cb req_cb;
349 bt_a2dp_ctrl_done_cb done_cb;
350
351 __ASSERT(sep, "Invalid sep");
352 req_cb = a2dp_cb != NULL ? a2dp_cb->start_req : NULL;
353 done_cb = (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->started : NULL;
354 return a2dp_ctrl_ind(session, sep, errcode, req_cb, done_cb, false);
355 }
356
a2dp_suspend_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode)357 static int a2dp_suspend_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode)
358 {
359 struct bt_a2dp_ep *ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
360 bt_a2dp_ctrl_req_cb req_cb;
361 bt_a2dp_ctrl_done_cb done_cb;
362
363 __ASSERT(sep, "Invalid sep");
364 req_cb = a2dp_cb != NULL ? a2dp_cb->suspend_req : NULL;
365 done_cb =
366 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->suspended : NULL;
367 return a2dp_ctrl_ind(session, sep, errcode, req_cb, done_cb, false);
368 }
369
a2dp_close_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode)370 static int a2dp_close_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode)
371 {
372 struct bt_a2dp_ep *ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
373 bt_a2dp_ctrl_req_cb req_cb;
374 bt_a2dp_ctrl_done_cb done_cb;
375
376 __ASSERT(sep, "Invalid sep");
377 req_cb = a2dp_cb != NULL ? a2dp_cb->release_req : NULL;
378 done_cb =
379 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->released : NULL;
380 return a2dp_ctrl_ind(session, sep, errcode, req_cb, done_cb, true);
381 }
382
a2dp_abort_ind(struct bt_avdtp * session,struct bt_avdtp_sep * sep,uint8_t * errcode)383 static int a2dp_abort_ind(struct bt_avdtp *session, struct bt_avdtp_sep *sep, uint8_t *errcode)
384 {
385 struct bt_a2dp_ep *ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
386 bt_a2dp_ctrl_req_cb req_cb;
387 bt_a2dp_ctrl_done_cb done_cb;
388
389 __ASSERT(sep, "Invalid sep");
390 req_cb = a2dp_cb != NULL ? a2dp_cb->abort_req : NULL;
391 done_cb = (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->aborted : NULL;
392 return a2dp_ctrl_ind(session, sep, errcode, req_cb, done_cb, true);
393 }
394
bt_a2dp_set_config_cb(struct bt_avdtp_req * req,struct net_buf * buf)395 static int bt_a2dp_set_config_cb(struct bt_avdtp_req *req, struct net_buf *buf)
396 {
397 struct bt_a2dp *a2dp = SET_CONF_PARAM(SET_CONF_REQ(req));
398 struct bt_a2dp_ep *ep;
399 struct bt_a2dp_stream *stream;
400 struct bt_a2dp_stream_ops *ops;
401
402 ep = CONTAINER_OF(a2dp->set_config_param.sep, struct bt_a2dp_ep, sep);
403 if (ep->stream == NULL) {
404 return -EINVAL;
405 }
406
407 if ((ep->stream == NULL) || (SET_CONF_REQ(req) != &a2dp->set_config_param)) {
408 return -EINVAL;
409 }
410
411 stream = ep->stream;
412 LOG_DBG("SET CONFIGURATION result:%d", req->status);
413
414 if ((a2dp_cb != NULL) && (a2dp_cb->config_rsp != NULL)) {
415 a2dp_cb->config_rsp(stream, req->status);
416 }
417
418 ops = stream->ops;
419 if ((!req->status) && (ops->configured != NULL)) {
420 ops->configured(stream);
421 }
422 return 0;
423 }
424
bt_a2dp_get_capabilities_cb(struct bt_avdtp_req * req,struct net_buf * buf)425 static int bt_a2dp_get_capabilities_cb(struct bt_avdtp_req *req, struct net_buf *buf)
426 {
427 int err;
428 uint8_t *codec_info_element;
429 struct bt_a2dp *a2dp = GET_CAP_PARAM(GET_CAP_REQ(req));
430 uint16_t codec_info_element_len;
431 uint8_t codec_type;
432 uint8_t user_ret;
433
434 if (GET_CAP_REQ(req) != &a2dp->get_capabilities_param || buf == NULL) {
435 return -EINVAL;
436 }
437
438 LOG_DBG("GET CAPABILITIES result:%d", req->status);
439 if (req->status) {
440 if ((a2dp->discover_cb_param != NULL) && (a2dp->discover_cb_param->cb != NULL)) {
441 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
442 a2dp->discover_cb_param = NULL;
443 }
444 return 0;
445 }
446
447 err = bt_avdtp_parse_capability_codec(buf, &codec_type,
448 &codec_info_element, &codec_info_element_len);
449 if (err) {
450 LOG_DBG("codec capability parsing fail");
451 return 0;
452 }
453
454 if (codec_info_element_len > BT_A2DP_MAX_IE_LENGTH) {
455 codec_info_element_len = BT_A2DP_MAX_IE_LENGTH;
456 }
457
458 if ((a2dp->discover_cb_param != NULL) && (a2dp->discover_cb_param->cb != NULL)) {
459 struct bt_a2dp_ep *ep = NULL;
460 struct bt_a2dp_ep_info *info = &a2dp->discover_cb_param->info;
461
462 info->codec_type = codec_type;
463 info->sep_info = &a2dp->discover_cb_param->seps_info[a2dp->get_cap_index];
464 memcpy(&info->codec_cap.codec_ie, codec_info_element, codec_info_element_len);
465 info->codec_cap.len = codec_info_element_len;
466 user_ret = a2dp->discover_cb_param->cb(a2dp, info, &ep);
467
468 if (ep != NULL) {
469 ep->codec_type = info->codec_type;
470 ep->sep.sep_info = *info->sep_info;
471 *ep->codec_cap = info->codec_cap;
472 ep->stream = NULL;
473 }
474
475 if (user_ret == BT_A2DP_DISCOVER_EP_CONTINUE) {
476 if (bt_a2dp_get_sep_caps(a2dp) != 0) {
477 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
478 a2dp->discover_cb_param = NULL;
479 }
480 } else {
481 a2dp->discover_cb_param = NULL;
482 }
483 }
484
485 return 0;
486 }
487
bt_a2dp_get_sep_caps(struct bt_a2dp * a2dp)488 static int bt_a2dp_get_sep_caps(struct bt_a2dp *a2dp)
489 {
490 int err;
491
492 if ((a2dp->discover_cb_param == NULL) || (a2dp->discover_cb_param->cb == NULL)) {
493 return -EINVAL;
494 }
495
496 if (a2dp->get_cap_index == 0xFFu) {
497 a2dp->get_cap_index = 0U;
498 } else {
499 a2dp->get_cap_index++;
500 }
501
502 for (; a2dp->get_cap_index < a2dp->peer_seps_count; a2dp->get_cap_index++) {
503 if (a2dp->discover_cb_param->seps_info[a2dp->get_cap_index].media_type ==
504 BT_AVDTP_AUDIO) {
505 memset(&a2dp->get_capabilities_param, 0U,
506 sizeof(a2dp->get_capabilities_param));
507 a2dp->get_capabilities_param.req.func = bt_a2dp_get_capabilities_cb;
508 a2dp->get_capabilities_param.stream_endpoint_id =
509 a2dp->discover_cb_param->seps_info[a2dp->get_cap_index].id;
510 err = bt_avdtp_get_capabilities(&a2dp->session,
511 &a2dp->get_capabilities_param);
512
513 if (err) {
514 LOG_DBG("AVDTP get codec_cap failed");
515 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
516 a2dp->discover_cb_param = NULL;
517 }
518
519 return 0;
520 }
521 }
522 return -EINVAL;
523 }
524
bt_a2dp_discover_cb(struct bt_avdtp_req * req,struct net_buf * buf)525 static int bt_a2dp_discover_cb(struct bt_avdtp_req *req, struct net_buf *buf)
526 {
527 struct bt_a2dp *a2dp = DISCOVER_PARAM(DISCOVER_REQ(req));
528 struct bt_avdtp_sep_info *sep_info;
529 int err;
530
531 LOG_DBG("DISCOVER result:%d", req->status);
532 if (a2dp->discover_cb_param == NULL || buf == NULL) {
533 return -EINVAL;
534 }
535
536 a2dp->peer_seps_count = 0U;
537
538 if (!(req->status)) {
539 if (a2dp->discover_cb_param->sep_count == 0) {
540 if (a2dp->discover_cb_param->cb != NULL) {
541 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
542 a2dp->discover_cb_param = NULL;
543 }
544
545 return -EINVAL;
546 }
547
548 do {
549 sep_info = &a2dp->discover_cb_param->seps_info[a2dp->peer_seps_count];
550 err = bt_avdtp_parse_sep(buf, sep_info);
551
552 if (err) {
553 break;
554 }
555
556 a2dp->peer_seps_count++;
557 LOG_DBG("id:%d, inuse:%d, media_type:%d, tsep:%d, ", sep_info->id,
558 sep_info->inuse, sep_info->media_type, sep_info->tsep);
559 } while (a2dp->peer_seps_count < a2dp->discover_cb_param->sep_count);
560
561 /* trigger the getting capability */
562 a2dp->get_cap_index = 0xFFu;
563 if (bt_a2dp_get_sep_caps(a2dp) != 0) {
564 /* the peer_seps' caps is done.*/
565 if (a2dp->discover_cb_param->cb != NULL) {
566 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
567 a2dp->discover_cb_param = NULL;
568 }
569 }
570 } else {
571 if (a2dp->discover_cb_param->cb != NULL) {
572 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
573 a2dp->discover_cb_param = NULL;
574 }
575 }
576
577 return 0;
578 }
579
bt_a2dp_discover(struct bt_a2dp * a2dp,struct bt_a2dp_discover_param * param)580 int bt_a2dp_discover(struct bt_a2dp *a2dp, struct bt_a2dp_discover_param *param)
581 {
582 int err;
583
584 if ((a2dp == NULL) || (param == NULL)) {
585 return -EINVAL;
586 }
587
588 if (a2dp->a2dp_state != INTERNAL_STATE_AVDTP_CONNECTED) {
589 return -EIO;
590 }
591
592 if (a2dp->discover_cb_param != NULL) {
593 return -EBUSY;
594 }
595
596 memset(&a2dp->discover_cb_param, 0U, sizeof(a2dp->discover_cb_param));
597 a2dp->discover_cb_param = param;
598 a2dp->discover_param.req.func = bt_a2dp_discover_cb;
599
600 err = bt_avdtp_discover(&a2dp->session, &a2dp->discover_param);
601 if (err) {
602 if (a2dp->discover_cb_param->cb != NULL) {
603 a2dp->discover_cb_param->cb(a2dp, NULL, NULL);
604 }
605
606 a2dp->discover_cb_param = NULL;
607 }
608
609 return err;
610 }
611
bt_a2dp_stream_cb_register(struct bt_a2dp_stream * stream,struct bt_a2dp_stream_ops * ops)612 void bt_a2dp_stream_cb_register(struct bt_a2dp_stream *stream, struct bt_a2dp_stream_ops *ops)
613 {
614 __ASSERT_NO_MSG(stream);
615 stream->ops = ops;
616 }
617
bt_a2dp_stream_config_set_param(struct bt_a2dp * a2dp,struct bt_a2dp_codec_cfg * config,bt_avdtp_func_t cb,uint8_t remote_id,uint8_t int_id,uint8_t codec_type,struct bt_avdtp_sep * sep)618 static inline void bt_a2dp_stream_config_set_param(struct bt_a2dp *a2dp,
619 struct bt_a2dp_codec_cfg *config,
620 bt_avdtp_func_t cb, uint8_t remote_id,
621 uint8_t int_id, uint8_t codec_type,
622 struct bt_avdtp_sep *sep)
623 {
624 memset(&a2dp->set_config_param, 0U, sizeof(a2dp->set_config_param));
625 a2dp->set_config_param.req.func = cb;
626 a2dp->set_config_param.acp_stream_ep_id = remote_id;
627 a2dp->set_config_param.int_stream_endpoint_id = int_id;
628 a2dp->set_config_param.media_type = BT_AVDTP_AUDIO;
629 a2dp->set_config_param.media_codec_type = codec_type;
630 a2dp->set_config_param.codec_specific_ie_len = config->codec_config->len;
631 a2dp->set_config_param.codec_specific_ie = &config->codec_config->codec_ie[0];
632 a2dp->set_config_param.sep = sep;
633 }
634
bt_a2dp_stream_config(struct bt_a2dp * a2dp,struct bt_a2dp_stream * stream,struct bt_a2dp_ep * local_ep,struct bt_a2dp_ep * remote_ep,struct bt_a2dp_codec_cfg * config)635 int bt_a2dp_stream_config(struct bt_a2dp *a2dp, struct bt_a2dp_stream *stream,
636 struct bt_a2dp_ep *local_ep, struct bt_a2dp_ep *remote_ep,
637 struct bt_a2dp_codec_cfg *config)
638 {
639 if ((a2dp == NULL) || (stream == NULL) || (local_ep == NULL) || (remote_ep == NULL) ||
640 (config == NULL)) {
641 return -EINVAL;
642 }
643
644 if ((local_ep->sep.sep_info.tsep == remote_ep->sep.sep_info.tsep) ||
645 (local_ep->codec_type != remote_ep->codec_type)) {
646 return -EINVAL;
647 }
648
649 stream->local_ep = local_ep;
650 stream->remote_ep = remote_ep;
651 stream->remote_ep_id = remote_ep->sep.sep_info.id;
652 stream->a2dp = a2dp;
653 local_ep->stream = stream;
654 remote_ep->stream = stream;
655 bt_a2dp_stream_config_set_param(a2dp, config, bt_a2dp_set_config_cb,
656 remote_ep->sep.sep_info.id, local_ep->sep.sep_info.id,
657 local_ep->codec_type, &local_ep->sep);
658 return bt_avdtp_set_configuration(&a2dp->session, &a2dp->set_config_param);
659 }
660
661 typedef void (*bt_a2dp_rsp_cb)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code);
662 typedef void (*bt_a2dp_done_cb)(struct bt_a2dp_stream *stream);
663
bt_a2dp_ctrl_cb(struct bt_avdtp_req * req,bt_a2dp_rsp_cb rsp_cb,bt_a2dp_done_cb done_cb,bool clear_stream)664 static int bt_a2dp_ctrl_cb(struct bt_avdtp_req *req, bt_a2dp_rsp_cb rsp_cb, bt_a2dp_done_cb done_cb,
665 bool clear_stream)
666 {
667 struct bt_a2dp *a2dp = CTRL_PARAM(CTRL_REQ(req));
668 struct bt_a2dp_ep *ep;
669 struct bt_a2dp_stream *stream;
670
671 ep = CONTAINER_OF(a2dp->ctrl_param.sep, struct bt_a2dp_ep, sep);
672 if ((ep->stream == NULL) || (CTRL_REQ(req) != &a2dp->ctrl_param)) {
673 return -EINVAL;
674 }
675
676 stream = ep->stream;
677
678 if (clear_stream) {
679 ep->stream = NULL;
680 }
681
682 LOG_DBG("ctrl result:%d", req->status);
683
684 if (rsp_cb != NULL) {
685 rsp_cb(stream, req->status);
686 }
687
688 if ((!req->status) && (done_cb != NULL)) {
689 done_cb(stream);
690 }
691
692 return 0;
693 }
694
bt_a2dp_open_cb(struct bt_avdtp_req * req,struct net_buf * buf)695 static int bt_a2dp_open_cb(struct bt_avdtp_req *req, struct net_buf *buf)
696 {
697 struct bt_a2dp_ep *ep = CONTAINER_OF(CTRL_REQ(req)->sep, struct bt_a2dp_ep, sep);
698 bt_a2dp_rsp_cb rsp_cb = a2dp_cb != NULL ? a2dp_cb->establish_rsp : NULL;
699 bt_a2dp_done_cb done_cb = (ep->stream != NULL && ep->stream->ops != NULL)
700 ? ep->stream->ops->established
701 : NULL;
702
703 return bt_a2dp_ctrl_cb(req, rsp_cb, done_cb, false);
704 }
705
bt_a2dp_start_cb(struct bt_avdtp_req * req,struct net_buf * buf)706 static int bt_a2dp_start_cb(struct bt_avdtp_req *req, struct net_buf *buf)
707 {
708 struct bt_a2dp_ep *ep = CONTAINER_OF(CTRL_REQ(req)->sep, struct bt_a2dp_ep, sep);
709 bt_a2dp_rsp_cb rsp_cb = a2dp_cb != NULL ? a2dp_cb->start_rsp : NULL;
710 bt_a2dp_done_cb done_cb =
711 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->started : NULL;
712
713 return bt_a2dp_ctrl_cb(req, rsp_cb, done_cb, false);
714 }
715
bt_a2dp_suspend_cb(struct bt_avdtp_req * req,struct net_buf * buf)716 static int bt_a2dp_suspend_cb(struct bt_avdtp_req *req, struct net_buf *buf)
717 {
718 struct bt_a2dp_ep *ep = CONTAINER_OF(CTRL_REQ(req)->sep, struct bt_a2dp_ep, sep);
719 bt_a2dp_rsp_cb rsp_cb = a2dp_cb != NULL ? a2dp_cb->suspend_rsp : NULL;
720 bt_a2dp_done_cb done_cb =
721 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->suspended : NULL;
722
723 return bt_a2dp_ctrl_cb(req, rsp_cb, done_cb, false);
724 }
725
bt_a2dp_close_cb(struct bt_avdtp_req * req,struct net_buf * buf)726 static int bt_a2dp_close_cb(struct bt_avdtp_req *req, struct net_buf *buf)
727 {
728 struct bt_a2dp_ep *ep = CONTAINER_OF(CTRL_REQ(req)->sep, struct bt_a2dp_ep, sep);
729 bt_a2dp_rsp_cb rsp_cb = a2dp_cb != NULL ? a2dp_cb->release_rsp : NULL;
730 bt_a2dp_done_cb done_cb =
731 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->released : NULL;
732
733 return bt_a2dp_ctrl_cb(req, rsp_cb, done_cb, true);
734 }
735
bt_a2dp_abort_cb(struct bt_avdtp_req * req,struct net_buf * buf)736 static int bt_a2dp_abort_cb(struct bt_avdtp_req *req, struct net_buf *buf)
737 {
738 struct bt_a2dp_ep *ep = CONTAINER_OF(CTRL_REQ(req)->sep, struct bt_a2dp_ep, sep);
739 bt_a2dp_rsp_cb rsp_cb = a2dp_cb != NULL ? a2dp_cb->abort_rsp : NULL;
740 bt_a2dp_done_cb done_cb =
741 (ep->stream != NULL && ep->stream->ops != NULL) ? ep->stream->ops->aborted : NULL;
742
743 return bt_a2dp_ctrl_cb(req, rsp_cb, done_cb, true);
744 }
745
bt_a2dp_stream_ctrl_pre(struct bt_a2dp_stream * stream,bt_avdtp_func_t cb)746 static int bt_a2dp_stream_ctrl_pre(struct bt_a2dp_stream *stream, bt_avdtp_func_t cb)
747 {
748 struct bt_a2dp *a2dp;
749
750 if ((stream == NULL) || (stream->local_ep == NULL) || (stream->a2dp == NULL)) {
751 return -EINVAL;
752 }
753
754 a2dp = stream->a2dp;
755 memset(&a2dp->ctrl_param, 0U, sizeof(a2dp->ctrl_param));
756 a2dp->ctrl_param.req.func = cb;
757 a2dp->ctrl_param.acp_stream_ep_id = stream->remote_ep != NULL
758 ? stream->remote_ep->sep.sep_info.id
759 : stream->remote_ep_id;
760 a2dp->ctrl_param.sep = &stream->local_ep->sep;
761 return 0;
762 }
763
bt_a2dp_stream_establish(struct bt_a2dp_stream * stream)764 int bt_a2dp_stream_establish(struct bt_a2dp_stream *stream)
765 {
766 int err;
767 struct bt_a2dp *a2dp = stream->a2dp;
768
769 err = bt_a2dp_stream_ctrl_pre(stream, bt_a2dp_open_cb);
770 if (err) {
771 return err;
772 }
773
774 return bt_avdtp_open(&a2dp->session, &a2dp->ctrl_param);
775 }
776
bt_a2dp_stream_release(struct bt_a2dp_stream * stream)777 int bt_a2dp_stream_release(struct bt_a2dp_stream *stream)
778 {
779 int err;
780 struct bt_a2dp *a2dp = stream->a2dp;
781
782 err = bt_a2dp_stream_ctrl_pre(stream, bt_a2dp_close_cb);
783 if (err) {
784 return err;
785 }
786
787 return bt_avdtp_close(&a2dp->session, &a2dp->ctrl_param);
788 }
789
bt_a2dp_stream_start(struct bt_a2dp_stream * stream)790 int bt_a2dp_stream_start(struct bt_a2dp_stream *stream)
791 {
792 int err;
793 struct bt_a2dp *a2dp = stream->a2dp;
794
795 err = bt_a2dp_stream_ctrl_pre(stream, bt_a2dp_start_cb);
796 if (err) {
797 return err;
798 }
799
800 return bt_avdtp_start(&a2dp->session, &a2dp->ctrl_param);
801 }
802
bt_a2dp_stream_suspend(struct bt_a2dp_stream * stream)803 int bt_a2dp_stream_suspend(struct bt_a2dp_stream *stream)
804 {
805 int err;
806 struct bt_a2dp *a2dp = stream->a2dp;
807
808 err = bt_a2dp_stream_ctrl_pre(stream, bt_a2dp_suspend_cb);
809 if (err) {
810 return err;
811 }
812
813 return bt_avdtp_suspend(&a2dp->session, &a2dp->ctrl_param);
814 }
815
bt_a2dp_stream_abort(struct bt_a2dp_stream * stream)816 int bt_a2dp_stream_abort(struct bt_a2dp_stream *stream)
817 {
818 int err;
819 struct bt_a2dp *a2dp = stream->a2dp;
820
821 err = bt_a2dp_stream_ctrl_pre(stream, bt_a2dp_abort_cb);
822 if (err) {
823 return err;
824 }
825
826 return bt_avdtp_abort(&a2dp->session, &a2dp->ctrl_param);
827 }
828
bt_a2dp_stream_reconfig(struct bt_a2dp_stream * stream,struct bt_a2dp_codec_cfg * config)829 int bt_a2dp_stream_reconfig(struct bt_a2dp_stream *stream, struct bt_a2dp_codec_cfg *config)
830 {
831 uint8_t remote_id;
832
833 if ((stream == NULL) || (config == NULL)) {
834 return -EINVAL;
835 }
836
837 remote_id = stream->remote_ep != NULL ? stream->remote_ep->sep.sep_info.id
838 : stream->remote_ep_id;
839 bt_a2dp_stream_config_set_param(stream->a2dp, config, bt_a2dp_set_config_cb, remote_id,
840 stream->local_ep->sep.sep_info.id,
841 stream->local_ep->codec_type, &stream->local_ep->sep);
842 return bt_avdtp_reconfigure(&stream->a2dp->session, &stream->a2dp->set_config_param);
843 }
844
bt_a2dp_get_mtu(struct bt_a2dp_stream * stream)845 uint32_t bt_a2dp_get_mtu(struct bt_a2dp_stream *stream)
846 {
847 if ((stream == NULL) || (stream->local_ep == NULL)) {
848 return 0;
849 }
850
851 return bt_avdtp_get_media_mtu(&stream->local_ep->sep);
852 }
853
854 #if defined(CONFIG_BT_A2DP_SOURCE)
bt_a2dp_stream_send(struct bt_a2dp_stream * stream,struct net_buf * buf,uint16_t seq_num,uint32_t ts)855 int bt_a2dp_stream_send(struct bt_a2dp_stream *stream, struct net_buf *buf, uint16_t seq_num,
856 uint32_t ts)
857 {
858 struct bt_avdtp_media_hdr *media_hdr;
859
860 if (stream == NULL || stream->local_ep == NULL) {
861 return -EINVAL;
862 }
863
864 media_hdr = net_buf_push(buf, sizeof(struct bt_avdtp_media_hdr));
865 memset(media_hdr, 0, sizeof(struct bt_avdtp_media_hdr));
866
867 if (stream->local_ep->codec_type == BT_A2DP_SBC) {
868 media_hdr->playload_type = A2DP_SBC_PAYLOAD_TYPE;
869 }
870
871 media_hdr->RTP_version = BT_AVDTP_RTP_VERSION;
872 media_hdr->synchronization_source = 0U;
873 /* update time_stamp in the buf */
874 sys_put_be32(ts, (uint8_t *)&media_hdr->time_stamp);
875 /* update sequence_number in the buf */
876 sys_put_be16(seq_num, (uint8_t *)&media_hdr->sequence_number);
877 /* send the buf */
878 return bt_avdtp_send_media_data(&stream->local_ep->sep, buf);
879 }
880 #endif
881
a2dp_stream_l2cap_disconnected(struct bt_avdtp * session,struct bt_avdtp_sep * sep)882 int a2dp_stream_l2cap_disconnected(struct bt_avdtp *session, struct bt_avdtp_sep *sep)
883 {
884 struct bt_a2dp_ep *ep;
885
886 __ASSERT(sep, "Invalid sep");
887 ep = CONTAINER_OF(sep, struct bt_a2dp_ep, sep);
888
889 if (ep->stream != NULL) {
890 struct bt_a2dp_stream_ops *ops;
891 struct bt_a2dp_stream *stream = ep->stream;
892
893 ops = stream->ops;
894 /* Many places set ep->stream as NULL like abort and close.
895 * it should be OK without lock protection because
896 * all the related callbacks are in the same zephyr task context.
897 */
898 ep->stream = NULL;
899
900 if ((ops != NULL) && (ops->released != NULL)) {
901 ops->released(stream);
902 }
903 }
904
905 return 0;
906 }
907
908 static const struct bt_avdtp_ops_cb signaling_avdtp_ops = {
909 .connected = a2dp_connected,
910 .disconnected = a2dp_disconnected,
911 .alloc_buf = a2dp_alloc_buf,
912 .discovery_ind = a2dp_discovery_ind,
913 .get_capabilities_ind = a2dp_get_capabilities_ind,
914 .set_configuration_ind = a2dp_set_config_ind,
915 .re_configuration_ind = a2dp_re_config_ind,
916 .open_ind = a2dp_open_ind,
917 .start_ind = a2dp_start_ind,
918 .close_ind = a2dp_close_ind,
919 .suspend_ind = a2dp_suspend_ind,
920 .abort_ind = a2dp_abort_ind,
921 .stream_l2cap_disconnected = a2dp_stream_l2cap_disconnected,
922 };
923
a2dp_accept(struct bt_conn * conn,struct bt_avdtp ** session)924 int a2dp_accept(struct bt_conn *conn, struct bt_avdtp **session)
925 {
926 struct bt_a2dp *a2dp;
927
928 a2dp = a2dp_get_connection(conn);
929 if (!a2dp) {
930 return -ENOMEM;
931 }
932
933 *session = &(a2dp->session);
934 a2dp->session.ops = &signaling_avdtp_ops;
935 LOG_DBG("session: %p", &(a2dp->session));
936
937 return 0;
938 }
939
940 /* The above callback structures need to be packed and passed to AVDTP */
941 static struct bt_avdtp_event_cb avdtp_cb = {
942 .accept = a2dp_accept,
943 };
944
bt_a2dp_init(void)945 int bt_a2dp_init(void)
946 {
947 int err;
948
949 /* Register event handlers with AVDTP */
950 err = bt_avdtp_register(&avdtp_cb);
951 if (err < 0) {
952 LOG_ERR("A2DP registration failed");
953 return err;
954 }
955
956 for (uint8_t i = 0; i < CONFIG_BT_MAX_CONN; i++) {
957 memset(&connection[i], 0, sizeof(struct bt_a2dp));
958 }
959
960 LOG_DBG("A2DP Initialized successfully.");
961 return 0;
962 }
963
bt_a2dp_connect(struct bt_conn * conn)964 struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn)
965 {
966 struct bt_a2dp *a2dp;
967 int err;
968
969 a2dp = a2dp_get_connection(conn);
970 if (!a2dp) {
971 LOG_ERR("Cannot allocate memory");
972 return NULL;
973 }
974
975 a2dp->a2dp_state = INTERNAL_STATE_IDLE;
976 a2dp->session.ops = &signaling_avdtp_ops;
977
978 err = bt_avdtp_connect(conn, &(a2dp->session));
979 if (err < 0) {
980 LOG_DBG("AVDTP Connect failed");
981 return NULL;
982 }
983
984 LOG_DBG("Connect request sent");
985 return a2dp;
986 }
987
bt_a2dp_disconnect(struct bt_a2dp * a2dp)988 int bt_a2dp_disconnect(struct bt_a2dp *a2dp)
989 {
990 __ASSERT_NO_MSG(a2dp);
991 return bt_avdtp_disconnect(&a2dp->session);
992 }
993
bt_a2dp_register_ep(struct bt_a2dp_ep * ep,uint8_t media_type,uint8_t sep_type)994 int bt_a2dp_register_ep(struct bt_a2dp_ep *ep, uint8_t media_type, uint8_t sep_type)
995 {
996 int err;
997
998 __ASSERT_NO_MSG(ep);
999
1000 #if defined(CONFIG_BT_A2DP_SINK)
1001 if (sep_type == BT_AVDTP_SINK) {
1002 ep->sep.media_data_cb = bt_a2dp_media_data_callback;
1003 } else {
1004 ep->sep.media_data_cb = NULL;
1005 }
1006 #else
1007 ep->sep.media_data_cb = NULL;
1008 #endif
1009
1010 err = bt_avdtp_register_sep(media_type, sep_type, &(ep->sep));
1011 if (err < 0) {
1012 return err;
1013 }
1014
1015 return 0;
1016 }
1017
bt_a2dp_register_cb(struct bt_a2dp_cb * cb)1018 int bt_a2dp_register_cb(struct bt_a2dp_cb *cb)
1019 {
1020 a2dp_cb = cb;
1021 return 0;
1022 }
1023