Bluetooth: controller: Implement scan duplicate filter
Implement the controller's ability to drop duplicate advertising reports when instructed by the Host. Jira: ZEP-1246 Change-Id: I2d1b7abf1ed950dde705e5df30a858c595f3834c Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
7c22073195
commit
27e83660ff
3 changed files with 105 additions and 6 deletions
|
@ -82,6 +82,14 @@ config BLUETOOTH_CONTROLLER_RX_PRIO_STACK_SIZE
|
|||
int
|
||||
default 320
|
||||
|
||||
config BLUETOOTH_CONTROLLER_DUP_FILTER_LEN
|
||||
prompt "Number of addresses in the scan duplicate filter"
|
||||
int
|
||||
default 16
|
||||
help
|
||||
Set the number of unique BLE addresses that can be filtered as
|
||||
duplicates while scanning.
|
||||
|
||||
comment "BLE Controller features"
|
||||
|
||||
config BLUETOOTH_CONTROLLER_LE_PING
|
||||
|
|
|
@ -35,6 +35,17 @@
|
|||
*/
|
||||
static uint16_t _opcode;
|
||||
|
||||
#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
/* Scan duplicate filter */
|
||||
struct dup {
|
||||
uint8_t mask;
|
||||
bt_addr_le_t addr;
|
||||
};
|
||||
static struct dup dup_filter[CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN];
|
||||
static int32_t dup_count;
|
||||
static uint32_t dup_curr;
|
||||
#endif
|
||||
|
||||
static void evt_create(struct net_buf *buf, uint8_t evt, uint8_t len)
|
||||
{
|
||||
struct bt_hci_evt_hdr *hdr;
|
||||
|
@ -143,6 +154,10 @@ static void reset(struct net_buf *buf, struct net_buf **evt)
|
|||
|
||||
ll_reset();
|
||||
|
||||
#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
dup_count = -1;
|
||||
#endif
|
||||
|
||||
ccst = cmd_complete(evt, sizeof(*ccst));
|
||||
ccst->status = 0x00;
|
||||
}
|
||||
|
@ -411,6 +426,15 @@ static void le_set_scan_enable(struct net_buf *buf, struct net_buf **evt)
|
|||
struct bt_hci_evt_cc_status *ccst;
|
||||
uint32_t status;
|
||||
|
||||
#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
/* initialize duplicate filtering */
|
||||
if (cmd->enable && cmd->filter_dup) {
|
||||
dup_count = 0;
|
||||
dup_curr = 0;
|
||||
} else {
|
||||
dup_count = -1;
|
||||
}
|
||||
#endif
|
||||
status = ll_scan_enable(cmd->enable);
|
||||
|
||||
ccst = cmd_complete(evt, sizeof(*ccst));
|
||||
|
@ -973,6 +997,46 @@ static void le_advertising_report(struct pdu_data *pdu_data, uint8_t *b,
|
|||
uint8_t data_len;
|
||||
uint8_t *rssi;
|
||||
uint8_t info_len;
|
||||
int i;
|
||||
|
||||
#if CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
/* check for duplicate filtering */
|
||||
if (dup_count >= 0) {
|
||||
for (i = 0; i < dup_count; i++) {
|
||||
if (!memcmp(&adv->payload.adv_ind.addr[0],
|
||||
&dup_filter[i].addr.a.val[0],
|
||||
sizeof(bt_addr_t)) &&
|
||||
adv->tx_addr == dup_filter[i].addr.type) {
|
||||
|
||||
if (dup_filter[i].mask & BIT(adv->type)) {
|
||||
/* duplicate found */
|
||||
return;
|
||||
}
|
||||
/* report different adv types */
|
||||
dup_filter[i].mask |= BIT(adv->type);
|
||||
goto fill_report;
|
||||
}
|
||||
}
|
||||
|
||||
/* insert into the duplicate filter */
|
||||
memcpy(&dup_filter[dup_curr].addr.a.val[0],
|
||||
&adv->payload.adv_ind.addr[0], sizeof(bt_addr_t));
|
||||
dup_filter[dup_curr].addr.type = adv->tx_addr;
|
||||
dup_filter[dup_curr].mask = BIT(adv->type);
|
||||
|
||||
if (dup_count < CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN) {
|
||||
dup_count++;
|
||||
dup_curr = dup_count;
|
||||
} else {
|
||||
dup_curr++;
|
||||
}
|
||||
|
||||
if (dup_curr == CONFIG_BLUETOOTH_CONTROLLER_DUP_FILTER_LEN) {
|
||||
dup_curr = 0;
|
||||
}
|
||||
}
|
||||
fill_report:
|
||||
#endif
|
||||
|
||||
if (adv->type != PDU_ADV_TYPE_DIRECT_IND) {
|
||||
data_len = (adv->len - BDADDR_SIZE);
|
||||
|
|
|
@ -566,11 +566,20 @@ static int cmd_init(int argc, char *argv[])
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void cmd_active_scan_on(void)
|
||||
static void cmd_active_scan_on(int dups)
|
||||
{
|
||||
int err;
|
||||
struct bt_le_scan_param param = {
|
||||
.type = BT_HCI_LE_SCAN_PASSIVE,
|
||||
.filter_dup = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE,
|
||||
.interval = BT_GAP_SCAN_FAST_INTERVAL,
|
||||
.window = BT_GAP_SCAN_FAST_WINDOW };
|
||||
|
||||
err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
|
||||
if (dups >= 0) {
|
||||
param.filter_dup = dups;
|
||||
}
|
||||
|
||||
err = bt_le_scan_start(¶m, device_found);
|
||||
if (err) {
|
||||
printk("Bluetooth set active scan failed (err %d)\n", err);
|
||||
} else {
|
||||
|
@ -578,7 +587,7 @@ static void cmd_active_scan_on(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void cmd_passive_scan_on(void)
|
||||
static void cmd_passive_scan_on(int dups)
|
||||
{
|
||||
struct bt_le_scan_param param = {
|
||||
.type = BT_HCI_LE_SCAN_PASSIVE,
|
||||
|
@ -587,6 +596,10 @@ static void cmd_passive_scan_on(void)
|
|||
.window = 0x10 };
|
||||
int err;
|
||||
|
||||
if (dups >= 0) {
|
||||
param.filter_dup = dups;
|
||||
}
|
||||
|
||||
err = bt_le_scan_start(¶m, device_found);
|
||||
if (err) {
|
||||
printk("Bluetooth set passive scan failed (err %d)\n", err);
|
||||
|
@ -610,18 +623,32 @@ static void cmd_scan_off(void)
|
|||
static int cmd_scan(int argc, char *argv[])
|
||||
{
|
||||
const char *action;
|
||||
int dups = -1;
|
||||
|
||||
if (argc < 2) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Parse duplicate filtering data */
|
||||
if (argc >= 3) {
|
||||
const char *dup_filter = argv[2];
|
||||
|
||||
if (!strcmp(dup_filter, "dups")) {
|
||||
dups = BT_HCI_LE_SCAN_FILTER_DUP_DISABLE;
|
||||
} else if (!strcmp(dup_filter, "nodups")) {
|
||||
dups = BT_HCI_LE_SCAN_FILTER_DUP_ENABLE;
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
action = argv[1];
|
||||
if (!strcmp(action, "on")) {
|
||||
cmd_active_scan_on();
|
||||
cmd_active_scan_on(dups);
|
||||
} else if (!strcmp(action, "off")) {
|
||||
cmd_scan_off();
|
||||
} else if (!strcmp(action, "passive")) {
|
||||
cmd_passive_scan_on();
|
||||
cmd_passive_scan_on(dups);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
@ -2494,7 +2521,7 @@ static int cmd_bredr_sdp_find_record(int argc, char *argv[])
|
|||
|
||||
static const struct shell_cmd commands[] = {
|
||||
{ "init", cmd_init, HELP_ADDR_LE },
|
||||
{ "scan", cmd_scan, "<value: on, off>" },
|
||||
{ "scan", cmd_scan, "<value: on, off> <dup filter: dups, nodups>" },
|
||||
{ "advertise", cmd_advertise,
|
||||
"<type: off, on, scan, nconn> <mode: discov, non_discov>" },
|
||||
{ "connect", cmd_connect_le, HELP_ADDR_LE },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue