Bluetooth: controller: LE Directed Advertising Report
Implement the 4.2 event LE Directed Advertising Report, used for scanners in a privacy-enabled controller to report directed advertising events whose TargetA cannot be resolved by the local controller. Signed-off-by: Carles Cufi <carles.cufi@nordicsemi.no>
This commit is contained in:
parent
882bdd57b4
commit
868aeeb126
4 changed files with 132 additions and 43 deletions
|
@ -1607,8 +1607,8 @@ struct bt_hci_evt_le_enh_conn_complete {
|
|||
#define BT_HCI_EVT_LE_DIRECT_ADV_REPORT 0x0b
|
||||
struct bt_hci_evt_le_direct_adv_info {
|
||||
u8_t evt_type;
|
||||
bt_addr_le_t dir_addr;
|
||||
bt_addr_le_t addr;
|
||||
bt_addr_le_t dir_addr;
|
||||
s8_t rssi;
|
||||
} __packed;
|
||||
struct bt_hci_evt_le_direct_adv_report {
|
||||
|
|
|
@ -1620,27 +1620,9 @@ int hci_acl_handle(struct net_buf *buf)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
const u8_t c_adv_type[] = { 0x00, 0x01, 0x03, 0xff, 0x04,
|
||||
0xff, 0x02 };
|
||||
struct bt_hci_evt_le_advertising_report *sep;
|
||||
struct pdu_adv *adv = (struct pdu_adv *)pdu_data;
|
||||
struct bt_hci_evt_le_advertising_info *adv_info;
|
||||
u8_t data_len;
|
||||
u8_t info_len;
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
u8_t rl_idx;
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
u8_t *rssi;
|
||||
|
||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
|
||||
!(le_event_mask & BT_EVT_MASK_LE_ADVERTISING_REPORT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if CONFIG_BT_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
static inline bool dup_found(struct pdu_adv *adv)
|
||||
{
|
||||
/* check for duplicate filtering */
|
||||
if (dup_count >= 0) {
|
||||
int i;
|
||||
|
@ -1653,11 +1635,11 @@ static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
|
|||
|
||||
if (dup_filter[i].mask & BIT(adv->type)) {
|
||||
/* duplicate found */
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
/* report different adv types */
|
||||
dup_filter[i].mask |= BIT(adv->type);
|
||||
goto fill_report;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1678,8 +1660,51 @@ static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
|
|||
dup_curr = 0;
|
||||
}
|
||||
}
|
||||
fill_report:
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif /* CONFIG_BT_CONTROLLER_DUP_FILTER_LEN > 0 */
|
||||
|
||||
static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,
|
||||
struct net_buf *buf)
|
||||
{
|
||||
const u8_t c_adv_type[] = { 0x00, 0x01, 0x03, 0xff, 0x04,
|
||||
0xff, 0x02 };
|
||||
struct bt_hci_evt_le_advertising_report *sep;
|
||||
struct pdu_adv *adv = (struct pdu_adv *)pdu_data;
|
||||
struct bt_hci_evt_le_advertising_info *adv_info;
|
||||
u8_t data_len;
|
||||
u8_t info_len;
|
||||
u8_t rssi;
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
u8_t rl_idx, direct;
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
u8_t *prssi;
|
||||
|
||||
if (!(event_mask & BT_EVT_MASK_LE_META_EVENT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
direct = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_adv, payload) + adv->len + 2];
|
||||
|
||||
if ((!direct && !(le_event_mask & BT_EVT_MASK_LE_ADVERTISING_REPORT)) ||
|
||||
(direct && !(le_event_mask & BT_HCI_EVT_LE_DIRECT_ADV_REPORT))) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (!(le_event_mask & BT_EVT_MASK_LE_ADVERTISING_REPORT)) {
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
|
||||
|
||||
#if CONFIG_BT_CONTROLLER_DUP_FILTER_LEN > 0
|
||||
if (dup_found(adv)) {
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CONTROLLER_DUP_FILTER_LEN > 0 */
|
||||
|
||||
if (adv->type != PDU_ADV_TYPE_DIRECT_IND) {
|
||||
data_len = (adv->len - BDADDR_SIZE);
|
||||
|
@ -1687,8 +1712,51 @@ fill_report:
|
|||
data_len = 0;
|
||||
}
|
||||
|
||||
rssi = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_adv, payload) + adv->len];
|
||||
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
rl_idx = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_adv, payload) + adv->len + 1];
|
||||
|
||||
if (direct) {
|
||||
struct bt_hci_evt_le_direct_adv_report *drp;
|
||||
struct bt_hci_evt_le_direct_adv_info *dir_info;
|
||||
|
||||
LL_ASSERT(adv->type == PDU_ADV_TYPE_DIRECT_IND);
|
||||
drp = meta_evt(buf, BT_HCI_EVT_LE_DIRECT_ADV_REPORT,
|
||||
sizeof(*drp) + sizeof(*dir_info));
|
||||
|
||||
drp->num_reports = 1;
|
||||
dir_info = (void *)(((u8_t *)drp) + sizeof(*drp));
|
||||
|
||||
dir_info->evt_type = c_adv_type[PDU_ADV_TYPE_DIRECT_IND];
|
||||
|
||||
if (rl_idx < ll_rl_size_get()) {
|
||||
/* Store identity address */
|
||||
ll_rl_id_addr_get(rl_idx, &dir_info->addr.type,
|
||||
&dir_info->addr.a.val[0]);
|
||||
/* Mark it as identity address from RPA (0x02, 0x03) */
|
||||
dir_info->addr.type += 2;
|
||||
} else {
|
||||
dir_info->addr.type = adv->tx_addr;
|
||||
memcpy(&dir_info->addr.a.val[0],
|
||||
&adv->payload.direct_ind.adv_addr[0],
|
||||
sizeof(bt_addr_t));
|
||||
}
|
||||
|
||||
dir_info->dir_addr.type = 0x1;
|
||||
memcpy(&dir_info->dir_addr.a.val[0],
|
||||
&adv->payload.direct_ind.tgt_addr[0], sizeof(bt_addr_t));
|
||||
|
||||
dir_info->rssi = rssi;
|
||||
|
||||
return;
|
||||
}
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
|
||||
info_len = sizeof(struct bt_hci_evt_le_advertising_info) + data_len +
|
||||
sizeof(*rssi);
|
||||
sizeof(*prssi);
|
||||
sep = meta_evt(buf, BT_HCI_EVT_LE_ADVERTISING_REPORT,
|
||||
sizeof(*sep) + info_len);
|
||||
|
||||
|
@ -1698,8 +1766,6 @@ fill_report:
|
|||
adv_info->evt_type = c_adv_type[adv->type];
|
||||
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
rl_idx = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_adv, payload) + adv->len + 1];
|
||||
if (rl_idx < ll_rl_size_get()) {
|
||||
/* Store identity address */
|
||||
ll_rl_id_addr_get(rl_idx, &adv_info->addr.type,
|
||||
|
@ -1719,10 +1785,8 @@ fill_report:
|
|||
adv_info->length = data_len;
|
||||
memcpy(&adv_info->data[0], &adv->payload.adv_ind.data[0], data_len);
|
||||
/* RSSI */
|
||||
rssi = &adv_info->data[0] + data_len;
|
||||
*rssi = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
|
||||
offsetof(struct pdu_adv, payload) + adv->len];
|
||||
|
||||
prssi = &adv_info->data[0] + data_len;
|
||||
*prssi = rssi;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CONTROLLER_ADV_EXT)
|
||||
|
|
|
@ -1104,7 +1104,7 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static u32_t isr_rx_scan_report(u8_t rssi_ready, u8_t rl_idx)
|
||||
static u32_t isr_rx_scan_report(u8_t rssi_ready, u8_t rl_idx, bool dir_report)
|
||||
{
|
||||
struct radio_pdu_node_rx *radio_pdu_node_rx;
|
||||
struct pdu_adv *pdu_adv_rx;
|
||||
|
@ -1149,6 +1149,9 @@ static u32_t isr_rx_scan_report(u8_t rssi_ready, u8_t rl_idx)
|
|||
/* save the resolving list index */
|
||||
((u8_t *)pdu_adv_rx)[offsetof(struct pdu_adv, payload) +
|
||||
pdu_adv_rx->len + 1] = rl_idx;
|
||||
/* save the directed adv report flag */
|
||||
((u8_t *)pdu_adv_rx)[offsetof(struct pdu_adv, payload) +
|
||||
pdu_adv_rx->len + 2] = dir_report ? 1 : 0;
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
|
||||
packet_rx_enqueue();
|
||||
|
@ -1193,8 +1196,25 @@ static inline bool isr_scan_init_adva_check(struct pdu_adv *pdu,
|
|||
&pdu->payload.adv_ind.addr[0], BDADDR_SIZE) == 0));
|
||||
}
|
||||
|
||||
static inline bool isr_scan_tgta_rpa_check(struct pdu_adv *pdu,
|
||||
bool *dir_report)
|
||||
{
|
||||
if (((_radio.scanner.filter_policy & 0x02) != 0) &&
|
||||
(pdu->rx_addr != 0) &&
|
||||
((pdu->payload.direct_ind.tgt_addr[5] & 0xc0) == 0x40)) {
|
||||
|
||||
if (dir_report) {
|
||||
*dir_report = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool isr_scan_tgta_check(bool init, struct pdu_adv *pdu,
|
||||
u8_t rl_idx)
|
||||
u8_t rl_idx, bool *dir_report)
|
||||
{
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
if (ctrl_rl_addr_resolve(pdu->rx_addr,
|
||||
|
@ -1215,9 +1235,7 @@ static inline bool isr_scan_tgta_check(bool init, struct pdu_adv *pdu,
|
|||
/* allow directed adv packets where TargetA address
|
||||
* is resolvable private address (scanner only)
|
||||
*/
|
||||
(((_radio.scanner.filter_policy & 0x02) != 0) &&
|
||||
(pdu->rx_addr != 0) &&
|
||||
((pdu->payload.direct_ind.tgt_addr[5] & 0xc0) == 0x40));
|
||||
isr_scan_tgta_rpa_check(pdu, dir_report);
|
||||
}
|
||||
|
||||
static inline bool isr_scan_init_check(struct pdu_adv *pdu, u8_t rl_idx)
|
||||
|
@ -1227,7 +1245,7 @@ static inline bool isr_scan_init_check(struct pdu_adv *pdu, u8_t rl_idx)
|
|||
((pdu->type == PDU_ADV_TYPE_ADV_IND) ||
|
||||
((pdu->type == PDU_ADV_TYPE_DIRECT_IND) &&
|
||||
(/* allow directed adv packets addressed to this device */
|
||||
isr_scan_tgta_check(true, pdu, rl_idx)))));
|
||||
isr_scan_tgta_check(true, pdu, rl_idx, NULL)))));
|
||||
}
|
||||
|
||||
static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
||||
|
@ -1235,6 +1253,8 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
u8_t rssi_ready)
|
||||
{
|
||||
struct pdu_adv *pdu_adv_rx;
|
||||
/* Directed Adverising Report */
|
||||
bool dir_report = false;
|
||||
|
||||
pdu_adv_rx = (struct pdu_adv *)
|
||||
_radio.packet_rx[_radio.packet_rx_last]->pdu_data;
|
||||
|
@ -1521,7 +1541,8 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
/* save the adv packet */
|
||||
err = isr_rx_scan_report(rssi_ready,
|
||||
irkmatch_ok ? rl_idx :
|
||||
FILTER_IDX_NONE);
|
||||
FILTER_IDX_NONE,
|
||||
false);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
@ -1563,7 +1584,8 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
else if (((pdu_adv_rx->type == PDU_ADV_TYPE_ADV_IND) ||
|
||||
((pdu_adv_rx->type == PDU_ADV_TYPE_DIRECT_IND) &&
|
||||
(/* allow directed adv packets addressed to this device */
|
||||
isr_scan_tgta_check(false, pdu_adv_rx, rl_idx))) ||
|
||||
isr_scan_tgta_check(false, pdu_adv_rx, rl_idx,
|
||||
&dir_report))) ||
|
||||
(pdu_adv_rx->type == PDU_ADV_TYPE_NONCONN_IND) ||
|
||||
(pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND) ||
|
||||
#if defined(CONFIG_BT_CONTROLLER_ADV_EXT)
|
||||
|
@ -1579,7 +1601,8 @@ static inline u32_t isr_rx_scan(u8_t devmatch_ok, u8_t devmatch_id,
|
|||
/* save the scan response packet */
|
||||
err = isr_rx_scan_report(rssi_ready,
|
||||
irkmatch_ok ? rl_idx :
|
||||
FILTER_IDX_NONE);
|
||||
FILTER_IDX_NONE,
|
||||
dir_report);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -273,9 +273,11 @@ struct pdu_data_q_tx {
|
|||
struct radio_pdu_node_tx *node_tx;
|
||||
};
|
||||
|
||||
/* Extra bytes for enqueued rx_node metadata: rssi and resolving index */
|
||||
/* Extra bytes for enqueued rx_node metadata: rssi (always) and resolving
|
||||
* index and directed adv report (with privacy enabled).
|
||||
*/
|
||||
#if defined(CONFIG_BT_CONTROLLER_PRIVACY)
|
||||
#define PDU_AC_SIZE_EXTRA 2
|
||||
#define PDU_AC_SIZE_EXTRA 3
|
||||
#else
|
||||
#define PDU_AC_SIZE_EXTRA 1
|
||||
#endif /* CONFIG_BT_CONTROLLER_PRIVACY */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue