1 /*
2 * Copyright (c) 2020 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stddef.h>
8
9 #include <zephyr/sys/byteorder.h>
10 #include <zephyr/sys/printk.h>
11 #include <zephyr/sys/util.h>
12
13 #include <zephyr/bluetooth/bluetooth.h>
14 #include <zephyr/bluetooth/hci.h>
15 #include <zephyr/bluetooth/iso.h>
16
17 #include "subsys/bluetooth/host/hci_core.h"
18 #include "subsys/bluetooth/controller/include/ll.h"
19 #include "subsys/bluetooth/controller/util/memq.h"
20 #include "subsys/bluetooth/controller/ll_sw/lll.h"
21
22 /* For VS data path */
23 #include "subsys/bluetooth/controller/ll_sw/isoal.h"
24 #include "subsys/bluetooth/controller/ll_sw/ull_iso_types.h"
25
26 #include "bs_types.h"
27 #include "bs_tracing.h"
28 #include "time_machine.h"
29 #include "bstests.h"
30
31 #define FAIL(...) \
32 do { \
33 bst_result = Failed; \
34 bs_trace_error_time_line(__VA_ARGS__); \
35 } while (0)
36
37 #define PASS(...) \
38 do { \
39 bst_result = Passed; \
40 bs_trace_info_time(1, __VA_ARGS__); \
41 } while (0)
42
43 extern enum bst_result_t bst_result;
44
45 static uint8_t mfg_data1[] = { 0xff, 0xff, 0x01, 0x02, 0x03, 0x04 };
46 static uint8_t mfg_data2[] = { 0xff, 0xff, 0x05 };
47
48 static const struct bt_data per_ad_data1[] = {
49 BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data1, 6),
50 };
51
52 static const struct bt_data per_ad_data2[] = {
53 BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data2, 3),
54 };
55
56 static uint8_t chan_map[] = { 0x1F, 0XF1, 0x1F, 0xF1, 0x1F };
57
58 static bool volatile is_iso_connected;
59 static uint8_t volatile is_iso_disconnected;
60 static bool volatile deleting_pa_sync;
61
62 #if !defined(CONFIG_TEST_LL_INTERFACE)
63 static void iso_connected(struct bt_iso_chan *chan);
64 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason);
65 static void iso_recv(struct bt_iso_chan *chan,
66 const struct bt_iso_recv_info *info, struct net_buf *buf);
67
68 static struct bt_iso_chan_ops iso_ops = {
69 .connected = iso_connected,
70 .disconnected = iso_disconnected,
71 .recv = iso_recv,
72 };
73
74 static struct bt_iso_chan_path iso_path_rx = {
75 .pid = BT_HCI_DATAPATH_ID_HCI
76 };
77
78 static struct bt_iso_chan_qos bis_iso_qos;
79 static struct bt_iso_chan_io_qos iso_tx_qos;
80 static struct bt_iso_chan_io_qos iso_rx_qos = {
81 .path = &iso_path_rx
82 };
83
84 static struct bt_iso_chan bis_iso_chan = {
85 .ops = &iso_ops,
86 .qos = &bis_iso_qos,
87 };
88
89 #define BIS_ISO_CHAN_COUNT 1
90 static struct bt_iso_chan *bis_channels[BIS_ISO_CHAN_COUNT] = { &bis_iso_chan };
91 static uint16_t seq_num;
92
93 NET_BUF_POOL_FIXED_DEFINE(bis_tx_pool, BIS_ISO_CHAN_COUNT,
94 BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
95 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
96
97 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
98 static uint8_t test_rx_buffer[CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX];
99 static bool is_iso_vs_emitted;
100
test_sink_sdu_alloc(const struct isoal_sink * sink_ctx,const struct isoal_pdu_rx * valid_pdu,struct isoal_sdu_buffer * sdu_buffer)101 static isoal_status_t test_sink_sdu_alloc(const struct isoal_sink *sink_ctx,
102 const struct isoal_pdu_rx *valid_pdu,
103 struct isoal_sdu_buffer *sdu_buffer)
104 {
105 sdu_buffer->dbuf = test_rx_buffer;
106 sdu_buffer->size = sizeof(test_rx_buffer);
107
108 return ISOAL_STATUS_OK;
109 }
110
111
test_sink_sdu_emit(const struct isoal_sink * sink_ctx,const struct isoal_emitted_sdu_frag * sdu_frag,const struct isoal_emitted_sdu * sdu)112 static isoal_status_t test_sink_sdu_emit(const struct isoal_sink *sink_ctx,
113 const struct isoal_emitted_sdu_frag *sdu_frag,
114 const struct isoal_emitted_sdu *sdu)
115 {
116 printk("Vendor sink SDU fragment size %u / %u, seq_num %u, ts %u\n",
117 sdu_frag->sdu_frag_size, sdu->total_sdu_size, sdu_frag->sdu.sn,
118 sdu_frag->sdu.timestamp);
119 is_iso_vs_emitted = true;
120
121 return ISOAL_STATUS_OK;
122 }
123
test_sink_sdu_write(void * dbuf,const size_t sdu_written,const uint8_t * pdu_payload,const size_t consume_len)124 static isoal_status_t test_sink_sdu_write(void *dbuf,
125 const size_t sdu_written,
126 const uint8_t *pdu_payload,
127 const size_t consume_len)
128 {
129 memcpy((uint8_t *)dbuf + sdu_written, pdu_payload, consume_len);
130
131 return ISOAL_STATUS_OK;
132 }
133
134
ll_data_path_sink_create(uint16_t handle,struct ll_iso_datapath * datapath,isoal_sink_sdu_alloc_cb * sdu_alloc,isoal_sink_sdu_emit_cb * sdu_emit,isoal_sink_sdu_write_cb * sdu_write)135 bool ll_data_path_sink_create(uint16_t handle, struct ll_iso_datapath *datapath,
136 isoal_sink_sdu_alloc_cb *sdu_alloc,
137 isoal_sink_sdu_emit_cb *sdu_emit,
138 isoal_sink_sdu_write_cb *sdu_write)
139 {
140 ARG_UNUSED(handle);
141 ARG_UNUSED(datapath);
142
143 *sdu_alloc = test_sink_sdu_alloc;
144 *sdu_emit = test_sink_sdu_emit;
145 *sdu_write = test_sink_sdu_write;
146
147 printk("VS data path sink created\n");
148 return true;
149 }
150 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
151
152 /* Have timeout unit sufficient to wait for all enqueued SDU to be transmitted.
153 * We retry allocation by yielding out of the system work queue to mitigate
154 * deadlock.
155 */
156 #define BUF_ALLOC_TIMEOUT_MS (10) /* milliseconds */
157 #define BUF_ALLOC_RETRY_TIMEOUT_US (1000) /* microseconds */
158 #define BUF_ALLOC_RETRY_COUNT (10U)
159
160 NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT,
161 BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU),
162 CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL);
163
164 static struct k_work_delayable iso_send_work;
165
166 BUILD_ASSERT(sizeof(seq_num) <= CONFIG_BT_ISO_TX_MTU);
167
iso_send(struct k_work * work)168 static void iso_send(struct k_work *work)
169 {
170 static uint8_t iso_data[CONFIG_BT_ISO_TX_MTU];
171 static bool data_initialized;
172 static uint8_t retry_yield_wq;
173 struct net_buf *buf;
174 size_t iso_data_len;
175 int ret;
176
177 if (!data_initialized) {
178 data_initialized = true;
179
180 for (size_t i = 0; i < ARRAY_SIZE(iso_data); i++) {
181 iso_data[i] = (uint8_t)i;
182 }
183 }
184
185 buf = net_buf_alloc(&tx_pool, K_MSEC(BUF_ALLOC_TIMEOUT_MS));
186 if (!buf) {
187 /* Blocking in system work qeueue causes deadlock, hence yield
188 * and try getting the buffer again.
189 */
190 if (retry_yield_wq) {
191 retry_yield_wq--;
192
193 k_work_schedule(&iso_send_work, K_USEC(BUF_ALLOC_RETRY_TIMEOUT_US));
194 } else {
195 FAIL("Data buffer allocate timeout on channel\n");
196 }
197
198 return;
199 }
200
201 retry_yield_wq = BUF_ALLOC_RETRY_COUNT;
202
203 net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE);
204 sys_put_le16(seq_num, iso_data);
205 iso_data_len = MAX(sizeof(seq_num), ((seq_num % CONFIG_BT_ISO_TX_MTU) + 1));
206 net_buf_add_mem(buf, iso_data, iso_data_len);
207
208 bs_trace_info_time(4, "ISO send: seq_num %u\n", seq_num);
209 ret = bt_iso_chan_send(&bis_iso_chan, buf, seq_num++);
210 if (ret < 0) {
211 FAIL("Unable to broadcast data on channel (%d)\n", ret);
212 net_buf_unref(buf);
213 return;
214 }
215
216 /* Ideally we can wait 10 ms to enqueue next SDU, but to mitigate clock
217 * drift between OS clock and Bluetooth Sleep Clock, lets send/enqueue
218 * early towards the Controller so that the SDU is not considered stale
219 * by the Controller.
220 *
221 * As we use `net_buf_alloc()` which will indirectly wait for Number of
222 * Completed Packet event processing in the Host leading to availability
223 * of next buffer, sending early will eventually get sync-ed with the
224 * interval at which the Controller is sending the SDU on-air.
225 */
226 k_work_schedule(&iso_send_work, K_USEC(9900));
227 }
228 #endif /* !CONFIG_TEST_LL_INTERFACE */
229
setup_ext_adv(struct bt_le_ext_adv ** adv)230 static void setup_ext_adv(struct bt_le_ext_adv **adv)
231 {
232 int err;
233
234 printk("Create advertising set...");
235 err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv);
236 if (err) {
237 FAIL("Failed to create advertising set (err %d)\n", err);
238 return;
239 }
240 printk("success.\n");
241
242 printk("Setting Periodic Advertising parameters...");
243 err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT);
244 if (err) {
245 FAIL("Failed to set periodic advertising parameters (err %d)\n",
246 err);
247 return;
248 }
249 printk("success.\n");
250
251 printk("Enable Periodic Advertising...");
252 err = bt_le_per_adv_start(*adv);
253 if (err) {
254 FAIL("Failed to enable periodic advertising (err %d)\n", err);
255 return;
256 }
257 printk("success.\n");
258
259 printk("Start extended advertising...");
260 err = bt_le_ext_adv_start(*adv, BT_LE_EXT_ADV_START_DEFAULT);
261 if (err) {
262 printk("Failed to start extended advertising (err %d)\n", err);
263 return;
264 }
265 printk("success.\n");
266 }
267
teardown_ext_adv(struct bt_le_ext_adv * adv)268 static void teardown_ext_adv(struct bt_le_ext_adv *adv)
269 {
270 int err;
271
272 printk("Stop Periodic Advertising...");
273 err = bt_le_per_adv_stop(adv);
274 if (err) {
275 FAIL("Failed to stop periodic advertising (err %d)\n", err);
276 return;
277 }
278 printk("success.\n");
279
280 printk("Stop Extended Advertising...");
281 err = bt_le_ext_adv_stop(adv);
282 if (err) {
283 FAIL("Failed to stop extended advertising (err %d)\n", err);
284 return;
285 }
286 printk("success.\n");
287
288 printk("Deleting Extended Advertising...");
289 err = bt_le_ext_adv_delete(adv);
290 if (err) {
291 FAIL("Failed to delete extended advertising (err %d)\n", err);
292 return;
293 }
294 printk("success.\n");
295 }
296
297 #if defined(CONFIG_TEST_LL_INTERFACE)
create_ll_big(uint8_t big_handle,struct bt_le_ext_adv * adv)298 static void create_ll_big(uint8_t big_handle, struct bt_le_ext_adv *adv)
299 {
300 uint16_t max_sdu = CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX;
301 uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE] = { 0 };
302 uint32_t sdu_interval = 10000; /* us */
303 uint16_t max_latency = 10; /* ms */
304 uint8_t encryption = 0;
305 uint8_t bis_count = 1; /* TODO: Add support for multiple BIS per BIG */
306 uint8_t phy = BIT(1);
307 uint8_t packing = 0;
308 uint8_t framing = 0;
309 uint8_t adv_handle;
310 uint8_t rtn = 0;
311 int err;
312
313 printk("Creating LL BIG...");
314 /* Assume that index == handle */
315 adv_handle = bt_le_ext_adv_get_index(adv);
316
317 err = ll_big_create(big_handle, adv_handle, bis_count, sdu_interval,
318 max_sdu, max_latency, rtn, phy, packing, framing,
319 encryption, bcode);
320 if (err) {
321 FAIL("Could not create BIG: %d\n", err);
322 return;
323 }
324 printk("success.\n");
325 }
326
terminate_ll_big(uint8_t big_handle)327 static void terminate_ll_big(uint8_t big_handle)
328 {
329 int err;
330
331 printk("Terminating LL BIG...");
332 err = ll_big_terminate(big_handle, BT_HCI_ERR_LOCALHOST_TERM_CONN);
333 if (err) {
334 FAIL("Could not terminate BIG: %d\n", err);
335 return;
336 }
337 printk("success.\n");
338 }
339
340 #else /* !CONFIG_TEST_LL_INTERFACE */
create_big(struct bt_le_ext_adv * adv,struct bt_iso_big ** big)341 static void create_big(struct bt_le_ext_adv *adv, struct bt_iso_big **big)
342 {
343 struct bt_iso_big_create_param big_create_param = { 0 };
344 int err;
345
346 printk("Creating BIG...\n");
347 big_create_param.bis_channels = bis_channels;
348 big_create_param.num_bis = BIS_ISO_CHAN_COUNT;
349 big_create_param.encryption = false;
350 big_create_param.interval = 10000; /* us */
351 big_create_param.latency = 10; /* milliseconds */
352 big_create_param.packing = (IS_ENABLED(CONFIG_TEST_ISO_PACKING_INTERLEAVED) ?
353 BT_ISO_PACKING_INTERLEAVED :
354 BT_ISO_PACKING_SEQUENTIAL);
355 big_create_param.framing = 0; /* 0 - unframed; 1 - framed */
356 iso_tx_qos.sdu = CONFIG_BT_ISO_TX_MTU; /* bytes */
357 iso_tx_qos.rtn = 2;
358 iso_tx_qos.phy = BT_GAP_LE_PHY_2M;
359 bis_iso_qos.tx = &iso_tx_qos;
360 bis_iso_qos.rx = NULL;
361 err = bt_iso_big_create(adv, &big_create_param, big);
362 if (err) {
363 FAIL("Could not create BIG: %d\n", err);
364 return;
365 }
366 printk("success.\n");
367
368 printk("Wait for ISO connected callback...");
369 while (!is_iso_connected) {
370 k_sleep(K_MSEC(100));
371 }
372 printk("ISO connected\n");
373 }
374
terminate_big(struct bt_iso_big * big)375 static void terminate_big(struct bt_iso_big *big)
376 {
377 int err;
378
379 printk("Terminating BIG...\n");
380 err = bt_iso_big_terminate(big);
381 if (err) {
382 FAIL("Could not terminate BIG: %d\n", err);
383 return;
384 }
385 printk("success.\n");
386
387 printk("Wait for ISO disconnected callback...");
388 while (is_iso_disconnected == 0U) {
389 k_sleep(K_MSEC(100));
390 }
391 printk("ISO disconnected\n");
392 }
393 #endif /* !CONFIG_TEST_LL_INTERFACE */
394
395 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
create_advanced_big(struct bt_le_ext_adv * adv,struct bt_iso_big ** big)396 static void create_advanced_big(struct bt_le_ext_adv *adv, struct bt_iso_big **big)
397 {
398 struct bt_iso_big_create_param big_create_param;
399 int err;
400
401 printk("Creating BIG...\n");
402 big_create_param.bis_channels = bis_channels;
403 big_create_param.num_bis = BIS_ISO_CHAN_COUNT;
404 big_create_param.encryption = false;
405 big_create_param.interval = 10000; /* us */
406 big_create_param.packing = 0; /* 0 - sequential; 1 - interleaved */
407 big_create_param.framing = 0; /* 0 - unframed; 1 - framed */
408 big_create_param.irc = BT_ISO_IRC_MIN;
409 big_create_param.pto = BT_ISO_PTO_MIN;
410 big_create_param.iso_interval = big_create_param.interval / 1250U; /* N * 10 ms */
411
412 iso_tx_qos.sdu = 502; /* bytes */
413 iso_tx_qos.phy = BT_GAP_LE_PHY_2M;
414 iso_tx_qos.max_pdu = BT_ISO_PDU_MAX;
415 iso_tx_qos.burst_number = BT_ISO_BN_MIN;
416
417 bis_iso_qos.tx = &iso_tx_qos;
418 bis_iso_qos.rx = NULL;
419 bis_iso_qos.num_subevents = BT_ISO_NSE_MIN;
420
421 err = bt_iso_big_create(adv, &big_create_param, big);
422 if (err) {
423 FAIL("Could not create BIG: %d\n", err);
424 return;
425 }
426 printk("success.\n");
427
428 printk("Wait for ISO connected callback...");
429 while (!is_iso_connected) {
430 k_sleep(K_MSEC(100));
431 }
432 printk("ISO connected\n");
433 }
434 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
435
test_iso_main(void)436 static void test_iso_main(void)
437 {
438 struct bt_le_ext_adv *adv;
439 int err;
440
441 printk("\n*ISO broadcast test*\n");
442
443 printk("Bluetooth initializing...");
444 err = bt_enable(NULL);
445 if (err) {
446 FAIL("Could not init BT: %d\n", err);
447 return;
448 }
449 printk("success.\n");
450
451 setup_ext_adv(&adv);
452
453 #if defined(CONFIG_TEST_LL_INTERFACE)
454 uint8_t big_handle = 0;
455
456 create_ll_big(big_handle, adv);
457
458 #else /* !CONFIG_TEST_LL_INTERFACE */
459 struct bt_iso_big *big;
460
461 create_big(adv, &big);
462
463 k_work_init_delayable(&iso_send_work, iso_send);
464 k_work_schedule(&iso_send_work, K_NO_WAIT);
465 #endif /* !CONFIG_TEST_LL_INTERFACE */
466
467 k_sleep(K_MSEC(5000));
468
469 printk("Update periodic advertising data 1...");
470 err = bt_le_per_adv_set_data(adv, per_ad_data1,
471 ARRAY_SIZE(per_ad_data1));
472 if (err) {
473 FAIL("Failed to update periodic advertising data 1 (%d).\n",
474 err);
475 }
476 printk("success.\n");
477
478 k_sleep(K_MSEC(2500));
479
480 printk("Periodic Advertising and ISO Channel Map Update...");
481 err = bt_le_set_chan_map(chan_map);
482 if (err) {
483 FAIL("Channel Map Update failed.\n");
484 }
485 printk("success.\n");
486
487 k_sleep(K_MSEC(2500));
488
489 printk("Update periodic advertising data 2...");
490 err = bt_le_per_adv_set_data(adv, per_ad_data2,
491 ARRAY_SIZE(per_ad_data2));
492 if (err) {
493 FAIL("Failed to update periodic advertising data 2 (%d).\n",
494 err);
495 }
496 printk("success.\n");
497
498 k_sleep(K_MSEC(5000));
499
500 #if defined(CONFIG_TEST_LL_INTERFACE)
501 terminate_ll_big(big_handle);
502
503 #else /* !CONFIG_TEST_LL_INTERFACE */
504 k_work_cancel_delayable(&iso_send_work);
505
506 terminate_big(big);
507 big = NULL;
508
509 #if defined(CONFIG_BT_ISO_TEST_PARAMS)
510 /* Quick check to just verify that creating a BIG using advanced/test
511 * parameters work
512 */
513 create_advanced_big(adv, &big);
514
515 terminate_big(big);
516 big = NULL;
517 #endif /* CONFIG_BT_ISO_TEST_PARAMS */
518 #endif /* !CONFIG_TEST_LL_INTERFACE */
519
520 k_sleep(K_MSEC(10000));
521
522 teardown_ext_adv(adv);
523 adv = NULL;
524
525 PASS("ISO tests Passed\n");
526 }
527
phy2str(uint8_t phy)528 static const char *phy2str(uint8_t phy)
529 {
530 switch (phy) {
531 case 0: return "No packets";
532 case BT_GAP_LE_PHY_1M: return "LE 1M";
533 case BT_GAP_LE_PHY_2M: return "LE 2M";
534 case BT_GAP_LE_PHY_CODED: return "LE Coded";
535 default: return "Unknown";
536 }
537 }
538
539 #if !defined(CONFIG_TEST_LL_INTERFACE)
540 /** 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
541 *
542 * Examples:
543 * 01
544 * 0102
545 * 010203
546 * 01020304
547 * 0102030405
548 * 010203040506
549 * 010203...050607
550 * 010203...060708
551 * etc.
552 */
iso_print_data(uint8_t * data,size_t data_len)553 static void iso_print_data(uint8_t *data, size_t data_len)
554 {
555 /* Maximum number of octets from each end of the data */
556 const uint8_t max_octets = 3;
557 char data_str[35];
558 size_t str_len;
559
560 str_len = bin2hex(data, MIN(max_octets, data_len), data_str, sizeof(data_str));
561 if (data_len > max_octets) {
562 if (data_len > (max_octets * 2)) {
563 static const char dots[] = "...";
564
565 strcat(&data_str[str_len], dots);
566 str_len += strlen(dots);
567 }
568
569 str_len += bin2hex(data + (data_len - MIN(max_octets, data_len - max_octets)),
570 MIN(max_octets, data_len - max_octets),
571 data_str + str_len,
572 sizeof(data_str) - str_len);
573 }
574
575 printk("\t %s\n", data_str);
576 }
577
578 #define SEQ_NUM_MAX 1000U
579 static uint16_t expected_seq_num[CONFIG_BT_ISO_MAX_CHAN];
580
iso_recv(struct bt_iso_chan * chan,const struct bt_iso_recv_info * info,struct net_buf * buf)581 static void iso_recv(struct bt_iso_chan *chan,
582 const struct bt_iso_recv_info *info, struct net_buf *buf)
583 {
584 uint16_t seq_num;
585 uint8_t index;
586
587 index = bt_conn_index(chan->iso);
588
589 printk("Incoming data channel %p (%u) flags 0x%x seq_num %u ts %u len %u:\n",
590 chan, index, info->flags, info->seq_num, info->ts, buf->len);
591 iso_print_data(buf->data, buf->len);
592
593 seq_num = sys_get_le16(buf->data);
594 if (info->flags & BT_ISO_FLAGS_VALID) {
595 if (seq_num != expected_seq_num[index]) {
596 if (expected_seq_num[index]) {
597 FAIL("ISO data miss match, expected %u actual %u\n",
598 expected_seq_num[index], seq_num);
599 }
600 expected_seq_num[index] = seq_num;
601 }
602
603 expected_seq_num[index]++;
604
605 } else if (expected_seq_num[index] &&
606 expected_seq_num[index] < SEQ_NUM_MAX) {
607 FAIL("%s: Invalid ISO data after valid ISO data reception.\n"
608 "Expected %u\n", __func__, expected_seq_num[index]);
609 }
610 }
611
iso_connected(struct bt_iso_chan * chan)612 static void iso_connected(struct bt_iso_chan *chan)
613 {
614 printk("ISO Channel %p connected\n", chan);
615
616 seq_num = 0U;
617 is_iso_connected = true;
618 }
619
iso_disconnected(struct bt_iso_chan * chan,uint8_t reason)620 static void iso_disconnected(struct bt_iso_chan *chan, uint8_t reason)
621 {
622 printk("ISO Channel %p disconnected with reason 0x%02x\n", chan, reason);
623
624 is_iso_disconnected = reason;
625 }
626 #endif /* !CONFIG_TEST_LL_INTERFACE */
627
628 static bool volatile is_sync;
629
pa_sync_cb(struct bt_le_per_adv_sync * sync,struct bt_le_per_adv_sync_synced_info * info)630 static void pa_sync_cb(struct bt_le_per_adv_sync *sync,
631 struct bt_le_per_adv_sync_synced_info *info)
632 {
633 char le_addr[BT_ADDR_LE_STR_LEN];
634
635 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
636
637 printk("PER_ADV_SYNC[%u]: [DEVICE]: %s synced, "
638 "Interval 0x%04x (%u ms), PHY %s\n",
639 bt_le_per_adv_sync_get_index(sync), le_addr,
640 info->interval, info->interval * 5 / 4, phy2str(info->phy));
641
642 is_sync = true;
643 }
644
pa_terminated_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_term_info * info)645 static void pa_terminated_cb(struct bt_le_per_adv_sync *sync,
646 const struct bt_le_per_adv_sync_term_info *info)
647 {
648 char le_addr[BT_ADDR_LE_STR_LEN];
649
650 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
651
652 printk("PER_ADV_SYNC[%u]: [DEVICE]: %s sync terminated\n",
653 bt_le_per_adv_sync_get_index(sync), le_addr);
654
655 if (!deleting_pa_sync) {
656 FAIL("PA terminated unexpectedly\n");
657 } else {
658 deleting_pa_sync = false;
659 }
660 }
661
662 static bool volatile is_sync_recv;
663
pa_recv_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_recv_info * info,struct net_buf_simple * buf)664 static void pa_recv_cb(struct bt_le_per_adv_sync *sync,
665 const struct bt_le_per_adv_sync_recv_info *info,
666 struct net_buf_simple *buf)
667 {
668 char le_addr[BT_ADDR_LE_STR_LEN];
669
670 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
671
672 printk("PER_ADV_SYNC[%u]: [DEVICE]: %s, tx_power %i, "
673 "RSSI %i, CTE %u, data length %u\n",
674 bt_le_per_adv_sync_get_index(sync), le_addr, info->tx_power,
675 info->rssi, info->cte_type, buf->len);
676
677 is_sync_recv = true;
678 }
679
680 static void
pa_state_changed_cb(struct bt_le_per_adv_sync * sync,const struct bt_le_per_adv_sync_state_info * info)681 pa_state_changed_cb(struct bt_le_per_adv_sync *sync,
682 const struct bt_le_per_adv_sync_state_info *info)
683 {
684 printk("PER_ADV_SYNC[%u]: state changed, receive %s.\n",
685 bt_le_per_adv_sync_get_index(sync),
686 info->recv_enabled ? "enabled" : "disabled");
687 }
688
689 static bool volatile is_big_info;
690
pa_biginfo_cb(struct bt_le_per_adv_sync * sync,const struct bt_iso_biginfo * biginfo)691 static void pa_biginfo_cb(struct bt_le_per_adv_sync *sync,
692 const struct bt_iso_biginfo *biginfo)
693 {
694 char le_addr[BT_ADDR_LE_STR_LEN];
695
696 bt_addr_le_to_str(biginfo->addr, le_addr, sizeof(le_addr));
697 printk("BIG INFO[%u]: [DEVICE]: %s, sid 0x%02x, "
698 "num_bis %u, nse %u, interval 0x%04x (%u ms), "
699 "bn %u, pto %u, irc %u, max_pdu %u, "
700 "sdu_interval %u us, max_sdu %u, phy %s, "
701 "%s framing, %sencrypted\n",
702 bt_le_per_adv_sync_get_index(sync), le_addr, biginfo->sid,
703 biginfo->num_bis, biginfo->sub_evt_count,
704 biginfo->iso_interval,
705 (biginfo->iso_interval * 5 / 4),
706 biginfo->burst_number, biginfo->offset,
707 biginfo->rep_count, biginfo->max_pdu, biginfo->sdu_interval,
708 biginfo->max_sdu, phy2str(biginfo->phy),
709 biginfo->framing ? "with" : "without",
710 biginfo->encryption ? "" : "not ");
711
712 if (!is_big_info) {
713 is_big_info = true;
714 }
715 }
716
717 static struct bt_le_per_adv_sync_cb sync_cb = {
718 .synced = pa_sync_cb,
719 .term = pa_terminated_cb,
720 .recv = pa_recv_cb,
721 .state_changed = pa_state_changed_cb,
722 .biginfo = pa_biginfo_cb,
723 };
724
725 #define NAME_LEN 30
726
data_cb(struct bt_data * data,void * user_data)727 static bool data_cb(struct bt_data *data, void *user_data)
728 {
729 char *name = user_data;
730
731 switch (data->type) {
732 case BT_DATA_NAME_SHORTENED:
733 case BT_DATA_NAME_COMPLETE:
734 memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1));
735 return false;
736 default:
737 return true;
738 }
739 }
740
741 static bool volatile is_periodic;
742 static bt_addr_le_t per_addr;
743 static uint8_t per_sid;
744
scan_recv(const struct bt_le_scan_recv_info * info,struct net_buf_simple * buf)745 static void scan_recv(const struct bt_le_scan_recv_info *info,
746 struct net_buf_simple *buf)
747 {
748 char le_addr[BT_ADDR_LE_STR_LEN];
749 char name[NAME_LEN];
750
751 (void)memset(name, 0, sizeof(name));
752
753 bt_data_parse(buf, data_cb, name);
754
755 bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr));
756 printk("[DEVICE]: %s, AD evt type %u, Tx Pwr: %i, RSSI %i %s "
757 "C:%u S:%u D:%u SR:%u E:%u Prim: %s, Secn: %s, "
758 "Interval: 0x%04x (%u ms), SID: %u\n",
759 le_addr, info->adv_type, info->tx_power, info->rssi, name,
760 (info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0,
761 (info->adv_props & BT_GAP_ADV_PROP_SCANNABLE) != 0,
762 (info->adv_props & BT_GAP_ADV_PROP_DIRECTED) != 0,
763 (info->adv_props & BT_GAP_ADV_PROP_SCAN_RESPONSE) != 0,
764 (info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0,
765 phy2str(info->primary_phy), phy2str(info->secondary_phy),
766 info->interval, info->interval * 5 / 4, info->sid);
767
768 if (info->interval) {
769 if (!is_periodic) {
770 is_periodic = true;
771 per_sid = info->sid;
772 bt_addr_le_copy(&per_addr, info->addr);
773 }
774 }
775 }
776
777 static struct bt_le_scan_cb scan_callbacks = {
778 .recv = scan_recv,
779 };
780
test_iso_recv_main(void)781 static void test_iso_recv_main(void)
782 {
783 struct bt_le_scan_param scan_param = {
784 .type = BT_LE_SCAN_TYPE_ACTIVE,
785 .options = BT_LE_SCAN_OPT_NONE,
786 .interval = 0x0004,
787 .window = 0x0004,
788 };
789 struct bt_le_per_adv_sync_param sync_create_param;
790 struct bt_le_per_adv_sync *sync = NULL;
791 int err;
792
793 printk("\n*ISO broadcast test*\n");
794
795 printk("Bluetooth initializing...");
796 err = bt_enable(NULL);
797 if (err) {
798 FAIL("Could not init BT: %d\n", err);
799 return;
800 }
801 printk("success.\n");
802
803 printk("Scan callbacks register...");
804 bt_le_scan_cb_register(&scan_callbacks);
805 printk("success.\n");
806
807 printk("Periodic Advertising callbacks register...");
808 bt_le_per_adv_sync_cb_register(&sync_cb);
809 printk("Success.\n");
810
811 printk("Start scanning...");
812 is_periodic = false;
813 err = bt_le_scan_start(&scan_param, NULL);
814 if (err) {
815 FAIL("Could not start scan: %d\n", err);
816 return;
817 }
818 printk("success.\n");
819
820 while (!is_periodic) {
821 k_sleep(K_MSEC(100));
822 }
823 printk("Periodic Advertising found (SID: %u)\n", per_sid);
824
825 printk("Creating Periodic Advertising Sync...");
826 is_sync = false;
827 bt_addr_le_copy(&sync_create_param.addr, &per_addr);
828 sync_create_param.options =
829 BT_LE_PER_ADV_SYNC_OPT_REPORTING_INITIALLY_DISABLED;
830 sync_create_param.sid = per_sid;
831 sync_create_param.skip = 0;
832 sync_create_param.timeout = 0xa;
833 err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
834 if (err) {
835 FAIL("Could not create sync: %d\n", err);
836 return;
837 }
838 printk("success.\n");
839
840 /* TODO: Enable when advertiser is added */
841 printk("Waiting for sync...");
842 while (!is_sync) {
843 k_sleep(K_MSEC(100));
844 }
845
846 printk("Stop scanning...");
847 err = bt_le_scan_stop();
848 if (err) {
849 FAIL("Could not stop scan: %d\n", err);
850 return;
851 }
852 printk("success.\n");
853
854 printk("Wait for BIG Info Advertising Report...");
855 is_big_info = false;
856 while (!is_big_info) {
857 k_sleep(K_MSEC(100));
858 }
859 printk("success.\n");
860
861 #if defined(CONFIG_TEST_LL_INTERFACE)
862 uint8_t bcode[BT_ISO_BROADCAST_CODE_SIZE] = { 0 };
863 uint16_t sync_timeout = 10;
864 uint8_t bis[1] = { 0x01, };
865 uint8_t big_handle = 0;
866 uint8_t encryption = 0;
867 uint8_t mse = 0;
868
869 printk("Creating BIG Sync...");
870 err = ll_big_sync_create(big_handle, sync->handle, encryption, bcode,
871 mse, sync_timeout, ARRAY_SIZE(bis), bis);
872 if (err) {
873 FAIL("Could not create BIG sync: %d\n", err);
874 return;
875 }
876 printk("success.\n");
877
878 k_sleep(K_MSEC(5000));
879
880 printk("Terminating BIG Sync...");
881
882 struct node_rx_pdu *node_rx = NULL;
883
884 err = ll_big_sync_terminate(big_handle, (void **)&node_rx);
885 if (err) {
886 FAIL("Could not terminate BIG sync: %d\n", err);
887 return;
888 }
889 printk("success.\n");
890
891 if (node_rx) {
892 FAIL("Generated Node Rx for synchronized BIG.\n");
893 }
894
895 k_sleep(K_MSEC(5000));
896
897 printk("Creating BIG Sync after terminate...");
898 err = ll_big_sync_create(big_handle, sync->handle, encryption, bcode,
899 mse, sync_timeout, ARRAY_SIZE(bis), bis);
900 if (err) {
901 FAIL("Could not create BIG sync: %d\n", err);
902 return;
903 }
904 printk("success.\n");
905
906 printk("Terminating BIG Sync...");
907 node_rx = NULL;
908 err = ll_big_sync_terminate(big_handle, (void **)&node_rx);
909 if (err) {
910 FAIL("Could not terminate BIG sync: %d\n", err);
911 return;
912 }
913 printk("success.\n");
914
915 if (node_rx) {
916 node_rx->hdr.next = NULL;
917 ll_rx_mem_release((void **)&node_rx);
918 }
919
920 printk("Deleting Periodic Advertising Sync...");
921 deleting_pa_sync = true;
922 err = bt_le_per_adv_sync_delete(sync);
923 if (err) {
924 FAIL("Failed to delete periodic advertising sync (err %d)\n",
925 err);
926 return;
927 }
928 printk("success.\n");
929
930 #else /* !CONFIG_TEST_LL_INTERFACE */
931 struct bt_iso_big_sync_param big_param = { 0, };
932 struct bt_iso_big *big;
933
934 printk("ISO BIG create sync...");
935 is_iso_connected = false;
936 bis_iso_qos.tx = NULL;
937 bis_iso_qos.rx = &iso_rx_qos;
938 big_param.bis_channels = bis_channels;
939 big_param.num_bis = BIS_ISO_CHAN_COUNT;
940 big_param.bis_bitfield = BT_ISO_BIS_INDEX_BIT(1); /* BIS 1 selected */
941 big_param.mse = 1;
942 big_param.sync_timeout = 100; /* 1000 ms */
943 big_param.encryption = false;
944 iso_path_rx.pid = BT_HCI_DATAPATH_ID_HCI;
945 memset(big_param.bcode, 0, sizeof(big_param.bcode));
946 err = bt_iso_big_sync(sync, &big_param, &big);
947 if (err) {
948 FAIL("Could not create BIG sync: %d\n", err);
949 return;
950 }
951 printk("success.\n");
952
953 printk("Wait for ISO connected callback...");
954 while (!is_iso_connected) {
955 k_sleep(K_MSEC(100));
956 }
957
958 printk("ISO terminate BIG...");
959 is_iso_disconnected = 0U;
960 err = bt_iso_big_terminate(big);
961 if (err) {
962 FAIL("Could not terminate BIG sync: %d\n", err);
963 return;
964 }
965 printk("success.\n");
966
967 printk("Waiting for ISO disconnected callback...\n");
968 while (!is_iso_disconnected) {
969 k_sleep(K_MSEC(100));
970 }
971 printk("disconnected.\n");
972
973 if (is_iso_disconnected != BT_HCI_ERR_LOCALHOST_TERM_CONN) {
974 FAIL("Local Host Terminate Failed.\n");
975 }
976
977 printk("ISO BIG create sync (test remote disconnect)...");
978 is_iso_connected = false;
979 is_iso_disconnected = 0U;
980 memset(expected_seq_num, 0U, sizeof(expected_seq_num));
981 err = bt_iso_big_sync(sync, &big_param, &big);
982 if (err) {
983 FAIL("Could not create BIG sync: %d\n", err);
984 return;
985 }
986 printk("success.\n");
987
988 printk("Wait for ISO connected callback...");
989 while (!is_iso_connected) {
990 k_sleep(K_MSEC(100));
991 }
992 printk("connected.\n");
993
994 printk("Waiting for ISO disconnected callback...\n");
995 while (!is_iso_disconnected) {
996 k_sleep(K_MSEC(100));
997 }
998 printk("disconnected.\n");
999
1000 if (is_iso_disconnected != BT_HCI_ERR_REMOTE_USER_TERM_CONN) {
1001 FAIL("Remote Host Terminate Failed.\n");
1002 }
1003
1004 printk("Periodic sync receive enable...\n");
1005 err = bt_le_per_adv_sync_recv_enable(sync);
1006 if (err) {
1007 printk("failed (err %d)\n", err);
1008 return;
1009 }
1010 printk("receive enabled.\n");
1011
1012 uint8_t check_countdown = 3;
1013
1014 printk("Waiting for remote BIG terminate by checking for missing "
1015 "%u BIG Info report...\n", check_countdown);
1016 do {
1017 is_sync_recv = false;
1018 is_big_info = false;
1019 while (!is_sync_recv) {
1020 k_sleep(K_MSEC(100));
1021 }
1022
1023 k_sleep(K_MSEC(100));
1024
1025 if (!is_big_info) {
1026 if (!--check_countdown) {
1027 break;
1028 }
1029 }
1030 } while (1);
1031 printk("success.\n");
1032
1033 printk("Deleting Periodic Advertising Sync...");
1034 deleting_pa_sync = true;
1035 err = bt_le_per_adv_sync_delete(sync);
1036 if (err) {
1037 FAIL("Failed to delete periodic advertising sync (err %d)\n",
1038 err);
1039 return;
1040 }
1041 printk("success.\n");
1042
1043 for (int chan = 0; chan < CONFIG_BT_ISO_MAX_CHAN; chan++) {
1044 if (expected_seq_num[chan] < SEQ_NUM_MAX) {
1045 FAIL("ISO Data reception incomplete %u (%u).\n",
1046 expected_seq_num[chan], SEQ_NUM_MAX);
1047 return;
1048 }
1049 }
1050 #endif /* !CONFIG_TEST_LL_INTERFACE */
1051
1052 PASS("ISO recv test Passed\n");
1053 }
1054
1055 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
test_iso_recv_vs_dp_main(void)1056 static void test_iso_recv_vs_dp_main(void)
1057 {
1058 struct bt_le_scan_param scan_param = {
1059 .type = BT_LE_SCAN_TYPE_ACTIVE,
1060 .options = BT_LE_SCAN_OPT_NONE,
1061 .interval = 0x0004,
1062 .window = 0x0004,
1063 };
1064 struct bt_le_per_adv_sync_param sync_create_param;
1065 struct bt_le_per_adv_sync *sync = NULL;
1066 int err;
1067
1068 printk("Bluetooth initializing... ");
1069 err = bt_enable(NULL);
1070 if (err) {
1071 FAIL("Could not init BT: %d\n", err);
1072 return;
1073 }
1074 printk("success.\n");
1075
1076 printk("Scan callbacks register... ");
1077 bt_le_scan_cb_register(&scan_callbacks);
1078 printk("success.\n");
1079
1080 printk("Periodic Advertising callbacks register... ");
1081 bt_le_per_adv_sync_cb_register(&sync_cb);
1082 printk("success.\n");
1083
1084 printk("Configure vendor data path... ");
1085 err = bt_configure_data_path(BT_HCI_DATAPATH_DIR_CTLR_TO_HOST,
1086 BT_HCI_DATAPATH_ID_VS, 0U, NULL);
1087 if (err) {
1088 FAIL("Failed (err %d)\n", err);
1089 return;
1090 }
1091
1092 printk("success.\n");
1093 printk("Start scanning... ");
1094 is_periodic = false;
1095 err = bt_le_scan_start(&scan_param, NULL);
1096 if (err) {
1097 FAIL("Could not start scan: %d\n", err);
1098 return;
1099 }
1100 printk("success.\n");
1101
1102 while (!is_periodic) {
1103 k_sleep(K_MSEC(100));
1104 }
1105 printk("Periodic Advertising found (SID: %u)\n", per_sid);
1106
1107 printk("Creating Periodic Advertising Sync... ");
1108 is_sync = false;
1109
1110 bt_addr_le_copy(&sync_create_param.addr, &per_addr);
1111 sync_create_param.options =
1112 BT_LE_PER_ADV_SYNC_OPT_REPORTING_INITIALLY_DISABLED;
1113 sync_create_param.sid = per_sid;
1114 sync_create_param.skip = 0;
1115 sync_create_param.timeout = 0xa;
1116
1117 err = bt_le_per_adv_sync_create(&sync_create_param, &sync);
1118 if (err) {
1119 FAIL("Could not create sync: %d\n", err);
1120 return;
1121 }
1122 printk("success.\n");
1123
1124 /* TODO: Enable when advertiser is added */
1125 printk("Waiting for sync...\n");
1126 while (!is_sync) {
1127 k_sleep(K_MSEC(100));
1128 }
1129 printk("success.\n");
1130
1131 printk("Stop scanning... ");
1132 err = bt_le_scan_stop();
1133 if (err) {
1134 FAIL("Could not stop scan: %d\n", err);
1135 return;
1136 }
1137 printk("success.\n");
1138
1139 printk("Wait for BIG Info Advertising Report...\n");
1140 is_big_info = false;
1141 while (!is_big_info) {
1142 k_sleep(K_MSEC(100));
1143 }
1144 printk("success.\n");
1145
1146 struct bt_iso_big_sync_param big_param = { 0, };
1147 struct bt_iso_big *big;
1148
1149 printk("ISO BIG create sync... ");
1150 is_iso_connected = false;
1151 bis_iso_qos.tx = NULL;
1152 bis_iso_qos.rx = &iso_rx_qos;
1153 big_param.bis_channels = bis_channels;
1154 big_param.num_bis = BIS_ISO_CHAN_COUNT;
1155 big_param.bis_bitfield = BT_ISO_BIS_INDEX_BIT(1); /* BIS 1 selected */
1156 big_param.mse = 1;
1157 big_param.sync_timeout = 100; /* 1000 ms */
1158 big_param.encryption = false;
1159 memset(big_param.bcode, 0, sizeof(big_param.bcode));
1160
1161 is_iso_connected = false;
1162 is_iso_disconnected = 0U;
1163 is_iso_vs_emitted = false;
1164 iso_path_rx.pid = BT_HCI_DATAPATH_ID_VS;
1165
1166 err = bt_iso_big_sync(sync, &big_param, &big);
1167 if (err) {
1168 FAIL("Could not create BIG sync: %d\n", err);
1169 return;
1170 }
1171 printk("success.\n");
1172
1173 printk("Wait for ISO connected callback... ");
1174 while (!is_iso_connected) {
1175 k_sleep(K_MSEC(100));
1176 }
1177
1178 /* Allow some SDUs to be received */
1179 k_sleep(K_MSEC(100));
1180
1181 printk("ISO terminate BIG... ");
1182 is_iso_disconnected = 0U;
1183 err = bt_iso_big_terminate(big);
1184 if (err) {
1185 FAIL("Could not terminate BIG sync: %d\n", err);
1186 return;
1187 }
1188 printk("success.\n");
1189
1190 printk("Waiting for ISO disconnected callback...\n");
1191 while (!is_iso_disconnected) {
1192 k_sleep(K_MSEC(100));
1193 }
1194 printk("disconnected.\n");
1195
1196 if (is_iso_disconnected != BT_HCI_ERR_LOCALHOST_TERM_CONN) {
1197 FAIL("Local Host Terminate Failed.\n");
1198 }
1199
1200 if (!is_iso_vs_emitted) {
1201 FAIL("Emitting of VS SDUs failed.\n");
1202 }
1203
1204 printk("success.\n");
1205
1206 printk("Deleting Periodic Advertising Sync... ");
1207 deleting_pa_sync = true;
1208 err = bt_le_per_adv_sync_delete(sync);
1209 if (err) {
1210 FAIL("Failed to delete periodic advertising sync (err %d)\n",
1211 err);
1212 return;
1213 }
1214 printk("success.\n");
1215
1216 PASS("ISO recv VS test Passed\n");
1217 }
1218 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1219
test_iso_init(void)1220 static void test_iso_init(void)
1221 {
1222 bst_ticker_set_next_tick_absolute(60e6);
1223 bst_result = In_progress;
1224 }
1225
test_iso_tick(bs_time_t HW_device_time)1226 static void test_iso_tick(bs_time_t HW_device_time)
1227 {
1228 if (bst_result != Passed) {
1229 FAIL("test failed (not passed after seconds)\n");
1230 }
1231 }
1232
1233 static const struct bst_test_instance test_def[] = {
1234 {
1235 .test_id = "broadcast",
1236 .test_descr = "ISO broadcast",
1237 .test_pre_init_f = test_iso_init,
1238 .test_tick_f = test_iso_tick,
1239 .test_main_f = test_iso_main
1240 },
1241 {
1242 .test_id = "receive",
1243 .test_descr = "ISO receive",
1244 .test_pre_init_f = test_iso_init,
1245 .test_tick_f = test_iso_tick,
1246 .test_main_f = test_iso_recv_main
1247 },
1248 #if defined(CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH)
1249 {
1250 .test_id = "receive_vs_dp",
1251 .test_descr = "ISO receive VS",
1252 .test_pre_init_f = test_iso_init,
1253 .test_tick_f = test_iso_tick,
1254 .test_main_f = test_iso_recv_vs_dp_main
1255 },
1256 #endif /* CONFIG_BT_CTLR_ISO_VENDOR_DATA_PATH */
1257 BSTEST_END_MARKER
1258 };
1259
test_iso_install(struct bst_test_list * tests)1260 struct bst_test_list *test_iso_install(struct bst_test_list *tests)
1261 {
1262 return bst_add_tests(tests, test_def);
1263 }
1264