[PATCH v2 3/5] PR: Use preferred frequency for channel selection in PASN ranging
Peddolla Harshavardhan Reddy
peddolla.reddy at oss.qualcomm.com
Fri Jul 31 02:52:25 PDT 2026
Currently the channel for proximity ranging is always selected
automatically from the common channel set using the best available
option. This gives no control to the caller over which channel is
used for ranging.
Add a preferred_freq field to pr_pasn_ranging_params. When set,
the op_class with the highest bandwidth whose channel range covers
the preferred frequency is selected from the common channel set.
If the preferred frequency is not present in the common channel
set, automatic channel selection is used as a fallback.
Channel numbers are op_class-specific so the match is done by
comparing the preferred frequency against the frequency range
[chan_freq, chan_freq + bw) of each entry. 80+80 MHz entries are
skipped since their two segments are not contiguous and a single
channel entry cannot reliably represent the full range.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla.reddy at oss.qualcomm.com>
---
src/common/proximity_ranging.c | 80 ++++++++++++++++++++++++++++++++--
src/common/proximity_ranging.h | 1 +
2 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/src/common/proximity_ranging.c b/src/common/proximity_ranging.c
index 5e39bfaf0..bc177d50d 100644
--- a/src/common/proximity_ranging.c
+++ b/src/common/proximity_ranging.c
@@ -609,6 +609,57 @@ static void pr_channels_intersect(const struct pr_channels *a,
}
}
+
+static bool pr_get_preferred_channel(int preferred_freq,
+ const struct pr_channels *common_chan,
+ u8 *op_class, u8 *op_channel)
+{
+ const struct oper_class_map *map;
+ u8 best_op_class = 0, best_channel = 0;
+ u8 op_class_num;
+ int best_bw = 0;
+ size_t i, j;
+
+ if (!preferred_freq || !common_chan || !op_class || !op_channel)
+ return false;
+
+ /*
+ * Channel numbers are op_class-specific, so compare by frequency
+ * range instead. Pick the widest-bandwidth match.
+ */
+ for (i = 0; i < common_chan->op_classes; i++) {
+ op_class_num = common_chan->op_class[i].op_class;
+ map = get_oper_class(NULL, op_class_num);
+ if (!map || map->bw == BW80P80)
+ continue;
+ for (j = 0; j < common_chan->op_class[i].channels; j++) {
+ u8 chan = common_chan->op_class[i].channel[j];
+ int chan_freq, bw;
+
+ chan_freq = ieee80211_chan_to_freq(NULL, op_class_num,
+ chan);
+ if (chan_freq < 0)
+ continue;
+ bw = oper_class_bw_to_int(map);
+ if (preferred_freq < chan_freq ||
+ preferred_freq >= chan_freq + bw)
+ continue;
+ if (bw > best_bw) {
+ best_bw = bw;
+ best_op_class = op_class_num;
+ best_channel = chan;
+ }
+ }
+ }
+
+ if (!best_op_class)
+ return false;
+
+ *op_class = best_op_class;
+ *op_channel = best_channel;
+ return true;
+}
+
#endif /* CONFIG_PASN */
@@ -1409,6 +1460,7 @@ static u8 pr_pasn_get_best_op_mode(struct pr_data *pr, u8 peer_supp_roles,
int status = PR_NEGOTIATION_FAIL;
u8 op_class = 0, op_channel = 0;
bool own_ista_support = false, own_rsta_support = false;
+ bool preferred_found;
if (op_mode->protocol_type &
(PR_NTB_SECURE_LTF_BASED_RANGING | PR_NTB_OPEN_BASED_RANGING)) {
@@ -1510,11 +1562,24 @@ static u8 pr_pasn_get_best_op_mode(struct pr_data *pr, u8 peer_supp_roles,
res_op_mode->protocol_type = ranging_type;
os_memcpy(res_op_mode->country, pr->cfg->country, 3);
- if (res_op_mode->role == PR_RSTA_SUPPORT) {
+ preferred_found = pr->pr_pasn_params &&
+ pr->pr_pasn_params->preferred_freq &&
+ pr_get_preferred_channel(pr->pr_pasn_params->preferred_freq,
+ &common_chan, &op_class, &op_channel);
+
+ if (!preferred_found && res_op_mode->role == PR_RSTA_SUPPORT) {
pr_copy_channels(&res_op_mode->channels, &common_chan,
pr->cfg->support_6ghz);
} else {
- pr_choose_best_channel(&common_chan, &op_class, &op_channel);
+ if (preferred_found) {
+ wpa_printf(MSG_DEBUG,
+ "PR: Using preferred_freq %d: op_class=%u, channel=%u",
+ pr->pr_pasn_params->preferred_freq,
+ op_class, op_channel);
+ } else {
+ pr_choose_best_channel(&common_chan, &op_class,
+ &op_channel);
+ }
if (!op_class || !op_channel) {
wpa_printf(MSG_DEBUG,
"PR: Couldn't choose a common channel for ranging in ISTA role");
@@ -1614,7 +1679,16 @@ static u8 pr_pasn_get_final_op_mode(struct pr_data *pr, u8 supp_roles,
return PR_NEGOTIATION_FAIL;
}
- pr_choose_best_channel(&common_chan, &op_class, &op_channel);
+ if (pr->pr_pasn_params && pr->pr_pasn_params->preferred_freq &&
+ pr_get_preferred_channel(pr->pr_pasn_params->preferred_freq,
+ &common_chan, &op_class, &op_channel)) {
+ wpa_printf(MSG_DEBUG,
+ "PR: Using preferred_freq %d: op_class=%u, channel=%u",
+ pr->pr_pasn_params->preferred_freq, op_class,
+ op_channel);
+ } else {
+ pr_choose_best_channel(&common_chan, &op_class, &op_channel);
+ }
if (!op_class || !op_channel) {
wpa_printf(MSG_INFO,
"PR: Couldn't choose a common channel for ranging");
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index 6ce9f6922..1a28b3bf5 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -364,6 +364,7 @@ struct pr_pasn_ranging_params {
u32 continuous_ranging_session_time;
int forced_pr_freq;
+ int preferred_freq;
u8 ranging_op_class;
u16 channel_width; /* channel width in MHz (20/40/80/160/320) */
u8 format_bw;
--
2.34.1
More information about the Hostap
mailing list