[RFC PATCH 03/34] Add API to initiate USD for Proximity Ranging

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


Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
 src/common/ieee802_11_defs.h   | 13 +++++++++
 src/common/nan_de.c            | 53 ++++++++++++++++++++++++++--------
 src/common/nan_de.h            |  6 ++++
 src/common/proximity_ranging.c | 51 ++++++++++++++++++++++++++++++++
 src/common/proximity_ranging.h |  1 +
 wpa_supplicant/nan_usd.c       | 25 +++++++++++++---
 wpa_supplicant/pr_supplicant.c |  6 ++++
 wpa_supplicant/pr_supplicant.h |  6 ++++
 8 files changed, 145 insertions(+), 16 deletions(-)

diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h
index c5341d3b0..2c094ef25 100644
--- a/src/common/ieee802_11_defs.h
+++ b/src/common/ieee802_11_defs.h
@@ -1477,6 +1477,12 @@ struct ieee80211_ampe_ie {
 #define RSNXE_OVERRIDE_IE_VENDOR_TYPE 0x506f9a2b
 #define RSN_SELECTION_IE_VENDOR_TYPE 0x506f9a2c
 
+/* TODO: The PR_IE_VENDOR_TYPE has not been finalized yet.
+ * Please update the type once it is confirmed.
+ */
+#define PR_IE_VENDOR_TYPE 0x506f9afe
+
+
 #define MULTI_AP_SUB_ELEM_TYPE 0x06
 #define MULTI_AP_PROFILE_SUB_ELEM_TYPE 0x07
 #define MULTI_AP_VLAN_SUB_ELEM_TYPE 0x08
@@ -3165,6 +3171,13 @@ struct ieee80211_s1g_beacon_compat {
 	le32 tsf_completion;
 } STRUCT_PACKED;
 
+/* Proximity Ranging (PR) */
+
+/* TODO: The PR_OUI_TYPE has not been finalized yet.
+ * Please update the OUI type once it is confirmed.
+ */
+#define PR_OUI_TYPE 0xFE
+
 #ifdef _MSC_VER
 #pragma pack(pop)
 #endif /* _MSC_VER */
diff --git a/src/common/nan_de.c b/src/common/nan_de.c
index 2833211f9..ba038094b 100644
--- a/src/common/nan_de.c
+++ b/src/common/nan_de.c
@@ -64,6 +64,7 @@ struct nan_de_service {
 	struct os_reltime next_publish_chan;
 	unsigned int next_publish_duration;
 	bool is_p2p;
+	bool is_pr;
 };
 
 struct nan_de {
@@ -1328,7 +1329,7 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
 	int publish_id;
 	struct nan_de_service *srv;
 
-	if (!service_name) {
+	if (!service_name && !params->proximity_ranging) {
 		wpa_printf(MSG_DEBUG, "NAN: Publish() - no service_name");
 		return -1;
 	}
@@ -1339,6 +1340,12 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
 		return -1;
 	}
 
+	if (params->proximity_ranging && params->solicited && !elems) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: Unable to fetch proximity ranging params");
+		return -1;
+	}
+
 	publish_id = nan_de_get_handle(de);
 	if (publish_id < 1)
 		return -1;
@@ -1348,11 +1355,18 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
 		return -1;
 	srv->type = NAN_DE_PUBLISH;
 	srv->freq = srv->default_freq = params->freq;
-	srv->service_name = os_strdup(service_name);
-	if (!srv->service_name)
-		goto fail;
-	if (nan_de_derive_service_id(srv) < 0)
+
+	if (service_name) {
+		srv->service_name = os_strdup(service_name);
+		if (!srv->service_name)
+			goto fail;
+	}
+
+	if (params->proximity_ranging && !service_name)
+		os_memset(srv->service_id, 0, NAN_SERVICE_ID_LEN);
+	else if (nan_de_derive_service_id(srv) < 0)
 		goto fail;
+
 	os_memcpy(&srv->publish, params, sizeof(*params));
 
 	if (params->freq_list) {
@@ -1383,9 +1397,10 @@ int nan_de_publish(struct nan_de *de, const char *service_name,
 	nan_de_start_new_publish_state(srv, true);
 
 	wpa_printf(MSG_DEBUG, "NAN: Assigned new publish handle %d for %s",
-		   publish_id, service_name);
+		   publish_id, service_name ? service_name : "Ranging");
 	srv->id = publish_id;
 	srv->is_p2p = p2p;
+	srv->is_pr = params->proximity_ranging && params->solicited;
 	nan_de_add_srv(de, srv);
 	nan_de_run_timer(de);
 	return publish_id;
@@ -1468,11 +1483,17 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
 	int subscribe_id;
 	struct nan_de_service *srv;
 
-	if (!service_name) {
+	if (!service_name && !params->proximity_ranging) {
 		wpa_printf(MSG_DEBUG, "NAN: Subscribe() - no service_name");
 		return -1;
 	}
 
+	if (params->proximity_ranging && params->active && !elems) {
+		wpa_printf(MSG_ERROR,
+			   "NAN: Unable to fetch proximity ranging params");
+		return -1;
+	}
+
 	subscribe_id = nan_de_get_handle(de);
 	if (subscribe_id < 1)
 		return -1;
@@ -1482,11 +1503,18 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
 		return -1;
 	srv->type = NAN_DE_SUBSCRIBE;
 	srv->freq = params->freq;
-	srv->service_name = os_strdup(service_name);
-	if (!srv->service_name)
-		goto fail;
-	if (nan_de_derive_service_id(srv) < 0)
+
+	if (service_name) {
+		srv->service_name = os_strdup(service_name);
+		if (!srv->service_name)
+			goto fail;
+	}
+
+	if (params->proximity_ranging && !service_name)
+		os_memset(srv->service_id, 0, NAN_SERVICE_ID_LEN);
+	else if (nan_de_derive_service_id(srv) < 0)
 		goto fail;
+
 	os_memcpy(&srv->subscribe, params, sizeof(*params));
 
 	if (params->freq_list) {
@@ -1512,9 +1540,10 @@ int nan_de_subscribe(struct nan_de *de, const char *service_name,
 	}
 
 	wpa_printf(MSG_DEBUG, "NAN: Assigned new subscribe handle %d for %s",
-		   subscribe_id, service_name);
+		   subscribe_id, service_name ? service_name : "Ranging");
 	srv->id = subscribe_id;
 	srv->is_p2p = p2p;
+	srv->is_pr = params->proximity_ranging && params->active;
 	nan_de_add_srv(de, srv);
 	nan_de_run_timer(de);
 	return subscribe_id;
diff --git a/src/common/nan_de.h b/src/common/nan_de.h
index 2900bab5c..7f0836332 100644
--- a/src/common/nan_de.h
+++ b/src/common/nan_de.h
@@ -110,6 +110,9 @@ struct nan_publish_params {
 
 	/* Announcement period in ms; 0 = use default */
 	unsigned int announcement_period;
+
+	/* Proximity ranging flag */
+	bool proximity_ranging;
 };
 
 /* Returns -1 on failure or >0 publish_id */
@@ -143,6 +146,9 @@ struct nan_subscribe_params {
 
 	/* Query period in ms; 0 = use default */
 	unsigned int query_period;
+
+	/*  Proximity ranging flag */
+	bool proximity_ranging;
 };
 
 /* Returns -1 on failure or >0 subscribe_id */
diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index 287bff2f7..ab61f6e3a 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -51,3 +51,54 @@ void pr_deinit(struct pr_data *pr)
 	os_free(pr);
 	wpa_printf(MSG_DEBUG, "PR: Deinit done");
 }
+
+
+static struct wpabuf * pr_encaps_ie(const struct wpabuf *subelems, u32 ie_type)
+{
+	struct wpabuf *ie = NULL;
+	const u8 *pos, *end;
+	size_t len = 0;
+
+	if (!subelems)
+		return NULL;
+
+	len = wpabuf_len(subelems) + 1000;
+
+	ie = wpabuf_alloc(len);
+
+	if (!ie)
+		return NULL;
+
+	pos = wpabuf_head(subelems);
+	end = pos + wpabuf_len(subelems);
+
+	while (end > pos) {
+		size_t frag_len = end - pos;
+
+		if (frag_len > 251)
+			frag_len = 251;
+		wpabuf_put_u8(ie, WLAN_EID_VENDOR_SPECIFIC);
+		wpabuf_put_u8(ie, 4 + frag_len);
+		wpabuf_put_be32(ie, ie_type);
+		wpabuf_put_data(ie, pos, frag_len);
+		pos += frag_len;
+	}
+	return ie;
+}
+
+
+struct wpabuf * pr_prepare_usd_elems(struct pr_data *pr, const char *country)
+{
+	u32 ie_type;
+	struct wpabuf *buf, *buf2;
+
+	buf = wpabuf_alloc(1000);
+	if (!buf)
+		return NULL;
+
+	ie_type = (OUI_WFA << 8) | PR_OUI_TYPE;
+	buf2 = pr_encaps_ie(buf, ie_type);
+	wpabuf_free(buf);
+
+	return buf2;
+}
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 9992c005c..8ebc363c1 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -145,5 +145,6 @@ 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);
 
 #endif /* PROXIMITY_RANGING_H */
diff --git a/wpa_supplicant/nan_usd.c b/wpa_supplicant/nan_usd.c
index b2d195ca7..68b2e6521 100644
--- a/wpa_supplicant/nan_usd.c
+++ b/wpa_supplicant/nan_usd.c
@@ -16,6 +16,7 @@
 #include "notify.h"
 #include "p2p_supplicant.h"
 #include "nan_usd.h"
+#include "pr_supplicant.h"
 
 
 static const char *
@@ -388,11 +389,19 @@ int wpas_nan_usd_publish(struct wpa_supplicant *wpa_s, const char *service_name,
 	if (!wpa_s->nan_de)
 		return -1;
 
+	if (params->proximity_ranging && !params->solicited) {
+		wpa_printf(MSG_ERROR,
+			   "PR unsolicited publish service discovery not allowed");
+		return -1;
+	}
+
+	addr = wpa_s->own_addr;
+
 	if (p2p) {
 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
 		addr = wpa_s->global->p2p_dev_addr;
-	} else {
-		addr = wpa_s->own_addr;
+	} else if (params->proximity_ranging) {
+		elems = wpas_pr_usd_elems(wpa_s);
 	}
 
 	publish_id = nan_de_publish(wpa_s->nan_de, service_name, srv_proto_type,
@@ -460,11 +469,19 @@ int wpas_nan_usd_subscribe(struct wpa_supplicant *wpa_s,
 	if (!wpa_s->nan_de)
 		return -1;
 
+	if (params->proximity_ranging && !params->active) {
+		wpa_printf(MSG_ERROR,
+			   "PR passive subscriber service discovery not allowed");
+		return -1;
+	}
+
+	addr = wpa_s->own_addr;
+
 	if (p2p) {
 		elems = wpas_p2p_usd_elems(wpa_s, service_name);
 		addr = wpa_s->global->p2p_dev_addr;
-	} else {
-		addr = wpa_s->own_addr;
+	} else if (params->proximity_ranging) {
+		elems = wpas_pr_usd_elems(wpa_s);
 	}
 
 	subscribe_id = nan_de_subscribe(wpa_s->nan_de, service_name,
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index 308eac9b1..59955d6dc 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -74,6 +74,12 @@ static int wpas_pr_setup_channels(struct wpa_supplicant *wpa_s,
 	return 0;
 }
 
+struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s)
+{
+	return pr_prepare_usd_elems(wpa_s->global->pr, wpa_s->conf->country);
+}
+
+
 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 fc8019dda..b2469781a 100644
--- a/wpa_supplicant/pr_supplicant.h
+++ b/wpa_supplicant/pr_supplicant.h
@@ -15,6 +15,7 @@
 
 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);
 #else /* CONFIG_PR */
 static inline int wpas_pr_init(struct wpa_global *global,
 			       struct wpa_supplicant *wpa_s)
@@ -26,6 +27,11 @@ static inline void wpas_pr_deinit(struct wpa_supplicant *wpa_s)
 {
 }
 
+static inline struct wpabuf * wpas_pr_usd_elems(struct wpa_supplicant *wpa_s)
+{
+	return NULL;
+}
+
 #endif /* CONFIG_PR */
 
 #endif /*PR_SUPPLICANT_H */
-- 
2.34.1




More information about the Hostap mailing list