am 91c40cdc: wpa_supplicant: P2P-related fixes

* commit '91c40cdce17424d9a4718876becf0b7811cf68f2':
  wpa_supplicant: P2P-related fixes
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index bbe2002..7f4d295 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -132,7 +132,8 @@
 
 	/* Update attribute length */
 	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
-	wpa_printf(MSG_DEBUG, "P2P: * Channel List");
+	wpa_hexdump(MSG_DEBUG, "P2P: * Channel List",
+		    len + 2, (u8 *) wpabuf_put(buf, 0) - len - 2);
 }
 
 #ifdef ANDROID_P2P
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index b0b53fe..9c287b6 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -368,8 +368,8 @@
 }
 
 
-static void p2p_reselect_channel(struct p2p_data *p2p,
-				 struct p2p_channels *intersection)
+void p2p_reselect_channel(struct p2p_data *p2p,
+			  struct p2p_channels *intersection)
 {
 	struct p2p_reg_class *cl;
 	int freq;
diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h
index bf55015..673c4c1 100644
--- a/src/p2p/p2p_i.h
+++ b/src/p2p/p2p_i.h
@@ -655,6 +655,8 @@
 			     const u8 *data, size_t len);
 int p2p_connect_send(struct p2p_data *p2p, struct p2p_device *dev);
 u16 p2p_wps_method_pw_id(enum p2p_wps_method wps_method);
+void p2p_reselect_channel(struct p2p_data *p2p,
+			  struct p2p_channels *intersection);
 
 /* p2p_pd.c */
 void p2p_process_prov_disc_req(struct p2p_data *p2p, const u8 *sa,
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index 785200c..7d6dd11 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -253,6 +253,8 @@
 	}
 
 	if (op_freq) {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation "
+			"processing forced frequency %d MHz", op_freq);
 		if (p2p_freq_to_channel(p2p->cfg->country, op_freq,
 					&reg_class, &channel) < 0) {
 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
@@ -276,24 +278,89 @@
 		if (status == P2P_SC_SUCCESS)
 			channels = &intersection;
 	} else {
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+			"P2P: No forced channel from invitation processing - "
+			"figure out best one to use");
+
+		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
+				       &intersection);
+		/* Default to own configuration as a starting point */
+		p2p->op_reg_class = p2p->cfg->op_reg_class;
+		p2p->op_channel = p2p->cfg->op_channel;
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default "
+			"op_class %d channel %d",
+			p2p->op_reg_class, p2p->op_channel);
+
+		/* Use peer preference if specified and compatible */
+		if (msg.operating_channel) {
+			int req_freq;
+			req_freq = p2p_channel_to_freq(
+				(const char *) msg.operating_channel,
+				msg.operating_channel[3],
+				msg.operating_channel[4]);
+			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer "
+				"operating channel preference: %d MHz",
+				req_freq);
+			if (req_freq > 0 &&
+			    p2p_channels_includes(&intersection,
+						  msg.operating_channel[3],
+						  msg.operating_channel[4])) {
+				p2p->op_reg_class = msg.operating_channel[3];
+				p2p->op_channel = msg.operating_channel[4];
+				wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+					"P2P: Use peer preference op_class %d "
+					"channel %d",
+					p2p->op_reg_class, p2p->op_channel);
+			} else {
+				wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+					"P2P: Cannot use peer channel "
+					"preference");
+			}
+		}
+
+		if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
+					   p2p->op_channel)) {
+			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+				"P2P: Initially selected channel (op_class %d "
+				"channel %d) not in channel intersection - try "
+				"to reselect",
+				p2p->op_reg_class, p2p->op_channel);
+			p2p_reselect_channel(p2p, &intersection);
+			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+				"P2P: Re-selection result: op_class %d "
+				"channel %d",
+				p2p->op_reg_class, p2p->op_channel);
+			if (!p2p_channels_includes(&intersection,
+						   p2p->op_reg_class,
+						   p2p->op_channel)) {
+				wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
+					"P2P: Peer does not support selected "
+					"operating channel (reg_class=%u "
+					"channel=%u)",
+					p2p->op_reg_class, p2p->op_channel);
+				status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
+				goto fail;
+			}
+		}
+
 		op_freq = p2p_channel_to_freq(p2p->cfg->country,
-					      p2p->cfg->op_reg_class,
-					      p2p->cfg->op_channel);
+					      p2p->op_reg_class,
+					      p2p->op_channel);
 		if (op_freq < 0) {
 			wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 				"P2P: Unknown operational channel "
 				"(country=%c%c reg_class=%u channel=%u)",
 				p2p->cfg->country[0], p2p->cfg->country[1],
-				p2p->cfg->op_reg_class, p2p->cfg->op_channel);
+				p2p->op_reg_class, p2p->op_channel);
 			status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
 			goto fail;
 		}
+		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating "
+			"channel - %d MHz", op_freq);
 
-		p2p_channels_intersect(&p2p->cfg->channels, &dev->channels,
-				       &intersection);
 		if (status == P2P_SC_SUCCESS) {
-			reg_class = p2p->cfg->op_reg_class;
-			channel = p2p->cfg->op_channel;
+			reg_class = p2p->op_reg_class;
+			channel = p2p->op_channel;
 			channels = &intersection;
 		}
 	}
diff --git a/src/p2p/p2p_pd.c b/src/p2p/p2p_pd.c
index a2d5aee..42447e5 100644
--- a/src/p2p/p2p_pd.c
+++ b/src/p2p/p2p_pd.c
@@ -278,11 +278,6 @@
 		return;
 	}
 
-	if (p2p->pending_action_state == P2P_PENDING_PD) {
-		os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
-		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
-	}
-
 	if (dev->dialog_token != msg.dialog_token) {
 		wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
 			"P2P: Ignore Provision Discovery Response with "
@@ -292,6 +287,11 @@
 		return;
 	}
 
+	if (p2p->pending_action_state == P2P_PENDING_PD) {
+		os_memset(p2p->pending_pd_devaddr, 0, ETH_ALEN);
+		p2p->pending_action_state = P2P_NO_PENDING_ACTION;
+	}
+
 	/*
 	 * If the response is from the peer to whom a user initiated request
 	 * was sent earlier, we reset that state info here.
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index cf8f935..c721a29 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -377,6 +377,7 @@
 		wpa_config_remove_network(wpa_s->conf, id);
 		wpa_supplicant_clear_status(wpa_s);
 		wpa_supplicant_cancel_sched_scan(wpa_s);
+		wpa_s->sta_scan_pending = 0;
 	} else {
 		wpa_printf(MSG_DEBUG, "P2P: Temporary group network not "
 			   "found");
@@ -2322,8 +2323,9 @@
 			   " was accepted; op_freq=%d MHz",
 			   MAC2STR(sa), op_freq);
 		if (s) {
+			int go = s->mode == WPAS_MODE_P2P_GO;
 			wpas_p2p_group_add_persistent(
-				wpa_s, s, s->mode == WPAS_MODE_P2P_GO, 0, 0);
+				wpa_s, s, go, go ? op_freq : 0, 0);
 		} else if (bssid) {
 			wpas_p2p_join(wpa_s, bssid, go_dev_addr,
 				      wpa_s->p2p_wps_method, 0);