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 const struct oper_class_map
*op_class
)
215 struct hostapd_hw_modes
*mode
;
218 mode
= get_mode(wpa_s
->hw
.modes
, wpa_s
->hw
.num_modes
, op_class
->mode
);
222 if (op_class
->op_class
== 128) {
223 u8 channels
[] = { 42, 58, 106, 122, 138, 155 };
225 for (i
= 0; i
< ARRAY_SIZE(channels
); i
++) {
226 if (verify_channel(mode
, channels
[i
], op_class
->bw
) !=
234 if (op_class
->op_class
== 129) {
235 /* Check if either 160 MHz channels is allowed */
236 return verify_channel(mode
, 50, op_class
->bw
) != NOT_ALLOWED
||
237 verify_channel(mode
, 114, op_class
->bw
) != NOT_ALLOWED
;
240 if (op_class
->op_class
== 130) {
241 /* Need at least two non-contiguous 80 MHz segments */
244 if (verify_channel(mode
, 42, op_class
->bw
) != NOT_ALLOWED
||
245 verify_channel(mode
, 58, op_class
->bw
) != NOT_ALLOWED
)
247 if (verify_channel(mode
, 106, op_class
->bw
) != NOT_ALLOWED
||
248 verify_channel(mode
, 122, op_class
->bw
) != NOT_ALLOWED
||
249 verify_channel(mode
, 138, op_class
->bw
) != NOT_ALLOWED
)
251 if (verify_channel(mode
, 106, op_class
->bw
) != NOT_ALLOWED
&&
252 verify_channel(mode
, 138, op_class
->bw
) != NOT_ALLOWED
)
254 if (verify_channel(mode
, 155, op_class
->bw
) != NOT_ALLOWED
)
264 for (chan
= op_class
->min_chan
; chan
<= op_class
->max_chan
;
265 chan
+= op_class
->inc
) {
266 if (verify_channel(mode
, chan
, op_class
->bw
) != NOT_ALLOWED
) {
276 size_t wpas_supp_op_class_ie(struct wpa_supplicant
*wpa_s
, int freq
, u8
*pos
,
280 u8 op
, current
, chan
;
285 * Assume 20 MHz channel for now.
286 * TODO: Use the secondary channel and VHT channel width that will be
287 * used after association.
289 if (ieee80211_freq_to_channel_ext(freq
, 0, VHT_CHANWIDTH_USE_HT
,
290 ¤t
, &chan
) == NUM_HOSTAPD_MODES
)
294 * Need 3 bytes for EID, length, and current operating class, plus
295 * 1 byte for every other supported operating class.
297 buf
= wpabuf_alloc(global_op_class_size
+ 3);
301 wpabuf_put_u8(buf
, WLAN_EID_SUPPORTED_OPERATING_CLASSES
);
302 /* Will set the length later, putting a placeholder */
303 ie_len
= wpabuf_put(buf
, 1);
304 wpabuf_put_u8(buf
, current
);
306 for (op
= 0; global_op_class
[op
].op_class
; op
++) {
307 if (wpas_op_class_supported(wpa_s
, &global_op_class
[op
]))
308 wpabuf_put_u8(buf
, global_op_class
[op
].op_class
);
311 *ie_len
= wpabuf_len(buf
) - 2;
312 if (*ie_len
< 2 || wpabuf_len(buf
) > len
) {
313 wpa_printf(MSG_ERROR
,
314 "Failed to add supported operating classes IE");
317 os_memcpy(pos
, wpabuf_head(buf
), wpabuf_len(buf
));
318 res
= wpabuf_len(buf
);
319 wpa_hexdump_buf(MSG_DEBUG
,
320 "Added supported operating classes IE", buf
);