Bluetooth: Controller: Update PDU header fields population
Updated the implementation to allow population of auxiliary
pointer field as necessary to append PDU chains.
Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c
index 7a7c2d7..fea6955 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_adv.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c
@@ -560,7 +560,8 @@
pri_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
}
if (pri_hdr->aux_ptr) {
- ull_adv_aux_ptr_fill(&pri_dptr, phy_s);
+ pri_dptr -= sizeof(struct pdu_adv_aux_ptr);
+ ull_adv_aux_ptr_fill((void *)pri_dptr, 0U, phy_s);
}
adv->lll.phy_s = phy_s;
#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
index 46ceabc..eb3c720 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
@@ -503,9 +503,9 @@
struct pdu_adv *pri_pdu, *pri_pdu_prev;
struct pdu_adv *sec_pdu_prev, *sec_pdu;
struct pdu_adv_adi *pri_adi, *sec_adi;
- struct pdu_adv_sync_info *sync_info;
uint8_t *pri_dptr, *pri_dptr_prev;
uint8_t *sec_dptr, *sec_dptr_prev;
+ struct pdu_adv_aux_ptr *aux_ptr;
uint8_t pri_len, sec_len_prev;
struct lll_adv_aux *lll_aux;
struct ll_adv_aux_set *aux;
@@ -527,12 +527,12 @@
pri_pdu_prev = lll_adv_data_peek(lll);
if (pri_pdu_prev->type != PDU_ADV_TYPE_EXT_IND) {
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
- uint8_t *val_ptr = value;
+ /* pick the data length */
+ ad_len = *((uint8_t *)value);
+ value = (uint8_t *)value + sizeof(uint8_t);
- ad_len = *val_ptr;
- val_ptr++;
-
- ad_data = (void *)sys_get_le32(val_ptr);
+ /* pick the reference to data */
+ (void)memcpy(&ad_data, value, sizeof(ad_data));
return ull_adv_data_set(adv, ad_len, ad_data);
}
@@ -625,6 +625,9 @@
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_ADVA) {
uint8_t own_addr_type = *(uint8_t *)value;
+ /* Move to next value */
+ value = (uint8_t *)value + sizeof(own_addr_type);
+
sec_pdu->tx_addr = own_addr_type & 0x1;
} else if (pri_hdr_prev.adv_addr) {
sec_pdu->tx_addr = pri_pdu_prev->tx_addr;
@@ -689,13 +692,37 @@
}
pri_hdr->aux_ptr = 1;
pri_dptr += sizeof(struct pdu_adv_aux_ptr);
+
+ if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) {
+ sec_hdr->aux_ptr = 1;
+ aux_ptr = NULL;
+
+ /* return the size of aux pointer structure */
+ *(uint8_t *)value = sizeof(struct pdu_adv_aux_ptr);
+ value = (uint8_t *)value + sizeof(uint8_t);
+
+ /* return the pointer to aux pointer struct inside the PDU
+ * buffer
+ */
+ memcpy(value, &sec_dptr, sizeof(sec_dptr));
+ value = (uint8_t *)value + sizeof(sec_dptr);
+ } else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_AUX_PTR) &&
+ sec_hdr_prev.aux_ptr) {
+ sec_hdr->aux_ptr = 1;
+ aux_ptr = (void *)sec_dptr_prev;
+ } else {
+ aux_ptr = NULL;
+ }
if (sec_hdr_prev.aux_ptr) {
sec_dptr_prev += sizeof(struct pdu_adv_aux_ptr);
-
- sec_hdr->aux_ptr = 1;
+ }
+ if (sec_hdr->aux_ptr) {
sec_dptr += sizeof(struct pdu_adv_aux_ptr);
}
+#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
+ struct pdu_adv_sync_info *sync_info;
+
/* No SyncInfo flag in primary channel PDU */
/* Add/Remove SyncInfo flag in secondary channel PDU */
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) {
@@ -704,25 +731,27 @@
/* return the size of sync info structure */
*(uint8_t *)value = sizeof(*sync_info);
- value = (uint8_t *)value + 1;
+ value = (uint8_t *)value + sizeof(uint8_t);
/* return the pointer to sync info struct inside the PDU
* buffer
*/
(void)memcpy(value, &sec_dptr, sizeof(sec_dptr));
value = (uint8_t *)value + sizeof(sec_dptr);
-
- sec_dptr += sizeof(*sync_info);
} else if (!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) &&
sec_hdr_prev.sync_info) {
sec_hdr->sync_info = 1;
sync_info = (void *)sec_dptr_prev;
-
- sec_dptr_prev += sizeof(*sync_info);
- sec_dptr += sizeof(*sync_info);
} else {
sync_info = NULL;
}
+ if (sec_hdr_prev.sync_info) {
+ sec_dptr_prev += sizeof(*sync_info);
+ }
+ if (sec_hdr->sync_info) {
+ sec_dptr += sizeof(*sync_info);
+ }
+#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
/* Tx Power flag */
if (pri_hdr_prev.tx_pwr) {
@@ -774,12 +803,12 @@
/* AD Data, add or remove */
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_AD_DATA) {
- uint8_t *val_ptr = value;
+ /* pick the data length */
+ ad_len = *((uint8_t *)value);
+ value = (uint8_t *)value + sizeof(uint8_t);
- ad_len = *val_ptr;
- val_ptr++;
-
- ad_data = (void *)sys_get_le32(val_ptr);
+ /* pick the reference to data */
+ (void)memcpy(&ad_data, value, sizeof(ad_data));
} else {
/* Calc the previous AD data length in auxiliary PDU */
ad_len = sec_pdu_prev->len - sec_len_prev;
@@ -842,12 +871,18 @@
if (pri_hdr_prev.aux_ptr) {
pri_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
}
- ull_adv_aux_ptr_fill(&pri_dptr, lll->phy_s);
+ pri_dptr -= sizeof(struct pdu_adv_aux_ptr);
+ ull_adv_aux_ptr_fill((void *)pri_dptr, 0U, lll->phy_s);
if (sec_hdr_prev.aux_ptr) {
sec_dptr_prev -= sizeof(struct pdu_adv_aux_ptr);
+ }
+ if (sec_hdr->aux_ptr) {
+ sec_dptr -= sizeof(struct pdu_adv_aux_ptr);
+ }
- ull_adv_aux_ptr_fill(&sec_dptr, lll->phy_s);
+ if (aux_ptr) {
+ memmove(sec_dptr, aux_ptr, sizeof(*aux_ptr));
}
/* ADI */
@@ -939,24 +974,28 @@
return 0;
}
-void ull_adv_aux_ptr_fill(uint8_t **dptr, uint8_t phy_s)
+void ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr *aux_ptr, uint32_t offs_us,
+ uint8_t phy_s)
{
- struct pdu_adv_aux_ptr *aux_ptr;
+ uint32_t offs;
/* NOTE: Channel Index and Aux Offset will be set on every advertiser's
* event prepare when finding the auxiliary event's ticker offset.
+ * Here we fill initial values.
*/
-
- *dptr -= sizeof(struct pdu_adv_aux_ptr);
- aux_ptr = (void *)*dptr;
-
aux_ptr->chan_idx = 0U;
aux_ptr->ca = (lll_clock_ppm_local_get() <= SCA_50_PPM) ?
SCA_VALUE_50_PPM : SCA_VALUE_500_PPM;
- aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
- aux_ptr->offs = 0U;
+ offs = offs_us / OFFS_UNIT_30_US;
+ if (!!(offs >> 13)) {
+ aux_ptr->offs = offs / (OFFS_UNIT_300_US / OFFS_UNIT_30_US);
+ aux_ptr->offs_units = OFFS_UNIT_VALUE_300_US;
+ } else {
+ aux_ptr->offs = offs;
+ aux_ptr->offs_units = OFFS_UNIT_VALUE_30_US;
+ }
aux_ptr->phy = find_lsb_set(phy_s) - 1;
}
diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h
index dbd8ed7..3bd2d58 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h
+++ b/subsys/bluetooth/controller/ll_sw/ull_adv_internal.h
@@ -159,7 +159,8 @@
}
/* helper function to fill the aux ptr structure in common ext adv payload */
-void ull_adv_aux_ptr_fill(uint8_t **dptr, uint8_t phy_s);
+void ull_adv_aux_ptr_fill(struct pdu_adv_aux_ptr *aux_ptr, uint32_t offs_us,
+ uint8_t phy_s);
/* helper function to handle adv aux done events */
void ull_adv_aux_done(struct node_rx_event_done *done);
diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
index 187eca8..8d4c984 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
@@ -1227,7 +1227,9 @@
memmove(ter_dptr, ter_dptr_prev,
sizeof(struct pdu_adv_aux_ptr));
} else {
- ull_adv_aux_ptr_fill(&ter_dptr, lll_sync->adv->phy_s);
+ ter_dptr -= sizeof(struct pdu_adv_aux_ptr);
+ ull_adv_aux_ptr_fill((void *)ter_dptr, 0U,
+ lll_sync->adv->phy_s);
}
}