diff --git a/src/drivers/driver_test.c b/src/drivers/driver_test.c index e7bf19565..dd3a57f7b 100644 --- a/src/drivers/driver_test.c +++ b/src/drivers/driver_test.c @@ -2870,7 +2870,7 @@ static int wpa_driver_test_p2p_connect(void *priv, const u8 *peer_addr, return -1; return p2p_connect(drv->p2p, peer_addr, wps_method, go_intent, own_interface_addr, force_freq, persistent_group, - NULL, 0, 0); + NULL, 0, 0, 0); } diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 365d5fdf9..7d449c689 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1086,15 +1086,17 @@ void p2p_stop_find(struct p2p_data *p2p) } -static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq) +static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq, + unsigned int pref_freq) { - if (force_freq) { + if (force_freq || pref_freq) { u8 op_reg_class, op_channel; - if (p2p_freq_to_channel(p2p->cfg->country, force_freq, + unsigned int freq = force_freq ? force_freq : pref_freq; + if (p2p_freq_to_channel(p2p->cfg->country, freq, &op_reg_class, &op_channel) < 0) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Unsupported frequency %u MHz", - force_freq); + freq); return -1; } if (!p2p_channels_includes(&p2p->cfg->channels, op_reg_class, @@ -1102,15 +1104,21 @@ static int p2p_prepare_channel(struct p2p_data *p2p, unsigned int force_freq) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Frequency %u MHz (oper_class %u " "channel %u) not allowed for P2P", - force_freq, op_reg_class, op_channel); + freq, op_reg_class, op_channel); return -1; } p2p->op_reg_class = op_reg_class; p2p->op_channel = op_channel; - p2p->channels.reg_classes = 1; - p2p->channels.reg_class[0].channels = 1; - p2p->channels.reg_class[0].reg_class = p2p->op_reg_class; - p2p->channels.reg_class[0].channel[0] = p2p->op_channel; + if (force_freq) { + p2p->channels.reg_classes = 1; + p2p->channels.reg_class[0].channels = 1; + p2p->channels.reg_class[0].reg_class = + p2p->op_reg_class; + p2p->channels.reg_class[0].channel[0] = p2p->op_channel; + } else { + os_memcpy(&p2p->channels, &p2p->cfg->channels, + sizeof(struct p2p_channels)); + } } else { u8 op_reg_class, op_channel; @@ -1190,7 +1198,7 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - int pd_before_go_neg) + int pd_before_go_neg, unsigned int pref_freq) { struct p2p_device *dev; @@ -1201,7 +1209,7 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr), wps_method, persistent_group, pd_before_go_neg); - if (p2p_prepare_channel(p2p, force_freq) < 0) + if (p2p_prepare_channel(p2p, force_freq, pref_freq) < 0) return -1; dev = p2p_get_device(p2p, peer_addr); @@ -1301,7 +1309,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - const u8 *force_ssid, size_t force_ssid_len) + const u8 *force_ssid, size_t force_ssid_len, + unsigned int pref_freq) { struct p2p_device *dev; @@ -1312,7 +1321,7 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, MAC2STR(peer_addr), go_intent, MAC2STR(own_interface_addr), wps_method, persistent_group); - if (p2p_prepare_channel(p2p, force_freq) < 0) + if (p2p_prepare_channel(p2p, force_freq, pref_freq) < 0) return -1; dev = p2p_get_device(p2p, peer_addr); diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index 9ea4694e7..e5833f009 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -889,6 +889,8 @@ int p2p_listen(struct p2p_data *p2p, unsigned int timeout); * @pd_before_go_neg: Whether to send Provision Discovery prior to GO * Negotiation as an interoperability workaround when initiating group * formation + * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if + * force_freq == 0) * Returns: 0 on success, -1 on failure */ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, @@ -896,7 +898,7 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, const u8 *force_ssid, size_t force_ssid_len, - int pd_before_go_neg); + int pd_before_go_neg, unsigned int pref_freq); /** * p2p_authorize - Authorize P2P group formation (GO negotiation) @@ -912,6 +914,8 @@ int p2p_connect(struct p2p_data *p2p, const u8 *peer_addr, * @force_ssid: Forced SSID for the group if we become GO or %NULL to generate * a new SSID * @force_ssid_len: Length of $force_ssid buffer + * @pref_freq: Preferred operating frequency in MHz or 0 (this is only used if + * force_freq == 0) * Returns: 0 on success, -1 on failure * * This is like p2p_connect(), but the actual group negotiation is not @@ -921,7 +925,8 @@ int p2p_authorize(struct p2p_data *p2p, const u8 *peer_addr, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - const u8 *force_ssid, size_t force_ssid_len); + const u8 *force_ssid, size_t force_ssid_len, + unsigned int pref_freq); /** * p2p_reject - Reject peer device (explicitly block connection attempts) diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 9e552c82e..be87567a4 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2879,7 +2879,7 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - struct wpa_ssid *ssid) + struct wpa_ssid *ssid, unsigned int pref_freq) { if (persistent_group && wpa_s->conf->persistent_reconnect) persistent_group = 2; @@ -2901,7 +2901,7 @@ static int wpas_p2p_start_go_neg(struct wpa_supplicant *wpa_s, go_intent, own_interface_addr, force_freq, persistent_group, ssid ? ssid->ssid : NULL, ssid ? ssid->ssid_len : 0, - wpa_s->p2p_pd_before_go_neg); + wpa_s->p2p_pd_before_go_neg, pref_freq); } @@ -2910,7 +2910,7 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s, enum p2p_wps_method wps_method, int go_intent, const u8 *own_interface_addr, unsigned int force_freq, int persistent_group, - struct wpa_ssid *ssid) + struct wpa_ssid *ssid, unsigned int pref_freq) { if (persistent_group && wpa_s->conf->persistent_reconnect) persistent_group = 2; @@ -2921,7 +2921,7 @@ static int wpas_p2p_auth_go_neg(struct wpa_supplicant *wpa_s, return p2p_authorize(wpa_s->global->p2p, peer_addr, wps_method, go_intent, own_interface_addr, force_freq, persistent_group, ssid ? ssid->ssid : NULL, - ssid ? ssid->ssid_len : 0); + ssid ? ssid->ssid_len : 0, pref_freq); } @@ -3399,7 +3399,7 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, int go_intent, int freq, int persistent_id, int pd, int ht40) { - int force_freq = 0, oper_freq = 0; + int force_freq = 0, pref_freq = 0, oper_freq = 0; u8 bssid[ETH_ALEN]; int ret = 0; enum wpa_driver_if_type iftype; @@ -3512,6 +3512,13 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, "(%u MHz) not available for P2P - try to use " "another channel", oper_freq); force_freq = 0; + } else if (oper_freq > 0 && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) { + wpa_printf(MSG_DEBUG, "P2P: Trying to prefer the channel we " + "are already using (%u MHz) on another interface", + oper_freq); + pref_freq = oper_freq; } else if (oper_freq > 0) { wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the " "channel we are already using (%u MHz) on another " @@ -3539,15 +3546,15 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, if (auth) { if (wpas_p2p_auth_go_neg(wpa_s, peer_addr, wps_method, go_intent, if_addr, - force_freq, persistent_group, ssid) < - 0) + force_freq, persistent_group, ssid, + pref_freq) < 0) return -1; return ret; } if (wpas_p2p_start_go_neg(wpa_s, peer_addr, wps_method, go_intent, if_addr, force_freq, - persistent_group, ssid) < 0) { + persistent_group, ssid, pref_freq) < 0) { if (wpa_s->create_p2p_iface) wpas_p2p_remove_pending_group_interface(wpa_s); return -1;