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