Bluetooth: Controller: Implement direct addr type in ext adv report

Implement setting the correct directed advertisers address
type in the Extended Advertising Report.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
diff --git a/include/bluetooth/addr.h b/include/bluetooth/addr.h
index bd6669b..a2d31da 100644
--- a/include/bluetooth/addr.h
+++ b/include/bluetooth/addr.h
@@ -29,6 +29,12 @@
 #define BT_ADDR_LE_RANDOM       0x01
 #define BT_ADDR_LE_PUBLIC_ID    0x02
 #define BT_ADDR_LE_RANDOM_ID    0x03
+#define BT_ADDR_LE_UNRESOLVED   0xFE /* Resolvable Private Address
+				      * (Controller unable to resolve)
+				      */
+#define BT_ADDR_LE_ANONYMOUS    0xFF /* No address provided
+				      * (anonymous advertisement)
+				      */
 
 /** Length in bytes of a standard Bluetooth address */
 #define BT_ADDR_SIZE 6
diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c
index 7558c95..30b08e7 100644
--- a/subsys/bluetooth/controller/hci/hci.c
+++ b/subsys/bluetooth/controller/hci/hci.c
@@ -5095,6 +5095,41 @@
 	memcpy(&adv_info->data[0], &adv->adv_ind.data[0], data_len);
 }
 
+static uint8_t ext_adv_direct_addr_type(struct lll_scan *lll,
+					bool resolved, bool direct,
+					uint8_t rx_addr_type,
+					const uint8_t *const rx_addr)
+{
+	if (0) {
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	} else if (resolved) {
+		if (!direct) {
+			struct ll_scan_set *scan;
+
+			scan = HDR_LLL2ULL(lll);
+			if ((rx_addr_type == lll->init_addr_type) &&
+			    !memcmp(lll->init_addr, rx_addr, BDADDR_SIZE)) {
+				return scan->own_addr_type;
+			} else {
+				return scan->own_addr_type | BIT(1);
+			}
+		} else {
+			return BT_ADDR_LE_UNRESOLVED;
+		}
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+	} else {
+		if (!direct) {
+			struct ll_scan_set *scan;
+
+			scan = HDR_LLL2ULL(lll);
+
+			return scan->own_addr_type;
+		} else {
+			return BT_ADDR_LE_UNRESOLVED;
+		}
+	}
+}
+
 static void node_rx_extra_list_release(struct node_rx_pdu *node_rx_extra)
 {
 	while (node_rx_extra) {
@@ -5219,6 +5254,7 @@
 	do {
 		struct pdu_adv_adi *adi_curr = NULL;
 		uint8_t direct_addr_type_curr = 0U;
+		bool direct_resolved_curr = false;
 		uint8_t *direct_addr_curr = NULL;
 		uint8_t adv_addr_type_curr = 0U;
 		struct pdu_adv_com_ext_adv *p;
@@ -5238,6 +5274,8 @@
 
 #if defined(CONFIG_BT_CTLR_PRIVACY)
 		uint8_t rl_idx_curr = node_rx_curr->hdr.rx_ftr.rl_idx;
+
+		direct_resolved_curr = node_rx_curr->hdr.rx_ftr.direct_resolved;
 #endif /* CONFIG_BT_CTLR_PRIVACY */
 
 		/* The Link Layer currently returns RSSI as an absolute value */
@@ -5278,14 +5316,21 @@
 		}
 
 		if (h->tgt_addr) {
+			struct lll_scan *lll;
 			bt_addr_le_t addr;
 
-			direct_addr_type_curr = adv->rx_addr;
+			lll = node_rx->hdr.rx_ftr.param;
+			direct_addr_type_curr =
+				ext_adv_direct_addr_type(lll,
+							 direct_resolved_curr,
+							 direct_curr,
+							 adv->rx_addr, ptr);
 			direct_addr_curr = ptr;
+			ptr += BDADDR_SIZE;
 
 			addr.type = adv->rx_addr;
-			(void)memcpy(addr.a.val, ptr, sizeof(bt_addr_t));
-			ptr += BDADDR_SIZE;
+			(void)memcpy(addr.a.val, direct_addr_curr,
+				     sizeof(bt_addr_t));
 
 			BT_DBG("    TgtA: %s", bt_addr_le_str(&addr));
 		}
diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h
index e1905a0..cde58b9 100644
--- a/subsys/bluetooth/controller/ll_sw/lll.h
+++ b/subsys/bluetooth/controller/ll_sw/lll.h
@@ -280,7 +280,21 @@
 	uint32_t ticks_anchor;
 	uint32_t radio_end_us;
 	uint8_t  rssi;
+
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  rl_idx;
+	uint8_t  lrpa_used:1;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
+#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
+	uint8_t  direct:1;
+#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
 #if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_OBSERVER)
+#if defined(CONFIG_BT_CTLR_PRIVACY)
+	uint8_t  direct_resolved:1;
+#endif /* CONFIG_BT_CTLR_PRIVACY */
+
 	uint8_t  aux_lll_sched:1;
 	uint8_t  aux_w4next:1;
 	uint8_t  aux_failed:1;
@@ -292,13 +306,7 @@
 	uint8_t  scan_req:1;
 	uint8_t  scan_rsp:1;
 #endif /* CONFIG_BT_CTLR_ADV_EXT && CONFIG_BT_OBSERVER */
-#if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
-	uint8_t  direct:1;
-#endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
-#if defined(CONFIG_BT_CTLR_PRIVACY)
-	uint8_t  lrpa_used:1;
-	uint8_t  rl_idx;
-#endif /* CONFIG_BT_CTLR_PRIVACY */
+
 #if defined(CONFIG_BT_HCI_MESH_EXT)
 	uint8_t  chan_idx;
 #endif /* CONFIG_BT_HCI_MESH_EXT */
diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c
index 2cb733a..65aa7f3 100644
--- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c
+++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c
@@ -92,8 +92,8 @@
 					   bool *dir_report);
 static inline bool isr_scan_rsp_adva_matches(struct pdu_adv *srsp);
 static int isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
-			      uint8_t phy_flags_rx, uint8_t rl_idx,
-			      bool dir_report);
+			      uint8_t phy_flags_rx, uint8_t irkmatch_ok,
+			      uint8_t rl_idx, bool dir_report);
 
 int lll_scan_init(void)
 {
@@ -1304,8 +1304,7 @@
 
 		/* save the adv packet */
 		err = isr_rx_scan_report(lll, rssi_ready, phy_flags_rx,
-					 irkmatch_ok ? rl_idx : FILTER_IDX_NONE,
-					 false);
+					 irkmatch_ok, rl_idx, false);
 		if (err) {
 			return err;
 		}
