From: Neo Jou <neojou@xxxxxxxxx> This patch is to extend the existing hw_mode=any to cover the not-offloaded-ACS case. In wpa_driver_nl80211_postprocess_modes, the approach, similar to the one for 80211.b is used for the mode HOSTAPD_MODE_IEEE80211ANY. it is for hostapd_select_hw_mode() to get the support configured mode. And after ACS computed, the current_mode is changed back to B/G/A/AD, depends on the frequency ACS decided. By this way, "hw_mode=any" can be used for not-offloaded-ACS case. Signed-off-by: Neo Jou <neojou@xxxxxxxxx> --- src/ap/hw_features.c | 35 +++++++++++++++++++++++++++++ src/drivers/driver_nl80211_capa.c | 47 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index ba10752..2db65c5 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -963,6 +963,39 @@ int hostapd_acs_completed(struct hostapd_iface *iface, int err) wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_COMPLETED "freq=%d channel=%d", iface->freq, iface->conf->channel); + + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211ANY) { + int i; + enum hostapd_hw_mode target_mode; + + if (iface->freq < 4000) { + target_mode = HOSTAPD_MODE_IEEE80211B; + for (i = 0; i < iface->current_mode->num_rates; i++) { + if (iface->current_mode->rates[i] > 200) { + target_mode = HOSTAPD_MODE_IEEE80211G; + break; + } + } + } else if (iface->freq > 50000) + target_mode = HOSTAPD_MODE_IEEE80211AD; + else + target_mode = HOSTAPD_MODE_IEEE80211A; + + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = &iface->hw_features[i]; + if (mode->mode == target_mode) { + iface->current_mode = mode; + break; + } + } + + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211ANY) { + wpa_printf(MSG_ERROR, "ACS error - cannot decide band"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + } + } break; case HOSTAPD_CHAN_ACS: wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); @@ -1070,6 +1103,8 @@ const char * hostapd_hw_mode_txt(int mode) return "IEEE 802.11g"; case HOSTAPD_MODE_IEEE80211AD: return "IEEE 802.11ad"; + case HOSTAPD_MODE_IEEE80211ANY: + return "IEEE 802.11any"; default: return "UNKNOWN"; } diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index e1cf9f7..908d1fd 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1808,6 +1808,53 @@ wpa_driver_nl80211_postprocess_modes(struct hostapd_hw_modes *modes, modes[m].mode = HOSTAPD_MODE_IEEE80211A; } + /* Add HOSTAPD_MODE_IEEE80211ANY */ + nmodes = os_realloc_array(modes, *num_modes + 1, sizeof(*nmodes)); + if (nmodes == NULL) + return modes; /* Could not add mode ANY */ + + mode = &nmodes[*num_modes]; + os_memset(mode, 0, sizeof(*mode)); + modes = nmodes; + mode->mode = HOSTAPD_MODE_IEEE80211ANY; + + for (m = 0; m < *num_modes; m++) { + struct hostapd_channel_data *m_channels; + int *m_rates; + + if (!modes[m].num_channels) + continue; + + /* add channels */ + m_channels = os_realloc_array(mode->channels, + mode->num_channels + modes[m].num_channels, + sizeof(struct hostapd_channel_data)); + if (m_channels == NULL) + return modes; + + mode->channels = m_channels; + + memcpy(&(mode->channels[mode->num_channels]), + modes[m].channels, + modes[m].num_channels * sizeof(struct hostapd_channel_data)); + + mode->num_channels += modes[m].num_channels; + + /* add rates */ + m_rates = os_realloc_array(mode->rates, + mode->num_rates + modes[m].num_rates, + sizeof(int)); + if (m_rates == NULL) + return modes; + mode->rates = m_rates; + memcpy(&(mode->rates[mode->num_rates]), + modes[m].rates, + modes[m].num_rates * sizeof(int)); + mode->num_rates += modes[m].num_rates; + } + + (*num_modes)++; + /* If only 802.11g mode is included, use it to construct matching * 802.11b mode data. */ -- 2.7.4 _______________________________________________ Hostap mailing list Hostap@xxxxxxxxxxxxxxxxxxx http://lists.infradead.org/mailman/listinfo/hostap