Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bluetooth: controller: Scan Request Notifications #16

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions subsys/bluetooth/controller/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,17 @@ config BLUETOOTH_CONTROLLER_ADV_INDICATION
help
Generate events indicating on air advertisement events.

config BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY
bool "Scan Request Notifications"
help
Generate events notifying the on air scan requests received.

config BLUETOOTH_CONTROLLER_SCAN_REQ_RSSI
bool "Measure Scan Request RSSI"
depends on BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY
help
Measure RSSI of the on air scan requests received.

endmenu

comment "BLE Controller debug configuration"
Expand Down
45 changes: 45 additions & 0 deletions subsys/bluetooth/controller/hci/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -1236,6 +1236,45 @@ static void le_advertising_report(struct pdu_data *pdu_data, u8_t *b,

}

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
static void le_scan_req_received(struct pdu_data *pdu_data, u8_t *b,
struct net_buf *buf)
{
struct pdu_adv *adv = (struct pdu_adv *)pdu_data;
struct bt_hci_evt_le_scan_req_received *sep;

/* TODO: fill handle when Adv Ext. feature is implemented. */

if (!(event_mask & BT_EVT_MASK_LE_META_EVENT) ||
!(le_event_mask & BT_EVT_MASK_LE_SCAN_REQ_RECEIVED)) {
char addr_str[BT_ADDR_LE_STR_LEN];
bt_addr_le_t addr;
u8_t handle;
u8_t rssi;

handle = 0;
addr.type = adv->tx_addr;
memcpy(&addr.a.val[0], &adv->payload.scan_req.scan_addr[0],
sizeof(bt_addr_t));
rssi = b[offsetof(struct radio_pdu_node_rx, pdu_data) +
offsetof(struct pdu_adv, payload) + adv->len];

bt_addr_le_to_str(&addr, addr_str, sizeof(addr_str));

BT_WARN("handle: %d, addr: %s, rssi: -%d dB.",
handle, addr_str, rssi);

return;
}

sep = meta_evt(buf, BT_HCI_EVT_LE_SCAN_REQ_RECEIVED, sizeof(*sep));
sep->handle = 0;
sep->addr.type = adv->tx_addr;
memcpy(&sep->addr.a.val[0], &adv->payload.scan_req.scan_addr[0],
sizeof(bt_addr_t));
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

#if defined(CONFIG_BLUETOOTH_CONN)
static void le_conn_complete(struct pdu_data *pdu_data, u16_t handle,
struct net_buf *buf)
Expand Down Expand Up @@ -1372,6 +1411,12 @@ static void encode_control(struct radio_pdu_node_rx *node_rx,
le_advertising_report(pdu_data, b, buf);
break;

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
case NODE_RX_TYPE_SCAN_REQ:
le_scan_req_received(pdu_data, b, buf);
break;
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

#if defined(CONFIG_BLUETOOTH_CONN)
case NODE_RX_TYPE_CONNECTION:
le_conn_complete(pdu_data, handle, buf);
Expand Down
124 changes: 93 additions & 31 deletions subsys/bluetooth/controller/ll_sw/ctrl.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,11 @@ static inline void isr_radio_state_tx(void)
}

radio_tmr_end_capture();

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_RSSI)
radio_rssi_measure();
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_RSSI */

break;

