355 lines
13 KiB
C
355 lines
13 KiB
C
/*
|
|
* Copyright (c) 2017-2021 Nordic Semiconductor ASA
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
|
|
|
|
/* Bitmask value returned by ull_adv_is_enabled() */
|
|
#define ULL_ADV_ENABLED_BITMASK_ENABLED BIT(0)
|
|
|
|
/* Helper defined to check if Extended Advertising HCI commands used */
|
|
#define LL_ADV_CMDS_ANY 0 /* Any advertising cmd/evt allowed */
|
|
#define LL_ADV_CMDS_LEGACY 1 /* Only legacy advertising cmd/evt allowed */
|
|
#define LL_ADV_CMDS_EXT 2 /* Only extended advertising cmd/evt allowed */
|
|
|
|
/* Helper function to check if Extended Advertising HCI commands used */
|
|
int ll_adv_cmds_is_ext(void);
|
|
|
|
/* Helper functions to initialise and reset ull_adv module */
|
|
int ull_adv_init(void);
|
|
int ull_adv_reset(void);
|
|
int ull_adv_reset_finalize(void);
|
|
|
|
/* Return ll_adv_set context (unconditional) */
|
|
struct ll_adv_set *ull_adv_set_get(uint8_t handle);
|
|
|
|
/* Return the adv set handle given the adv set instance */
|
|
uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
|
|
|
|
/* Return ll_adv_set context if enabled */
|
|
struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle);
|
|
|
|
/* Return enabled status of a set */
|
|
int ull_adv_is_enabled(uint8_t handle);
|
|
|
|
/* Return filter policy used */
|
|
uint32_t ull_adv_filter_pol_get(uint8_t handle);
|
|
|
|
/* Return ll_adv_set context if created */
|
|
struct ll_adv_set *ull_adv_is_created_get(uint8_t handle);
|
|
|
|
/* Helper function to construct AD data */
|
|
uint8_t ull_adv_data_set(struct ll_adv_set *adv, uint8_t len,
|
|
uint8_t const *const data);
|
|
|
|
/* Helper function to construct SR data */
|
|
uint8_t ull_scan_rsp_set(struct ll_adv_set *adv, uint8_t len,
|
|
uint8_t const *const data);
|
|
|
|
/* Update AdvA and TgtA (if application) in advertising PDU */
|
|
const uint8_t *ull_adv_pdu_update_addrs(struct ll_adv_set *adv,
|
|
struct pdu_adv *pdu);
|
|
|
|
/* Helper to update primary channel advertising event time reservation */
|
|
uint8_t ull_adv_time_update(struct ll_adv_set *adv, struct pdu_adv *pdu,
|
|
struct pdu_adv *pdu_scan);
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_CTLR_JIT_SCHEDULING)
|
|
/* helper function to handle adv done events */
|
|
void ull_adv_done(struct node_rx_event_done *done);
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT || CONFIG_BT_CTLR_JIT_SCHEDULING */
|
|
|
|
/* Enumeration provides flags for management of memory for extra_data
|
|
* related with advertising PDUs.
|
|
*/
|
|
enum ull_adv_pdu_extra_data_flag {
|
|
/* Allocate extra_data memory if it was available in former PDU */
|
|
ULL_ADV_PDU_EXTRA_DATA_ALLOC_IF_EXIST,
|
|
/* Allocate extra_data memory no matter if it was available */
|
|
ULL_ADV_PDU_EXTRA_DATA_ALLOC_ALWAYS,
|
|
/* Never allocate new memory for extra_data */
|
|
ULL_ADV_PDU_EXTRA_DATA_ALLOC_NEVER
|
|
};
|
|
|
|
/* Helper functions to initialise and reset ull_adv_aux module */
|
|
int ull_adv_aux_init(void);
|
|
int ull_adv_aux_reset_finalize(void);
|
|
|
|
/* Return the aux set handle given the aux set instance */
|
|
uint8_t ull_adv_aux_handle_get(struct ll_adv_aux_set *aux);
|
|
|
|
/* Helper function to apply Channel Map Update for auxiliary PDUs */
|
|
uint8_t ull_adv_aux_chm_update(void);
|
|
|
|
/* helper function to initialize event timings */
|
|
uint32_t ull_adv_aux_evt_init(struct ll_adv_aux_set *aux,
|
|
uint32_t *ticks_anchor);
|
|
|
|
/* helper function to start auxiliary advertising */
|
|
uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
|
|
uint32_t ticks_slot_overhead);
|
|
|
|
/* helper function to stop auxiliary advertising */
|
|
int ull_adv_aux_stop(struct ll_adv_aux_set *aux);
|
|
|
|
/* helper function to acquire and initialize auxiliary advertising instance */
|
|
struct ll_adv_aux_set *ull_adv_aux_acquire(struct lll_adv *lll);
|
|
|
|
/* helper function to release auxiliary advertising instance */
|
|
void ull_adv_aux_release(struct ll_adv_aux_set *aux);
|
|
|
|
/* helper function to give the auxiliary context */
|
|
struct ll_adv_aux_set *ull_adv_aux_get(uint8_t handle);
|
|
|
|
/* helper function to return time reservation for auxiliary PDU */
|
|
uint32_t ull_adv_aux_time_get(const struct ll_adv_aux_set *aux, uint8_t pdu_len,
|
|
uint8_t pdu_scan_len);
|
|
|
|
/* helper function to schedule a mayfly to get aux offset */
|
|
void ull_adv_aux_offset_get(struct ll_adv_set *adv);
|
|
|
|
/* Below are BT Spec v5.2, Vol 6, Part B Section 2.3.4 Table 2.12 defined */
|
|
#define ULL_ADV_PDU_HDR_FIELD_NONE 0
|
|
#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(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)
|
|
#define ULL_ADV_PDU_HDR_FIELD_AD_DATA_APPEND BIT(10)
|
|
|
|
/* helper defined for field offsets in the hdr_set_clear interfaces */
|
|
#define ULL_ADV_HDR_DATA_LEN_OFFSET 0
|
|
#define ULL_ADV_HDR_DATA_LEN_SIZE 1
|
|
#define ULL_ADV_HDR_DATA_CTE_INFO_OFFSET 0
|
|
#define ULL_ADV_HDR_DATA_CTE_INFO_SIZE (sizeof(struct pdu_cte_info))
|
|
#define ULL_ADV_HDR_DATA_ADI_PTR_OFFSET 1
|
|
#define ULL_ADV_HDR_DATA_ADI_PTR_SIZE (sizeof(uint8_t *))
|
|
#define ULL_ADV_HDR_DATA_AUX_PTR_PTR_OFFSET 1
|
|
#define ULL_ADV_HDR_DATA_AUX_PTR_PTR_SIZE (sizeof(uint8_t *))
|
|
#define ULL_ADV_HDR_DATA_ACAD_PTR_OFFSET 1
|
|
#define ULL_ADV_HDR_DATA_ACAD_PTR_SIZE (sizeof(uint8_t *))
|
|
#define ULL_ADV_HDR_DATA_DATA_PTR_OFFSET 1
|
|
#define ULL_ADV_HDR_DATA_DATA_PTR_SIZE (sizeof(uint8_t *))
|
|
|
|
/* helper function to set/clear common extended header format fields */
|
|
uint8_t ull_adv_aux_hdr_set_clear(struct ll_adv_set *adv,
|
|
uint16_t sec_hdr_add_fields,
|
|
uint16_t sec_hdr_rem_fields,
|
|
void *value,
|
|
uint8_t *pri_idx, uint8_t *sec_idx);
|
|
|
|
/* helper function to set/clear common extended header format fields for
|
|
* auxiliary PDU
|
|
*/
|
|
uint8_t 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);
|
|
|
|
/* helper to initialize extended advertising PDU */
|
|
void ull_adv_sync_pdu_init(struct pdu_adv *pdu, uint8_t ext_hdr_flags,
|
|
uint8_t phy_s, uint8_t phy_flags,
|
|
struct pdu_cte_info *cte_info);
|
|
|
|
/* helper to add cte_info field to extended advertising header */
|
|
uint8_t ull_adv_sync_pdu_cte_info_set(struct pdu_adv *pdu, const struct pdu_cte_info *cte_info);
|
|
|
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
|
/* notify adv_set that an aux instance has been created for it */
|
|
void ull_adv_aux_created(struct ll_adv_set *adv);
|
|
|
|
/* helper to get information whether ADI field is available in extended advertising PDU */
|
|
static inline bool ull_adv_sync_pdu_had_adi(const struct pdu_adv *pdu)
|
|
{
|
|
return pdu->adv_ext_ind.ext_hdr.adi;
|
|
}
|
|
/* 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
|
|
* header fields flags set, and hence no header fields have been
|
|
* populated.
|
|
*/
|
|
static inline uint8_t
|
|
ull_adv_aux_hdr_len_calc(struct pdu_adv_com_ext_adv *com_hdr, uint8_t **dptr)
|
|
{
|
|
uint8_t len;
|
|
|
|
len = *dptr - (uint8_t *)com_hdr;
|
|
if (len <= (PDU_AC_EXT_HEADER_SIZE_MIN +
|
|
sizeof(struct pdu_adv_ext_hdr))) {
|
|
len = PDU_AC_EXT_HEADER_SIZE_MIN;
|
|
*dptr = (uint8_t *)com_hdr + len;
|
|
}
|
|
|
|
return len;
|
|
}
|
|
|
|
/* helper function to fill common ext adv payload header length */
|
|
static inline void
|
|
ull_adv_aux_hdr_len_fill(struct pdu_adv_com_ext_adv *com_hdr, uint8_t len)
|
|
{
|
|
com_hdr->ext_hdr_len = len - PDU_AC_EXT_HEADER_SIZE_MIN;
|
|
}
|
|
|
|
/* notify adv_aux_set that a sync instance has been started/stopped for it */
|
|
void ull_adv_sync_started_stopped(struct ll_adv_aux_set *aux);
|
|
|
|
/* notify adv_sync_set that an iso instance has been created for it */
|
|
void ull_adv_sync_iso_created(struct ll_adv_sync_set *sync);
|
|
|
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
|
|
|
/* helper function to get next unique DID value */
|
|
uint16_t ull_adv_aux_did_next_unique_get(uint8_t sid);
|
|
|
|
/* helper function to fill the aux ptr structure in common ext adv payload */
|
|
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);
|
|
|
|
/* helper function to duplicate chain PDUs */
|
|
void 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);
|
|
int ull_adv_sync_init(void);
|
|
int ull_adv_sync_reset(void);
|
|
int ull_adv_sync_reset_finalize(void);
|
|
|
|
/* Return ll_adv_sync_set context (unconditional) */
|
|
struct ll_adv_sync_set *ull_adv_sync_get(uint8_t handle);
|
|
|
|
/* Return the aux set handle given the sync set instance */
|
|
uint16_t ull_adv_sync_handle_get(const struct ll_adv_sync_set *sync);
|
|
|
|
/* helper function to release periodic advertising instance */
|
|
void ull_adv_sync_release(struct ll_adv_sync_set *sync);
|
|
|
|
/* helper function to return event time reservation */
|
|
uint32_t ull_adv_sync_time_get(const struct ll_adv_sync_set *sync,
|
|
uint8_t pdu_len);
|
|
|
|
/* helper function to calculate ticks_slot and return slot overhead */
|
|
uint32_t ull_adv_sync_evt_init(struct ll_adv_set *adv,
|
|
struct ll_adv_sync_set *sync,
|
|
struct pdu_adv *pdu);
|
|
|
|
/* helper function to start periodic advertising */
|
|
uint32_t ull_adv_sync_start(struct ll_adv_set *adv,
|
|
struct ll_adv_sync_set *sync,
|
|
uint32_t ticks_anchor,
|
|
uint32_t ticks_slot_overhead);
|
|
|
|
/* helper function to update periodic advertising event time reservation */
|
|
uint8_t ull_adv_sync_time_update(struct ll_adv_sync_set *sync,
|
|
struct pdu_adv *pdu);
|
|
|
|
/* helper function to initial channel map update indications */
|
|
uint8_t ull_adv_sync_chm_update(void);
|
|
|
|
/* helper function to cleanup after channel map update indications complete */
|
|
void ull_adv_sync_chm_complete(struct node_rx_pdu *rx);
|
|
|
|
/* 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 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,
|
|
enum ull_adv_pdu_extra_data_flag extra_data_flags,
|
|
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 copy PDU(s) content from prev to new PDU */
|
|
uint8_t ull_adv_sync_duplicate(const struct pdu_adv *pdu_prev, struct pdu_adv *pdu_new);
|
|
|
|
/* helper function to remove an entry with matching type from ACAD */
|
|
uint8_t ull_adv_sync_remove_from_acad(struct lll_adv_sync *lll_sync,
|
|
struct pdu_adv *pdu_prev,
|
|
struct pdu_adv *pdu,
|
|
uint8_t ad_type);
|
|
|
|
/* helper function to get a pointer to the ACAD and its length */
|
|
uint8_t *ull_adv_sync_get_acad(struct pdu_adv *pdu, uint8_t *acad_len);
|
|
|
|
/* helper function to add some new adv data to the ACAD */
|
|
uint8_t ull_adv_sync_add_to_acad(struct lll_adv_sync *lll_sync,
|
|
struct pdu_adv *pdu_prev,
|
|
struct pdu_adv *pdu,
|
|
const uint8_t *new_ad,
|
|
uint8_t new_ad_len);
|
|
|
|
#if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
|
|
uint8_t ull_adv_sync_add_cteinfo(struct lll_adv_sync *lll_sync,
|
|
struct pdu_adv *pdu_prev,
|
|
struct pdu_adv *pdu,
|
|
const struct pdu_cte_info *cte_info,
|
|
uint8_t cte_count);
|
|
uint8_t ull_adv_sync_remove_cteinfo(struct lll_adv_sync *lll_sync,
|
|
struct pdu_adv *pdu_prev,
|
|
struct pdu_adv *pdu);
|
|
#endif /* ull_adv_sync_add_cteinfo */
|
|
|
|
/* 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);
|
|
|
|
int ull_adv_iso_init(void);
|
|
int ull_adv_iso_reset(void);
|
|
|
|
/* Return ll_adv_iso_set context (unconditional) */
|
|
struct ll_adv_iso_set *ull_adv_iso_get(uint8_t handle);
|
|
|
|
/* helper function to initial channel map update indications */
|
|
uint8_t ull_adv_iso_chm_update(void);
|
|
|
|
/* helper function to cleanup after channel map update complete */
|
|
void ull_adv_iso_chm_complete(struct node_rx_pdu *rx);
|
|
|
|
/* helper function to schedule a mayfly to get BIG offset */
|
|
void ull_adv_iso_offset_get(struct ll_adv_sync_set *sync);
|
|
|
|
/* helper function to handle adv ISO done BIG complete events */
|
|
void ull_adv_iso_done_complete(struct node_rx_event_done *done);
|
|
|
|
/* helper function to handle adv ISO done BIG terminate events */
|
|
void ull_adv_iso_done_terminate(struct node_rx_event_done *done);
|
|
|
|
/* helper function to return adv_iso instance */
|
|
struct ll_adv_iso_set *ull_adv_iso_by_stream_get(uint16_t handle);
|
|
|
|
/* helper function to return adv_iso stream instance */
|
|
struct lll_adv_iso_stream *ull_adv_iso_stream_get(uint16_t handle);
|
|
|
|
/* helper function to release stream instances */
|
|
void ull_adv_iso_stream_release(struct ll_adv_iso_set *adv_iso);
|
|
|
|
/* helper function to return time reservation for Broadcast ISO event */
|
|
uint32_t ull_adv_iso_max_time_get(const struct ll_adv_iso_set *adv_iso);
|
|
|
|
#if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
|
|
/* helper function to release unused DF configuration memory */
|
|
void ull_df_adv_cfg_release(struct lll_df_adv_cfg *df_adv_cfg);
|
|
#endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
|