diff options
author | Cy Schubert <cy@FreeBSD.org> | 2018-12-06 05:04:28 +0000 |
---|---|---|
committer | Cy Schubert <cy@FreeBSD.org> | 2018-12-06 05:04:28 +0000 |
commit | 8a36c5c2ca4d1f8a900ca3d9ffde40b96463def7 (patch) | |
tree | b9a3166587c75d5325dc46c7c83ca435f2e54917 /src/ap/hw_features.c | |
parent | 765ef8a7642d07aa9616f2b1a9cdebb8e3552f6a (diff) | |
download | src-test2-8a36c5c2ca4d1f8a900ca3d9ffde40b96463def7.tar.gz src-test2-8a36c5c2ca4d1f8a900ca3d9ffde40b96463def7.zip |
Notes
Diffstat (limited to 'src/ap/hw_features.c')
-rw-r--r-- | src/ap/hw_features.c | 127 |
1 files changed, 48 insertions, 79 deletions
diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index 16887acdfef4..5279abca1f1f 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -78,10 +78,12 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) int i, j; u16 num_modes, flags; struct hostapd_hw_modes *modes; + u8 dfs_domain; if (hostapd_drv_none(hapd)) return -1; - modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); + modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, + &dfs_domain); if (modes == NULL) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, @@ -91,6 +93,7 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) } iface->hw_flags = flags; + iface->dfs_domain = dfs_domain; hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); iface->hw_features = modes; @@ -329,6 +332,9 @@ static void ieee80211n_check_scan(struct hostapd_iface *iface) res = ieee80211n_allowed_ht40_channel_pair(iface); if (!res) { iface->conf->secondary_channel = 0; + iface->conf->vht_oper_centr_freq_seg0_idx = 0; + iface->conf->vht_oper_centr_freq_seg1_idx = 0; + iface->conf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; res = 1; wpa_printf(MSG_INFO, "Fallback to 20 MHz"); } @@ -621,41 +627,6 @@ static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) #ifdef CONFIG_IEEE80211AC - -static int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name) -{ - u32 req_cap = conf & cap; - - /* - * Make sure we support all requested capabilities. - * NOTE: We assume that 'cap' represents a capability mask, - * not a discrete value. - */ - if ((hw & req_cap) != req_cap) { - wpa_printf(MSG_ERROR, "Driver does not support configured VHT capability [%s]", - name); - return 0; - } - return 1; -} - - -static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 mask, - unsigned int shift, - const char *name) -{ - u32 hw_max = hw & mask; - u32 conf_val = conf & mask; - - if (conf_val > hw_max) { - wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)", - name, conf_val >> shift, hw_max >> shift); - return 0; - } - return 1; -} - - static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) { struct hostapd_hw_modes *mode = iface->current_mode; @@ -683,45 +654,7 @@ static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) } } -#define VHT_CAP_CHECK(cap) \ - do { \ - if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \ - return 0; \ - } while (0) - -#define VHT_CAP_CHECK_MAX(cap) \ - do { \ - if (!ieee80211ac_cap_check_max(hw, conf, cap, cap ## _SHIFT, \ - #cap)) \ - return 0; \ - } while (0) - - VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK); - VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ); - VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); - VHT_CAP_CHECK(VHT_CAP_RXLDPC); - VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80); - VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160); - VHT_CAP_CHECK(VHT_CAP_TXSTBC); - VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK); - VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE); - VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE); - VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX); - VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX); - VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE); - VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE); - VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS); - VHT_CAP_CHECK(VHT_CAP_HTC_VHT); - VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX); - VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB); - VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); - VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); - VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); - -#undef VHT_CAP_CHECK -#undef VHT_CAP_CHECK_MAX - - return 1; + return ieee80211ac_cap_check(hw, conf); } #endif /* CONFIG_IEEE80211AC */ @@ -746,7 +679,8 @@ int hostapd_check_ht_capab(struct hostapd_iface *iface) if (!ieee80211n_supported_ht_capab(iface)) return -1; #ifdef CONFIG_IEEE80211AC - if (!ieee80211ac_supported_vht_capab(iface)) + if (iface->conf->ieee80211ac && + !ieee80211ac_supported_vht_capab(iface)) return -1; #endif /* CONFIG_IEEE80211AC */ ret = ieee80211n_check_40mhz(iface); @@ -785,20 +719,41 @@ static int hostapd_is_usable_chan(struct hostapd_iface *iface, chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); } + wpa_printf(MSG_INFO, "Channel %d (%s) not allowed for AP mode", + channel, primary ? "primary" : "secondary"); return 0; } 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; } @@ -978,5 +933,19 @@ int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) { - return hw_get_chan(hapd->iface->current_mode, freq); + int i, channel; + struct hostapd_hw_modes *mode; + + channel = hw_get_chan(hapd->iface->current_mode, freq); + if (channel) + return channel; + /* Check other available modes since the channel list for the current + * mode did not include the specified frequency. */ + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + channel = hw_get_chan(mode, freq); + if (channel) + return channel; + } + return 0; } |