static enum chan_allowed has_channel(struct wpa_global *global,
- struct hostapd_hw_modes *mode, u8 chan,
- int *flags)
+ struct hostapd_hw_modes *mode, u8 op_class,
+ u8 chan, int *flags)
{
int i;
unsigned int freq;
- freq = (mode->mode == HOSTAPD_MODE_IEEE80211A ? 5000 : 2407) +
- chan * 5;
+ freq = ieee80211_chan_to_freq(NULL, op_class, chan);
if (wpas_p2p_disallowed_freq(global, freq))
return NOT_ALLOWED;
for (i = 0; i < mode->num_channels; i++) {
- if (mode->channels[i].chan == chan) {
+ if ((unsigned int) mode->channels[i].freq == freq) {
if (flags)
*flags = mode->channels[i].flag;
if (mode->channels[i].flag &
static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel)
+ u8 channel, const u8 *center_channels,
+ size_t num_chan)
{
- u8 center_channels[] = { 42, 58, 106, 122, 138, 155, 171 };
size_t i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
- for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+ for (i = 0; i < num_chan; i++)
/*
* In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
* so the center channel is 6 channels away from the start/end.
}
+static const u8 center_channels_5ghz_80mhz[] = { 42, 58, 106, 122, 138,
+ 155, 171 };
+static const u8 center_channels_6ghz_80mhz[] = { 7, 23, 39, 55, 71, 87, 103,
+ 119, 135, 151, 167, 183, 199,
+ 215 };
+
static enum chan_allowed wpas_p2p_verify_80mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
u8 center_chan;
int i, flags;
enum chan_allowed res, ret = ALLOWED;
+ const u8 *chans;
+ size_t num_chans;
+ bool is_6ghz = is_6ghz_op_class(op_class);
- center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+ if (is_6ghz) {
+ chans = center_channels_6ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+ } else {
+ chans = center_channels_5ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+ }
+ center_chan = wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+ chans, num_chans);
if (!center_chan)
return NOT_ALLOWED;
- if (center_chan >= 58 && center_chan <= 138)
+ if (!is_6ghz && center_chan >= 58 && center_chan <= 138)
return NOT_ALLOWED; /* Do not allow DFS channels for P2P */
/* check all the channels are available */
for (i = 0; i < 4; i++) {
int adj_chan = center_chan - 6 + i * 4;
- res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+ res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+ &flags);
if (res == NOT_ALLOWED)
return NOT_ALLOWED;
if (res == NO_IR)
static int wpas_p2p_get_center_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel)
+ u8 channel, const u8 *center_channels,
+ size_t num_chan)
{
- u8 center_channels[] = { 50, 114, 163 };
unsigned int i;
if (mode->mode != HOSTAPD_MODE_IEEE80211A)
return 0;
- for (i = 0; i < ARRAY_SIZE(center_channels); i++)
+ for (i = 0; i < num_chan; i++)
/*
* In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
* so the center channel is 14 channels away from the start/end.
}
+static const u8 center_channels_5ghz_160mhz[] = { 50, 114, 163 };
+static const u8 center_channels_6ghz_160mhz[] = { 15, 47, 79, 111, 143, 175,
+ 207 };
+
static enum chan_allowed wpas_p2p_verify_160mhz(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
u8 center_chan;
int i, flags;
enum chan_allowed res, ret = ALLOWED;
+ const u8 *chans;
+ size_t num_chans;
- center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+ } else {
+ chans = center_channels_5ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+ }
+ center_chan = wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+ chans, num_chans);
if (!center_chan)
return NOT_ALLOWED;
/* VHT 160 MHz uses DFS channels in most countries. */
for (i = 0; i < 8; i++) {
int adj_chan = center_chan - 14 + i * 4;
- res = has_channel(wpa_s->global, mode, adj_chan, &flags);
+ res = has_channel(wpa_s->global, mode, op_class, adj_chan,
+ &flags);
if (res == NOT_ALLOWED)
return NOT_ALLOWED;
static enum chan_allowed wpas_p2p_verify_channel(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode,
- u8 channel, u8 bw)
+ u8 op_class, u8 channel, u8 bw)
{
int flag = 0;
enum chan_allowed res, res2;
- res2 = res = has_channel(wpa_s->global, mode, channel, &flag);
+ res2 = res = has_channel(wpa_s->global, mode, op_class, channel, &flag);
if (bw == BW40MINUS) {
if (!(flag & HOSTAPD_CHAN_HT40MINUS))
return NOT_ALLOWED;
- res2 = has_channel(wpa_s->global, mode, channel - 4, NULL);
+ res2 = has_channel(wpa_s->global, mode, op_class, channel - 4,
+ NULL);
} else if (bw == BW40PLUS) {
if (!(flag & HOSTAPD_CHAN_HT40PLUS))
return NOT_ALLOWED;
- res2 = has_channel(wpa_s->global, mode, channel + 4, NULL);
+ res2 = has_channel(wpa_s->global, mode, op_class, channel + 4,
+ NULL);
} else if (bw == BW80) {
- res2 = wpas_p2p_verify_80mhz(wpa_s, mode, channel, bw);
+ res2 = wpas_p2p_verify_80mhz(wpa_s, mode, op_class, channel,
+ bw);
} else if (bw == BW160) {
- res2 = wpas_p2p_verify_160mhz(wpa_s, mode, channel, bw);
+ res2 = wpas_p2p_verify_160mhz(wpa_s, mode, op_class, channel,
+ bw);
} else if (bw == BW4320 || bw == BW6480 || bw == BW8640) {
return wpas_p2p_verify_edmg(wpa_s, mode, channel);
}
ch < 149 && ch + o->inc > 149)
ch = 149;
- res = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+ res = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+ ch, o->bw);
if (res == ALLOWED) {
if (reg == NULL) {
if (cla == P2P_MAX_REG_CLASSES)
(o->bw != BW40PLUS && o->bw != BW40MINUS) ||
ch != channel)
continue;
- ret = wpas_p2p_verify_channel(wpa_s, mode, ch, o->bw);
+ ret = wpas_p2p_verify_channel(wpa_s, mode, o->op_class,
+ ch, o->bw);
if (ret == ALLOWED)
return (o->bw == BW40MINUS) ? -1 : 1;
}
int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel)
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class)
{
- if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW80))
+ const u8 *chans;
+ size_t num_chans;
+
+ if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW80))
return 0;
- return wpas_p2p_get_center_80mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_80mhz);
+ } else {
+ chans = center_channels_5ghz_80mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_80mhz);
+ }
+ return wpas_p2p_get_center_80mhz(wpa_s, mode, channel,
+ chans, num_chans);
}
int wpas_p2p_get_vht160_center(struct wpa_supplicant *wpa_s,
- struct hostapd_hw_modes *mode, u8 channel)
+ struct hostapd_hw_modes *mode, u8 channel,
+ u8 op_class)
{
- if (!wpas_p2p_verify_channel(wpa_s, mode, channel, BW160))
+ const u8 *chans;
+ size_t num_chans;
+
+ if (!wpas_p2p_verify_channel(wpa_s, mode, op_class, channel, BW160))
return 0;
- return wpas_p2p_get_center_160mhz(wpa_s, mode, channel);
+ if (is_6ghz_op_class(op_class)) {
+ chans = center_channels_6ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_6ghz_160mhz);
+ } else {
+ chans = center_channels_5ghz_160mhz;
+ num_chans = ARRAY_SIZE(center_channels_5ghz_160mhz);
+ }
+ return wpas_p2p_get_center_160mhz(wpa_s, mode, channel,
+ chans, num_chans);
}
enum hostapd_hw_mode mode;
struct hostapd_hw_modes *hwmode;
u8 chan;
+ u8 op_class;
cand = wpa_s->p2p_group_common_freqs[i];
+ op_class = is_6ghz_freq(cand) ? 133 : 128;
mode = ieee80211_freq_to_chan(cand, &chan);
hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
mode, is_6ghz_freq(cand));
if (!hwmode ||
- wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW80) != ALLOWED)
+ wpas_p2p_verify_channel(wpa_s, hwmode, op_class,
+ chan, BW80) != ALLOWED)
continue;
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
for (i = 0; i < wpa_s->p2p_group_common_freqs_num; i++) {
enum hostapd_hw_mode mode;
struct hostapd_hw_modes *hwmode;
- u8 chan;
+ u8 chan, op_class;
+ bool is_6ghz, supported = false;
+ is_6ghz = is_6ghz_freq(cand);
cand = wpa_s->p2p_group_common_freqs[i];
mode = ieee80211_freq_to_chan(cand, &chan);
hwmode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes,
- mode, is_6ghz_freq(cand));
+ mode, is_6ghz);
if (!wpas_same_band(wpa_s->current_ssid->frequency,
cand) ||
- !hwmode ||
- (wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW40MINUS) != ALLOWED &&
- wpas_p2p_verify_channel(wpa_s, hwmode, chan,
- BW40PLUS) != ALLOWED))
+ !hwmode)
continue;
+ if (is_6ghz &&
+ wpas_p2p_verify_channel(wpa_s, hwmode, 132, chan,
+ BW40) == ALLOWED)
+ supported = true;
+
+ if (!is_6ghz &&
+ ieee80211_freq_to_channel_ext(
+ cand, -1, CHANWIDTH_USE_HT, &op_class,
+ &chan) != NUM_HOSTAPD_MODES &&
+ wpas_p2p_verify_channel(
+ wpa_s, hwmode, op_class, chan,
+ BW40MINUS) == ALLOWED)
+ supported = true;
+
+ if (!supported && !is_6ghz &&
+ ieee80211_freq_to_channel_ext(
+ cand, 1, CHANWIDTH_USE_HT, &op_class,
+ &chan) != NUM_HOSTAPD_MODES &&
+ wpas_p2p_verify_channel(
+ wpa_s, hwmode, op_class, chan,
+ BW40PLUS) == ALLOWED)
+ supported = true;
+
+ if (!supported)
+ continue;
+
if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) {
params->freq = cand;
wpa_printf(MSG_DEBUG,