From 7c813acf9ca69f3c6d442ce820237249a6216201 Mon Sep 17 00:00:00 2001 From: Ahmad Kholaif Date: Thu, 23 Jul 2015 17:07:55 -0700 Subject: [PATCH] P2P: Inform driver of the operating channel following group formation Upon GO Negotiation completion, if the remote peer becomes GO, send a hint event over QCA vendor specific interface to inform the driver of the likely operating channel of the P2P GO. Signed-off-by: Jouni Malinen --- src/drivers/driver.h | 12 ++++++++ src/drivers/driver_nl80211.c | 47 +++++++++++++++++++++++++++++++ src/drivers/driver_nl80211.h | 1 + src/drivers/driver_nl80211_capa.c | 3 ++ wpa_supplicant/driver_i.h | 8 ++++++ wpa_supplicant/p2p_supplicant.c | 5 ++++ 6 files changed, 76 insertions(+) diff --git a/src/drivers/driver.h b/src/drivers/driver.h index d5946f46f..d73e6fdcd 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -3403,6 +3403,18 @@ struct wpa_driver_ops { * Returns 0 on success, -1 on failure */ int (*set_band)(void *priv, enum set_band band); + + /** + * set_prob_oper_freq - Indicate probable P2P operating channel + * @priv: Private driver interface data + * @freq: Channel frequency in MHz + * Returns 0 on success, -1 on failure + * + * This command can be used to inform the driver of the operating + * frequency that an ongoing P2P group formation is likely to come up + * on. Local device is assuming P2P Client role. + */ + int (*set_prob_oper_freq)(void *priv, unsigned int freq); }; diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c index 1f274065a..fd598901b 100644 --- a/src/drivers/driver_nl80211.c +++ b/src/drivers/driver_nl80211.c @@ -8509,6 +8509,52 @@ static int nl80211_set_band(void *priv, enum set_band band) } +static int nl80211_set_prob_oper_freq(void *priv, unsigned int freq) +{ + struct i802_bss *bss = priv; + struct wpa_driver_nl80211_data *drv = bss->drv; + struct nl_msg *msg; + int ret; + struct nlattr *params; + + if (!drv->set_prob_oper_freq) + return -1; + + wpa_printf(MSG_DEBUG, + "nl80211: Set P2P probable operating freq %u for ifindex %d", + freq, bss->ifindex); + + if (!(msg = nl80211_drv_msg(drv, 0, NL80211_CMD_VENDOR)) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_ID, OUI_QCA) || + nla_put_u32(msg, NL80211_ATTR_VENDOR_SUBCMD, + QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL) || + !(params = nla_nest_start(msg, NL80211_ATTR_VENDOR_DATA)) || + nla_put_u32(msg, + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_IFACE_TYPE, + QCA_IFACE_TYPE_P2P_CLIENT) || + nla_put_u32(msg, + QCA_WLAN_VENDOR_ATTR_PROBABLE_OPER_CHANNEL_FREQ, + freq)) { + wpa_printf(MSG_ERROR, + "%s: err in adding vendor_cmd and vendor_data", + __func__); + nlmsg_free(msg); + return -1; + } + nla_nest_end(msg, params); + + ret = send_and_recv_msgs(drv, msg, NULL, NULL); + msg = NULL; + if (ret) { + wpa_printf(MSG_ERROR, "%s: err in send_and_recv_msgs", + __func__); + return ret; + } + nlmsg_free(msg); + return 0; +} + + const struct wpa_driver_ops wpa_driver_nl80211_ops = { .name = "nl80211", .desc = "Linux nl80211/cfg80211", @@ -8617,4 +8663,5 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = { .del_tx_ts = nl80211_del_ts, .do_acs = wpa_driver_do_acs, .set_band = nl80211_set_band, + .set_prob_oper_freq = nl80211_set_prob_oper_freq, }; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 1536d2ffb..078df4c0f 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -146,6 +146,7 @@ struct wpa_driver_nl80211_data { unsigned int set_rekey_offload:1; unsigned int p2p_go_ctwindow_supported:1; unsigned int setband_vendor_cmd_avail:1; + unsigned int set_prob_oper_freq:1; u64 remain_on_chan_cookie; u64 send_action_cookie; diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index 926c11545..e56f11138 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -589,6 +589,9 @@ static int wiphy_info_handler(struct nl_msg *msg, void *arg) case QCA_NL80211_VENDOR_SUBCMD_GET_FEATURES: drv->get_features_vendor_cmd_avail = 1; break; + case QCA_NL80211_VENDOR_SUBCMD_SET_PROBABLE_OPER_CHANNEL: + drv->set_prob_oper_freq = 1; + break; case QCA_NL80211_VENDOR_SUBCMD_DO_ACS: drv->capa.flags |= WPA_DRIVER_FLAGS_ACS_OFFLOAD; diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index d1f9f8be1..6ce4c2727 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -893,4 +893,12 @@ static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s, return wpa_s->driver->set_band(wpa_s->drv_priv, band); } +static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s, + unsigned int freq) +{ + if (!wpa_s->driver->set_prob_oper_freq) + return 0; + return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq); +} + #endif /* DRIVER_I_H */ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 541cb2064..8f90e38ad 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -2081,6 +2081,11 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) return; } + if (!res->role_go) { + /* Inform driver of the operating channel of GO. */ + wpa_drv_set_prob_oper_freq(wpa_s, res->freq); + } + if (wpa_s->p2p_go_ht40) res->ht40 = 1; if (wpa_s->p2p_go_vht)