/*
* WPA Supplicant - Driver event processing
- * Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2014, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
union wpa_event_data *data,
int own_request)
{
- struct wpa_scan_results *scan_res;
+ struct wpa_scan_results *scan_res = NULL;
+ int ret = 0;
int ap = 0;
#ifndef CONFIG_NO_RANDOM_POOL
size_t i, num;
wpa_s->scan_req = wpa_s->last_scan_req;
wpa_s->sta_scan_pending = 1;
wpa_supplicant_req_scan(wpa_s, 5, 0);
- return -1;
+ ret = -1;
+ goto scan_work_done;
}
}
wpa_s->sta_scan_pending = 0;
wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results - try "
"scanning again");
wpa_supplicant_req_new_scan(wpa_s, 1, 0);
- return -1;
+ ret = -1;
+ goto scan_work_done;
}
#ifndef CONFIG_NO_RANDOM_POOL
scan_res_handler = wpa_s->scan_res_handler;
wpa_s->scan_res_handler = NULL;
scan_res_handler(wpa_s, scan_res);
-
- wpa_scan_results_free(scan_res);
- return -2;
+ ret = -2;
+ goto scan_work_done;
}
if (ap) {
if (wpa_s->ap_iface->scan_cb)
wpa_s->ap_iface->scan_cb(wpa_s->ap_iface);
#endif /* CONFIG_AP */
- wpa_scan_results_free(scan_res);
- return 0;
+ goto scan_work_done;
}
wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)",
return 0;
}
- if (sme_proc_obss_scan(wpa_s) > 0) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ if (sme_proc_obss_scan(wpa_s) > 0)
+ goto scan_work_done;
- if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)))
+ goto scan_work_done;
- if (autoscan_notify_scan(wpa_s, scan_res)) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ if (autoscan_notify_scan(wpa_s, scan_res))
+ goto scan_work_done;
if (wpa_s->disconnected) {
wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
- wpa_scan_results_free(scan_res);
- return 0;
+ goto scan_work_done;
}
if (!wpas_driver_bss_selection(wpa_s) &&
- bgscan_notify_scan(wpa_s, scan_res) == 1) {
- wpa_scan_results_free(scan_res);
- return 0;
- }
+ bgscan_notify_scan(wpa_s, scan_res) == 1)
+ goto scan_work_done;
wpas_wps_update_ap_info(wpa_s, scan_res);
wpa_scan_results_free(scan_res);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
+
return wpas_select_network_from_last_scan(wpa_s, 1, own_request);
+
+scan_work_done:
+ wpa_scan_results_free(scan_res);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
+ return ret;
}
}
-/**
- * wpa_supplicant_trigger_scan - Request driver to start a scan
- * @wpa_s: Pointer to wpa_supplicant data
- * @params: Scan parameters
- * Returns: 0 on success, -1 on failure
- */
-int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
- struct wpa_driver_scan_params *params)
+static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit)
{
+ struct wpa_supplicant *wpa_s = work->wpa_s;
+ struct wpa_driver_scan_params *params = work->ctx;
int ret;
+ if (deinit) {
+ wpa_scan_free_params(params);
+ return;
+ }
+
wpa_supplicant_notify_scanning(wpa_s, 1);
if (wpa_s->clear_driver_scan_cache)
params->only_new_results = 1;
ret = wpa_drv_scan(wpa_s, params);
+ wpa_scan_free_params(params);
+ work->ctx = NULL;
if (ret) {
wpa_supplicant_notify_scanning(wpa_s, 0);
wpas_notify_scan_done(wpa_s, 0);
- } else {
- os_get_reltime(&wpa_s->scan_trigger_time);
- wpa_s->scan_runs++;
- wpa_s->normal_scans++;
- wpa_s->own_scan_requested = 1;
- wpa_s->clear_driver_scan_cache = 0;
+ radio_work_done(work);
+ return;
}
- return ret;
+ os_get_reltime(&wpa_s->scan_trigger_time);
+ wpa_s->scan_runs++;
+ wpa_s->normal_scans++;
+ wpa_s->own_scan_requested = 1;
+ wpa_s->clear_driver_scan_cache = 0;
+ wpa_s->scan_work = work;
+}
+
+
+/**
+ * wpa_supplicant_trigger_scan - Request driver to start a scan
+ * @wpa_s: Pointer to wpa_supplicant data
+ * @params: Scan parameters
+ * Returns: 0 on success, -1 on failure
+ */
+int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
+ struct wpa_driver_scan_params *params)
+{
+ struct wpa_driver_scan_params *ctx;
+
+ if (wpa_s->scan_work) {
+ wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending");
+ return -1;
+ }
+
+ ctx = wpa_scan_clone_params(params);
+ if (ctx == NULL)
+ return -1;
+
+ if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0)
+ {
+ wpa_scan_free_params(ctx);
+ return -1;
+ }
+
+ return 0;
}
}
wpas_notify_scan_results(wpa_s);
wpas_notify_scan_done(wpa_s, 1);
+ if (wpa_s->scan_work) {
+ struct wpa_radio_work *work = wpa_s->scan_work;
+ wpa_s->scan_work = NULL;
+ radio_work_done(work);
+ }
}