p2p->cfg->invitation_result(
p2p->cfg->cb_ctx, -1, NULL, NULL,
p2p->invite_peer->info.p2p_device_addr,
- 0);
+ 0, 0);
}
p2p_set_state(p2p, P2P_IDLE);
}
* @channels: Available operating channels for the group
* @addr: Peer address
* @freq: Frequency (in MHz) indicated during invitation or 0
+ * @peer_oper_freq: Operating frequency (in MHz) advertized by the peer
+ * during invitation or 0
*
* This callback is used to indicate result of an Invitation procedure
* started with a call to p2p_invite(). The indicated status code is
*/
void (*invitation_result)(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
- const u8 *addr, int freq);
+ const u8 *addr, int freq, int peer_oper_freq);
/**
* go_connected - Check whether we are connected to a GO
}
}
- if (!p2p_channels_includes(&intersection, p2p->op_reg_class,
+ /* Reselect the channel only for the case of the GO */
+ if (go &&
+ !p2p_channels_includes(&intersection, p2p->op_reg_class,
p2p->op_channel)) {
p2p_dbg(p2p, "Initially selected channel (op_class %d channel %d) not in channel intersection - try to reselect",
p2p->op_reg_class, p2p->op_channel);
status = P2P_SC_FAIL_NO_COMMON_CHANNELS;
goto fail;
}
- } else if (!(dev->flags & P2P_DEV_FORCE_FREQ) &&
+ } else if (go && !(dev->flags & P2P_DEV_FORCE_FREQ) &&
!p2p->cfg->cfg_op_channel) {
p2p_dbg(p2p, "Try to reselect channel selection with peer information received; previously selected op_class %u channel %u",
p2p->op_reg_class, p2p->op_channel);
}
if (p2p->cfg->invitation_result) {
+ int peer_oper_freq = 0;
int freq = p2p_channel_to_freq(p2p->op_reg_class,
p2p->op_channel);
if (freq < 0)
freq = 0;
+
+ if (msg.operating_channel) {
+ peer_oper_freq = p2p_channel_to_freq(
+ msg.operating_channel[3],
+ msg.operating_channel[4]);
+ if (peer_oper_freq < 0)
+ peer_oper_freq = 0;
+ }
+
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
msg.group_bssid, channels, sa,
- freq);
+ freq, peer_oper_freq);
}
p2p_parse_free(&msg);
return 0;
if (wpa_s->p2p_in_provisioning ||
- wpa_s->show_group_started) {
+ wpa_s->show_group_started ||
+ wpa_s->p2p_in_invitation) {
/*
* Use shorter wait during P2P Provisioning
* state and during P2P join-a-group operation
wpa_s->p2p_in_provisioning = 0;
}
+ wpa_s->p2p_in_invitation = 0;
+
/*
* Make sure wait for the first client does not remain active after the
* group has been removed.
if (s) {
int go = s->mode == WPAS_MODE_P2P_GO;
wpas_p2p_group_add_persistent(
- wpa_s, s, go, 0, go ? op_freq : 0, 0, 0, NULL,
+ wpa_s, s, go, 0, op_freq, 0, 0, NULL,
go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0);
} else if (bssid) {
wpa_s->user_initiated_pd = 0;
static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
const struct p2p_channels *channels,
- const u8 *peer, int neg_freq)
+ const u8 *peer, int neg_freq,
+ int peer_oper_freq)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *ssid;
+ int freq;
if (bssid) {
wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_INVITATION_RESULT
"starting persistent group");
os_sleep(0, 50000);
+ if (neg_freq > 0 && ssid->mode == WPAS_MODE_P2P_GO &&
+ freq_included(channels, neg_freq))
+ freq = neg_freq;
+ else if (peer_oper_freq > 0 && ssid->mode != WPAS_MODE_P2P_GO &&
+ freq_included(channels, peer_oper_freq))
+ freq = peer_oper_freq;
+ else
+ freq = 0;
+
+ wpa_printf(MSG_DEBUG, "P2P: Persistent group invitation success - op_freq=%d MHz SSID=%s",
+ freq, wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
wpas_p2p_group_add_persistent(wpa_s, ssid,
ssid->mode == WPAS_MODE_P2P_GO,
wpa_s->p2p_persistent_go_freq,
- neg_freq,
+ freq,
wpa_s->p2p_go_ht40, wpa_s->p2p_go_vht,
channels,
ssid->mode == WPAS_MODE_P2P_GO ?
static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s,
- struct wpa_ssid *params, int addr_allocated)
+ struct wpa_ssid *params, int addr_allocated,
+ int freq)
{
struct wpa_ssid *ssid;
ssid->passphrase = os_strdup(params->passphrase);
wpa_s->show_group_started = 1;
+ wpa_s->p2p_in_invitation = 1;
+ wpa_s->p2p_invite_go_freq = freq;
wpa_supplicant_select_network(wpa_s, ssid);
wpa_s->p2p_fallback_to_go_neg = 0;
- if (ssid->mode == WPAS_MODE_INFRA)
- return wpas_start_p2p_client(wpa_s, ssid, addr_allocated);
-
- if (ssid->mode != WPAS_MODE_P2P_GO)
- return -1;
-
if (force_freq > 0) {
freq = wpas_p2p_select_go_freq(wpa_s, force_freq);
if (freq < 0)
freq = 0;
}
+ if (ssid->mode == WPAS_MODE_INFRA)
+ return wpas_start_p2p_client(wpa_s, ssid, addr_allocated, freq);
+
+ if (ssid->mode != WPAS_MODE_P2P_GO)
+ return -1;
+
if (wpas_p2p_init_go_params(wpa_s, ¶ms, freq, ht40, vht, channels))
return -1;
}
wpa_s->p2p_in_provisioning++;
}
+
+ if (params->freqs == NULL && wpa_s->p2p_in_invitation) {
+ /*
+ * Optimize scan based on GO information during persistent
+ * group reinvocation
+ */
+ if (wpa_s->p2p_in_invitation < 5 ||
+ wpa_s->p2p_invite_go_freq > 0) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation",
+ wpa_s->p2p_invite_go_freq);
+ params->freqs = os_zalloc(2 * sizeof(int));
+ if (params->freqs)
+ params->freqs[0] = wpa_s->p2p_invite_go_freq;
+ }
+ wpa_s->p2p_in_invitation++;
+ if (wpa_s->p2p_in_invitation > 20) {
+ /*
+ * This should not really happen since the variable is
+ * cleared on group removal, but if it does happen, make
+ * sure we do not get stuck in special invitation scan
+ * mode.
+ */
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation");
+ wpa_s->p2p_in_invitation = 0;
+ }
+ }
#endif /* CONFIG_P2P */
#ifdef CONFIG_WPS
params.num_ssids = 1;
goto ssid_list_set;
}
+
+ if (wpa_s->p2p_in_invitation) {
+ if (wpa_s->current_ssid) {
+ wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation");
+ params.ssids[0].ssid = wpa_s->current_ssid->ssid;
+ params.ssids[0].ssid_len =
+ wpa_s->current_ssid->ssid_len;
+ params.num_ssids = 1;
+ } else {
+ wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation");
+ }
+ goto ssid_list_set;
+ }
#endif /* CONFIG_P2P */
/* Find the starting point from which to continue scanning */
u8 p2p_auth_invite[ETH_ALEN];
int p2p_sd_over_ctrl_iface;
int p2p_in_provisioning;
+ int p2p_in_invitation;
+ int p2p_invite_go_freq;
int pending_invite_ssid_id;
int show_group_started;
u8 go_dev_addr[ETH_ALEN];