From df6745e8c8c1312d41f3e7fd044f438408526a2b Mon Sep 17 00:00:00 2001 From: Markus Theil Date: Tue, 30 Jun 2020 13:53:19 +0200 Subject: [PATCH] wpa_supplicant: Handle HT40 and mode downgrade in AP mode Add some missing pieces to the interface configuration of AP/mesh mode in wpa_supplicant. - check for secondary channel and HT40 capability - try to downgrade to IEEE 802.11b if 802.11g is not available Especially with the HT40 check, this code now performs all settings, which the deleted/duplicated mesh code did. Signed-off-by: Markus Theil --- wpa_supplicant/ap.c | 52 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 9 deletions(-) diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 895b62ae3..bac79b2e4 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -134,6 +134,24 @@ no_vht: } +static struct hostapd_hw_modes * +wpa_supplicant_find_hw_mode(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode hw_mode) +{ + struct hostapd_hw_modes *mode = NULL; + int i; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + if (wpa_s->hw.modes[i].mode == hw_mode) { + mode = &wpa_s->hw.modes[i]; + break; + } + } + + return mode; +} + + int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, struct hostapd_config *conf) @@ -147,9 +165,6 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, return -1; } - /* TODO: enable HT40 if driver supports it; - * drop to 11b if driver does not support 11g */ - /* * Enable HT20 if the driver supports it, by setting conf->ieee80211n * and a mask of allowed capabilities within conf->ht_capab. @@ -158,17 +173,28 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, */ if (wpa_s->hw.modes) { struct hostapd_hw_modes *mode = NULL; - int i, no_ht = 0; + int no_ht = 0; wpa_printf(MSG_DEBUG, "Determining HT/VHT options based on driver capabilities (freq=%u chan=%u)", ssid->frequency, conf->channel); - for (i = 0; i < wpa_s->hw.num_modes; i++) { - if (wpa_s->hw.modes[i].mode == conf->hw_mode) { - mode = &wpa_s->hw.modes[i]; - break; - } + mode = wpa_supplicant_find_hw_mode(wpa_s, conf->hw_mode); + + /* May drop to IEEE 802.11b if the driver does not support IEEE + * 802.11g */ + if (!mode && conf->hw_mode == HOSTAPD_MODE_IEEE80211G) { + conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + wpa_printf(MSG_INFO, + "Try downgrade to IEEE 802.11b as 802.11g is not supported by the current hardware"); + mode = wpa_supplicant_find_hw_mode(wpa_s, + conf->hw_mode); + } + + if (!mode) { + wpa_printf(MSG_ERROR, + "No match between requested and supported hw modes found"); + return -1; } #ifdef CONFIG_HT_OVERRIDES @@ -193,6 +219,14 @@ int wpa_supplicant_conf_ap_ht(struct wpa_supplicant *wpa_s, HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET), ssid->ht40); conf->ieee80211n = 1; + + if (ssid->ht40 && + (mode->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + conf->secondary_channel = ssid->ht40; + else + conf->secondary_channel = 0; + #ifdef CONFIG_P2P if (ssid->p2p_group && conf->hw_mode == HOSTAPD_MODE_IEEE80211A &&