diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 2a13736cd..083a156b7 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -127,10 +127,6 @@ static const char * p2p_state_txt(int state) return "INVITE"; case P2P_INVITE_LISTEN: return "INVITE_LISTEN"; - case P2P_SEARCH_WHEN_READY: - return "SEARCH_WHEN_READY"; - case P2P_CONTINUE_SEARCH_WHEN_READY: - return "CONTINUE_SEARCH_WHEN_READY"; default: return "?"; } @@ -884,9 +880,6 @@ static void p2p_search(struct p2p_data *p2p) if (res < 0) { p2p_dbg(p2p, "Scan request failed"); p2p_continue_find(p2p); - } else if (res == 1) { - p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes"); - p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY); } else { p2p_dbg(p2p, "Running p2p_scan"); p2p->p2p_scan_running = 1; @@ -1041,11 +1034,9 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL); eloop_register_timeout(P2P_SCAN_TIMEOUT, 0, p2p_scan_timeout, p2p, NULL); - } else if (res == 1) { - p2p_dbg(p2p, "Could not start p2p_scan at this point - will try again after previous scan completes"); - res = 0; - p2p_set_state(p2p, P2P_SEARCH_WHEN_READY); - eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); + } else if (p2p->p2p_scan_running) { + p2p_dbg(p2p, "Failed to start p2p_scan - another p2p_scan was already running"); + /* wait for the previous p2p_scan to complete */ } else { p2p_dbg(p2p, "Failed to start p2p_scan"); p2p_set_state(p2p, P2P_IDLE); @@ -1056,34 +1047,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, } -int p2p_other_scan_completed(struct p2p_data *p2p) -{ - if (p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) { - p2p_set_state(p2p, P2P_SEARCH); - p2p_search(p2p); - return 1; - } - if (p2p->state != P2P_SEARCH_WHEN_READY) - return 0; - p2p_dbg(p2p, "Starting pending P2P find now that previous scan was completed"); - if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, - p2p->num_req_dev_types, p2p->req_dev_types, - p2p->find_dev_id, p2p->search_delay) < 0) { - p2p->cfg->find_stopped(p2p->cfg->cb_ctx); - return 0; - } - return 1; -} - - void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) { p2p_dbg(p2p, "Stopping find"); eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); p2p_clear_timeout(p2p); - if (p2p->state == P2P_SEARCH || - p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY || - p2p->state == P2P_SEARCH_WHEN_READY) + if (p2p->state == P2P_SEARCH) p2p->cfg->find_stopped(p2p->cfg->cb_ctx); p2p_set_state(p2p, P2P_IDLE); p2p_free_req_dev_types(p2p); @@ -3369,10 +3338,6 @@ static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx) case P2P_INVITE_LISTEN: p2p_timeout_invite_listen(p2p); break; - case P2P_SEARCH_WHEN_READY: - break; - case P2P_CONTINUE_SEARCH_WHEN_READY: - break; } } @@ -4183,8 +4148,7 @@ int p2p_in_progress(struct p2p_data *p2p) { if (p2p == NULL) return 0; - if (p2p->state == P2P_SEARCH || p2p->state == P2P_SEARCH_WHEN_READY || - p2p->state == P2P_CONTINUE_SEARCH_WHEN_READY) + if (p2p->state == P2P_SEARCH) return 2; return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING; } @@ -4200,13 +4164,6 @@ void p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout, } -void p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay) -{ - if (p2p && p2p->search_delay < delay) - p2p->search_delay = delay; -} - - #ifdef CONFIG_WIFI_DISPLAY static void p2p_update_wfd_ie_groups(struct p2p_data *p2p) diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index f35a2363e..25a91e77e 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1826,13 +1826,6 @@ int p2p_set_no_go_freq(struct p2p_data *p2p, */ int p2p_in_progress(struct p2p_data *p2p); -/** - * p2p_other_scan_completed - Notify completion of non-P2P scan - * @p2p: P2P module context from p2p_init() - * Returns: 0 if P2P module is idle or 1 if an operation was started - */ -int p2p_other_scan_completed(struct p2p_data *p2p); - const char * p2p_wps_method_text(enum p2p_wps_method method); /** @@ -1844,8 +1837,6 @@ const char * p2p_wps_method_text(enum p2p_wps_method method); void p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout, u8 client_timeout); -void p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay); - int p2p_set_wfd_ie_beacon(struct p2p_data *p2p, struct wpabuf *ie); int p2p_set_wfd_ie_probe_req(struct p2p_data *p2p, struct wpabuf *ie); int p2p_set_wfd_ie_probe_resp(struct p2p_data *p2p, struct wpabuf *ie); diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 4b328ca69..3e105eb79 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -205,16 +205,6 @@ struct p2p_data { * P2P_INVITE_LISTEN - Listen during Invite */ P2P_INVITE_LISTEN, - - /** - * P2P_SEARCH_WHEN_READY - Waiting to start Search - */ - P2P_SEARCH_WHEN_READY, - - /** - * P2P_CONTINUE_SEARCH_WHEN_READY - Waiting to continue Search - */ - P2P_CONTINUE_SEARCH_WHEN_READY, } state; /** diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index b0ea7a2a0..566f14849 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -978,9 +978,6 @@ static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request " "since there are no enabled networks"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); -#ifdef CONFIG_P2P - wpa_s->sta_scan_pending = 0; -#endif /* CONFIG_P2P */ return; } @@ -1195,25 +1192,6 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_supplicant_notify_scanning(wpa_s, 0); -#ifdef CONFIG_P2P - if (own_request && wpa_s->global->p2p_cb_on_scan_complete && - !wpa_s->global->p2p_disabled && - wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending && - !wpa_s->scan_res_handler) { - wpa_s->global->p2p_cb_on_scan_complete = 0; - if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { - wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " - "stopped scan processing"); - wpa_s->scan_req = wpa_s->last_scan_req; - wpa_s->sta_scan_pending = 1; - wpa_supplicant_req_scan(wpa_s, 5, 0); - ret = -1; - goto scan_work_done; - } - } - wpa_s->sta_scan_pending = 0; -#endif /* CONFIG_P2P */ - scan_res = wpa_supplicant_get_scan_results(wpa_s, data ? &data->scan_info : NULL, 1); @@ -2885,9 +2863,6 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event, wpa_supplicant_event_scan_results(wpa_s, data); wpa_s->own_scan_running = 0; wpa_s->external_scan_running = 0; - if (wpa_s->wpa_state != WPA_AUTHENTICATING && - wpa_s->wpa_state != WPA_ASSOCIATING) - wpas_p2p_continue_after_scan(wpa_s); break; #endif /* CONFIG_NO_SCAN_PROCESSING */ case EVENT_ASSOCINFO: diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index a71cbbec9..e84db5850 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -1,6 +1,7 @@ /* * wpa_supplicant - P2P * Copyright (c) 2009-2010, Atheros Communications + * Copyright (c) 2010-2014, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -196,6 +197,12 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, { size_t i; + if (wpa_s->p2p_scan_work) { + struct wpa_radio_work *work = wpa_s->p2p_scan_work; + wpa_s->p2p_scan_work = NULL; + radio_work_done(work); + } + if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return; @@ -234,95 +241,125 @@ static void wpas_p2p_scan_res_handler(struct wpa_supplicant *wpa_s, } +static void wpas_p2p_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; + } + + ret = wpa_drv_scan(wpa_s, params); + wpa_scan_free_params(params); + work->ctx = NULL; + if (ret) { + radio_work_done(work); + return; + } + + os_get_reltime(&wpa_s->scan_trigger_time); + wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; + wpa_s->own_scan_requested = 1; + wpa_s->p2p_scan_work = work; +} + + static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, unsigned int num_req_dev_types, const u8 *req_dev_types, const u8 *dev_id, u16 pw_id) { struct wpa_supplicant *wpa_s = ctx; - struct wpa_supplicant *ifs; - struct wpa_driver_scan_params params; - int ret; + struct wpa_driver_scan_params *params = NULL; struct wpabuf *wps_ie, *ies; - int social_channels[] = { 2412, 2437, 2462, 0, 0 }; size_t ielen; + u8 *n; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; - for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) { - if (ifs->sta_scan_pending && - (wpas_scan_scheduled(ifs) || ifs->scanning) && - wpas_p2p_in_progress(wpa_s) == 2) { - wpa_printf(MSG_DEBUG, "Delaying P2P scan to allow " - "pending station mode scan to be " - "completed on interface %s", ifs->ifname); - wpa_s->global->p2p_cb_on_scan_complete = 1; - wpa_supplicant_req_scan(ifs, 0, 0); - return 1; - } + if (wpa_s->p2p_scan_work) { + wpa_dbg(wpa_s, MSG_INFO, "P2P: Reject scan trigger since one is already pending"); + return -1; } - os_memset(¶ms, 0, sizeof(params)); + params = os_zalloc(sizeof(*params)); + if (params == NULL) + return -1; /* P2P Wildcard SSID */ - params.num_ssids = 1; - params.ssids[0].ssid = (u8 *) P2P_WILDCARD_SSID; - params.ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; + params->num_ssids = 1; + n = os_malloc(P2P_WILDCARD_SSID_LEN); + if (n == NULL) + goto fail; + os_memcpy(n, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN); + params->ssids[0].ssid = n; + params->ssids[0].ssid_len = P2P_WILDCARD_SSID_LEN; wpa_s->wps->dev.p2p = 1; wps_ie = wps_build_probe_req_ie(pw_id, &wpa_s->wps->dev, wpa_s->wps->uuid, WPS_REQ_ENROLLEE, num_req_dev_types, req_dev_types); if (wps_ie == NULL) - return -1; + goto fail; ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); if (ies == NULL) { wpabuf_free(wps_ie); - return -1; + goto fail; } wpabuf_put_buf(ies, wps_ie); wpabuf_free(wps_ie); p2p_scan_ie(wpa_s->global->p2p, ies, dev_id); - params.p2p_probe = 1; - params.extra_ies = wpabuf_head(ies); - params.extra_ies_len = wpabuf_len(ies); + params->p2p_probe = 1; + n = os_malloc(wpabuf_len(ies)); + if (n == NULL) { + wpabuf_free(ies); + goto fail; + } + os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies)); + params->extra_ies = n; + params->extra_ies_len = wpabuf_len(ies); + wpabuf_free(ies); switch (type) { case P2P_SCAN_SOCIAL: - params.freqs = social_channels; + params->freqs = os_malloc(4 * sizeof(int)); + if (params->freqs == NULL) + goto fail; + params->freqs[0] = 2412; + params->freqs[1] = 2437; + params->freqs[2] = 2462; + params->freqs[3] = 0; break; case P2P_SCAN_FULL: break; case P2P_SCAN_SOCIAL_PLUS_ONE: - social_channels[3] = freq; - params.freqs = social_channels; + params->freqs = os_malloc(5 * sizeof(int)); + if (params->freqs == NULL) + goto fail; + params->freqs[0] = 2412; + params->freqs[1] = 2437; + params->freqs[2] = 2462; + params->freqs[3] = freq; + params->freqs[4] = 0; break; } - ret = wpa_drv_scan(wpa_s, ¶ms); + radio_remove_unstarted_work(wpa_s, "p2p-scan"); + if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb, + params) < 0) + goto fail; + return 0; - wpabuf_free(ies); - - if (ret) { - for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) { - if (ifs->scanning || - ifs->scan_res_handler == wpas_p2p_scan_res_handler) { - wpa_s->global->p2p_cb_on_scan_complete = 1; - ret = 1; - break; - } - } - } else { - os_get_reltime(&wpa_s->scan_trigger_time); - wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; - wpa_s->own_scan_requested = 1; - } - - return ret; +fail: + wpa_scan_free_params(params); + return -1; } @@ -513,7 +550,6 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, wpa_config_remove_network(wpa_s->conf, id); wpa_supplicant_clear_status(wpa_s); wpa_supplicant_cancel_sched_scan(wpa_s); - wpa_s->sta_scan_pending = 0; } else { wpa_printf(MSG_DEBUG, "P2P: Temporary group network not " "found"); @@ -5092,7 +5128,6 @@ static int wpas_p2p_stop_find_oper(struct wpa_supplicant *wpa_s) wpa_s->p2p_long_listen = 0; eloop_cancel_timeout(wpas_p2p_long_listen_timeout, wpa_s, NULL); eloop_cancel_timeout(wpas_p2p_join_scan, wpa_s, NULL); - wpa_s->global->p2p_cb_on_scan_complete = 0; if (wpa_s->global->p2p) p2p_stop_find(wpa_s->global->p2p); @@ -5408,7 +5443,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) } if (!wpa_s->show_group_started || !ssid) - goto done; + return; wpa_s->show_group_started = 0; @@ -5450,9 +5485,6 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) if (network_id < 0) network_id = ssid->id; wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1); - -done: - wpas_p2p_continue_after_scan(wpa_s); } @@ -6250,30 +6282,6 @@ unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s) } -void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s) -{ - wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Station mode scan operation not " - "pending anymore (sta_scan_pending=%d " - "p2p_cb_on_scan_complete=%d)", wpa_s->sta_scan_pending, - wpa_s->global->p2p_cb_on_scan_complete); - wpa_s->sta_scan_pending = 0; - - if (!wpa_s->global->p2p_cb_on_scan_complete) - return; - wpa_s->global->p2p_cb_on_scan_complete = 0; - - if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) - return; - - if (p2p_other_scan_completed(wpa_s->global->p2p) == 1) { - wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Pending P2P operation " - "continued after successful connection"); - p2p_increase_search_delay(wpa_s->global->p2p, - wpas_p2p_search_delay(wpa_s)); - } -} - - static int wpas_p2p_remove_psk_entry(struct wpa_supplicant *wpa_s, struct wpa_ssid *s, const u8 *addr, int iface_addr) diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 9605136c4..49122caf3 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -149,14 +149,9 @@ void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer, int iface_addr); #ifdef CONFIG_P2P -void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s); int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s); void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s); #else /* CONFIG_P2P */ -static inline void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s) -{ -} - static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) { return 0; diff --git a/wpa_supplicant/scan.c b/wpa_supplicant/scan.c index 763fc133f..b36c87c6e 100644 --- a/wpa_supplicant/scan.c +++ b/wpa_supplicant/scan.c @@ -524,14 +524,12 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); - wpas_p2p_continue_after_scan(wpa_s); return; } if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) { wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); - wpas_p2p_continue_after_scan(wpa_s); return; } @@ -560,7 +558,6 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) wpa_s->scan_req == NORMAL_SCAN_REQ) { wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); - wpas_p2p_continue_after_scan(wpa_s); return; } @@ -579,18 +576,9 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) #ifdef CONFIG_P2P if (wpas_p2p_in_progress(wpa_s) || wpas_wpa_is_in_progress(wpa_s, 0)) { - if (wpa_s->sta_scan_pending && - wpas_p2p_in_progress(wpa_s) == 2 && - wpa_s->global->p2p_cb_on_scan_complete) { - wpa_dbg(wpa_s, MSG_DEBUG, "Process pending station " - "mode scan during P2P search"); - } else { - wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan " - "while P2P operation is in progress"); - wpa_s->sta_scan_pending = 1; - wpa_supplicant_req_scan(wpa_s, 5, 0); - return; - } + wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress"); + wpa_supplicant_req_scan(wpa_s, 5, 0); + return; } #endif /* CONFIG_P2P */ @@ -1202,7 +1190,6 @@ void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) { wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling scan request"); eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); - wpas_p2p_continue_after_scan(wpa_s); } diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index f04d60d49..138e975a8 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -195,8 +195,6 @@ static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) * So, wait a second until scanning again. */ wpa_supplicant_req_scan(wpa_s, 1, 0); - - wpas_p2p_continue_after_scan(wpa_s); } @@ -2910,6 +2908,15 @@ static void radio_work_free(struct wpa_radio_work *work) work->wpa_s->scan_work = NULL; } +#ifdef CONFIG_P2P + if (work->wpa_s->p2p_scan_work == work) { + /* This should not really happen. */ + wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work", + work->type, work, work->started); + work->wpa_s->p2p_scan_work = NULL; + } +#endif /* CONFIG_P2P */ + dl_list_del(&work->list); os_free(work); } @@ -3966,8 +3973,6 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) */ wpa_supplicant_req_scan(wpa_s, timeout / 1000, 1000 * (timeout % 1000)); - - wpas_p2p_continue_after_scan(wpa_s); } diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index c2d0a36a8..25739f1cc 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -257,7 +257,6 @@ struct wpa_global { WPA_CONC_PREF_STA, WPA_CONC_PREF_P2P } conc_pref; - unsigned int p2p_cb_on_scan_complete:1; unsigned int p2p_per_sta_psk:1; #ifdef CONFIG_WIFI_DISPLAY @@ -680,7 +679,6 @@ struct wpa_supplicant { */ char cross_connect_uplink[100]; - unsigned int sta_scan_pending:1; unsigned int p2p_auto_join:1; unsigned int p2p_auto_pd:1; unsigned int p2p_persistent_group:1; @@ -698,6 +696,7 @@ struct wpa_supplicant { int p2p_connect_freq; struct os_reltime p2p_auto_started; struct wpa_ssid *p2p_last_4way_hs_fail; + struct wpa_radio_work *p2p_scan_work; #endif /* CONFIG_P2P */ struct wpa_ssid *bgscan_ssid;