Bluetooth: controller: split: Add periodic adv ULL implementation
Add ULL implementation to perform periodic advertising. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
5ebbac32d9
commit
3eac6c3a52
15 changed files with 431 additions and 34 deletions
|
@ -31,6 +31,10 @@ if(CONFIG_BT_LL_SW_SPLIT)
|
|||
CONFIG_BT_CTLR_ADV_EXT
|
||||
ll_sw/ull_adv_aux.c
|
||||
)
|
||||
zephyr_library_sources_ifdef(
|
||||
CONFIG_BT_CTLR_ADV_PERIODIC
|
||||
ll_sw/ull_adv_sync.c
|
||||
)
|
||||
endif()
|
||||
if(CONFIG_BT_OBSERVER)
|
||||
zephyr_library_sources(
|
||||
|
|
|
@ -35,6 +35,10 @@ config BT_CTLR_PHY_UPDATE_SUPPORT
|
|||
config BT_CTLR_ADV_EXT_SUPPORT
|
||||
bool
|
||||
|
||||
config BT_CTLR_ADV_PERIODIC_SUPPORT
|
||||
depends on BT_CTLR_ADV_EXT_SUPPORT
|
||||
bool
|
||||
|
||||
config BT_CTLR_CHAN_SEL_2_SUPPORT
|
||||
bool
|
||||
|
||||
|
@ -95,6 +99,7 @@ config BT_LLL_VENDOR_NORDIC
|
|||
select BT_CTLR_PHY_UPDATE_SUPPORT if !SOC_SERIES_NRF51X || \
|
||||
BT_CTLR_PHY_2M_NRF
|
||||
select BT_CTLR_ADV_EXT_SUPPORT
|
||||
select BT_CTLR_ADV_PERIODIC_SUPPORT
|
||||
select BT_CTLR_CHAN_SEL_2_SUPPORT
|
||||
select BT_CTLR_MIN_USED_CHAN_SUPPORT
|
||||
select BT_CTLR_DTM_HCI_SUPPORT
|
||||
|
@ -448,13 +453,27 @@ config BT_CTLR_ADV_EXT
|
|||
Enable support for Bluetooth 5.0 LE Advertising Extensions in the
|
||||
Controller.
|
||||
|
||||
config BT_ADV_SET
|
||||
config BT_CTLR_ADV_SET
|
||||
int "LE Advertising Extensions Sets"
|
||||
depends on BT_CTLR_ADV_EXT
|
||||
default 1
|
||||
help
|
||||
Maximum supported advertising sets.
|
||||
|
||||
config BT_CTLR_ADV_PERIODIC
|
||||
bool "LE Periodic Advertising"
|
||||
depends on BT_CTLR_ADV_EXT
|
||||
help
|
||||
Enable support for Bluetooth 5.0 LE Periodic Advertising in the
|
||||
Controller.
|
||||
|
||||
config BT_CTLR_ADV_SYNC_SET
|
||||
int "LE Periodic Advertising Sets"
|
||||
depends on BT_CTLR_ADV_PERIODIC
|
||||
default 1
|
||||
help
|
||||
Maximum supported periodic advertising sets.
|
||||
|
||||
config BT_CTLR_DTM
|
||||
bool
|
||||
help
|
||||
|
|
|
@ -19,8 +19,10 @@ uint8_t ll_adv_params_set(uint8_t handle, uint16_t evt_prop, uint32_t interval,
|
|||
uint8_t direct_addr_type, uint8_t const *const direct_addr,
|
||||
uint8_t chan_map, uint8_t filter_policy, uint8_t *tx_pwr,
|
||||
uint8_t phy_p, uint8_t skip, uint8_t phy_s, uint8_t sid, uint8_t sreq);
|
||||
uint8_t ll_adv_data_set(uint16_t handle, uint8_t len, uint8_t const *const p_data);
|
||||
uint8_t ll_adv_scan_rsp_set(uint16_t handle, uint8_t len, uint8_t const *const p_data);
|
||||
uint8_t ll_adv_data_set(uint8_t handle, uint8_t len,
|
||||
uint8_t const *const p_data);
|
||||
uint8_t ll_adv_scan_rsp_set(uint8_t handle, uint8_t len,
|
||||
uint8_t const *const p_data);
|
||||
uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t *addr);
|
||||
uint8_t *ll_adv_aux_random_addr_get(uint8_t handle, uint8_t *addr);
|
||||
uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
|
||||
|
@ -31,6 +33,11 @@ uint16_t ll_adv_aux_max_data_length_get(void);
|
|||
uint8_t ll_adv_aux_set_count_get(void);
|
||||
uint8_t ll_adv_aux_set_remove(uint8_t handle);
|
||||
uint8_t ll_adv_aux_set_clear(void);
|
||||
uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval,
|
||||
uint16_t flags);
|
||||
uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
|
||||
uint8_t len, uint8_t *data);
|
||||
uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable);
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
|
||||
uint8_t own_addr_type, uint8_t direct_addr_type,
|
||||
|
@ -42,11 +49,11 @@ uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const p_data);
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
uint8_t ll_adv_enable(uint16_t handle, uint8_t enable,
|
||||
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
|
||||
uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry,
|
||||
uint8_t scan_window, uint8_t scan_delay);
|
||||
#else /* !CONFIG_BT_HCI_MESH_EXT */
|
||||
uint8_t ll_adv_enable(uint16_t handle, uint8_t enable);
|
||||
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable);
|
||||
#endif /* !CONFIG_BT_HCI_MESH_EXT */
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
uint8_t ll_adv_enable(uint8_t enable);
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
#include "pdu.h"
|
||||
#include "lll.h"
|
||||
|
||||
#include "lll_adv.h"
|
||||
#include "lll_scan.h"
|
||||
|
||||
#include "ull_adv_types.h"
|
||||
#include "ull_scan_types.h"
|
||||
#include "ull_adv_internal.h"
|
||||
#include "ull_scan_internal.h"
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
#define XON_BITMASK BIT(31) /* XTAL has been retained from previous prepare */
|
||||
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
|
||||
|
||||
#if defined(CONFIG_BT_BROADCASTER) && defined(CONFIG_BT_ADV_SET)
|
||||
#define BT_CTLR_ADV_MAX (CONFIG_BT_ADV_SET + 1)
|
||||
#if defined(CONFIG_BT_BROADCASTER) && defined(CONFIG_BT_CTLR_ADV_SET)
|
||||
#define BT_CTLR_ADV_MAX (CONFIG_BT_CTLR_ADV_SET + 1)
|
||||
#else
|
||||
#define BT_CTLR_ADV_MAX 1
|
||||
#endif
|
||||
|
@ -39,9 +39,20 @@ enum {
|
|||
TICKER_ID_ADV_BASE,
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
TICKER_ID_ADV_LAST = ((TICKER_ID_ADV_BASE) + (BT_CTLR_ADV_MAX) - 1),
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
TICKER_ID_ADV_AUX_BASE,
|
||||
TICKER_ID_ADV_AUX_LAST = ((TICKER_ID_ADV_AUX_BASE) +
|
||||
(CONFIG_BT_CTLR_ADV_SET) - 1),
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
#endif /* CONFIG_BT_BROADCASTER */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
TICKER_ID_ADV_SYNC_BASE,
|
||||
TICKER_ID_ADV_SYNC_LAST = ((TICKER_ID_ADV_SYNC_BASE) +
|
||||
(CONFIG_BT_CTLR_ADV_SYNC_SET) - 1),
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
|
||||
#if defined(CONFIG_BT_OBSERVER)
|
||||
TICKER_ID_SCAN_STOP,
|
||||
TICKER_ID_SCAN_BASE,
|
||||
|
|
|
@ -13,6 +13,15 @@ struct lll_adv_pdu {
|
|||
uint8_t pdu[DOUBLE_BUFFER_SIZE][PDU_AC_SIZE_MAX];
|
||||
};
|
||||
|
||||
struct lll_adv_sync {
|
||||
struct lll_hdr hdr;
|
||||
|
||||
uint8_t access_addr[4];
|
||||
uint8_t crc_init[3];
|
||||
|
||||
struct lll_adv_pdu data;
|
||||
};
|
||||
|
||||
struct lll_adv {
|
||||
struct lll_hdr hdr;
|
||||
|
||||
|
@ -43,6 +52,10 @@ struct lll_adv {
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
struct lll_adv_pdu aux_data;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
struct lll_adv_sync *sync;
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
|
@ -126,6 +139,25 @@ static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv *lll)
|
|||
{
|
||||
return (void *)lll->aux_data.pdu[lll->aux_data.last];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
static inline struct pdu_adv *lll_adv_sync_data_alloc(struct lll_adv_sync *lll,
|
||||
uint8_t *idx)
|
||||
{
|
||||
return lll_adv_pdu_alloc(&lll->data, idx);
|
||||
}
|
||||
|
||||
static inline void lll_adv_sync_data_enqueue(struct lll_adv_sync *lll,
|
||||
uint8_t idx)
|
||||
{
|
||||
lll_adv_pdu_enqueue(&lll->data, idx);
|
||||
}
|
||||
|
||||
static inline struct pdu_adv *lll_adv_sync_data_peek(struct lll_adv_sync *lll)
|
||||
{
|
||||
return (void *)lll->data.pdu[lll->data.last];
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
extern uint16_t ull_adv_lll_handle_get(struct lll_adv *lll);
|
||||
|
|
|
@ -55,4 +55,18 @@ static inline struct pdu_adv *lll_adv_aux_data_curr_get(struct lll_adv *lll)
|
|||
{
|
||||
return (void *)lll->aux_data.pdu[lll->aux_data.first];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
static inline struct pdu_adv *
|
||||
lll_adv_sync_data_latest_get(struct lll_adv_sync *lll, uint8_t *is_modified)
|
||||
{
|
||||
return lll_adv_pdu_latest_get(&lll->data, is_modified);
|
||||
}
|
||||
|
||||
static inline struct pdu_adv *
|
||||
lll_adv_sync_data_curr_get(struct lll_adv_sync *lll)
|
||||
{
|
||||
return (void *)lll->data.pdu[lll->data.first];
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
|
|
@ -52,11 +52,11 @@
|
|||
|
||||
#define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
|
||||
|
||||
inline struct ll_adv_set *ull_adv_set_get(uint16_t handle);
|
||||
inline struct ll_adv_set *ull_adv_set_get(uint8_t handle);
|
||||
inline uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
|
||||
|
||||
static int init_reset(void);
|
||||
static inline struct ll_adv_set *is_disabled_get(uint16_t handle);
|
||||
static inline struct ll_adv_set *is_disabled_get(uint8_t handle);
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
|
||||
void *param);
|
||||
static void ticker_op_update_cb(uint32_t status, void *params);
|
||||
|
@ -69,7 +69,7 @@ static void disabled_cb(void *param);
|
|||
static void conn_release(struct ll_adv_set *adv);
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
|
||||
static inline uint8_t disable(uint16_t handle);
|
||||
static inline uint8_t disable(uint8_t handle);
|
||||
|
||||
static struct ll_adv_set ll_adv[BT_CTLR_ADV_MAX];
|
||||
|
||||
|
@ -102,7 +102,7 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
|
|||
PDU_ADV_TYPE_SCAN_IND,
|
||||
PDU_ADV_TYPE_NONCONN_IND,
|
||||
PDU_ADV_TYPE_DIRECT_IND};
|
||||
uint16_t const handle = 0;
|
||||
uint8_t const handle = 0;
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
struct ll_adv_set *adv;
|
||||
|
@ -367,12 +367,12 @@ uint8_t ll_adv_params_set(uint16_t interval, uint8_t adv_type,
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
uint8_t ll_adv_data_set(uint16_t handle, uint8_t len, uint8_t const *const data)
|
||||
uint8_t ll_adv_data_set(uint8_t handle, uint8_t len, uint8_t const *const data)
|
||||
{
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
uint8_t ll_adv_data_set(uint8_t len, uint8_t const *const data)
|
||||
{
|
||||
const uint16_t handle = 0;
|
||||
const uint8_t handle = 0;
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
struct ll_adv_set *adv;
|
||||
struct pdu_adv *prev;
|
||||
|
@ -418,12 +418,13 @@ uint8_t ll_adv_data_set(uint8_t len, uint8_t const *const data)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
uint8_t ll_adv_scan_rsp_set(uint16_t handle, uint8_t len, uint8_t const *const data)
|
||||
uint8_t ll_adv_scan_rsp_set(uint8_t handle, uint8_t len,
|
||||
uint8_t const *const data)
|
||||
{
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const data)
|
||||
{
|
||||
const uint16_t handle = 0;
|
||||
const uint8_t handle = 0;
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
struct ll_adv_set *adv;
|
||||
struct pdu_adv *prev;
|
||||
|
@ -454,19 +455,23 @@ uint8_t ll_adv_scan_rsp_set(uint8_t len, uint8_t const *const data)
|
|||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
#if defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
uint8_t ll_adv_enable(uint16_t handle, uint8_t enable,
|
||||
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable,
|
||||
uint8_t at_anchor, uint32_t ticks_anchor, uint8_t retry,
|
||||
uint8_t scan_window, uint8_t scan_delay)
|
||||
{
|
||||
#else /* !CONFIG_BT_HCI_MESH_EXT */
|
||||
uint8_t ll_adv_enable(uint16_t handle, uint8_t enable)
|
||||
uint8_t ll_adv_enable(uint8_t handle, uint8_t enable)
|
||||
{
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
struct ll_adv_sync_set *sync;
|
||||
uint8_t sync_is_started = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
uint32_t ticks_anchor;
|
||||
#endif /* !CONFIG_BT_HCI_MESH_EXT */
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
uint8_t ll_adv_enable(uint8_t enable)
|
||||
{
|
||||
uint16_t const handle = 0;
|
||||
uint8_t const handle = 0;
|
||||
uint32_t ticks_anchor;
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
volatile uint32_t ret_cb = TICKER_STATUS_BUSY;
|
||||
|
@ -976,6 +981,25 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
&ll_adv_ticker_ext[handle]
|
||||
#endif /* CONFIG_BT_TICKER_EXT */
|
||||
);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
if (lll->sync) {
|
||||
struct lll_adv_sync *lll_sync = lll->sync;
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
if (sync->is_enabled && !sync->is_started) {
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret != TICKER_STATUS_SUCCESS) {
|
||||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
ret = ull_adv_sync_start(sync, ticks_anchor,
|
||||
&ret_cb);
|
||||
|
||||
sync_is_started = 1U;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
}
|
||||
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
|
@ -983,6 +1007,12 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
if (sync_is_started) {
|
||||
sync->is_started = sync_is_started;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
|
||||
adv->is_enabled = 1;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PRIVACY)
|
||||
|
@ -1026,7 +1056,7 @@ int ull_adv_init(void)
|
|||
|
||||
int ull_adv_reset(void)
|
||||
{
|
||||
uint16_t handle;
|
||||
uint8_t handle;
|
||||
int err;
|
||||
|
||||
for (handle = 0U; handle < BT_CTLR_ADV_MAX; handle++) {
|
||||
|
@ -1041,7 +1071,7 @@ int ull_adv_reset(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
inline struct ll_adv_set *ull_adv_set_get(uint16_t handle)
|
||||
inline struct ll_adv_set *ull_adv_set_get(uint8_t handle)
|
||||
{
|
||||
if (handle >= BT_CTLR_ADV_MAX) {
|
||||
return NULL;
|
||||
|
@ -1060,7 +1090,7 @@ uint16_t ull_adv_lll_handle_get(struct lll_adv *lll)
|
|||
return ull_adv_handle_get((void *)lll->hdr.parent);
|
||||
}
|
||||
|
||||
inline struct ll_adv_set *ull_adv_is_enabled_get(uint16_t handle)
|
||||
inline struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle)
|
||||
{
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
|
@ -1072,7 +1102,7 @@ inline struct ll_adv_set *ull_adv_is_enabled_get(uint16_t handle)
|
|||
return adv;
|
||||
}
|
||||
|
||||
uint32_t ull_adv_is_enabled(uint16_t handle)
|
||||
uint32_t ull_adv_is_enabled(uint8_t handle)
|
||||
{
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
|
@ -1084,7 +1114,7 @@ uint32_t ull_adv_is_enabled(uint16_t handle)
|
|||
return BIT(0);
|
||||
}
|
||||
|
||||
uint32_t ull_adv_filter_pol_get(uint16_t handle)
|
||||
uint32_t ull_adv_filter_pol_get(uint8_t handle)
|
||||
{
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
|
@ -1101,7 +1131,7 @@ static int init_reset(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline struct ll_adv_set *is_disabled_get(uint16_t handle)
|
||||
static inline struct ll_adv_set *is_disabled_get(uint8_t handle)
|
||||
{
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
|
@ -1184,7 +1214,7 @@ static void ticker_stop_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_
|
|||
void *param)
|
||||
{
|
||||
struct ll_adv_set *adv = param;
|
||||
uint16_t handle;
|
||||
uint8_t handle;
|
||||
uint32_t ret;
|
||||
|
||||
#if 0
|
||||
|
@ -1306,7 +1336,7 @@ static void conn_release(struct ll_adv_set *adv)
|
|||
}
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
|
||||
static inline uint8_t disable(uint16_t handle)
|
||||
static inline uint8_t disable(uint8_t handle)
|
||||
{
|
||||
volatile uint32_t ret_cb = TICKER_STATUS_BUSY;
|
||||
struct ll_adv_set *adv;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#include "hal/ccm.h"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2019 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
@ -8,16 +8,20 @@ int ull_adv_init(void);
|
|||
int ull_adv_reset(void);
|
||||
|
||||
/* Return ll_adv_set context (unconditional) */
|
||||
struct ll_adv_set *ull_adv_set_get(uint16_t handle);
|
||||
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(uint16_t handle);
|
||||
struct ll_adv_set *ull_adv_is_enabled_get(uint8_t handle);
|
||||
|
||||
/* Return flags, for now just: enabled */
|
||||
uint32_t ull_adv_is_enabled(uint16_t handle);
|
||||
uint32_t ull_adv_is_enabled(uint8_t handle);
|
||||
|
||||
/* Return filter policy used */
|
||||
uint32_t ull_adv_filter_pol_get(uint16_t handle);
|
||||
uint32_t ull_adv_filter_pol_get(uint8_t handle);
|
||||
|
||||
/* helper function to start periodic advertising */
|
||||
uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
||||
uint32_t volatile *ret_cb);
|
||||
|
|
260
subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
Normal file
260
subsys/bluetooth/controller/ll_sw/ull_adv_sync.c
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#include "hal/ticker.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/memq.h"
|
||||
#include "util/mayfly.h"
|
||||
|
||||
#include "ticker/ticker.h"
|
||||
|
||||
#include "pdu.h"
|
||||
#include "ll.h"
|
||||
#include "lll.h"
|
||||
#include "lll_vendor.h"
|
||||
#include "lll_adv.h"
|
||||
|
||||
#include "ull_adv_types.h"
|
||||
|
||||
#include "ull_internal.h"
|
||||
#include "ull_adv_internal.h"
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
||||
#define LOG_MODULE_NAME bt_ctlr_ull_adv_sync
|
||||
#include "common/log.h"
|
||||
#include <soc.h>
|
||||
#include "hal/debug.h"
|
||||
|
||||
static int init_reset(void);
|
||||
static inline struct ll_adv_sync_set *sync_acquire(void);
|
||||
static inline void sync_release(struct ll_adv_sync_set *sync);
|
||||
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param);
|
||||
|
||||
static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
|
||||
static void *adv_sync_free;
|
||||
|
||||
uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
||||
{
|
||||
struct lll_adv_sync *lll;
|
||||
struct ll_adv_sync_set *sync;
|
||||
struct ll_adv_set *adv;
|
||||
struct pdu_adv *pdu;
|
||||
|
||||
adv = ull_adv_is_enabled_get(handle);
|
||||
if (!adv) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
lll = adv->lll.sync;
|
||||
if (!lll) {
|
||||
sync = sync_acquire();
|
||||
if (!sync) {
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
lll = &sync->lll;
|
||||
adv->lll.sync = lll;
|
||||
} else {
|
||||
sync = (void *)HDR_LLL2EVT(lll);
|
||||
}
|
||||
|
||||
sync->interval = interval;
|
||||
|
||||
pdu = lll_adv_sync_data_peek(lll);
|
||||
pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
|
||||
pdu->rfu = 0U;
|
||||
pdu->chan_sel = 0U;
|
||||
pdu->tx_addr = 0U;
|
||||
pdu->rx_addr = 0U;
|
||||
|
||||
if (flags & BIT(6)) {
|
||||
/* TODO: add/remove Tx Power in AUX_SYNC_IND PDU */
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
|
||||
uint8_t len, uint8_t *data)
|
||||
{
|
||||
/* TODO */
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
|
||||
{
|
||||
struct lll_adv_sync *lll_sync;
|
||||
struct ll_adv_sync_set *sync;
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
adv = ull_adv_is_enabled_get(handle);
|
||||
if (!adv) {
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
lll_sync = adv->lll.sync;
|
||||
if (!lll_sync) {
|
||||
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
|
||||
}
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
|
||||
if (!enable) {
|
||||
/* TODO */
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* TODO: Check for periodic data being complete */
|
||||
|
||||
/* TODO: Check packet too long */
|
||||
|
||||
if (sync->is_enabled) {
|
||||
/* TODO: Enabling an already enabled advertising changes its
|
||||
* random address.
|
||||
*/
|
||||
} else {
|
||||
sync->is_enabled = 1U;
|
||||
}
|
||||
|
||||
if (!sync->is_started) {
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ull_adv_sync_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ull_adv_sync_reset(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
||||
uint32_t volatile *ret_cb)
|
||||
{
|
||||
uint32_t slot_us, ticks_slot_offset, ticks_slot_overhead;
|
||||
uint8_t sync_handle;
|
||||
uint32_t ret;
|
||||
|
||||
/* TODO: Calc AUX_SYNC_IND slot_us */
|
||||
slot_us = 0;
|
||||
|
||||
/* TODO: active_to_start feature port */
|
||||
sync->evt.ticks_active_to_start = 0;
|
||||
sync->evt.ticks_xtal_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
|
||||
sync->evt.ticks_preempt_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
|
||||
sync->evt.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
|
||||
|
||||
ticks_slot_offset = MAX(sync->evt.ticks_active_to_start,
|
||||
sync->evt.ticks_xtal_to_start);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
|
||||
ticks_slot_overhead = ticks_slot_offset;
|
||||
} else {
|
||||
ticks_slot_overhead = 0;
|
||||
}
|
||||
|
||||
sync_handle = sync_handle_get(sync);
|
||||
|
||||
*ret_cb = TICKER_STATUS_BUSY;
|
||||
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
|
||||
(TICKER_ID_ADV_SYNC_BASE + sync_handle),
|
||||
ticks_anchor, 0,
|
||||
(sync->evt.ticks_slot + ticks_slot_overhead),
|
||||
TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
|
||||
(sync->evt.ticks_slot + ticks_slot_overhead),
|
||||
ticker_cb, sync,
|
||||
ull_ticker_status_give, (void *)ret_cb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int init_reset(void)
|
||||
{
|
||||
/* Initialize adv sync pool. */
|
||||
mem_init(ll_adv_sync_pool, sizeof(struct ll_adv_sync_set),
|
||||
sizeof(ll_adv_sync_pool) / sizeof(struct ll_adv_sync_set),
|
||||
&adv_sync_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct ll_adv_sync_set *sync_acquire(void)
|
||||
{
|
||||
return mem_acquire(&adv_sync_free);
|
||||
}
|
||||
|
||||
static inline void sync_release(struct ll_adv_sync_set *sync)
|
||||
{
|
||||
mem_release(sync, &adv_sync_free);
|
||||
}
|
||||
|
||||
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync)
|
||||
{
|
||||
return mem_index_get(sync, ll_adv_sync_pool,
|
||||
sizeof(struct ll_adv_sync_set));
|
||||
}
|
||||
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_prepare};
|
||||
static struct lll_prepare_param p;
|
||||
struct ll_adv_sync_set *sync = param;
|
||||
struct lll_adv_sync *lll;
|
||||
uint32_t ret;
|
||||
uint8_t ref;
|
||||
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
|
||||
lll = &sync->lll;
|
||||
|
||||
/* Increment prepare reference count */
|
||||
ref = ull_ref_inc(&sync->ull);
|
||||
LL_ASSERT(ref);
|
||||
|
||||
/* Append timing parameters */
|
||||
p.ticks_at_expire = ticks_at_expire;
|
||||
p.remainder = remainder;
|
||||
p.lazy = lazy;
|
||||
p.param = lll;
|
||||
mfy.param = &p;
|
||||
|
||||
/* Kick LLL prepare */
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
|
||||
TICKER_USER_ID_LLL, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
}
|
|
@ -30,3 +30,14 @@ struct ll_adv_set {
|
|||
uint8_t id_addr[BDADDR_SIZE];
|
||||
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||
};
|
||||
|
||||
struct ll_adv_sync_set {
|
||||
struct evt_hdr evt;
|
||||
struct ull_hdr ull;
|
||||
struct lll_adv_sync lll;
|
||||
|
||||
uint16_t interval;
|
||||
|
||||
uint8_t is_enabled:1;
|
||||
uint8_t is_started:1;
|
||||
};
|
||||
|
|
|
@ -60,6 +60,7 @@ void ll_conn_release(struct ll_conn *conn);
|
|||
uint16_t ll_conn_handle_get(struct ll_conn *conn);
|
||||
struct ll_conn *ll_conn_get(uint16_t handle);
|
||||
struct ll_conn *ll_connected_get(uint16_t handle);
|
||||
void ll_tx_ack_put(uint16_t handle, struct node_tx *node_tx);
|
||||
int ull_conn_init(void);
|
||||
int ull_conn_reset(void);
|
||||
uint8_t ull_conn_chan_map_cpy(uint8_t *chan_map);
|
||||
|
|
|
@ -27,7 +27,6 @@ void *ll_pdu_rx_alloc_peek(uint8_t count);
|
|||
void *ll_pdu_rx_alloc(void);
|
||||
void ll_rx_put(memq_link_t *link, void *rx);
|
||||
void ll_rx_sched(void);
|
||||
void ll_tx_ack_put(uint16_t handle, struct node_tx *node_tx);
|
||||
void ull_ticker_status_give(uint32_t status, void *param);
|
||||
uint32_t ull_ticker_status_take(uint32_t ret, uint32_t volatile *ret_cb);
|
||||
void *ull_disable_mark(void *param);
|
||||
|
|
|
@ -136,9 +136,11 @@ int cmd_test_end(const struct shell *shell, size_t argc, char *argv[])
|
|||
#define AD_OP 0x03
|
||||
#define AD_FRAG_PREF 0x00
|
||||
|
||||
#if defined(CONFIG_BT_LL_SW_SPLIT)
|
||||
static const struct bt_data adv_data[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_NO_BREDR),
|
||||
};
|
||||
#endif
|
||||
|
||||
int cmd_advx(const struct shell *shell, size_t argc, char *argv[])
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue