diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 16e0bd7cb..bdd6815e3 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -522,6 +522,63 @@ static int shared_vif_oper_freq(struct wpa_supplicant *wpa_s) } +static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, + u16 num_modes, + enum hostapd_hw_mode mode) +{ + u16 i; + + for (i = 0; i < num_modes; i++) { + if (modes[i].mode == mode) + return &modes[i]; + } + + return NULL; +} + + +static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params) +{ + /* Include only supported channels for the specified band */ + struct hostapd_hw_modes *mode; + int count, i; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band); + if (mode == NULL) { + /* No channels supported in this band - use empty list */ + params->freqs = os_zalloc(sizeof(int)); + return; + } + + params->freqs = os_zalloc((mode->num_channels + 1) * sizeof(int)); + if (params->freqs == NULL) + return; + for (count = 0, i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) + continue; + params->freqs[count++] = mode->channels[i].freq; + } +} + + +static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ + if (wpa_s->hw.modes == NULL) + return; /* unknown what channels the driver supports */ + if (params->freqs) + return; /* already using a limited channel set */ + if (wpa_s->setband == WPA_SETBAND_5G) + wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, + params); + else if (wpa_s->setband == WPA_SETBAND_2G) + wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, + params); +} + + static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) { struct wpa_supplicant *wpa_s = eloop_ctx; @@ -747,6 +804,7 @@ ssid_list_set: } else os_free(wpa_s->next_scan_freqs); wpa_s->next_scan_freqs = NULL; + wpa_setband_scan_freqs(wpa_s, ¶ms); /* See if user specified frequencies. If so, scan only those. */ if (wpa_s->conf->freq_list && !params.freqs) { @@ -1120,6 +1178,8 @@ scan: wpa_s->sched_scan_interval); } + wpa_setband_scan_freqs(wpa_s, scan_params); + ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params, wpa_s->sched_scan_interval); wpabuf_free(extra_ie); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index d29318ec4..f4e6faff5 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -353,6 +353,8 @@ struct wpa_supplicant { struct wpa_ssid_value *disallow_aps_ssid; size_t disallow_aps_ssid_count; + enum { WPA_SETBAND_AUTO, WPA_SETBAND_5G, WPA_SETBAND_2G } setband; + /* previous scan was wildcard when interleaving between * wildcard scans and specific SSID scan when max_ssids=1 */ int prev_scan_wildcard;