case ROLE_OBS:
Expand Down Expand Up @@ -578,6 +583,37 @@ static inline void isr_radio_state_tx(void)
}
}

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
static u32_t isr_rx_adv_sr_report(struct pdu_adv *pdu_adv_rx, u8_t rssi_ready)
{
struct radio_pdu_node_rx *radio_pdu_node_rx;
struct pdu_adv *pdu_adv;
u8_t pdu_len;

radio_pdu_node_rx = packet_rx_reserve_get(3);
if (radio_pdu_node_rx == 0) {
return 1;
}

/* Prepare the report (scan req) */
radio_pdu_node_rx->hdr.handle = 0xffff;
radio_pdu_node_rx->hdr.type = NODE_RX_TYPE_SCAN_REQ;

/* Make a copy of PDU into Rx node (as the received PDU is in the
* scratch buffer), and save the RSSI value.
*/
pdu_adv = (struct pdu_adv *)radio_pdu_node_rx->pdu_data;
pdu_len = offsetof(struct pdu_adv, payload) + pdu_adv_rx->len;
memcpy(pdu_adv, pdu_adv_rx, pdu_len);
((u8_t *)pdu_adv)[pdu_len] =
(rssi_ready) ? (radio_rssi_get() & 0x7f) : 0x7f;

packet_rx_enqueue();

return 0;
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t irkmatch_ok,
u8_t irkmatch_id, u8_t rssi_ready)
{
Expand All @@ -591,13 +627,22 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t irkmatch_ok,
(((_radio.advertiser.filter_policy & 0x01) == 0) ||
(devmatch_ok) || (irkmatch_ok)) &&
(1 /** @todo own addr match check */)) {

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
u32_t err;

/* Generate the scan request event */
err = isr_rx_adv_sr_report(pdu_adv, rssi_ready);
if (err) {
/* Scan Response will not be transmitted */
return err;
}
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

_radio.state = STATE_CLOSE;

radio_switch_complete_and_disable();

/* TODO use rssi_ready to generate proprietary scan_req event */
ARG_UNUSED(rssi_ready);

/* use the latest scan data, if any */
if (_radio.advertiser.scan_data.first != _radio.
advertiser.scan_data.last) {
Expand Down Expand Up @@ -829,6 +874,31 @@ static inline u32_t isr_rx_adv(u8_t devmatch_ok, u8_t irkmatch_ok,
return 1;
}

static u32_t isr_rx_obs_report(u8_t rssi_ready)
{
struct radio_pdu_node_rx *radio_pdu_node_rx;
struct pdu_adv *pdu_adv_rx;

radio_pdu_node_rx = packet_rx_reserve_get(3);
if (radio_pdu_node_rx == 0) {
return 1;
}

/* Prepare the report (adv or scan resp) */
radio_pdu_node_rx->hdr.handle = 0xffff;
radio_pdu_node_rx->hdr.type = NODE_RX_TYPE_REPORT;

/* save the RSSI value */
pdu_adv_rx = (struct pdu_adv *)radio_pdu_node_rx->pdu_data;
((u8_t *)pdu_adv_rx)[offsetof(struct pdu_adv, payload) +
pdu_adv_rx->len] =
(rssi_ready) ? (radio_rssi_get() & 0x7f) : 0x7f;

packet_rx_enqueue();

return 0;
}

static inline u32_t isr_rx_obs(u8_t irkmatch_id, u8_t rssi_ready)
{
struct pdu_adv *pdu_adv_rx;
Expand Down Expand Up @@ -1084,23 +1154,14 @@ static inline u32_t isr_rx_obs(u8_t irkmatch_id, u8_t rssi_ready)
(pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_IND)) &&
(_radio.observer.scan_type != 0) &&
(_radio.observer.conn == 0)) {
struct radio_pdu_node_rx *radio_pdu_node_rx;
struct pdu_adv *pdu_adv_tx;

radio_pdu_node_rx = packet_rx_reserve_get(3);
if (radio_pdu_node_rx == 0) {
return 1;
}

/* save the RSSI value */
((u8_t *)pdu_adv_rx)[offsetof(struct pdu_adv, payload) +
pdu_adv_rx->len] =
(rssi_ready) ? (radio_rssi_get() & 0x7F) : 0x7F;
u32_t err;

/* save the adv packet */
radio_pdu_node_rx->hdr.handle = 0xffff;
radio_pdu_node_rx->hdr.type = NODE_RX_TYPE_REPORT;
packet_rx_enqueue();
err = isr_rx_obs_report(rssi_ready);
if (err) {
return err;
}

/* prepare the scan request packet */
pdu_adv_tx = (struct pdu_adv *)radio_pkt_scratch_get();
Expand Down Expand Up @@ -1143,22 +1204,13 @@ static inline u32_t isr_rx_obs(u8_t irkmatch_id, u8_t rssi_ready)
((pdu_adv_rx->type == PDU_ADV_TYPE_SCAN_RSP) &&
(_radio.observer.scan_state != 0))) &&
(pdu_adv_rx->len != 0) && (!_radio.observer.conn)) {
struct radio_pdu_node_rx *radio_pdu_node_rx;

radio_pdu_node_rx = packet_rx_reserve_get(3);
if (radio_pdu_node_rx == 0) {
return 1;
}

/* save the RSSI value */
((u8_t *)pdu_adv_rx)[offsetof(struct pdu_adv, payload) +
pdu_adv_rx->len] =
(rssi_ready) ? (radio_rssi_get() & 0x7f) : 0x7f;
u32_t err;

/* save the scan response packet */
radio_pdu_node_rx->hdr.handle = 0xffff;
radio_pdu_node_rx->hdr.type = NODE_RX_TYPE_REPORT;
packet_rx_enqueue();
err = isr_rx_obs_report(rssi_ready);
if (err) {
return err;
}
}
/* invalid PDU */
else {
Expand Down Expand Up @@ -8196,6 +8248,11 @@ void radio_rx_dequeue(void)
switch (radio_pdu_node_rx->hdr.type) {
case NODE_RX_TYPE_DC_PDU:
case NODE_RX_TYPE_REPORT:

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
case NODE_RX_TYPE_SCAN_REQ:
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

case NODE_RX_TYPE_CONNECTION:
case NODE_RX_TYPE_CONN_UPDATE:
case NODE_RX_TYPE_ENC_REFRESH:
Expand Down Expand Up @@ -8250,6 +8307,11 @@ void radio_rx_mem_release(struct radio_pdu_node_rx **radio_pdu_node_rx)
switch (_radio_pdu_node_rx_free->hdr.type) {
case NODE_RX_TYPE_DC_PDU:
case NODE_RX_TYPE_REPORT:

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
case NODE_RX_TYPE_SCAN_REQ:
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

case NODE_RX_TYPE_CONNECTION:
case NODE_RX_TYPE_CONN_UPDATE:
case NODE_RX_TYPE_ENC_REFRESH:
Expand Down
5 changes: 5 additions & 0 deletions subsys/bluetooth/controller/ll_sw/ctrl.h
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ enum radio_pdu_node_rx_type {
NODE_RX_TYPE_NONE,
NODE_RX_TYPE_DC_PDU,
NODE_RX_TYPE_REPORT,

#if defined(CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY)
NODE_RX_TYPE_SCAN_REQ,
#endif /* CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY */

NODE_RX_TYPE_CONNECTION,
NODE_RX_TYPE_TERMINATE,
NODE_RX_TYPE_CONN_UPDATE,
Expand Down
2 changes: 2 additions & 0 deletions tests/bluetooth/init/prj_controller_dbg.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ CONFIG_BLUETOOTH_CONTROLLER_XTAL_ADVANCED=n
CONFIG_BLUETOOTH_CONTROLLER_SCHED_ADVANCED=n
CONFIG_BLUETOOTH_CONTROLLER_CONN_RSSI=y
CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION=y
CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_NOTIFY=y
CONFIG_BLUETOOTH_CONTROLLER_SCAN_REQ_RSSI=y
CONFIG_BLUETOOTH_CONTROLLER_PROFILE_ISR=y
CONFIG_BLUETOOTH_PERIPHERAL=y
CONFIG_BLUETOOTH_CENTRAL=y
Expand Down