[RFC PATCH 04/34] Add support to process PR elements in USD frames

Peddolla Harshavardhan Reddy peddolla at qti.qualcomm.com
Thu May 15 00:17:27 PDT 2025


Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
 src/common/ieee802_11_common.c |  5 +++
 src/common/ieee802_11_common.h |  2 +
 src/common/nan_de.c            |  7 +++-
 src/common/nan_de.h            |  4 ++
 src/common/proximity_ranging.c | 73 +++++++++++++++++++++++++++++++++-
 src/common/proximity_ranging.h |  3 ++
 wpa_supplicant/nan_usd.c       | 15 +++++++
 wpa_supplicant/pr_supplicant.c | 12 ++++++
 wpa_supplicant/pr_supplicant.h |  3 ++
 9 files changed, 121 insertions(+), 3 deletions(-)

diff --git a/src/common/ieee802_11_common.c b/src/common/ieee802_11_common.c
index 838869a03..7bf255fbc 100644
--- a/src/common/ieee802_11_common.c
+++ b/src/common/ieee802_11_common.c
@@ -165,6 +165,11 @@ static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen,
 			elems->p2p2_ie = pos;
 			elems->p2p2_ie_len = elen;
 			break;
+		case PR_OUI_TYPE:
+			/* Wi-Fi Alliance - PR IE */
+			elems->proximity_ranging = pos;
+			elems->proximity_ranging_len = elen;
+			break;
 		default:
 			wpa_printf(MSG_MSGDUMP, "Unknown WFA "
 				   "information element ignored "
diff --git a/src/common/ieee802_11_common.h b/src/common/ieee802_11_common.h
index abd17f062..428531c9b 100644
--- a/src/common/ieee802_11_common.h
+++ b/src/common/ieee802_11_common.h
@@ -122,6 +122,7 @@ struct ieee802_11_elems {
 	const u8 *rsnxe_override;
 	const u8 *rsn_selection;
 	const u8 *wfa_capab;
+	const u8 *proximity_ranging;
 
 	u8 ssid_len;
 	u8 supp_rates_len;
@@ -191,6 +192,7 @@ struct ieee802_11_elems {
 	size_t rsnxe_override_len;
 	size_t rsn_selection_len;
 	u8 wfa_capab_len;
+	size_t proximity_ranging_len;
 
 	struct mb_ies_info mb_ies;
 
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index ba038094b..2247af895 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -843,7 +843,7 @@ static void nan_de_get_sdea(const u8 *buf, size_t len, u8 instance_id,
 
 static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
 					  size_t len, const u8 *peer_addr,
-					  unsigned int freq, bool p2p)
+					  unsigned int freq, bool p2p, bool pr)
 {
 	const u8 *elem;
 	u16 elem_len;
@@ -866,6 +866,9 @@ static void nan_de_process_elem_container(struct nan_de *de, const u8 *buf,
 	if (p2p && de->cb.process_p2p_usd_elems)
 		de->cb.process_p2p_usd_elems(de->cb.ctx, elem, elem_len,
 					     peer_addr, freq);
+	if (pr && de->cb.process_pr_usd_elems)
+		de->cb.process_pr_usd_elems(de->cb.ctx, elem, elem_len,
+					     peer_addr, freq);
 }
 
 
@@ -1205,7 +1208,7 @@ static void nan_de_rx_sda(struct nan_de *de, const u8 *peer_addr, const u8 *a3,
 					    ssi, ssi_len);
 			}
 			nan_de_process_elem_container(de, buf, len, peer_addr,
-						      freq, srv->is_p2p);
+						      freq, srv->is_p2p, srv->is_pr);
 		}
 
 		switch (type) {
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index 7f0836332..29999b31f 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -60,6 +60,10 @@ struct nan_callbacks {
 	void (*process_p2p_usd_elems)(void *ctx, const u8 *buf,
 				      u16 buf_len, const u8 *peer_addr,
 				      unsigned int freq);
+
+	void (*process_pr_usd_elems)(void *ctx, const u8 *buf,
+				     u16 buf_len, const u8 *peer_addr,
+				     unsigned int freq);
 };
 
 bool nan_de_is_nan_network_id(const u8 *addr);
diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index ab61f6e3a..d87856b12 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -15,6 +15,59 @@
 #include "wps/wps_i.h"
 #include "proximity_ranging.h"
 
+static void pr_device_free(struct pr_data *pr, struct pr_device *dev)
+{
+	os_free(dev);
+}
+
+
+static struct pr_device * pr_get_device(struct pr_data *pr, const u8 *addr)
+{
+	struct pr_device *dev;
+
+	dl_list_for_each(dev, &pr->devices, struct pr_device, list) {
+		if (ether_addr_equal(dev->pr_device_addr, addr))
+			return dev;
+	}
+	return NULL;
+}
+
+
+static struct pr_device * pr_create_device(struct pr_data *pr, const u8 *addr)
+{
+	struct pr_device *dev, *oldest = NULL;
+	size_t count = 0;
+
+	dev = pr_get_device(pr, addr);
+	if (dev)
+		return dev;
+
+	dl_list_for_each(dev, &pr->devices, struct pr_device, list) {
+		count++;
+		if (!oldest ||
+		    os_reltime_before(&dev->last_seen, &oldest->last_seen))
+			oldest = dev;
+	}
+	if (count + 1 > PR_MAX_PEER && oldest) {
+		wpa_printf(MSG_DEBUG,
+			   "Remove oldest peer entry to make room for a new peer " MACSTR,
+			   MAC2STR(oldest->pr_device_addr));
+		dl_list_del(&oldest->list);
+		pr_device_free(pr, oldest);
+	}
+
+	dev = os_zalloc(sizeof(*dev));
+	if (!dev)
+		return NULL;
+
+	dl_list_add(&pr->devices, &dev->list);
+	os_memcpy(dev->pr_device_addr, addr, ETH_ALEN);
+	wpa_printf(MSG_DEBUG, "PR: New Proximity Ranging device add to list");
+
+	return dev;
+}
+
+
 struct pr_data * pr_init(const struct pr_config *cfg)
 {
 	struct pr_data *pr;
@@ -45,8 +98,10 @@ void pr_deinit(struct pr_data *pr)
 
 	os_free(pr->cfg->dev_name);
 
-	dl_list_for_each_safe(dev, prev, &pr->devices, struct pr_device, list)
+	dl_list_for_each_safe(dev, prev, &pr->devices, struct pr_device, list) {
 		dl_list_del(&dev->list);
+		pr_device_free(pr, dev);
+	}
 
 	os_free(pr);
 	wpa_printf(MSG_DEBUG, "PR: Deinit done");
@@ -102,3 +157,19 @@ struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
 
 	return buf2;
 }
+
+
+void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
+			  const u8 *peer_addr, unsigned int freq)
+{
+	struct pr_device *dev;
+
+	dev = pr_create_device(pr, peer_addr);
+	if (!dev) {
+		wpa_printf(MSG_ERROR, "PR: Failed to create a device");
+		return;
+	}
+
+	os_get_reltime(&dev->last_seen);
+	dev->listen_freq = freq;
+}
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 8ebc363c1..4f5c59f9b 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -64,6 +64,7 @@ struct pr_channels {
 struct pr_device {
 	struct dl_list list;
 	struct os_reltime last_seen;
+	int listen_freq;
 
 	/**
 	 * pr_device_addr - PR Device Address of the peer
@@ -146,5 +147,7 @@ struct pr_data {
 struct pr_data * pr_init(const struct pr_config *cfg);
 void pr_deinit(struct pr_data *pr);
 struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country);
+void pr_process_usd_elems(struct pr_data *pr, const u8 *ies, u16 ies_len,
+			  const u8 *peer_addr, unsigned int freq);
 
 #endif /* PROXIMITY_RANGING_H */
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
index 68b2e6521..cb8c6d6aa 100644
--- a/wpa_supplicant/nan_usd.c
+++ b/wpa_supplicant/nan_usd.c
@@ -322,6 +322,18 @@ static void wpas_nan_process_p2p_usd_elems(void *ctx, const u8 *buf,
 #endif /* CONFIG_P2P */
 
 
+#ifdef CONFIG_PR
+static void wpas_nan_process_pr_usd_elems(void *ctx, const u8 *buf, u16 buf_len,
+					  const u8 *peer_addr,
+					  unsigned int freq)
+{
+	struct wpa_supplicant *wpa_s = ctx;
+
+	wpas_pr_process_usd_elems(wpa_s, buf, buf_len, peer_addr, freq);
+}
+#endif /* CONFIG_PR */
+
+
 int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
 {
 	struct nan_callbacks cb;
@@ -341,6 +353,9 @@ int wpas_nan_usd_init(struct wpa_supplicant *wpa_s)
 #ifdef CONFIG_P2P
 	cb.process_p2p_usd_elems = wpas_nan_process_p2p_usd_elems;
 #endif /* CONFIG_P2P */
+#ifdef CONFIG_PR
+	cb.process_pr_usd_elems = wpas_nan_process_pr_usd_elems;
+#endif /* CONFIG_PR */
 
 	wpa_s->nan_de = nan_de_init(wpa_s->own_addr, offload, false,
 				    wpa_s->max_remain_on_chan, &cb);
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index 59955d6dc..1e151581a 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -80,6 +80,18 @@ struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s)
 }
 
 
+void wpas_pr_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+			       u16 buf_len, const u8 *peer_addr,
+			       unsigned int freq)
+{
+	struct pr_data *pr = wpa_s->global->pr;
+
+	if (!pr)
+		return;
+	pr_process_usd_elems(pr, buf, buf_len, peer_addr, freq);
+}
+
+
 int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
 {
 	struct pr_config pr;
diff --git a/wpa_supplicant/pr_supplicant.h b/wpa_supplicant/pr_supplicant.h
index b2469781a..2bad595bb 100644
--- a/wpa_supplicant/pr_supplicant.h
+++ b/wpa_supplicant/pr_supplicant.h
@@ -16,6 +16,9 @@
 int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s);
 void wpas_pr_deinit(struct wpa_supplicant *wpa_s);
 struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s);
+void wpas_pr_process_usd_elems(struct wpa_supplicant *wpa_s, const u8 *buf,
+			       u16 buf_len, const u8 *peer_addr,
+			       unsigned int freq);
 #else /* CONFIG_PR */
 static inline int wpas_pr_init(struct wpa_global *global,
 			       struct wpa_supplicant *wpa_s)
-- 
2.34.1




More information about the Hostap mailing list