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, &param);
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