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_codec * codec)66 int bt_bap_unicast_server_reconfig(struct bt_bap_stream *stream, const struct bt_codec *codec)
67 {
68 struct bt_bap_ep *ep;
69 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
70 BT_BAP_ASCS_REASON_NONE);
71 int err;
72
73 ep = stream->ep;
74
75 if (unicast_server_cb != NULL &&
76 unicast_server_cb->reconfig != NULL) {
77 err = unicast_server_cb->reconfig(stream, ep->dir, codec,
78 &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, &codec, sizeof(codec));
88
89 ascs_ep_set_state(ep, BT_BAP_EP_STATE_CODEC_CONFIGURED);
90
91 return 0;
92 }
93
bt_bap_unicast_server_start(struct bt_bap_stream * stream)94 int bt_bap_unicast_server_start(struct bt_bap_stream *stream)
95 {
96 struct bt_bap_ep *ep = stream->ep;
97
98 if (ep->dir != BT_AUDIO_DIR_SINK) {
99 LOG_DBG("Invalid operation for stream %p with dir %u",
100 stream, ep->dir);
101
102 return -EINVAL;
103 }
104
105 /* If ISO is connected to go streaming state,
106 * else wait for ISO to be connected
107 */
108 if (ep->iso->chan.state == BT_ISO_STATE_CONNECTED) {
109 ascs_ep_set_state(ep, BT_BAP_EP_STATE_STREAMING);
110 } else {
111 ep->receiver_ready = true;
112 }
113
114 return 0;
115 }
116
bt_bap_unicast_server_metadata(struct bt_bap_stream * stream,struct bt_codec_data meta[],size_t meta_count)117 int bt_bap_unicast_server_metadata(struct bt_bap_stream *stream, struct bt_codec_data meta[],
118 size_t meta_count)
119 {
120 struct bt_bap_ep *ep;
121 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
122 BT_BAP_ASCS_REASON_NONE);
123 int err;
124
125
126 if (unicast_server_cb != NULL && unicast_server_cb->metadata != NULL) {
127 err = unicast_server_cb->metadata(stream, meta, meta_count, &rsp);
128 } else {
129 err = -ENOTSUP;
130 }
131
132 ep = stream->ep;
133 for (size_t i = 0U; i < meta_count; i++) {
134 (void)memcpy(&ep->codec.meta[i], &meta[i],
135 sizeof(ep->codec.meta[i]));
136 }
137
138 if (err) {
139 LOG_ERR("Metadata failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
140 return err;
141 }
142
143 /* Set the state to the same state to trigger the notifications */
144 ascs_ep_set_state(ep, ep->status.state);
145
146 return 0;
147 }
148
bt_bap_unicast_server_disable(struct bt_bap_stream * stream)149 int bt_bap_unicast_server_disable(struct bt_bap_stream *stream)
150 {
151 struct bt_bap_ep *ep;
152 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
153 BT_BAP_ASCS_REASON_NONE);
154 int err;
155
156 if (unicast_server_cb != NULL && unicast_server_cb->disable != NULL) {
157 err = unicast_server_cb->disable(stream, &rsp);
158 } else {
159 err = -ENOTSUP;
160 }
161
162 if (err != 0) {
163 LOG_ERR("Disable failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
164 return err;
165 }
166
167 ep = stream->ep;
168
169 /* The ASE state machine goes into different states from this operation
170 * based on whether it is a source or a sink ASE.
171 */
172 if (ep->dir == BT_AUDIO_DIR_SOURCE) {
173 ascs_ep_set_state(ep, BT_BAP_EP_STATE_DISABLING);
174 } else {
175 ascs_ep_set_state(ep, BT_BAP_EP_STATE_QOS_CONFIGURED);
176 }
177
178 return 0;
179 }
180
bt_bap_unicast_server_release(struct bt_bap_stream * stream)181 int bt_bap_unicast_server_release(struct bt_bap_stream *stream)
182 {
183 struct bt_bap_ascs_rsp rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_SUCCESS,
184 BT_BAP_ASCS_REASON_NONE);
185 int err;
186
187 if (unicast_server_cb != NULL && unicast_server_cb->release != NULL) {
188 err = unicast_server_cb->release(stream, &rsp);
189 } else {
190 err = -ENOTSUP;
191 }
192
193 if (err != 0) {
194 LOG_ERR("Release failed: err %d, code %u, reason %u", err, rsp.code, rsp.reason);
195 return err;
196 }
197
198 /* ase_process will set the state to IDLE after sending the
199 * notification, finalizing the release
200 */
201 ascs_ep_set_state(stream->ep, BT_BAP_EP_STATE_RELEASING);
202
203 return 0;
204 }
205
bt_bap_unicast_server_config_ase(struct bt_conn * conn,struct bt_bap_stream * stream,struct bt_codec * codec,const struct bt_codec_qos_pref * qos_pref)206 int bt_bap_unicast_server_config_ase(struct bt_conn *conn, struct bt_bap_stream *stream,
207 struct bt_codec *codec,
208 const struct bt_codec_qos_pref *qos_pref)
209 {
210 return bt_ascs_config_ase(conn, stream, codec, qos_pref);
211 }
212
bt_bap_unicast_server_foreach_ep(struct bt_conn * conn,bt_bap_ep_func_t func,void * user_data)213 void bt_bap_unicast_server_foreach_ep(struct bt_conn *conn, bt_bap_ep_func_t func, void *user_data)
214 {
215 bt_ascs_foreach_ep(conn, func, user_data);
216 }
217