diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 7b4380605..d4d0c92c9 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -1106,6 +1106,10 @@ static int hostapd_config_ht_capab(struct hostapd_config *conf, conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; conf->secondary_channel = 1; } + if (os_strstr(capab, "[HT40+]") && os_strstr(capab, "[HT40-]")) { + conf->ht_capab |= HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + conf->ht40_plus_minus_allowed = 1; + } if (os_strstr(capab, "[SMPS-STATIC]")) { conf->ht_capab &= ~HT_CAP_INFO_SMPS_MASK; conf->ht_capab |= HT_CAP_INFO_SMPS_STATIC; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 989b07107..498891c54 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -724,6 +724,7 @@ struct hostapd_config { u8 vht_oper_chwidth; u8 vht_oper_centr_freq_seg0_idx; u8 vht_oper_centr_freq_seg1_idx; + u8 ht40_plus_minus_allowed; /* Use driver-generated interface addresses when adding multiple BSSs */ u8 use_driver_iface_addr; diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 93d923af5..c677d30f4 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -722,14 +722,33 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface, static int hostapd_is_usable_chans(struct hostapd_iface *iface) { + int secondary_chan; + if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) return 0; if (!iface->conf->secondary_channel) return 1; - return hostapd_is_usable_chan(iface, iface->conf->channel + - iface->conf->secondary_channel * 4, 0); + if (!iface->conf->ht40_plus_minus_allowed) + return hostapd_is_usable_chan( + iface, iface->conf->channel + + iface->conf->secondary_channel * 4, 0); + + /* Both HT40+ and HT40- are set, pick a valid secondary channel */ + secondary_chan = iface->conf->channel + 4; + if (hostapd_is_usable_chan(iface, secondary_chan, 0)) { + iface->conf->secondary_channel = 1; + return 1; + } + + secondary_chan = iface->conf->channel - 4; + if (hostapd_is_usable_chan(iface, secondary_chan, 0)) { + iface->conf->secondary_channel = -1; + return 1; + } + + return 0; }