From a8e1d1bf5f63b192cd45b09a3a70b485d75467f2 Mon Sep 17 00:00:00 2001 From: Vinayak Chettimada Date: Thu, 27 Apr 2017 11:29:35 +0200 Subject: [PATCH] Bluetooth: controller: Scan Request Notifications Implement the framework for LE Scan Request Received Event. The feature is available under the Controller's advanced features and will be selected implcitly when Bluetooth v5.0 LE Advertising Extensions feature is implemented. Jira: ZEP-2073 Signed-off-by: Vinayak Kariappa Chettimada --- subsys/bluetooth/controller/Kconfig | 11 ++ subsys/bluetooth/controller/hci/hci.c | 45 +++++++ subsys/bluetooth/controller/ll_sw/ctrl.c | 124 ++++++++++++++----- subsys/bluetooth/controller/ll_sw/ctrl.h | 5 + tests/bluetooth/init/prj_controller_dbg.conf | 2 + 5 files changed, 156 insertions(+), 31 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index c57dd25601fcbf..3acc9ebeac4c65 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 bb354314549d59..805d793e00b707 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 f833316ccc9c07..3c786db3e2f225 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 fcb0351cdd0708..aed5a12e9d7012 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 4a3c9119375945..bff3c42675406b 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