diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index c5161544d..0aa92a28c 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -2890,6 +2890,7 @@ void wpa_config_free(struct wpa_config *config) os_free(config->p2p_no_go_freq.range); os_free(config->autoscan); os_free(config->freq_list); + os_free(config->initial_freq_list); wpabuf_free(config->wps_nfc_dh_pubkey); wpabuf_free(config->wps_nfc_dh_privkey); wpabuf_free(config->wps_nfc_dev_pw); @@ -4547,6 +4548,26 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data, } +static int +wpa_config_process_initial_freq_list(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (!freqs) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(config->initial_freq_list); + config->initial_freq_list = freqs; + return 0; +} + + #ifdef CONFIG_P2P static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, struct wpa_config *config, int line, @@ -5082,6 +5103,7 @@ static const struct global_parse_data global_fields[] = { { FUNC(ap_vendor_elements), 0 }, { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, { FUNC(freq_list), 0 }, + { FUNC(initial_freq_list), 0}, { INT(scan_cur_freq), 0 }, { INT(sched_scan_interval), 0 }, { INT(sched_scan_start_delay), 0 }, diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index 648573de0..d128cd9bf 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -916,6 +916,19 @@ struct wpa_config { */ int *freq_list; + /** + * initial_freq_list - like freq_list but for initial scan + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for narrowing scanning range when + * the application is started. + * + * This can be used to speed up initial connection time if the + * channel is known ahead of time, without limiting the scanned + * frequencies during normal use. + */ + int *initial_freq_list; + /** * scan_cur_freq - Whether to scan only the current channel * diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 246644a33..cb04a78a2 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -1475,6 +1475,15 @@ static void wpa_config_write_global(FILE *f, struct wpa_config *config) } fprintf(f, "\n"); } + if (config->initial_freq_list && config->initial_freq_list[0]) { + int i; + fprintf(f, "initial_freq_list="); + for (i = 0; config->initial_freq_list[i]; i++) { + fprintf(f, "%s%d", i > 0 ? " " : "", + config->initial_freq_list[i]); + } + fprintf(f, "\n"); + } if (config->scan_cur_freq != DEFAULT_SCAN_CUR_FREQ) fprintf(f, "scan_cur_freq=%d\n", config->scan_cur_freq); diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 78371d3ad..9ac658151 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -1201,7 +1201,12 @@ ssid_list_set: 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) { + if (wpa_s->last_scan_req == INITIAL_SCAN_REQ && + wpa_s->conf->initial_freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->initial_freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->initial_freq_list); + } else if (wpa_s->conf->freq_list && !params.freqs) { wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on conf->freq_list"); int_array_concat(¶ms.freqs, wpa_s->conf->freq_list);