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)",