aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIrfan Sheriff <isheriff@google.com>2012-09-22 16:59:30 -0700
committerIrfan Sheriff <isheriff@google.com>2012-09-23 17:28:47 -0700
commitaf84a575044f6556994fcc124a955fc0ac0a6736 (patch)
tree2fc48bbddb8ef135f997561f8d3beb951341a640
parent89ca702e8ed3247d7007dbdebe531036671c34af (diff)
downloadexternal_wpa_supplicant_8-af84a575044f6556994fcc124a955fc0ac0a6736.zip
external_wpa_supplicant_8-af84a575044f6556994fcc124a955fc0ac0a6736.tar.gz
external_wpa_supplicant_8-af84a575044f6556994fcc124a955fc0ac0a6736.tar.bz2
GC channel fixes for better interop with SCC
- Force operating channel as the only channel in channel list attribute for go negotiation and persistence - Force an operating channel in go negotiation response even if the GO indicates a different in negotiation request - Fix a bug with updating peer operating channel based on GO negotiation confirm Bug: 7217600 Change-Id: I6da0dc1a49c1d99ae97dcab8ee9899e07a80a6cb
-rw-r--r--src/p2p/p2p_build.c21
-rw-r--r--src/p2p/p2p_go_neg.c56
-rw-r--r--src/p2p/p2p_invitation.c18
-rw-r--r--wpa_supplicant/p2p_supplicant.c59
4 files changed, 135 insertions, 19 deletions
diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c
index def422d..66e8456 100644
--- a/src/p2p/p2p_build.c
+++ b/src/p2p/p2p_build.c
@@ -135,6 +135,27 @@ void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country,
wpa_printf(MSG_DEBUG, "P2P: * Channel List");
}
+/* Adds a given channel as the only channel in channel list attribute */
+void p2p_buf_add_oper_as_channel_list(struct wpabuf *buf, const char *country,
+ u8 reg_class, u8 channel)
+{
+ u8 *len;
+ u8 channel_list[1];
+ channel_list[0] = channel;
+
+ /* Channel List */
+ wpabuf_put_u8(buf, P2P_ATTR_CHANNEL_LIST);
+ len = wpabuf_put(buf, 2); /* IE length to be filled */
+ wpabuf_put_data(buf, country, 3); /* Country String */
+
+ wpabuf_put_u8(buf, reg_class);
+ wpabuf_put_u8(buf, 1);
+ wpabuf_put_data(buf, channel_list, 1);
+
+ /* Update attribute length */
+ WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
+ wpa_printf(MSG_DEBUG, "P2P: * Oper as Channel List %u", channel);
+}
void p2p_buf_add_status(struct wpabuf *buf, u8 status)
{
diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c
index 031b3a1..0324fe5 100644
--- a/src/p2p/p2p_go_neg.c
+++ b/src/p2p/p2p_go_neg.c
@@ -174,7 +174,13 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p,
p2p_buf_add_ext_listen_timing(buf, p2p->ext_listen_period,
p2p->ext_listen_interval);
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
- p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
+ if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && p2p->op_channel) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Force channel list %d", p2p->op_channel);
+ p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country, p2p->op_reg_class,
+ p2p->op_channel);
+ } else {
+ p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
+ }
p2p_buf_add_device_info(buf, p2p, peer);
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class, p2p->op_channel);
@@ -294,26 +300,40 @@ static struct wpabuf * p2p_build_go_neg_resp(struct p2p_data *p2p,
p2p_buf_add_go_intent(buf, (p2p->go_intent << 1) | tie_breaker);
p2p_buf_add_config_timeout(buf, p2p->go_timeout, p2p->client_timeout);
if (peer && peer->go_state == REMOTE_GO) {
- wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating "
- "Channel attribute");
+ if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && p2p->op_channel) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Forcing a channel ");
+ p2p_buf_add_operating_channel(buf, p2p->cfg->country,
+ p2p->op_reg_class, p2p->op_channel);
+ } else {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Omit Operating "
+ "Channel attribute");
+ }
} else {
p2p_buf_add_operating_channel(buf, p2p->cfg->country,
p2p->op_reg_class,
p2p->op_channel);
}
p2p_buf_add_intended_addr(buf, p2p->intended_addr);
- if (status || peer == NULL) {
- p2p_buf_add_channel_list(buf, p2p->cfg->country,
- &p2p->channels);
- } else if (peer->go_state == REMOTE_GO) {
- p2p_buf_add_channel_list(buf, p2p->cfg->country,
- &p2p->channels);
+
+ if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && p2p->op_channel) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Force channel list %d", p2p->op_channel);
+ p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country, p2p->op_reg_class,
+ p2p->op_channel);
} else {
- struct p2p_channels res;
- p2p_channels_intersect(&p2p->channels, &peer->channels,
- &res);
- p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
+ if (status || peer == NULL) {
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &p2p->channels);
+ } else if (peer->go_state == REMOTE_GO) {
+ p2p_buf_add_channel_list(buf, p2p->cfg->country,
+ &p2p->channels);
+ } else {
+ struct p2p_channels res;
+ p2p_channels_intersect(&p2p->channels, &peer->channels,
+ &res);
+ p2p_buf_add_channel_list(buf, p2p->cfg->country, &res);
+ }
}
+
p2p_buf_add_device_info(buf, p2p, peer);
if (peer && peer->go_state == LOCAL_GO) {
p2p_buf_add_group_id(buf, p2p->cfg->dev_addr, p2p->ssid,
@@ -1168,6 +1188,16 @@ void p2p_process_go_neg_conf(struct p2p_data *p2p, const u8 *sa,
#endif /* CONFIG_P2P_STRICT */
}
+ if (msg.operating_channel) {
+ dev->oper_freq = p2p_channel_to_freq((const char *)
+ msg.operating_channel,
+ msg.operating_channel[3],
+ msg.operating_channel[4]);
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer operating "
+ "channel preference: %d MHz", dev->oper_freq);
+ } else
+ dev->oper_freq = 0;
+
if (!msg.channel_list) {
wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG,
"P2P: Mandatory Operating Channel attribute missing "
diff --git a/src/p2p/p2p_invitation.c b/src/p2p/p2p_invitation.c
index d26654b..b237cf8 100644
--- a/src/p2p/p2p_invitation.c
+++ b/src/p2p/p2p_invitation.c
@@ -66,7 +66,13 @@ static struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p,
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);
+ if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && p2p->op_channel) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Forcing channel list %d", p2p->op_channel);
+ p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country, p2p->op_reg_class,
+ p2p->op_channel);
+ } else {
+ p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels);
+ }
if (go_dev_addr)
dev_addr = go_dev_addr;
else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
@@ -133,8 +139,14 @@ static struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p,
reg_class, channel);
if (group_bssid)
p2p_buf_add_group_bssid(buf, group_bssid);
- if (channels)
- p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
+ if (p2p->cfg->p2p_concurrency == P2P_SINGLE_CHANNEL_CONCURRENT && channel) {
+ wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "Forcing channel list %d", channel);
+ p2p_buf_add_oper_as_channel_list(buf, p2p->cfg->country,
+ reg_class, channel);
+ } else {
+ if (channels)
+ p2p_buf_add_channel_list(buf, p2p->cfg->country, channels);
+ }
p2p_buf_update_ie_hdr(buf, len);
#ifdef CONFIG_WIFI_DISPLAY
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index f8db14e..53b2d5d 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -2807,10 +2807,14 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
p2p.p2p_intra_bss = wpa_s->conf->p2p_intra_bss;
#ifdef ANDROID_P2P
- if(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)
+ if(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT) {
p2p.p2p_concurrency = P2P_MULTI_CHANNEL_CONCURRENT;
- else if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_CONCURRENT)
+ wpa_printf(MSG_DEBUG, "P2P: Multi channel concurrency support");
+ } else {
+ // Add support for WPA_DRIVER_FLAGS_P2P_CONCURRENT
p2p.p2p_concurrency = P2P_SINGLE_CHANNEL_CONCURRENT;
+ wpa_printf(MSG_DEBUG, "P2P: Single channel concurrency support");
+ }
#endif
global->p2p = p2p_init(&p2p);
@@ -4427,6 +4431,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
{
enum p2p_invite_role role;
u8 *bssid = NULL;
+ int force_freq = 0, oper_freq = 0;
wpa_s->p2p_persistent_go_freq = freq;
wpa_s->p2p_go_ht40 = !!ht40;
@@ -4454,6 +4459,54 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
}
wpa_s->pending_invite_ssid_id = ssid->id;
+ if (wpa_s->current_ssid && wpa_drv_get_bssid(wpa_s, bssid) == 0 &&
+ wpa_s->assoc_freq)
+ oper_freq = wpa_s->assoc_freq;
+ else {
+ oper_freq = wpa_drv_shared_freq(wpa_s);
+ if (oper_freq < 0)
+ oper_freq = 0;
+ }
+
+ if (freq > 0) {
+ if (!p2p_supported_freq(wpa_s->global->p2p, freq)) {
+ wpa_printf(MSG_DEBUG, "P2P: The forced channel "
+ "(%u MHz) is not supported for P2P uses",
+ freq);
+ return -3;
+ }
+
+ if (oper_freq > 0 && freq != oper_freq &&
+ !(wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+ wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
+ "on %u MHz while connected on another "
+ "channel (%u MHz)", freq, oper_freq);
+ return -2;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Trying to force us to use the "
+ "requested channel (%u MHz)", freq);
+ force_freq = freq;
+ } else if (oper_freq > 0 &&
+ !p2p_supported_freq(wpa_s->global->p2p, oper_freq)) {
+ if (!(wpa_s->drv_flags &
+ WPA_DRIVER_FLAGS_MULTI_CHANNEL_CONCURRENT)) {
+ wpa_printf(MSG_DEBUG, "P2P: Cannot start P2P group "
+ "while connected on non-P2P supported "
+ "channel (%u MHz)", oper_freq);
+ return -2;
+ }
+ wpa_printf(MSG_DEBUG, "P2P: Current operating channel "
+ "(%u MHz) not available for P2P - try to use "
+ "another channel", oper_freq);
+ force_freq = 0;
+ } 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 "
+ "interface", oper_freq);
+ force_freq = oper_freq;
+ }
+
if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_MGMT)
return wpa_drv_p2p_invite(wpa_s, peer_addr, role, bssid,
ssid->ssid, ssid->ssid_len,
@@ -4463,7 +4516,7 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
return -1;
return p2p_invite(wpa_s->global->p2p, peer_addr, role, bssid,
- ssid->ssid, ssid->ssid_len, freq, go_dev_addr, 1);
+ ssid->ssid, ssid->ssid_len, force_freq, go_dev_addr, 1);
}