Bluetooth: controller: split: Added Extended Scan Support

Updated implementation to support Extended Scan Parameters
and Extended Scan Enable.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-04-08 16:43:15 +05:30 committed by Carles Cufí
commit e941e72092

View file

@ -44,67 +44,152 @@
#include <soc.h> #include <soc.h>
#include "hal/debug.h" #include "hal/debug.h"
#define SCAN_HANDLE_1M 0
#define SCAN_HANDLE_PHY_CODED 1
static int init_reset(void); static int init_reset(void);
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy, static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t lazy,
void *param); void *param);
static uint8_t disable(uint8_t handle); static uint8_t disable(uint8_t handle);
#if defined(CONFIG_BT_CTLR_ADV_EXT)
#define BT_CTLR_SCAN_MAX 2
#else /* !CONFIG_BT_CTLR_ADV_EXT */
#define BT_CTLR_SCAN_MAX 1 #define BT_CTLR_SCAN_MAX 1
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
static struct ll_scan_set ll_scan[BT_CTLR_SCAN_MAX]; static struct ll_scan_set ll_scan[BT_CTLR_SCAN_MAX];
uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window, uint8_t ll_scan_params_set(uint8_t type, uint16_t interval, uint16_t window,
uint8_t own_addr_type, uint8_t filter_policy) uint8_t own_addr_type, uint8_t filter_policy)
{ {
struct ll_scan_set *scan; struct ll_scan_set *scan;
struct lll_scan *lll;
scan = ull_scan_is_disabled_get(0); scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
if (!scan) { if (!scan) {
return BT_HCI_ERR_CMD_DISALLOWED; return BT_HCI_ERR_CMD_DISALLOWED;
} }
#if defined(CONFIG_BT_CTLR_ADV_EXT)
struct ll_scan_set *scan_coded;
uint8_t phy;
scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
if (!scan_coded) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
phy = type >> 1;
if (phy & BT_HCI_LE_EXT_SCAN_PHY_CODED) {
scan = scan_coded;
}
lll = &scan->lll;
lll->phy = phy;
#else /* !CONFIG_BT_CTLR_ADV_EXT */
lll = &scan->lll;
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
scan->own_addr_type = own_addr_type; scan->own_addr_type = own_addr_type;
ull_scan_params_set(&scan->lll, type, interval, window, filter_policy); ull_scan_params_set(lll, type, interval, window, filter_policy);
return 0; return 0;
} }
uint8_t ll_scan_enable(uint8_t enable) uint8_t ll_scan_enable(uint8_t enable)
{ {
struct ll_scan_set *scan_coded = NULL;
struct ll_scan_set *scan; struct ll_scan_set *scan;
uint8_t own_addr_type = 0U;
uint8_t is_coded_phy = 0U;
uint8_t err;
if (!enable) { if (!enable) {
return disable(0); err = disable(SCAN_HANDLE_1M);
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
uint8_t err_coded;
err_coded = disable(SCAN_HANDLE_PHY_CODED);
if (!err_coded) {
err = 0U;
}
}
return err;
} }
scan = ull_scan_is_disabled_get(0); scan = ull_scan_is_disabled_get(SCAN_HANDLE_1M);
if (!scan) { if (!scan) {
return BT_HCI_ERR_CMD_DISALLOWED; return BT_HCI_ERR_CMD_DISALLOWED;
} }
if (scan->own_addr_type & 0x1) { if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
scan_coded = ull_scan_is_disabled_get(SCAN_HANDLE_PHY_CODED);
if (!scan_coded) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
own_addr_type = scan_coded->own_addr_type;
is_coded_phy = (scan_coded->lll.type >> 1) &
BT_HCI_LE_EXT_SCAN_PHY_CODED;
}
if ((IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && is_coded_phy &&
(own_addr_type & 0x1)) ||
(scan->own_addr_type & 0x1)) {
if (!mem_nz(ll_addr_get(1, NULL), BDADDR_SIZE)) { if (!mem_nz(ll_addr_get(1, NULL), BDADDR_SIZE)) {
return BT_HCI_ERR_INVALID_PARAM; return BT_HCI_ERR_INVALID_PARAM;
} }
} }
#if defined(CONFIG_BT_CTLR_PRIVACY) #if defined(CONFIG_BT_CTLR_PRIVACY)
struct lll_scan *lll = &scan->lll; struct lll_scan *lll;
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) && is_coded_phy) {
lll = &scan_coded->lll;
/* TODO: Privacy support in Advertising Extensions */
} else {
lll = &scan->lll;
own_addr_type = scan->own_addr_type;
}
ull_filter_scan_update(lll->filter_policy); ull_filter_scan_update(lll->filter_policy);
lll->rl_idx = FILTER_IDX_NONE; lll->rl_idx = FILTER_IDX_NONE;
lll->rpa_gen = 0; lll->rpa_gen = 0;
if ((lll->type & 0x1) && if ((lll->type & 0x1) &&
(scan->own_addr_type == BT_ADDR_LE_PUBLIC_ID || (own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
scan->own_addr_type == BT_ADDR_LE_RANDOM_ID)) { own_addr_type == BT_ADDR_LE_RANDOM_ID)) {
/* Generate RPAs if required */ /* Generate RPAs if required */
ull_filter_rpa_update(false); ull_filter_rpa_update(false);
lll->rpa_gen = 1; lll->rpa_gen = 1;
} }
#endif #endif
return ull_scan_enable(scan); if (!IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) ||
!is_coded_phy ||
((scan->lll.type >> 1) & BIT(0))) {
err = ull_scan_enable(scan);
if (err) {
return err;
}
}
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
is_coded_phy) {
err = ull_scan_enable(scan_coded);
if (err) {
return err;
}
}
return 0;
} }
int ull_scan_init(void) int ull_scan_init(void)
@ -152,11 +237,6 @@ void ull_scan_params_set(struct lll_scan *lll, uint8_t type, uint16_t interval,
* 1001b - Ext. Coded active * 1001b - Ext. Coded active
*/ */
lll->type = type; lll->type = type;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
lll->phy = type >> 1;
#endif /* CONFIG_BT_CTLR_ADV_EXT */
lll->filter_policy = filter_policy; lll->filter_policy = filter_policy;
lll->interval = interval; lll->interval = interval;
lll->ticks_window = HAL_TICKER_US_TO_TICKS((uint64_t)window * 625U); lll->ticks_window = HAL_TICKER_US_TO_TICKS((uint64_t)window * 625U);
@ -234,8 +314,10 @@ uint8_t ull_scan_enable(struct ll_scan_set *scan)
} }
#endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */ #endif /* CONFIG_BT_CENTRAL && CONFIG_BT_CTLR_SCHED_ADVANCED */
uint8_t handle = ull_scan_handle_get(scan);
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
TICKER_USER_ID_THREAD, TICKER_ID_SCAN_BASE, TICKER_USER_ID_THREAD, TICKER_ID_SCAN_BASE + handle,
ticks_anchor, 0, ticks_interval, ticks_anchor, 0, ticks_interval,
HAL_TICKER_REMAINDER((uint64_t)lll->interval * 625U), HAL_TICKER_REMAINDER((uint64_t)lll->interval * 625U),
TICKER_NULL_LAZY, TICKER_NULL_LAZY,