diff -up wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface.c.scan-faster wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface.c --- wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface.c.scan-faster 2009-02-15 10:00:00.000000000 -0800 +++ wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface.c 2009-11-29 13:35:44.517283679 -0800 @@ -733,8 +733,9 @@ static int wpa_supplicant_ctrl_iface_sca static int wpa_supplicant_ctrl_iface_select_network( struct wpa_supplicant *wpa_s, char *cmd) { - int id; + int id, timeout, do_scan = 1; struct wpa_ssid *ssid; + struct os_time now; /* cmd: "" or "any" */ if (os_strcmp(cmd, "any") == 0) { @@ -745,7 +746,22 @@ static int wpa_supplicant_ctrl_iface_sel ssid = ssid->next; } wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); + + /* Just associate and don't request a scan if the latest + * scan results are less than 10 seconds old. + */ + if (os_get_time(&now) == 0) { + now.sec -= 10; + if (os_time_before(&now, &(wpa_s->last_scan))) { + if (wpa_supplicant_select_bss_and_associate ( + wpa_s, &timeout) >= 0) { + do_scan = 0; + } + } + } + + if (do_scan) + wpa_supplicant_req_scan(wpa_s, 0, 0); return 0; } diff -up wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface_dbus_handlers.c.scan-faster wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface_dbus_handlers.c --- wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface_dbus_handlers.c.scan-faster 2009-11-29 13:35:44.511309733 -0800 +++ wpa_supplicant-0.6.8/wpa_supplicant/ctrl_iface_dbus_handlers.c 2009-11-29 13:35:44.518283666 -0800 @@ -1073,7 +1073,8 @@ DBusMessage * wpas_dbus_iface_select_net wpa_supplicant_req_scan(wpa_s, 0, 0); } else { const char *obj_path; - int nid; + int nid, timeout, do_scan = 1; + struct os_time now; if (!dbus_message_get_args(message, NULL, DBUS_TYPE_OBJECT_PATH, &op, @@ -1124,7 +1125,22 @@ DBusMessage * wpas_dbus_iface_select_net } wpa_s->disconnected = 0; wpa_s->reassociate = 1; - wpa_supplicant_req_scan(wpa_s, 0, 0); + + /* Just associate and don't request a scan if the latest + * scan results are less than 10 seconds old. + */ + if (os_get_time(&now) == 0) { + now.sec -= 10; + if (os_time_before(&now, &(wpa_s->last_scan))) { + if (wpa_supplicant_select_bss_and_associate ( + wpa_s, &timeout) >= 0) { + do_scan = 0; + } + } + } + + if (do_scan) + wpa_supplicant_req_scan(wpa_s, 0, 0); } reply = wpas_dbus_new_success_reply(message); diff -up wpa_supplicant-0.6.8/wpa_supplicant/events.c.scan-faster wpa_supplicant-0.6.8/wpa_supplicant/events.c --- wpa_supplicant-0.6.8/wpa_supplicant/events.c.scan-faster 2009-11-29 13:35:44.512309091 -0800 +++ wpa_supplicant-0.6.8/wpa_supplicant/events.c 2009-11-29 13:47:07.789286282 -0800 @@ -683,43 +683,17 @@ wpa_supplicant_select_bss(struct wpa_sup } -static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) -{ - int prio, timeout; - struct wpa_scan_res *selected = NULL; - struct wpa_ssid *ssid = NULL; +/* Returns 0 on success; -1 when no BSS has been selected */ +int +wpa_supplicant_select_bss_and_associate (struct wpa_supplicant *wpa_s, + int *out_timeout) + { + struct wpa_scan_res *selected = NULL; + struct wpa_ssid *ssid = NULL; + int prio; int qual = 0, max_qual = 0, qual_valid = 0, bssid_valid = 0, i; struct cur_ap cur; - wpa_supplicant_notify_scanning(wpa_s, 0); - - if (wpa_supplicant_get_scan_results(wpa_s) < 0) { - if (wpa_s->conf->ap_scan == 2) - return; - wpa_printf(MSG_DEBUG, "Failed to get scan results - try " - "scanning again"); - timeout = 1; - goto req_scan; - } - - /* - * Don't post the results if this was the initial cached - * and there were no results. - */ - if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && - wpa_s->scan_res->num == 0) { - wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " - "empty - not posting"); - } else { - wpa_msg(wpa_s, MSG_DEBUG, WPA_EVENT_SCAN_RESULTS); - wpa_supplicant_dbus_notify_scan_results(wpa_s); - wpas_wps_notify_scan_results(wpa_s); - } - - if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)) || - wpa_s->disconnected) - return; - /* Get current driver BSSID and signal strength */ os_memset(&cur, 0, sizeof(cur)); @@ -772,40 +746,84 @@ static void wpa_supplicant_event_scan_re } } - if (selected) { - if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { - wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP - "PBC session overlap"); - timeout = 10; - goto req_scan; - } - - /* Do not trigger new association unless the BSSID has changed - * or if reassociation is requested. If we are in process of - * associating with the selected BSSID, do not trigger new - * attempt. */ - if (wpa_s->reassociate || - (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && - (wpa_s->wpa_state != WPA_ASSOCIATING || - os_memcmp(selected->bssid, wpa_s->pending_bssid, - ETH_ALEN) != 0))) { - if (wpa_supplicant_scard_init(wpa_s, ssid)) { - wpa_supplicant_req_scan(wpa_s, 10, 0); - return; - } - wpa_supplicant_associate(wpa_s, selected, ssid); - } else { - wpa_printf(MSG_DEBUG, "Already associated with the " - "selected AP."); + if (!selected) { + *out_timeout = 5; + return -1; + } + + if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP + "PBC session overlap"); + *out_timeout = 10; + return -1; + } + + /* Do not trigger new association unless the BSSID has changed + * or if reassociation is requested. If we are in process of + * associating with the selected BSSID, do not trigger new + * attempt. */ + if (wpa_s->reassociate || + (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && + (wpa_s->wpa_state != WPA_ASSOCIATING || + os_memcmp(selected->bssid, wpa_s->pending_bssid, + ETH_ALEN) != 0))) { + if (wpa_supplicant_scard_init(wpa_s, ssid)) { + *out_timeout = 10; + return -1; } - rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); + wpa_supplicant_associate(wpa_s, selected, ssid); } else { - wpa_printf(MSG_DEBUG, "No suitable AP found."); - timeout = 5; + wpa_printf(MSG_DEBUG, "Already associated with the " + "selected AP."); + } + + return 0; +} + +static void wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s) +{ + int timeout; + + wpa_supplicant_notify_scanning(wpa_s, 0); + + if (wpa_supplicant_get_scan_results(wpa_s) < 0) { + if (wpa_s->conf->ap_scan == 2) + return; + wpa_printf(MSG_DEBUG, "Failed to get scan results - try " + "scanning again"); + timeout = 1; goto req_scan; } - return; + /* + * Don't post the results if this was the initial cached + * and there were no results. + */ + if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1 && + wpa_s->scan_res->num == 0) { + wpa_msg(wpa_s, MSG_DEBUG, "Cached scan results are " + "empty - not posting"); + } else { + wpa_msg(wpa_s, MSG_DEBUG, WPA_EVENT_SCAN_RESULTS); + wpa_supplicant_dbus_notify_scan_results(wpa_s); + wpas_wps_notify_scan_results(wpa_s); + } + + /* Update scan timestamp if there are any scan results */ + if (wpa_s->scan_res->num > 0) + os_get_time(&(wpa_s->last_scan)); + + if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s)) || + wpa_s->disconnected) + return; + + /* Find a BSS and kick off an association with it */ + if (wpa_supplicant_select_bss_and_associate(wpa_s, &timeout) == 0) { + rsn_preauth_scan_results(wpa_s->wpa, wpa_s->scan_res); + return; + } else { + wpa_printf(MSG_DEBUG, "No suitable AP found."); + } req_scan: if (wpa_s->scan_res_tried == 1 && wpa_s->conf->ap_scan == 1) { diff -up wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h.scan-faster wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h --- wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h.scan-faster 2009-11-29 13:35:44.514283924 -0800 +++ wpa_supplicant-0.6.8/wpa_supplicant/wpa_supplicant_i.h 2009-11-29 13:35:44.520285108 -0800 @@ -347,6 +347,7 @@ struct wpa_supplicant { * to speed up the first association if the driver * has already available scan results. */ int scan_runs; /* number of scan runs since WPS was started */ + struct os_time last_scan; /* timestamp of last scan results */ struct wpa_client_mlme mlme; int use_client_mlme; @@ -415,6 +416,8 @@ void wpa_supplicant_notify_scanning(stru /* events.c */ void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s); +int wpa_supplicant_select_bss_and_associate (struct wpa_supplicant *wpa_s, + int *out_timeout); /* driver_ops */ static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s,