2 * hostapd / Hardware feature query and different modes
3 * Copyright 2002-2003, Instant802 Networks, Inc.
4 * Copyright 2005-2006, Devicescape Software, Inc.
5 * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
11 #include "utils/includes.h"
13 #include "utils/common.h"
14 #include "utils/eloop.h"
15 #include "common/ieee802_11_defs.h"
16 #include "common/ieee802_11_common.h"
17 #include "common/wpa_ctrl.h"
18 #include "common/hw_features_common.h"
20 #include "ap_config.h"
21 #include "ap_drv_ops.h"
23 #include "ieee802_11.h"
25 #include "hw_features.h"
28 void hostapd_free_hw_features(struct hostapd_hw_modes
*hw_features
,
29 size_t num_hw_features
)
33 if (hw_features
== NULL
)
36 for (i
= 0; i
< num_hw_features
; i
++) {
37 os_free(hw_features
[i
].channels
);
38 os_free(hw_features
[i
].rates
);
45 #ifndef CONFIG_NO_STDOUT_DEBUG
46 static char * dfs_info(struct hostapd_channel_data
*chan
)
48 static char info
[256];
51 switch (chan
->flag
& HOSTAPD_CHAN_DFS_MASK
) {
52 case HOSTAPD_CHAN_DFS_UNKNOWN
:
55 case HOSTAPD_CHAN_DFS_USABLE
:
58 case HOSTAPD_CHAN_DFS_UNAVAILABLE
:
59 state
= "unavailable";
61 case HOSTAPD_CHAN_DFS_AVAILABLE
:
67 os_snprintf(info
, sizeof(info
), " (DFS state = %s)", state
);
68 info
[sizeof(info
) - 1] = '\0';
72 #endif /* CONFIG_NO_STDOUT_DEBUG */
75 int hostapd_get_hw_features(struct hostapd_iface
*iface
)
77 struct hostapd_data
*hapd
= iface
->bss
[0];
80 struct hostapd_hw_modes
*modes
;
83 if (hostapd_drv_none(hapd
))
85 modes
= hostapd_get_hw_feature_data(hapd
, &num_modes
, &flags
,
88 hostapd_logger(hapd
, NULL
, HOSTAPD_MODULE_IEEE80211
,
90 "Fetching hardware channel/rate support not "
95 iface
->hw_flags
= flags
;
96 iface
->dfs_domain
= dfs_domain
;
98 hostapd_free_hw_features(iface
->hw_features
, iface
->num_hw_features
);
99 iface
->hw_features
= modes
;
100 iface
->num_hw_features
= num_modes
;
102 for (i
= 0; i
< num_modes
; i
++) {
103 struct hostapd_hw_modes
*feature
= &modes
[i
];
104 int dfs_enabled
= hapd
->iconf
->ieee80211h
&&
105 (iface
->drv_flags
& WPA_DRIVER_FLAGS_RADAR
);
107 /* set flag for channels we can use in current regulatory
109 for (j
= 0; j
< feature
->num_channels
; j
++) {
113 * Disable all channels that are marked not to allow
114 * to initiate radiation (a.k.a. passive scan and no
116 * Use radar channels only if the driver supports DFS.
118 if ((feature
->channels
[j
].flag
&
119 HOSTAPD_CHAN_RADAR
) && dfs_enabled
) {
121 } else if (((feature
->channels
[j
].flag
&
122 HOSTAPD_CHAN_RADAR
) &&
124 WPA_DRIVER_FLAGS_DFS_OFFLOAD
)) ||
125 (feature
->channels
[j
].flag
&
126 HOSTAPD_CHAN_NO_IR
)) {
127 feature
->channels
[j
].flag
|=
128 HOSTAPD_CHAN_DISABLED
;
131 if (feature
->channels
[j
].flag
& HOSTAPD_CHAN_DISABLED
)
134 wpa_printf(MSG_MSGDUMP
, "Allowed channel: mode=%d "
135 "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
137 feature
->channels
[j
].chan
,
138 feature
->channels
[j
].freq
,
139 feature
->channels
[j
].max_tx_power
,
140 dfs
? dfs_info(&feature
->channels
[j
]) : "");
148 int hostapd_prepare_rates(struct hostapd_iface
*iface
,
149 struct hostapd_hw_modes
*mode
)
151 int i
, num_basic_rates
= 0;
152 int basic_rates_a
[] = { 60, 120, 240, -1 };
153 int basic_rates_b
[] = { 10, 20, -1 };
154 int basic_rates_g
[] = { 10, 20, 55, 110, -1 };
157 if (iface
->conf
->basic_rates
)
158 basic_rates
= iface
->conf
->basic_rates
;
159 else switch (mode
->mode
) {
160 case HOSTAPD_MODE_IEEE80211A
:
161 basic_rates
= basic_rates_a
;
163 case HOSTAPD_MODE_IEEE80211B
:
164 basic_rates
= basic_rates_b
;
166 case HOSTAPD_MODE_IEEE80211G
:
167 basic_rates
= basic_rates_g
;
169 case HOSTAPD_MODE_IEEE80211AD
:
170 return 0; /* No basic rates for 11ad */
176 while (basic_rates
[i
] >= 0)
179 i
++; /* -1 termination */
180 os_free(iface
->basic_rates
);
181 iface
->basic_rates
= os_malloc(i
* sizeof(int));
182 if (iface
->basic_rates
)
183 os_memcpy(iface
->basic_rates
, basic_rates
, i
* sizeof(int));
185 os_free(iface
->current_rates
);
186 iface
->num_rates
= 0;
188 iface
->current_rates
=
189 os_calloc(mode
->num_rates
, sizeof(struct hostapd_rate_data
));
190 if (!iface
->current_rates
) {
191 wpa_printf(MSG_ERROR
, "Failed to allocate memory for rate "
196 for (i
= 0; i
< mode
->num_rates
; i
++) {
197 struct hostapd_rate_data
*rate
;
199 if (iface
->conf
->supported_rates
&&
200 !hostapd_rate_found(iface
->conf
->supported_rates
,
204 rate
= &iface
->current_rates
[iface
->num_rates
];
205 rate
->rate
= mode
->rates
[i
];
206 if (hostapd_rate_found(basic_rates
, rate
->rate
)) {
207 rate
->flags
|= HOSTAPD_RATE_BASIC
;
210 wpa_printf(MSG_DEBUG
, "RATE[%d] rate=%d flags=0x%x",
211 iface
->num_rates
, rate
->rate
, rate
->flags
);
215 if ((iface
->num_rates
== 0 || num_basic_rates
== 0) &&
216 (!iface
->conf
->ieee80211n
|| !iface
->conf
->require_ht
)) {
217 wpa_printf(MSG_ERROR
, "No rates remaining in supported/basic "
218 "rate sets (%d,%d).",
219 iface
->num_rates
, num_basic_rates
);
227 #ifdef CONFIG_IEEE80211N
228 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface
*iface
)
230 int pri_chan
, sec_chan
;
232 pri_chan
= iface
->conf
->channel
;
233 sec_chan
= pri_chan
+ iface
->conf
->secondary_channel
* 4;
235 return allowed_ht40_channel_pair(iface
->current_mode
, pri_chan
,
240 static void ieee80211n_switch_pri_sec(struct hostapd_iface
*iface
)
242 if (iface
->conf
->secondary_channel
> 0) {
243 iface
->conf
->channel
+= 4;
244 iface
->conf
->secondary_channel
= -1;
246 iface
->conf
->channel
-= 4;
247 iface
->conf
->secondary_channel
= 1;
252 static int ieee80211n_check_40mhz_5g(struct hostapd_iface
*iface
,
253 struct wpa_scan_results
*scan_res
)
255 int pri_chan
, sec_chan
;
258 pri_chan
= iface
->conf
->channel
;
259 sec_chan
= pri_chan
+ iface
->conf
->secondary_channel
* 4;
261 res
= check_40mhz_5g(iface
->current_mode
, scan_res
, pri_chan
, sec_chan
);
264 if (iface
->conf
->no_pri_sec_switch
) {
265 wpa_printf(MSG_DEBUG
,
266 "Cannot switch PRI/SEC channels due to local constraint");
268 ieee80211n_switch_pri_sec(iface
);
276 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface
*iface
,
277 struct wpa_scan_results
*scan_res
)
279 int pri_chan
, sec_chan
;
281 pri_chan
= iface
->conf
->channel
;
282 sec_chan
= pri_chan
+ iface
->conf
->secondary_channel
* 4;
284 return check_40mhz_2g4(iface
->current_mode
, scan_res
, pri_chan
,
289 static void ieee80211n_check_scan(struct hostapd_iface
*iface
)
291 struct wpa_scan_results
*scan_res
;
295 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
296 * allowed per IEEE Std 802.11-2012, 10.15.3.2 */
298 iface
->scan_cb
= NULL
;
300 scan_res
= hostapd_driver_get_scan_results(iface
->bss
[0]);
301 if (scan_res
== NULL
) {
302 hostapd_setup_interface_complete(iface
, 1);
306 if (iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211A
)
307 oper40
= ieee80211n_check_40mhz_5g(iface
, scan_res
);
309 oper40
= ieee80211n_check_40mhz_2g4(iface
, scan_res
);
310 wpa_scan_results_free(scan_res
);
312 iface
->secondary_ch
= iface
->conf
->secondary_channel
;
314 wpa_printf(MSG_INFO
, "20/40 MHz operation not permitted on "
315 "channel pri=%d sec=%d based on overlapping BSSes",
316 iface
->conf
->channel
,
317 iface
->conf
->channel
+
318 iface
->conf
->secondary_channel
* 4);
319 iface
->conf
->secondary_channel
= 0;
320 if (iface
->drv_flags
& WPA_DRIVER_FLAGS_HT_2040_COEX
) {
322 * TODO: Could consider scheduling another scan to check
323 * if channel width can be changed if no coex reports
324 * are received from associating stations.
329 res
= ieee80211n_allowed_ht40_channel_pair(iface
);
331 iface
->conf
->secondary_channel
= 0;
332 hostapd_set_oper_centr_freq_seg0_idx(iface
->conf
, 0);
333 hostapd_set_oper_centr_freq_seg1_idx(iface
->conf
, 0);
334 hostapd_set_oper_chwidth(iface
->conf
, CHANWIDTH_USE_HT
);
336 wpa_printf(MSG_INFO
, "Fallback to 20 MHz");
339 hostapd_setup_interface_complete(iface
, !res
);
343 static void ieee80211n_scan_channels_2g4(struct hostapd_iface
*iface
,
344 struct wpa_driver_scan_params
*params
)
346 /* Scan only the affected frequency range */
347 int pri_freq
, sec_freq
;
348 int affected_start
, affected_end
;
350 struct hostapd_hw_modes
*mode
;
352 if (iface
->current_mode
== NULL
)
355 pri_freq
= hostapd_hw_get_freq(iface
->bss
[0], iface
->conf
->channel
);
356 if (iface
->conf
->secondary_channel
> 0)
357 sec_freq
= pri_freq
+ 20;
359 sec_freq
= pri_freq
- 20;
361 * Note: Need to find the PRI channel also in cases where the affected
362 * channel is the SEC channel of a 40 MHz BSS, so need to include the
363 * scanning coverage here to be 40 MHz from the center frequency.
365 affected_start
= (pri_freq
+ sec_freq
) / 2 - 40;
366 affected_end
= (pri_freq
+ sec_freq
) / 2 + 40;
367 wpa_printf(MSG_DEBUG
, "40 MHz affected channel range: [%d,%d] MHz",
368 affected_start
, affected_end
);
370 mode
= iface
->current_mode
;
371 params
->freqs
= os_calloc(mode
->num_channels
+ 1, sizeof(int));
372 if (params
->freqs
== NULL
)
376 for (i
= 0; i
< mode
->num_channels
; i
++) {
377 struct hostapd_channel_data
*chan
= &mode
->channels
[i
];
378 if (chan
->flag
& HOSTAPD_CHAN_DISABLED
)
380 if (chan
->freq
< affected_start
||
381 chan
->freq
> affected_end
)
383 params
->freqs
[pos
++] = chan
->freq
;
388 static void ieee80211n_scan_channels_5g(struct hostapd_iface
*iface
,
389 struct wpa_driver_scan_params
*params
)
391 /* Scan only the affected frequency range */
393 int affected_start
, affected_end
;
395 struct hostapd_hw_modes
*mode
;
397 if (iface
->current_mode
== NULL
)
400 pri_freq
= hostapd_hw_get_freq(iface
->bss
[0], iface
->conf
->channel
);
401 if (iface
->conf
->secondary_channel
> 0) {
402 affected_start
= pri_freq
- 10;
403 affected_end
= pri_freq
+ 30;
405 affected_start
= pri_freq
- 30;
406 affected_end
= pri_freq
+ 10;
408 wpa_printf(MSG_DEBUG
, "40 MHz affected channel range: [%d,%d] MHz",
409 affected_start
, affected_end
);
411 mode
= iface
->current_mode
;
412 params
->freqs
= os_calloc(mode
->num_channels
+ 1, sizeof(int));
413 if (params
->freqs
== NULL
)
417 for (i
= 0; i
< mode
->num_channels
; i
++) {
418 struct hostapd_channel_data
*chan
= &mode
->channels
[i
];
419 if (chan
->flag
& HOSTAPD_CHAN_DISABLED
)
421 if (chan
->freq
< affected_start
||
422 chan
->freq
> affected_end
)
424 params
->freqs
[pos
++] = chan
->freq
;
429 static void ap_ht40_scan_retry(void *eloop_data
, void *user_data
)
431 #define HT2040_COEX_SCAN_RETRY 15
432 struct hostapd_iface
*iface
= eloop_data
;
433 struct wpa_driver_scan_params params
;
436 os_memset(¶ms
, 0, sizeof(params
));
437 if (iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211G
)
438 ieee80211n_scan_channels_2g4(iface
, ¶ms
);
440 ieee80211n_scan_channels_5g(iface
, ¶ms
);
442 ret
= hostapd_driver_scan(iface
->bss
[0], ¶ms
);
443 iface
->num_ht40_scan_tries
++;
444 os_free(params
.freqs
);
447 iface
->num_ht40_scan_tries
< HT2040_COEX_SCAN_RETRY
) {
448 wpa_printf(MSG_ERROR
,
449 "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)",
450 ret
, strerror(-ret
), iface
->num_ht40_scan_tries
);
451 eloop_register_timeout(1, 0, ap_ht40_scan_retry
, iface
, NULL
);
456 iface
->scan_cb
= ieee80211n_check_scan
;
460 wpa_printf(MSG_DEBUG
,
461 "Failed to request a scan in device, bringing up in HT20 mode");
462 iface
->conf
->secondary_channel
= 0;
463 iface
->conf
->ht_capab
&= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
;
464 hostapd_setup_interface_complete(iface
, 0);
468 void hostapd_stop_setup_timers(struct hostapd_iface
*iface
)
470 eloop_cancel_timeout(ap_ht40_scan_retry
, iface
, NULL
);
474 static int ieee80211n_check_40mhz(struct hostapd_iface
*iface
)
476 struct wpa_driver_scan_params params
;
479 /* Check that HT40 is used and PRI / SEC switch is allowed */
480 if (!iface
->conf
->secondary_channel
|| iface
->conf
->no_pri_sec_switch
)
483 hostapd_set_state(iface
, HAPD_IFACE_HT_SCAN
);
484 wpa_printf(MSG_DEBUG
, "Scan for neighboring BSSes prior to enabling "
486 os_memset(¶ms
, 0, sizeof(params
));
487 if (iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211G
)
488 ieee80211n_scan_channels_2g4(iface
, ¶ms
);
490 ieee80211n_scan_channels_5g(iface
, ¶ms
);
492 ret
= hostapd_driver_scan(iface
->bss
[0], ¶ms
);
493 os_free(params
.freqs
);
496 wpa_printf(MSG_ERROR
,
497 "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again",
498 ret
, strerror(-ret
));
499 iface
->num_ht40_scan_tries
= 1;
500 eloop_cancel_timeout(ap_ht40_scan_retry
, iface
, NULL
);
501 eloop_register_timeout(1, 0, ap_ht40_scan_retry
, iface
, NULL
);
506 wpa_printf(MSG_ERROR
,
507 "Failed to request a scan of neighboring BSSes ret=%d (%s)",
508 ret
, strerror(-ret
));
512 iface
->scan_cb
= ieee80211n_check_scan
;
517 static int ieee80211n_supported_ht_capab(struct hostapd_iface
*iface
)
519 u16 hw
= iface
->current_mode
->ht_capab
;
520 u16 conf
= iface
->conf
->ht_capab
;
522 if ((conf
& HT_CAP_INFO_LDPC_CODING_CAP
) &&
523 !(hw
& HT_CAP_INFO_LDPC_CODING_CAP
)) {
524 wpa_printf(MSG_ERROR
, "Driver does not support configured "
525 "HT capability [LDPC]");
530 * Driver ACS chosen channel may not be HT40 due to internal driver
533 if (!iface
->conf
->acs
&& (conf
& HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
) &&
534 !(hw
& HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
)) {
535 wpa_printf(MSG_ERROR
, "Driver does not support configured "
536 "HT capability [HT40*]");
540 switch (conf
& HT_CAP_INFO_SMPS_MASK
) {
541 case HT_CAP_INFO_SMPS_STATIC
:
542 if (!(iface
->smps_modes
& WPA_DRIVER_SMPS_MODE_STATIC
)) {
543 wpa_printf(MSG_ERROR
,
544 "Driver does not support configured HT capability [SMPS-STATIC]");
548 case HT_CAP_INFO_SMPS_DYNAMIC
:
549 if (!(iface
->smps_modes
& WPA_DRIVER_SMPS_MODE_DYNAMIC
)) {
550 wpa_printf(MSG_ERROR
,
551 "Driver does not support configured HT capability [SMPS-DYNAMIC]");
555 case HT_CAP_INFO_SMPS_DISABLED
:
560 if ((conf
& HT_CAP_INFO_GREEN_FIELD
) &&
561 !(hw
& HT_CAP_INFO_GREEN_FIELD
)) {
562 wpa_printf(MSG_ERROR
, "Driver does not support configured "
563 "HT capability [GF]");
567 if ((conf
& HT_CAP_INFO_SHORT_GI20MHZ
) &&
568 !(hw
& HT_CAP_INFO_SHORT_GI20MHZ
)) {
569 wpa_printf(MSG_ERROR
, "Driver does not support configured "
570 "HT capability [SHORT-GI-20]");
574 if ((conf
& HT_CAP_INFO_SHORT_GI40MHZ
) &&
575 !(hw
& HT_CAP_INFO_SHORT_GI40MHZ
)) {
576 wpa_printf(MSG_ERROR
, "Driver does not support configured "
577 "HT capability [SHORT-GI-40]");
581 if ((conf
& HT_CAP_INFO_TX_STBC
) && !(hw
& HT_CAP_INFO_TX_STBC
)) {
582 wpa_printf(MSG_ERROR
, "Driver does not support configured "
583 "HT capability [TX-STBC]");
587 if ((conf
& HT_CAP_INFO_RX_STBC_MASK
) >
588 (hw
& HT_CAP_INFO_RX_STBC_MASK
)) {
589 wpa_printf(MSG_ERROR
, "Driver does not support configured "
590 "HT capability [RX-STBC*]");
594 if ((conf
& HT_CAP_INFO_DELAYED_BA
) &&
595 !(hw
& HT_CAP_INFO_DELAYED_BA
)) {
596 wpa_printf(MSG_ERROR
, "Driver does not support configured "
597 "HT capability [DELAYED-BA]");
601 if ((conf
& HT_CAP_INFO_MAX_AMSDU_SIZE
) &&
602 !(hw
& HT_CAP_INFO_MAX_AMSDU_SIZE
)) {
603 wpa_printf(MSG_ERROR
, "Driver does not support configured "
604 "HT capability [MAX-AMSDU-7935]");
608 if ((conf
& HT_CAP_INFO_DSSS_CCK40MHZ
) &&
609 !(hw
& HT_CAP_INFO_DSSS_CCK40MHZ
)) {
610 wpa_printf(MSG_ERROR
, "Driver does not support configured "
611 "HT capability [DSSS_CCK-40]");
615 if ((conf
& HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT
) &&
616 !(hw
& HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT
)) {
617 wpa_printf(MSG_ERROR
, "Driver does not support configured "
618 "HT capability [LSIG-TXOP-PROT]");
626 #ifdef CONFIG_IEEE80211AC
627 static int ieee80211ac_supported_vht_capab(struct hostapd_iface
*iface
)
629 struct hostapd_hw_modes
*mode
= iface
->current_mode
;
630 u32 hw
= mode
->vht_capab
;
631 u32 conf
= iface
->conf
->vht_capab
;
633 wpa_printf(MSG_DEBUG
, "hw vht capab: 0x%x, conf vht capab: 0x%x",
636 if (mode
->mode
== HOSTAPD_MODE_IEEE80211G
&&
637 iface
->conf
->bss
[0]->vendor_vht
&&
638 mode
->vht_capab
== 0 && iface
->hw_features
) {
641 for (i
= 0; i
< iface
->num_hw_features
; i
++) {
642 if (iface
->hw_features
[i
].mode
==
643 HOSTAPD_MODE_IEEE80211A
) {
644 mode
= &iface
->hw_features
[i
];
645 hw
= mode
->vht_capab
;
646 wpa_printf(MSG_DEBUG
,
647 "update hw vht capab based on 5 GHz band: 0x%x",
654 return ieee80211ac_cap_check(hw
, conf
);
656 #endif /* CONFIG_IEEE80211AC */
658 #endif /* CONFIG_IEEE80211N */
661 int hostapd_check_ht_capab(struct hostapd_iface
*iface
)
663 #ifdef CONFIG_IEEE80211N
665 if (!iface
->conf
->ieee80211n
)
668 if (iface
->current_mode
->mode
!= HOSTAPD_MODE_IEEE80211B
&&
669 iface
->current_mode
->mode
!= HOSTAPD_MODE_IEEE80211G
&&
670 (iface
->conf
->ht_capab
& HT_CAP_INFO_DSSS_CCK40MHZ
)) {
671 wpa_printf(MSG_DEBUG
,
672 "Disable HT capability [DSSS_CCK-40] on 5 GHz band");
673 iface
->conf
->ht_capab
&= ~HT_CAP_INFO_DSSS_CCK40MHZ
;
676 if (!ieee80211n_supported_ht_capab(iface
))
678 #ifdef CONFIG_IEEE80211AC
679 if (iface
->conf
->ieee80211ac
&&
680 !ieee80211ac_supported_vht_capab(iface
))
682 #endif /* CONFIG_IEEE80211AC */
683 ret
= ieee80211n_check_40mhz(iface
);
686 if (!ieee80211n_allowed_ht40_channel_pair(iface
))
688 #endif /* CONFIG_IEEE80211N */
694 static int hostapd_is_usable_chan(struct hostapd_iface
*iface
,
695 int channel
, int primary
)
697 struct hostapd_channel_data
*chan
;
699 if (!iface
->current_mode
)
702 chan
= hw_get_channel_chan(iface
->current_mode
, channel
, NULL
);
706 if ((primary
&& chan_pri_allowed(chan
)) ||
707 (!primary
&& !(chan
->flag
& HOSTAPD_CHAN_DISABLED
)))
711 "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
712 channel
, primary
? "primary" : "secondary",
714 chan
->flag
& HOSTAPD_CHAN_NO_IR
? " NO-IR" : "",
715 chan
->flag
& HOSTAPD_CHAN_RADAR
? " RADAR" : "");
720 static int hostapd_is_usable_chans(struct hostapd_iface
*iface
)
723 struct hostapd_channel_data
*pri_chan
;
725 pri_chan
= hw_get_channel_chan(iface
->current_mode
,
726 iface
->conf
->channel
, NULL
);
730 if (!hostapd_is_usable_chan(iface
, iface
->conf
->channel
, 1))
733 if (!iface
->conf
->secondary_channel
)
736 if (!iface
->conf
->ht40_plus_minus_allowed
)
737 return hostapd_is_usable_chan(
738 iface
, iface
->conf
->channel
+
739 iface
->conf
->secondary_channel
* 4, 0);
741 /* Both HT40+ and HT40- are set, pick a valid secondary channel */
742 secondary_chan
= iface
->conf
->channel
+ 4;
743 if (hostapd_is_usable_chan(iface
, secondary_chan
, 0) &&
744 (pri_chan
->allowed_bw
& HOSTAPD_CHAN_WIDTH_40P
)) {
745 iface
->conf
->secondary_channel
= 1;
749 secondary_chan
= iface
->conf
->channel
- 4;
750 if (hostapd_is_usable_chan(iface
, secondary_chan
, 0) &&
751 (pri_chan
->allowed_bw
& HOSTAPD_CHAN_WIDTH_40M
)) {
752 iface
->conf
->secondary_channel
= -1;
760 static enum hostapd_chan_status
761 hostapd_check_chans(struct hostapd_iface
*iface
)
763 if (iface
->conf
->channel
) {
764 if (hostapd_is_usable_chans(iface
))
765 return HOSTAPD_CHAN_VALID
;
767 return HOSTAPD_CHAN_INVALID
;
771 * The user set channel=0 or channel=acs_survey
772 * which is used to trigger ACS.
775 switch (acs_init(iface
)) {
776 case HOSTAPD_CHAN_ACS
:
777 return HOSTAPD_CHAN_ACS
;
778 case HOSTAPD_CHAN_VALID
:
779 case HOSTAPD_CHAN_INVALID
:
781 return HOSTAPD_CHAN_INVALID
;
786 static void hostapd_notify_bad_chans(struct hostapd_iface
*iface
)
788 if (!iface
->current_mode
) {
789 hostapd_logger(iface
->bss
[0], NULL
, HOSTAPD_MODULE_IEEE80211
,
790 HOSTAPD_LEVEL_WARNING
,
791 "Hardware does not support configured mode");
794 hostapd_logger(iface
->bss
[0], NULL
,
795 HOSTAPD_MODULE_IEEE80211
,
796 HOSTAPD_LEVEL_WARNING
,
797 "Configured channel (%d) not found from the "
798 "channel list of current mode (%d) %s",
799 iface
->conf
->channel
,
800 iface
->current_mode
->mode
,
801 hostapd_hw_mode_txt(iface
->current_mode
->mode
));
802 hostapd_logger(iface
->bss
[0], NULL
, HOSTAPD_MODULE_IEEE80211
,
803 HOSTAPD_LEVEL_WARNING
,
804 "Hardware does not support configured channel");
808 int hostapd_acs_completed(struct hostapd_iface
*iface
, int err
)
815 switch (hostapd_check_chans(iface
)) {
816 case HOSTAPD_CHAN_VALID
:
817 wpa_msg(iface
->bss
[0]->msg_ctx
, MSG_INFO
,
818 ACS_EVENT_COMPLETED
"freq=%d channel=%d",
819 hostapd_hw_get_freq(iface
->bss
[0],
820 iface
->conf
->channel
),
821 iface
->conf
->channel
);
823 case HOSTAPD_CHAN_ACS
:
824 wpa_printf(MSG_ERROR
, "ACS error - reported complete, but no result available");
825 wpa_msg(iface
->bss
[0]->msg_ctx
, MSG_INFO
, ACS_EVENT_FAILED
);
826 hostapd_notify_bad_chans(iface
);
828 case HOSTAPD_CHAN_INVALID
:
830 wpa_printf(MSG_ERROR
, "ACS picked unusable channels");
831 wpa_msg(iface
->bss
[0]->msg_ctx
, MSG_INFO
, ACS_EVENT_FAILED
);
832 hostapd_notify_bad_chans(iface
);
836 ret
= hostapd_check_ht_capab(iface
);
840 wpa_printf(MSG_DEBUG
, "Interface initialization will be completed in a callback");
846 return hostapd_setup_interface_complete(iface
, ret
);
851 * hostapd_select_hw_mode - Select the hardware mode
852 * @iface: Pointer to interface data.
853 * Returns: 0 on success, < 0 on failure
855 * Sets up the hardware mode, channel, rates, and passive scanning
856 * based on the configuration.
858 int hostapd_select_hw_mode(struct hostapd_iface
*iface
)
862 if (iface
->num_hw_features
< 1)
865 if ((iface
->conf
->hw_mode
== HOSTAPD_MODE_IEEE80211G
||
866 iface
->conf
->ieee80211n
|| iface
->conf
->ieee80211ac
) &&
867 iface
->conf
->channel
== 14) {
868 wpa_printf(MSG_INFO
, "Disable OFDM/HT/VHT on channel 14");
869 iface
->conf
->hw_mode
= HOSTAPD_MODE_IEEE80211B
;
870 iface
->conf
->ieee80211n
= 0;
871 iface
->conf
->ieee80211ac
= 0;
874 iface
->current_mode
= NULL
;
875 for (i
= 0; i
< iface
->num_hw_features
; i
++) {
876 struct hostapd_hw_modes
*mode
= &iface
->hw_features
[i
];
877 if (mode
->mode
== iface
->conf
->hw_mode
) {
878 iface
->current_mode
= mode
;
883 if (iface
->current_mode
== NULL
) {
884 if (!(iface
->drv_flags
& WPA_DRIVER_FLAGS_ACS_OFFLOAD
) ||
885 !(iface
->drv_flags
& WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY
))
887 wpa_printf(MSG_ERROR
,
888 "Hardware does not support configured mode");
889 hostapd_logger(iface
->bss
[0], NULL
,
890 HOSTAPD_MODULE_IEEE80211
,
891 HOSTAPD_LEVEL_WARNING
,
892 "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)",
893 (int) iface
->conf
->hw_mode
);
898 switch (hostapd_check_chans(iface
)) {
899 case HOSTAPD_CHAN_VALID
:
901 case HOSTAPD_CHAN_ACS
: /* ACS will run and later complete */
903 case HOSTAPD_CHAN_INVALID
:
905 hostapd_notify_bad_chans(iface
);
911 const char * hostapd_hw_mode_txt(int mode
)
914 case HOSTAPD_MODE_IEEE80211A
:
915 return "IEEE 802.11a";
916 case HOSTAPD_MODE_IEEE80211B
:
917 return "IEEE 802.11b";
918 case HOSTAPD_MODE_IEEE80211G
:
919 return "IEEE 802.11g";
920 case HOSTAPD_MODE_IEEE80211AD
:
921 return "IEEE 802.11ad";
928 int hostapd_hw_get_freq(struct hostapd_data
*hapd
, int chan
)
930 return hw_get_freq(hapd
->iface
->current_mode
, chan
);
934 int hostapd_hw_get_channel(struct hostapd_data
*hapd
, int freq
)
937 struct hostapd_hw_modes
*mode
;
939 if (hapd
->iface
->current_mode
) {
940 channel
= hw_get_chan(hapd
->iface
->current_mode
, freq
);
945 /* Check other available modes since the channel list for the current
946 * mode did not include the specified frequency. */
947 if (!hapd
->iface
->hw_features
)
949 for (i
= 0; i
< hapd
->iface
->num_hw_features
; i
++) {
950 mode
= &hapd
->iface
->hw_features
[i
];
951 channel
= hw_get_chan(mode
, freq
);