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