P2PS: Add channel policy to PD Request
[mech_eap.git] / src / p2p / p2p.c
index 767706c..d861519 100644 (file)
@@ -1459,7 +1459,7 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
 
 
 /**
- * p2p_prepare_channel - Select operating channel for GO Negotiation
+ * p2p_prepare_channel - Select operating channel for GO Negotiation or P2PS PD
  * @p2p: P2P module context from p2p_init()
  * @dev: Selected peer device
  * @force_freq: Forced frequency in MHz or 0 if not forced
@@ -1468,9 +1468,9 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p)
  * Returns: 0 on success, -1 on failure (channel not supported for P2P)
  *
  * This function is used to do initial operating channel selection for GO
- * Negotiation prior to having received peer information. The selected channel
- * may be further optimized in p2p_reselect_channel() once the peer information
- * is available.
+ * Negotiation prior to having received peer information or for P2PS PD
+ * signalling. The selected channel may be further optimized in
+ * p2p_reselect_channel() once the peer information is available.
  */
 int p2p_prepare_channel(struct p2p_data *p2p, struct p2p_device *dev,
                        unsigned int force_freq, unsigned int pref_freq, int go)
@@ -2944,7 +2944,6 @@ void p2p_deinit(struct p2p_data *p2p)
        wpabuf_free(p2p->wfd_coupled_sink_info);
 #endif /* CONFIG_WIFI_DISPLAY */
 
-       eloop_cancel_timeout(p2p_ext_listen_timeout, p2p, NULL);
        eloop_cancel_timeout(p2p_scan_timeout, p2p, NULL);
        eloop_cancel_timeout(p2p_go_neg_start, p2p, NULL);
        eloop_cancel_timeout(p2p_go_neg_wait_timeout, p2p, NULL);
@@ -2971,6 +2970,8 @@ void p2p_deinit(struct p2p_data *p2p)
 void p2p_flush(struct p2p_data *p2p)
 {
        struct p2p_device *dev, *prev;
+
+       p2p_ext_listen(p2p, 0, 0);
        p2p_stop_find(p2p);
        dl_list_for_each_safe(dev, prev, &p2p->devices, struct p2p_device,
                              list) {
@@ -3326,6 +3327,43 @@ static void p2p_prov_disc_cb(struct p2p_data *p2p, int success)
        }
 
        /*
+        * If after PD Request the peer doesn't expect to receive PD Response
+        * the PD Request ACK indicates a completion of the current PD. This
+        * happens only on the advertiser side sending the follow-on PD Request
+        * with the status different than 12 (Success: accepted by user).
+        */
+       if (p2p->p2ps_prov && !p2p->p2ps_prov->pd_seeker &&
+           p2p->p2ps_prov->status != P2P_SC_SUCCESS_DEFERRED) {
+               p2p_dbg(p2p, "P2PS PD completion on Follow-on PD Request ACK");
+
+               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 (p2p->cfg->p2ps_prov_complete) {
+                       p2p->cfg->p2ps_prov_complete(
+                               p2p->cfg->cb_ctx,
+                               p2p->p2ps_prov->status,
+                               p2p->p2ps_prov->adv_mac,
+                               p2p->p2ps_prov->adv_mac,
+                               p2p->p2ps_prov->session_mac,
+                               NULL, p2p->p2ps_prov->adv_id,
+                               p2p->p2ps_prov->session_id,
+                               0, 0, NULL, 0, 0, 0,
+                               NULL, NULL, 0);
+               }
+
+               if (p2p->user_initiated_pd)
+                       p2p_reset_pending_pd(p2p);
+
+               p2ps_prov_free(p2p);
+               return;
+       }
+
+       /*
         * This postponing, of resetting pending_action_state, needs to be
         * done only for user initiated PD requests and not internal ones.
         */