diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index c57dd25601fc..3acc9ebeac4c 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -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" diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index bb354314549d..805d793e00b7 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -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) @@ -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); diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index f833316ccc9c..3c786db3e2f2 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.c +++ b/subsys/bluetooth/controller/ll_sw/ctrl.c @@ -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: @@ -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) { @@ -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) { @@ -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; @@ -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(); @@ -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 { @@ -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: @@ -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: diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.h b/subsys/bluetooth/controller/ll_sw/ctrl.h index fcb0351cdd07..aed5a12e9d70 100644 --- a/subsys/bluetooth/controller/ll_sw/ctrl.h +++ b/subsys/bluetooth/controller/ll_sw/ctrl.h @@ -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, diff --git a/tests/bluetooth/init/prj_controller_dbg.conf b/tests/bluetooth/init/prj_controller_dbg.conf index 4a3c91193759..bff3c4267540 100644 --- a/tests/bluetooth/init/prj_controller_dbg.conf +++ b/tests/bluetooth/init/prj_controller_dbg.conf @@ -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