From af84a575044f6556994fcc124a955fc0ac0a6736 Mon Sep 17 00:00:00 2001 From: Irfan Sheriff Date: Sat, 22 Sep 2012 16:59:30 -0700 Subject: 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 --- src/p2p/p2p_build.c | 21 +++++++++++++++ src/p2p/p2p_go_neg.c | 56 +++++++++++++++++++++++++++++--------- src/p2p/p2p_invitation.c | 18 ++++++++++--- wpa_supplicant/p2p_supplicant.c | 59 ++++++++++++++++++++++++++++++++++++++--- 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); } -- cgit v1.1