[PATCH v3 03/36] PR: Update channels that are supported to perform ranging
Peddolla Harshavardhan Reddy
peddolla at qti.qualcomm.com
Thu Aug 28 08:42:38 PDT 2025
Add changes to fetch supported channels for ranging and store them in
Proximity Ranging global context.
This includes channels where Enhanced Distributed channel Access
(EDCA-802.11mc) is supported as well channels where Non-Trigger Based
(NTB-802.11az) ranging is supported based on the corresponding format
and bandwidth.
Signed-off-by: Peddolla Harshavardhan Reddy <peddolla at qti.qualcomm.com>
---
src/common/proximity_ranging.h | 73 +++++++++++
wpa_supplicant/pr_supplicant.c | 224 +++++++++++++++++++++++++++++++++
2 files changed, 297 insertions(+)
diff --git a/src/common/proximity_ranging.h b/src/common/proximity_ranging.h
index affabc19c..7b63c35dc 100644
--- a/src/common/proximity_ranging.h
+++ b/src/common/proximity_ranging.h
@@ -14,11 +14,80 @@
#include "drivers/driver.h"
+/**
+ * PR_MAX_OP_CLASSES - Maximum number of operating classes
+ */
+#define PR_MAX_OP_CLASSES 15
+
+/**
+ * PR_MAX_OP_CLASS_CHANNELS - Maximum number of channels per operating class
+ */
+#define PR_MAX_OP_CLASS_CHANNELS 60
+
/**
* PR_MAX_PEER - Maximum number of Proximity Ranging peers that device can store
*/
#define PR_MAX_PEER 100
+/**
+ * struct pr_channels - List of supported channels
+ */
+struct pr_channels {
+ /**
+ * struct pr_op_class - Supported operating class
+ */
+ struct pr_op_class {
+ /**
+ * op_class - Regulatory class (IEEE 802.11-2020)
+ */
+ u8 op_class;
+
+ /**
+ * channel - Supported channels
+ */
+ u8 channel[PR_MAX_OP_CLASS_CHANNELS];
+
+ /**
+ * channels - Number of channel entries in use
+ */
+ size_t channels;
+ } op_class[PR_MAX_OP_CLASSES];
+
+ /**
+ * op_classes - Number of op_class entries in use
+ */
+ size_t op_classes;
+};
+
+/**
+ * Format and Bandwidth values for EDCA based ranging with range of 10-16
+ * specified in (Proximity Ranging Implementation Considerations for P2P
+ * Operation July 2025 Draft 1.8 Table-8)
+ */
+enum edca_fomat_and_bw_value {
+ EDCA_FORMAT_AND_BW_VHT20 = 10,
+ EDCA_FORMAT_AND_BW_HT40 = 11,
+ EDCA_FORMAT_AND_BW_VHT40 = 12,
+ EDCA_FORMAT_AND_BW_VHT80 = 13,
+ EDCA_FORMAT_AND_BW_VHT80P80 = 14,
+ EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO = 15,
+ EDCA_FORMAT_AND_BW_VHT160_DUAL_LO = 16
+};
+
+/**
+ * Format and Bandwidth values for NTB based ranging as
+ * specified in (Proximity Ranging Implementation Considerations for P2P
+ * Operation July 2025 Draft 1.8 Table-9)
+ */
+enum ntb_fomat_and_bw_value {
+ NTB_FORMAT_AND_BW_HE20 = 0,
+ NTB_FORMAT_AND_BW_HE40 = 1,
+ NTB_FORMAT_AND_BW_HE80 = 2,
+ NTB_FORMAT_AND_BW_HE80P80 = 3,
+ NTB_FORMAT_AND_BW_HE160_SINGLE_LO = 4,
+ NTB_FORMAT_AND_BW_HE160_DUAL_LO = 5
+};
+
/**
* struct pr_device_info - Proximity ranging peer information
*/
@@ -57,6 +126,8 @@ struct pr_config {
u8 max_rx_antenna;
+ struct pr_channels edca_channels;
+
bool ntb_ista_support;
bool ntb_rsta_support;
@@ -81,6 +152,8 @@ struct pr_config {
u8 ntb_format_and_bw;
+ struct pr_channels ntb_channels;
+
bool support_6ghz;
diff --git a/wpa_supplicant/pr_supplicant.c b/wpa_supplicant/pr_supplicant.c
index a69385980..98dafaa56 100644
--- a/wpa_supplicant/pr_supplicant.c
+++ b/wpa_supplicant/pr_supplicant.c
@@ -19,6 +19,223 @@
#include "pr_supplicant.h"
+int wpas_pr_edca_get_bw(int format_and_bw)
+{
+ switch (format_and_bw) {
+ case EDCA_FORMAT_AND_BW_VHT20:
+ return 20;
+ case EDCA_FORMAT_AND_BW_HT40:
+ case EDCA_FORMAT_AND_BW_VHT40:
+ return 40;
+ case EDCA_FORMAT_AND_BW_VHT80:
+ return 80;
+ case EDCA_FORMAT_AND_BW_VHT80P80:
+ case EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO:
+ case EDCA_FORMAT_AND_BW_VHT160_DUAL_LO:
+ return 160;
+ default:
+ return 0;
+ }
+}
+
+
+int wpas_pr_ntb_get_bw(int format_and_bw)
+{
+ switch (format_and_bw) {
+ case NTB_FORMAT_AND_BW_HE20:
+ return 20;
+ case NTB_FORMAT_AND_BW_HE40:
+ return 40;
+ case NTB_FORMAT_AND_BW_HE80:
+ return 80;
+ case NTB_FORMAT_AND_BW_HE80P80:
+ case NTB_FORMAT_AND_BW_HE160_SINGLE_LO:
+ case NTB_FORMAT_AND_BW_HE160_DUAL_LO:
+ return 160;
+ default:
+ return 0;
+ }
+}
+
+
+int wpas_pr_edca_is_valid_op_class(int format_and_bw,
+ const struct oper_class_map *op_class_map)
+{
+ int bw = 0, op_class_bw = 0;
+
+ if (!op_class_map)
+ return -1;
+
+ op_class_bw = oper_class_bw_to_int(op_class_map);
+ bw = wpas_pr_edca_get_bw(format_and_bw);
+
+ if (!op_class_bw || !bw)
+ return -1;
+
+ if (format_and_bw <= EDCA_FORMAT_AND_BW_VHT80 &&
+ format_and_bw >= EDCA_FORMAT_AND_BW_VHT20 &&
+ op_class_bw <= bw) {
+ return 0;
+ } else if (format_and_bw == EDCA_FORMAT_AND_BW_VHT80P80 &&
+ (op_class_bw < bw || op_class_map->bw == BW80P80)) {
+ return 0;
+ } else if ((format_and_bw == EDCA_FORMAT_AND_BW_VHT160_DUAL_LO ||
+ format_and_bw == EDCA_FORMAT_AND_BW_VHT160_SINGLE_LO) &&
+ (op_class_bw < bw || op_class_map->bw == BW160)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+int wpas_pr_ntb_is_valid_op_class(int format_and_bw,
+ const struct oper_class_map *op_class_map)
+{
+ int bw = 0, op_class_bw = 0;
+
+ if (!op_class_map)
+ return -1;
+
+ op_class_bw = oper_class_bw_to_int(op_class_map);
+ bw = wpas_pr_ntb_get_bw(format_and_bw);
+
+ if (!op_class_bw || !bw)
+ return -1;
+
+ if (format_and_bw <= NTB_FORMAT_AND_BW_HE80 &&
+ format_and_bw >= NTB_FORMAT_AND_BW_HE20 &&
+ op_class_bw <= bw) {
+ return 0;
+ } else if (format_and_bw == NTB_FORMAT_AND_BW_HE80P80 &&
+ (op_class_bw < bw || op_class_map->bw == BW80P80)) {
+ return 0;
+ } else if ((format_and_bw == NTB_FORMAT_AND_BW_HE160_DUAL_LO ||
+ format_and_bw == NTB_FORMAT_AND_BW_HE160_SINGLE_LO) &&
+ (op_class_bw < bw || op_class_map->bw == BW160)) {
+ return 0;
+ }
+
+ return -1;
+}
+
+
+static int wpas_pr_setup_edca_channels(struct wpa_supplicant *wpa_s,
+ struct pr_channels *chan,
+ int format_and_bw)
+{
+ int cla = 0, i;
+ struct hostapd_hw_modes *mode;
+
+ for (i = 0; global_op_class[i].op_class; i++) {
+ unsigned int ch;
+ struct pr_op_class *op = NULL;
+ const struct oper_class_map *o = &global_op_class[i];
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode,
+ is_6ghz_op_class(o->op_class));
+ if (!mode || is_6ghz_op_class(o->op_class) ||
+ wpas_pr_edca_is_valid_op_class(format_and_bw, o))
+ continue;
+
+ for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+ enum chan_allowed res;
+
+ /* Check for non-continuous jump in channel index
+ * increment.
+ */
+ if ((o->op_class >= 128 && o->op_class <= 130) &&
+ ch < 149 && ch + o->inc > 149)
+ ch = 149;
+
+ res = verify_channel(mode, o->op_class, ch, o->bw);
+
+ if (res == ALLOWED) {
+ if (!op) {
+ if (cla == PR_MAX_OP_CLASSES)
+ continue;
+ wpa_printf(MSG_DEBUG, "PR: Add operating class: %u",
+ o->op_class);
+ op = &chan->op_class[cla];
+ cla++;
+ op->op_class = o->op_class;
+ }
+ if (op->channels == PR_MAX_OP_CLASS_CHANNELS)
+ continue;
+ op->channel[op->channels] = ch;
+ op->channels++;
+ }
+ }
+ if (op) {
+ wpa_hexdump(MSG_DEBUG, "PR: Channels",
+ op->channel, op->channels);
+ }
+ }
+
+ chan->op_classes = cla;
+
+ return 0;
+}
+
+
+static int wpas_pr_setup_ntb_channels(struct wpa_supplicant *wpa_s,
+ struct pr_channels *chan,
+ int format_and_bw, bool allow_6ghz)
+{
+ int cla = 0, i;
+ struct hostapd_hw_modes *mode;
+
+ for (i = 0; global_op_class[i].op_class; i++) {
+ unsigned int ch;
+ struct pr_op_class *op = NULL;
+ const struct oper_class_map *o = &global_op_class[i];
+
+ mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, o->mode,
+ is_6ghz_op_class(o->op_class));
+ if (!mode || (!allow_6ghz && is_6ghz_op_class(o->op_class)) ||
+ wpas_pr_ntb_is_valid_op_class(format_and_bw, o))
+ continue;
+
+ for (ch = o->min_chan; ch <= o->max_chan; ch += o->inc) {
+ enum chan_allowed res;
+
+ /* Check for non-continuous jump in channel index
+ * increment.
+ */
+ if ((o->op_class >= 128 && o->op_class <= 130) &&
+ ch < 149 && ch + o->inc > 149)
+ ch = 149;
+
+ res = verify_channel(mode, o->op_class, ch, o->bw);
+
+ if (res == ALLOWED) {
+ if (!op) {
+ if (cla == PR_MAX_OP_CLASSES)
+ continue;
+ wpa_printf(MSG_DEBUG, "PR: Add operating class: %u",
+ o->op_class);
+ op = &chan->op_class[cla];
+ cla++;
+ op->op_class = o->op_class;
+ }
+ if (op->channels == PR_MAX_OP_CLASS_CHANNELS)
+ continue;
+ op->channel[op->channels] = ch;
+ op->channels++;
+ }
+ }
+ if (op) {
+ wpa_hexdump(MSG_DEBUG, "PR: Channels",
+ op->channel, op->channels);
+ }
+ }
+
+ chan->op_classes = cla;
+
+ return 0;
+}
+
+
int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
{
struct pr_config pr;
@@ -42,6 +259,9 @@ int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
pr.max_rx_antenna = wpa_s->max_rx_antenna;
pr.max_tx_antenna = wpa_s->max_tx_antenna;
+ wpas_pr_setup_edca_channels(wpa_s, &pr.edca_channels,
+ pr.edca_format_and_bw);
+
pr.ntb_ista_support = (wpa_s->drv_flags2
& WPA_DRIVER_FLAGS2_NON_TRIGGER_BASED_INITIATOR);
pr.ntb_rsta_support = (wpa_s->drv_flags2 &
@@ -60,6 +280,10 @@ int wpas_pr_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
pr.secure_he_ltf = wpa_s->drv_flags2 & WPA_DRIVER_FLAGS2_SEC_LTF_STA;
+ wpas_pr_setup_ntb_channels(wpa_s, &pr.ntb_channels,
+ pr.ntb_format_and_bw,
+ pr.support_6ghz);
+
if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) {
os_memcpy(pr.country, wpa_s->conf->country, 2);
pr.country[2] = 0x04;
--
2.34.1
More information about the Hostap
mailing list