From 1595eb93aee0239de51f1090d4528e4b2cfe3add Mon Sep 17 00:00:00 2001 From: Ahmad Masri Date: Thu, 25 Sep 2014 12:42:07 +0300 Subject: [PATCH] P2P: Add support for 60 GHz social channel Support 60 GHz band in P2P module by selecting random social channel from all supported social channels in 2.4 GHz and 60 GHz bands. Signed-off-by: Jouni Malinen --- src/p2p/p2p.c | 11 +++- src/p2p/p2p.h | 14 +++++ src/p2p/p2p_utils.c | 20 ++++++- wpa_supplicant/p2p_supplicant.c | 99 ++++++++++++++++++++++----------- 4 files changed, 108 insertions(+), 36 deletions(-) diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index f0eba1a1b..9985e4f25 100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -1287,8 +1287,8 @@ static void p2p_prepare_channel_best(struct p2p_data *p2p) } else if (p2p_channel_random_social(&p2p->cfg->channels, &p2p->op_reg_class, &p2p->op_channel) == 0) { - p2p_dbg(p2p, "Select random available social channel %d from 2.4 GHz band as operating channel preference", - p2p->op_channel); + p2p_dbg(p2p, "Select random available social channel (op_class %u channel %u) as operating channel preference", + p2p->op_reg_class, p2p->op_channel); } else { /* Select any random available channel from the first available * operating class */ @@ -4095,6 +4095,13 @@ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled) } +int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, + u8 *op_channel) +{ + return p2p_channel_random_social(&p2p->channels, op_class, op_channel); +} + + int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced) { diff --git a/src/p2p/p2p.h b/src/p2p/p2p.h index dee79dfb5..076a2ac1a 100644 --- a/src/p2p/p2p.h +++ b/src/p2p/p2p.h @@ -1691,6 +1691,20 @@ void p2p_set_client_discoverability(struct p2p_data *p2p, int enabled); */ void p2p_set_managed_oper(struct p2p_data *p2p, int enabled); +/** + * p2p_config_get_random_social - Return a random social channel + * @p2p: P2P config + * @op_class: Selected operating class + * @op_channel: Selected social channel + * Returns: 0 on success, -1 on failure + * + * This function is used before p2p_init is called. A random social channel + * from supports bands 2.4 GHz (channels 1,6,11) and 60 GHz (channel 2) is + * returned on success. + */ +int p2p_config_get_random_social(struct p2p_config *p2p, u8 *op_class, + u8 *op_channel); + int p2p_set_listen_channel(struct p2p_data *p2p, u8 reg_class, u8 channel, u8 forced); diff --git a/src/p2p/p2p_utils.c b/src/p2p/p2p_utils.c index 508a60943..23acce761 100644 --- a/src/p2p/p2p_utils.c +++ b/src/p2p/p2p_utils.c @@ -149,6 +149,15 @@ int p2p_freq_to_channel(unsigned int freq, u8 *op_class, u8 *channel) return 0; } + if (freq >= 58320 && freq <= 64800) { + if ((freq - 58320) % 2160) + return -1; + + *op_class = 180; /* 60 GHz, channels 1..4 */ + *channel = (freq - 56160) / 2160; + return 0; + } + return -1; } @@ -482,7 +491,7 @@ int p2p_channel_select(struct p2p_channels *chans, const int *classes, int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, u8 *op_channel) { - u8 chan[3]; + u8 chan[4]; unsigned int num_channels = 0; /* Try to find available social channels from 2.4 GHz */ @@ -493,11 +502,18 @@ int p2p_channel_random_social(struct p2p_channels *chans, u8 *op_class, if (p2p_channels_includes(chans, 81, 11)) chan[num_channels++] = 11; + /* Try to find available social channels from 60 GHz */ + if (p2p_channels_includes(chans, 180, 2)) + chan[num_channels++] = 2; + if (num_channels == 0) return -1; - *op_class = 81; *op_channel = p2p_channel_pick_random(chan, num_channels); + if (*op_channel == 2) + *op_class = 180; + else + *op_class = 81; return 0; } diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index e206def7a..1189a6d4b 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -286,8 +286,10 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, struct wpa_supplicant *wpa_s = ctx; struct wpa_driver_scan_params *params = NULL; struct wpabuf *wps_ie, *ies; + unsigned int num_channels = 0; + int social_channels_freq[] = { 2412, 2437, 2462, 60480 }; size_t ielen; - u8 *n; + u8 *n, i; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -341,25 +343,34 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, switch (type) { case P2P_SCAN_SOCIAL: - params->freqs = os_malloc(4 * sizeof(int)); + params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1, + sizeof(int)); if (params->freqs == NULL) goto fail; - params->freqs[0] = 2412; - params->freqs[1] = 2437; - params->freqs[2] = 2462; - params->freqs[3] = 0; + for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) { + if (p2p_supported_freq(wpa_s->global->p2p, + social_channels_freq[i])) + params->freqs[num_channels++] = + social_channels_freq[i]; + } + params->freqs[num_channels++] = 0; break; case P2P_SCAN_FULL: break; case P2P_SCAN_SOCIAL_PLUS_ONE: - params->freqs = os_malloc(5 * sizeof(int)); + params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 2, + sizeof(int)); if (params->freqs == NULL) goto fail; - params->freqs[0] = 2412; - params->freqs[1] = 2437; - params->freqs[2] = 2462; - params->freqs[3] = freq; - params->freqs[4] = 0; + for (i = 0; i < ARRAY_SIZE(social_channels_freq); i++) { + if (p2p_supported_freq(wpa_s->global->p2p, + social_channels_freq[i])) + params->freqs[num_channels++] = + social_channels_freq[i]; + } + if (p2p_supported_freq(wpa_s->global->p2p, freq)) + params->freqs[num_channels++] = freq; + params->freqs[num_channels++] = 0; break; } @@ -3468,7 +3479,7 @@ struct p2p_oper_class_map { u8 min_chan; u8 max_chan; u8 inc; - enum { BW20, BW40PLUS, BW40MINUS, BW80 } bw; + enum { BW20, BW40PLUS, BW40MINUS, BW80, BW2160 } bw; }; static struct p2p_oper_class_map op_class[] = { @@ -3493,6 +3504,7 @@ static struct p2p_oper_class_map op_class[] = { * removing invalid channels. */ { HOSTAPD_MODE_IEEE80211A, 128, 36, 161, 4, BW80 }, + { HOSTAPD_MODE_IEEE80211AD, 180, 1, 4, 1, BW2160 }, { -1, 0, 0, 0, 0, BW20 } }; @@ -3864,7 +3876,6 @@ static int _wpas_p2p_in_progress(void *ctx) int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) { struct p2p_config p2p; - unsigned int r; int i; if (wpa_s->conf->p2p_disabled) @@ -3916,23 +3927,32 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) p2p.config_methods = wpa_s->wps->config_methods; } + if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) { + wpa_printf(MSG_ERROR, + "P2P: Failed to configure supported channel list"); + return -1; + } + if (wpa_s->conf->p2p_listen_reg_class && wpa_s->conf->p2p_listen_channel) { p2p.reg_class = wpa_s->conf->p2p_listen_reg_class; p2p.channel = wpa_s->conf->p2p_listen_channel; p2p.channel_forced = 1; } else { - p2p.reg_class = 81; /* * Pick one of the social channels randomly as the listen * channel. */ - if (os_get_random((u8 *) &r, sizeof(r)) < 0) + if (p2p_config_get_random_social(&p2p, &p2p.reg_class, + &p2p.channel) != 0) { + wpa_printf(MSG_ERROR, + "P2P: Failed to select random social channel as listen channel"); return -1; - p2p.channel = 1 + (r % 3) * 5; + } p2p.channel_forced = 0; } - wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d", p2p.channel); + wpa_printf(MSG_DEBUG, "P2P: Own listen channel: %d:%d", + p2p.reg_class, p2p.channel); if (wpa_s->conf->p2p_oper_reg_class && wpa_s->conf->p2p_oper_channel) { @@ -3943,14 +3963,17 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) "%d:%d", p2p.op_reg_class, p2p.op_channel); } else { - p2p.op_reg_class = 81; /* - * Use random operation channel from (1, 6, 11) if no other - * preference is indicated. + * Use random operation channel from 2.4 GHz band social + * channels (1, 6, 11) or band 60 GHz social channel (2) if no + * other preference is indicated. */ - if (os_get_random((u8 *) &r, sizeof(r)) < 0) + if (p2p_config_get_random_social(&p2p, &p2p.op_reg_class, + &p2p.op_channel) != 0) { + wpa_printf(MSG_ERROR, + "P2P: Failed to select random social channel as operation channel"); return -1; - p2p.op_channel = 1 + (r % 3) * 5; + } p2p.cfg_op_channel = 0; wpa_printf(MSG_DEBUG, "P2P: Random operating channel: " "%d:%d", p2p.op_reg_class, p2p.op_channel); @@ -3967,12 +3990,6 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) } else os_memcpy(p2p.country, "XX\x04", 3); - if (wpas_p2p_setup_channels(wpa_s, &p2p.channels, &p2p.cli_channels)) { - wpa_printf(MSG_ERROR, "P2P: Failed to configure supported " - "channel list"); - return -1; - } - os_memcpy(p2p.pri_dev_type, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN); @@ -5084,7 +5101,8 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 3; i++) { params->freq = 2412 + ((r + i) % 3) * 25; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq)) + freq_included(channels, params->freq) && + p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } @@ -5092,11 +5110,28 @@ static int wpas_p2p_select_freq_no_pref(struct wpa_supplicant *wpa_s, for (i = 0; i < 11; i++) { params->freq = 2412 + i * 5; if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && - freq_included(channels, params->freq)) + freq_included(channels, params->freq) && + p2p_supported_freq(wpa_s->global->p2p, params->freq)) goto out; } - wpa_printf(MSG_DEBUG, "P2P: No 2.4 GHz channel allowed"); + /* try social channel class 180 channel 2 */ + params->freq = 58320 + 1 * 2160; + if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && + freq_included(channels, params->freq) && + p2p_supported_freq(wpa_s->global->p2p, params->freq)) + goto out; + + /* try all channels in reg. class 180 */ + for (i = 0; i < 4; i++) { + params->freq = 58320 + i * 2160; + if (!wpas_p2p_disallowed_freq(wpa_s->global, params->freq) && + freq_included(channels, params->freq) && + p2p_supported_freq(wpa_s->global->p2p, params->freq)) + goto out; + } + + wpa_printf(MSG_DEBUG, "P2P: No 2.4 and 60 GHz channel allowed"); return -1; out: wpa_printf(MSG_DEBUG, "P2P: Set GO freq %d MHz (no preference known)",