From 39185dfa549f076a6be114e0149a3649d302f477 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 15 Nov 2011 21:25:21 +0200 Subject: [PATCH] P2P: Wait until ongoing scan completes before starting P2P find The P2P_FIND command was failing if it was issued at the moment when a scan operation was in progress. Avoid returning failure in this case by scheduling the P2P find to start once the ongoing scan is completed. Signed-hostap: Jouni Malinen --- src/p2p/p2p.c | 25 +++++++++++++++++++++++++ src/p2p/p2p.h | 7 +++++++ src/p2p/p2p_i.h | 6 ++++++ wpa_supplicant/events.c | 12 ++++++++++++ wpa_supplicant/p2p_supplicant.c | 10 +++++++++- wpa_supplicant/wpa_supplicant_i.h | 2 ++ 6 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 404b2cdc8..dfa8662ad 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -106,6 +106,8 @@ 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"; default: return "?"; } @@ -878,6 +880,7 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p_device_clear_reported(p2p); p2p_set_state(p2p, P2P_SEARCH); eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); + p2p->last_p2p_find_timeout = timeout; if (timeout) eloop_register_timeout(timeout, 0, p2p_find_timeout, p2p, NULL); @@ -903,6 +906,13 @@ 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) { + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "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 { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Failed to start " "p2p_scan"); @@ -914,6 +924,19 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, } +int p2p_other_scan_completed(struct p2p_data *p2p) +{ + if (p2p->state != P2P_SEARCH_WHEN_READY) + return 0; + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "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) < 0) + return 0; + return 1; +} + + void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); @@ -2947,6 +2970,8 @@ 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; } } diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index aa7889b06..1501a2014 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1542,4 +1542,11 @@ int p2p_set_oper_channel(struct p2p_data *p2p, u8 op_reg_class, u8 op_channel, */ 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); + #endif /* P2P_H */ diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 7ee6e07d5..9d72a1c7d 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -201,6 +201,11 @@ struct p2p_data { * P2P_INVITE_LISTEN - Listen during Invite */ P2P_INVITE_LISTEN, + + /** + * P2P_SEARCH_WHEN_READY - Waiting to start Search + */ + P2P_SEARCH_WHEN_READY, } state; /** @@ -355,6 +360,7 @@ struct p2p_data { int inv_persistent; enum p2p_discovery_type find_type; + unsigned int last_p2p_find_timeout; u8 last_prog_scan_class; u8 last_prog_scan_chan; int p2p_scan_running; diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index 719555cb8..b2e95eec9 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -1009,6 +1009,18 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, wpa_supplicant_notify_scanning(wpa_s, 0); +#ifdef CONFIG_P2P + if (wpa_s->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled && + wpa_s->global->p2p != NULL) { + wpa_s->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"); + return -1; + } + } +#endif /* CONFIG_P2P */ + scan_res = wpa_supplicant_get_scan_results(wpa_s, data ? &data->scan_info : NULL, 1); diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index f3108c45f..a2b3f0654 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -94,6 +94,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, struct wpabuf *wps_ie, *ies; int social_channels[] = { 2412, 2437, 2462, 0, 0 }; size_t ielen; + int was_in_p2p_scan; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -144,13 +145,19 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, break; } + was_in_p2p_scan = wpa_s->scan_res_handler == wpas_p2p_scan_res_handler; wpa_s->scan_res_handler = wpas_p2p_scan_res_handler; ret = wpa_drv_scan(wpa_s, ¶ms); wpabuf_free(ies); - if (ret < 0) + if (ret) { wpa_s->scan_res_handler = NULL; + if (wpa_s->scanning || was_in_p2p_scan) { + wpa_s->p2p_cb_on_scan_complete = 1; + ret = 1; + } + } return ret; } @@ -3351,6 +3358,7 @@ void wpas_p2p_stop_find(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->p2p_cb_on_scan_complete = 0; if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT) { wpa_drv_p2p_stop_find(wpa_s); diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 63a6fead0..59fc9a317 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -476,6 +476,8 @@ struct wpa_supplicant { P2P_GROUP_REMOVAL_IDLE_TIMEOUT, P2P_GROUP_REMOVAL_UNAVAILABLE } removal_reason; + + unsigned int p2p_cb_on_scan_complete:1; #endif /* CONFIG_P2P */ struct wpa_ssid *bgscan_ssid;