diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 6fb65a1ea..2dea1a974 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -3284,6 +3284,51 @@ static void p2p_prov_disc_cb(struct p2p_data *p2p, int success) } +static int p2p_check_after_scan_tx_continuation(struct p2p_data *p2p) +{ + if (p2p->after_scan_tx_in_progress) { + p2p->after_scan_tx_in_progress = 0; + if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING && + p2p_run_after_scan(p2p)) + return 1; + if (p2p->state == P2P_SEARCH) { + p2p_dbg(p2p, "Continue find after after_scan_tx completion"); + p2p_continue_find(p2p); + } + } + + return 0; +} + + +static void p2p_prov_disc_resp_cb(struct p2p_data *p2p, int success) +{ + p2p_dbg(p2p, "Provision Discovery Response TX callback: success=%d", + success); + + if (p2p->send_action_in_progress) { + p2p->send_action_in_progress = 0; + p2p->cfg->send_action_done(p2p->cfg->cb_ctx); + } + + p2p->pending_action_state = P2P_NO_PENDING_ACTION; + + if (!success) + goto continue_search; + + if (!p2p->cfg->prov_disc_resp_cb || + p2p->cfg->prov_disc_resp_cb(p2p->cfg->cb_ctx) < 1) + goto continue_search; + + p2p_dbg(p2p, + "Post-Provision Discovery operations started - do not try to continue other P2P operations"); + return; + +continue_search: + p2p_check_after_scan_tx_continuation(p2p); +} + + int p2p_scan_res_handler(struct p2p_data *p2p, const u8 *bssid, int freq, struct os_reltime *rx_time, int level, const u8 *ies, size_t ies_len) @@ -3558,16 +3603,7 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst, p2p->send_action_in_progress = 0; p2p->cfg->send_action_done(p2p->cfg->cb_ctx); } - if (p2p->after_scan_tx_in_progress) { - p2p->after_scan_tx_in_progress = 0; - if (p2p->start_after_scan != P2P_AFTER_SCAN_NOTHING && - p2p_run_after_scan(p2p)) - break; - if (p2p->state == P2P_SEARCH) { - p2p_dbg(p2p, "Continue find after after_scan_tx completion"); - p2p_continue_find(p2p); - } - } + p2p_check_after_scan_tx_continuation(p2p); break; case P2P_PENDING_GO_NEG_REQUEST: p2p_go_neg_req_cb(p2p, success); @@ -3587,6 +3623,9 @@ void p2p_send_action_cb(struct p2p_data *p2p, unsigned int freq, const u8 *dst, case P2P_PENDING_PD: p2p_prov_disc_cb(p2p, success); break; + case P2P_PENDING_PD_RESPONSE: + p2p_prov_disc_resp_cb(p2p, success); + break; case P2P_PENDING_INVITATION_REQUEST: p2p_invitation_req_cb(p2p, success); break; diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 2681a6b9d..ea3f67950 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -980,6 +980,16 @@ struct p2p_config { */ int (*remove_stale_groups)(void *ctx, const u8 *peer, const u8 *go, const u8 *ssid, size_t ssid_len); + + /** + * prov_disc_resp_cb - Callback for indicating completion of PD Response + * @ctx: Callback context from cb_ctx + * Returns: 1 if operation was started, 0 otherwise + * + * This callback can be used to perform any pending actions after + * provisioning. It is mainly used for P2PS pending group creation. + */ + int (*prov_disc_resp_cb)(void *ctx); }; diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index f80b9baf3..23846322d 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -362,6 +362,7 @@ struct p2p_data { P2P_PENDING_GO_NEG_CONFIRM, P2P_PENDING_SD, P2P_PENDING_PD, + P2P_PENDING_PD_RESPONSE, P2P_PENDING_INVITATION_REQUEST, P2P_PENDING_INVITATION_RESPONSE, P2P_PENDING_DEV_DISC_REQUEST, diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c index ddf619c26..7f08f9b4a 100644 --- a/src/p2p/p2p_pd.c +++ b/src/p2p/p2p_pd.c @@ -355,7 +355,7 @@ out: p2p_parse_free(&msg); return; } - p2p->pending_action_state = P2P_NO_PENDING_ACTION; + p2p->pending_action_state = P2P_PENDING_PD_RESPONSE; if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, p2p->cfg->dev_addr, wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index eb2f20e3b..ddc08bc59 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -6563,6 +6563,7 @@ static void wpa_supplicant_ctrl_iface_flush(struct wpa_supplicant *wpa_s) p2p_wpa_s->p2p_disable_ip_addr_req = 0; os_free(p2p_wpa_s->global->p2p_go_avoid_freq.range); p2p_wpa_s->global->p2p_go_avoid_freq.range = NULL; + p2p_wpa_s->global->pending_p2ps_group = 0; #endif /* CONFIG_P2P */ #ifdef CONFIG_WPS_TESTING diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 47cf05642..dcfba7932 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -4736,6 +4736,33 @@ static int _wpas_p2p_in_progress(void *ctx) } +static int wpas_prov_disc_resp_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + struct wpa_ssid *persistent_go; + + if (!wpa_s->global->pending_p2ps_group) + return 0; + + wpa_s->global->pending_p2ps_group = 0; + + if (wpas_p2p_get_go_group(wpa_s)) + return 0; + persistent_go = wpas_p2p_get_persistent_go(wpa_s); + + if (persistent_go) { + wpas_p2p_group_add_persistent( + wpa_s, persistent_go, 0, 0, 0, 0, 0, NULL, + persistent_go->mode == WPAS_MODE_P2P_GO ? + P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0); + } else { + wpas_p2p_group_add(wpa_s, 1, 0, 0, 0); + } + + return 1; +} + + /** * wpas_p2p_init - Initialize P2P module for %wpa_supplicant * @global: Pointer to global data from wpa_supplicant_init() @@ -4786,6 +4813,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.get_persistent_group = wpas_get_persistent_group; p2p.get_go_info = wpas_get_go_info; p2p.remove_stale_groups = wpas_remove_stale_groups; + p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb; os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN); os_memcpy(p2p.dev_addr, wpa_s->global->p2p_dev_addr, ETH_ALEN); @@ -5692,6 +5720,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->global->add_psk = NULL; wpa_s->global->p2p_fail_on_wps_complete = 0; + wpa_s->global->pending_p2ps_group = 0; if (go_intent < 0) go_intent = wpa_s->conf->p2p_go_intent; @@ -6571,6 +6600,7 @@ int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr, { u16 config_methods; + wpa_s->global->pending_p2ps_group = 0; wpa_s->p2p_fallback_to_go_neg = 0; wpa_s->pending_pd_use = NORMAL_PD; if (p2ps_prov && use == WPAS_P2P_PD_FOR_ASP) { diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 9ee36a628..0a94ba81a 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -275,6 +275,7 @@ struct wpa_global { unsigned int p2p_per_sta_psk:1; unsigned int p2p_fail_on_wps_complete:1; unsigned int p2p_24ghz_social_channels:1; + unsigned int pending_p2ps_group:1; #ifdef CONFIG_WIFI_DISPLAY int wifi_display;