Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions subsys/bluetooth/controller/hci/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -5019,9 +5019,13 @@ static void le_ext_adv_report(struct pdu_data *pdu_data,
sys_le16_to_cpu(si->offs),
si->offs_units,
sys_le16_to_cpu(si->interval),
(si->sca_chm[4] >> 5),
((si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &
PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK) >>
PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS),
si->sca_chm[0], si->sca_chm[1], si->sca_chm[2],
si->sca_chm[3], (si->sca_chm[4] & 0x3F),
si->sca_chm[3],
(si->sca_chm[PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET] &
~PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK),
sys_le32_to_cpu(si->aa),
si->crc_init[0], si->crc_init[1],
si->crc_init[2], sys_le16_to_cpu(si->evt_cntr));
Expand Down
5 changes: 5 additions & 0 deletions subsys/bluetooth/controller/ll_sw/pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,11 @@ struct pdu_adv_sync_info {
uint16_t evt_cntr;
} __packed;

#define PDU_SYNC_INFO_SCA_CHM_SCA_BYTE_OFFSET 4
#define PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS 5
#define PDU_SYNC_INFO_SCA_CHM_SCA_BIT_MASK \
(0x07 << (PDU_SYNC_INFO_SCA_CHM_SCA_BIT_POS))

enum pdu_adv_type {
PDU_ADV_TYPE_ADV_IND = 0x00,
PDU_ADV_TYPE_DIRECT_IND = 0x01,
Expand Down
15 changes: 13 additions & 2 deletions subsys/bluetooth/controller/ll_sw/ull_adv.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2020 Nordic Semiconductor ASA
* Copyright (c) 2016-2021 Nordic Semiconductor ASA
* Copyright (c) 2016 Vinayak Kariappa Chettimada
*
* SPDX-License-Identifier: Apache-2.0
Expand All @@ -10,6 +10,7 @@
#include <zephyr.h>
#include <soc.h>
#include <bluetooth/hci.h>
#include <sys/byteorder.h>

#include "hal/cpu.h"
#include "hal/ccm.h"
Expand Down Expand Up @@ -1208,14 +1209,24 @@ uint8_t ll_adv_enable(uint8_t enable)
if (lll->sync) {
sync = HDR_LLL2ULL(lll->sync);
if (sync->is_enabled && !sync->is_started) {
struct pdu_adv_sync_info *sync_info;
uint8_t value[1 + sizeof(sync_info)];
uint8_t err;

err = ull_adv_aux_hdr_set_clear(adv,
ULL_ADV_PDU_HDR_FIELD_SYNC_INFO,
0, NULL, NULL, &pri_idx);
0, value, NULL, &pri_idx);
if (err) {
return err;
}

/* First byte in the length-value encoded
* parameter is size of sync_info structure,
* followed by pointer to sync_info in the
* PDU.
*/
memcpy(&sync_info, &value[1], sizeof(sync_info));
ull_adv_sync_info_fill(sync, sync_info);
} else {
/* Do not start periodic advertising */
sync = NULL;
Expand Down
84 changes: 34 additions & 50 deletions subsys/bluetooth/controller/ll_sw/ull_adv_aux.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
* Copyright (c) 2017-2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -22,7 +22,6 @@
#include "pdu.h"

#include "lll.h"
#include "lll_clock.h"
#include "lll/lll_vendor.h"
#include "lll/lll_adv_types.h"
#include "lll_adv.h"
Expand All @@ -47,10 +46,6 @@ static int init_reset(void);
#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
static inline struct ll_adv_aux_set *aux_acquire(void);
static inline void aux_release(struct ll_adv_aux_set *aux);
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
static inline void sync_info_fill(struct lll_adv_sync *lll_sync,
uint8_t **dptr);
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
static void mfy_aux_offset_get(void *param);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
uint16_t lazy, uint8_t force, void *param);
Expand Down Expand Up @@ -93,7 +88,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
uint8_t const *const data)
{
struct ll_adv_set *adv;
uint8_t value[5];
uint8_t value[1 + sizeof(data)];
uint8_t *val_ptr;
uint8_t pri_idx;
uint8_t err;
Expand Down Expand Up @@ -122,7 +117,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui

val_ptr = value;
*val_ptr++ = len;
sys_put_le32((uint32_t)data, val_ptr);
memcpy(val_ptr, &data, sizeof(data));
err = ull_adv_aux_hdr_set_clear(adv, ULL_ADV_PDU_HDR_FIELD_AD_DATA,
0, value, NULL, &pri_idx);
if (err) {
Expand Down Expand Up @@ -441,6 +436,7 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
struct pdu_adv_ext_hdr *sec_hdr, sec_hdr_prev;
struct pdu_adv *pri_pdu, *pri_pdu_prev;
struct pdu_adv *sec_pdu_prev, *sec_pdu;
struct pdu_adv_sync_info *sync_info;
uint8_t *pri_dptr, *pri_dptr_prev;
uint8_t *sec_dptr, *sec_dptr_prev;
uint8_t pri_len, sec_len_prev;
Expand Down Expand Up @@ -611,16 +607,30 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,

/* 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) ||
(!(sec_hdr_rem_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) &&
sec_hdr_prev.sync_info)) {
if (sec_hdr_add_fields & ULL_ADV_PDU_HDR_FIELD_SYNC_INFO) {
sec_hdr->sync_info = 1;
}
if (sec_hdr_prev.sync_info) {
sec_dptr_prev += sizeof(struct pdu_adv_sync_info);
}
if (sec_hdr->sync_info) {
sec_dptr += sizeof(struct pdu_adv_sync_info);
sync_info = NULL;

/* return the size of sync info structure */
*(uint8_t *)value = sizeof(*sync_info);
value = (uint8_t *)value + 1;

/* return the pointer to sync info struct inside the PDU
* buffer
*/
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;
}

/* Tx Power flag */
Expand Down Expand Up @@ -724,10 +734,15 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
/* No SyncInfo in primary channel PDU */
/* Fill SyncInfo in secondary channel PDU */
if (sec_hdr_prev.sync_info) {
sec_dptr_prev -= sizeof(struct pdu_adv_sync_info);
sec_dptr_prev -= sizeof(*sync_info);
}

if (sec_hdr->sync_info) {
sync_info_fill(lll->sync, &sec_dptr);
sec_dptr -= sizeof(*sync_info);
}

if (sync_info) {
memmove(sec_dptr, sync_info, sizeof(*sync_info));
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */

Expand Down Expand Up @@ -1016,37 +1031,6 @@ inline uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux)
sizeof(struct ll_adv_aux_set));
}

