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