]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Wait until ongoing scan completes before starting P2P find
authorJouni Malinen <jouni@qca.qualcomm.com>
Tue, 15 Nov 2011 19:25:21 +0000 (21:25 +0200)
committerJouni Malinen <j@w1.fi>
Tue, 15 Nov 2011 19:28:35 +0000 (21:28 +0200)
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 <jouni@qca.qualcomm.com>

src/p2p/p2p.c
src/p2p/p2p.h
src/p2p/p2p_i.h
wpa_supplicant/events.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 404b2cdc87427b4f8ef0843226aa0961e2863c58..dfa8662ad3e478302ea126ec039b5035ac67e563 100644 (file)
@@ -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;
        }
 }
 
index aa7889b060dec8d22ec53a7f46c99fde453584ae..1501a20146b94b13940f5841f64126b373f55346 100644 (file)
@@ -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 */
index 7ee6e07d532a9d94ff7ccf3bcbb3fa459e388ac9..9d72a1c7d2c5dc1a58cfe66e6387301f45042f70 100644 (file)
@@ -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;
index 719555cb849d2d82c1f100d639aa7ffb34123dcf..b2e95eec9a1b0e491eef2054a45a951de2270b5c 100644 (file)
@@ -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);
index f3108c45fd691da064b95bddb0722bea8fbf0484..a2b3f06545c5f484e6cb4fdf93c4114066af7266 100644 (file)
@@ -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, &params);
 
        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);
index 63a6fead09bc2a3883e343f1dceba699d66a859c..59fc9a317b0c6a3af9670cbda1cd31793a65c58d 100644 (file)
@@ -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;