Bluetooth: controller: Add extended scan filter duplicates
Added implementation to filter out duplicates in generated extended advertising reports. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
f6ef508f6f
commit
17c006ce4a
1 changed files with 94 additions and 21 deletions
|
@ -68,8 +68,14 @@ static uint16_t _opcode;
|
||||||
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
/* Scan duplicate filter */
|
/* Scan duplicate filter */
|
||||||
struct dup {
|
struct dup {
|
||||||
uint8_t mask;
|
uint8_t mask;
|
||||||
bt_addr_le_t addr;
|
bt_addr_le_t addr;
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||||
|
uint8_t adv_mode:2;
|
||||||
|
uint8_t data_cmplt:1;
|
||||||
|
struct pdu_adv_adi adi;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
static struct dup dup_filter[CONFIG_BT_CTLR_DUP_FILTER_LEN];
|
static struct dup dup_filter[CONFIG_BT_CTLR_DUP_FILTER_LEN];
|
||||||
static int32_t dup_count;
|
static int32_t dup_count;
|
||||||
|
@ -4078,33 +4084,90 @@ int hci_acl_handle(struct net_buf *buf, struct net_buf **evt)
|
||||||
#endif /* CONFIG_BT_CONN */
|
#endif /* CONFIG_BT_CONN */
|
||||||
|
|
||||||
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
static inline bool dup_found(struct pdu_adv *adv)
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||||
|
static void store_adi(int i, struct pdu_adv_adi *adi)
|
||||||
|
{
|
||||||
|
if (adi) {
|
||||||
|
memcpy(&dup_filter[i].adi, adi, sizeof(*adi));
|
||||||
|
} else {
|
||||||
|
memset(&dup_filter[i].adi, 0, sizeof(*adi));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||||
|
|
||||||
|
static inline bool is_dup_or_update(int i, uint8_t adv_type, uint8_t adv_mode,
|
||||||
|
struct pdu_adv_adi *adi,
|
||||||
|
uint8_t data_status)
|
||||||
|
{
|
||||||
|
if (!(dup_filter[i].mask & BIT(adv_type))) {
|
||||||
|
/* report different adv types */
|
||||||
|
dup_filter[i].mask |= BIT(adv_type);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||||
|
dup_filter[i].adv_mode = adv_mode;
|
||||||
|
dup_filter[i].data_cmplt = !data_status;
|
||||||
|
store_adi(i, adi);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (dup_filter[i].adv_mode != adv_mode) {
|
||||||
|
/* report different adv mode */
|
||||||
|
dup_filter[i].adv_mode = adv_mode;
|
||||||
|
|
||||||
|
dup_filter[i].data_cmplt = !data_status;
|
||||||
|
store_adi(i, adi);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (adi && ((dup_filter[i].adi.sid != adi->sid) ||
|
||||||
|
(dup_filter[i].adi.did != adi->did))) {
|
||||||
|
/* report different adi */
|
||||||
|
store_adi(i, adi);
|
||||||
|
|
||||||
|
dup_filter[i].data_cmplt = !data_status;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else if (!dup_filter[i].data_cmplt && !data_status) {
|
||||||
|
/* report data complete */
|
||||||
|
dup_filter[i].data_cmplt = !data_status;
|
||||||
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dup_found(uint8_t adv_type, uint8_t addr_type, uint8_t *addr,
|
||||||
|
uint8_t adv_mode, struct pdu_adv_adi *adi,
|
||||||
|
uint8_t data_status)
|
||||||
{
|
{
|
||||||
/* check for duplicate filtering */
|
/* check for duplicate filtering */
|
||||||
if (dup_count >= 0) {
|
if (dup_count >= 0) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
/* find for existing entry and update if changed */
|
||||||
for (i = 0; i < dup_count; i++) {
|
for (i = 0; i < dup_count; i++) {
|
||||||
if (!memcmp(&adv->adv_ind.addr[0],
|
if (memcmp(addr, &dup_filter[i].addr.a.val[0],
|
||||||
&dup_filter[i].addr.a.val[0],
|
sizeof(bt_addr_t)) ||
|
||||||
sizeof(bt_addr_t)) &&
|
(addr_type != dup_filter[i].addr.type)) {
|
||||||
adv->tx_addr == dup_filter[i].addr.type) {
|
continue;
|
||||||
|
|
||||||
if (dup_filter[i].mask & BIT(adv->type)) {
|
|
||||||
/* duplicate found */
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
/* report different adv types */
|
|
||||||
dup_filter[i].mask |= BIT(adv->type);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* still duplicate or update entry with change */
|
||||||
|
return is_dup_or_update(i, adv_type, adv_mode, adi,
|
||||||
|
data_status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* insert into the duplicate filter */
|
/* insert into the duplicate filter */
|
||||||
memcpy(&dup_filter[dup_curr].addr.a.val[0],
|
memcpy(&dup_filter[dup_curr].addr.a.val[0], addr,
|
||||||
&adv->adv_ind.addr[0], sizeof(bt_addr_t));
|
sizeof(bt_addr_t));
|
||||||
dup_filter[dup_curr].addr.type = adv->tx_addr;
|
dup_filter[dup_curr].addr.type = addr_type;
|
||||||
dup_filter[dup_curr].mask = BIT(adv->type);
|
dup_filter[dup_curr].mask = BIT(adv_type);
|
||||||
|
|
||||||
|
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||||
|
dup_filter[dup_curr].adv_mode = adv_mode;
|
||||||
|
dup_filter[i].data_cmplt = !data_status;
|
||||||
|
store_adi(dup_curr, adi);
|
||||||
|
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||||
|
|
||||||
if (dup_count < CONFIG_BT_CTLR_DUP_FILTER_LEN) {
|
if (dup_count < CONFIG_BT_CTLR_DUP_FILTER_LEN) {
|
||||||
dup_count++;
|
dup_count++;
|
||||||
|
@ -4137,7 +4200,7 @@ static inline void le_dir_adv_report(struct pdu_adv *adv, struct net_buf *buf,
|
||||||
LL_ASSERT(adv->type == PDU_ADV_TYPE_DIRECT_IND);
|
LL_ASSERT(adv->type == PDU_ADV_TYPE_DIRECT_IND);
|
||||||
|
|
||||||
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
if (dup_found(adv)) {
|
if (dup_found(adv->type, adv->tx_addr, adv->adv_ind.addr, 0, NULL, 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
||||||
|
@ -4291,7 +4354,7 @@ static void le_advertising_report(struct pdu_data *pdu_data,
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
if (dup_found(adv)) {
|
if (dup_found(adv->type, adv->tx_addr, adv->adv_ind.addr, 0, NULL, 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
||||||
|
@ -4401,7 +4464,7 @@ static void le_ext_adv_legacy_report(struct pdu_data *pdu_data,
|
||||||
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||||
|
|
||||||
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
if (dup_found(adv)) {
|
if (dup_found(adv->type, adv->tx_addr, adv->adv_ind.addr, 0, NULL, 0)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
||||||
|
@ -4726,6 +4789,16 @@ no_ext_hdr:
|
||||||
adv = (void *)node_rx_curr->pdu;
|
adv = (void *)node_rx_curr->pdu;
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
|
#if CONFIG_BT_CTLR_DUP_FILTER_LEN > 0
|
||||||
|
if (adv_addr) {
|
||||||
|
if (dup_found(PDU_ADV_TYPE_EXT_IND, adv_addr_type, adv_addr,
|
||||||
|
evt_type, adi, data_status)) {
|
||||||
|
node_rx_extra_list_release(node_rx->hdr.rx_ftr.extra);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* CONFIG_BT_CTLR_DUP_FILTER_LEN > 0 */
|
||||||
|
|
||||||
/* FIXME: move most of below into above loop to dispatch fragments of
|
/* FIXME: move most of below into above loop to dispatch fragments of
|
||||||
* data in HCI event.
|
* data in HCI event.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue