P2P: Allow P2P client to specify preferred group channel
authorJouni Malinen <jouni@qca.qualcomm.com>
Fri, 1 Mar 2013 17:40:54 +0000 (19:40 +0200)
committerJouni Malinen <j@w1.fi>
Fri, 1 Mar 2013 17:40:54 +0000 (19:40 +0200)
When re-invoking a persistent group in P2P client role, the new
pref=<MHz> parameter can now be used with the p2p_invite command to
indicate a preferred operating frequency. Unlike the older freq=<MHz>
parameter, this leaves GO an option to select another channel (from our
supported channels) if the GO cannot accept the channel.

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

src/p2p/p2p_i.h
src/p2p/p2p_invitation.c
wpa_supplicant/README-P2P
wpa_supplicant/ctrl_iface.c
wpa_supplicant/dbus/dbus_new_handlers_p2p.c
wpa_supplicant/p2p_supplicant.c
wpa_supplicant/p2p_supplicant.h

index 856f78f..c753d49 100644 (file)
@@ -92,6 +92,7 @@ struct p2p_device {
 #define P2P_DEV_REPORTED_ONCE BIT(15)
 #define P2P_DEV_PREFER_PERSISTENT_RECONN BIT(16)
 #define P2P_DEV_PD_BEFORE_GO_NEG BIT(17)
+#define P2P_DEV_NO_PREF_CHAN BIT(18)
        unsigned int flags;
 
        int status; /* enum p2p_status_code */
index 918fd4b..9cde8bf 100644 (file)
@@ -62,8 +62,11 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
                                           p2p->client_timeout);
        p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ?
                                     P2P_INVITATION_FLAGS_TYPE : 0);
-       p2p_buf_add_operating_channel(buf, p2p->cfg->country,
-                                     p2p->op_reg_class, p2p->op_channel);
+       if (p2p->inv_role != P2P_INVITE_ROLE_CLIENT ||
+           !(peer->flags & P2P_DEV_NO_PREF_CHAN))
+               p2p_buf_add_operating_channel(buf, p2p->cfg->country,
+                                             p2p->op_reg_class,
+                                             p2p->op_channel);
        if (p2p->inv_bssid_set)
                p2p_buf_add_group_bssid(buf, p2p->inv_bssid);
        p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
@@ -564,6 +567,12 @@ int p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role,
        if (p2p_prepare_channel(p2p, dev, force_freq, pref_freq) < 0)
                return -1;
 
+       if (persistent_group && role == P2P_INVITE_ROLE_CLIENT && !force_freq &&
+           !pref_freq)
+               dev->flags |= P2P_DEV_NO_PREF_CHAN;
+       else
+               dev->flags &= ~P2P_DEV_NO_PREF_CHAN;
+
        if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) {
                if (!(dev->info.dev_capab &
                      P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) {
index fb99c7b..8447a90 100644 (file)
@@ -365,7 +365,7 @@ Remove all local services from internal SD query processing.
 Invitation
 
 p2p_invite [persistent=<network id>|group=<group ifname>] [peer=address]
-       [go_dev_addr=address] [freq=<freq in MHz>] [ht40]
+       [go_dev_addr=address] [freq=<freq in MHz>] [ht40] [pref=<MHz>]
 
 Invite a peer to join a group (e.g., group=wlan1) or to reinvoke a
 persistent group (e.g., persistent=4). If the peer device is the GO of
@@ -374,7 +374,11 @@ used to specify which device to invite. go_dev_addr parameter can be
 used to override the GO device address for Invitation Request should
 it be not known for some reason (this should not be needed in most
 cases). When reinvoking a persistent group, the GO device can specify
-the frequency for the group with the freq parameter.
+the frequency for the group with the freq parameter. When reinvoking a
+persistent group, the P2P client device can use freq parameter to force
+a specific operating channel (or invitation failure if GO rejects that)
+or pref parameter to request a specific channel (while allowing GO to
+select to use another channel, if needed).
 
 Group Operations
 
index 06efd2c..0804d71 100644 (file)
@@ -3969,7 +3969,7 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
        int id;
        struct wpa_ssid *ssid;
        u8 *_peer = NULL, peer[ETH_ALEN];
-       int freq = 0;
+       int freq = 0, pref_freq = 0;
        int ht40;
 
        id = atoi(cmd);
@@ -3996,9 +3996,17 @@ static int p2p_ctrl_invite_persistent(struct wpa_supplicant *wpa_s, char *cmd)
                        return -1;
        }
 
+       pos = os_strstr(cmd, " pref=");
+       if (pos) {
+               pos += 6;
+               pref_freq = atoi(pos);
+               if (pref_freq <= 0)
+                       return -1;
+       }
+
        ht40 = (os_strstr(cmd, " ht40") != NULL) || wpa_s->conf->p2p_go_ht40;
 
-       return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40);
+       return wpas_p2p_invite(wpa_s, _peer, ssid, NULL, freq, ht40, pref_freq);
 }
 
 
index 30e0eb3..6279f41 100644 (file)
@@ -630,7 +630,8 @@ DBusMessage * wpas_dbus_handler_p2p_invite(DBusMessage *message,
                if (ssid == NULL || ssid->disabled != 2)
                        goto err;
 
-               if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0) < 0) {
+               if (wpas_p2p_invite(wpa_s, peer_addr, ssid, NULL, 0, 0, 0) < 0)
+               {
                        reply = wpas_dbus_error_unknown_error(
                                message,
                                "Failed to reinvoke a persistent group");
index 4ec6ed1..004cf74 100644 (file)
@@ -3585,7 +3585,7 @@ static int wpas_p2p_setup_freqs(struct wpa_supplicant *wpa_s, int freq,
                           "(%u MHz) not available for P2P - try to use "
                           "another channel", *oper_freq);
                *force_freq = 0;
-       } else if (*oper_freq > 0 &&
+       } else if (*oper_freq > 0 && *pref_freq == 0 &&
                   (wpa_s->drv_flags &
                    WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
                wpa_printf(MSG_DEBUG, "P2P: Trying to prefer the channel we "
@@ -4583,11 +4583,11 @@ int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr)
 /* Invite to reinvoke a persistent group */
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
-                   int ht40)
+                   int ht40, int pref_freq)
 {
        enum p2p_invite_role role;
        u8 *bssid = NULL, bssid_buf[ETH_ALEN];
-       int force_freq = 0, pref_freq = 0, oper_freq = 0;
+       int force_freq = 0, oper_freq = 0;
        int res;
 
        wpa_s->p2p_persistent_go_freq = freq;
index b6ecf14..caeac7c 100644 (file)
@@ -105,7 +105,7 @@ int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version,
 int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr);
 int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
                    struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq,
-                   int ht40);
+                   int ht40, int pref_freq);
 int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname,
                          const u8 *peer_addr, const u8 *go_dev_addr);
 void wpas_p2p_completed(struct wpa_supplicant *wpa_s);