#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
static inline void sync_info_fill(struct lll_adv_sync *lll_sync,
uint8_t **dptr)
{
struct ll_adv_sync_set *sync;
struct pdu_adv_sync_info *si;

*dptr -= sizeof(*si);
si = (void *)*dptr;

/* NOTE: sync offset and offset unit filled by secondary prepare */
si->offs_units = 0U;
/* If sync_info is part of ADV PDU the offs_adjust field
* is always set to 0.
*/
si->offs_adjust = 0U;
si->offs = 0U;

sync = HDR_LLL2ULL(lll_sync);
si->interval = sys_cpu_to_le16(sync->interval);
memcpy(si->sca_chm, lll_sync->data_chan_map,
sizeof(si->sca_chm));
si->sca_chm[4] &= 0x1f;
si->sca_chm[4] |= lll_clock_sca_local_get() << 5;
memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));

si->evt_cntr = 0U; /* NOTE: Filled by secondary prepare */
}
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */

static void mfy_aux_offset_get(void *param)
{
struct ll_adv_set *adv = param;
Expand Down
84 changes: 46 additions & 38 deletions subsys/bluetooth/controller/ll_sw/ull_adv_internal.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
* Copyright (c) 2017-2021 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -46,20 +46,24 @@ const uint8_t *ull_adv_pdu_update_addrs(struct ll_adv_set *adv,

#if defined(CONFIG_BT_CTLR_ADV_EXT)

/* Below are BT Spec v5.2, Vol 6, Part B Section 2.3.4 Table 2.12 defined */
#define ULL_ADV_PDU_HDR_FIELD_ADVA BIT(0)
#define ULL_ADV_PDU_HDR_FIELD_TARGETA BIT(1)
#define ULL_ADV_PDU_HDR_FIELD_CTE_INFO BIT(2)
#define ULL_ADV_PDU_HDR_FIELD_ADI BIT(3)
#define ULL_ADV_PDU_HDR_FIELD_AUX_PTR BIT(4)
#define ULL_ADV_PDU_HDR_FIELD_SYNC_INFO BIT(5)
#define ULL_ADV_PDU_HDR_FIELD_TX_POWER BIT(7)
#define ULL_ADV_PDU_HDR_FIELD_AD_DATA BIT(8)
#define ULL_ADV_PDU_HDR_FIELD_TX_POWER BIT(6)
#define ULL_ADV_PDU_HDR_FIELD_RFU BIT(7)
/* Below are implementation defined bit fields */
#define ULL_ADV_PDU_HDR_FIELD_ACAD BIT(8)
#define ULL_ADV_PDU_HDR_FIELD_AD_DATA BIT(9)

/* Helper type to store data for extended advertising
* header fields and extra data.
*/
struct adv_pdu_field_data {
uint8_t *field_data;
struct ull_adv_ext_hdr_data {
void *field_data;

#if defined(CONFIG_BT_CTLR_ADV_EXT_PDU_EXTRA_DATA_MEMORY)
void *extra_data;
Expand Down Expand Up @@ -107,39 +111,6 @@ uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
struct pdu_adv_adi *adi,
uint8_t *pri_idx);

/* helper function to release periodic advertising instance */
void ull_adv_sync_release(struct ll_adv_sync_set *sync);

/* helper function to allocate new PDU data for AUX_SYNC_IND and return
* previous and new PDU for further processing.
*/
uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
struct adv_pdu_field_data *data,
struct pdu_adv **ter_pdu_prev,
struct pdu_adv **ter_pdu_new,
void **extra_data_prev,
void **extra_data_new,
uint8_t *ter_idx);

/* helper function to set/clear common extended header format fields
* for AUX_SYNC_IND PDU.
*/
uint8_t ull_adv_sync_pdu_set_clear(struct lll_adv_sync *lll_sync,
struct pdu_adv *ter_pdu_prev,
struct pdu_adv *ter_pdu,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
struct adv_pdu_field_data *data);

/* helper function to update extra_data field */
void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
void *extra_data_new,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
void *data);

/* helper function to calculate common ext adv payload header length and
* adjust the data pointer.
* NOTE: This function reverts the header data pointer if there is no
Expand Down Expand Up @@ -180,10 +151,47 @@ uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
struct ll_adv_sync_set *sync,
uint32_t ticks_anchor);

/* helper function to release periodic advertising instance */
void ull_adv_sync_release(struct ll_adv_sync_set *sync);

/* helper function to fill initial value of sync_info structure */
void ull_adv_sync_info_fill(struct ll_adv_sync_set *sync,
struct pdu_adv_sync_info *si);

/* helper function to update periodic advertising event length */
void ull_adv_sync_update(struct ll_adv_sync_set *sync, uint32_t slot_plus_us,
uint32_t slot_minus_us);

/* helper function to allocate new PDU data for AUX_SYNC_IND and return
* previous and new PDU for further processing.
*/
uint8_t ull_adv_sync_pdu_alloc(struct ll_adv_set *adv,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
struct ull_adv_ext_hdr_data *hdr_data,
struct pdu_adv **ter_pdu_prev,
struct pdu_adv **ter_pdu_new,
void **extra_data_prev,
void **extra_data_new,
uint8_t *ter_idx);

/* helper function to set/clear common extended header format fields
* for AUX_SYNC_IND PDU.
*/
uint8_t ull_adv_sync_pdu_set_clear(struct lll_adv_sync *lll_sync,
struct pdu_adv *ter_pdu_prev,
struct pdu_adv *ter_pdu,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
struct ull_adv_ext_hdr_data *hdr_data);

/* helper function to update extra_data field */
void ull_adv_sync_extra_data_set_clear(void *extra_data_prev,
void *extra_data_new,
uint16_t hdr_add_fields,
uint16_t hdr_rem_fields,
void *data);

/* helper function to schedule a mayfly to get sync offset */
void ull_adv_sync_offset_get(struct ll_adv_set *adv);

Expand Down
Loading