From fc6d8d1bc46b2b521dc05c4ba8855bf7accd2a56 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 | 48 +++++++ 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, 159 insertions(+), 31 deletions(-) diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index c57dd25601f..3acc9ebeac4 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 8af56af61fc..cfbd4d0db9c 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -1236,6 +1236,45 @@ fill_report: } +#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); @@ -1706,6 +1751,9 @@ s8_t hci_get_class(struct radio_pdu_node_rx *node_rx) switch (node_rx->hdr.type) { 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 */ #if defined(CONFIG_BLUETOOTH_CONTROLLER_ADV_INDICATION) case NODE_RX_TYPE_ADV_INDICATION: #endif diff --git a/subsys/bluetooth/controller/ll_sw/ctrl.c b/subsys/bluetooth/controller/ll_sw/ctrl.c index f833316ccc9..3c786db3e2f 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 fcb0351cdd0..aed5a12e9d7 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 4a3c9119375..bff3c426754 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