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@xxxxxxxxxxxxxxxx> --- 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 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap