]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
P2P: Allow scan operations during p2p_find
authorJouni Malinen <jouni@qca.qualcomm.com>
Thu, 23 Aug 2012 16:42:53 +0000 (19:42 +0300)
committerJouni Malinen <j@w1.fi>
Thu, 23 Aug 2012 16:42:53 +0000 (19:42 +0300)
Previously, all station mode scan operations were either skipped or
delayed while any P2P operation was in progress. To make concurrent
operations easier to use, reduce this limitation by allowing a scan
operation to be completed in the middle of a p2p_find. In addition,
allow station mode association to be completed. When the station mode
operation is run to its completion (scan results not acted on,
connection to an AP completed, connection failed), resume the p2p_find
operation.

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/scan.c
wpa_supplicant/wpa_supplicant.c
wpa_supplicant/wpa_supplicant_i.h

index 85d506252a0f541bcd41ccb4cecff7adcc3e2779..311aad3b35daad73f8739538812b3642fda462c2 100644 (file)
@@ -130,6 +130,8 @@ static const char * p2p_state_txt(int state)
                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 "?";
        }
@@ -799,6 +801,7 @@ static void p2p_search(struct p2p_data *p2p)
        int freq = 0;
        enum p2p_scan_type type;
        u16 pw_id = DEV_PW_DEFAULT;
+       int res;
 
        if (p2p->drv_in_listen) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Driver is still "
@@ -818,12 +821,18 @@ static void p2p_search(struct p2p_data *p2p)
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting search");
        }
 
-       if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
-                              p2p->num_req_dev_types, p2p->req_dev_types,
-                              p2p->find_dev_id, pw_id)) {
+       res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq,
+                                p2p->num_req_dev_types, p2p->req_dev_types,
+                                p2p->find_dev_id, pw_id);
+       if (res < 0) {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
                        "P2P: Scan request failed");
                p2p_continue_find(p2p);
+       } 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");
+               p2p_set_state(p2p, P2P_CONTINUE_SEARCH_WHEN_READY);
        } else {
                wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Running p2p_scan");
                p2p->p2p_scan_running = 1;
@@ -1005,6 +1014,11 @@ 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;
        wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find "
@@ -3199,6 +3213,8 @@ static void p2p_state_timeout(void *eloop_ctx, void *timeout_ctx)
                break;
        case P2P_SEARCH_WHEN_READY:
                break;
+       case P2P_CONTINUE_SEARCH_WHEN_READY:
+               break;
        }
 }
 
@@ -3980,6 +3996,9 @@ 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)
+               return 2;
        return p2p->state != P2P_IDLE && p2p->state != P2P_PROVISIONING;
 }
 
@@ -3992,3 +4011,10 @@ void p2p_set_config_timeout(struct p2p_data *p2p, u8 go_timeout,
                p2p->client_timeout = client_timeout;
        }
 }
+
+
+void p2p_increase_search_delay(struct p2p_data *p2p, unsigned int delay)
+{
+       if (p2p && p2p->search_delay < delay)
+               p2p->search_delay = delay;
+}
index 138f3e7607b60016454314272027837159e9a9f6..2f35deb7427e69daa723c38c423eb5ee1a00df38 100644 (file)
@@ -1708,4 +1708,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);
+
 #endif /* P2P_H */
index 3c505563a5348dfcee3b43a96ca796e38b96e4d3..7dbdf805e3cfb470327ef13eb2ce891f5ba60a21 100644 (file)
@@ -207,6 +207,11 @@ struct p2p_data {
                 * 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;
 
        /**
index 0c5c07c9fdeacdc35f4a8913a7e9e31b97978604..d70eae78dc8ac36b9b6d8430112fa38e55b55a51 100644 (file)
@@ -1027,7 +1027,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
 
 #ifdef CONFIG_P2P
        if (wpa_s->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
-           wpa_s->global->p2p != NULL) {
+           wpa_s->global->p2p != NULL && !wpa_s->sta_scan_pending) {
                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 "
@@ -1035,6 +1035,7 @@ static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s,
                        return -1;
                }
        }
+       wpa_s->sta_scan_pending = 0;
 #endif /* CONFIG_P2P */
 
        scan_res = wpa_supplicant_get_scan_results(wpa_s,
@@ -2321,6 +2322,18 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
 #ifndef CONFIG_NO_SCAN_PROCESSING
        case EVENT_SCAN_RESULTS:
                wpa_supplicant_event_scan_results(wpa_s, data);
+#ifdef CONFIG_P2P
+       if (wpa_s->p2p_cb_on_scan_complete && !wpa_s->global->p2p_disabled &&
+           wpa_s->global->p2p != NULL &&
+           wpa_s->wpa_state != WPA_AUTHENTICATING &&
+           wpa_s->wpa_state != WPA_ASSOCIATING) {
+               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 "
+                               "continued after scan result processing");
+               }
+       }
+#endif /* CONFIG_P2P */
                break;
 #endif /* CONFIG_NO_SCAN_PROCESSING */
        case EVENT_ASSOCINFO:
index e9934ae141cdf436f2d21b403877bb01ab2dc360..b47cf66a4f0f2f725632f3ccd9799a1a220280ca 100644 (file)
@@ -121,6 +121,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
                         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 wpabuf *wps_ie, *ies;
@@ -130,6 +131,18 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq,
        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_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->p2p_cb_on_scan_complete = 1;
+                       wpa_supplicant_req_scan(ifs, 0, 0);
+                       return 1;
+               }
+       }
+
        os_memset(&params, 0, sizeof(params));
 
        /* P2P Wildcard SSID */
@@ -4263,7 +4276,7 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s)
        }
 
        if (!wpa_s->show_group_started || !ssid)
-               return;
+               goto done;
 
        wpa_s->show_group_started = 0;
 
@@ -4305,6 +4318,19 @@ 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:
+       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 "
+                               "continued after successful connection");
+                       p2p_increase_search_delay(
+                               wpa_s->global->p2p,
+                               wpas_p2p_search_delay(wpa_s));
+               }
+       }
 }
 
 
index c608c3877848fefe7ed91b81b148a6853ef40fbc..93d152ed9223794d6b12d2e5049a208f55597fc2 100644 (file)
@@ -468,15 +468,18 @@ static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
 
 #ifdef CONFIG_P2P
        if (wpas_p2p_in_progress(wpa_s)) {
-               if (wpa_s->wpa_state == WPA_SCANNING) {
+               if (wpa_s->sta_scan_pending &&
+                   wpas_p2p_in_progress(wpa_s) == 2 &&
+                   wpa_s->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);
-               } else {
-                       wpa_dbg(wpa_s, MSG_DEBUG, "Do not request scan while "
-                               "P2P operation is in progress");
+                       return;
                }
-               return;
        }
 #endif /* CONFIG_P2P */
 
index aa0e578f25578a3bed13586224755fecbab6d47a..a0c2608c2cc1207873f0c1dd1ff39763b3bb7c2e 100644 (file)
@@ -192,6 +192,20 @@ 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);
+
+#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 "
+                               "continued after timed out authentication");
+                       p2p_increase_search_delay(
+                               wpa_s->global->p2p,
+                               wpas_p2p_search_delay(wpa_s));
+               }
+       }
+#endif /* CONFIG_P2P */
 }
 
 
@@ -3392,6 +3406,17 @@ void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid)
         */
        wpa_supplicant_req_scan(wpa_s, timeout / 1000,
                                1000 * (timeout % 1000));
+
+#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 "
+                               "continued after failed association");
+               }
+       }
+#endif /* CONFIG_P2P */
 }
 
 
index 1bd1f5a25d96da03fa12556937c906e163001c38..b2457c7bf1584891fffacc290225f9ce3280a712 100644 (file)
@@ -515,6 +515,7 @@ struct wpa_supplicant {
        char cross_connect_uplink[100];
 
        unsigned int p2p_cb_on_scan_complete:1;
+       unsigned int sta_scan_pending:1;
        unsigned int p2p_auto_join:1;
        unsigned int p2p_auto_pd:1;
        unsigned int p2p_persistent_group:1;