1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/bluetooth/bluetooth.h>
9 #include <zephyr/bluetooth/hci.h>
10 #include <zephyr/bluetooth/l2cap.h>
11
12 #include "host/hci_core.h"
13 #include "common.h"
14
15 #include "babblekit/testcase.h"
16 #include "babblekit/flags.h"
17
18 #define LOG_MODULE_NAME main
19 #include <zephyr/logging/log.h>
20 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
21
22 DEFINE_FLAG_STATIC(is_connected);
23 DEFINE_FLAG_STATIC(flag_l2cap_connected);
24 DEFINE_FLAG_STATIC(flag_l2cap_rx_ok);
25
26 static struct bt_l2cap_le_chan test_chan;
27
28 NET_BUF_POOL_DEFINE(sdu_rx_pool,
29 CONFIG_BT_MAX_CONN, BT_L2CAP_SDU_BUF_SIZE(L2CAP_SDU_LEN),
30 8, NULL);
31
alloc_buf_cb(struct bt_l2cap_chan * chan)32 struct net_buf *alloc_buf_cb(struct bt_l2cap_chan *chan)
33 {
34 return net_buf_alloc(&sdu_rx_pool, K_NO_WAIT);
35 }
36
sent_cb(struct bt_l2cap_chan * chan)37 void sent_cb(struct bt_l2cap_chan *chan)
38 {
39 LOG_DBG("%p", chan);
40 }
41
recv_cb(struct bt_l2cap_chan * chan,struct net_buf * buf)42 int recv_cb(struct bt_l2cap_chan *chan, struct net_buf *buf)
43 {
44 static int sdu_count;
45
46 LOG_INF("SDU RX: len %d", buf->len);
47
48 LOG_HEXDUMP_DBG(buf->data, buf->len, "L2CAP RX");
49 sdu_count++;
50
51 /* Verify data follows the expected sequence */
52 for (int i = 0; i < buf->len; i++) {
53 __ASSERT_NO_MSG(buf->data[i] == (uint8_t)i);
54 }
55
56 /* We expect two SDUs */
57 if (sdu_count == 2) {
58 SET_FLAG(flag_l2cap_rx_ok);
59 }
60
61 return 0;
62 }
63
l2cap_chan_connected_cb(struct bt_l2cap_chan * l2cap_chan)64 void l2cap_chan_connected_cb(struct bt_l2cap_chan *l2cap_chan)
65 {
66 struct bt_l2cap_le_chan *chan =
67 CONTAINER_OF(l2cap_chan, struct bt_l2cap_le_chan, chan);
68
69 SET_FLAG(flag_l2cap_connected);
70
71 LOG_DBG("%x (tx mtu %d mps %d) (rx mtu %d mps %d)",
72 l2cap_chan,
73 chan->tx.mtu,
74 chan->tx.mps,
75 chan->rx.mtu,
76 chan->rx.mps);
77 }
78
l2cap_chan_disconnected_cb(struct bt_l2cap_chan * chan)79 void l2cap_chan_disconnected_cb(struct bt_l2cap_chan *chan)
80 {
81 UNSET_FLAG(flag_l2cap_connected);
82 LOG_DBG("%p", chan);
83 }
84
85 static struct bt_l2cap_chan_ops ops = {
86 .connected = l2cap_chan_connected_cb,
87 .disconnected = l2cap_chan_disconnected_cb,
88 .alloc_buf = alloc_buf_cb,
89 .recv = recv_cb,
90 .sent = sent_cb,
91 };
92
server_accept_cb(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** chan)93 int server_accept_cb(struct bt_conn *conn, struct bt_l2cap_server *server,
94 struct bt_l2cap_chan **chan)
95 {
96 struct bt_l2cap_le_chan *le_chan = &test_chan;
97
98 memset(le_chan, 0, sizeof(*le_chan));
99 le_chan->chan.ops = &ops;
100 le_chan->rx.mtu = L2CAP_MTU;
101 *chan = &le_chan->chan;
102
103 LOG_DBG("accepting new l2cap connection");
104
105 return 0;
106 }
107
108 static struct bt_l2cap_server test_l2cap_server = {
109 .accept = server_accept_cb
110 };
111
l2cap_server_register(bt_security_t sec_level)112 static int l2cap_server_register(bt_security_t sec_level)
113 {
114 test_l2cap_server.psm = 0;
115 test_l2cap_server.sec_level = sec_level;
116
117 int err = bt_l2cap_server_register(&test_l2cap_server);
118
119 TEST_ASSERT(err == 0, "Failed to register l2cap server.");
120
121 return test_l2cap_server.psm;
122 }
123
connected(struct bt_conn * conn,uint8_t conn_err)124 static void connected(struct bt_conn *conn, uint8_t conn_err)
125 {
126 char addr[BT_ADDR_LE_STR_LEN];
127
128 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
129
130 if (conn_err) {
131 TEST_FAIL("Failed to connect to %s (%u)", addr, conn_err);
132 return;
133 }
134
135 LOG_DBG("%s", addr);
136
137 SET_FLAG(is_connected);
138 }
139
disconnected(struct bt_conn * conn,uint8_t reason)140 static void disconnected(struct bt_conn *conn, uint8_t reason)
141 {
142 char addr[BT_ADDR_LE_STR_LEN];
143
144 bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
145
146 LOG_DBG("%p %s (reason 0x%02x)", conn, addr, reason);
147
148 UNSET_FLAG(is_connected);
149 }
150
151 BT_CONN_CB_DEFINE(conn_callbacks) = {
152 .connected = connected,
153 .disconnected = disconnected,
154 };
155
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)156 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
157 struct net_buf_simple *ad)
158 {
159 struct bt_le_conn_param *param;
160 struct bt_conn *conn;
161 int err;
162
163 err = bt_le_scan_stop();
164 if (err) {
165 TEST_FAIL("Stop LE scan failed (err %d)", err);
166 return;
167 }
168
169 char str[BT_ADDR_LE_STR_LEN];
170
171 bt_addr_le_to_str(addr, str, sizeof(str));
172
173 LOG_DBG("Connecting to %s", str);
174
175 param = BT_LE_CONN_PARAM_DEFAULT;
176 err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &conn);
177 if (err) {
178 TEST_FAIL("Create conn failed (err %d)", err);
179 return;
180 }
181 }
182
connect(void)183 static void connect(void)
184 {
185 struct bt_le_scan_param scan_param = {
186 .type = BT_LE_SCAN_TYPE_ACTIVE,
187 .options = BT_LE_SCAN_OPT_NONE,
188 .interval = BT_GAP_SCAN_FAST_INTERVAL,
189 .window = BT_GAP_SCAN_FAST_WINDOW,
190 };
191
192 UNSET_FLAG(is_connected);
193
194 int err = bt_le_scan_start(&scan_param, device_found);
195
196 TEST_ASSERT(!err, "Scanning failed to start (err %d)", err);
197
198 LOG_DBG("Central initiating connection...");
199 WAIT_FOR_FLAG(is_connected);
200 }
201
disconnect_device(struct bt_conn * conn,void * data)202 static void disconnect_device(struct bt_conn *conn, void *data)
203 {
204 int err;
205
206 SET_FLAG(is_connected);
207
208 err = bt_conn_disconnect(conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
209 TEST_ASSERT(!err, "Failed to initate disconnect (err %d)", err);
210
211 LOG_DBG("Waiting for disconnection...");
212 WAIT_FOR_FLAG_UNSET(is_connected);
213 }
214
do_dlu(struct bt_conn * conn,void * data)215 static void do_dlu(struct bt_conn *conn, void *data)
216 {
217 int err;
218
219 struct bt_conn_le_data_len_param param;
220
221 param.tx_max_len = 200;
222 param.tx_max_time = 1712;
223
224 err = bt_conn_le_data_len_update(conn, ¶m);
225 TEST_ASSERT(err == 0, "Can't update data length (err %d)", err);
226 }
227
test_procedure_0(void)228 void test_procedure_0(void)
229 {
230 LOG_DBG("L2CAP MPS DUT/central started*");
231 int err;
232
233 err = bt_enable(NULL);
234 TEST_ASSERT(err == 0, "Can't enable Bluetooth (err %d)", err);
235 LOG_DBG("Central Bluetooth initialized.");
236
237 int psm = l2cap_server_register(BT_SECURITY_L1);
238
239 LOG_DBG("Registered server PSM %x", psm);
240 __ASSERT_NO_MSG(psm == L2CAP_PSM);
241
242 connect();
243
244 bt_conn_foreach(BT_CONN_TYPE_LE, do_dlu, NULL);
245
246 WAIT_FOR_FLAG(flag_l2cap_rx_ok);
247
248 bt_conn_foreach(BT_CONN_TYPE_LE, disconnect_device, NULL);
249
250 TEST_PASS("DUT done");
251 }
252
253 static const struct bst_test_instance test_to_add[] = {
254 {
255 .test_id = "test_0",
256 .test_main_f = test_procedure_0,
257 },
258 BSTEST_END_MARKER,
259 };
260
install(struct bst_test_list * tests)261 static struct bst_test_list *install(struct bst_test_list *tests)
262 {
263 return bst_add_tests(tests, test_to_add);
264 };
265
266 bst_test_install_t test_installers[] = {install, NULL};
267
main(void)268 int main(void)
269 {
270 bst_main();
271
272 return 0;
273 }
274