1 /*
2 * Copyright (c) 2017-2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <soc.h>
9 #include <zephyr/bluetooth/hci_types.h>
10 #include <zephyr/sys/byteorder.h>
11
12 #include "hal/cpu.h"
13 #include "hal/ccm.h"
14 #include "hal/ticker.h"
15
16 #include "util/util.h"
17 #include "util/mem.h"
18 #include "util/memq.h"
19 #include "util/mayfly.h"
20 #include "util/dbuf.h"
21
22 #include "ticker/ticker.h"
23
24 #include "pdu_df.h"
25 #include "lll/pdu_vendor.h"
26 #include "pdu.h"
27
28 #include "lll.h"
29 #include "lll_clock.h"
30 #include "lll/lll_vendor.h"
31 #include "lll_chan.h"
32 #include "lll/lll_adv_types.h"
33 #include "lll_adv.h"
34 #include "lll/lll_adv_pdu.h"
35 #include "lll_adv_aux.h"
36 #include "lll/lll_df_types.h"
37 #include "lll_conn.h"
38
39 #include "ull_adv_types.h"
40
41 #include "ull_internal.h"
42 #include "ull_chan_internal.h"
43 #include "ull_adv_internal.h"
44 #include "ull_sched_internal.h"
45
46 #include "ll.h"
47
48 #include "hal/debug.h"
49
50 static int init_reset(void);
51
52 #if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
53 static inline struct ll_adv_aux_set *aux_acquire(void);
54 static inline void aux_release(struct ll_adv_aux_set *aux);
55 static uint32_t aux_time_get(const struct ll_adv_aux_set *aux,
56 const struct pdu_adv *pdu,
57 uint8_t pdu_len, uint8_t pdu_scan_len);
58 static uint32_t aux_time_min_get(const struct ll_adv_aux_set *aux);
59 static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu,
60 struct pdu_adv *pdu_scan);
61
62 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
63 static void mfy_aux_offset_get(void *param);
64 static void ticker_op_cb(uint32_t status, void *param);
65 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
66
67 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
68 uint32_t remainder, uint16_t lazy, uint8_t force,
69 void *param);
70
71 static struct ll_adv_aux_set ll_adv_aux_pool[CONFIG_BT_CTLR_ADV_AUX_SET];
72 static void *adv_aux_free;
73
74 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
75 static void ticker_update_op_cb(uint32_t status, void *param);
76
77 static struct ticker_ext ll_adv_aux_ticker_ext[CONFIG_BT_CTLR_ADV_AUX_SET];
78 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
79 #endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
80
81 static uint16_t did_unique[PDU_ADV_SID_COUNT];
82
ll_adv_aux_random_addr_set(uint8_t handle,uint8_t const * const addr)83 uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t const *const addr)
84 {
85 struct ll_adv_set *adv;
86
87 adv = ull_adv_is_created_get(handle);
88 if (!adv) {
89 return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
90 }
91
92 /* TODO: Fail if connectable advertising is enabled */
93 if (0) {
94 return BT_HCI_ERR_CMD_DISALLOWED;
95 }
96
97 (void)memcpy(adv->rnd_addr, addr, BDADDR_SIZE);
98
99 return 0;
100 }
101
ll_adv_aux_ad_data_set(uint8_t handle,uint8_t op,uint8_t frag_pref,uint8_t len,uint8_t const * const data)102 uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
103 uint8_t len, uint8_t const *const data)
104 {
105 uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
106 ULL_ADV_HDR_DATA_DATA_PTR_SIZE +
107 ULL_ADV_HDR_DATA_LEN_SIZE +
108 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
109 ULL_ADV_HDR_DATA_LEN_SIZE];
110 uint8_t pri_idx, sec_idx;
111 struct ll_adv_set *adv;
112 uint8_t *val_ptr;
113 uint8_t err;
114
115 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
116 struct pdu_adv *pdu_prev;
117 uint8_t ad_len_overflow;
118 uint8_t ad_len_chain;
119 struct pdu_adv *pdu;
120 uint8_t ad_len = 0U;
121 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
122
123 /* Get the advertising set instance */
124 adv = ull_adv_is_created_get(handle);
125 if (!adv) {
126 return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
127 }
128
129 /* Reject setting fragment when Extended Advertising is enabled */
130 if (adv->is_enabled && (op <= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) {
131 return BT_HCI_ERR_CMD_DISALLOWED;
132 }
133
134 /* Reject intermediate op before first op */
135 if (adv->is_ad_data_cmplt &&
136 ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
137 (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG))) {
138 return BT_HCI_ERR_CMD_DISALLOWED;
139 }
140
141 /* Reject unchanged op before complete status */
142 if (!adv->is_ad_data_cmplt &&
143 (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
144 return BT_HCI_ERR_CMD_DISALLOWED;
145 }
146
147 /* Reject len > 191 bytes if chain PDUs unsupported */
148 if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) &&
149 (len > PDU_AC_EXT_AD_DATA_LEN_MAX)) {
150 return BT_HCI_ERR_CMD_DISALLOWED;
151 }
152
153 /* Prepare the AD data as parameter to update in PDU */
154 /* Use length = 0 and NULL pointer to retain old data in the PDU.
155 * Use length = 0 and valid pointer of `data` (auto/local variable) to
156 * remove old data.
157 * User length > 0 and valid pointer of `data` (auto/local variable) to
158 * set new data.
159 */
160 val_ptr = hdr_data;
161 if ((IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) && (
162 op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG ||
163 op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) ||
164 op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
165 *val_ptr++ = 0U;
166 (void)memset((void *)val_ptr, 0U,
167 ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
168 } else {
169 *val_ptr++ = len;
170 (void)memcpy(val_ptr, &data, sizeof(data));
171 }
172
173 if ((!IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) &&
174 (op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA ||
175 op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG)) ||
176 (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA)) {
177 err = ull_adv_aux_hdr_set_clear(adv,
178 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
179 0U, hdr_data, &pri_idx,
180 &sec_idx);
181 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
182 /* No AD data overflow */
183 ad_len_overflow = 0U;
184
185 /* No AD data in chain PDU */
186 ad_len_chain = 0U;
187
188 /* local variables not used due to overflow being 0 */
189 pdu_prev = NULL;
190 pdu = NULL;
191 } else if (op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG ||
192 op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) {
193 /* Add AD Data and remove any prior presence of Aux Ptr */
194 err = ull_adv_aux_hdr_set_clear(adv,
195 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
196 ULL_ADV_PDU_HDR_FIELD_AUX_PTR,
197 hdr_data, &pri_idx, &sec_idx);
198 if (err == BT_HCI_ERR_PACKET_TOO_LONG) {
199 ad_len_overflow =
200 hdr_data[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET +
201 ULL_ADV_HDR_DATA_DATA_PTR_SIZE];
202 /* Prepare the AD data as parameter to update in
203 * PDU
204 */
205 val_ptr = hdr_data;
206 *val_ptr++ = len - ad_len_overflow;
207 (void)memcpy(val_ptr, &data, sizeof(data));
208
209 err = ull_adv_aux_hdr_set_clear(adv,
210 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
211 ULL_ADV_PDU_HDR_FIELD_AUX_PTR,
212 hdr_data, &pri_idx, &sec_idx);
213 }
214
215 if (!err && adv->lll.aux) {
216 /* Fragment into chain PDU if len > 191 bytes */
217 if (len > PDU_AC_EXT_AD_DATA_LEN_MAX) {
218 uint8_t idx;
219
220 /* Prepare the AD data as parameter to update in
221 * PDU
222 */
223 val_ptr = hdr_data;
224 *val_ptr++ = PDU_AC_EXT_AD_DATA_LEN_MAX;
225 (void)memcpy(val_ptr, &data, sizeof(data));
226
227 /* Traverse to next set clear hdr data
228 * parameter, as aux ptr reference to be
229 * returned, hence second parameter will be for
230 * AD data field.
231 */
232 val_ptr += sizeof(data);
233
234 *val_ptr = PDU_AC_EXT_AD_DATA_LEN_MAX;
235 (void)memcpy(&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
236 &data, sizeof(data));
237
238 /* Calculate the overflow chain PDU's AD data
239 * length
240 */
241 ad_len_overflow =
242 len - PDU_AC_EXT_AD_DATA_LEN_MAX;
243
244 /* No AD data in chain PDU besides the
245 * overflow
246 */
247 ad_len_chain = 0U;
248
249 /* Get the reference to auxiliary PDU chain */
250 pdu_prev = lll_adv_aux_data_alloc(adv->lll.aux,
251 &idx);
252 LL_ASSERT(idx == sec_idx);
253
254 /* Current auxiliary PDU */
255 pdu = pdu_prev;
256 } else {
257 struct pdu_adv *pdu_parent;
258 struct pdu_adv *pdu_chain;
259 uint8_t idx;
260
261 /* Get the reference to auxiliary PDU chain */
262 pdu_parent =
263 lll_adv_aux_data_alloc(adv->lll.aux,
264 &idx);
265 LL_ASSERT(idx == sec_idx);
266
267 /* Remove/Release any previous chain PDU
268 * allocations
269 */
270 pdu_chain =
271 lll_adv_pdu_linked_next_get(pdu_parent);
272 if (pdu_chain) {
273 lll_adv_pdu_linked_append(NULL,
274 pdu_parent);
275 lll_adv_pdu_linked_release_all(pdu_chain);
276 }
277
278 /* No AD data overflow */
279 ad_len_overflow = 0U;
280
281 /* No AD data in chain PDU */
282 ad_len_chain = 0U;
283
284 /* local variables not used due to overflow
285 * being 0
286 */
287 pdu_prev = NULL;
288 pdu = NULL;
289 }
290 } else {
291 /* No AD data overflow */
292 ad_len_overflow = 0U;
293
294 /* No AD data in chain PDU */
295 ad_len_chain = 0U;
296
297 /* local variables not used due to overflow being 0 */
298 pdu_prev = NULL;
299 pdu = NULL;
300 }
301 } else {
302 struct pdu_adv *pdu_chain_prev;
303 struct pdu_adv *pdu_chain;
304 uint16_t ad_len_total;
305 uint8_t ad_len_prev = 0U;
306
307 /* Traverse to next set clear hdr data parameter */
308 val_ptr += sizeof(data);
309
310 /* Get reference to previous secondary PDU data */
311 pdu_prev = lll_adv_aux_data_peek(adv->lll.aux);
312
313 /* Get the reference to auxiliary PDU chain */
314 pdu = lll_adv_aux_data_alloc(adv->lll.aux,
315 &sec_idx);
316
317 /* Traverse to the last chain PDU */
318 ad_len_total = 0U;
319 pdu_chain_prev = pdu_prev;
320 pdu_chain = pdu;
321 /* make a copy of the previous chain, until we reach the end */
322 do {
323 val_ptr = hdr_data;
324 *val_ptr++ = 0U;
325 (void)memset((void *)val_ptr, 0U,
326 ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
327
328 pdu_prev = pdu_chain_prev;
329 pdu = pdu_chain;
330
331 err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu,
332 ULL_ADV_PDU_HDR_FIELD_AD_DATA,
333 0U, hdr_data);
334 ad_len_prev = hdr_data[ULL_ADV_HDR_DATA_LEN_OFFSET];
335
336 LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG));
337
338 /* Check of max supported AD data len */
339 ad_len_total += ad_len_prev;
340 if ((ad_len_total + len) >
341 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
342 /* NOTE: latest PDU was not consumed by LLL and
343 * as ull_adv_sync_pdu_alloc() has reverted back
344 * the double buffer with the first PDU, and
345 * returned the latest PDU as the new PDU, we
346 * need to enqueue back the new PDU which is
347 * infact the latest PDU.
348 */
349 if (pdu_prev == pdu) {
350 lll_adv_aux_data_enqueue(adv->lll.aux,
351 sec_idx);
352 }
353
354 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
355 }
356
357 pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu_prev);
358 pdu_chain = lll_adv_pdu_linked_next_get(pdu);
359 LL_ASSERT((pdu_chain_prev && pdu_chain) ||
360 (!pdu_chain_prev && !pdu_chain));
361 } while (pdu_chain_prev);
362
363 /* No AD data overflow */
364 ad_len_overflow = 0U;
365 /* No AD data in chain PDU */
366 ad_len_chain = 0U;
367 }
368 #else /* !CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
369 } else {
370 /* Append new fragment */
371 err = ull_adv_aux_hdr_set_clear(adv,
372 ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND,
373 0U, hdr_data, &pri_idx,
374 &sec_idx);
375 }
376 #endif /* !CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
377
378 if (err) {
379 return err;
380 }
381
382 if (!adv->lll.aux) {
383 return 0;
384 }
385
386 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
387 if ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
388 (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) {
389 /* in the previous step we duplicated the chain
390 * the next step is to append new data in the last existing pdu in the chain,
391 */
392
393 uint8_t chain_err = 0U;
394
395 val_ptr = hdr_data;
396 *val_ptr++ = len;
397 (void)memcpy(val_ptr, &data, sizeof(data));
398
399 /* Append data to the last PDU */
400 chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu,
401 ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND,
402 0U, hdr_data);
403
404 LL_ASSERT((!chain_err) || (chain_err == BT_HCI_ERR_PACKET_TOO_LONG));
405
406 /* FIXME: the code has become quite complex, an alternative and simpler
407 * implementation would be to first fill an array with all data that
408 * must be send, and create the chained PDUs from this array
409 */
410 if (chain_err == BT_HCI_ERR_PACKET_TOO_LONG) {
411 /* We could not fit all the data, append as much as possible
412 * ad_len_overflow is how much overflows with the AUX ptr
413 */
414 const uint16_t chain_add_fields = ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND |
415 ULL_ADV_PDU_HDR_FIELD_AUX_PTR;
416
417 val_ptr = hdr_data;
418 *val_ptr++ = len;
419 (void)memcpy(val_ptr, &data, sizeof(data));
420 val_ptr += sizeof(data);
421 *val_ptr++ = len;
422 (void)memcpy(val_ptr, &data, sizeof(data));
423 chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu,
424 chain_add_fields,
425 0U, hdr_data);
426 ad_len_chain = hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET +
427 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
428 ULL_ADV_HDR_DATA_DATA_PTR_OFFSET +
429 ULL_ADV_HDR_DATA_DATA_PTR_SIZE];
430
431 /* len is the total amount of datawe want to add
432 * ad_len_chain is the amount of data that does
433 * not fit in the current PDU
434 * the difference of the two is the amount that
435 * we can fit in the current PDU
436 */
437 ad_len = len - ad_len_chain;
438
439 val_ptr = hdr_data;
440 *val_ptr++ = ad_len;
441 (void)memcpy(val_ptr, &data, sizeof(data));
442 val_ptr += sizeof(data);
443 *val_ptr++ = ad_len;
444 (void)memcpy(val_ptr, &data, sizeof(data));
445
446 /* we now know how much data we can add to the
447 * last PDU without getting an overflow
448 */
449 chain_err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu,
450 chain_add_fields,
451 0U, hdr_data);
452 LL_ASSERT(chain_err == 0U);
453 /*
454 * in the next PDU we still need to add ad_len_chain bytes of data
455 * but we do not have overflow, since we already added
456 * the exact amount that would fit. We explicitly set overflow to 0.
457 * FIXME: ad_len_overflow already should be 0, to be verified. We wait
458 * fixing this until rewriting this whole function
459 */
460 ad_len_overflow = 0U;
461 } else {
462 ad_len_overflow = 0U;
463 }
464 }
465
466 if (ad_len_chain || ad_len_overflow) {
467 struct pdu_adv_com_ext_adv *com_hdr_chain;
468 struct pdu_adv_com_ext_adv *com_hdr;
469 struct pdu_adv_ext_hdr *hdr_chain;
470 struct pdu_adv_aux_ptr *aux_ptr;
471 struct pdu_adv *pdu_chain_prev;
472 struct pdu_adv_ext_hdr hdr;
473 struct pdu_adv *pdu_chain;
474 uint8_t *dptr_chain;
475 uint32_t offs_us;
476 uint16_t sec_len;
477 uint8_t *dptr;
478
479 len = ad_len_chain;
480 /* Get reference to flags in superior PDU */
481 com_hdr = &pdu->adv_ext_ind;
482 if (com_hdr->ext_hdr_len) {
483 hdr = com_hdr->ext_hdr;
484 } else {
485 *(uint8_t *)&hdr = 0U;
486 }
487 dptr = com_hdr->ext_hdr.data;
488
489 /* Allocate new PDU */
490 pdu_chain = lll_adv_pdu_alloc_pdu_adv();
491 LL_ASSERT(pdu_chain);
492
493 /* Populate the appended chain PDU */
494 pdu_chain->type = PDU_ADV_TYPE_AUX_CHAIN_IND;
495 pdu_chain->rfu = 0U;
496 pdu_chain->chan_sel = 0U;
497 pdu_chain->tx_addr = 0U;
498 pdu_chain->rx_addr = 0U;
499 pdu_chain->len = 0U;
500
501 com_hdr_chain = &pdu_chain->adv_ext_ind;
502 hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0];
503 dptr_chain = (void *)hdr_chain;
504
505 LL_ASSERT(dptr_chain);
506 /* Flags */
507 *dptr_chain = 0U;
508
509 /* ADI flag, mandatory if superior PDU has it */
510 if (hdr.adi) {
511 hdr_chain->adi = 1U;
512 }
513
514 /* Proceed to next byte if any flags present */
515 if (*dptr_chain) {
516 dptr_chain++;
517 }
518
519 /* Start adding fields corresponding to flags here, if any */
520
521 /* AdvA flag */
522 if (hdr.adv_addr) {
523 dptr += BDADDR_SIZE;
524 }
525
526 /* TgtA flag */
527 if (hdr.tgt_addr) {
528 dptr += BDADDR_SIZE;
529 }
530
531 /* No CTEInfo in Extended Advertising */
532
533 /* ADI flag */
534 if (hdr_chain->adi) {
535 (void)memcpy(dptr_chain, dptr,
536 sizeof(struct pdu_adv_adi));
537
538 dptr += sizeof(struct pdu_adv_adi);
539 dptr_chain += sizeof(struct pdu_adv_adi);
540 }
541
542 /* non-connectable non-scannable chain pdu */
543 com_hdr_chain->adv_mode = 0;
544
545 /* Calc current chain PDU len */
546 sec_len = ull_adv_aux_hdr_len_calc(com_hdr_chain, &dptr_chain);
547
548 /* Prefix overflowed data to chain PDU and reduce the AD data in
549 * in the current PDU.
550 */
551 if (ad_len_overflow) {
552 uint8_t *ad_overflow;
553
554 val_ptr = hdr_data;
555 /* Copy overflowed AD data from previous PDU into this
556 * new chain PDU
557 */
558 (void)memcpy(&ad_overflow,
559 &val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
560 sizeof(ad_overflow));
561 ad_overflow += *val_ptr;
562
563 (void)memcpy(dptr_chain, ad_overflow, ad_len_overflow);
564 dptr_chain += ad_len_overflow;
565
566 /* Reduce the AD data in the previous PDU */
567 err = ull_adv_aux_pdu_set_clear(adv, pdu_prev, pdu,
568 (ULL_ADV_PDU_HDR_FIELD_AD_DATA |
569 ULL_ADV_PDU_HDR_FIELD_AUX_PTR),
570 0U, hdr_data);
571 if (err) {
572 /* NOTE: latest PDU was not consumed by LLL and
573 * as ull_adv_sync_pdu_alloc() has reverted back
574 * the double buffer with the first PDU, and
575 * returned the latest PDU as the new PDU, we
576 * need to enqueue back the new PDU which is
577 * infact the latest PDU.
578 */
579 if (pdu_prev == pdu) {
580 lll_adv_aux_data_enqueue(adv->lll.aux,
581 sec_idx);
582 }
583
584 return err;
585 }
586
587 }
588
589 /* Check AdvData overflow */
590 if ((sec_len + ad_len_overflow + len) >
591 PDU_AC_PAYLOAD_SIZE_MAX) {
592 /* NOTE: latest PDU was not consumed by LLL and
593 * as ull_adv_sync_pdu_alloc() has reverted back
594 * the double buffer with the first PDU, and
595 * returned the latest PDU as the new PDU, we
596 * need to enqueue back the new PDU which is
597 * infact the latest PDU.
598 */
599 if (pdu_prev == pdu) {
600 lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
601 }
602
603 return BT_HCI_ERR_PACKET_TOO_LONG;
604 }
605
606 /* Fill the chain PDU length */
607 ull_adv_aux_hdr_len_fill(com_hdr_chain, sec_len);
608 pdu_chain->len = sec_len + ad_len_overflow + len;
609
610 /* Fill AD Data in chain PDU */
611 if (ad_len_overflow != 0U) {
612 (void)memcpy(dptr_chain, data, ad_len_overflow);
613 }
614
615 if (ad_len_chain != 0U) {
616 (void)memcpy(dptr_chain, &data[ad_len + ad_len_overflow], ad_len_chain);
617 }
618
619 /* Get reference to aux ptr in superior PDU */
620 (void)memcpy(&aux_ptr,
621 &hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET],
622 sizeof(aux_ptr));
623
624 /* Fill the aux offset in the previous AUX_SYNC_IND PDU */
625 offs_us = PDU_AC_US(pdu->len, adv->lll.phy_s,
626 adv->lll.phy_flags) +
627 EVENT_B2B_MAFS_US;
628 ull_adv_aux_ptr_fill(aux_ptr, offs_us, adv->lll.phy_s);
629
630 /* Remove/Release any previous chain PDUs */
631 pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu);
632 if (pdu_chain_prev) {
633 lll_adv_pdu_linked_append(NULL, pdu);
634 lll_adv_pdu_linked_release_all(pdu_chain_prev);
635 }
636
637 /* Chain the PDU */
638 lll_adv_pdu_linked_append(pdu_chain, pdu);
639 }
640 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
641
642 if (adv->is_enabled) {
643 struct ll_adv_aux_set *aux;
644 struct pdu_adv *chan_res_pdu;
645 uint8_t tmp_idx;
646
647 aux = HDR_LLL2ULL(adv->lll.aux);
648 if (!aux->is_started) {
649 uint32_t ticks_slot_overhead;
650 uint32_t ticks_anchor;
651 uint32_t ret;
652
653 /* Keep aux interval equal or higher than primary PDU
654 * interval.
655 * Use periodic interval units to represent the
656 * periodic behavior of scheduling of AUX_ADV_IND PDUs
657 * so that it is grouped with similar interval units
658 * used for ACL Connections, Periodic Advertising and
659 * BIG radio events.
660 */
661 aux->interval =
662 DIV_ROUND_UP(((uint64_t)adv->interval *
663 ADV_INT_UNIT_US) +
664 HAL_TICKER_TICKS_TO_US(
665 ULL_ADV_RANDOM_DELAY),
666 PERIODIC_INT_UNIT_US);
667
668 /* TODO: Find the anchor before the group of
669 * active Periodic Advertising events, so
670 * that auxiliary sets are grouped such
671 * that auxiliary sets and Periodic
672 * Advertising sets are non-overlapping
673 * for the same event interval.
674 */
675 ticks_anchor =
676 ticker_ticks_now_get() +
677 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
678
679 ticks_slot_overhead =
680 ull_adv_aux_evt_init(aux, &ticks_anchor);
681
682 ret = ull_adv_aux_start(aux, ticks_anchor,
683 ticks_slot_overhead);
684 if (ret) {
685 /* NOTE: This failure, to start an auxiliary
686 * channel radio event shall not occur unless
687 * a defect in the controller design.
688 */
689 return BT_HCI_ERR_INSUFFICIENT_RESOURCES;
690 }
691
692 aux->is_started = 1;
693 }
694
695 /* Update primary channel reservation */
696 chan_res_pdu = lll_adv_data_alloc(&adv->lll, &tmp_idx);
697 err = ull_adv_time_update(adv, chan_res_pdu, NULL);
698 if (err) {
699 return err;
700 }
701
702 ARG_UNUSED(tmp_idx);
703 }
704
705 lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
706
707 if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) ||
708 op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG ||
709 op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA ||
710 op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
711 lll_adv_data_enqueue(&adv->lll, pri_idx);
712 }
713
714 /* Check if Extended Advertising Data is complete */
715 adv->is_ad_data_cmplt = (op >= BT_HCI_LE_EXT_ADV_OP_LAST_FRAG);
716
717 return 0;
718 }
719
ll_adv_aux_sr_data_set(uint8_t handle,uint8_t op,uint8_t frag_pref,uint8_t len,uint8_t const * const data)720 uint8_t ll_adv_aux_sr_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
721 uint8_t len, uint8_t const *const data)
722 {
723 uint8_t hdr_data[ULL_ADV_HDR_DATA_LEN_SIZE +
724 ULL_ADV_HDR_DATA_ADI_PTR_SIZE +
725 ULL_ADV_HDR_DATA_LEN_SIZE +
726 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
727 ULL_ADV_HDR_DATA_LEN_SIZE +
728 ULL_ADV_HDR_DATA_DATA_PTR_SIZE +
729 ULL_ADV_HDR_DATA_LEN_SIZE];
730 struct pdu_adv *pri_pdu_prev;
731 struct pdu_adv *sec_pdu_prev;
732 struct pdu_adv *sr_pdu_prev;
733 uint8_t pri_idx, sec_idx;
734 uint16_t hdr_add_fields;
735 struct ll_adv_set *adv;
736 struct pdu_adv *sr_pdu;
737 struct lll_adv *lll;
738 uint8_t *val_ptr;
739 uint8_t sr_idx;
740 uint8_t err;
741
742 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
743 uint8_t ad_len_overflow;
744 uint8_t ad_len_chain;
745 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
746
747 /* Get the advertising set instance */
748 adv = ull_adv_is_created_get(handle);
749 if (!adv) {
750 return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
751 }
752
753 /* Do not use Common Extended Advertising Header Format if not extended
754 * advertising.
755 */
756 lll = &adv->lll;
757 pri_pdu_prev = lll_adv_data_peek(lll);
758 if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
759 if ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) ||
760 (len > PDU_AC_LEG_DATA_SIZE_MAX)) {
761 return BT_HCI_ERR_INVALID_PARAM;
762 }
763 return ull_scan_rsp_set(adv, len, data);
764 }
765
766 /* Can only set complete data if advertising is enabled */
767 if (adv->is_enabled && (op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA)) {
768 return BT_HCI_ERR_CMD_DISALLOWED;
769 }
770
771 /* Data can be discarded only using 0x03 op */
772 if ((op != BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) && !len) {
773 return BT_HCI_ERR_INVALID_PARAM;
774 }
775
776 /* Scannable advertising shall have aux context allocated */
777 LL_ASSERT(lll->aux);
778
779 /* Get reference to previous secondary channel PDU */
780 sec_pdu_prev = lll_adv_aux_data_peek(lll->aux);
781
782 /* Can only discard data on non-scannable instances */
783 if (!(sec_pdu_prev->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) &&
784 len) {
785 return BT_HCI_ERR_INVALID_PARAM;
786 }
787
788 /* Cannot discard scan response if scannable advertising is enabled */
789 if (adv->is_enabled &&
790 (sec_pdu_prev->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) &&
791 !len) {
792 return BT_HCI_ERR_CMD_DISALLOWED;
793 }
794
795 /* Get reference to previous scan response PDU */
796 sr_pdu_prev = lll_adv_scan_rsp_peek(lll);
797
798 /* Get reference to next scan response PDU */
799 sr_pdu = lll_adv_aux_scan_rsp_alloc(lll, &sr_idx);
800
801 /* Prepare the AD data as parameter to update in PDU */
802 /* Use length = 0 and NULL pointer to retain old data in the PDU.
803 * Use length = 0 and valid pointer of `data` (auto/local variable) to
804 * remove old data.
805 * User length > 0 and valid pointer of `data` (auto/local variable) to
806 * set new data.
807 */
808 val_ptr = hdr_data;
809 if ((IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) && (
810 op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG ||
811 op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) ||
812 op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
813 *val_ptr++ = 0U;
814 (void)memset((void *)val_ptr, 0U,
815 ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
816 } else {
817 *val_ptr++ = len;
818 (void)memcpy(val_ptr, &data, sizeof(data));
819 }
820
821 if (false) {
822
823 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
824 } else if (op == BT_HCI_LE_EXT_ADV_OP_UNCHANGED_DATA) {
825 hdr_add_fields = ULL_ADV_PDU_HDR_FIELD_AD_DATA;
826 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev, sr_pdu,
827 hdr_add_fields, 0U, hdr_data);
828
829 /* No AD data overflow */
830 ad_len_overflow = 0U;
831
832 /* No AD data in chain PDU */
833 ad_len_chain = 0U;
834
835 /* pri_idx and sec_idx not used later in code in this function
836 */
837 pri_idx = 0U;
838 sec_idx = 0U;
839 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
840
841 } else if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) ||
842 (op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG ||
843 op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA)) {
844 struct pdu_adv_adi *adi;
845
846 /* If ADI in scan response is not supported then we do not
847 * need reference to ADI in auxiliary PDU
848 */
849 hdr_add_fields = 0U;
850
851 /* Add ADI if support enabled */
852 if (IS_ENABLED(CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP)) {
853 /* We need to get reference to ADI in auxiliary PDU */
854 hdr_add_fields |= ULL_ADV_PDU_HDR_FIELD_ADI;
855
856 /* Update DID by passing NULL reference for ADI */
857 (void)memset((void *)val_ptr, 0,
858 sizeof(struct pdu_adv_adi *));
859
860 /* Data place holder is after ADI */
861 val_ptr += sizeof(struct pdu_adv_adi *);
862
863 /* Place holder and reference to data passed and
864 * old reference to be returned
865 */
866 *val_ptr++ = len;
867 (void)memcpy(val_ptr, &data, sizeof(data));
868 }
869
870 /* Trigger DID update */
871 err = ull_adv_aux_hdr_set_clear(adv, hdr_add_fields, 0U,
872 hdr_data, &pri_idx, &sec_idx);
873 if (err) {
874 return err;
875 }
876
877 if ((op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA) && !len) {
878 sr_pdu->len = 0;
879 goto sr_data_set_did_update;
880 }
881
882 if (IS_ENABLED(CONFIG_BT_CTRL_ADV_ADI_IN_SCAN_RSP)) {
883 (void)memcpy(&adi,
884 &hdr_data[ULL_ADV_HDR_DATA_ADI_PTR_OFFSET],
885 sizeof(struct pdu_adv_adi *));
886 }
887
888 if (op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG ||
889 op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG) {
890 /* Append fragment to existing data */
891 hdr_add_fields |= ULL_ADV_PDU_HDR_FIELD_ADVA |
892 ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND;
893 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev, sr_pdu,
894 hdr_add_fields,
895 0U,
896 hdr_data);
897 } else {
898 /* Add AD Data and remove any prior presence of Aux Ptr */
899 hdr_add_fields |= ULL_ADV_PDU_HDR_FIELD_ADVA |
900 ULL_ADV_PDU_HDR_FIELD_AD_DATA;
901 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev, sr_pdu,
902 hdr_add_fields,
903 ULL_ADV_PDU_HDR_FIELD_AUX_PTR,
904 hdr_data);
905 }
906 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
907 if (err == BT_HCI_ERR_PACKET_TOO_LONG) {
908 uint8_t ad_len_offset;
909
910 ad_len_offset = ULL_ADV_HDR_DATA_DATA_PTR_OFFSET +
911 ULL_ADV_HDR_DATA_DATA_PTR_SIZE;
912 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
913 ad_len_offset +=
914 ULL_ADV_HDR_DATA_ADI_PTR_OFFSET +
915 ULL_ADV_HDR_DATA_ADI_PTR_SIZE;
916 }
917 ad_len_overflow = hdr_data[ad_len_offset];
918
919 /* Prepare the AD data as parameter to update in
920 * PDU
921 */
922 val_ptr = hdr_data;
923
924 /* Place holder for ADI field reference to be
925 * returned
926 */
927 if (hdr_add_fields &
928 ULL_ADV_PDU_HDR_FIELD_ADI) {
929 val_ptr++;
930 (void)memcpy(val_ptr, &adi,
931 sizeof(struct pdu_adv_adi *));
932 val_ptr += sizeof(struct pdu_adv_adi *);
933 }
934
935 /* Place holder and reference to data passed and
936 * old reference to be returned
937 */
938 *val_ptr++ = len - ad_len_overflow;
939 (void)memcpy(val_ptr, &data, sizeof(data));
940
941 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev,
942 sr_pdu, hdr_add_fields,
943 ULL_ADV_PDU_HDR_FIELD_AUX_PTR,
944 hdr_data);
945 }
946
947 if (!err) {
948 /* Fragment into chain PDU if len > 191 bytes */
949 if (len > PDU_AC_EXT_AD_DATA_LEN_MAX) {
950 /* Prepare the AD data as parameter to update in
951 * PDU
952 */
953 val_ptr = hdr_data;
954
955 /* Place holder for ADI field reference to be
956 * returned
957 */
958 if (hdr_add_fields &
959 ULL_ADV_PDU_HDR_FIELD_ADI) {
960 val_ptr++;
961 val_ptr += sizeof(struct pdu_adv_adi *);
962 }
963
964 /* Place holder for aux ptr reference to be
965 * returned
966 */
967 val_ptr++;
968 val_ptr += sizeof(uint8_t *);
969
970 /* Place holder and reference to data passed and
971 * old reference to be returned
972 */
973 *val_ptr = PDU_AC_EXT_AD_DATA_LEN_MAX;
974 (void)memcpy(&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
975 &data, sizeof(data));
976
977 /* Calculate the overflow chain PDU's AD data
978 * length
979 */
980 ad_len_overflow =
981 len - PDU_AC_EXT_AD_DATA_LEN_MAX;
982
983 /* No AD data in chain PDU besides the
984 * overflow
985 */
986 ad_len_chain = 0U;
987 } else {
988 struct pdu_adv *pdu_chain;
989
990 /* Remove/Release any previous chain PDU
991 * allocations
992 */
993 pdu_chain = lll_adv_pdu_linked_next_get(sr_pdu);
994 if (pdu_chain) {
995 lll_adv_pdu_linked_append(NULL, sr_pdu);
996 lll_adv_pdu_linked_release_all(pdu_chain);
997 }
998
999 /* No AD data overflow */
1000 ad_len_overflow = 0U;
1001
1002 /* No AD data in chain PDU */
1003 ad_len_chain = 0U;
1004 }
1005 } else {
1006 /* No AD data overflow */
1007 ad_len_overflow = 0U;
1008
1009 /* No AD data in chain PDU */
1010 ad_len_chain = 0U;
1011 }
1012 } else {
1013 struct pdu_adv *pdu_chain_prev;
1014 struct pdu_adv *pdu_chain;
1015 uint16_t ad_len_total;
1016 uint8_t ad_len_prev;
1017
1018 /* Traverse to next set clear hdr data parameter */
1019 val_ptr += sizeof(data);
1020
1021 /* Traverse to the last chain PDU */
1022 ad_len_total = 0U;
1023 pdu_chain_prev = sr_pdu_prev;
1024 pdu_chain = sr_pdu;
1025 do {
1026 /* Prepare for aux ptr field reference to be returned, hence
1027 * second parameter will be for AD data field.
1028 */
1029 *val_ptr = 0U;
1030 (void)memset((void *)&val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
1031 0U, ULL_ADV_HDR_DATA_DATA_PTR_SIZE);
1032
1033 sr_pdu_prev = pdu_chain_prev;
1034 sr_pdu = pdu_chain;
1035
1036 /* Add Aux Ptr field if not already present */
1037 hdr_add_fields = ULL_ADV_PDU_HDR_FIELD_AD_DATA |
1038 ULL_ADV_PDU_HDR_FIELD_AUX_PTR;
1039 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev,
1040 sr_pdu, hdr_add_fields,
1041 0U, hdr_data);
1042 LL_ASSERT(!err || (err == BT_HCI_ERR_PACKET_TOO_LONG));
1043
1044 /* Get PDUs previous AD data length */
1045 ad_len_prev =
1046 hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET +
1047 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE];
1048
1049 /* Check of max supported AD data len */
1050 ad_len_total += ad_len_prev;
1051 if ((ad_len_total + len) >
1052 CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1053 /* NOTE: latest PDU was not consumed by LLL and
1054 * as ull_adv_sync_pdu_alloc() has reverted back
1055 * the double buffer with the first PDU, and
1056 * returned the latest PDU as the new PDU, we
1057 * need to enqueue back the new PDU which is
1058 * infact the latest PDU.
1059 */
1060 if (sr_pdu_prev == sr_pdu) {
1061 lll_adv_scan_rsp_enqueue(lll, sr_idx);
1062 }
1063
1064 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1065 }
1066
1067 pdu_chain_prev = lll_adv_pdu_linked_next_get(sr_pdu_prev);
1068 pdu_chain = lll_adv_pdu_linked_next_get(sr_pdu);
1069 LL_ASSERT((pdu_chain_prev && pdu_chain) ||
1070 (!pdu_chain_prev && !pdu_chain));
1071 } while (pdu_chain_prev);
1072
1073 if (err == BT_HCI_ERR_PACKET_TOO_LONG) {
1074 ad_len_overflow =
1075 hdr_data[ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET +
1076 ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE +
1077 ULL_ADV_HDR_DATA_DATA_PTR_OFFSET +
1078 ULL_ADV_HDR_DATA_DATA_PTR_SIZE];
1079
1080 /* Prepare for aux ptr field reference to be returned,
1081 * hence second parameter will be for AD data field.
1082 * Fill it with reduced AD data length.
1083 */
1084 *val_ptr = ad_len_prev - ad_len_overflow;
1085
1086 /* AD data len in chain PDU */
1087 ad_len_chain = len;
1088
1089 /* Proceed to add chain PDU */
1090 err = 0U;
1091 } else {
1092 /* No AD data overflow */
1093 ad_len_overflow = 0U;
1094
1095 /* No AD data in chain PDU */
1096 ad_len_chain = 0U;
1097 }
1098
1099 /* pri_idx and sec_idx not used later in code in this function
1100 */
1101 pri_idx = 0U;
1102 sec_idx = 0U;
1103 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
1104 }
1105 if (err) {
1106 return err;
1107 }
1108
1109 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
1110 if ((op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG) ||
1111 (op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG) ||
1112 ad_len_overflow) {
1113 struct pdu_adv_com_ext_adv *com_hdr_chain;
1114 struct pdu_adv_com_ext_adv *com_hdr;
1115 struct pdu_adv_ext_hdr *hdr_chain;
1116 struct pdu_adv_aux_ptr *aux_ptr;
1117 struct pdu_adv *pdu_chain_prev;
1118 struct pdu_adv_ext_hdr hdr;
1119 struct pdu_adv *pdu_chain;
1120 uint8_t aux_ptr_offset;
1121 uint8_t *dptr_chain;
1122 uint32_t offs_us;
1123 uint16_t sec_len;
1124 uint8_t *dptr;
1125
1126 /* Get reference to flags in superior PDU */
1127 com_hdr = &sr_pdu->adv_ext_ind;
1128 if (com_hdr->ext_hdr_len) {
1129 hdr = com_hdr->ext_hdr;
1130 } else {
1131 *(uint8_t *)&hdr = 0U;
1132 }
1133 dptr = com_hdr->ext_hdr.data;
1134
1135 /* Allocate new PDU */
1136 pdu_chain = lll_adv_pdu_alloc_pdu_adv();
1137 LL_ASSERT(pdu_chain);
1138
1139 /* Populate the appended chain PDU */
1140 pdu_chain->type = PDU_ADV_TYPE_AUX_CHAIN_IND;
1141 pdu_chain->rfu = 0U;
1142 pdu_chain->chan_sel = 0U;
1143 pdu_chain->tx_addr = 0U;
1144 pdu_chain->rx_addr = 0U;
1145 pdu_chain->len = 0U;
1146
1147 com_hdr_chain = &pdu_chain->adv_ext_ind;
1148 hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0];
1149 dptr_chain = (void *)hdr_chain;
1150
1151 /* Flags */
1152 *dptr_chain = 0U;
1153
1154 /* ADI flag, mandatory if superior PDU has it */
1155 if (hdr.adi) {
1156 hdr_chain->adi = 1U;
1157 }
1158
1159 /* Proceed to next byte if any flags present */
1160 if (*dptr_chain) {
1161 dptr_chain++;
1162 }
1163
1164 /* Start adding fields corresponding to flags here, if any */
1165
1166 /* AdvA flag */
1167 if (hdr.adv_addr) {
1168 dptr += BDADDR_SIZE;
1169 }
1170
1171 /* TgtA flag */
1172 if (hdr.tgt_addr) {
1173 dptr += BDADDR_SIZE;
1174 }
1175
1176 /* No CTEInfo in Extended Advertising */
1177
1178 /* ADI flag */
1179 if (hdr_chain->adi) {
1180 (void)memcpy(dptr_chain, dptr,
1181 sizeof(struct pdu_adv_adi));
1182
1183 dptr += sizeof(struct pdu_adv_adi);
1184 dptr_chain += sizeof(struct pdu_adv_adi);
1185 }
1186
1187 /* non-connectable non-scannable chain pdu */
1188 com_hdr_chain->adv_mode = 0;
1189
1190 /* Calc current chain PDU len */
1191 sec_len = ull_adv_aux_hdr_len_calc(com_hdr_chain, &dptr_chain);
1192
1193 /* Prefix overflowed data to chain PDU and reduce the AD data in
1194 * in the current PDU.
1195 */
1196 if (ad_len_overflow) {
1197 uint8_t *ad_overflow;
1198
1199 /* Copy overflowed AD data from previous PDU into this
1200 * new chain PDU
1201 */
1202 (void)memcpy(&ad_overflow,
1203 &val_ptr[ULL_ADV_HDR_DATA_DATA_PTR_OFFSET],
1204 sizeof(ad_overflow));
1205 ad_overflow += *val_ptr;
1206 (void)memcpy(dptr_chain, ad_overflow, ad_len_overflow);
1207 dptr_chain += ad_len_overflow;
1208
1209 hdr_add_fields |= ULL_ADV_PDU_HDR_FIELD_AUX_PTR;
1210
1211 /* Reduce the AD data in the previous PDU */
1212 err = ull_adv_aux_pdu_set_clear(adv, sr_pdu_prev,
1213 sr_pdu, hdr_add_fields,
1214 0U, hdr_data);
1215 if (err) {
1216 /* NOTE: latest PDU was not consumed by LLL and
1217 * as ull_adv_sync_pdu_alloc() has reverted back
1218 * the double buffer with the first PDU, and
1219 * returned the latest PDU as the new PDU, we
1220 * need to enqueue back the new PDU which is
1221 * infact the latest PDU.
1222 */
1223 if (sr_pdu_prev == sr_pdu) {
1224 lll_adv_scan_rsp_enqueue(lll, sr_idx);
1225 }
1226
1227 return err;
1228 }
1229
1230 /* AD data len in chain PDU besides the overflow */
1231 len = ad_len_chain;
1232 }
1233
1234 /* Check AdvData overflow */
1235 if ((sec_len + ad_len_overflow + len) >
1236 PDU_AC_PAYLOAD_SIZE_MAX) {
1237 /* NOTE: latest PDU was not consumed by LLL and
1238 * as ull_adv_sync_pdu_alloc() has reverted back
1239 * the double buffer with the first PDU, and
1240 * returned the latest PDU as the new PDU, we
1241 * need to enqueue back the new PDU which is
1242 * infact the latest PDU.
1243 */
1244 if (sr_pdu_prev == sr_pdu) {
1245 lll_adv_aux_data_enqueue(adv->lll.aux, sr_idx);
1246 }
1247
1248 return BT_HCI_ERR_PACKET_TOO_LONG;
1249 }
1250
1251 /* Fill the chain PDU length */
1252 ull_adv_aux_hdr_len_fill(com_hdr_chain, sec_len);
1253 pdu_chain->len = sec_len + ad_len_overflow + len;
1254
1255 /* Fill AD Data in chain PDU */
1256 (void)memcpy(dptr_chain, data, len);
1257
1258 /* Get reference to aux ptr in superior PDU */
1259 aux_ptr_offset = ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET;
1260 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
1261 aux_ptr_offset += ULL_ADV_HDR_DATA_ADI_PTR_OFFSET +
1262 ULL_ADV_HDR_DATA_ADI_PTR_SIZE;
1263 }
1264 (void)memcpy(&aux_ptr, &hdr_data[aux_ptr_offset],
1265 sizeof(aux_ptr));
1266
1267 /* Fill the aux offset in the previous AUX_SYNC_IND PDU */
1268 offs_us = PDU_AC_US(sr_pdu->len, adv->lll.phy_s,
1269 adv->lll.phy_flags) +
1270 EVENT_B2B_MAFS_US;
1271 ull_adv_aux_ptr_fill(aux_ptr, offs_us, adv->lll.phy_s);
1272
1273 /* Remove/Release any previous chain PDUs */
1274 pdu_chain_prev = lll_adv_pdu_linked_next_get(sr_pdu);
1275 if (pdu_chain_prev) {
1276 lll_adv_pdu_linked_append(NULL, sr_pdu);
1277 lll_adv_pdu_linked_release_all(pdu_chain_prev);
1278 }
1279
1280 /* Chain the PDU */
1281 lll_adv_pdu_linked_append(pdu_chain, sr_pdu);
1282 }
1283 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
1284
1285 sr_data_set_did_update:
1286 if ((!IS_ENABLED(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK) &&
1287 (op == BT_HCI_LE_EXT_ADV_OP_INTERM_FRAG ||
1288 op == BT_HCI_LE_EXT_ADV_OP_LAST_FRAG)) ||
1289 (op == BT_HCI_LE_EXT_ADV_OP_FIRST_FRAG) ||
1290 (op == BT_HCI_LE_EXT_ADV_OP_COMPLETE_DATA)) {
1291 /* NOTE: No update to primary channel PDU time reservation */
1292
1293 lll_adv_aux_data_enqueue(adv->lll.aux, sec_idx);
1294 lll_adv_data_enqueue(&adv->lll, pri_idx);
1295
1296 sr_pdu->type = PDU_ADV_TYPE_AUX_SCAN_RSP;
1297 sr_pdu->rfu = 0U;
1298 sr_pdu->chan_sel = 0U;
1299 sr_pdu->rx_addr = 0U;
1300 if (sr_pdu->len) {
1301 sr_pdu->adv_ext_ind.adv_mode = 0U;
1302 sr_pdu->tx_addr = sec_pdu_prev->tx_addr;
1303 (void)memcpy(&sr_pdu->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
1304 &sec_pdu_prev->adv_ext_ind.ext_hdr.data[ADVA_OFFSET],
1305 BDADDR_SIZE);
1306 } else {
1307 sr_pdu->tx_addr = 0U;
1308 }
1309 }
1310
1311 lll_adv_scan_rsp_enqueue(lll, sr_idx);
1312
1313 return 0;
1314 }
1315
ll_adv_aux_max_data_length_get(void)1316 uint16_t ll_adv_aux_max_data_length_get(void)
1317 {
1318 return CONFIG_BT_CTLR_ADV_DATA_LEN_MAX;
1319 }
1320
ll_adv_aux_set_count_get(void)1321 uint8_t ll_adv_aux_set_count_get(void)
1322 {
1323 return BT_CTLR_ADV_SET;
1324 }
1325
ll_adv_aux_set_remove(uint8_t handle)1326 uint8_t ll_adv_aux_set_remove(uint8_t handle)
1327 {
1328 struct ll_adv_set *adv;
1329 struct lll_adv *lll;
1330
1331 /* Get the advertising set instance */
1332 adv = ull_adv_is_created_get(handle);
1333 if (!adv) {
1334 return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
1335 }
1336
1337 if (adv->is_enabled) {
1338 return BT_HCI_ERR_CMD_DISALLOWED;
1339 }
1340
1341 lll = &adv->lll;
1342
1343 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
1344 if (lll->sync) {
1345 struct ll_adv_sync_set *sync;
1346
1347 sync = HDR_LLL2ULL(lll->sync);
1348
1349 if (sync->is_enabled) {
1350 return BT_HCI_ERR_CMD_DISALLOWED;
1351 }
1352 lll->sync = NULL;
1353
1354 ull_adv_sync_release(sync);
1355 }
1356 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1357
1358 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1359 if (adv->df_cfg) {
1360 if (adv->df_cfg->is_enabled) {
1361 return BT_HCI_ERR_CMD_DISALLOWED;
1362 }
1363
1364 ull_df_adv_cfg_release(adv->df_cfg);
1365 adv->df_cfg = NULL;
1366 }
1367 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1368
1369 /* Release auxiliary channel set */
1370 if (lll->aux) {
1371 struct ll_adv_aux_set *aux;
1372
1373 aux = HDR_LLL2ULL(lll->aux);
1374 lll->aux = NULL;
1375
1376 ull_adv_aux_release(aux);
1377 }
1378
1379 /* Dequeue and release, advertising and scan response data, to keep
1380 * one initial primary channel PDU each for the advertising set.
1381 * This is done to prevent common extended payload format contents from
1382 * being overwritten and corrupted due to same primary PDU buffer being
1383 * used to remove AdvA and other fields are moved over in its place when
1384 * auxiliary PDU is allocated to new advertising set.
1385 */
1386 (void)lll_adv_data_dequeue(&adv->lll.adv_data);
1387 (void)lll_adv_data_dequeue(&adv->lll.scan_rsp);
1388
1389 /* Make the advertising set available for new advertisements */
1390 adv->is_created = 0;
1391
1392 return BT_HCI_ERR_SUCCESS;
1393 }
1394
ll_adv_aux_set_clear(void)1395 uint8_t ll_adv_aux_set_clear(void)
1396 {
1397 uint8_t retval = BT_HCI_ERR_SUCCESS;
1398 uint8_t handle;
1399 uint8_t err;
1400
1401 for (handle = 0; handle < BT_CTLR_ADV_SET; ++handle) {
1402 err = ll_adv_aux_set_remove(handle);
1403 if (err == BT_HCI_ERR_CMD_DISALLOWED) {
1404 retval = err;
1405 }
1406 }
1407
1408 return retval;
1409 }
1410
ull_adv_aux_init(void)1411 int ull_adv_aux_init(void)
1412 {
1413 int err;
1414
1415 err = lll_rand_get(&did_unique, sizeof(did_unique));
1416 if (err) {
1417 return err;
1418 }
1419
1420 err = init_reset();
1421 if (err) {
1422 return err;
1423 }
1424
1425 return 0;
1426 }
1427
ull_adv_aux_reset_finalize(void)1428 int ull_adv_aux_reset_finalize(void)
1429 {
1430 int err;
1431
1432 err = init_reset();
1433 if (err) {
1434 return err;
1435 }
1436
1437 return 0;
1438 }
1439
ull_adv_aux_chm_update(void)1440 uint8_t ull_adv_aux_chm_update(void)
1441 {
1442 /* For each created extended advertising set */
1443 for (uint8_t handle = 0; handle < BT_CTLR_ADV_SET; ++handle) {
1444 struct ll_adv_aux_set *aux;
1445 struct ll_adv_set *adv;
1446 uint8_t chm_last;
1447
1448 adv = ull_adv_is_created_get(handle);
1449 if (!adv || !adv->lll.aux) {
1450 continue;
1451 }
1452
1453 aux = HDR_LLL2ULL(adv->lll.aux);
1454 if (aux->chm_last != aux->chm_first) {
1455 /* TODO: Handle previous Channel Map Update being in
1456 * progress
1457 */
1458 continue;
1459 }
1460
1461 /* Append the channelMapNew that will be picked up by ULL */
1462 chm_last = aux->chm_last + 1;
1463 if (chm_last == DOUBLE_BUFFER_SIZE) {
1464 chm_last = 0U;
1465 }
1466 aux->chm[chm_last].data_chan_count =
1467 ull_chan_map_get(aux->chm[chm_last].data_chan_map);
1468 aux->chm_last = chm_last;
1469
1470 if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) && !aux->is_started) {
1471 /* Ticker not started yet, apply new channel map now
1472 * Note that it should be safe to modify chm_first here
1473 * since advertising is not active
1474 */
1475 aux->chm_first = aux->chm_last;
1476 }
1477 }
1478
1479 /* TODO: Should failure due to Channel Map Update being already in
1480 * progress be returned to caller?
1481 */
1482 return 0;
1483 }
1484
ull_adv_aux_hdr_set_clear(struct ll_adv_set * adv,uint16_t sec_hdr_add_fields,uint16_t sec_hdr_rem_fields,void * hdr_data,uint8_t * pri_idx,uint8_t * sec_idx)1485 uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
1486 uint16_t sec_hdr_add_fields,
1487 uint16_t sec_hdr_rem_fields,
1488 void *hdr_data,
1489 uint8_t *pri_idx, uint8_t *sec_idx)
1490 {
1491 struct pdu_adv_com_ext_adv *pri_com_hdr, *pri_com_hdr_prev;
1492 struct pdu_adv_com_ext_adv *sec_com_hdr, *sec_com_hdr_prev;
1493 struct pdu_adv_ext_hdr *hdr, pri_hdr, pri_hdr_prev;
1494 struct pdu_adv_ext_hdr sec_hdr, sec_hdr_prev;
1495 struct pdu_adv *pri_pdu, *pri_pdu_prev;
1496 struct pdu_adv *sec_pdu_prev, *sec_pdu;
1497 struct pdu_adv_adi *pri_adi, *sec_adi;
1498 uint8_t *pri_dptr, *pri_dptr_prev;
1499 uint8_t *sec_dptr, *sec_dptr_prev;
1500 struct pdu_adv_aux_ptr *aux_ptr;
1501 uint8_t pri_len, sec_len_prev;
1502 struct lll_adv_aux *lll_aux;
1503 uint8_t *ad_fragment = NULL;
1504 uint8_t ad_fragment_len = 0;
1505 struct ll_adv_aux_set *aux;
1506 struct pdu_adv_adi *adi;
1507 struct lll_adv *lll;
1508 uint8_t is_aux_new;
1509 uint8_t *ad_data;
1510 uint16_t sec_len;
1511 uint8_t ad_len;
1512 uint16_t did;
1513
1514 lll = &adv->lll;
1515
1516 /* Can't have both flags set here since both use 'hdr_data' param */
1517 LL_ASSERT(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) ||
1518 !(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA));
1519
1520 /* Get reference to previous primary PDU data */
1521 pri_pdu_prev = lll_adv_data_peek(lll);
1522 if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
1523 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
1524 /* pick the data length */
1525 ad_len = *((uint8_t *)hdr_data);
1526 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
1527
1528 /* pick the reference to data */
1529 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
1530
1531 return ull_adv_data_set(adv, ad_len, ad_data);
1532 }
1533
1534 return BT_HCI_ERR_CMD_DISALLOWED;
1535 }
1536
1537 pri_com_hdr_prev = (void *)&pri_pdu_prev->adv_ext_ind;
1538 hdr = (void *)pri_com_hdr_prev->ext_hdr_adv_data;
1539 if (pri_com_hdr_prev->ext_hdr_len) {
1540 pri_hdr_prev = *hdr;
1541 } else {
1542 *(uint8_t *)&pri_hdr_prev = 0U;
1543 }
1544 pri_dptr_prev = hdr->data;
1545
1546 /* Advertising data are not supported by scannable instances */
1547 if ((sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) &&
1548 (pri_com_hdr_prev->adv_mode & BT_HCI_LE_ADV_PROP_SCAN)) {
1549 return BT_HCI_ERR_INVALID_PARAM;
1550 }
1551
1552 /* Get reference to new primary PDU data buffer */
1553 pri_pdu = lll_adv_data_alloc(lll, pri_idx);
1554 pri_pdu->type = pri_pdu_prev->type;
1555 pri_pdu->rfu = 0U;
1556 pri_pdu->chan_sel = 0U;
1557 pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
1558 pri_com_hdr->adv_mode = pri_com_hdr_prev->adv_mode;
1559 hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
1560 pri_dptr = hdr->data;
1561 *(uint8_t *)&pri_hdr = 0U;
1562
1563 /* Get the reference to aux instance */
1564 lll_aux = lll->aux;
1565 if (!lll_aux) {
1566 aux = ull_adv_aux_acquire(lll);
1567 if (!aux) {
1568 LL_ASSERT(pri_pdu != pri_pdu_prev);
1569
1570 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1571 }
1572
1573 lll_aux = &aux->lll;
1574
1575 if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)) {
1576 ull_adv_aux_created(adv);
1577 }
1578
1579 is_aux_new = 1U;
1580 } else {
1581 aux = HDR_LLL2ULL(lll_aux);
1582 is_aux_new = 0U;
1583 }
1584
1585 /* Get reference to previous secondary PDU data */
1586 sec_pdu_prev = lll_adv_aux_data_peek(lll_aux);
1587 sec_com_hdr_prev = (void *)&sec_pdu_prev->adv_ext_ind;
1588 hdr = (void *)sec_com_hdr_prev->ext_hdr_adv_data;
1589 if (!is_aux_new) {
1590 sec_hdr_prev = *hdr;
1591 } else {
1592 /* Initialize only those fields used to copy into new PDU
1593 * buffer.
1594 */
1595 sec_pdu_prev->tx_addr = 0U;
1596 sec_pdu_prev->rx_addr = 0U;
1597 sec_pdu_prev->len = PDU_AC_EXT_HEADER_SIZE_MIN;
1598 *(uint8_t *)hdr = 0U;
1599 *(uint8_t *)&sec_hdr_prev = 0U;
1600 }
1601 sec_dptr_prev = hdr->data;
1602
1603 /* Get reference to new secondary PDU data buffer */
1604 sec_pdu = lll_adv_aux_data_alloc(lll_aux, sec_idx);
1605 sec_pdu->type = pri_pdu->type;
1606 sec_pdu->rfu = 0U;
1607 sec_pdu->chan_sel = 0U;
1608
1609 sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
1610 sec_pdu->rx_addr = sec_pdu_prev->rx_addr;
1611
1612 sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
1613 sec_com_hdr->adv_mode = pri_com_hdr->adv_mode;
1614 hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
1615 sec_dptr = hdr->data;
1616 *(uint8_t *)&sec_hdr = 0U;
1617
1618 /* AdvA flag */
1619 /* NOTE: as we will use auxiliary packet, we remove AdvA in primary
1620 * channel, i.e. do nothing to not add AdvA in the primary PDU.
1621 * AdvA can be either set explicitly (i.e. needs own_addr_type to be
1622 * set), can be copied from primary PDU (i.e. adding AD to existing set)
1623 * or can be copied from previous secondary PDU.
1624 */
1625 sec_hdr.adv_addr = 1;
1626 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
1627 uint8_t own_addr_type = *(uint8_t *)hdr_data;
1628
1629 /* Move to next hdr_data */
1630 hdr_data = (uint8_t *)hdr_data + sizeof(own_addr_type);
1631
1632 sec_pdu->tx_addr = own_addr_type & 0x1;
1633 } else if (pri_hdr_prev.adv_addr) {
1634 sec_pdu->tx_addr = pri_pdu_prev->tx_addr;
1635 } else if (sec_hdr_prev.adv_addr) {
1636 sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
1637 } else {
1638 /* We do not have valid address info, this should not happen */
1639 return BT_HCI_ERR_UNSPECIFIED;
1640 }
1641 pri_pdu->tx_addr = 0U;
1642
1643 if (pri_hdr_prev.adv_addr) {
1644 pri_dptr_prev += BDADDR_SIZE;
1645 }
1646 if (sec_hdr_prev.adv_addr) {
1647 sec_dptr_prev += BDADDR_SIZE;
1648 }
1649 sec_dptr += BDADDR_SIZE;
1650
1651 /* No TargetA in primary and secondary channel for undirected.
1652 * Move from primary to secondary PDU, if present in primary PDU.
1653 */
1654 if (pri_hdr_prev.tgt_addr) {
1655 sec_hdr.tgt_addr = 1U;
1656 sec_pdu->rx_addr = pri_pdu_prev->rx_addr;
1657 sec_dptr += BDADDR_SIZE;
1658
1659 /* Retain the target address if present in the previous PDU */
1660 } else if (!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) &&
1661 sec_hdr_prev.tgt_addr) {
1662 sec_hdr.tgt_addr = 1U;
1663 sec_pdu->rx_addr = sec_pdu_prev->rx_addr;
1664 sec_dptr += BDADDR_SIZE;
1665 }
1666 pri_pdu->rx_addr = 0U;
1667
1668 if (pri_hdr_prev.tgt_addr) {
1669 pri_dptr_prev += BDADDR_SIZE;
1670 }
1671
1672 if (sec_hdr_prev.tgt_addr) {
1673 sec_dptr_prev += BDADDR_SIZE;
1674 }
1675
1676 /* No CTEInfo flag in primary and secondary channel PDU */
1677
1678 /* ADI flag */
1679 if (pri_hdr_prev.adi) {
1680 pri_dptr_prev += sizeof(struct pdu_adv_adi);
1681 }
1682 pri_hdr.adi = 1;
1683 pri_dptr += sizeof(struct pdu_adv_adi);
1684 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
1685 sec_hdr.adi = 1U;
1686 /* return the size of ADI structure */
1687 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_adi);
1688 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1689 /* pick the reference to ADI param */
1690 (void)memcpy(&adi, hdr_data, sizeof(struct pdu_adv_adi *));
1691 /* return the pointer to ADI struct inside the PDU */
1692 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1693 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1694 sec_dptr += sizeof(struct pdu_adv_adi);
1695 } else {
1696 sec_hdr.adi = 1;
1697 adi = NULL;
1698 sec_dptr += sizeof(struct pdu_adv_adi);
1699 }
1700 if (sec_hdr_prev.adi) {
1701 sec_dptr_prev += sizeof(struct pdu_adv_adi);
1702 }
1703
1704 /* AuxPtr flag */
1705 if (pri_hdr_prev.aux_ptr) {
1706 pri_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
1707 }
1708 pri_hdr.aux_ptr = 1;
1709 pri_dptr += sizeof(struct pdu_adv_aux_ptr);
1710
1711 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1712 sec_hdr.aux_ptr = 1;
1713 aux_ptr = NULL;
1714
1715 /* return the size of aux pointer structure */
1716 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_aux_ptr);
1717 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1718
1719 /* return the pointer to aux pointer struct inside the PDU
1720 * buffer
1721 */
1722 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1723 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1724 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
1725 sec_hdr_prev.aux_ptr) {
1726 sec_hdr.aux_ptr = 1;
1727 aux_ptr = (void *)sec_dptr_prev;
1728 } else {
1729 aux_ptr = NULL;
1730 }
1731 if (sec_hdr_prev.aux_ptr) {
1732 sec_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
1733 }
1734 if (sec_hdr.aux_ptr) {
1735 sec_dptr += sizeof(struct pdu_adv_aux_ptr);
1736 }
1737
1738 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
1739 struct pdu_adv_sync_info *sync_info;
1740
1741 /* No SyncInfo flag in primary channel PDU */
1742 /* Add/Remove SyncInfo flag in secondary channel PDU */
1743 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) {
1744 sec_hdr.sync_info = 1;
1745 sync_info = NULL;
1746
1747 /* return the size of sync info structure */
1748 *(uint8_t *)hdr_data = sizeof(*sync_info);
1749 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1750
1751 /* return the pointer to sync info struct inside the PDU
1752 * buffer
1753 */
1754 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1755 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1756 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) &&
1757 sec_hdr_prev.sync_info) {
1758 sec_hdr.sync_info = 1;
1759 sync_info = (void *)sec_dptr_prev;
1760 } else {
1761 sync_info = NULL;
1762 }
1763 if (sec_hdr_prev.sync_info) {
1764 sec_dptr_prev += sizeof(*sync_info);
1765 }
1766 if (sec_hdr.sync_info) {
1767 sec_dptr += sizeof(*sync_info);
1768 }
1769 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1770
1771 /* Tx Power flag */
1772 if (pri_hdr_prev.tx_pwr) {
1773 pri_dptr_prev++;
1774
1775 /* C1, Tx Power is optional on the LE 1M PHY, and
1776 * reserved for future use on the LE Coded PHY.
1777 */
1778 if (lll->phy_p != PHY_CODED) {
1779 pri_hdr.tx_pwr = 1;
1780 pri_dptr++;
1781 } else {
1782 sec_hdr.tx_pwr = 1;
1783 }
1784 }
1785 if (sec_hdr_prev.tx_pwr) {
1786 sec_dptr_prev++;
1787
1788 sec_hdr.tx_pwr = 1;
1789 }
1790 if (sec_hdr.tx_pwr) {
1791 sec_dptr++;
1792 }
1793
1794 /* No ACAD in primary channel PDU */
1795 /* TODO: ACAD in secondary channel PDU */
1796
1797 /* Calc primary PDU len */
1798 pri_len = ull_adv_aux_hdr_len_calc(pri_com_hdr, &pri_dptr);
1799
1800 /* Calc previous secondary PDU len */
1801 sec_len_prev = ull_adv_aux_hdr_len_calc(sec_com_hdr_prev,
1802 &sec_dptr_prev);
1803
1804 /* Did we parse beyond PDU length? */
1805 if (sec_len_prev > sec_pdu_prev->len) {
1806 /* we should not encounter invalid length */
1807 /* FIXME: release allocations */
1808 return BT_HCI_ERR_UNSPECIFIED;
1809 }
1810
1811 /* Calc current secondary PDU len */
1812 sec_len = ull_adv_aux_hdr_len_calc(sec_com_hdr, &sec_dptr);
1813
1814 /* AD Data, add or remove */
1815 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
1816 uint8_t ad_len_prev;
1817
1818 /* remember the new ad data len */
1819 ad_len = *(uint8_t *)hdr_data;
1820
1821 /* return prev ad data length */
1822 ad_len_prev = sec_pdu_prev->len - sec_len_prev;
1823 *(uint8_t *)hdr_data = ad_len_prev;
1824 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
1825
1826 /* remember the reference to new ad data */
1827 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
1828
1829 /* return the reference to prev ad data */
1830 (void)memcpy(hdr_data, &sec_dptr_prev, sizeof(sec_dptr_prev));
1831 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr_prev);
1832
1833 /* unchanged data */
1834 if (!ad_len && !ad_data) {
1835 ad_len = ad_len_prev;
1836 ad_data = sec_dptr_prev;
1837 }
1838 } else if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND) {
1839 /* Calc the previous AD data length in auxiliary PDU */
1840 ad_len = sec_pdu_prev->len - sec_len_prev;
1841 ad_data = sec_dptr_prev;
1842
1843 /* Append the new ad data fragment */
1844 ad_fragment_len = *(uint8_t *)hdr_data;
1845 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment_len);
1846 (void)memcpy(&ad_fragment, hdr_data, sizeof(ad_fragment));
1847 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment);
1848 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)) {
1849 /* Calc the previous AD data length in auxiliary PDU */
1850 ad_len = sec_pdu_prev->len - sec_len_prev;
1851 ad_data = sec_dptr_prev;
1852 } else {
1853 ad_len = 0U;
1854 ad_data = NULL;
1855 }
1856
1857 /* Check Max Advertising Data Length */
1858 if (ad_len + ad_fragment_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1859 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1860 }
1861
1862 /* Check AdvData overflow */
1863 /* TODO: need aux_chain_ind support */
1864 if ((sec_len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) {
1865 /* return excess length */
1866 *(uint8_t *)hdr_data = sec_len + ad_len + ad_fragment_len -
1867 PDU_AC_PAYLOAD_SIZE_MAX;
1868
1869 if (pri_pdu == pri_pdu_prev) {
1870 lll_adv_data_enqueue(&adv->lll, *pri_idx);
1871 }
1872 if (sec_pdu == sec_pdu_prev) {
1873 lll_adv_aux_data_enqueue(adv->lll.aux, *sec_idx);
1874 }
1875
1876 /* Will use packet too long error to determine fragmenting
1877 * long data
1878 */
1879 return BT_HCI_ERR_PACKET_TOO_LONG;
1880 }
1881
1882 /* set the primary PDU len */
1883 ull_adv_aux_hdr_len_fill(pri_com_hdr, pri_len);
1884 pri_pdu->len = pri_len;
1885
1886 /* set the secondary PDU len */
1887 ull_adv_aux_hdr_len_fill(sec_com_hdr, sec_len);
1888 sec_pdu->len = sec_len + ad_len + ad_fragment_len;
1889
1890 /* Start filling pri and sec PDU payload based on flags from here
1891 * ==============================================================
1892 */
1893
1894 /* No AdvData in primary channel PDU */
1895 /* Fill AdvData in secondary PDU */
1896 (void)memmove(sec_dptr, ad_data, ad_len);
1897
1898 if (ad_fragment) {
1899 (void)memcpy(sec_dptr + ad_len, ad_fragment, ad_fragment_len);
1900 }
1901
1902 /* Early exit if no flags set */
1903 if (!sec_com_hdr->ext_hdr_len) {
1904 return 0;
1905 }
1906
1907 /* No ACAD in primary channel PDU */
1908 /* TODO: Fill ACAD in secondary channel PDU */
1909
1910 /* Tx Power */
1911 if (pri_hdr.tx_pwr) {
1912 *--pri_dptr = *--pri_dptr_prev;
1913 } else if (sec_hdr.tx_pwr) {
1914 *--sec_dptr = *--sec_dptr_prev;
1915 }
1916
1917 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
1918 /* No SyncInfo in primary channel PDU */
1919 /* Fill SyncInfo in secondary channel PDU */
1920 if (sec_hdr_prev.sync_info) {
1921 sec_dptr_prev -= sizeof(*sync_info);
1922 }
1923
1924 if (sec_hdr.sync_info) {
1925 sec_dptr -= sizeof(*sync_info);
1926 }
1927
1928 if (sync_info) {
1929 (void)memmove(sec_dptr, sync_info, sizeof(*sync_info));
1930 }
1931 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1932
1933 /* AuxPtr */
1934 if (pri_hdr_prev.aux_ptr) {
1935 pri_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
1936 }
1937 pri_dptr -= sizeof(struct pdu_adv_aux_ptr);
1938 ull_adv_aux_ptr_fill((void *)pri_dptr, 0U, lll->phy_s);
1939
1940 if (sec_hdr_prev.aux_ptr) {
1941 sec_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
1942 }
1943 if (sec_hdr.aux_ptr) {
1944 sec_dptr -= sizeof(struct pdu_adv_aux_ptr);
1945 }
1946
1947 if (aux_ptr) {
1948 (void)memmove(sec_dptr, aux_ptr, sizeof(*aux_ptr));
1949 }
1950
1951 /* ADI */
1952 if (pri_hdr_prev.adi) {
1953 pri_dptr_prev -= sizeof(struct pdu_adv_adi);
1954 }
1955 if (sec_hdr_prev.adi) {
1956 sec_dptr_prev -= sizeof(struct pdu_adv_adi);
1957 }
1958
1959 pri_dptr -= sizeof(struct pdu_adv_adi);
1960 sec_dptr -= sizeof(struct pdu_adv_adi);
1961
1962 pri_adi = (void *)pri_dptr;
1963 sec_adi = (void *)sec_dptr;
1964
1965 if (!adi) {
1966 /* The DID for a specific SID shall be unique.
1967 */
1968 did = ull_adv_aux_did_next_unique_get(adv->sid);
1969 } else {
1970 did = PDU_ADV_ADI_DID_GET(adi);
1971 }
1972
1973 did = sys_cpu_to_le16(did);
1974 PDU_ADV_ADI_DID_SID_SET(pri_adi, did, adv->sid);
1975 PDU_ADV_ADI_DID_SID_SET(sec_adi, did, adv->sid);
1976
1977 /* No CTEInfo field in primary channel PDU */
1978
1979 /* No TargetA non-conn non-scan advertising, but present in directed
1980 * advertising.
1981 */
1982 if (sec_hdr.tgt_addr) {
1983 void *bdaddr;
1984
1985 if (sec_hdr_prev.tgt_addr) {
1986 sec_dptr_prev -= BDADDR_SIZE;
1987 bdaddr = sec_dptr_prev;
1988 } else {
1989 pri_dptr_prev -= BDADDR_SIZE;
1990 bdaddr = pri_dptr_prev;
1991 }
1992
1993 sec_dptr -= BDADDR_SIZE;
1994
1995 (void)memcpy(sec_dptr, bdaddr, BDADDR_SIZE);
1996 }
1997
1998 /* No AdvA in primary channel due to AuxPtr being added */
1999
2000 /* NOTE: AdvA in aux channel is also filled at enable and RPA
2001 * timeout
2002 */
2003 if (sec_hdr.adv_addr) {
2004 void *bdaddr;
2005
2006 if (sec_hdr_prev.adv_addr) {
2007 sec_dptr_prev -= BDADDR_SIZE;
2008 bdaddr = sec_dptr_prev;
2009 } else {
2010 pri_dptr_prev -= BDADDR_SIZE;
2011 bdaddr = pri_dptr_prev;
2012 }
2013
2014 sec_dptr -= BDADDR_SIZE;
2015
2016 (void)memcpy(sec_dptr, bdaddr, BDADDR_SIZE);
2017 }
2018
2019 /* Set the common extended header format flags in the current primary
2020 * PDU
2021 */
2022 if (pri_com_hdr->ext_hdr_len != 0) {
2023 pri_com_hdr->ext_hdr = pri_hdr;
2024 }
2025
2026 /* Set the common extended header format flags in the current secondary
2027 * PDU
2028 */
2029 if (sec_com_hdr->ext_hdr_len != 0) {
2030 sec_com_hdr->ext_hdr = sec_hdr;
2031 }
2032
2033 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
2034 ull_adv_aux_chain_pdu_duplicate(sec_pdu_prev, sec_pdu, aux_ptr,
2035 adv->lll.phy_s, adv->lll.phy_flags,
2036 EVENT_B2B_MAFS_US);
2037 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
2038
2039 /* Update auxiliary channel event time reservation */
2040 if (aux->is_started) {
2041 struct pdu_adv *pdu_scan;
2042 uint8_t err;
2043
2044 pdu_scan = lll_adv_scan_rsp_peek(lll);
2045 err = aux_time_update(aux, sec_pdu, pdu_scan);
2046 if (err) {
2047 return err;
2048 }
2049 }
2050
2051 return 0;
2052 }
2053
ull_adv_aux_pdu_set_clear(struct ll_adv_set * adv,struct pdu_adv * pdu_prev,struct pdu_adv * pdu,uint16_t hdr_add_fields,uint16_t hdr_rem_fields,void * hdr_data)2054 uint8_t ull_adv_aux_pdu_set_clear(struct ll_adv_set *adv,
2055 struct pdu_adv *pdu_prev,
2056 struct pdu_adv *pdu,
2057 uint16_t hdr_add_fields,
2058 uint16_t hdr_rem_fields,
2059 void *hdr_data)
2060 {
2061 struct pdu_adv_com_ext_adv *com_hdr, *com_hdr_prev;
2062 struct pdu_adv_ext_hdr hdr = { 0 }, hdr_prev = { 0 };
2063 struct pdu_adv_aux_ptr *aux_ptr, *aux_ptr_prev;
2064 uint8_t *ad_fragment = NULL;
2065 uint8_t ad_fragment_len = 0;
2066 uint8_t *dptr, *dptr_prev;
2067 struct pdu_adv_adi *adi;
2068 uint8_t acad_len_prev;
2069 uint8_t hdr_buf_len;
2070 uint8_t len_prev;
2071 uint8_t *ad_data;
2072 uint8_t acad_len;
2073 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2074 uint8_t cte_info;
2075 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2076 uint8_t ad_len;
2077 uint16_t len;
2078
2079 /* Get common pointers from reference to previous tertiary PDU data */
2080 com_hdr_prev = (void *)&pdu_prev->adv_ext_ind;
2081 if (pdu_prev->len && com_hdr_prev->ext_hdr_len) {
2082 hdr_prev = com_hdr_prev->ext_hdr;
2083 } else {
2084 com_hdr_prev->ext_hdr_len = 0U;
2085 }
2086 dptr_prev = com_hdr_prev->ext_hdr.data;
2087
2088 /* Set common fields in reference to new tertiary PDU data buffer */
2089 pdu->type = pdu_prev->type;
2090 pdu->rfu = 0U;
2091 pdu->chan_sel = 0U;
2092
2093 pdu->tx_addr = pdu_prev->tx_addr;
2094 pdu->rx_addr = pdu_prev->rx_addr;
2095
2096 /* Get common pointers from current tertiary PDU data.
2097 * It is possible that the current tertiary is the same as
2098 * previous one. It may happen if update periodic advertising
2099 * chain in place.
2100 */
2101 com_hdr = (void *)&pdu->adv_ext_ind;
2102 com_hdr->adv_mode = com_hdr_prev->adv_mode;
2103 dptr = com_hdr->ext_hdr.data;
2104
2105 /* AdvA flag */
2106 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
2107 hdr.adv_addr = 1U;
2108 dptr += BDADDR_SIZE;
2109 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) &&
2110 hdr_prev.adv_addr) {
2111 hdr.adv_addr = 1U;
2112 pdu->tx_addr = pdu_prev->tx_addr;
2113
2114 dptr += BDADDR_SIZE;
2115 }
2116 if (hdr_prev.adv_addr) {
2117 dptr_prev += BDADDR_SIZE;
2118 }
2119
2120 /* TargetA flag */
2121 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_TARGETA) {
2122 hdr.tgt_addr = 1U;
2123 dptr += BDADDR_SIZE;
2124 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_TARGETA) &&
2125 hdr_prev.tgt_addr) {
2126 hdr.tgt_addr = 1U;
2127 pdu->rx_addr = pdu_prev->rx_addr;
2128
2129 dptr += BDADDR_SIZE;
2130 }
2131 if (hdr_prev.tgt_addr) {
2132 dptr_prev += BDADDR_SIZE;
2133 }
2134
2135 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2136 /* If requested add or update CTEInfo */
2137 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2138 hdr.cte_info = 1;
2139 cte_info = *(uint8_t *)hdr_data;
2140 hdr_data = (uint8_t *)hdr_data + 1;
2141 dptr += sizeof(struct pdu_cte_info);
2142 /* If CTEInfo exists in prev and is not requested to be removed */
2143 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) &&
2144 hdr_prev.cte_info) {
2145 hdr.cte_info = 1;
2146 cte_info = 0U; /* value not used, will be read from prev PDU */
2147 dptr += sizeof(struct pdu_cte_info);
2148 } else {
2149 cte_info = 0U; /* value not used */
2150 }
2151
2152 /* If CTEInfo exists in prev PDU */
2153 if (hdr_prev.cte_info) {
2154 dptr_prev += sizeof(struct pdu_cte_info);
2155 }
2156 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2157
2158 /* ADI */
2159 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
2160 hdr.adi = 1U;
2161 /* return the size of ADI structure */
2162 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_adi);
2163 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
2164 /* pick the reference to ADI param */
2165 (void)memcpy(&adi, hdr_data, sizeof(struct pdu_adv_adi *));
2166 /* return the pointer to ADI struct inside the PDU */
2167 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2168 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2169 dptr += sizeof(struct pdu_adv_adi);
2170 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ADI) &&
2171 hdr_prev.adi) {
2172 hdr.adi = 1U;
2173 adi = (void *)dptr_prev;
2174 dptr += sizeof(struct pdu_adv_adi);
2175 } else {
2176 adi = NULL;
2177 }
2178 if (hdr_prev.adi) {
2179 dptr_prev += sizeof(struct pdu_adv_adi);
2180 }
2181
2182 /* AuxPtr - will be added if AUX_CHAIN_IND is required */
2183 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
2184 hdr.aux_ptr = 1;
2185 aux_ptr_prev = NULL;
2186 aux_ptr = (void *)dptr;
2187
2188 /* return the size of aux pointer structure */
2189 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_aux_ptr);
2190 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
2191
2192 /* return the pointer to aux pointer struct inside the PDU
2193 * buffer
2194 */
2195 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2196 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2197 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
2198 hdr_prev.aux_ptr) {
2199 hdr.aux_ptr = 1;
2200 aux_ptr_prev = (void *)dptr_prev;
2201 aux_ptr = (void *)dptr;
2202 } else {
2203 aux_ptr_prev = NULL;
2204 aux_ptr = NULL;
2205 }
2206 if (hdr_prev.aux_ptr) {
2207 dptr_prev += sizeof(struct pdu_adv_aux_ptr);
2208 }
2209 if (hdr.aux_ptr) {
2210 dptr += sizeof(struct pdu_adv_aux_ptr);
2211 }
2212
2213 /* SyncInfo flag */
2214 if (hdr_prev.sync_info) {
2215 hdr.sync_info = 1;
2216 dptr_prev += sizeof(struct pdu_adv_sync_info);
2217 dptr += sizeof(struct pdu_adv_sync_info);
2218 }
2219
2220 /* Tx Power flag */
2221 if (hdr_prev.tx_pwr) {
2222 dptr_prev++;
2223
2224 hdr.tx_pwr = 1;
2225 dptr++;
2226 }
2227
2228 /* Calc previous ACAD len and update PDU len */
2229 len_prev = dptr_prev - (uint8_t *)com_hdr_prev;
2230 hdr_buf_len = com_hdr_prev->ext_hdr_len +
2231 PDU_AC_EXT_HEADER_SIZE_MIN;
2232 if (len_prev <= hdr_buf_len) {
2233 /* There are some data, except ACAD, in extended header if len_prev
2234 * equals to hdr_buf_len. There is ACAD if the size of len_prev
2235 * is smaller than hdr_buf_len.
2236 */
2237 acad_len_prev = hdr_buf_len - len_prev;
2238 len_prev += acad_len_prev;
2239 dptr_prev += acad_len_prev;
2240 } else {
2241 /* There are no data in extended header, all flags are zeros. */
2242 acad_len_prev = 0;
2243 /* NOTE: If no flags are set then extended header length will be
2244 * zero. Under this condition the current len_prev
2245 * value will be greater than extended header length,
2246 * hence set len_prev to size of the length/mode
2247 * field.
2248 */
2249 len_prev = (pdu_prev->len) ? PDU_AC_EXT_HEADER_SIZE_MIN : 0U;
2250 dptr_prev = (uint8_t *)com_hdr_prev + len_prev;
2251 }
2252
2253 /* Did we parse beyond PDU length? */
2254 if (len_prev > pdu_prev->len) {
2255 /* we should not encounter invalid length */
2256 return BT_HCI_ERR_UNSPECIFIED;
2257 }
2258
2259 /* Add/Retain/Remove ACAD */
2260 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ACAD) {
2261 acad_len = *(uint8_t *)hdr_data;
2262 /* If zero length ACAD then do not reduce ACAD but return
2263 * return previous ACAD length.
2264 */
2265 if (!acad_len) {
2266 acad_len = acad_len_prev;
2267 }
2268 /* return prev ACAD length */
2269 *(uint8_t *)hdr_data = acad_len_prev;
2270 hdr_data = (uint8_t *)hdr_data + 1;
2271 /* return the pointer to ACAD offset */
2272 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2273 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2274 dptr += acad_len;
2275 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ACAD)) {
2276 acad_len = acad_len_prev;
2277 dptr += acad_len_prev;
2278 } else {
2279 acad_len = 0U;
2280 }
2281
2282 /* Calc current tertiary PDU len so far without AD data added */
2283 len = ull_adv_aux_hdr_len_calc(com_hdr, &dptr);
2284
2285 /* Get Adv data from function parameters */
2286 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
2287 uint8_t ad_len_prev;
2288
2289 /* remember the new ad data len */
2290 ad_len = *(uint8_t *)hdr_data;
2291
2292 /* return prev ad data length */
2293 ad_len_prev = pdu_prev->len - len_prev;
2294 *(uint8_t *)hdr_data = ad_len_prev;
2295 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
2296
2297 /* remember the reference to new ad data */
2298 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
2299
2300 /* return the reference to prev ad data */
2301 (void)memcpy(hdr_data, &dptr_prev, sizeof(dptr_prev));
2302 hdr_data = (uint8_t *)hdr_data + sizeof(dptr_prev);
2303
2304 /* unchanged data */
2305 if (!ad_len && !ad_data) {
2306 ad_len = ad_len_prev;
2307 ad_data = dptr_prev;
2308 }
2309 } else if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND) {
2310 ad_len = pdu_prev->len - len_prev;
2311 ad_data = dptr_prev;
2312
2313 /* Append the new ad data fragment */
2314 ad_fragment_len = *(uint8_t *)hdr_data;
2315 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment_len);
2316 (void)memcpy(&ad_fragment, hdr_data, sizeof(ad_fragment));
2317 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment);
2318 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)) {
2319 ad_len = pdu_prev->len - len_prev;
2320 ad_data = dptr_prev;
2321 } else {
2322 ad_len = 0;
2323 ad_data = NULL;
2324 }
2325
2326 /* Check Max Advertising Data Length */
2327 if (ad_len + ad_fragment_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
2328 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
2329 }
2330
2331 /* Check AdvData overflow */
2332 if ((len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) {
2333 /* return excess length */
2334 *(uint8_t *)hdr_data = len + ad_len + ad_fragment_len -
2335 PDU_AC_PAYLOAD_SIZE_MAX;
2336
2337 /* Will use packet too long error to determine fragmenting
2338 * long data
2339 */
2340 return BT_HCI_ERR_PACKET_TOO_LONG;
2341 }
2342
2343 /* set the tertiary extended header and PDU length */
2344 ull_adv_aux_hdr_len_fill(com_hdr, len);
2345 pdu->len = len + ad_len + ad_fragment_len;
2346
2347 /* Start filling tertiary PDU payload based on flags from here
2348 * ==============================================================
2349 */
2350
2351 /* Fill AdvData in tertiary PDU */
2352 (void)memmove(dptr, ad_data, ad_len);
2353
2354 if (ad_fragment) {
2355 (void)memcpy(dptr + ad_len, ad_fragment, ad_fragment_len);
2356 }
2357
2358 /* Early exit if no flags set */
2359 if (!com_hdr->ext_hdr_len) {
2360 return 0;
2361 }
2362
2363 /* Retain ACAD in tertiary PDU */
2364 dptr_prev -= acad_len_prev;
2365 if (acad_len) {
2366 dptr -= acad_len;
2367 (void)memmove(dptr, dptr_prev, acad_len_prev);
2368 }
2369
2370 /* Tx Power */
2371 if (hdr.tx_pwr) {
2372 *--dptr = *--dptr_prev;
2373 }
2374
2375 /* SyncInfo */
2376 if (hdr.sync_info) {
2377 dptr_prev -= sizeof(struct pdu_adv_sync_info);
2378 dptr -= sizeof(struct pdu_adv_sync_info);
2379
2380 (void)memmove(dptr, dptr_prev,
2381 sizeof(struct pdu_adv_sync_info));
2382 }
2383
2384 /* AuxPtr */
2385 if (hdr_prev.aux_ptr) {
2386 dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
2387 }
2388 if (hdr.aux_ptr) {
2389 dptr -= sizeof(struct pdu_adv_aux_ptr);
2390 }
2391 if (aux_ptr_prev) {
2392 (void)memmove(dptr, aux_ptr_prev, sizeof(*aux_ptr_prev));
2393 }
2394
2395 /* ADI */
2396 if (hdr_prev.adi) {
2397 dptr_prev -= sizeof(struct pdu_adv_adi);
2398 }
2399 if (hdr.adi) {
2400 struct pdu_adv_adi *adi_pdu;
2401
2402 dptr -= sizeof(struct pdu_adv_adi);
2403 adi_pdu = (void *)dptr;
2404
2405 if (!adi) {
2406 /* The DID for a specific SID shall be unique.
2407 */
2408 const uint16_t did =
2409 sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
2410 PDU_ADV_ADI_DID_SID_SET(adi_pdu, did, adv->sid);
2411 } else {
2412 adi_pdu->did_sid_packed[0] = adi->did_sid_packed[0];
2413 adi_pdu->did_sid_packed[1] = adi->did_sid_packed[1];
2414 }
2415 }
2416
2417 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2418 if (hdr.cte_info) {
2419 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2420 *--dptr = cte_info;
2421 } else {
2422 *--dptr = *--dptr_prev;
2423 }
2424 }
2425 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2426
2427 /* No TargetA in non-conn non-scan advertising, but present in directed
2428 * advertising.
2429 */
2430 if (hdr.tgt_addr) {
2431 dptr_prev -= BDADDR_SIZE;
2432 dptr -= BDADDR_SIZE;
2433
2434 (void)memmove(dptr, dptr_prev, BDADDR_SIZE);
2435 }
2436
2437 /* NOTE: AdvA in aux channel is also filled at enable and RPA
2438 * timeout
2439 */
2440 if (hdr.adv_addr) {
2441 dptr_prev -= BDADDR_SIZE;
2442 dptr -= BDADDR_SIZE;
2443
2444 (void)memmove(dptr, dptr_prev, BDADDR_SIZE);
2445 }
2446
2447 if (com_hdr->ext_hdr_len != 0) {
2448 com_hdr->ext_hdr = hdr;
2449 }
2450
2451 return 0;
2452 }
2453
ull_adv_aux_did_next_unique_get(uint8_t sid)2454 uint16_t ull_adv_aux_did_next_unique_get(uint8_t sid)
2455 {
2456 /* The DID is 12 bits and did_unique may overflow without any negative
2457 * consequences.
2458 */
2459 return BIT_MASK(12) & did_unique[sid]++;
2460 }
2461
ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr * aux_ptr,uint32_t offs_us,uint8_t phy_s)2462 void ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr *aux_ptr, uint32_t offs_us,
2463 uint8_t phy_s)
2464 {
2465 uint32_t offs;
2466 uint8_t phy;
2467
2468 /* NOTE: Channel Index and Aux Offset will be set on every advertiser's
2469 * event prepare when finding the auxiliary event's ticker offset.
2470 * Here we fill initial values.
2471 */
2472 aux_ptr->chan_idx = 0U;
2473
2474 aux_ptr->ca = (lll_clock_ppm_local_get() <= SCA_50_PPM) ?
2475 SCA_VALUE_50_PPM : SCA_VALUE_500_PPM;
2476
2477 offs = offs_us / OFFS_UNIT_30_US;
2478 if (!!(offs >> OFFS_UNIT_BITS)) {
2479 offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
2480 aux_ptr->offs_units = OFFS_UNIT_VALUE_300_US;
2481 } else {
2482 aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
2483 }
2484 phy = find_lsb_set(phy_s) - 1;
2485
2486 aux_ptr->offs_phy_packed[0] = offs & 0xFF;
2487 aux_ptr->offs_phy_packed[1] = ((offs>>8) & 0x1F) + (phy << 5);
2488 }
2489
2490 #if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
ull_adv_aux_handle_get(struct ll_adv_aux_set * aux)2491 inline uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux)
2492 {
2493 return mem_index_get(aux, ll_adv_aux_pool,
2494 sizeof(struct ll_adv_aux_set));
2495 }
2496
ull_adv_aux_lll_handle_get(struct lll_adv_aux * lll)2497 uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll)
2498 {
2499 return ull_adv_aux_handle_get((void *)lll->hdr.parent);
2500 }
2501
ull_adv_aux_evt_init(struct ll_adv_aux_set * aux,uint32_t * ticks_anchor)2502 uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
2503 uint32_t *ticks_anchor)
2504 {
2505 uint32_t ticks_slot_overhead;
2506 uint32_t time_us;
2507
2508 time_us = aux_time_min_get(aux);
2509
2510 /* TODO: active_to_start feature port */
2511 aux->ull.ticks_active_to_start = 0;
2512 aux->ull.ticks_prepare_to_start =
2513 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
2514 aux->ull.ticks_preempt_to_start =
2515 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
2516 aux->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
2517
2518 if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
2519 ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start,
2520 aux->ull.ticks_prepare_to_start);
2521 } else {
2522 ticks_slot_overhead = 0;
2523 }
2524
2525 #if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
2526 uint32_t ticks_anchor_aux;
2527 uint32_t ticks_slot;
2528 int err;
2529
2530 #if defined(CONFIG_BT_CTLR_ADV_RESERVE_MAX)
2531 time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
2532 PDU_AC_PAYLOAD_SIZE_MAX);
2533 ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
2534 #else
2535 ticks_slot = aux->ull.ticks_slot;
2536 #endif
2537
2538 err = ull_sched_adv_aux_sync_free_anchor_get((ticks_slot +
2539 ticks_slot_overhead),
2540 &ticks_anchor_aux);
2541 if (!err) {
2542 *ticks_anchor = ticks_anchor_aux;
2543 *ticks_anchor += HAL_TICKER_US_TO_TICKS(
2544 MAX(EVENT_MAFS_US,
2545 EVENT_OVERHEAD_START_US) -
2546 EVENT_OVERHEAD_START_US +
2547 (EVENT_TICKER_RES_MARGIN_US << 1));
2548 }
2549 #endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
2550
2551 return ticks_slot_overhead;
2552 }
2553
2554 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_sync_started_stopped(struct ll_adv_aux_set * aux)2555 void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux)
2556 {
2557 if (aux->is_started) {
2558 struct lll_adv_sync *lll_sync = aux->lll.adv->sync;
2559 struct ll_adv_sync_set *sync;
2560 uint8_t aux_handle;
2561
2562 LL_ASSERT(lll_sync);
2563
2564 sync = HDR_LLL2ULL(lll_sync);
2565 aux_handle = ull_adv_aux_handle_get(aux);
2566
2567 if (sync->is_started) {
2568 uint8_t sync_handle = ull_adv_sync_handle_get(sync);
2569
2570 ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2571 (TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
2572 ticker_update_op_cb, aux, 0,
2573 TICKER_ID_ADV_SYNC_BASE + sync_handle);
2574 } else {
2575 ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2576 (TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
2577 ticker_update_op_cb, aux, 0,
2578 TICKER_NULL);
2579 }
2580 }
2581 }
2582 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2583
ull_adv_aux_start(struct ll_adv_aux_set * aux,uint32_t ticks_anchor,uint32_t ticks_slot_overhead)2584 uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
2585 uint32_t ticks_slot_overhead)
2586 {
2587 uint32_t volatile ret_cb;
2588 uint32_t interval_us;
2589 uint8_t aux_handle;
2590 uint32_t ret;
2591
2592 ull_hdr_init(&aux->ull);
2593 aux_handle = ull_adv_aux_handle_get(aux);
2594 interval_us = aux->interval * PERIODIC_INT_UNIT_US;
2595
2596 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2597 if (aux->lll.adv->sync) {
2598 const struct ll_adv_sync_set *sync = HDR_LLL2ULL(aux->lll.adv->sync);
2599 uint8_t sync_handle = ull_adv_sync_handle_get(sync);
2600
2601 ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_ID_ADV_SYNC_BASE +
2602 sync_handle;
2603 } else {
2604 ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_NULL;
2605 }
2606
2607 ll_adv_aux_ticker_ext[aux_handle].ext_timeout_func = ticker_cb;
2608
2609 ret_cb = TICKER_STATUS_BUSY;
2610 ret = ticker_start_ext(
2611 #else /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2612
2613 ret_cb = TICKER_STATUS_BUSY;
2614 ret = ticker_start(
2615 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2616 TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2617 (TICKER_ID_ADV_AUX_BASE + aux_handle),
2618 ticks_anchor, 0U,
2619 HAL_TICKER_US_TO_TICKS(interval_us),
2620 HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
2621 (aux->ull.ticks_slot + ticks_slot_overhead),
2622 ticker_cb, aux,
2623 ull_ticker_status_give, (void *)&ret_cb
2624 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2625 ,
2626 &ll_adv_aux_ticker_ext[aux_handle]
2627 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2628 );
2629 ret = ull_ticker_status_take(ret, &ret_cb);
2630
2631 return ret;
2632 }
2633
ull_adv_aux_stop(struct ll_adv_aux_set * aux)2634 int ull_adv_aux_stop(struct ll_adv_aux_set *aux)
2635 {
2636 uint8_t aux_handle;
2637 int err;
2638
2639 aux_handle = ull_adv_aux_handle_get(aux);
2640
2641 err = ull_ticker_stop_with_mark(TICKER_ID_ADV_AUX_BASE + aux_handle,
2642 aux, &aux->lll);
2643 LL_ASSERT(err == 0 || err == -EALREADY);
2644 if (err) {
2645 return err;
2646 }
2647
2648 aux->is_started = 0U;
2649
2650 return 0;
2651 }
2652
ull_adv_aux_acquire(struct lll_adv * lll)2653 struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll)
2654 {
2655 struct lll_adv_aux *lll_aux;
2656 struct ll_adv_aux_set *aux;
2657 uint8_t chm_last;
2658 int err;
2659
2660 aux = aux_acquire();
2661 if (!aux) {
2662 return aux;
2663 }
2664
2665 lll_aux = &aux->lll;
2666 lll->aux = lll_aux;
2667 lll_aux->adv = lll;
2668
2669 lll_adv_data_reset(&lll_aux->data);
2670 err = lll_adv_aux_data_init(&lll_aux->data);
2671 if (err) {
2672 return NULL;
2673 }
2674
2675 /* Initialize data channel calculation counter, data channel identifier,
2676 * and channel map to use.
2677 */
2678 lll_csrand_get(&lll_aux->data_chan_counter,
2679 sizeof(lll_aux->data_chan_counter));
2680 lll_csrand_get(&aux->data_chan_id, sizeof(aux->data_chan_id));
2681 chm_last = aux->chm_first;
2682 aux->chm_last = chm_last;
2683 aux->chm[chm_last].data_chan_count =
2684 ull_chan_map_get(aux->chm[chm_last].data_chan_map);
2685
2686
2687 /* NOTE: ull_hdr_init(&aux->ull); is done on start */
2688 lll_hdr_init(lll_aux, aux);
2689
2690 aux->is_started = 0U;
2691
2692 return aux;
2693 }
2694
ull_adv_aux_release(struct ll_adv_aux_set * aux)2695 void ull_adv_aux_release(struct ll_adv_aux_set *aux)
2696 {
2697 lll_adv_data_release(&aux->lll.data);
2698 aux_release(aux);
2699 }
2700
ull_adv_aux_get(uint8_t handle)2701 struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle)
2702 {
2703 if (handle >= CONFIG_BT_CTLR_ADV_AUX_SET) {
2704 return NULL;
2705 }
2706
2707 return &ll_adv_aux_pool[handle];
2708 }
2709
ull_adv_aux_time_get(const struct ll_adv_aux_set * aux,uint8_t pdu_len,uint8_t pdu_scan_len)2710 uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
2711 uint8_t pdu_scan_len)
2712 {
2713 const struct pdu_adv *pdu;
2714
2715 pdu = lll_adv_aux_data_peek(&aux->lll);
2716
2717 return aux_time_get(aux, pdu, pdu_len, pdu_scan_len);
2718 }
2719
2720 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_aux_offset_get(struct ll_adv_set * adv)2721 void ull_adv_aux_offset_get(struct ll_adv_set *adv)
2722 {
2723 static memq_link_t link;
2724 static struct mayfly mfy = {0, 0, &link, NULL, mfy_aux_offset_get};
2725 uint32_t ret;
2726
2727 /* NOTE: Single mayfly instance is sufficient as primary channel PDUs
2728 * use time reservation, and this mayfly shall complete within
2729 * the radio event. Multiple advertising sets do not need
2730 * independent mayfly allocations.
2731 */
2732 mfy.param = adv;
2733 ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
2734 &mfy);
2735 LL_ASSERT(!ret);
2736 }
2737 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2738
ull_adv_aux_lll_offset_fill(struct pdu_adv * pdu,uint32_t ticks_offset,uint32_t remainder_us,uint32_t start_us)2739 struct pdu_adv_aux_ptr *ull_adv_aux_lll_offset_fill(struct pdu_adv *pdu,
2740 uint32_t ticks_offset,
2741 uint32_t remainder_us,
2742 uint32_t start_us)
2743 {
2744 struct pdu_adv_com_ext_adv *pri_com_hdr;
2745 struct pdu_adv_aux_ptr *aux_ptr;
2746 struct pdu_adv_ext_hdr *h;
2747 uint32_t offs;
2748 uint8_t *ptr;
2749
2750 pri_com_hdr = (void *)&pdu->adv_ext_ind;
2751 h = (void *)pri_com_hdr->ext_hdr_adv_data;
2752 ptr = h->data;
2753
2754 /* traverse through adv_addr, if present */
2755 if (h->adv_addr) {
2756 ptr += BDADDR_SIZE;
2757 }
2758
2759 /* traverse through tgt_addr, if present */
2760 if (h->tgt_addr) {
2761 ptr += BDADDR_SIZE;
2762 }
2763
2764 /* No CTEInfo flag in primary and secondary channel PDU */
2765
2766 /* traverse through adi, if present */
2767 if (h->adi) {
2768 ptr += sizeof(struct pdu_adv_adi);
2769 }
2770
2771 aux_ptr = (void *)ptr;
2772 offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
2773 offs = offs / OFFS_UNIT_30_US;
2774 if (!!(offs >> OFFS_UNIT_BITS)) {
2775 offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
2776 aux_ptr->offs_units = OFFS_UNIT_VALUE_300_US;
2777 } else {
2778 aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
2779 }
2780 aux_ptr->offs_phy_packed[0] = offs & 0xFF;
2781 aux_ptr->offs_phy_packed[1] = ((offs>>8) & 0x1F) + (aux_ptr->offs_phy_packed[1] & 0xE0);
2782
2783 return aux_ptr;
2784 }
2785
ull_adv_aux_done(struct node_rx_event_done * done)2786 void ull_adv_aux_done(struct node_rx_event_done *done)
2787 {
2788 struct lll_adv_aux *lll_aux;
2789 struct ll_adv_aux_set *aux;
2790 struct ll_adv_set *adv;
2791
2792 /* Get reference to ULL context */
2793 aux = CONTAINER_OF(done->param, struct ll_adv_aux_set, ull);
2794 lll_aux = &aux->lll;
2795 adv = HDR_LLL2ULL(lll_aux->adv);
2796
2797 /* Call the primary channel advertising done */
2798 done->param = &adv->ull;
2799 ull_adv_done(done);
2800 }
2801
2802 #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
2803 /* @brief Duplicate previous chain of PDUs into current chain of PDUs, fill the
2804 * aux ptr field of the parent primary channel PDU with the aux offset,
2805 * and the secondary channel PDU's PHY.
2806 *
2807 * @param[in] pdu_prev Pointer to previous PDU's chain PDU
2808 * @param[in] pdu Pointer to current PDU's chain PDU
2809 * @param[in] aux_ptr Pointer to aux ptr field in the primary channel PDU
2810 * @param[in] phy_s Secondary/auxiliary PDU PHY
2811 * @param[in] phy_flags Secondary/auxiliary PDU coded PHY encoding (S2/S8)
2812 * @param[in] mafs_us Minimum Aux Frame Spacing to use, in microseconds
2813 */
ull_adv_aux_chain_pdu_duplicate(struct pdu_adv * pdu_prev,struct pdu_adv * pdu,struct pdu_adv_aux_ptr * aux_ptr,uint8_t phy_s,uint8_t phy_flags,uint32_t mafs_us)2814 void ull_adv_aux_chain_pdu_duplicate(struct pdu_adv *pdu_prev,
2815 struct pdu_adv *pdu,
2816 struct pdu_adv_aux_ptr *aux_ptr,
2817 uint8_t phy_s, uint8_t phy_flags,
2818 uint32_t mafs_us)
2819 {
2820 /* Duplicate any chain PDUs */
2821 while (aux_ptr) {
2822 struct pdu_adv_com_ext_adv *com_hdr_chain;
2823 struct pdu_adv_com_ext_adv *com_hdr;
2824 struct pdu_adv_ext_hdr *hdr_chain;
2825 struct pdu_adv_adi *adi_parent;
2826 struct pdu_adv *pdu_chain_prev;
2827 struct pdu_adv_ext_hdr *hdr;
2828 struct pdu_adv *pdu_chain;
2829 uint8_t *dptr_chain;
2830 uint32_t offs_us;
2831 uint8_t *dptr;
2832
2833 /* Get the next chain PDU */
2834 pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu_prev);
2835 if (!pdu_chain_prev) {
2836 break;
2837 }
2838
2839 /* Fill the aux offset in the (first iteration, it is the
2840 * primary channel ADV_EXT_IND PDU, rest it is AUX_ADV_IND and
2841 * AUX_CHAIN_IND) parent PDU
2842 */
2843 offs_us = PDU_AC_US(pdu->len, phy_s, phy_flags) + mafs_us;
2844 ull_adv_aux_ptr_fill(aux_ptr, offs_us, phy_s);
2845
2846 /* Get reference to flags in superior PDU */
2847 com_hdr = &pdu->adv_ext_ind;
2848 hdr = (void *)&com_hdr->ext_hdr_adv_data[0];
2849 dptr = (void *)hdr;
2850
2851 /* Get the next new chain PDU */
2852 pdu_chain = lll_adv_pdu_linked_next_get(pdu);
2853 if (!pdu_chain) {
2854 /* Get a new chain PDU */
2855 pdu_chain = lll_adv_pdu_alloc_pdu_adv();
2856 LL_ASSERT(pdu_chain);
2857
2858 /* Copy previous chain PDU into new chain PDU */
2859 (void)memcpy(pdu_chain, pdu_chain_prev,
2860 offsetof(struct pdu_adv, payload) +
2861 pdu_chain_prev->len);
2862
2863 /* Link the chain PDU to parent PDU */
2864 lll_adv_pdu_linked_append(pdu_chain, pdu);
2865 }
2866
2867 /* Get reference to common header format */
2868 com_hdr_chain = &pdu_chain_prev->adv_ext_ind;
2869 hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0];
2870 dptr_chain = (void *)hdr_chain;
2871
2872 /* Check for no Flags */
2873 if (!com_hdr_chain->ext_hdr_len) {
2874 break;
2875 }
2876
2877 /* Proceed to next byte if any flags present */
2878 if (*dptr) {
2879 dptr++;
2880 }
2881 if (*dptr_chain) {
2882 dptr_chain++;
2883 }
2884
2885 /* AdvA flag */
2886 if (hdr->adv_addr) {
2887 dptr += BDADDR_SIZE;
2888 }
2889 if (hdr_chain->adv_addr) {
2890 dptr_chain += BDADDR_SIZE;
2891 }
2892
2893 /* TgtA flag */
2894 if (hdr->tgt_addr) {
2895 dptr += BDADDR_SIZE;
2896 }
2897 if (hdr_chain->tgt_addr) {
2898 dptr_chain += BDADDR_SIZE;
2899 }
2900
2901 /* CTE Info */
2902 if (hdr->cte_info) {
2903 dptr += sizeof(struct pdu_cte_info);
2904 }
2905 if (hdr_chain->cte_info) {
2906 dptr_chain += sizeof(struct pdu_cte_info);
2907 }
2908
2909 /* ADI */
2910 if (hdr->adi) {
2911 adi_parent = (void *)dptr;
2912
2913 dptr += sizeof(struct pdu_adv_adi);
2914 } else {
2915 adi_parent = NULL;
2916 }
2917 if (hdr_chain->adi) {
2918 struct pdu_adv_adi *adi;
2919
2920 /* update ADI to superior PDU ADI */
2921 adi = (void *)dptr_chain;
2922 if (adi_parent) {
2923 adi->did_sid_packed[0] = adi_parent->did_sid_packed[0];
2924 adi->did_sid_packed[1] = adi_parent->did_sid_packed[1];
2925 }
2926
2927 dptr_chain += sizeof(struct pdu_adv_adi);
2928 }
2929
2930 /* No aux ptr, no further chain PDUs */
2931 if (!hdr_chain->aux_ptr) {
2932 break;
2933 }
2934
2935 /* Remember the aux ptr to be populated */
2936 aux_ptr = (void *)dptr_chain;
2937
2938 /* Progress to next chain PDU */
2939 pdu_prev = pdu_chain_prev;
2940 pdu = pdu_chain;
2941 }
2942 }
2943 #endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */
2944
init_reset(void)2945 static int init_reset(void)
2946 {
2947 /* Initialize adv aux pool. */
2948 mem_init(ll_adv_aux_pool, sizeof(struct ll_adv_aux_set),
2949 sizeof(ll_adv_aux_pool) / sizeof(struct ll_adv_aux_set),
2950 &adv_aux_free);
2951
2952 return 0;
2953 }
2954
aux_acquire(void)2955 static inline struct ll_adv_aux_set *aux_acquire(void)
2956 {
2957 return mem_acquire(&adv_aux_free);
2958 }
2959
aux_release(struct ll_adv_aux_set * aux)2960 static inline void aux_release(struct ll_adv_aux_set *aux)
2961 {
2962 mem_release(aux, &adv_aux_free);
2963 }
2964
aux_time_get(const struct ll_adv_aux_set * aux,const struct pdu_adv * pdu,uint8_t pdu_len,uint8_t pdu_scan_len)2965 static uint32_t aux_time_get(const struct ll_adv_aux_set *aux,
2966 const struct pdu_adv *pdu,
2967 uint8_t pdu_len, uint8_t pdu_scan_len)
2968 {
2969 const struct lll_adv_aux *lll_aux;
2970 const struct lll_adv *lll;
2971 uint32_t time_us;
2972
2973 lll_aux = &aux->lll;
2974 lll = lll_aux->adv;
2975
2976 if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX) &&
2977 (lll->phy_s == PHY_CODED)) {
2978 pdu_len = PDU_AC_EXT_PAYLOAD_OVERHEAD;
2979 pdu_scan_len = PDU_AC_EXT_PAYLOAD_OVERHEAD;
2980 }
2981
2982 /* NOTE: 16-bit values are sufficient for minimum radio event time
2983 * reservation, 32-bit are used here so that reservations for
2984 * whole back-to-back chaining of PDUs can be accomodated where
2985 * the required microseconds could overflow 16-bits, example,
2986 * back-to-back chained Coded PHY PDUs.
2987 */
2988 time_us = PDU_AC_US(pdu_len, lll->phy_s, lll->phy_flags) +
2989 EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
2990
2991 if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_CONN) ==
2992 BT_HCI_LE_ADV_PROP_CONN) {
2993 const uint16_t conn_req_us =
2994 PDU_AC_MAX_US((INITA_SIZE + ADVA_SIZE + LLDATA_SIZE),
2995 lll->phy_s);
2996 const uint16_t conn_rsp_us =
2997 PDU_AC_US((PDU_AC_EXT_HEADER_SIZE_MIN + ADVA_SIZE +
2998 TARGETA_SIZE), lll->phy_s, lll->phy_flags);
2999
3000 time_us += EVENT_IFS_MAX_US * 2 + conn_req_us + conn_rsp_us;
3001 } else if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) ==
3002 BT_HCI_LE_ADV_PROP_SCAN) {
3003 const uint16_t scan_req_us =
3004 PDU_AC_MAX_US((SCANA_SIZE + ADVA_SIZE), lll->phy_s);
3005 const uint16_t scan_rsp_us =
3006 PDU_AC_US(pdu_scan_len, lll->phy_s, lll->phy_flags);
3007
3008 time_us += EVENT_IFS_MAX_US * 2 + scan_req_us + scan_rsp_us;
3009
3010 /* FIXME: Calculate additional time reservations for scan
3011 * response chain PDUs, if any.
3012 */
3013 } else {
3014 /* Non-connectable Non-Scannable */
3015
3016 /* FIXME: Calculate additional time reservations for chain PDUs,
3017 * if any.
3018 */
3019 }
3020
3021 return time_us;
3022 }
3023
aux_time_min_get(const struct ll_adv_aux_set * aux)3024 static uint32_t aux_time_min_get(const struct ll_adv_aux_set *aux)
3025 {
3026 const struct lll_adv_aux *lll_aux;
3027 const struct pdu_adv *pdu_scan;
3028 const struct lll_adv *lll;
3029 const struct pdu_adv *pdu;
3030 uint8_t pdu_scan_len;
3031 uint8_t pdu_len;
3032
3033 lll_aux = &aux->lll;
3034 lll = lll_aux->adv;
3035 pdu = lll_adv_aux_data_peek(lll_aux);
3036 pdu_scan = lll_adv_scan_rsp_peek(lll);
3037
3038 /* Calculate the PDU Tx Time and hence the radio event length,
3039 * Always use maximum length for common extended header format so that
3040 * ACAD could be update when periodic advertising is active and the
3041 * time reservation need not be updated everytime avoiding overlapping
3042 * with other active states/roles.
3043 */
3044 pdu_len = pdu->len - pdu->adv_ext_ind.ext_hdr_len -
3045 PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
3046 pdu_scan_len = pdu_scan->len - pdu_scan->adv_ext_ind.ext_hdr_len -
3047 PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
3048
3049 return aux_time_get(aux, pdu, pdu_len, pdu_scan_len);
3050 }
3051
aux_time_update(struct ll_adv_aux_set * aux,struct pdu_adv * pdu,struct pdu_adv * pdu_scan)3052 static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu,
3053 struct pdu_adv *pdu_scan)
3054 {
3055 uint32_t time_ticks;
3056 uint32_t time_us;
3057
3058 time_us = aux_time_min_get(aux);
3059 time_ticks = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
3060
3061 #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
3062 uint32_t volatile ret_cb;
3063 uint32_t ticks_minus;
3064 uint32_t ticks_plus;
3065 uint32_t ret;
3066
3067 if (aux->ull.ticks_slot > time_ticks) {
3068 ticks_minus = aux->ull.ticks_slot - time_ticks;
3069 ticks_plus = 0U;
3070 } else if (aux->ull.ticks_slot < time_ticks) {
3071 ticks_minus = 0U;
3072 ticks_plus = time_ticks - aux->ull.ticks_slot;
3073 } else {
3074 return BT_HCI_ERR_SUCCESS;
3075 }
3076
3077 ret_cb = TICKER_STATUS_BUSY;
3078 ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
3079 TICKER_USER_ID_THREAD,
3080 (TICKER_ID_ADV_AUX_BASE +
3081 ull_adv_aux_handle_get(aux)),
3082 0, 0, ticks_plus, ticks_minus, 0, 0,
3083 ull_ticker_status_give, (void *)&ret_cb);
3084 ret = ull_ticker_status_take(ret, &ret_cb);
3085 if (ret != TICKER_STATUS_SUCCESS) {
3086 return BT_HCI_ERR_CMD_DISALLOWED;
3087 }
3088 #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
3089
3090 aux->ull.ticks_slot = time_ticks;
3091
3092 return BT_HCI_ERR_SUCCESS;
3093 }
3094
3095 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_aux_lll_auxptr_fill(struct pdu_adv * pdu,struct lll_adv * adv)3096 void ull_adv_aux_lll_auxptr_fill(struct pdu_adv *pdu, struct lll_adv *adv)
3097 {
3098 struct lll_adv_aux *lll_aux = adv->aux;
3099 struct pdu_adv_aux_ptr *aux_ptr;
3100 struct ll_adv_aux_set *aux;
3101 uint8_t data_chan_count;
3102 uint8_t *data_chan_map;
3103 uint16_t chan_counter;
3104 uint32_t offset_us;
3105 uint16_t pdu_us;
3106
3107 aux = HDR_LLL2ULL(lll_aux);
3108
3109 chan_counter = lll_aux->data_chan_counter;
3110
3111 /* The offset has to be at least T_MAFS microseconds from the end of packet
3112 * In addition, the offset recorded in the aux ptr has the same requirement and this
3113 * offset is in steps of 30 microseconds; So use the quantized value in check
3114 */
3115 pdu_us = PDU_AC_US(pdu->len, adv->phy_p, adv->phy_flags);
3116 offset_us = HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset) +
3117 lll_aux->us_pri_pdu_offset;
3118 if ((offset_us/OFFS_UNIT_30_US)*OFFS_UNIT_30_US < EVENT_MAFS_US + pdu_us) {
3119 uint32_t interval_us;
3120
3121 /* Offset too small, point to next aux packet instead */
3122 interval_us = aux->interval * PERIODIC_INT_UNIT_US;
3123 offset_us = offset_us + interval_us;
3124 lll_aux->ticks_pri_pdu_offset = HAL_TICKER_US_TO_TICKS(offset_us);
3125 lll_aux->us_pri_pdu_offset = offset_us -
3126 HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset);
3127 chan_counter++;
3128 }
3129
3130 /* Fill the aux offset */
3131 aux_ptr = ull_adv_aux_lll_offset_fill(pdu, lll_aux->ticks_pri_pdu_offset,
3132 lll_aux->us_pri_pdu_offset, 0U);
3133
3134
3135 /* Calculate and fill the radio channel to use */
3136 data_chan_map = aux->chm[aux->chm_first].data_chan_map;
3137 data_chan_count = aux->chm[aux->chm_first].data_chan_count;
3138 aux_ptr->chan_idx = lll_chan_sel_2(chan_counter,
3139 aux->data_chan_id,
3140 data_chan_map, data_chan_count);
3141 }
3142
3143 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
mfy_aux_offset_get(void * param)3144 static void mfy_aux_offset_get(void *param)
3145 {
3146 struct pdu_adv_aux_ptr *aux_ptr;
3147 struct lll_adv_aux *lll_aux;
3148 struct ll_adv_aux_set *aux;
3149 uint32_t ticks_to_expire;
3150 uint8_t data_chan_count;
3151 uint8_t *data_chan_map;
3152 uint32_t ticks_current;
3153 struct ll_adv_set *adv;
3154 struct pdu_adv *pdu;
3155 uint32_t remainder;
3156 uint8_t ticker_id;
3157 uint8_t retry;
3158 uint8_t id;
3159
3160 adv = param;
3161 lll_aux = adv->lll.aux;
3162 aux = HDR_LLL2ULL(lll_aux);
3163 ticker_id = TICKER_ID_ADV_AUX_BASE + ull_adv_aux_handle_get(aux);
3164
3165 id = TICKER_NULL;
3166 ticks_to_expire = 0U;
3167 ticks_current = 0U;
3168 retry = 4U;
3169 do {
3170 uint32_t volatile ret_cb;
3171 uint32_t ticks_previous;
3172 uint32_t ret;
3173 bool success;
3174
3175 ticks_previous = ticks_current;
3176
3177 ret_cb = TICKER_STATUS_BUSY;
3178 ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
3179 TICKER_USER_ID_ULL_LOW,
3180 &id, &ticks_current,
3181 &ticks_to_expire, &remainder,
3182 NULL, NULL, NULL,
3183 ticker_op_cb, (void *)&ret_cb);
3184 if (ret == TICKER_STATUS_BUSY) {
3185 while (ret_cb == TICKER_STATUS_BUSY) {
3186 ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
3187 TICKER_USER_ID_ULL_LOW);
3188 }
3189 }
3190
3191 success = (ret_cb == TICKER_STATUS_SUCCESS);
3192 LL_ASSERT(success);
3193
3194 LL_ASSERT((ticks_current == ticks_previous) || retry--);
3195
3196 LL_ASSERT(id != TICKER_NULL);
3197 } while (id != ticker_id);
3198
3199 /* Adjust ticks to expire based on remainder value */
3200 hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
3201
3202 /* Store the ticks offset for population in other advertising primary
3203 * channel PDUs.
3204 */
3205 lll_aux->ticks_pri_pdu_offset = ticks_to_expire;
3206
3207 /* NOTE: as first primary channel PDU does not use remainder, the packet
3208 * timer is started one tick in advance to start the radio with
3209 * microsecond precision, hence compensate for the higher start_us value
3210 * captured at radio start of the first primary channel PDU.
3211 */
3212 lll_aux->ticks_pri_pdu_offset += 1U;
3213
3214 /* Store the microsecond remainder offset for population in other
3215 * advertising primary channel PDUs.
3216 */
3217 lll_aux->us_pri_pdu_offset = remainder;
3218
3219 /* Fill the aux offset in the first Primary channel PDU */
3220 /* FIXME: we are in ULL_LOW context, fill offset in LLL context? */
3221 pdu = lll_adv_data_latest_peek(&adv->lll);
3222 aux_ptr = ull_adv_aux_lll_offset_fill(pdu, ticks_to_expire, remainder,
3223 0U);
3224
3225 /* Process channel map update, if any */
3226 if (aux->chm_first != aux->chm_last) {
3227 /* Use channelMapNew */
3228 aux->chm_first = aux->chm_last;
3229 }
3230
3231 /* Calculate the radio channel to use */
3232 data_chan_map = aux->chm[aux->chm_first].data_chan_map;
3233 data_chan_count = aux->chm[aux->chm_first].data_chan_count;
3234 aux_ptr->chan_idx = lll_chan_sel_2(lll_aux->data_chan_counter,
3235 aux->data_chan_id,
3236 data_chan_map, data_chan_count);
3237 }
3238
ticker_op_cb(uint32_t status,void * param)3239 static void ticker_op_cb(uint32_t status, void *param)
3240 {
3241 *((uint32_t volatile *)param) = status;
3242 }
3243 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3244
ticker_cb(uint32_t ticks_at_expire,uint32_t ticks_drift,uint32_t remainder,uint16_t lazy,uint8_t force,void * param)3245 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
3246 uint32_t remainder, uint16_t lazy, uint8_t force,
3247 void *param)
3248 {
3249 static memq_link_t link;
3250 static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_aux_prepare};
3251 static struct lll_prepare_param p;
3252 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3253 struct ticker_ext_context *context = param;
3254 struct ll_adv_aux_set *aux = context->context;
3255 #else /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3256 struct ll_adv_aux_set *aux = param;
3257 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3258 struct lll_adv_aux *lll;
3259 uint32_t ret;
3260 uint8_t ref;
3261
3262 DEBUG_RADIO_PREPARE_A(1);
3263
3264 lll = &aux->lll;
3265
3266 /* Increment prepare reference count */
3267 ref = ull_ref_inc(&aux->ull);
3268 LL_ASSERT(ref);
3269
3270 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3271 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
3272 struct ll_adv_set *adv;
3273
3274 adv = HDR_LLL2ULL(lll->adv);
3275 if (adv->lll.sync) {
3276 struct lll_adv_sync *lll_sync = adv->lll.sync;
3277 struct ll_adv_sync_set *sync;
3278
3279 sync = HDR_LLL2ULL(adv->lll.sync);
3280 if (sync->is_started) {
3281 uint32_t ticks_to_expire;
3282 uint32_t sync_remainder_us;
3283
3284 LL_ASSERT(context->other_expire_info);
3285
3286 /* Reduce a tick for negative remainder and return positive remainder
3287 * value.
3288 */
3289 ticks_to_expire = context->other_expire_info->ticks_to_expire;
3290 sync_remainder_us = context->other_expire_info->remainder;
3291 hal_ticker_remove_jitter(&ticks_to_expire, &sync_remainder_us);
3292
3293 /* Add a tick for negative remainder and return positive remainder
3294 * value.
3295 */
3296 hal_ticker_add_jitter(&ticks_to_expire, &remainder);
3297
3298 /* Store the offset in us */
3299 lll_sync->us_adv_sync_pdu_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire) +
3300 sync_remainder_us - remainder;
3301
3302 /* store the lazy value */
3303 lll_sync->sync_lazy = context->other_expire_info->lazy;
3304 }
3305 }
3306 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
3307
3308 /* Process channel map update, if any */
3309 if (aux->chm_first != aux->chm_last) {
3310 /* Use channelMapNew */
3311 aux->chm_first = aux->chm_last;
3312 }
3313 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3314
3315 /* Append timing parameters */
3316 p.ticks_at_expire = ticks_at_expire;
3317 p.remainder = remainder;
3318 p.lazy = lazy;
3319 p.force = force;
3320 p.param = lll;
3321 mfy.param = &p;
3322
3323 /* Kick LLL prepare */
3324 ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
3325 TICKER_USER_ID_LLL, 0, &mfy);
3326 LL_ASSERT(!ret);
3327
3328 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3329 struct ll_adv_set *adv;
3330
3331 adv = HDR_LLL2ULL(lll->adv);
3332 if (adv->lll.sync) {
3333 struct ll_adv_sync_set *sync;
3334
3335 sync = HDR_LLL2ULL(adv->lll.sync);
3336 if (sync->is_started) {
3337 sync->aux_remainder = remainder;
3338 ull_adv_sync_offset_get(adv);
3339 }
3340 }
3341 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC && !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3342
3343 DEBUG_RADIO_PREPARE_A(1);
3344 }
3345
3346 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ticker_update_op_cb(uint32_t status,void * param)3347 static void ticker_update_op_cb(uint32_t status, void *param)
3348 {
3349 LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
3350 param == ull_disable_mark_get());
3351 }
3352 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3353
3354 #else /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
3355
init_reset(void)3356 static int init_reset(void)
3357 {
3358 return 0;
3359 }
3360 #endif /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
3361