1 /*
2  * Copyright (c) 2023 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdbool.h>
8 
9 #include "common.h"
10 
11 #include <zephyr/bluetooth/bluetooth.h>
12 #include <zephyr/bluetooth/iso.h>
13 #include <zephyr/sys/printk.h>
14 
15 #include <testlib/conn.h>
16 
17 extern enum bst_result_t bst_result;
18 
19 CREATE_FLAG(flag_data_received);
20 
21 static const struct bt_data ad[] = {
22 	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
23 };
24 static struct bt_iso_chan iso_chan;
25 
26 /** Print data as d_0 d_1 d_2 ... d_(n-2) d_(n-1) d_(n) to show the 3 first and 3 last octets
27  *
28  * Examples:
29  * 01
30  * 0102
31  * 010203
32  * 01020304
33  * 0102030405
34  * 010203040506
35  * 010203...050607
36  * 010203...060708
37  * etc.
38  */
iso_print_data(uint8_t * data,size_t data_len)39 static void iso_print_data(uint8_t *data, size_t data_len)
40 {
41 	/* Maximum number of octets from each end of the data */
42 	const uint8_t max_octets = 3;
43 	char data_str[35];
44 	size_t str_len;
45 
46 	str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str));
47 	if (data_len > max_octets) {
48 		if (data_len > (max_octets * 2)) {
49 			static const char dots[] = "...";
50 
51 			strcat(&data_str[str_len], dots);
52 			str_len += strlen(dots);
53 		}
54 
55 		str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)),
56 				   MIN(max_octets, data_len - max_octets), data_str + str_len,
57 				   sizeof(data_str) - str_len);
58 	}
59 
60 	printk("\t %s\n", data_str);
61 }
62 
iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)63 static void iso_recv(struct bt_iso_chan *chan, const struct bt_iso_recv_info *info,
64 		     struct net_buf *buf)
65 {
66 	if (info->flags & BT_ISO_FLAGS_VALID) {
67 		printk("Incoming data channel %p len %u\n", chan, buf->len);
68 		iso_print_data(buf->data, buf->len);
69 		SET_FLAG(flag_data_received);
70 	}
71 }
72 
iso_connected(struct bt_iso_chan * chan)73 static void iso_connected(struct bt_iso_chan *chan)
74 {
75 	printk("ISO Channel %p connected\n", chan);
76 }
77 
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)78 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
79 {
80 	printk("ISO Channel %p disconnected (reason 0x%02x)\n", chan, reason);
81 }
82 
iso_accept(const struct bt_iso_accept_info * info,struct bt_iso_chan ** chan)83 static int iso_accept(const struct bt_iso_accept_info *info, struct bt_iso_chan **chan)
84 {
85 	printk("Incoming request from %p\n", (void *)info->acl);
86 
87 	if (iso_chan.iso) {
88 		FAIL("No channels available\n");
89 
90 		return -ENOMEM;
91 	}
92 
93 	*chan = &iso_chan;
94 
95 	return 0;
96 }
97 
init(void)98 static void init(void)
99 {
100 	static struct bt_iso_chan_io_qos iso_rx = {
101 		.sdu = CONFIG_BT_ISO_TX_MTU,
102 		.path = NULL,
103 	};
104 	static struct bt_iso_server iso_server = {
105 #if defined(CONFIG_BT_SMP)
106 		.sec_level = BT_SECURITY_L2,
107 #endif /* CONFIG_BT_SMP */
108 		.accept = iso_accept,
109 	};
110 	static struct bt_iso_chan_ops iso_ops = {
111 		.recv = iso_recv,
112 		.connected = iso_connected,
113 		.disconnected = iso_disconnected,
114 	};
115 	static struct bt_iso_chan_qos iso_qos = {
116 		.rx = &iso_rx,
117 		.tx = NULL,
118 	};
119 	int err;
120 
121 	err = bt_enable(NULL);
122 	if (err) {
123 		FAIL("Bluetooth enable failed (err %d)\n", err);
124 
125 		return;
126 	}
127 
128 	iso_chan.ops = &iso_ops;
129 	iso_chan.qos = &iso_qos;
130 #if defined(CONFIG_BT_SMP)
131 	iso_chan.required_sec_level = BT_SECURITY_L2,
132 #endif /* CONFIG_BT_SMP */
133 
134 	err = bt_iso_server_register(&iso_server);
135 	if (err) {
136 		FAIL("Unable to register ISO server (err %d)\n", err);
137 
138 		return;
139 	}
140 }
141 
adv_connect(void)142 static void adv_connect(void)
143 {
144 	int err;
145 
146 	err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), NULL, 0);
147 	if (err) {
148 		FAIL("Advertising failed to start (err %d)\n", err);
149 
150 		return;
151 	}
152 
153 	printk("Advertising successfully started\n");
154 
155 	WAIT_FOR_FLAG_SET(flag_connected);
156 }
157 
test_main(void)158 static void test_main(void)
159 {
160 	init();
161 
162 	while (true) {
163 		adv_connect();
164 		bt_testlib_conn_wait_free();
165 
166 		if (TEST_FLAG(flag_data_received)) {
167 			PASS("Test passed\n");
168 		}
169 	}
170 }
171 
172 static const struct bst_test_instance test_def[] = {
173 	{
174 		.test_id = "peripheral",
175 		.test_descr = "Peripheral",
176 		.test_pre_init_f = test_init,
177 		.test_tick_f = test_tick,
178 		.test_main_f = test_main,
179 	},
180 	BSTEST_END_MARKER,
181 };
182 
test_main_cis_peripheral_install(struct bst_test_list * tests)183 struct bst_test_list *test_main_cis_peripheral_install(struct bst_test_list *tests)
184 {
185 	return bst_add_tests(tests, test_def);
186 }
187