zephyr/subsys/bluetooth/controller/ll_sw/ll_scan.c

111 lines
2.3 KiB
C

/*
* Copyright (c) 2016-2017 Nordic Semiconductor ASA
* Copyright (c) 2016 Vinayak Kariappa Chettimada
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <bluetooth/hci.h>
#include "util/util.h"
#include "util/mem.h"
#include "util/memq.h"
#include "pdu.h"
#include "lll.h"
#include "ctrl.h"
#include "ll.h"
#include "ll_filter.h"
static struct {
u16_t interval;
u16_t window;
#if defined(CONFIG_BT_CTLR_ADV_EXT)
u8_t type:4;
#else /* !CONFIG_BT_CTLR_ADV_EXT */
u8_t type:1;
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
u8_t own_addr_type:2;
u8_t filter_policy:2;
} ll_scan;
u8_t ll_scan_params_set(u8_t type, u16_t interval, u16_t window,
u8_t own_addr_type, u8_t filter_policy)
{
if (ll_scan_is_enabled(0)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
/* type value:
* 0000b - legacy 1M passive
* 0001b - legacy 1M active
* 0010b - Ext. 1M passive
* 0011b - Ext. 1M active
* 0100b - invalid
* 0101b - invalid
* 0110b - invalid
* 0111b - invalid
* 1000b - Ext. Coded passive
* 1001b - Ext. Coded active
*/
ll_scan.type = type;
ll_scan.interval = interval;
ll_scan.window = window;
ll_scan.own_addr_type = own_addr_type;
ll_scan.filter_policy = filter_policy;
return 0;
}
u8_t ll_scan_enable(u8_t enable)
{
u8_t rpa_gen = 0U;
u32_t status;
u32_t scan;
if (!enable) {
return radio_scan_disable(true);
}
scan = ll_scan_is_enabled(0);
/* Initiator and scanning are not supported */
if (scan & BIT(2)) {
return BT_HCI_ERR_CMD_DISALLOWED;
}
if (scan) {
/* Duplicate filtering is processed in the HCI layer */
return 0;
}
if (ll_scan.own_addr_type & 0x1) {
if (!mem_nz(ll_addr_get(1, NULL), BDADDR_SIZE)) {
return BT_HCI_ERR_INVALID_PARAM;
}
}
#if defined(CONFIG_BT_CTLR_PRIVACY)
ll_filters_scan_update(ll_scan.filter_policy);
if ((ll_scan.type & 0x1) &&
(ll_scan.own_addr_type == BT_ADDR_LE_PUBLIC_ID ||
ll_scan.own_addr_type == BT_ADDR_LE_RANDOM_ID)) {
/* Generate RPAs if required */
ll_rl_rpa_update(false);
rpa_gen = 1U;
}
#endif
status = radio_scan_enable(ll_scan.type, ll_scan.own_addr_type & 0x1,
ll_addr_get(ll_scan.own_addr_type & 0x1,
NULL),
ll_scan.interval, ll_scan.window,
ll_scan.filter_policy, rpa_gen,
FILTER_IDX_NONE);
return status;
}