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