@@ -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";
}
@@ -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. */