P2P: Allow all channels with multi-channel concurrency
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 26 Oct 2012 15:10:46 +0000 (18:10 +0300)
committerJouni Malinen <j@w1.fi>
Fri, 26 Oct 2012 15:10:46 +0000 (18:10 +0300)
If the driver indicates support for multi-channel concurrency, change
the p2p_connect behavior to not force the current operating channel, but
instead, just mark it as preferred for GO Negotiation. This change
applies only for the case when the freq parameter is not used with the
p2p_connect command.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

src/drivers/driver_test.c
src/p2p/p2p.c
src/p2p/p2p.h
wpa_supplicant/p2p_supplicant.c

index e7bf195..dd3a57f 100644 (file)
@@ -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);
 }
 
 
index 365d5fd..7d449c6 100644 (file)
@@ -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);
index 9ea4694..e5833f0 100644 (file)
@@ -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)
index 9e552c8..be87567 100644 (file)
@@ -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;