[RFC PATCH v2 18/23] PR: Add extended ranging parameters to PASN peer structure

Peddolla Harshavardhan Reddy peddolla.reddy at oss.qualcomm.com
Thu Apr 2 05:24:23 PDT 2026


Add EDCA, NTB, and continuous ranging parameters to the single-peer
pr_pasn_ranging_params structure. This enables comprehensive ranging
configuration for proximity ranging operations.

EDCA parameters:
- burst_period, num_bursts_exp, ftms_per_burst
- ftmr_retries, burst_duration

NTB parameters:
- min_time_between_measurements, max_time_between_measurements
- availability_window, nominal_time, measurements_per_aw

Continuous ranging and location parameters:
- request_lci, request_civicloc
- trigger_continuous_ranging
- continuous_ranging_interval, continuous_ranging_session_time

Enhanced wpas_pr_pasn_trigger() with debug logging for all parameter
categories to aid in debugging and verification of ranging operations.

Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>
---
 src/common/proximity_ranging.h |  78 +++++++++++++
 wpa_supplicant/pr_supplicant.c | 203 ++++++++++++++++++++++++++++++++-
 2 files changed, 280 insertions(+), 1 deletion(-)

diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index b7e9da303..cd12aaa50 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -275,6 +275,84 @@ struct pr_pasn_ranging_params {
 	int freq;
 	u8 src_addr[ETH_ALEN];
 	enum pr_pasn_role pasn_role;
+
+	/**
+	 * EDCA based ranging specific parameters
+	 *
+	 * @burst_period: Burst period in units of 100 ms
+	 * @num_bursts_exp: Number of bursts exponent
+	 * @ftms_per_burst: Number of FTM frames per burst
+	 * @ftmr_retries: Number of retries for FTM Request frame
+	 * @burst_duration: Burst duration as defined in IEEE 2024 std
+	 *  Table 9-322—Burst Duration subfield encoding.
+	 */
+	u16 burst_period;
+	u8 num_bursts_exp;
+	u8 ftms_per_burst;
+	u8 ftmr_retries;
+	u8 burst_duration;
+
+	/**
+	 * NTB ranging specific parameters
+	 *
+	 * @min_time_between_measurements: Minimum time between two consecutive
+	 *  range measurements in units of 100 micro seconds.
+	 * @max_time_between_measurements: Maximum time between two consecutive
+	 *  range measurements in units of 10 milli seconds, to avoid FTM
+	 *  negotiation.
+	 * @availability_window: Duration of the Availability Window (AW) in
+	 *  units of 1 millisecond (0-255 ms).
+	 * @nominal_time: Nominal duration between adjacent Availability Windows
+	 *  in units of milliseconds.
+	 * @measurements_per_aw: Number of measurement attempts per Availability
+	 *  Window.
+	 */
+	u32 min_time_between_measurements;
+	u32 max_time_between_measurements;
+	u8 availability_window;
+	u32 nominal_time;
+	u8 measurements_per_aw;
+
+	/**
+	 * @request_lci: Whether to request LCI
+	 * @request_civicloc: Whether to request civic location
+	 */
+	bool request_lci;
+	bool request_civicloc;
+
+	/**
+	 * @lmr_feedback: Negotiate LMR feedback for NTB ranging.
+	 * Only valid when NTB ranging type is set. Required for RSTA
+	 * to report measurement results back to the initiator.
+	 */
+	bool lmr_feedback;
+
+	/**
+	 * @ingress_threshold: Ingress range threshold in millimeters.
+	 * Only valid when NL80211_PMSR_PEER_ATTR_PD_REQUEST is set.
+	 * The kernel reports a measurement result when the device
+	 * moves INTO this range.
+	 */
+	u64 ingress_threshold;
+
+	/**
+	 * @egress_threshold: Egress range threshold in millimeters.
+	 * Only valid when NL80211_PMSR_PEER_ATTR_PD_REQUEST is set.
+	 * The kernel reports a measurement result when the device
+	 * moves OUT OF this range.
+	 */
+	u64 egress_threshold;
+
+	/**
+	 * @pr_suppress_results: Suppress ranging results for PD requests.
+	 * Only valid when NL80211_PMSR_PEER_ATTR_PD_REQUEST is set.
+	 * Cannot be used with range_report or lmr_feedback.
+	 */
+	bool pr_suppress_results;
+
+	u32 continuous_ranging_session_time;
+
+	int forced_pr_freq;
 };
 
 struct pr_dev_ik {
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index 496334021..3ccc659ee 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -920,6 +920,136 @@ int wpas_pr_initiate_pasn_auth(struct wpa_supplicant *wpa_s,
 }
 
 
+/**
+ * wpas_pr_validate_ranging_request - Validate PR ranging request parameters
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @pr_pasn_params: Pointer to PR PASN ranging parameters to validate
+ * Returns: 0 on success, -1 on validation failure
+ *
+ * This function validates the ranging request against device capabilities,
+ * driver support, and parameter compatibility before triggering PASN.
+ */
+static int wpas_pr_validate_ranging_request(struct wpa_supplicant *wpa_s,
+					    struct pr_pasn_ranging_params *pr_pasn_params)
+{
+	struct pr_data *pr = wpa_s->global->pr;
+	struct pr_config *cfg;
+	bool is_edca, is_ntb, is_ista;
+
+	if (!pr || !pr->cfg) {
+		wpa_printf(MSG_DEBUG, "PR: PR not initialized");
+		return -1;
+	}
+
+	cfg = pr->cfg;
+
+	/* Peer address must not be all-zeros */
+	if (is_zero_ether_addr(pr_pasn_params->peer_addr)) {
+		wpa_printf(MSG_DEBUG, "PR: Invalid peer address (all zeros)");
+		return -1;
+	}
+
+	/* Frequency must be set */
+	if (!pr_pasn_params->freq) {
+		wpa_printf(MSG_DEBUG, "PR: Invalid frequency (zero)");
+		return -1;
+	}
+
+	/* ranging_type must have at least one valid bit and no unknown bits */
+	if (!pr_pasn_params->ranging_type ||
+	    (pr_pasn_params->ranging_type &
+	     ~(PR_EDCA_BASED_RANGING | PR_NTB_SECURE_LTF_BASED_RANGING |
+	       PR_NTB_OPEN_BASED_RANGING))) {
+		wpa_printf(MSG_DEBUG,
+			   "PR: Invalid ranging_type=0x%x",
+			   pr_pasn_params->ranging_type);
+		return -1;
+	}
+
+	/* ranging_role must have at least one valid bit and no unknown bits */
+	if (!pr_pasn_params->ranging_role ||
+	    (pr_pasn_params->ranging_role &
+	     ~(PR_ISTA_SUPPORT | PR_RSTA_SUPPORT))) {
+		wpa_printf(MSG_DEBUG,
+			   "PR: Invalid ranging_role=0x%x",
+			   pr_pasn_params->ranging_role);
+		return -1;
+	}
+
+	is_edca = !!(pr_pasn_params->ranging_type & PR_EDCA_BASED_RANGING);
+	is_ntb = !!(pr_pasn_params->ranging_type &
+		    (PR_NTB_SECURE_LTF_BASED_RANGING |
+		     PR_NTB_OPEN_BASED_RANGING));
+	is_ista = !!(pr_pasn_params->ranging_role & PR_ISTA_SUPPORT);
+
+	/* Validate ranging type against device capabilities */
+	if (is_edca) {
+		if (is_ista && !cfg->edca_ista_support) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: EDCA ISTA ranging not supported by device");
+			return -1;
+		}
+		if (!is_ista && !cfg->edca_rsta_support) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: EDCA RSTA ranging not supported by device");
+			return -1;
+		}
+	}
+
+	if (is_ntb) {
+		if (is_ista && !cfg->ntb_ista_support) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: NTB ISTA ranging not supported by device");
+			return -1;
+		}
+		if (!is_ista && !cfg->ntb_rsta_support) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: NTB RSTA ranging not supported by device");
+			return -1;
+		}
+
+		/* Secure LTF requires explicit device support */
+		if ((pr_pasn_params->ranging_type &
+		     PR_NTB_SECURE_LTF_BASED_RANGING) &&
+		    !cfg->secure_he_ltf) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: Secure HE-LTF NTB ranging not supported by device");
+			return -1;
+		}
+
+		/* measurements_per_aw max value is 4 per spec */
+		if (pr_pasn_params->measurements_per_aw > 4) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: measurements_per_aw=%u exceeds max (4)",
+				   pr_pasn_params->measurements_per_aw);
+			return -1;
+		}
+
+		/* min must not exceed max time between measurements */
+		if (pr_pasn_params->min_time_between_measurements &&
+		    pr_pasn_params->max_time_between_measurements &&
+		    pr_pasn_params->min_time_between_measurements >
+		    pr_pasn_params->max_time_between_measurements) {
+			wpa_printf(MSG_DEBUG,
+				   "PR: min_time_between_measurements=%u > max=%u",
+				   pr_pasn_params->min_time_between_measurements,
+				   pr_pasn_params->max_time_between_measurements);
+			return -1;
+		}
+	}
+
+	/* lmr_feedback is only valid for NTB ranging */
+	if (pr_pasn_params->lmr_feedback && !is_ntb) {
+		wpa_printf(MSG_DEBUG,
+			   "PR: lmr_feedback is only valid for NTB ranging");
+		return -1;
+	}
+
+	wpa_printf(MSG_DEBUG, "PR: Ranging request validation successful");
+	return 0;
+}
+
+
 /**
  * wpas_pr_pasn_trigger - Trigger PASN authentication for a single peer
  * @wpa_s: Pointer to wpa_supplicant data
@@ -952,6 +1082,13 @@ void wpas_pr_pasn_trigger(struct wpa_supplicant *wpa_s,
 		return;
 	}
 
+	/* VALIDATE REQUEST BEFORE PROCEEDING */
+	if (wpas_pr_validate_ranging_request(wpa_s, pr_pasn_params) < 0) {
+		wpa_printf(MSG_DEBUG, "PR PASN: Request validation failed");
+		pr_pasn_params->pr_pasn_status = PASN_STATUS_FAILURE;
+		return;
+	}
+
 	if (pr_pasn_params->action == PR_PASN_AND_RANGING) {
 		wpa_printf(MSG_DEBUG,
 			   "PR PASN: Triggering PASN authentication for " MACSTR
@@ -983,12 +1120,76 @@ void wpas_pr_pasn_trigger(struct wpa_supplicant *wpa_s,
 		os_memcpy(dst->src_addr, pr_pasn_params->src_addr, ETH_ALEN);
 		dst->pasn_role = pr_pasn_params->pasn_role;
 
+		/* Copy EDCA parameters */
+		dst->burst_period = pr_pasn_params->burst_period;
+		dst->num_bursts_exp = pr_pasn_params->num_bursts_exp;
+		dst->ftms_per_burst = pr_pasn_params->ftms_per_burst;
+		dst->ftmr_retries = pr_pasn_params->ftmr_retries;
+		dst->burst_duration = pr_pasn_params->burst_duration;
+
+		/* Copy NTB parameters */
+		dst->min_time_between_measurements =
+			pr_pasn_params->min_time_between_measurements;
+		dst->max_time_between_measurements =
+			pr_pasn_params->max_time_between_measurements;
+		dst->availability_window = pr_pasn_params->availability_window;
+		dst->nominal_time = pr_pasn_params->nominal_time;
+		dst->measurements_per_aw = pr_pasn_params->measurements_per_aw;
+
+		/* Copy continuous ranging and location parameters */
+		dst->request_lci = pr_pasn_params->request_lci;
+		dst->request_civicloc = pr_pasn_params->request_civicloc;
+		dst->continuous_ranging_session_time =
+			pr_pasn_params->continuous_ranging_session_time;
+
+		/* Copy PD-specific parameters */
+		dst->lmr_feedback = pr_pasn_params->lmr_feedback;
+		dst->ingress_threshold = pr_pasn_params->ingress_threshold;
+		dst->egress_threshold = pr_pasn_params->egress_threshold;
+		dst->pr_suppress_results = pr_pasn_params->pr_suppress_results;
+		dst->forced_pr_freq = pr_pasn_params->forced_pr_freq;
+
+		/* Log EDCA parameters if applicable */
+		if (pr_pasn_params->ranging_type & PR_EDCA_BASED_RANGING) {
+			wpa_printf(MSG_DEBUG,
+				   "PR PASN: EDCA params - burst_period=%u num_bursts_exp=%u "
+				   "ftms_per_burst=%u ftmr_retries=%u burst_duration=%u",
+				   pr_pasn_params->burst_period,
+				   pr_pasn_params->num_bursts_exp,
+				   pr_pasn_params->ftms_per_burst,
+				   pr_pasn_params->ftmr_retries,
+				   pr_pasn_params->burst_duration);
+		}
+
+		/* Log NTB parameters if applicable */
+		if (pr_pasn_params->ranging_type & (PR_NTB_SECURE_LTF_BASED_RANGING |
+						    PR_NTB_OPEN_BASED_RANGING)) {
+			wpa_printf(MSG_DEBUG,
+				   "PR PASN: NTB params - min_time=%u max_time=%u "
+				   "aw=%u nominal_time=%u meas_per_aw=%u",
+				   pr_pasn_params->min_time_between_measurements,
+				   pr_pasn_params->max_time_between_measurements,
+				   pr_pasn_params->availability_window,
+				   pr_pasn_params->nominal_time,
+				   pr_pasn_params->measurements_per_aw);
+		}
+
+		/* Log location request parameters */
+		if (pr_pasn_params->request_lci ||
+		    pr_pasn_params->request_civicloc) {
+			wpa_printf(MSG_DEBUG,
+				   "PR PASN: Location requests - LCI=%d CivicLoc=%d",
+				   pr_pasn_params->request_lci,
+				   pr_pasn_params->request_civicloc);
+		}
+
 		/* Initiate PASN authentication for the peer */
 		if (wpas_pr_initiate_pasn_auth(wpa_s, pr_pasn_params->peer_addr,
 					       pr_pasn_params->freq,
 					       pr_pasn_params->auth_mode,
 					       pr_pasn_params->ranging_role,
-					       pr_pasn_params->ranging_type, 0,
+					       pr_pasn_params->ranging_type,
+					       dst->forced_pr_freq,
 					       pr_pasn_params->src_addr,
 					       pr_pasn_params->pasn_role)) {
 			wpa_printf(MSG_DEBUG,
-- 
2.34.1




More information about the Hostap mailing list