1 /*  Bluetooth Audio Unicast Server */
2 
3 /*
4  * Copyright (c) 2021-2023 Nordic Semiconductor ASA
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include <zephyr/sys/check.h>
10 
11 #include <zephyr/bluetooth/audio/audio.h>
12 #include <zephyr/bluetooth/audio/bap.h>
13 
14 #include "bap_iso.h"
15 #include "pacs_internal.h"
16 #include "bap_endpoint.h"
17 
18 #include <zephyr/logging/log.h>
19 
20 LOG_MODULE_REGISTER(bt_bap_unicast_server, CONFIG_BT_BAP_UNICAST_SERVER_LOG_LEVEL);
21 
22 static const struct bt_bap_unicast_server_cb *unicast_server_cb;
23 
bt_bap_unicast_server_register_cb(const struct bt_bap_unicast_server_cb * cb)24 int bt_bap_unicast_server_register_cb(const struct bt_bap_unicast_server_cb *cb)
25 {
26 	int err;
27 
28 	CHECKIF(cb == NULL) {
29 		LOG_DBG("cb is NULL");
30 		return -EINVAL;
31 	}
32 
33 	if (unicast_server_cb != NULL) {
34 		LOG_DBG("callback structure already registered");
35 		return -EALREADY;
36 	}
37 
38 	err = bt_ascs_init(cb);
39 	if (err != 0) {
40 		return err;
41 	}
42 
43 	unicast_server_cb = cb;
44 
45 	return 0;
46 }
47 
bt_bap_unicast_server_unregister_cb(const struct bt_bap_unicast_server_cb * cb)48 int bt_bap_unicast_server_unregister_cb(const struct bt_bap_unicast_server_cb *cb)
49 {
50 	CHECKIF(cb == NULL) {
51 		LOG_DBG("cb is NULL");
52 		return -EINVAL;
53 	}
54 
55 	if (unicast_server_cb != cb) {
56 		LOG_DBG("callback structure not registered");
57 		return -EINVAL;
58 	}
59 
60 	bt_ascs_cleanup();
61 	unicast_server_cb = NULL;
62 
63 	return 0;
64 }
65 
bt_bap_unicast_server_reconfig(struct bt_bap_stream * stream,const struct bt_audio_codec_cfg * codec_cfg)66 int bt_bap_unicast_server_reconfig(struct bt_bap_stream *stream,
67 				   const struct bt_audio_codec_cfg *codec_cfg)
68 {
69 	struct bt_bap_ep *ep;
70 	struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
71 						     BT_BAP_ASCS_REASON_NONE);
72 	int err;
73 
74 	ep = stream->ep;
75 
76 	if (unicast_server_cb != NULL &&
77 		unicast_server_cb->reconfig != NULL) {
78 		err = unicast_server_cb->reconfig(stream, ep->dir, codec_cfg, &ep->qos_pref, &rsp);
79 	} else {
80 		err = -ENOTSUP;
81 	}
82 
83 	if (err != 0) {
84 		return err;
85 	}
86 
87 	(void)memcpy(&ep->codec_cfg, codec_cfg, sizeof(*codec_cfg));
88 
89 	return ascs_ep_set_state(ep, BT_BAP_EP_STATE_CODEC_CONFIGURED);
90 }
91 
bt_bap_unicast_server_start(struct bt_bap_stream * stream)92 int bt_bap_unicast_server_start(struct bt_bap_stream *stream)
93 {
94 	struct bt_bap_ep *ep = stream->ep;
95 
96 	if (ep->dir != BT_AUDIO_DIR_SINK) {
97 		LOG_DBG("Invalid operation for stream %p with dir %u",
98 			stream, ep->dir);
99 
100 		return -EINVAL;
101 	}
102 
103 	/* If ISO is connected to go streaming state,
104 	 * else wait for ISO to be connected
105 	 */
106 	if (ep->iso->chan.state == BT_ISO_STATE_CONNECTED) {
107 		return ascs_ep_set_state(ep, BT_BAP_EP_STATE_STREAMING);
108 	}
109 
110 	ep->receiver_ready = true;
111 
112 	return 0;
113 }
114 
bt_bap_unicast_server_metadata(struct bt_bap_stream * stream,const uint8_t meta[],size_t meta_len)115 int bt_bap_unicast_server_metadata(struct bt_bap_stream *stream, const uint8_t meta[],
116 				   size_t meta_len)
117 {
118 	struct bt_bap_ep *ep;
119 	struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
120 						     BT_BAP_ASCS_REASON_NONE);
121 	int err;
122 
123 	if (meta_len > sizeof(ep->codec_cfg.meta)) {
124 		return -ENOMEM;
125 	}
126 
127 	if (unicast_server_cb != NULL && unicast_server_cb->metadata != NULL) {
128 		err = unicast_server_cb->metadata(stream, meta, meta_len, &rsp);
129 	} else {
130 		err = -ENOTSUP;
131 	}
132 
133 
134 	if (err) {
135 		LOG_ERR("Metadata failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
136 		return err;
137 	}
138 
139 	ep = stream->ep;
140 	(void)memcpy(ep->codec_cfg.meta, meta, meta_len);
141 
142 	/* Set the state to the same state to trigger the notifications */
143 	return ascs_ep_set_state(ep, ep->status.state);
144 }
145 
bt_bap_unicast_server_disable(struct bt_bap_stream * stream)146 int bt_bap_unicast_server_disable(struct bt_bap_stream *stream)
147 {
148 	return bt_ascs_disable_ase(stream->ep);
149 }
150 
bt_bap_unicast_server_release(struct bt_bap_stream * stream)151 int bt_bap_unicast_server_release(struct bt_bap_stream *stream)
152 {
153 	return bt_ascs_release_ase(stream->ep);
154 }
155 
bt_bap_unicast_server_config_ase(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_audio_codec_cfg * codec_cfg,const struct bt_audio_codec_qos_pref * qos_pref)156 int bt_bap_unicast_server_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream,
157 				     struct bt_audio_codec_cfg *codec_cfg,
158 				     const struct bt_audio_codec_qos_pref *qos_pref)
159 {
160 	return bt_ascs_config_ase(conn, stream, codec_cfg, qos_pref);
161 }
162 
bt_bap_unicast_server_foreach_ep(struct bt_conn * conn,bt_bap_ep_func_t func,void * user_data)163 void bt_bap_unicast_server_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data)
164 {
165 	bt_ascs_foreach_ep(conn, func, user_data);
166 }
167