3 * Copyright(c) 2015 Intel Deutschland GmbH
5 * Intel Linux Wireless <ilw@linux.intel.com>
6 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
8 * This software may be distributed under the terms of the BSD license.
9 * See README for more details.
12 #include "utils/includes.h"
14 #include "utils/common.h"
15 #include "common/ieee802_11_common.h"
16 #include "wpa_supplicant_i.h"
19 static enum chan_allowed
allow_channel(struct hostapd_hw_modes
*mode
, u8 chan
,
24 for (i
= 0; i
< mode
->num_channels
; i
++) {
25 if (mode
->channels
[i
].chan
== chan
)
29 if (i
== mode
->num_channels
||
30 (mode
->channels
[i
].flag
& HOSTAPD_CHAN_DISABLED
))
34 *flags
= mode
->channels
[i
].flag
;
36 if (mode
->channels
[i
].flag
& HOSTAPD_CHAN_NO_IR
)
43 static int get_center_80mhz(struct hostapd_hw_modes
*mode
, u8 channel
)
45 u8 center_channels
[] = { 42, 58, 106, 122, 138, 155 };
48 if (mode
->mode
!= HOSTAPD_MODE_IEEE80211A
)
51 for (i
= 0; i
< ARRAY_SIZE(center_channels
); i
++) {
53 * In 80 MHz, the bandwidth "spans" 12 channels (e.g., 36-48),
54 * so the center channel is 6 channels away from the start/end.
56 if (channel
>= center_channels
[i
] - 6 &&
57 channel
<= center_channels
[i
] + 6)
58 return center_channels
[i
];
65 static enum chan_allowed
verify_80mhz(struct hostapd_hw_modes
*mode
, u8 channel
)
69 unsigned int no_ir
= 0;
71 center_chan
= get_center_80mhz(mode
, channel
);
75 /* check all the channels are available */
76 for (i
= 0; i
< 4; i
++) {
78 u8 adj_chan
= center_chan
- 6 + i
* 4;
80 if (allow_channel(mode
, adj_chan
, &flags
) == NOT_ALLOWED
)
83 if ((i
== 0 && !(flags
& HOSTAPD_CHAN_VHT_10_70
)) ||
84 (i
== 1 && !(flags
& HOSTAPD_CHAN_VHT_30_50
)) ||
85 (i
== 2 && !(flags
& HOSTAPD_CHAN_VHT_50_30
)) ||
86 (i
== 3 && !(flags
& HOSTAPD_CHAN_VHT_70_10
)))
89 if (flags
& HOSTAPD_CHAN_NO_IR
)
100 static int get_center_160mhz(struct hostapd_hw_modes
*mode
, u8 channel
)
102 u8 center_channels
[] = { 50, 114 };
105 if (mode
->mode
!= HOSTAPD_MODE_IEEE80211A
)
108 for (i
= 0; i
< ARRAY_SIZE(center_channels
); i
++) {
110 * In 160 MHz, the bandwidth "spans" 28 channels (e.g., 36-64),
111 * so the center channel is 14 channels away from the start/end.
113 if (channel
>= center_channels
[i
] - 14 &&
114 channel
<= center_channels
[i
] + 14)
115 return center_channels
[i
];
122 static enum chan_allowed
verify_160mhz(struct hostapd_hw_modes
*mode
,
127 unsigned int no_ir
= 0;
129 center_chan
= get_center_160mhz(mode
, channel
);
133 /* Check all the channels are available */
134 for (i
= 0; i
< 8; i
++) {
136 u8 adj_chan
= center_chan
- 14 + i
* 4;
138 if (allow_channel(mode
, adj_chan
, &flags
) == NOT_ALLOWED
)
141 if ((i
== 0 && !(flags
& HOSTAPD_CHAN_VHT_10_150
)) ||
142 (i
== 1 && !(flags
& HOSTAPD_CHAN_VHT_30_130
)) ||
143 (i
== 2 && !(flags
& HOSTAPD_CHAN_VHT_50_110
)) ||
144 (i
== 3 && !(flags
& HOSTAPD_CHAN_VHT_70_90
)) ||
145 (i
== 4 && !(flags
& HOSTAPD_CHAN_VHT_90_70
)) ||
146 (i
== 5 && !(flags
& HOSTAPD_CHAN_VHT_110_50
)) ||
147 (i
== 6 && !(flags
& HOSTAPD_CHAN_VHT_130_30
)) ||
148 (i
== 7 && !(flags
& HOSTAPD_CHAN_VHT_150_10
)))
151 if (flags
& HOSTAPD_CHAN_NO_IR
)
162 enum chan_allowed
verify_channel(struct hostapd_hw_modes
*mode
, u8 channel
,
165 unsigned int flag
= 0;
166 enum chan_allowed res
, res2
;
168 res2
= res
= allow_channel(mode
, channel
, &flag
);
169 if (bw
== BW40MINUS
) {
170 if (!(flag
& HOSTAPD_CHAN_HT40MINUS
))
172 res2
= allow_channel(mode
, channel
- 4, NULL
);
173 } else if (bw
== BW40PLUS
) {
174 if (!(flag
& HOSTAPD_CHAN_HT40PLUS
))
176 res2
= allow_channel(mode
, channel
+ 4, NULL
);
177 } else if (bw
== BW80
) {
179 * channel is a center channel and as such, not necessarily a
180 * valid 20 MHz channels. Override earlier allow_channel()
181 * result and use only the 80 MHz specific version.
183 res2
= res
= verify_80mhz(mode
, channel
);
184 } else if (bw
== BW160
) {
186 * channel is a center channel and as such, not necessarily a
187 * valid 20 MHz channels. Override earlier allow_channel()
188 * result and use only the 160 MHz specific version.
190 res2
= res
= verify_160mhz(mode
, channel
);
191 } else if (bw
== BW80P80
) {
193 * channel is a center channel and as such, not necessarily a
194 * valid 20 MHz channels. Override earlier allow_channel()
195 * result and use only the 80 MHz specific version.
197 res2
= res
= verify_80mhz(mode
, channel
);
200 if (res
== NOT_ALLOWED
|| res2
== NOT_ALLOWED
)
203 if (res
== NO_IR
|| res2
== NO_IR
)
210 static int wpas_op_class_supported(struct wpa_supplicant
*wpa_s
,
211 struct wpa_ssid
*ssid
,
212 const struct oper_class_map
*op_class
)
216 struct hostapd_hw_modes
*mode
;
222 mode
= get_mode(wpa_s
->hw
.modes
, wpa_s
->hw
.num_modes
, op_class
->mode
);
226 /* If we are configured to disable certain things, take that into
228 if (ssid
->freq_list
&& ssid
->freq_list
[0]) {
230 int f
= ssid
->freq_list
[z
];
233 break; /* end of list */
234 if (f
> 4000 && f
< 6000)
236 else if (f
> 2400 && f
< 2500)
240 /* No frequencies specified, can use anything hardware supports.
245 if (op_class
->op_class
>= 115 && op_class
->op_class
<= 130 && !freq5
)
247 if (op_class
->op_class
>= 81 && op_class
->op_class
<= 84 && !freq2
)
250 #ifdef CONFIG_HT_OVERRIDES
251 if (ssid
->disable_ht
) {
252 switch (op_class
->op_class
) {
268 /* Disable >= 40 MHz channels if HT is disabled */
272 #endif /* CONFIG_HT_OVERRIDES */
274 #ifdef CONFIG_VHT_OVERRIDES
275 if (ssid
->disable_vht
) {
276 if (op_class
->op_class
>= 128 && op_class
->op_class
<= 130) {
277 /* Disable >= 80 MHz channels if VHT is disabled */
281 #endif /* CONFIG_VHT_OVERRIDES */
283 if (op_class
->op_class
== 128) {
284 u8 channels
[] = { 42, 58, 106, 122, 138, 155 };
286 for (i
= 0; i
< ARRAY_SIZE(channels
); i
++) {
287 if (verify_channel(mode
, channels
[i
], op_class
->bw
) !=
295 if (op_class
->op_class
== 129) {
296 /* Check if either 160 MHz channels is allowed */
297 return verify_channel(mode
, 50, op_class
->bw
) != NOT_ALLOWED
||
298 verify_channel(mode
, 114, op_class
->bw
) != NOT_ALLOWED
;
301 if (op_class
->op_class
== 130) {
302 /* Need at least two non-contiguous 80 MHz segments */
305 if (verify_channel(mode
, 42, op_class
->bw
) != NOT_ALLOWED
||
306 verify_channel(mode
, 58, op_class
->bw
) != NOT_ALLOWED
)
308 if (verify_channel(mode
, 106, op_class
->bw
) != NOT_ALLOWED
||
309 verify_channel(mode
, 122, op_class
->bw
) != NOT_ALLOWED
||
310 verify_channel(mode
, 138, op_class
->bw
) != NOT_ALLOWED
)
312 if (verify_channel(mode
, 106, op_class
->bw
) != NOT_ALLOWED
&&
313 verify_channel(mode
, 138, op_class
->bw
) != NOT_ALLOWED
)
315 if (verify_channel(mode
, 155, op_class
->bw
) != NOT_ALLOWED
)
325 for (chan
= op_class
->min_chan
; chan
<= op_class
->max_chan
;
326 chan
+= op_class
->inc
) {
327 if (verify_channel(mode
, chan
, op_class
->bw
) != NOT_ALLOWED
) {
337 size_t wpas_supp_op_class_ie(struct wpa_supplicant
*wpa_s
,
338 struct wpa_ssid
*ssid
,
339 int freq
, u8
*pos
, size_t len
)
342 u8 op
, current
, chan
;
347 * Assume 20 MHz channel for now.
348 * TODO: Use the secondary channel and VHT channel width that will be
349 * used after association.
351 if (ieee80211_freq_to_channel_ext(freq
, 0, CHANWIDTH_USE_HT
,
352 ¤t
, &chan
) == NUM_HOSTAPD_MODES
)
356 * Need 3 bytes for EID, length, and current operating class, plus
357 * 1 byte for every other supported operating class.
359 buf
= wpabuf_alloc(global_op_class_size
+ 3);
363 wpabuf_put_u8(buf
, WLAN_EID_SUPPORTED_OPERATING_CLASSES
);
364 /* Will set the length later, putting a placeholder */
365 ie_len
= wpabuf_put(buf
, 1);
366 wpabuf_put_u8(buf
, current
);
368 for (op
= 0; global_op_class
[op
].op_class
; op
++) {
369 if (wpas_op_class_supported(wpa_s
, ssid
, &global_op_class
[op
]))
370 wpabuf_put_u8(buf
, global_op_class
[op
].op_class
);
373 *ie_len
= wpabuf_len(buf
) - 2;
374 if (*ie_len
< 2 || wpabuf_len(buf
) > len
) {
375 wpa_printf(MSG_ERROR
,
376 "Failed to add supported operating classes IE");
379 os_memcpy(pos
, wpabuf_head(buf
), wpabuf_len(buf
));
380 res
= wpabuf_len(buf
);
381 wpa_hexdump_buf(MSG_DEBUG
,
382 "Added supported operating classes IE", buf
);