1 /* main_l2cap_ecred.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2022 Nordic Semiconductor
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 #include "common.h"
10 
11 #define LOG_MODULE_NAME main_l2cap_ecred
12 #include <zephyr/logging/log.h>
13 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_DBG);
14 
15 extern enum bst_result_t bst_result;
16 
17 static struct bt_conn *default_conn;
18 
19 static const struct bt_data ad[] = {
20 	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
21 };
22 
23 #define DATA_MTU CONFIG_BT_L2CAP_TX_MTU
24 #define DATA_MPS 65
25 #define DATA_BUF_SIZE BT_L2CAP_SDU_BUF_SIZE(DATA_MTU)
26 #define L2CAP_CHANNELS 2
27 #define SERVERS 1
28 #define SDU_SEND_COUNT 200
29 #define ECRED_CHAN_MAX 5
30 #define LONG_MSG (DATA_MTU - 500)
31 #define SHORT_MSG (DATA_MPS - 2)
32 #define LONG_MSG_CHAN_IDX 0
33 #define SHORT_MSG_CHAN_IDX 1
34 
35 NET_BUF_POOL_FIXED_DEFINE(rx_data_pool, L2CAP_CHANNELS, BT_L2CAP_BUF_SIZE(DATA_BUF_SIZE), 8, NULL);
36 NET_BUF_POOL_FIXED_DEFINE(tx_data_pool_0, 1, BT_L2CAP_SDU_BUF_SIZE(DATA_MTU),
37 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
38 NET_BUF_POOL_FIXED_DEFINE(tx_data_pool_1, 1, BT_L2CAP_SDU_BUF_SIZE(DATA_MTU),
39 			  CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
40 
41 static struct bt_l2cap_server servers[SERVERS];
42 void send_sdu_chan_worker(struct k_work *item);
43 struct channel {
44 	uint8_t chan_id; /* Internal number that identifies L2CAP channel. */
45 	struct bt_l2cap_le_chan le;
46 	bool in_use;
47 	size_t sdus_received;
48 	size_t bytes_to_send;
49 	uint8_t iteration;
50 	struct net_buf *buf;
51 	struct k_work work;
52 	struct k_work_q work_queue;
53 	uint8_t payload[DATA_MTU];
54 };
55 static struct channel channels[L2CAP_CHANNELS];
56 
57 CREATE_FLAG(is_connected);
58 CREATE_FLAG(unsequenced_data);
59 
60 #define T_STACK_SIZE 512
61 #define T_PRIORITY 5
62 
63 static K_THREAD_STACK_ARRAY_DEFINE(stack_area, L2CAP_CHANNELS, T_STACK_SIZE);
64 static K_SEM_DEFINE(chan_conn_sem, 0, L2CAP_CHANNELS);
65 static K_SEM_DEFINE(all_chan_conn_sem, 0, 1);
66 static K_SEM_DEFINE(all_chan_disconn_sem, 0, 1);
67 static K_SEM_DEFINE(sent_sem, 0, L2CAP_CHANNELS);
68 
init_workqs(void)69 static void init_workqs(void)
70 {
71 	for (int i = 0; i < L2CAP_CHANNELS; i++) {
72 		k_work_queue_init(&channels[i].work_queue);
73 		k_work_queue_start(&channels[i].work_queue, stack_area[i],
74 		K_THREAD_STACK_SIZEOF(*stack_area), T_PRIORITY, NULL);
75 	}
76 }
77 
chan_alloc_buf_cb(struct bt_l2cap_chan * chan)78 static struct net_buf *chan_alloc_buf_cb(struct bt_l2cap_chan *chan)
79 {
80 	LOG_DBG("Allocated on chan %p", chan);
81 	return net_buf_alloc(&rx_data_pool, K_FOREVER);
82 }
83 
chan_recv_cb(struct bt_l2cap_chan * l2cap_chan,struct net_buf * buf)84 static int chan_recv_cb(struct bt_l2cap_chan *l2cap_chan, struct net_buf *buf)
85 {
86 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
87 			l2cap_chan, struct bt_l2cap_le_chan, chan);
88 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
89 	const uint32_t received_iterration = net_buf_pull_le32(buf);
90 
91 	LOG_DBG("received_iterration %i sdus_received %i, chan_id: %d, data_length: %d",
92 		received_iterration, chan->sdus_received, chan->chan_id, buf->len);
93 	if (!TEST_FLAG(unsequenced_data) && received_iterration != chan->sdus_received) {
94 		FAIL("Received out of sequence data.");
95 	}
96 
97 	const int retval = memcmp(buf->data + sizeof(received_iterration),
98 			    chan->payload + sizeof(received_iterration),
99 			    buf->len - sizeof(received_iterration));
100 	if (retval) {
101 		FAIL("Payload received didn't match expected value memcmp returned %i", retval);
102 	}
103 
104 	/*By the time we rx on long msg channel we should have already rx on short msg channel*/
105 	if (chan->chan_id == 0) {
106 		if (channels[SHORT_MSG_CHAN_IDX].sdus_received !=
107 			(channels[LONG_MSG_CHAN_IDX].sdus_received + 1)) {
108 			FAIL("Didn't receive on short msg channel first");
109 		}
110 	}
111 
112 	chan->sdus_received++;
113 
114 	return 0;
115 }
116 
chan_sent_cb(struct bt_l2cap_chan * l2cap_chan)117 static void chan_sent_cb(struct bt_l2cap_chan *l2cap_chan)
118 {
119 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
120 			l2cap_chan, struct bt_l2cap_le_chan, chan);
121 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
122 
123 	chan->buf = 0;
124 	k_sem_give(&sent_sem);
125 
126 	LOG_DBG("chan_id: %d", chan->chan_id);
127 }
128 
chan_connected_cb(struct bt_l2cap_chan * l2cap_chan)129 static void chan_connected_cb(struct bt_l2cap_chan *l2cap_chan)
130 {
131 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
132 			l2cap_chan, struct bt_l2cap_le_chan, chan);
133 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
134 
135 	LOG_DBG("chan_id: %d", chan->chan_id);
136 
137 	LOG_DBG("tx.mtu %d, tx.mps: %d, rx.mtu: %d, rx.mps %d", sys_cpu_to_le16(chan->le.tx.mtu),
138 		sys_cpu_to_le16(chan->le.tx.mps), sys_cpu_to_le16(chan->le.rx.mtu),
139 		sys_cpu_to_le16(chan->le.rx.mps));
140 
141 	k_sem_give(&chan_conn_sem);
142 
143 	if (k_sem_count_get(&chan_conn_sem) == L2CAP_CHANNELS) {
144 		k_sem_give(&all_chan_conn_sem);
145 		k_sem_reset(&all_chan_disconn_sem);
146 	}
147 }
148 
chan_disconnected_cb(struct bt_l2cap_chan * l2cap_chan)149 static void chan_disconnected_cb(struct bt_l2cap_chan *l2cap_chan)
150 {
151 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
152 			l2cap_chan, struct bt_l2cap_le_chan, chan);
153 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
154 
155 	LOG_DBG("chan_id: %d", chan->chan_id);
156 
157 	chan->in_use = false;
158 	k_sem_take(&chan_conn_sem, K_FOREVER);
159 
160 	if (k_sem_count_get(&chan_conn_sem) == 0) {
161 		k_sem_give(&all_chan_disconn_sem);
162 		k_sem_reset(&all_chan_conn_sem);
163 	}
164 }
165 
chan_status_cb(struct bt_l2cap_chan * l2cap_chan,atomic_t * status)166 static void chan_status_cb(struct bt_l2cap_chan *l2cap_chan, atomic_t *status)
167 {
168 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
169 			l2cap_chan, struct bt_l2cap_le_chan, chan);
170 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
171 
172 	LOG_DBG("chan_id: %d, status: %ld", chan->chan_id, *status);
173 }
174 
chan_released_cb(struct bt_l2cap_chan * l2cap_chan)175 static void chan_released_cb(struct bt_l2cap_chan *l2cap_chan)
176 {
177 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
178 			l2cap_chan, struct bt_l2cap_le_chan, chan);
179 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
180 
181 	LOG_DBG("chan_id: %d", chan->chan_id);
182 }
183 
chan_reconfigured_cb(struct bt_l2cap_chan * l2cap_chan)184 static void chan_reconfigured_cb(struct bt_l2cap_chan *l2cap_chan)
185 {
186 	struct bt_l2cap_le_chan *l2cap_le_chan = CONTAINER_OF(
187 			l2cap_chan, struct bt_l2cap_le_chan, chan);
188 	struct channel *chan = CONTAINER_OF(l2cap_le_chan, struct channel, le);
189 
190 	LOG_DBG("chan_id: %d", chan->chan_id);
191 }
192 
193 static const struct bt_l2cap_chan_ops l2cap_ops = {
194 	.alloc_buf = chan_alloc_buf_cb,
195 	.recv = chan_recv_cb,
196 	.sent = chan_sent_cb,
197 	.connected = chan_connected_cb,
198 	.disconnected = chan_disconnected_cb,
199 	.status = chan_status_cb,
200 	.released = chan_released_cb,
201 	.reconfigured = chan_reconfigured_cb,
202 };
203 
get_free_channel(void)204 static struct channel *get_free_channel(void)
205 {
206 	for (int idx = 0; idx < L2CAP_CHANNELS; idx++) {
207 		struct channel *chan = &channels[idx];
208 
209 		if (chan->in_use) {
210 			continue;
211 		}
212 
213 		chan->chan_id = idx;
214 		channels[idx].in_use = true;
215 		(void)memset(chan->payload, idx, sizeof(chan->payload));
216 		k_work_init(&chan->work, send_sdu_chan_worker);
217 		chan->le.chan.ops = &l2cap_ops;
218 		chan->le.rx.mtu = DATA_MTU;
219 		chan->le.rx.mps = DATA_MPS;
220 
221 		return chan;
222 	}
223 
224 	return NULL;
225 }
226 
connect_num_channels(uint8_t num_l2cap_channels)227 static void connect_num_channels(uint8_t num_l2cap_channels)
228 {
229 	struct bt_l2cap_chan *allocated_channels[ECRED_CHAN_MAX] = { NULL };
230 
231 	for (int i = 0; i < num_l2cap_channels; i++) {
232 		struct channel *chan = get_free_channel();
233 
234 		if (!chan) {
235 			FAIL("failed, chan not free");
236 			return;
237 		}
238 
239 		allocated_channels[i] = &chan->le.chan;
240 	}
241 
242 	const int err = bt_l2cap_ecred_chan_connect(default_conn, allocated_channels,
243 						     servers[0].psm);
244 
245 	if (err) {
246 		FAIL("can't connect ecred %d ", err);
247 	}
248 }
249 
disconnect_all_channels(void)250 static void disconnect_all_channels(void)
251 {
252 	for (int i = 0; i < ARRAY_SIZE(channels); i++) {
253 		if (channels[i].in_use) {
254 			LOG_DBG("Disconnecting channel: %d)", channels[i].chan_id);
255 			const int err = bt_l2cap_chan_disconnect(&channels[i].le.chan);
256 
257 			if (err) {
258 				LOG_DBG("can't disconnect channel (err: %d)", err);
259 			}
260 
261 			channels[i].in_use = false;
262 		}
263 	}
264 }
265 
accept(struct bt_conn * conn,struct bt_l2cap_server * server,struct bt_l2cap_chan ** l2cap_chan)266 static int accept(struct bt_conn *conn, struct bt_l2cap_server *server,
267 		  struct bt_l2cap_chan **l2cap_chan)
268 {
269 	struct channel *chan;
270 
271 	chan = get_free_channel();
272 	if (!chan) {
273 		return -ENOMEM;
274 	}
275 
276 	*l2cap_chan = &chan->le.chan;
277 
278 	return 0;
279 }
280 
get_free_server(void)281 static struct bt_l2cap_server *get_free_server(void)
282 {
283 	for (int i = 0; i < SERVERS; i++) {
284 		if (servers[i].psm) {
285 			continue;
286 		}
287 
288 		return &servers[i];
289 	}
290 
291 	return NULL;
292 }
293 
register_l2cap_server(void)294 static void register_l2cap_server(void)
295 {
296 	struct bt_l2cap_server *server;
297 
298 	server = get_free_server();
299 	if (!server) {
300 		FAIL("Failed to get free server");
301 		return;
302 	}
303 
304 	server->accept = accept;
305 	server->psm = 0;
306 
307 	if (bt_l2cap_server_register(server) < 0) {
308 		FAIL("Failed to get free server");
309 		return;
310 	}
311 
312 	LOG_DBG("L2CAP server registered, PSM:0x%X", server->psm);
313 }
314 
connected(struct bt_conn * conn,uint8_t conn_err)315 static void connected(struct bt_conn *conn, uint8_t conn_err)
316 {
317 	char addr[BT_ADDR_LE_STR_LEN];
318 
319 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
320 
321 	if (conn_err) {
322 		FAIL("Failed to connect to %s (%u)", addr, conn_err);
323 		bt_conn_unref(default_conn);
324 		default_conn = NULL;
325 		return;
326 	}
327 
328 	default_conn = bt_conn_ref(conn);
329 	LOG_DBG("%s", addr);
330 
331 	SET_FLAG(is_connected);
332 }
333 
disconnected(struct bt_conn * conn,uint8_t reason)334 static void disconnected(struct bt_conn *conn, uint8_t reason)
335 {
336 	char addr[BT_ADDR_LE_STR_LEN];
337 
338 	bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
339 
340 	LOG_DBG("%s (reason 0x%02x)", addr, reason);
341 
342 	if (default_conn != conn) {
343 		FAIL("Conn mismatch disconnect %s %s)", default_conn, conn);
344 		return;
345 	}
346 
347 	bt_conn_unref(default_conn);
348 	default_conn = NULL;
349 	UNSET_FLAG(is_connected);
350 }
351 
352 BT_CONN_CB_DEFINE(conn_callbacks) = {
353 	.connected = connected,
354 	.disconnected = disconnected,
355 };
356 
send_sdu(int iteration,int chan_idx,int bytes)357 static void send_sdu(int iteration, int chan_idx, int bytes)
358 {
359 	struct bt_l2cap_chan *chan = &channels[chan_idx].le.chan;
360 	struct net_buf *buf;
361 
362 	/* First 4 bytes in sent payload is iteration count */
363 	sys_put_le32(iteration, channels[chan_idx].payload);
364 
365 	if (channels[chan_idx].buf != 0) {
366 		FAIL("Buf should have been deallocated by now");
367 		return;
368 	}
369 
370 	if (chan_idx == 0) {
371 		buf = net_buf_alloc(&tx_data_pool_0, K_NO_WAIT);
372 	} else {
373 		buf = net_buf_alloc(&tx_data_pool_1, K_NO_WAIT);
374 	}
375 
376 	if (buf == NULL) {
377 		FAIL("Failed to get buff on ch %i, iteration %i should never happen", chan_idx,
378 		     chan_idx);
379 	}
380 
381 	channels[chan_idx].buf = buf;
382 	net_buf_reserve(buf, BT_L2CAP_SDU_CHAN_SEND_RESERVE);
383 	net_buf_add_mem(buf, channels[chan_idx].payload, bytes);
384 
385 	LOG_DBG("bt_l2cap_chan_sending ch: %i bytes: %i iteration: %i", chan_idx, bytes, iteration);
386 	const int ret = bt_l2cap_chan_send(chan, buf);
387 
388 	LOG_DBG("bt_l2cap_chan_send returned: %i", ret);
389 
390 	if (ret < 0) {
391 		FAIL("Error: send failed error: %i", ret);
392 		channels[chan_idx].buf = 0;
393 		net_buf_unref(buf);
394 	}
395 }
396 
send_sdu_chan_worker(struct k_work * item)397 void send_sdu_chan_worker(struct k_work *item)
398 {
399 	const struct channel *ch = CONTAINER_OF(item, struct channel, work);
400 
401 	send_sdu(ch->iteration, ch->chan_id, ch->bytes_to_send);
402 }
403 
send_sdu_concurrently(void)404 static void send_sdu_concurrently(void)
405 {
406 	for (int i = 0; i < SDU_SEND_COUNT; i++) {
407 		for (int k = 0; k < L2CAP_CHANNELS; k++) {
408 			channels[k].iteration = i;
409 			/* Assign the right msg to the right channel */
410 			channels[k].bytes_to_send = (k == LONG_MSG_CHAN_IDX) ? LONG_MSG : SHORT_MSG;
411 			const int err = k_work_submit_to_queue(&channels[k].work_queue,
412 								&channels[k].work);
413 
414 			if (err < 0) {
415 				FAIL("Failed to submit work to the queue, error: %d", err);
416 			}
417 		}
418 
419 		/* Wait until messages on all of the channels has been sent */
420 		for (int l = 0; l < L2CAP_CHANNELS; l++) {
421 			k_sem_take(&sent_sem, K_FOREVER);
422 		}
423 	}
424 }
425 
change_mtu_on_channels(int num_channels,int new_mtu)426 static int change_mtu_on_channels(int num_channels, int new_mtu)
427 {
428 	struct bt_l2cap_chan *reconf_channels[ECRED_CHAN_MAX] = { NULL };
429 
430 	for (int i = 0; i < num_channels; i++) {
431 		reconf_channels[i] = &(&channels[i])->le.chan;
432 	}
433 
434 	return bt_l2cap_ecred_chan_reconfigure(reconf_channels, new_mtu);
435 }
436 
test_peripheral_main(void)437 static void test_peripheral_main(void)
438 {
439 	device_sync_init(PERIPHERAL_ID);
440 	LOG_DBG("*L2CAP ECRED Peripheral started*");
441 	init_workqs();
442 	int err;
443 
444 	err = bt_enable(NULL);
445 	if (err) {
446 		FAIL("Can't enable Bluetooth (err %d)", err);
447 		return;
448 	}
449 
450 	LOG_DBG("Peripheral Bluetooth initialized.");
451 	LOG_DBG("Connectable advertising...");
452 	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);
453 	if (err) {
454 		FAIL("Advertising failed to start (err %d)", err);
455 		return;
456 	}
457 
458 	LOG_DBG("Advertising started.");
459 	LOG_DBG("Peripheral waiting for connection...");
460 	WAIT_FOR_FLAG_SET(is_connected);
461 	LOG_DBG("Peripheral Connected.");
462 	register_l2cap_server();
463 	connect_num_channels(L2CAP_CHANNELS);
464 	k_sem_take(&all_chan_conn_sem, K_FOREVER);
465 
466 	/* Disconnect and reconnect channels *****************************************************/
467 	LOG_DBG("############# Disconnect and reconnect channels");
468 	disconnect_all_channels();
469 	k_sem_take(&all_chan_disconn_sem, K_FOREVER);
470 
471 	connect_num_channels(L2CAP_CHANNELS);
472 	k_sem_take(&all_chan_conn_sem, K_FOREVER);
473 
474 	LOG_DBG("Send sync after reconnection");
475 	device_sync_send();
476 
477 	/* Send bytes on both channels and expect ch 1 to receive all of them before ch 0 *********/
478 	LOG_DBG("############# Send bytes on both channels concurrently");
479 	send_sdu_concurrently();
480 
481 	/* Change mtu size on all connected channels *********************************************/
482 	LOG_DBG("############# Change MTU of the channels");
483 	err = change_mtu_on_channels(L2CAP_CHANNELS, CONFIG_BT_L2CAP_TX_MTU + 10);
484 
485 	if (err) {
486 		FAIL("MTU change failed (err %d)\n", err);
487 	}
488 
489 	/* Read from both devices (Central and Peripheral) at the same time **********************/
490 	LOG_DBG("############# Read from both devices (Central and Peripheral) at the same time");
491 	LOG_DBG("Wait for sync before sending the msg");
492 	device_sync_wait();
493 	LOG_DBG("Received sync");
494 	send_sdu(0, 1, 10);
495 
496 	k_sem_take(&sent_sem, K_FOREVER);
497 	disconnect_all_channels();
498 	WAIT_FOR_FLAG_UNSET(is_connected);
499 	PASS("L2CAP ECRED Peripheral tests Passed");
500 	bs_trace_silent_exit(0);
501 }
502 
device_found(const bt_addr_le_t * addr,int8_t rssi,uint8_t type,struct net_buf_simple * ad)503 static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
504 			 struct net_buf_simple *ad)
505 {
506 	struct bt_le_conn_param *param;
507 	int err;
508 
509 	err = bt_le_scan_stop();
510 	if (err) {
511 		FAIL("Stop LE scan failed (err %d)", err);
512 		return;
513 	}
514 
515 	param = BT_LE_CONN_PARAM_DEFAULT;
516 	err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, param, &default_conn);
517 	if (err) {
518 		FAIL("Create conn failed (err %d)", err);
519 		return;
520 	}
521 }
522 
test_central_main(void)523 static void test_central_main(void)
524 {
525 	struct bt_le_scan_param scan_param = {
526 		.type = BT_LE_SCAN_TYPE_ACTIVE,
527 		.options = BT_LE_SCAN_OPT_NONE,
528 		.interval = BT_GAP_SCAN_FAST_INTERVAL,
529 		.window = BT_GAP_SCAN_FAST_WINDOW,
530 	};
531 
532 	device_sync_init(CENTRAL_ID);
533 
534 	LOG_DBG("*L2CAP ECRED Central started*");
535 	int err;
536 
537 	err = bt_enable(NULL);
538 	if (err) {
539 		FAIL("Can't enable Bluetooth (err %d)\n", err);
540 		return;
541 	}
542 	LOG_DBG("Central Bluetooth initialized.\n");
543 
544 	err = bt_le_scan_start(&scan_param, device_found);
545 	if (err) {
546 		FAIL("Scanning failed to start (err %d)\n", err);
547 		return;
548 	}
549 
550 	LOG_DBG("Scanning successfully started\n");
551 
552 	LOG_DBG("Central waiting for connection...\n");
553 	WAIT_FOR_FLAG_SET(is_connected);
554 	LOG_DBG("Central Connected.\n");
555 	register_l2cap_server();
556 
557 	LOG_DBG("Wait for sync after reconnection");
558 	device_sync_wait();
559 	LOG_DBG("Received sync");
560 
561 	/* Read from both devices (Central and Peripheral) at the same time **********************/
562 	LOG_DBG("############# Read from both devices (Central and Peripheral) at the same time");
563 	LOG_DBG("Send sync for SDU send");
564 	SET_FLAG(unsequenced_data);
565 	device_sync_send();
566 	send_sdu(0, 1, 10);
567 
568 	/* Wait until all of the channels are disconnected */
569 	k_sem_take(&all_chan_disconn_sem, K_FOREVER);
570 
571 	LOG_DBG("Both l2cap channels disconnected, test over\n");
572 
573 	UNSET_FLAG(unsequenced_data);
574 	LOG_DBG("received PDUs on long msg channel %i and short msg channel %i",
575 		channels[LONG_MSG_CHAN_IDX].sdus_received,
576 		channels[SHORT_MSG_CHAN_IDX].sdus_received);
577 
578 	if (channels[LONG_MSG_CHAN_IDX].sdus_received < SDU_SEND_COUNT ||
579 	    channels[SHORT_MSG_CHAN_IDX].sdus_received < SDU_SEND_COUNT) {
580 		FAIL("received less than %i", SDU_SEND_COUNT);
581 	}
582 
583 	/* Disconnect */
584 	LOG_DBG("Central Disconnecting....");
585 	err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
586 	bt_conn_unref(default_conn);
587 	LOG_DBG("Central tried to disconnect");
588 
589 	if (err) {
590 		FAIL("Disconnection failed (err %d)", err);
591 		return;
592 	}
593 
594 	LOG_DBG("Central Disconnected.");
595 
596 	PASS("L2CAP ECRED Central tests Passed\n");
597 }
598 
599 static const struct bst_test_instance test_def[] = {
600 	{
601 		.test_id = "peripheral",
602 		.test_descr = "Peripheral L2CAP ECRED",
603 		.test_pre_init_f = test_init,
604 		.test_tick_f = test_tick,
605 		.test_main_f = test_peripheral_main
606 	},
607 	{
608 		.test_id = "central",
609 		.test_descr = "Central L2CAP ECRED",
610 		.test_pre_init_f = test_init,
611 		.test_tick_f = test_tick,
612 		.test_main_f = test_central_main
613 	},
614 	BSTEST_END_MARKER
615 };
616 
test_main_l2cap_ecred_install(struct bst_test_list * tests)617 struct bst_test_list *test_main_l2cap_ecred_install(struct bst_test_list *tests)
618 {
619 	return bst_add_tests(tests, test_def);
620 }
621