@@ -1409,9 +1408,7 @@
 
 		/* save the scan response packet */
 		err = isr_rx_scan_report(lll, rssi_ready, phy_flags_rx,
-					 irkmatch_ok ? rl_idx :
-						       FILTER_IDX_NONE,
-					 dir_report);
+					 irkmatch_ok, rl_idx, dir_report);
 		if (err) {
 			/* Auxiliary PDU LLL scanning has been setup */
 			if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT) &&
@@ -1499,8 +1496,8 @@
 }
 
 static int isr_rx_scan_report(struct lll_scan *lll, uint8_t rssi_ready,
-			      uint8_t phy_flags_rx, uint8_t rl_idx,
-			      bool dir_report)
+			      uint8_t phy_flags_rx, uint8_t irkmatch_ok,
+			      uint8_t rl_idx, bool dir_report)
 {
 	struct node_rx_pdu *node_rx;
 	int err = 0;
@@ -1581,12 +1578,18 @@
 						  BT_HCI_LE_RSSI_NOT_AVAILABLE;
 #if defined(CONFIG_BT_CTLR_PRIVACY)
 	/* save the resolving list index. */
-	node_rx->hdr.rx_ftr.rl_idx = rl_idx;
+	node_rx->hdr.rx_ftr.rl_idx = irkmatch_ok ? rl_idx : FILTER_IDX_NONE;
+
+#if defined(CONFIG_BT_CTLR_ADV_EXT)
+	node_rx->hdr.rx_ftr.direct_resolved = (rl_idx != FILTER_IDX_NONE);
+#endif /* CONFIG_BT_CTLR_ADV_EXT */
 #endif /* CONFIG_BT_CTLR_PRIVACY */
+
 #if defined(CONFIG_BT_CTLR_EXT_SCAN_FP)
 	/* save the directed adv report flag */
 	node_rx->hdr.rx_ftr.direct = dir_report;
 #endif /* CONFIG_BT_CTLR_EXT_SCAN_FP */
+
 #if defined(CONFIG_BT_HCI_MESH_EXT)
 	if (node_rx->hdr.type == NODE_RX_TYPE_MESH_REPORT) {
 		/* save channel and anchor point ticks. */