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 * in fact 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 * in fact 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 * in fact 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 * in fact 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 * in fact 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 * in fact 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 #if defined(CONFIG_BT_CTLR_ADV_ISO)
1348 if (lll->sync->iso) {
1349 return BT_HCI_ERR_CMD_DISALLOWED;
1350 }
1351 #endif /* CONFIG_BT_CTLR_ADV_ISO */
1352
1353 sync = HDR_LLL2ULL(lll->sync);
1354
1355 if (sync->is_enabled) {
1356 return BT_HCI_ERR_CMD_DISALLOWED;
1357 }
1358
1359 lll->sync = NULL;
1360
1361 ull_adv_sync_release(sync);
1362 }
1363 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1364
1365 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
1366 if (adv->df_cfg) {
1367 if (adv->df_cfg->is_enabled) {
1368 return BT_HCI_ERR_CMD_DISALLOWED;
1369 }
1370
1371 ull_df_adv_cfg_release(adv->df_cfg);
1372 adv->df_cfg = NULL;
1373 }
1374 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
1375
1376 /* Release auxiliary channel set */
1377 if (lll->aux) {
1378 struct ll_adv_aux_set *aux;
1379
1380 aux = HDR_LLL2ULL(lll->aux);
1381 lll->aux = NULL;
1382
1383 ull_adv_aux_release(aux);
1384 }
1385
1386 /* Dequeue and release, advertising and scan response data, to keep
1387 * one initial primary channel PDU each for the advertising set.
1388 * This is done to prevent common extended payload format contents from
1389 * being overwritten and corrupted due to same primary PDU buffer being
1390 * used to remove AdvA and other fields are moved over in its place when
1391 * auxiliary PDU is allocated to new advertising set.
1392 */
1393 (void)lll_adv_data_dequeue(&adv->lll.adv_data);
1394 (void)lll_adv_data_dequeue(&adv->lll.scan_rsp);
1395
1396 /* Make the advertising set available for new advertisements */
1397 adv->is_created = 0;
1398
1399 return BT_HCI_ERR_SUCCESS;
1400 }
1401
ll_adv_aux_set_clear(void)1402 uint8_t ll_adv_aux_set_clear(void)
1403 {
1404 uint8_t retval = BT_HCI_ERR_SUCCESS;
1405 uint8_t handle;
1406 uint8_t err;
1407
1408 for (handle = 0; handle < BT_CTLR_ADV_SET; ++handle) {
1409 err = ll_adv_aux_set_remove(handle);
1410 if (err == BT_HCI_ERR_CMD_DISALLOWED) {
1411 retval = err;
1412 }
1413 }
1414
1415 return retval;
1416 }
1417
ull_adv_aux_init(void)1418 int ull_adv_aux_init(void)
1419 {
1420 int err;
1421
1422 err = lll_rand_get(&did_unique, sizeof(did_unique));
1423 if (err) {
1424 return err;
1425 }
1426
1427 err = init_reset();
1428 if (err) {
1429 return err;
1430 }
1431
1432 return 0;
1433 }
1434
ull_adv_aux_reset_finalize(void)1435 int ull_adv_aux_reset_finalize(void)
1436 {
1437 int err;
1438
1439 err = init_reset();
1440 if (err) {
1441 return err;
1442 }
1443
1444 return 0;
1445 }
1446
ull_adv_aux_chm_update(void)1447 uint8_t ull_adv_aux_chm_update(void)
1448 {
1449 /* For each created extended advertising set */
1450 for (uint8_t handle = 0; handle < BT_CTLR_ADV_SET; ++handle) {
1451 struct ll_adv_aux_set *aux;
1452 struct ll_adv_set *adv;
1453 uint8_t chm_last;
1454
1455 adv = ull_adv_is_created_get(handle);
1456 if (!adv || !adv->lll.aux) {
1457 continue;
1458 }
1459
1460 aux = HDR_LLL2ULL(adv->lll.aux);
1461 if (aux->chm_last != aux->chm_first) {
1462 /* TODO: Handle previous Channel Map Update being in
1463 * progress
1464 */
1465 continue;
1466 }
1467
1468 /* Append the channelMapNew that will be picked up by ULL */
1469 chm_last = aux->chm_last + 1;
1470 if (chm_last == DOUBLE_BUFFER_SIZE) {
1471 chm_last = 0U;
1472 }
1473 aux->chm[chm_last].data_chan_count =
1474 ull_chan_map_get(aux->chm[chm_last].data_chan_map);
1475 aux->chm_last = chm_last;
1476
1477 if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO) && !aux->is_started) {
1478 /* Ticker not started yet, apply new channel map now
1479 * Note that it should be safe to modify chm_first here
1480 * since advertising is not active
1481 */
1482 aux->chm_first = aux->chm_last;
1483 }
1484 }
1485
1486 /* TODO: Should failure due to Channel Map Update being already in
1487 * progress be returned to caller?
1488 */
1489 return 0;
1490 }
1491
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)1492 uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
1493 uint16_t sec_hdr_add_fields,
1494 uint16_t sec_hdr_rem_fields,
1495 void *hdr_data,
1496 uint8_t *pri_idx, uint8_t *sec_idx)
1497 {
1498 struct pdu_adv_com_ext_adv *pri_com_hdr, *pri_com_hdr_prev;
1499 struct pdu_adv_com_ext_adv *sec_com_hdr, *sec_com_hdr_prev;
1500 struct pdu_adv_ext_hdr *hdr, pri_hdr, pri_hdr_prev;
1501 struct pdu_adv_ext_hdr sec_hdr, sec_hdr_prev;
1502 struct pdu_adv *pri_pdu, *pri_pdu_prev;
1503 struct pdu_adv *sec_pdu_prev, *sec_pdu;
1504 struct pdu_adv_adi *pri_adi, *sec_adi;
1505 uint8_t *pri_dptr, *pri_dptr_prev;
1506 uint8_t *sec_dptr, *sec_dptr_prev;
1507 struct pdu_adv_aux_ptr *aux_ptr;
1508 uint8_t pri_len, sec_len_prev;
1509 struct lll_adv_aux *lll_aux;
1510 uint8_t *ad_fragment = NULL;
1511 uint8_t ad_fragment_len = 0;
1512 struct ll_adv_aux_set *aux;
1513 struct pdu_adv_adi *adi;
1514 struct lll_adv *lll;
1515 uint8_t is_aux_new;
1516 uint8_t *ad_data;
1517 uint16_t sec_len;
1518 uint8_t ad_len;
1519 uint16_t did;
1520
1521 lll = &adv->lll;
1522
1523 /* Can't have both flags set here since both use 'hdr_data' param */
1524 LL_ASSERT(!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) ||
1525 !(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA));
1526
1527 /* Get reference to previous primary PDU data */
1528 pri_pdu_prev = lll_adv_data_peek(lll);
1529 if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
1530 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
1531 /* pick the data length */
1532 ad_len = *((uint8_t *)hdr_data);
1533 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
1534
1535 /* pick the reference to data */
1536 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
1537
1538 return ull_adv_data_set(adv, ad_len, ad_data);
1539 }
1540
1541 return BT_HCI_ERR_CMD_DISALLOWED;
1542 }
1543
1544 pri_com_hdr_prev = (void *)&pri_pdu_prev->adv_ext_ind;
1545 hdr = (void *)pri_com_hdr_prev->ext_hdr_adv_data;
1546 if (pri_com_hdr_prev->ext_hdr_len) {
1547 pri_hdr_prev = *hdr;
1548 } else {
1549 *(uint8_t *)&pri_hdr_prev = 0U;
1550 }
1551 pri_dptr_prev = hdr->data;
1552
1553 /* Advertising data are not supported by scannable instances */
1554 if ((sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) &&
1555 (pri_com_hdr_prev->adv_mode & BT_HCI_LE_ADV_PROP_SCAN)) {
1556 return BT_HCI_ERR_INVALID_PARAM;
1557 }
1558
1559 /* Get reference to new primary PDU data buffer */
1560 pri_pdu = lll_adv_data_alloc(lll, pri_idx);
1561 pri_pdu->type = pri_pdu_prev->type;
1562 pri_pdu->rfu = 0U;
1563 pri_pdu->chan_sel = 0U;
1564 pri_com_hdr = (void *)&pri_pdu->adv_ext_ind;
1565 pri_com_hdr->adv_mode = pri_com_hdr_prev->adv_mode;
1566 hdr = (void *)pri_com_hdr->ext_hdr_adv_data;
1567 pri_dptr = hdr->data;
1568 *(uint8_t *)&pri_hdr = 0U;
1569
1570 /* Get the reference to aux instance */
1571 lll_aux = lll->aux;
1572 if (!lll_aux) {
1573 aux = ull_adv_aux_acquire(lll);
1574 if (!aux) {
1575 LL_ASSERT(pri_pdu != pri_pdu_prev);
1576
1577 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1578 }
1579
1580 lll_aux = &aux->lll;
1581
1582 if (IS_ENABLED(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)) {
1583 ull_adv_aux_created(adv);
1584 }
1585
1586 is_aux_new = 1U;
1587 } else {
1588 aux = HDR_LLL2ULL(lll_aux);
1589 is_aux_new = 0U;
1590 }
1591
1592 /* Get reference to previous secondary PDU data */
1593 sec_pdu_prev = lll_adv_aux_data_peek(lll_aux);
1594 sec_com_hdr_prev = (void *)&sec_pdu_prev->adv_ext_ind;
1595 hdr = (void *)sec_com_hdr_prev->ext_hdr_adv_data;
1596 if (!is_aux_new) {
1597 sec_hdr_prev = *hdr;
1598 } else {
1599 /* Initialize only those fields used to copy into new PDU
1600 * buffer.
1601 */
1602 sec_pdu_prev->tx_addr = 0U;
1603 sec_pdu_prev->rx_addr = 0U;
1604 sec_pdu_prev->len = PDU_AC_EXT_HEADER_SIZE_MIN;
1605 *(uint8_t *)hdr = 0U;
1606 *(uint8_t *)&sec_hdr_prev = 0U;
1607 }
1608 sec_dptr_prev = hdr->data;
1609
1610 /* Get reference to new secondary PDU data buffer */
1611 sec_pdu = lll_adv_aux_data_alloc(lll_aux, sec_idx);
1612 sec_pdu->type = pri_pdu->type;
1613 sec_pdu->rfu = 0U;
1614 sec_pdu->chan_sel = 0U;
1615
1616 sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
1617 sec_pdu->rx_addr = sec_pdu_prev->rx_addr;
1618
1619 sec_com_hdr = (void *)&sec_pdu->adv_ext_ind;
1620 sec_com_hdr->adv_mode = pri_com_hdr->adv_mode;
1621 hdr = (void *)sec_com_hdr->ext_hdr_adv_data;
1622 sec_dptr = hdr->data;
1623 *(uint8_t *)&sec_hdr = 0U;
1624
1625 /* AdvA flag */
1626 /* NOTE: as we will use auxiliary packet, we remove AdvA in primary
1627 * channel, i.e. do nothing to not add AdvA in the primary PDU.
1628 * AdvA can be either set explicitly (i.e. needs own_addr_type to be
1629 * set), can be copied from primary PDU (i.e. adding AD to existing set)
1630 * or can be copied from previous secondary PDU.
1631 */
1632 sec_hdr.adv_addr = 1;
1633 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
1634 uint8_t own_addr_type = *(uint8_t *)hdr_data;
1635
1636 /* Move to next hdr_data */
1637 hdr_data = (uint8_t *)hdr_data + sizeof(own_addr_type);
1638
1639 sec_pdu->tx_addr = own_addr_type & 0x1;
1640 } else if (pri_hdr_prev.adv_addr) {
1641 sec_pdu->tx_addr = pri_pdu_prev->tx_addr;
1642 } else if (sec_hdr_prev.adv_addr) {
1643 sec_pdu->tx_addr = sec_pdu_prev->tx_addr;
1644 } else {
1645 /* We do not have valid address info, this should not happen */
1646 return BT_HCI_ERR_UNSPECIFIED;
1647 }
1648 pri_pdu->tx_addr = 0U;
1649
1650 if (pri_hdr_prev.adv_addr) {
1651 pri_dptr_prev += BDADDR_SIZE;
1652 }
1653 if (sec_hdr_prev.adv_addr) {
1654 sec_dptr_prev += BDADDR_SIZE;
1655 }
1656 sec_dptr += BDADDR_SIZE;
1657
1658 /* No TargetA in primary and secondary channel for undirected.
1659 * Move from primary to secondary PDU, if present in primary PDU.
1660 */
1661 if (pri_hdr_prev.tgt_addr) {
1662 sec_hdr.tgt_addr = 1U;
1663 sec_pdu->rx_addr = pri_pdu_prev->rx_addr;
1664 sec_dptr += BDADDR_SIZE;
1665
1666 /* Retain the target address if present in the previous PDU */
1667 } else if (!(sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) &&
1668 sec_hdr_prev.tgt_addr) {
1669 sec_hdr.tgt_addr = 1U;
1670 sec_pdu->rx_addr = sec_pdu_prev->rx_addr;
1671 sec_dptr += BDADDR_SIZE;
1672 }
1673 pri_pdu->rx_addr = 0U;
1674
1675 if (pri_hdr_prev.tgt_addr) {
1676 pri_dptr_prev += BDADDR_SIZE;
1677 }
1678
1679 if (sec_hdr_prev.tgt_addr) {
1680 sec_dptr_prev += BDADDR_SIZE;
1681 }
1682
1683 /* No CTEInfo flag in primary and secondary channel PDU */
1684
1685 /* ADI flag */
1686 if (pri_hdr_prev.adi) {
1687 pri_dptr_prev += sizeof(struct pdu_adv_adi);
1688 }
1689 pri_hdr.adi = 1;
1690 pri_dptr += sizeof(struct pdu_adv_adi);
1691 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
1692 sec_hdr.adi = 1U;
1693 /* return the size of ADI structure */
1694 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_adi);
1695 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1696 /* pick the reference to ADI param */
1697 (void)memcpy(&adi, hdr_data, sizeof(struct pdu_adv_adi *));
1698 /* return the pointer to ADI struct inside the PDU */
1699 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1700 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1701 sec_dptr += sizeof(struct pdu_adv_adi);
1702 } else {
1703 sec_hdr.adi = 1;
1704 adi = NULL;
1705 sec_dptr += sizeof(struct pdu_adv_adi);
1706 }
1707 if (sec_hdr_prev.adi) {
1708 sec_dptr_prev += sizeof(struct pdu_adv_adi);
1709 }
1710
1711 /* AuxPtr flag */
1712 if (pri_hdr_prev.aux_ptr) {
1713 pri_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
1714 }
1715 pri_hdr.aux_ptr = 1;
1716 pri_dptr += sizeof(struct pdu_adv_aux_ptr);
1717
1718 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
1719 sec_hdr.aux_ptr = 1;
1720 aux_ptr = NULL;
1721
1722 /* return the size of aux pointer structure */
1723 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_aux_ptr);
1724 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1725
1726 /* return the pointer to aux pointer struct inside the PDU
1727 * buffer
1728 */
1729 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1730 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1731 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
1732 sec_hdr_prev.aux_ptr) {
1733 sec_hdr.aux_ptr = 1;
1734 aux_ptr = (void *)sec_dptr_prev;
1735 } else {
1736 aux_ptr = NULL;
1737 }
1738 if (sec_hdr_prev.aux_ptr) {
1739 sec_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
1740 }
1741 if (sec_hdr.aux_ptr) {
1742 sec_dptr += sizeof(struct pdu_adv_aux_ptr);
1743 }
1744
1745 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
1746 struct pdu_adv_sync_info *sync_info;
1747
1748 /* No SyncInfo flag in primary channel PDU */
1749 /* Add/Remove SyncInfo flag in secondary channel PDU */
1750 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) {
1751 sec_hdr.sync_info = 1;
1752 sync_info = NULL;
1753
1754 /* return the size of sync info structure */
1755 *(uint8_t *)hdr_data = sizeof(*sync_info);
1756 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
1757
1758 /* return the pointer to sync info struct inside the PDU
1759 * buffer
1760 */
1761 (void)memcpy(hdr_data, &sec_dptr, sizeof(sec_dptr));
1762 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr);
1763 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) &&
1764 sec_hdr_prev.sync_info) {
1765 sec_hdr.sync_info = 1;
1766 sync_info = (void *)sec_dptr_prev;
1767 } else {
1768 sync_info = NULL;
1769 }
1770 if (sec_hdr_prev.sync_info) {
1771 sec_dptr_prev += sizeof(*sync_info);
1772 }
1773 if (sec_hdr.sync_info) {
1774 sec_dptr += sizeof(*sync_info);
1775 }
1776 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1777
1778 /* Tx Power flag */
1779 if (pri_hdr_prev.tx_pwr) {
1780 pri_dptr_prev++;
1781
1782 /* C1, Tx Power is optional on the LE 1M PHY, and
1783 * reserved for future use on the LE Coded PHY.
1784 */
1785 if (lll->phy_p != PHY_CODED) {
1786 pri_hdr.tx_pwr = 1;
1787 pri_dptr++;
1788 } else {
1789 sec_hdr.tx_pwr = 1;
1790 }
1791 }
1792 if (sec_hdr_prev.tx_pwr) {
1793 sec_dptr_prev++;
1794
1795 sec_hdr.tx_pwr = 1;
1796 }
1797 if (sec_hdr.tx_pwr) {
1798 sec_dptr++;
1799 }
1800
1801 /* No ACAD in primary channel PDU */
1802 /* TODO: ACAD in secondary channel PDU */
1803
1804 /* Calc primary PDU len */
1805 pri_len = ull_adv_aux_hdr_len_calc(pri_com_hdr, &pri_dptr);
1806
1807 /* Calc previous secondary PDU len */
1808 sec_len_prev = ull_adv_aux_hdr_len_calc(sec_com_hdr_prev,
1809 &sec_dptr_prev);
1810
1811 /* Did we parse beyond PDU length? */
1812 if (sec_len_prev > sec_pdu_prev->len) {
1813 /* we should not encounter invalid length */
1814 /* FIXME: release allocations */
1815 return BT_HCI_ERR_UNSPECIFIED;
1816 }
1817
1818 /* Calc current secondary PDU len */
1819 sec_len = ull_adv_aux_hdr_len_calc(sec_com_hdr, &sec_dptr);
1820
1821 /* AD Data, add or remove */
1822 if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
1823 uint8_t ad_len_prev;
1824
1825 /* remember the new ad data len */
1826 ad_len = *(uint8_t *)hdr_data;
1827
1828 /* return prev ad data length */
1829 ad_len_prev = sec_pdu_prev->len - sec_len_prev;
1830 *(uint8_t *)hdr_data = ad_len_prev;
1831 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
1832
1833 /* remember the reference to new ad data */
1834 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
1835
1836 /* return the reference to prev ad data */
1837 (void)memcpy(hdr_data, &sec_dptr_prev, sizeof(sec_dptr_prev));
1838 hdr_data = (uint8_t *)hdr_data + sizeof(sec_dptr_prev);
1839
1840 /* unchanged data */
1841 if (!ad_len && !ad_data) {
1842 ad_len = ad_len_prev;
1843 ad_data = sec_dptr_prev;
1844 }
1845 } else if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND) {
1846 /* Calc the previous AD data length in auxiliary PDU */
1847 ad_len = sec_pdu_prev->len - sec_len_prev;
1848 ad_data = sec_dptr_prev;
1849
1850 /* Append the new ad data fragment */
1851 ad_fragment_len = *(uint8_t *)hdr_data;
1852 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment_len);
1853 (void)memcpy(&ad_fragment, hdr_data, sizeof(ad_fragment));
1854 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment);
1855 } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)) {
1856 /* Calc the previous AD data length in auxiliary PDU */
1857 ad_len = sec_pdu_prev->len - sec_len_prev;
1858 ad_data = sec_dptr_prev;
1859 } else {
1860 ad_len = 0U;
1861 ad_data = NULL;
1862 }
1863
1864 /* Check Max Advertising Data Length */
1865 if (ad_len + ad_fragment_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
1866 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
1867 }
1868
1869 /* Check AdvData overflow */
1870 /* TODO: need aux_chain_ind support */
1871 if ((sec_len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) {
1872 /* return excess length */
1873 *(uint8_t *)hdr_data = sec_len + ad_len + ad_fragment_len -
1874 PDU_AC_PAYLOAD_SIZE_MAX;
1875
1876 if (pri_pdu == pri_pdu_prev) {
1877 lll_adv_data_enqueue(&adv->lll, *pri_idx);
1878 }
1879 if (sec_pdu == sec_pdu_prev) {
1880 lll_adv_aux_data_enqueue(adv->lll.aux, *sec_idx);
1881 }
1882
1883 /* Will use packet too long error to determine fragmenting
1884 * long data
1885 */
1886 return BT_HCI_ERR_PACKET_TOO_LONG;
1887 }
1888
1889 /* set the primary PDU len */
1890 ull_adv_aux_hdr_len_fill(pri_com_hdr, pri_len);
1891 pri_pdu->len = pri_len;
1892
1893 /* set the secondary PDU len */
1894 ull_adv_aux_hdr_len_fill(sec_com_hdr, sec_len);
1895 sec_pdu->len = sec_len + ad_len + ad_fragment_len;
1896
1897 /* Start filling pri and sec PDU payload based on flags from here
1898 * ==============================================================
1899 */
1900
1901 /* No AdvData in primary channel PDU */
1902 /* Fill AdvData in secondary PDU */
1903 (void)memmove(sec_dptr, ad_data, ad_len);
1904
1905 if (ad_fragment) {
1906 (void)memcpy(sec_dptr + ad_len, ad_fragment, ad_fragment_len);
1907 }
1908
1909 /* Early exit if no flags set */
1910 if (!sec_com_hdr->ext_hdr_len) {
1911 return 0;
1912 }
1913
1914 /* No ACAD in primary channel PDU */
1915 /* TODO: Fill ACAD in secondary channel PDU */
1916
1917 /* Tx Power */
1918 if (pri_hdr.tx_pwr) {
1919 *--pri_dptr = *--pri_dptr_prev;
1920 } else if (sec_hdr.tx_pwr) {
1921 *--sec_dptr = *--sec_dptr_prev;
1922 }
1923
1924 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
1925 /* No SyncInfo in primary channel PDU */
1926 /* Fill SyncInfo in secondary channel PDU */
1927 if (sec_hdr_prev.sync_info) {
1928 sec_dptr_prev -= sizeof(*sync_info);
1929 }
1930
1931 if (sec_hdr.sync_info) {
1932 sec_dptr -= sizeof(*sync_info);
1933 }
1934
1935 if (sync_info) {
1936 (void)memmove(sec_dptr, sync_info, sizeof(*sync_info));
1937 }
1938 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
1939
1940 /* AuxPtr */
1941 if (pri_hdr_prev.aux_ptr) {
1942 pri_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
1943 }
1944 pri_dptr -= sizeof(struct pdu_adv_aux_ptr);
1945 ull_adv_aux_ptr_fill((void *)pri_dptr, 0U, lll->phy_s);
1946
1947 if (sec_hdr_prev.aux_ptr) {
1948 sec_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
1949 }
1950 if (sec_hdr.aux_ptr) {
1951 sec_dptr -= sizeof(struct pdu_adv_aux_ptr);
1952 }
1953
1954 if (aux_ptr) {
1955 (void)memmove(sec_dptr, aux_ptr, sizeof(*aux_ptr));
1956 }
1957
1958 /* ADI */
1959 if (pri_hdr_prev.adi) {
1960 pri_dptr_prev -= sizeof(struct pdu_adv_adi);
1961 }
1962 if (sec_hdr_prev.adi) {
1963 sec_dptr_prev -= sizeof(struct pdu_adv_adi);
1964 }
1965
1966 pri_dptr -= sizeof(struct pdu_adv_adi);
1967 sec_dptr -= sizeof(struct pdu_adv_adi);
1968
1969 pri_adi = (void *)pri_dptr;
1970 sec_adi = (void *)sec_dptr;
1971
1972 if (!adi) {
1973 /* The DID for a specific SID shall be unique.
1974 */
1975 did = ull_adv_aux_did_next_unique_get(adv->sid);
1976 } else {
1977 did = PDU_ADV_ADI_DID_GET(adi);
1978 }
1979
1980 did = sys_cpu_to_le16(did);
1981 PDU_ADV_ADI_DID_SID_SET(pri_adi, did, adv->sid);
1982 PDU_ADV_ADI_DID_SID_SET(sec_adi, did, adv->sid);
1983
1984 /* No CTEInfo field in primary channel PDU */
1985
1986 /* No TargetA non-conn non-scan advertising, but present in directed
1987 * advertising.
1988 */
1989 if (sec_hdr.tgt_addr) {
1990 void *bdaddr;
1991
1992 if (sec_hdr_prev.tgt_addr) {
1993 sec_dptr_prev -= BDADDR_SIZE;
1994 bdaddr = sec_dptr_prev;
1995 } else {
1996 pri_dptr_prev -= BDADDR_SIZE;
1997 bdaddr = pri_dptr_prev;
1998 }
1999
2000 sec_dptr -= BDADDR_SIZE;
2001
2002 (void)memcpy(sec_dptr, bdaddr, BDADDR_SIZE);
2003 }
2004
2005 /* No AdvA in primary channel due to AuxPtr being added */
2006
2007 /* NOTE: AdvA in aux channel is also filled at enable and RPA
2008 * timeout
2009 */
2010 if (sec_hdr.adv_addr) {
2011 void *bdaddr;
2012
2013 if (sec_hdr_prev.adv_addr) {
2014 sec_dptr_prev -= BDADDR_SIZE;
2015 bdaddr = sec_dptr_prev;
2016 } else {
2017 pri_dptr_prev -= BDADDR_SIZE;
2018 bdaddr = pri_dptr_prev;
2019 }
2020
2021 sec_dptr -= BDADDR_SIZE;
2022
2023 (void)memcpy(sec_dptr, bdaddr, BDADDR_SIZE);
2024 }
2025
2026 /* Set the common extended header format flags in the current primary
2027 * PDU
2028 */
2029 if (pri_com_hdr->ext_hdr_len != 0) {
2030 pri_com_hdr->ext_hdr = pri_hdr;
2031 }
2032
2033 /* Set the common extended header format flags in the current secondary
2034 * PDU
2035 */
2036 if (sec_com_hdr->ext_hdr_len != 0) {
2037 sec_com_hdr->ext_hdr = sec_hdr;
2038 }
2039
2040 #if defined(CONFIG_BT_CTLR_ADV_AUX_PDU_LINK)
2041 ull_adv_aux_chain_pdu_duplicate(sec_pdu_prev, sec_pdu, aux_ptr,
2042 adv->lll.phy_s, adv->lll.phy_flags,
2043 EVENT_B2B_MAFS_US);
2044 #endif /* CONFIG_BT_CTLR_ADV_AUX_PDU_LINK */
2045
2046 /* Update auxiliary channel event time reservation */
2047 if (aux->is_started) {
2048 struct pdu_adv *pdu_scan;
2049 uint8_t err;
2050
2051 pdu_scan = lll_adv_scan_rsp_peek(lll);
2052 err = aux_time_update(aux, sec_pdu, pdu_scan);
2053 if (err) {
2054 return err;
2055 }
2056 }
2057
2058 return 0;
2059 }
2060
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)2061 uint8_t ull_adv_aux_pdu_set_clear(struct ll_adv_set *adv,
2062 struct pdu_adv *pdu_prev,
2063 struct pdu_adv *pdu,
2064 uint16_t hdr_add_fields,
2065 uint16_t hdr_rem_fields,
2066 void *hdr_data)
2067 {
2068 struct pdu_adv_com_ext_adv *com_hdr, *com_hdr_prev;
2069 struct pdu_adv_ext_hdr hdr = { 0 }, hdr_prev = { 0 };
2070 struct pdu_adv_aux_ptr *aux_ptr, *aux_ptr_prev;
2071 uint8_t *ad_fragment = NULL;
2072 uint8_t ad_fragment_len = 0;
2073 uint8_t *dptr, *dptr_prev;
2074 struct pdu_adv_adi *adi;
2075 uint8_t acad_len_prev;
2076 uint8_t hdr_buf_len;
2077 uint8_t len_prev;
2078 uint8_t *ad_data;
2079 uint8_t acad_len;
2080 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2081 uint8_t cte_info;
2082 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2083 uint8_t ad_len;
2084 uint16_t len;
2085
2086 /* Get common pointers from reference to previous tertiary PDU data */
2087 com_hdr_prev = (void *)&pdu_prev->adv_ext_ind;
2088 if (pdu_prev->len && com_hdr_prev->ext_hdr_len) {
2089 hdr_prev = com_hdr_prev->ext_hdr;
2090 } else {
2091 com_hdr_prev->ext_hdr_len = 0U;
2092 }
2093 dptr_prev = com_hdr_prev->ext_hdr.data;
2094
2095 /* Set common fields in reference to new tertiary PDU data buffer */
2096 pdu->type = pdu_prev->type;
2097 pdu->rfu = 0U;
2098 pdu->chan_sel = 0U;
2099
2100 pdu->tx_addr = pdu_prev->tx_addr;
2101 pdu->rx_addr = pdu_prev->rx_addr;
2102
2103 /* Get common pointers from current tertiary PDU data.
2104 * It is possible that the current tertiary is the same as
2105 * previous one. It may happen if update periodic advertising
2106 * chain in place.
2107 */
2108 com_hdr = (void *)&pdu->adv_ext_ind;
2109 com_hdr->adv_mode = com_hdr_prev->adv_mode;
2110 dptr = com_hdr->ext_hdr.data;
2111
2112 /* AdvA flag */
2113 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
2114 hdr.adv_addr = 1U;
2115 dptr += BDADDR_SIZE;
2116 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) &&
2117 hdr_prev.adv_addr) {
2118 hdr.adv_addr = 1U;
2119 pdu->tx_addr = pdu_prev->tx_addr;
2120
2121 dptr += BDADDR_SIZE;
2122 }
2123 if (hdr_prev.adv_addr) {
2124 dptr_prev += BDADDR_SIZE;
2125 }
2126
2127 /* TargetA flag */
2128 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_TARGETA) {
2129 hdr.tgt_addr = 1U;
2130 dptr += BDADDR_SIZE;
2131 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_TARGETA) &&
2132 hdr_prev.tgt_addr) {
2133 hdr.tgt_addr = 1U;
2134 pdu->rx_addr = pdu_prev->rx_addr;
2135
2136 dptr += BDADDR_SIZE;
2137 }
2138 if (hdr_prev.tgt_addr) {
2139 dptr_prev += BDADDR_SIZE;
2140 }
2141
2142 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2143 /* If requested add or update CTEInfo */
2144 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2145 hdr.cte_info = 1;
2146 cte_info = *(uint8_t *)hdr_data;
2147 hdr_data = (uint8_t *)hdr_data + 1;
2148 dptr += sizeof(struct pdu_cte_info);
2149 /* If CTEInfo exists in prev and is not requested to be removed */
2150 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) &&
2151 hdr_prev.cte_info) {
2152 hdr.cte_info = 1;
2153 cte_info = 0U; /* value not used, will be read from prev PDU */
2154 dptr += sizeof(struct pdu_cte_info);
2155 } else {
2156 cte_info = 0U; /* value not used */
2157 }
2158
2159 /* If CTEInfo exists in prev PDU */
2160 if (hdr_prev.cte_info) {
2161 dptr_prev += sizeof(struct pdu_cte_info);
2162 }
2163 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2164
2165 /* ADI */
2166 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADI) {
2167 hdr.adi = 1U;
2168 /* return the size of ADI structure */
2169 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_adi);
2170 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
2171 /* pick the reference to ADI param */
2172 (void)memcpy(&adi, hdr_data, sizeof(struct pdu_adv_adi *));
2173 /* return the pointer to ADI struct inside the PDU */
2174 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2175 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2176 dptr += sizeof(struct pdu_adv_adi);
2177 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ADI) &&
2178 hdr_prev.adi) {
2179 hdr.adi = 1U;
2180 adi = (void *)dptr_prev;
2181 dptr += sizeof(struct pdu_adv_adi);
2182 } else {
2183 adi = NULL;
2184 }
2185 if (hdr_prev.adi) {
2186 dptr_prev += sizeof(struct pdu_adv_adi);
2187 }
2188
2189 /* AuxPtr - will be added if AUX_CHAIN_IND is required */
2190 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
2191 hdr.aux_ptr = 1;
2192 aux_ptr_prev = NULL;
2193 aux_ptr = (void *)dptr;
2194
2195 /* return the size of aux pointer structure */
2196 *(uint8_t *)hdr_data = sizeof(struct pdu_adv_aux_ptr);
2197 hdr_data = (uint8_t *)hdr_data + sizeof(uint8_t);
2198
2199 /* return the pointer to aux pointer struct inside the PDU
2200 * buffer
2201 */
2202 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2203 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2204 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
2205 hdr_prev.aux_ptr) {
2206 hdr.aux_ptr = 1;
2207 aux_ptr_prev = (void *)dptr_prev;
2208 aux_ptr = (void *)dptr;
2209 } else {
2210 aux_ptr_prev = NULL;
2211 aux_ptr = NULL;
2212 }
2213 if (hdr_prev.aux_ptr) {
2214 dptr_prev += sizeof(struct pdu_adv_aux_ptr);
2215 }
2216 if (hdr.aux_ptr) {
2217 dptr += sizeof(struct pdu_adv_aux_ptr);
2218 }
2219
2220 /* SyncInfo flag */
2221 if (hdr_prev.sync_info) {
2222 hdr.sync_info = 1;
2223 dptr_prev += sizeof(struct pdu_adv_sync_info);
2224 dptr += sizeof(struct pdu_adv_sync_info);
2225 }
2226
2227 /* Tx Power flag */
2228 if (hdr_prev.tx_pwr) {
2229 dptr_prev++;
2230
2231 hdr.tx_pwr = 1;
2232 dptr++;
2233 }
2234
2235 /* Calc previous ACAD len and update PDU len */
2236 len_prev = dptr_prev - (uint8_t *)com_hdr_prev;
2237 hdr_buf_len = com_hdr_prev->ext_hdr_len +
2238 PDU_AC_EXT_HEADER_SIZE_MIN;
2239 if (len_prev <= hdr_buf_len) {
2240 /* There are some data, except ACAD, in extended header if len_prev
2241 * equals to hdr_buf_len. There is ACAD if the size of len_prev
2242 * is smaller than hdr_buf_len.
2243 */
2244 acad_len_prev = hdr_buf_len - len_prev;
2245 len_prev += acad_len_prev;
2246 dptr_prev += acad_len_prev;
2247 } else {
2248 /* There are no data in extended header, all flags are zeros. */
2249 acad_len_prev = 0;
2250 /* NOTE: If no flags are set then extended header length will be
2251 * zero. Under this condition the current len_prev
2252 * value will be greater than extended header length,
2253 * hence set len_prev to size of the length/mode
2254 * field.
2255 */
2256 len_prev = (pdu_prev->len) ? PDU_AC_EXT_HEADER_SIZE_MIN : 0U;
2257 dptr_prev = (uint8_t *)com_hdr_prev + len_prev;
2258 }
2259
2260 /* Did we parse beyond PDU length? */
2261 if (len_prev > pdu_prev->len) {
2262 /* we should not encounter invalid length */
2263 return BT_HCI_ERR_UNSPECIFIED;
2264 }
2265
2266 /* Add/Retain/Remove ACAD */
2267 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ACAD) {
2268 acad_len = *(uint8_t *)hdr_data;
2269 /* If zero length ACAD then do not reduce ACAD but return
2270 * return previous ACAD length.
2271 */
2272 if (!acad_len) {
2273 acad_len = acad_len_prev;
2274 }
2275 /* return prev ACAD length */
2276 *(uint8_t *)hdr_data = acad_len_prev;
2277 hdr_data = (uint8_t *)hdr_data + 1;
2278 /* return the pointer to ACAD offset */
2279 (void)memcpy(hdr_data, &dptr, sizeof(dptr));
2280 hdr_data = (uint8_t *)hdr_data + sizeof(dptr);
2281 dptr += acad_len;
2282 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_ACAD)) {
2283 acad_len = acad_len_prev;
2284 dptr += acad_len_prev;
2285 } else {
2286 acad_len = 0U;
2287 }
2288
2289 /* Calc current tertiary PDU len so far without AD data added */
2290 len = ull_adv_aux_hdr_len_calc(com_hdr, &dptr);
2291
2292 /* Get Adv data from function parameters */
2293 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
2294 uint8_t ad_len_prev;
2295
2296 /* remember the new ad data len */
2297 ad_len = *(uint8_t *)hdr_data;
2298
2299 /* return prev ad data length */
2300 ad_len_prev = pdu_prev->len - len_prev;
2301 *(uint8_t *)hdr_data = ad_len_prev;
2302 hdr_data = (uint8_t *)hdr_data + sizeof(ad_len);
2303
2304 /* remember the reference to new ad data */
2305 (void)memcpy(&ad_data, hdr_data, sizeof(ad_data));
2306
2307 /* return the reference to prev ad data */
2308 (void)memcpy(hdr_data, &dptr_prev, sizeof(dptr_prev));
2309 hdr_data = (uint8_t *)hdr_data + sizeof(dptr_prev);
2310
2311 /* unchanged data */
2312 if (!ad_len && !ad_data) {
2313 ad_len = ad_len_prev;
2314 ad_data = dptr_prev;
2315 }
2316 } else if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND) {
2317 ad_len = pdu_prev->len - len_prev;
2318 ad_data = dptr_prev;
2319
2320 /* Append the new ad data fragment */
2321 ad_fragment_len = *(uint8_t *)hdr_data;
2322 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment_len);
2323 (void)memcpy(&ad_fragment, hdr_data, sizeof(ad_fragment));
2324 hdr_data = (uint8_t *)hdr_data + sizeof(ad_fragment);
2325 } else if (!(hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA)) {
2326 ad_len = pdu_prev->len - len_prev;
2327 ad_data = dptr_prev;
2328 } else {
2329 ad_len = 0;
2330 ad_data = NULL;
2331 }
2332
2333 /* Check Max Advertising Data Length */
2334 if (ad_len + ad_fragment_len > CONFIG_BT_CTLR_ADV_DATA_LEN_MAX) {
2335 return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
2336 }
2337
2338 /* Check AdvData overflow */
2339 if ((len + ad_len + ad_fragment_len) > PDU_AC_PAYLOAD_SIZE_MAX) {
2340 /* return excess length */
2341 *(uint8_t *)hdr_data = len + ad_len + ad_fragment_len -
2342 PDU_AC_PAYLOAD_SIZE_MAX;
2343
2344 /* Will use packet too long error to determine fragmenting
2345 * long data
2346 */
2347 return BT_HCI_ERR_PACKET_TOO_LONG;
2348 }
2349
2350 /* set the tertiary extended header and PDU length */
2351 ull_adv_aux_hdr_len_fill(com_hdr, len);
2352 pdu->len = len + ad_len + ad_fragment_len;
2353
2354 /* Start filling tertiary PDU payload based on flags from here
2355 * ==============================================================
2356 */
2357
2358 /* Fill AdvData in tertiary PDU */
2359 (void)memmove(dptr, ad_data, ad_len);
2360
2361 if (ad_fragment) {
2362 (void)memcpy(dptr + ad_len, ad_fragment, ad_fragment_len);
2363 }
2364
2365 /* Early exit if no flags set */
2366 if (!com_hdr->ext_hdr_len) {
2367 return 0;
2368 }
2369
2370 /* Retain ACAD in tertiary PDU */
2371 dptr_prev -= acad_len_prev;
2372 if (acad_len) {
2373 dptr -= acad_len;
2374 (void)memmove(dptr, dptr_prev, acad_len_prev);
2375 }
2376
2377 /* Tx Power */
2378 if (hdr.tx_pwr) {
2379 *--dptr = *--dptr_prev;
2380 }
2381
2382 /* SyncInfo */
2383 if (hdr.sync_info) {
2384 dptr_prev -= sizeof(struct pdu_adv_sync_info);
2385 dptr -= sizeof(struct pdu_adv_sync_info);
2386
2387 (void)memmove(dptr, dptr_prev,
2388 sizeof(struct pdu_adv_sync_info));
2389 }
2390
2391 /* AuxPtr */
2392 if (hdr_prev.aux_ptr) {
2393 dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
2394 }
2395 if (hdr.aux_ptr) {
2396 dptr -= sizeof(struct pdu_adv_aux_ptr);
2397 }
2398 if (aux_ptr_prev) {
2399 (void)memmove(dptr, aux_ptr_prev, sizeof(*aux_ptr_prev));
2400 }
2401
2402 /* ADI */
2403 if (hdr_prev.adi) {
2404 dptr_prev -= sizeof(struct pdu_adv_adi);
2405 }
2406 if (hdr.adi) {
2407 struct pdu_adv_adi *adi_pdu;
2408
2409 dptr -= sizeof(struct pdu_adv_adi);
2410 adi_pdu = (void *)dptr;
2411
2412 if (!adi) {
2413 /* The DID for a specific SID shall be unique.
2414 */
2415 const uint16_t did =
2416 sys_cpu_to_le16(ull_adv_aux_did_next_unique_get(adv->sid));
2417 PDU_ADV_ADI_DID_SID_SET(adi_pdu, did, adv->sid);
2418 } else {
2419 adi_pdu->did_sid_packed[0] = adi->did_sid_packed[0];
2420 adi_pdu->did_sid_packed[1] = adi->did_sid_packed[1];
2421 }
2422 }
2423
2424 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
2425 if (hdr.cte_info) {
2426 if (hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_CTE_INFO) {
2427 *--dptr = cte_info;
2428 } else {
2429 *--dptr = *--dptr_prev;
2430 }
2431 }
2432 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
2433
2434 /* No TargetA in non-conn non-scan advertising, but present in directed
2435 * advertising.
2436 */
2437 if (hdr.tgt_addr) {
2438 dptr_prev -= BDADDR_SIZE;
2439 dptr -= BDADDR_SIZE;
2440
2441 (void)memmove(dptr, dptr_prev, BDADDR_SIZE);
2442 }
2443
2444 /* NOTE: AdvA in aux channel is also filled at enable and RPA
2445 * timeout
2446 */
2447 if (hdr.adv_addr) {
2448 dptr_prev -= BDADDR_SIZE;
2449 dptr -= BDADDR_SIZE;
2450
2451 (void)memmove(dptr, dptr_prev, BDADDR_SIZE);
2452 }
2453
2454 if (com_hdr->ext_hdr_len != 0) {
2455 com_hdr->ext_hdr = hdr;
2456 }
2457
2458 return 0;
2459 }
2460
ull_adv_aux_did_next_unique_get(uint8_t sid)2461 uint16_t ull_adv_aux_did_next_unique_get(uint8_t sid)
2462 {
2463 /* The DID is 12 bits and did_unique may overflow without any negative
2464 * consequences.
2465 */
2466 return BIT_MASK(12) & did_unique[sid]++;
2467 }
2468
ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr * aux_ptr,uint32_t offs_us,uint8_t phy_s)2469 void ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr *aux_ptr, uint32_t offs_us,
2470 uint8_t phy_s)
2471 {
2472 uint32_t offs;
2473 uint8_t phy;
2474
2475 /* NOTE: Channel Index and Aux Offset will be set on every advertiser's
2476 * event prepare when finding the auxiliary event's ticker offset.
2477 * Here we fill initial values.
2478 */
2479 aux_ptr->chan_idx = 0U;
2480
2481 aux_ptr->ca = (lll_clock_ppm_local_get() <= SCA_50_PPM) ?
2482 SCA_VALUE_50_PPM : SCA_VALUE_500_PPM;
2483
2484 offs = offs_us / OFFS_UNIT_30_US;
2485 if (!!(offs >> OFFS_UNIT_BITS)) {
2486 offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
2487 aux_ptr->offs_units = OFFS_UNIT_VALUE_300_US;
2488 } else {
2489 aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
2490 }
2491 phy = find_lsb_set(phy_s) - 1;
2492
2493 aux_ptr->offs_phy_packed[0] = offs & 0xFF;
2494 aux_ptr->offs_phy_packed[1] = ((offs>>8) & 0x1F) + (phy << 5);
2495 }
2496
2497 #if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
ull_adv_aux_handle_get(struct ll_adv_aux_set * aux)2498 inline uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux)
2499 {
2500 return mem_index_get(aux, ll_adv_aux_pool,
2501 sizeof(struct ll_adv_aux_set));
2502 }
2503
ull_adv_aux_lll_handle_get(struct lll_adv_aux * lll)2504 uint8_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll)
2505 {
2506 return ull_adv_aux_handle_get((void *)lll->hdr.parent);
2507 }
2508
ull_adv_aux_evt_init(struct ll_adv_aux_set * aux,uint32_t * ticks_anchor)2509 uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
2510 uint32_t *ticks_anchor)
2511 {
2512 uint32_t ticks_slot_overhead;
2513 uint32_t time_us;
2514
2515 time_us = aux_time_min_get(aux);
2516
2517 /* TODO: active_to_start feature port */
2518 aux->ull.ticks_active_to_start = 0;
2519 aux->ull.ticks_prepare_to_start =
2520 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
2521 aux->ull.ticks_preempt_to_start =
2522 HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
2523 aux->ull.ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
2524
2525 if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
2526 ticks_slot_overhead = MAX(aux->ull.ticks_active_to_start,
2527 aux->ull.ticks_prepare_to_start);
2528 } else {
2529 ticks_slot_overhead = 0;
2530 }
2531
2532 #if defined(CONFIG_BT_CTLR_SCHED_ADVANCED)
2533 uint32_t ticks_anchor_aux;
2534 uint32_t ticks_slot;
2535 int err;
2536
2537 #if defined(CONFIG_BT_CTLR_ADV_RESERVE_MAX)
2538 time_us = ull_adv_aux_time_get(aux, PDU_AC_PAYLOAD_SIZE_MAX,
2539 PDU_AC_PAYLOAD_SIZE_MAX);
2540 ticks_slot = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
2541 #else
2542 ticks_slot = aux->ull.ticks_slot;
2543 #endif
2544
2545 err = ull_sched_adv_aux_sync_free_anchor_get((ticks_slot +
2546 ticks_slot_overhead),
2547 &ticks_anchor_aux);
2548 if (!err) {
2549 *ticks_anchor = ticks_anchor_aux;
2550 *ticks_anchor += HAL_TICKER_US_TO_TICKS(
2551 MAX(EVENT_MAFS_US,
2552 EVENT_OVERHEAD_START_US) -
2553 EVENT_OVERHEAD_START_US +
2554 (EVENT_TICKER_RES_MARGIN_US << 1));
2555 }
2556 #endif /* CONFIG_BT_CTLR_SCHED_ADVANCED */
2557
2558 return ticks_slot_overhead;
2559 }
2560
2561 #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)2562 void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux)
2563 {
2564 if (aux->is_started) {
2565 struct lll_adv_sync *lll_sync = aux->lll.adv->sync;
2566 struct ll_adv_sync_set *sync;
2567 uint8_t aux_handle;
2568
2569 LL_ASSERT(lll_sync);
2570
2571 sync = HDR_LLL2ULL(lll_sync);
2572 aux_handle = ull_adv_aux_handle_get(aux);
2573
2574 if (sync->is_started) {
2575 uint8_t sync_handle = ull_adv_sync_handle_get(sync);
2576
2577 ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2578 (TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
2579 ticker_update_op_cb, aux, 0,
2580 TICKER_ID_ADV_SYNC_BASE + sync_handle);
2581 } else {
2582 ticker_update_ext(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2583 (TICKER_ID_ADV_AUX_BASE + aux_handle), 0, 0, 0, 0, 0, 0,
2584 ticker_update_op_cb, aux, 0,
2585 TICKER_NULL);
2586 }
2587 }
2588 }
2589 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2590
ull_adv_aux_start(struct ll_adv_aux_set * aux,uint32_t ticks_anchor,uint32_t ticks_slot_overhead)2591 uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
2592 uint32_t ticks_slot_overhead)
2593 {
2594 uint32_t volatile ret_cb;
2595 uint32_t interval_us;
2596 uint8_t aux_handle;
2597 uint32_t ret;
2598
2599 ull_hdr_init(&aux->ull);
2600 aux_handle = ull_adv_aux_handle_get(aux);
2601 interval_us = aux->interval * PERIODIC_INT_UNIT_US;
2602
2603 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2604 if (aux->lll.adv->sync) {
2605 const struct ll_adv_sync_set *sync = HDR_LLL2ULL(aux->lll.adv->sync);
2606 uint8_t sync_handle = ull_adv_sync_handle_get(sync);
2607
2608 ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_ID_ADV_SYNC_BASE +
2609 sync_handle;
2610 } else {
2611 ll_adv_aux_ticker_ext[aux_handle].expire_info_id = TICKER_NULL;
2612 }
2613
2614 ll_adv_aux_ticker_ext[aux_handle].ext_timeout_func = ticker_cb;
2615
2616 ret_cb = TICKER_STATUS_BUSY;
2617 ret = ticker_start_ext(
2618 #else /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2619
2620 ret_cb = TICKER_STATUS_BUSY;
2621 ret = ticker_start(
2622 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2623 TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
2624 (TICKER_ID_ADV_AUX_BASE + aux_handle),
2625 ticks_anchor, 0U,
2626 HAL_TICKER_US_TO_TICKS(interval_us),
2627 HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
2628 (aux->ull.ticks_slot + ticks_slot_overhead),
2629 ticker_cb, aux,
2630 ull_ticker_status_give, (void *)&ret_cb
2631 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
2632 ,
2633 &ll_adv_aux_ticker_ext[aux_handle]
2634 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2635 );
2636 ret = ull_ticker_status_take(ret, &ret_cb);
2637
2638 return ret;
2639 }
2640
ull_adv_aux_stop(struct ll_adv_aux_set * aux)2641 int ull_adv_aux_stop(struct ll_adv_aux_set *aux)
2642 {
2643 uint8_t aux_handle;
2644 int err;
2645
2646 aux_handle = ull_adv_aux_handle_get(aux);
2647
2648 err = ull_ticker_stop_with_mark(TICKER_ID_ADV_AUX_BASE + aux_handle,
2649 aux, &aux->lll);
2650 LL_ASSERT_INFO2(err == 0 || err == -EALREADY, aux_handle, err);
2651 if (err) {
2652 return err;
2653 }
2654
2655 aux->is_started = 0U;
2656
2657 return 0;
2658 }
2659
ull_adv_aux_acquire(struct lll_adv * lll)2660 struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll)
2661 {
2662 struct lll_adv_aux *lll_aux;
2663 struct ll_adv_aux_set *aux;
2664 uint8_t chm_last;
2665 int err;
2666
2667 aux = aux_acquire();
2668 if (!aux) {
2669 return aux;
2670 }
2671
2672 lll_aux = &aux->lll;
2673 lll->aux = lll_aux;
2674 lll_aux->adv = lll;
2675
2676 lll_adv_data_reset(&lll_aux->data);
2677 err = lll_adv_aux_data_init(&lll_aux->data);
2678 if (err) {
2679 return NULL;
2680 }
2681
2682 /* Initialize data channel calculation counter, data channel identifier,
2683 * and channel map to use.
2684 */
2685 lll_csrand_get(&lll_aux->data_chan_counter,
2686 sizeof(lll_aux->data_chan_counter));
2687 lll_csrand_get(&aux->data_chan_id, sizeof(aux->data_chan_id));
2688 chm_last = aux->chm_first;
2689 aux->chm_last = chm_last;
2690 aux->chm[chm_last].data_chan_count =
2691 ull_chan_map_get(aux->chm[chm_last].data_chan_map);
2692
2693
2694 /* NOTE: ull_hdr_init(&aux->ull); is done on start */
2695 lll_hdr_init(lll_aux, aux);
2696
2697 aux->is_started = 0U;
2698
2699 return aux;
2700 }
2701
ull_adv_aux_release(struct ll_adv_aux_set * aux)2702 void ull_adv_aux_release(struct ll_adv_aux_set *aux)
2703 {
2704 lll_adv_data_release(&aux->lll.data);
2705 aux_release(aux);
2706 }
2707
ull_adv_aux_get(uint8_t handle)2708 struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle)
2709 {
2710 if (handle >= CONFIG_BT_CTLR_ADV_AUX_SET) {
2711 return NULL;
2712 }
2713
2714 return &ll_adv_aux_pool[handle];
2715 }
2716
ull_adv_aux_time_get(const struct ll_adv_aux_set * aux,uint8_t pdu_len,uint8_t pdu_scan_len)2717 uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
2718 uint8_t pdu_scan_len)
2719 {
2720 const struct pdu_adv *pdu;
2721
2722 pdu = lll_adv_aux_data_peek(&aux->lll);
2723
2724 return aux_time_get(aux, pdu, pdu_len, pdu_scan_len);
2725 }
2726
2727 #if !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_aux_offset_get(struct ll_adv_set * adv)2728 void ull_adv_aux_offset_get(struct ll_adv_set *adv)
2729 {
2730 static memq_link_t link;
2731 static struct mayfly mfy = {0, 0, &link, NULL, mfy_aux_offset_get};
2732 uint32_t ret;
2733
2734 /* NOTE: Single mayfly instance is sufficient as primary channel PDUs
2735 * use time reservation, and this mayfly shall complete within
2736 * the radio event. Multiple advertising sets do not need
2737 * independent mayfly allocations.
2738 */
2739 mfy.param = adv;
2740 ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
2741 &mfy);
2742 LL_ASSERT(!ret);
2743 }
2744 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
2745
ull_adv_aux_lll_offset_fill(struct pdu_adv * pdu,uint32_t ticks_offset,uint32_t remainder_us,uint32_t start_us)2746 struct pdu_adv_aux_ptr *ull_adv_aux_lll_offset_fill(struct pdu_adv *pdu,
2747 uint32_t ticks_offset,
2748 uint32_t remainder_us,
2749 uint32_t start_us)
2750 {
2751 struct pdu_adv_com_ext_adv *pri_com_hdr;
2752 struct pdu_adv_aux_ptr *aux_ptr;
2753 struct pdu_adv_ext_hdr *h;
2754 uint32_t offs;
2755 uint8_t *ptr;
2756
2757 pri_com_hdr = (void *)&pdu->adv_ext_ind;
2758 h = (void *)pri_com_hdr->ext_hdr_adv_data;
2759 ptr = h->data;
2760
2761 /* traverse through adv_addr, if present */
2762 if (h->adv_addr) {
2763 ptr += BDADDR_SIZE;
2764 }
2765
2766 /* traverse through tgt_addr, if present */
2767 if (h->tgt_addr) {
2768 ptr += BDADDR_SIZE;
2769 }
2770
2771 /* No CTEInfo flag in primary and secondary channel PDU */
2772
2773 /* traverse through adi, if present */
2774 if (h->adi) {
2775 ptr += sizeof(struct pdu_adv_adi);
2776 }
2777
2778 /* Reference to aux ptr structure in the PDU */
2779 aux_ptr = (void *)ptr;
2780
2781 /* Aux offset value in micro seconds */
2782 offs = HAL_TICKER_TICKS_TO_US(ticks_offset) + remainder_us - start_us;
2783
2784 /* Fill aux offset in offset units 30 or 300 us */
2785 offs = offs / OFFS_UNIT_30_US;
2786 if (!!(offs >> OFFS_UNIT_BITS)) {
2787 offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
2788 aux_ptr->offs_units = OFFS_UNIT_VALUE_300_US;
2789 } else {
2790 aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
2791 }
2792 aux_ptr->offs_phy_packed[0] = offs & 0xFF;
2793 aux_ptr->offs_phy_packed[1] = ((offs>>8) & 0x1F) + (aux_ptr->offs_phy_packed[1] & 0xE0);
2794
2795 return aux_ptr;
2796 }
2797
ull_adv_aux_done(struct node_rx_event_done * done)2798 void ull_adv_aux_done(struct node_rx_event_done *done)
2799 {
2800 struct lll_adv_aux *lll_aux;
2801 struct ll_adv_aux_set *aux;
2802 struct ll_adv_set *adv;
2803
2804 /* Get reference to ULL context */
2805 aux = CONTAINER_OF(done->param, struct ll_adv_aux_set, ull);
2806 lll_aux = &aux->lll;
2807 adv = HDR_LLL2ULL(lll_aux->adv);
2808
2809 /* Call the primary channel advertising done */
2810 done->param = &adv->ull;
2811 ull_adv_done(done);
2812 }
2813
2814 #if defined(CONFIG_BT_CTLR_ADV_PDU_LINK)
2815 /* @brief Duplicate previous chain of PDUs into current chain of PDUs, fill the
2816 * aux ptr field of the parent primary channel PDU with the aux offset,
2817 * and the secondary channel PDU's PHY.
2818 *
2819 * @param[in] pdu_prev Pointer to previous PDU's chain PDU
2820 * @param[in] pdu Pointer to current PDU's chain PDU
2821 * @param[in] aux_ptr Pointer to aux ptr field in the primary channel PDU
2822 * @param[in] phy_s Secondary/auxiliary PDU PHY
2823 * @param[in] phy_flags Secondary/auxiliary PDU coded PHY encoding (S2/S8)
2824 * @param[in] mafs_us Minimum Aux Frame Spacing to use, in microseconds
2825 */
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)2826 void ull_adv_aux_chain_pdu_duplicate(struct pdu_adv *pdu_prev,
2827 struct pdu_adv *pdu,
2828 struct pdu_adv_aux_ptr *aux_ptr,
2829 uint8_t phy_s, uint8_t phy_flags,
2830 uint32_t mafs_us)
2831 {
2832 /* Duplicate any chain PDUs */
2833 while (aux_ptr) {
2834 struct pdu_adv_com_ext_adv *com_hdr_chain;
2835 struct pdu_adv_com_ext_adv *com_hdr;
2836 struct pdu_adv_ext_hdr *hdr_chain;
2837 struct pdu_adv_adi *adi_parent;
2838 struct pdu_adv *pdu_chain_prev;
2839 struct pdu_adv_ext_hdr *hdr;
2840 struct pdu_adv *pdu_chain;
2841 uint8_t *dptr_chain;
2842 uint32_t offs_us;
2843 uint8_t *dptr;
2844
2845 /* Get the next chain PDU */
2846 pdu_chain_prev = lll_adv_pdu_linked_next_get(pdu_prev);
2847 if (!pdu_chain_prev) {
2848 break;
2849 }
2850
2851 /* Fill the aux offset in the (first iteration, it is the
2852 * primary channel ADV_EXT_IND PDU, rest it is AUX_ADV_IND and
2853 * AUX_CHAIN_IND) parent PDU
2854 */
2855 offs_us = PDU_AC_US(pdu->len, phy_s, phy_flags) + mafs_us;
2856 ull_adv_aux_ptr_fill(aux_ptr, offs_us, phy_s);
2857
2858 /* Get reference to flags in superior PDU */
2859 com_hdr = &pdu->adv_ext_ind;
2860 hdr = (void *)&com_hdr->ext_hdr_adv_data[0];
2861 dptr = (void *)hdr;
2862
2863 /* Get the next new chain PDU */
2864 pdu_chain = lll_adv_pdu_linked_next_get(pdu);
2865 if (!pdu_chain) {
2866 /* Get a new chain PDU */
2867 pdu_chain = lll_adv_pdu_alloc_pdu_adv();
2868 LL_ASSERT(pdu_chain);
2869
2870 /* Copy previous chain PDU into new chain PDU */
2871 (void)memcpy(pdu_chain, pdu_chain_prev,
2872 offsetof(struct pdu_adv, payload) +
2873 pdu_chain_prev->len);
2874
2875 /* Link the chain PDU to parent PDU */
2876 lll_adv_pdu_linked_append(pdu_chain, pdu);
2877 }
2878
2879 /* Get reference to common header format */
2880 com_hdr_chain = &pdu_chain_prev->adv_ext_ind;
2881 hdr_chain = (void *)&com_hdr_chain->ext_hdr_adv_data[0];
2882 dptr_chain = (void *)hdr_chain;
2883
2884 /* Check for no Flags */
2885 if (!com_hdr_chain->ext_hdr_len) {
2886 break;
2887 }
2888
2889 /* Proceed to next byte if any flags present */
2890 if (*dptr) {
2891 dptr++;
2892 }
2893 if (*dptr_chain) {
2894 dptr_chain++;
2895 }
2896
2897 /* AdvA flag */
2898 if (hdr->adv_addr) {
2899 dptr += BDADDR_SIZE;
2900 }
2901 if (hdr_chain->adv_addr) {
2902 dptr_chain += BDADDR_SIZE;
2903 }
2904
2905 /* TgtA flag */
2906 if (hdr->tgt_addr) {
2907 dptr += BDADDR_SIZE;
2908 }
2909 if (hdr_chain->tgt_addr) {
2910 dptr_chain += BDADDR_SIZE;
2911 }
2912
2913 /* CTE Info */
2914 if (hdr->cte_info) {
2915 dptr += sizeof(struct pdu_cte_info);
2916 }
2917 if (hdr_chain->cte_info) {
2918 dptr_chain += sizeof(struct pdu_cte_info);
2919 }
2920
2921 /* ADI */
2922 if (hdr->adi) {
2923 adi_parent = (void *)dptr;
2924
2925 dptr += sizeof(struct pdu_adv_adi);
2926 } else {
2927 adi_parent = NULL;
2928 }
2929 if (hdr_chain->adi) {
2930 struct pdu_adv_adi *adi;
2931
2932 /* update ADI to superior PDU ADI */
2933 adi = (void *)dptr_chain;
2934 if (adi_parent) {
2935 adi->did_sid_packed[0] = adi_parent->did_sid_packed[0];
2936 adi->did_sid_packed[1] = adi_parent->did_sid_packed[1];
2937 }
2938
2939 dptr_chain += sizeof(struct pdu_adv_adi);
2940 }
2941
2942 /* No aux ptr, no further chain PDUs */
2943 if (!hdr_chain->aux_ptr) {
2944 break;
2945 }
2946
2947 /* Remember the aux ptr to be populated */
2948 aux_ptr = (void *)dptr_chain;
2949
2950 /* Progress to next chain PDU */
2951 pdu_prev = pdu_chain_prev;
2952 pdu = pdu_chain;
2953 }
2954 }
2955 #endif /* CONFIG_BT_CTLR_ADV_PDU_LINK */
2956
init_reset(void)2957 static int init_reset(void)
2958 {
2959 /* Initialize adv aux pool. */
2960 mem_init(ll_adv_aux_pool, sizeof(struct ll_adv_aux_set),
2961 sizeof(ll_adv_aux_pool) / sizeof(struct ll_adv_aux_set),
2962 &adv_aux_free);
2963
2964 return 0;
2965 }
2966
aux_acquire(void)2967 static inline struct ll_adv_aux_set *aux_acquire(void)
2968 {
2969 return mem_acquire(&adv_aux_free);
2970 }
2971
aux_release(struct ll_adv_aux_set * aux)2972 static inline void aux_release(struct ll_adv_aux_set *aux)
2973 {
2974 mem_release(aux, &adv_aux_free);
2975 }
2976
aux_time_get(const struct ll_adv_aux_set * aux,const struct pdu_adv * pdu,uint8_t pdu_len,uint8_t pdu_scan_len)2977 static uint32_t aux_time_get(const struct ll_adv_aux_set *aux,
2978 const struct pdu_adv *pdu,
2979 uint8_t pdu_len, uint8_t pdu_scan_len)
2980 {
2981 const struct lll_adv_aux *lll_aux;
2982 const struct lll_adv *lll;
2983 uint32_t time_us;
2984
2985 lll_aux = &aux->lll;
2986 lll = lll_aux->adv;
2987
2988 if (IS_ENABLED(CONFIG_BT_CTLR_ADV_RESERVE_MAX) &&
2989 (lll->phy_s == PHY_CODED)) {
2990 pdu_len = PDU_AC_EXT_PAYLOAD_OVERHEAD;
2991 pdu_scan_len = PDU_AC_EXT_PAYLOAD_OVERHEAD;
2992 }
2993
2994 /* NOTE: 16-bit values are sufficient for minimum radio event time
2995 * reservation, 32-bit are used here so that reservations for
2996 * whole back-to-back chaining of PDUs can be accommodated where
2997 * the required microseconds could overflow 16-bits, example,
2998 * back-to-back chained Coded PHY PDUs.
2999 */
3000 time_us = PDU_AC_US(pdu_len, lll->phy_s, lll->phy_flags) +
3001 EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
3002
3003 if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_CONN) ==
3004 BT_HCI_LE_ADV_PROP_CONN) {
3005 const uint16_t conn_req_us =
3006 PDU_AC_MAX_US((INITA_SIZE + ADVA_SIZE + LLDATA_SIZE),
3007 lll->phy_s);
3008 const uint16_t conn_rsp_us =
3009 PDU_AC_US((PDU_AC_EXT_HEADER_SIZE_MIN + ADVA_SIZE +
3010 TARGETA_SIZE), lll->phy_s, lll->phy_flags);
3011
3012 time_us += EVENT_IFS_MAX_US * 2 + conn_req_us + conn_rsp_us;
3013 } else if ((pdu->adv_ext_ind.adv_mode & BT_HCI_LE_ADV_PROP_SCAN) ==
3014 BT_HCI_LE_ADV_PROP_SCAN) {
3015 const uint16_t scan_req_us =
3016 PDU_AC_MAX_US((SCANA_SIZE + ADVA_SIZE), lll->phy_s);
3017 const uint16_t scan_rsp_us =
3018 PDU_AC_US(pdu_scan_len, lll->phy_s, lll->phy_flags);
3019
3020 time_us += EVENT_IFS_MAX_US * 2 + scan_req_us + scan_rsp_us;
3021
3022 /* FIXME: Calculate additional time reservations for scan
3023 * response chain PDUs, if any.
3024 */
3025 } else {
3026 /* Non-connectable Non-Scannable */
3027
3028 /* FIXME: Calculate additional time reservations for chain PDUs,
3029 * if any.
3030 */
3031 }
3032
3033 return time_us;
3034 }
3035
aux_time_min_get(const struct ll_adv_aux_set * aux)3036 static uint32_t aux_time_min_get(const struct ll_adv_aux_set *aux)
3037 {
3038 const struct lll_adv_aux *lll_aux;
3039 const struct pdu_adv *pdu_scan;
3040 const struct lll_adv *lll;
3041 const struct pdu_adv *pdu;
3042 uint8_t pdu_scan_len;
3043 uint8_t pdu_len;
3044
3045 lll_aux = &aux->lll;
3046 lll = lll_aux->adv;
3047 pdu = lll_adv_aux_data_peek(lll_aux);
3048 pdu_scan = lll_adv_scan_rsp_peek(lll);
3049
3050 /* Calculate the PDU Tx Time and hence the radio event length,
3051 * Always use maximum length for common extended header format so that
3052 * ACAD could be update when periodic advertising is active and the
3053 * time reservation need not be updated every time avoiding overlapping
3054 * with other active states/roles.
3055 */
3056 pdu_len = pdu->len - pdu->adv_ext_ind.ext_hdr_len -
3057 PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
3058 pdu_scan_len = pdu_scan->len - pdu_scan->adv_ext_ind.ext_hdr_len -
3059 PDU_AC_EXT_HEADER_SIZE_MIN + PDU_AC_EXT_HEADER_SIZE_MAX;
3060
3061 return aux_time_get(aux, pdu, pdu_len, pdu_scan_len);
3062 }
3063
aux_time_update(struct ll_adv_aux_set * aux,struct pdu_adv * pdu,struct pdu_adv * pdu_scan)3064 static uint8_t aux_time_update(struct ll_adv_aux_set *aux, struct pdu_adv *pdu,
3065 struct pdu_adv *pdu_scan)
3066 {
3067 uint32_t time_ticks;
3068 uint32_t time_us;
3069
3070 time_us = aux_time_min_get(aux);
3071 time_ticks = HAL_TICKER_US_TO_TICKS_CEIL(time_us);
3072
3073 #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
3074 uint32_t volatile ret_cb;
3075 uint32_t ticks_minus;
3076 uint32_t ticks_plus;
3077 uint32_t ret;
3078
3079 if (aux->ull.ticks_slot > time_ticks) {
3080 ticks_minus = aux->ull.ticks_slot - time_ticks;
3081 ticks_plus = 0U;
3082 } else if (aux->ull.ticks_slot < time_ticks) {
3083 ticks_minus = 0U;
3084 ticks_plus = time_ticks - aux->ull.ticks_slot;
3085 } else {
3086 return BT_HCI_ERR_SUCCESS;
3087 }
3088
3089 ret_cb = TICKER_STATUS_BUSY;
3090 ret = ticker_update(TICKER_INSTANCE_ID_CTLR,
3091 TICKER_USER_ID_THREAD,
3092 (TICKER_ID_ADV_AUX_BASE +
3093 ull_adv_aux_handle_get(aux)),
3094 0, 0, ticks_plus, ticks_minus, 0, 0,
3095 ull_ticker_status_give, (void *)&ret_cb);
3096 ret = ull_ticker_status_take(ret, &ret_cb);
3097 if (ret != TICKER_STATUS_SUCCESS) {
3098 return BT_HCI_ERR_CMD_DISALLOWED;
3099 }
3100 #endif /* !CONFIG_BT_CTLR_JIT_SCHEDULING */
3101
3102 aux->ull.ticks_slot = time_ticks;
3103
3104 return BT_HCI_ERR_SUCCESS;
3105 }
3106
3107 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ull_adv_aux_lll_auxptr_fill(struct pdu_adv * pdu,struct lll_adv * adv)3108 void ull_adv_aux_lll_auxptr_fill(struct pdu_adv *pdu, struct lll_adv *adv)
3109 {
3110 struct lll_adv_aux *lll_aux = adv->aux;
3111 struct pdu_adv_aux_ptr *aux_ptr;
3112 struct ll_adv_aux_set *aux;
3113 uint8_t data_chan_count;
3114 uint8_t *data_chan_map;
3115 uint16_t chan_counter;
3116 uint32_t offset_us;
3117 uint16_t pdu_us;
3118
3119 aux = HDR_LLL2ULL(lll_aux);
3120
3121 chan_counter = lll_aux->data_chan_counter;
3122
3123 /* The offset has to be at least T_MAFS microseconds from the end of packet
3124 * In addition, the offset recorded in the aux ptr has the same requirement and this
3125 * offset is in steps of 30 microseconds; So use the quantized value in check
3126 */
3127 pdu_us = PDU_AC_US(pdu->len, adv->phy_p, adv->phy_flags);
3128 offset_us = HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset) +
3129 lll_aux->us_pri_pdu_offset;
3130 if ((offset_us/OFFS_UNIT_30_US)*OFFS_UNIT_30_US < EVENT_MAFS_US + pdu_us) {
3131 uint32_t interval_us;
3132
3133 /* Offset too small, point to next aux packet instead */
3134 interval_us = aux->interval * PERIODIC_INT_UNIT_US;
3135 offset_us = offset_us + interval_us;
3136 lll_aux->ticks_pri_pdu_offset = HAL_TICKER_US_TO_TICKS(offset_us);
3137 lll_aux->us_pri_pdu_offset = offset_us -
3138 HAL_TICKER_TICKS_TO_US(lll_aux->ticks_pri_pdu_offset);
3139 chan_counter++;
3140 }
3141
3142 /* Fill the aux offset */
3143 aux_ptr = ull_adv_aux_lll_offset_fill(pdu, lll_aux->ticks_pri_pdu_offset,
3144 lll_aux->us_pri_pdu_offset, 0U);
3145
3146
3147 /* Calculate and fill the radio channel to use */
3148 data_chan_map = aux->chm[aux->chm_first].data_chan_map;
3149 data_chan_count = aux->chm[aux->chm_first].data_chan_count;
3150 aux_ptr->chan_idx = lll_chan_sel_2(chan_counter,
3151 aux->data_chan_id,
3152 data_chan_map, data_chan_count);
3153 }
3154
3155 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
mfy_aux_offset_get(void * param)3156 static void mfy_aux_offset_get(void *param)
3157 {
3158 struct pdu_adv_aux_ptr *aux_ptr;
3159 struct lll_adv_aux *lll_aux;
3160 struct ll_adv_aux_set *aux;
3161 uint32_t ticks_to_expire;
3162 uint32_t ticks_to_start;
3163 uint8_t data_chan_count;
3164 uint8_t *data_chan_map;
3165 uint32_t ticks_current;
3166 uint32_t ticks_elapsed;
3167 struct ll_adv_set *adv;
3168 struct pdu_adv *pdu;
3169 uint32_t ticks_now;
3170 uint32_t remainder;
3171 uint8_t ticker_id;
3172 uint8_t retry;
3173 uint8_t id;
3174
3175 adv = param;
3176 lll_aux = adv->lll.aux;
3177 aux = HDR_LLL2ULL(lll_aux);
3178 ticker_id = TICKER_ID_ADV_AUX_BASE + ull_adv_aux_handle_get(aux);
3179
3180 id = TICKER_NULL;
3181 ticks_to_expire = 0U;
3182 ticks_current = adv->ticks_at_expire;
3183 retry = 1U; /* Assert on first ticks_current change */
3184 do {
3185 uint32_t volatile ret_cb;
3186 uint32_t ticks_previous;
3187 uint32_t ret;
3188 bool success;
3189
3190 ticks_previous = ticks_current;
3191
3192 ret_cb = TICKER_STATUS_BUSY;
3193 ret = ticker_next_slot_get_ext(TICKER_INSTANCE_ID_CTLR,
3194 TICKER_USER_ID_ULL_LOW,
3195 &id, &ticks_current,
3196 &ticks_to_expire, &remainder,
3197 NULL, NULL, NULL,
3198 ticker_op_cb, (void *)&ret_cb);
3199 if (ret == TICKER_STATUS_BUSY) {
3200 while (ret_cb == TICKER_STATUS_BUSY) {
3201 ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
3202 TICKER_USER_ID_ULL_LOW);
3203 }
3204 }
3205
3206 success = (ret_cb == TICKER_STATUS_SUCCESS);
3207 LL_ASSERT(success);
3208
3209 /* FIXME: If the reference ticks change then implement the
3210 * compensation by adding the difference to the
3211 * calculated ticks_to_expire.
3212 * The ticks current can change if there are overlapping
3213 * ticker expiry that update the ticks_current.
3214 * For now assert until the fix implementation is added.
3215 */
3216 LL_ASSERT((ticks_current == ticks_previous) || retry--);
3217
3218 LL_ASSERT(id != TICKER_NULL);
3219 } while (id != ticker_id);
3220
3221 /* Adjust ticks to expire based on remainder value */
3222 hal_ticker_remove_jitter(&ticks_to_expire, &remainder);
3223
3224 /* Store the ticks offset for population in other advertising primary
3225 * channel PDUs.
3226 */
3227 lll_aux->ticks_pri_pdu_offset = ticks_to_expire;
3228
3229 /* NOTE: as first primary channel PDU does not use remainder, the packet
3230 * timer is started one tick in advance to start the radio with
3231 * microsecond precision, hence compensate for the higher start_us value
3232 * captured at radio start of the first primary channel PDU.
3233 */
3234 lll_aux->ticks_pri_pdu_offset += 1U;
3235
3236 /* Store the microsecond remainder offset for population in other
3237 * advertising primary channel PDUs.
3238 */
3239 lll_aux->us_pri_pdu_offset = remainder;
3240
3241 /* Fill the aux offset in the first Primary channel PDU */
3242 /* FIXME: we are in ULL_LOW context, fill offset in LLL context? */
3243 pdu = lll_adv_data_latest_peek(&adv->lll);
3244 aux_ptr = ull_adv_aux_lll_offset_fill(pdu, ticks_to_expire, remainder,
3245 0U);
3246
3247 /* Process channel map update, if any */
3248 if (aux->chm_first != aux->chm_last) {
3249 /* Use channelMapNew */
3250 aux->chm_first = aux->chm_last;
3251 }
3252
3253 /* Calculate the radio channel to use */
3254 data_chan_map = aux->chm[aux->chm_first].data_chan_map;
3255 data_chan_count = aux->chm[aux->chm_first].data_chan_count;
3256 aux_ptr->chan_idx = lll_chan_sel_2(lll_aux->data_chan_counter,
3257 aux->data_chan_id,
3258 data_chan_map, data_chan_count);
3259
3260 ticks_now = ticker_ticks_now_get();
3261 ticks_elapsed = ticker_ticks_diff_get(ticks_now, ticks_current);
3262 ticks_to_start = MAX(adv->ull.ticks_active_to_start,
3263 adv->ull.ticks_prepare_to_start) -
3264 adv->ull.ticks_preempt_to_start;
3265 LL_ASSERT(ticks_elapsed < ticks_to_start);
3266 }
3267
ticker_op_cb(uint32_t status,void * param)3268 static void ticker_op_cb(uint32_t status, void *param)
3269 {
3270 *((uint32_t volatile *)param) = status;
3271 }
3272 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3273
ticker_cb(uint32_t ticks_at_expire,uint32_t ticks_drift,uint32_t remainder,uint16_t lazy,uint8_t force,void * param)3274 static void ticker_cb(uint32_t ticks_at_expire, uint32_t ticks_drift,
3275 uint32_t remainder, uint16_t lazy, uint8_t force,
3276 void *param)
3277 {
3278 static memq_link_t link;
3279 static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_aux_prepare};
3280 static struct lll_prepare_param p;
3281 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3282 struct ticker_ext_context *context = param;
3283 struct ll_adv_aux_set *aux = context->context;
3284 #else /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3285 struct ll_adv_aux_set *aux = param;
3286 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC || !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3287 struct lll_adv_aux *lll;
3288 uint32_t ret;
3289 uint8_t ref;
3290
3291 DEBUG_RADIO_PREPARE_A(1);
3292
3293 lll = &aux->lll;
3294
3295 /* Increment prepare reference count */
3296 ref = ull_ref_inc(&aux->ull);
3297 LL_ASSERT(ref);
3298
3299 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3300 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
3301 struct ll_adv_set *adv;
3302
3303 adv = HDR_LLL2ULL(lll->adv);
3304 if (adv->lll.sync) {
3305 struct lll_adv_sync *lll_sync = adv->lll.sync;
3306 struct ll_adv_sync_set *sync;
3307
3308 sync = HDR_LLL2ULL(adv->lll.sync);
3309 if (sync->is_started) {
3310 uint32_t ticks_to_expire;
3311 uint32_t sync_remainder_us;
3312
3313 LL_ASSERT(context->other_expire_info);
3314
3315 /* Reduce a tick for negative remainder and return positive remainder
3316 * value.
3317 */
3318 ticks_to_expire = context->other_expire_info->ticks_to_expire;
3319 sync_remainder_us = context->other_expire_info->remainder;
3320 hal_ticker_remove_jitter(&ticks_to_expire, &sync_remainder_us);
3321
3322 /* Add a tick for negative remainder and return positive remainder
3323 * value.
3324 */
3325 hal_ticker_add_jitter(&ticks_to_expire, &remainder);
3326
3327 /* Store the offset in us */
3328 lll_sync->us_adv_sync_pdu_offset = HAL_TICKER_TICKS_TO_US(ticks_to_expire) +
3329 sync_remainder_us - remainder;
3330
3331 /* store the lazy value */
3332 lll_sync->sync_lazy = context->other_expire_info->lazy;
3333 }
3334 }
3335 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
3336
3337 /* Process channel map update, if any */
3338 if (aux->chm_first != aux->chm_last) {
3339 /* Use channelMapNew */
3340 aux->chm_first = aux->chm_last;
3341 }
3342 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3343
3344 /* Append timing parameters */
3345 p.ticks_at_expire = ticks_at_expire;
3346 p.remainder = remainder;
3347 p.lazy = lazy;
3348 p.force = force;
3349 p.param = lll;
3350 mfy.param = &p;
3351
3352 /* Kick LLL prepare */
3353 ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
3354 TICKER_USER_ID_LLL, 0, &mfy);
3355 LL_ASSERT(!ret);
3356
3357 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && !defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
3358 struct ll_adv_set *adv;
3359
3360 adv = HDR_LLL2ULL(lll->adv);
3361 if (adv->lll.sync) {
3362 struct ll_adv_sync_set *sync;
3363
3364 sync = HDR_LLL2ULL(adv->lll.sync);
3365 if (sync->is_started) {
3366 sync->aux_remainder = remainder;
3367 ull_adv_sync_offset_get(adv);
3368 }
3369 }
3370 #endif /* CONFIG_BT_CTLR_ADV_PERIODIC && !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3371
3372 DEBUG_RADIO_PREPARE_A(1);
3373 }
3374
3375 #if defined(CONFIG_BT_CTLR_ADV_PERIODIC) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
ticker_update_op_cb(uint32_t status,void * param)3376 static void ticker_update_op_cb(uint32_t status, void *param)
3377 {
3378 LL_ASSERT(status == TICKER_STATUS_SUCCESS ||
3379 param == ull_disable_mark_get());
3380 }
3381 #endif /* !CONFIG_BT_CTLR_ADV_PERIODIC && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
3382
3383 #else /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
3384
init_reset(void)3385 static int init_reset(void)
3386 {
3387 return 0;
3388 }
3389 #endif /* !(CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
3390