1 /*
2 * Copyright (c) 2023 Codecoup
3 * Copyright (c) 2024-2025 Nordic Semiconductor ASA
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #include <errno.h>
9 #include <stdint.h>
10 #include <stdlib.h>
11
12 #include <zephyr/bluetooth/bluetooth.h>
13 #include <zephyr/bluetooth/hci_types.h>
14 #include <zephyr/bluetooth/iso.h>
15 #include <zephyr/fff.h>
16 #include <zephyr/net_buf.h>
17 #include <zephyr/ztest_assert.h>
18
19 #include "conn.h"
20 #include "iso.h"
21
22 /* List of fakes used by this unit tester */
23 #define FFF_FAKES_LIST(FAKE) FAKE(bt_iso_chan_get_tx_sync)
24
25 static struct bt_iso_server *iso_server;
26
27 DEFINE_FAKE_VALUE_FUNC(int, bt_iso_chan_get_tx_sync, const struct bt_iso_chan *,
28 struct bt_iso_tx_info *);
29
bt_iso_chan_send(struct bt_iso_chan * chan,struct net_buf * buf,uint16_t seq_num)30 int bt_iso_chan_send(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num)
31 {
32 if (chan->ops != NULL && chan->ops->sent != NULL) {
33 chan->ops->sent(chan);
34 }
35
36 return 0;
37 }
38
bt_iso_chan_send_ts(struct bt_iso_chan * chan,struct net_buf * buf,uint16_t seq_num,uint32_t ts)39 int bt_iso_chan_send_ts(struct bt_iso_chan *chan, struct net_buf *buf, uint16_t seq_num,
40 uint32_t ts)
41 {
42 if (chan->ops != NULL && chan->ops->sent != NULL) {
43 chan->ops->sent(chan);
44 }
45
46 return 0;
47 }
48
bt_iso_server_register(struct bt_iso_server * server)49 int bt_iso_server_register(struct bt_iso_server *server)
50 {
51 zassert_not_null(server, "server is NULL");
52 zassert_not_null(server->accept, "server->accept is NULL");
53 zassert_is_null(iso_server, "iso_server is NULL");
54
55 iso_server = server;
56
57 return 0;
58 }
59
bt_iso_server_unregister(struct bt_iso_server * server)60 int bt_iso_server_unregister(struct bt_iso_server *server)
61 {
62 zassert_not_null(server, "server is NULL");
63 zassert_equal_ptr(iso_server, server, "not registered");
64
65 iso_server = NULL;
66
67 return 0;
68 }
69
bt_iso_chan_disconnect(struct bt_iso_chan * chan)70 int bt_iso_chan_disconnect(struct bt_iso_chan *chan)
71 {
72 return mock_bt_iso_disconnected(chan, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
73 }
74
mock_bt_iso_init(void)75 void mock_bt_iso_init(void)
76 {
77 FFF_FAKES_LIST(RESET_FAKE);
78 }
79
mock_bt_iso_cleanup(void)80 void mock_bt_iso_cleanup(void)
81 {
82
83 }
84
bt_iso_setup_data_path(const struct bt_iso_chan * chan,uint8_t dir,const struct bt_iso_chan_path * path)85 int bt_iso_setup_data_path(const struct bt_iso_chan *chan, uint8_t dir,
86 const struct bt_iso_chan_path *path)
87 {
88 return 0;
89 }
90
bt_iso_remove_data_path(const struct bt_iso_chan * chan,uint8_t dir)91 int bt_iso_remove_data_path(const struct bt_iso_chan *chan, uint8_t dir)
92 {
93 return 0;
94 }
95
mock_bt_iso_connected(struct bt_conn * iso)96 void mock_bt_iso_connected(struct bt_conn *iso)
97 {
98 struct bt_iso_chan *chan = iso->chan;
99
100 chan->state = BT_ISO_STATE_CONNECTED;
101 chan->iso = iso;
102
103 chan->ops->connected(chan);
104 }
105
mock_bt_iso_accept(struct bt_conn * conn,uint8_t cig_id,uint8_t cis_id,struct bt_iso_chan ** chan)106 int mock_bt_iso_accept(struct bt_conn *conn, uint8_t cig_id, uint8_t cis_id,
107 struct bt_iso_chan **chan)
108 {
109 struct bt_iso_accept_info info = {
110 .acl = conn,
111 .cig_id = cig_id,
112 .cis_id = cis_id,
113 };
114 struct bt_conn *iso;
115 int err;
116
117 zassert_not_null(iso_server, "iso_server is NULL");
118
119 err = iso_server->accept(&info, chan);
120 if (err != 0) {
121 return err;
122 }
123
124 zassert_not_null(*chan, "chan is NULL");
125
126 iso = malloc(sizeof(struct bt_conn));
127 zassert_not_null(iso);
128
129 iso->chan = (*chan);
130 mock_bt_iso_connected(iso);
131
132 return 0;
133 }
134
mock_bt_iso_disconnected(struct bt_iso_chan * chan,uint8_t err)135 int mock_bt_iso_disconnected(struct bt_iso_chan *chan, uint8_t err)
136 {
137 chan->state = BT_ISO_STATE_DISCONNECTED;
138 chan->ops->disconnected(chan, err);
139 free(chan->iso);
140 chan->iso = NULL;
141
142 return 0;
143 }
144
145 #if defined(CONFIG_BT_BAP_BROADCAST_SOURCE)
146 static struct bt_iso_big_cb *iso_cb;
147
bt_iso_big_register_cb(struct bt_iso_big_cb * cb)148 int bt_iso_big_register_cb(struct bt_iso_big_cb *cb)
149 {
150 if (cb == NULL) {
151 return -EINVAL;
152 }
153
154 iso_cb = cb;
155
156 return 0;
157 }
158
bt_iso_big_create(struct bt_le_ext_adv * padv,struct bt_iso_big_create_param * param,struct bt_iso_big ** out_big)159 int bt_iso_big_create(struct bt_le_ext_adv *padv, struct bt_iso_big_create_param *param,
160 struct bt_iso_big **out_big)
161 {
162 struct bt_iso_big *big;
163
164 zassert_not_null(out_big);
165 zassert_not_null(param);
166 zassert_not_equal(param->num_bis, 0);
167
168 big = malloc(sizeof(struct bt_iso_big));
169 zassert_not_null(big);
170 big->num_bis = 0U;
171
172 for (uint8_t i = 0U; i < param->num_bis; i++) {
173 struct bt_iso_chan *bis = param->bis_channels[i];
174 struct bt_conn *iso;
175
176 zassert_not_null(bis);
177
178 iso = malloc(sizeof(struct bt_conn));
179 zassert_not_null(iso);
180 big->bis[i] = bis;
181 big->num_bis++;
182
183 iso->chan = bis;
184 mock_bt_iso_connected(iso);
185 }
186
187 *out_big = big;
188
189 if (iso_cb != NULL && iso_cb->started != NULL) {
190 iso_cb->started(big);
191 }
192
193 return 0;
194 }
195
bt_iso_big_terminate(struct bt_iso_big * big)196 int bt_iso_big_terminate(struct bt_iso_big *big)
197 {
198 /* TODO: Call chan->ops->disconnected(*chan); for each BIS */
199 zassert_not_equal(big->num_bis, 0);
200
201 for (uint8_t i = 0U; i < big->num_bis; i++) {
202 struct bt_iso_chan *bis = big->bis[i];
203
204 zassert_not_null(bis, "big %p", big);
205
206 mock_bt_iso_disconnected(bis, BT_HCI_ERR_LOCALHOST_TERM_CONN);
207 }
208
209 if (iso_cb != NULL && iso_cb->stopped != NULL) {
210 iso_cb->stopped(big, BT_HCI_ERR_LOCALHOST_TERM_CONN);
211 }
212
213 free(big);
214
215 return 0;
216 }
217 #endif /* CONFIG_BT_BAP_BROADCAST_SOURCE */
218