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, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
14 * See README and COPYING for more details.
20 #include "common/ieee802_11_defs.h"
21 #include "common/ieee802_11_common.h"
23 #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 int hostapd_get_hw_features(struct hostapd_iface
*iface
)
47 struct hostapd_data
*hapd
= iface
->bss
[0];
50 struct hostapd_hw_modes
*modes
;
52 if (hostapd_drv_none(hapd
))
54 modes
= hostapd_get_hw_feature_data(hapd
, &num_modes
, &flags
);
56 hostapd_logger(hapd
, NULL
, HOSTAPD_MODULE_IEEE80211
,
58 "Fetching hardware channel/rate support not "
63 iface
->hw_flags
= flags
;
65 hostapd_free_hw_features(iface
->hw_features
, iface
->num_hw_features
);
66 iface
->hw_features
= modes
;
67 iface
->num_hw_features
= num_modes
;
69 for (i
= 0; i
< num_modes
; i
++) {
70 struct hostapd_hw_modes
*feature
= &modes
[i
];
71 /* set flag for channels we can use in current regulatory
73 for (j
= 0; j
< feature
->num_channels
; j
++) {
75 * Disable all channels that are marked not to allow
76 * IBSS operation or active scanning. In addition,
77 * disable all channels that require radar detection,
78 * since that (in addition to full DFS) is not yet
81 if (feature
->channels
[j
].flag
&
82 (HOSTAPD_CHAN_NO_IBSS
|
83 HOSTAPD_CHAN_PASSIVE_SCAN
|
85 feature
->channels
[j
].flag
|=
86 HOSTAPD_CHAN_DISABLED
;
87 if (feature
->channels
[j
].flag
& HOSTAPD_CHAN_DISABLED
)
89 wpa_printf(MSG_MSGDUMP
, "Allowed channel: mode=%d "
90 "chan=%d freq=%d MHz max_tx_power=%d dBm",
92 feature
->channels
[j
].chan
,
93 feature
->channels
[j
].freq
,
94 feature
->channels
[j
].max_tx_power
);
102 static int hostapd_prepare_rates(struct hostapd_data
*hapd
,
103 struct hostapd_hw_modes
*mode
)
105 int i
, num_basic_rates
= 0;
106 int basic_rates_a
[] = { 60, 120, 240, -1 };
107 int basic_rates_b
[] = { 10, 20, -1 };
108 int basic_rates_g
[] = { 10, 20, 55, 110, -1 };
111 if (hapd
->iconf
->basic_rates
)
112 basic_rates
= hapd
->iconf
->basic_rates
;
113 else switch (mode
->mode
) {
114 case HOSTAPD_MODE_IEEE80211A
:
115 basic_rates
= basic_rates_a
;
117 case HOSTAPD_MODE_IEEE80211B
:
118 basic_rates
= basic_rates_b
;
120 case HOSTAPD_MODE_IEEE80211G
:
121 basic_rates
= basic_rates_g
;
127 if (hostapd_set_rate_sets(hapd
, hapd
->iconf
->supported_rates
,
128 basic_rates
, mode
->mode
)) {
129 wpa_printf(MSG_ERROR
, "Failed to update rate sets in kernel "
133 os_free(hapd
->iface
->current_rates
);
134 hapd
->iface
->num_rates
= 0;
136 hapd
->iface
->current_rates
=
137 os_malloc(mode
->num_rates
* sizeof(struct hostapd_rate_data
));
138 if (!hapd
->iface
->current_rates
) {
139 wpa_printf(MSG_ERROR
, "Failed to allocate memory for rate "
144 for (i
= 0; i
< mode
->num_rates
; i
++) {
145 struct hostapd_rate_data
*rate
;
147 if (hapd
->iconf
->supported_rates
&&
148 !hostapd_rate_found(hapd
->iconf
->supported_rates
,
149 mode
->rates
[i
].rate
))
152 rate
= &hapd
->iface
->current_rates
[hapd
->iface
->num_rates
];
153 os_memcpy(rate
, &mode
->rates
[i
],
154 sizeof(struct hostapd_rate_data
));
155 if (hostapd_rate_found(basic_rates
, rate
->rate
)) {
156 rate
->flags
|= HOSTAPD_RATE_BASIC
;
159 rate
->flags
&= ~HOSTAPD_RATE_BASIC
;
160 wpa_printf(MSG_DEBUG
, "RATE[%d] rate=%d flags=0x%x",
161 hapd
->iface
->num_rates
, rate
->rate
, rate
->flags
);
162 hapd
->iface
->num_rates
++;
165 if (hapd
->iface
->num_rates
== 0 || num_basic_rates
== 0) {
166 wpa_printf(MSG_ERROR
, "No rates remaining in supported/basic "
167 "rate sets (%d,%d).",
168 hapd
->iface
->num_rates
, num_basic_rates
);
176 #ifdef CONFIG_IEEE80211N
177 static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface
*iface
)
179 int sec_chan
, ok
, j
, first
;
180 int allowed
[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157,
184 if (!iface
->conf
->secondary_channel
)
185 return 1; /* HT40 not used */
187 sec_chan
= iface
->conf
->channel
+ iface
->conf
->secondary_channel
* 4;
188 wpa_printf(MSG_DEBUG
, "HT40: control channel: %d "
189 "secondary channel: %d",
190 iface
->conf
->channel
, sec_chan
);
192 /* Verify that HT40 secondary channel is an allowed 20 MHz
195 for (j
= 0; j
< iface
->current_mode
->num_channels
; j
++) {
196 struct hostapd_channel_data
*chan
=
197 &iface
->current_mode
->channels
[j
];
198 if (!(chan
->flag
& HOSTAPD_CHAN_DISABLED
) &&
199 chan
->chan
== sec_chan
) {
205 wpa_printf(MSG_ERROR
, "HT40 secondary channel %d not allowed",
211 * Verify that HT40 primary,secondary channel pair is allowed per
212 * IEEE 802.11n Annex J. This is only needed for 5 GHz band since
213 * 2.4 GHz rules allow all cases where the secondary channel fits into
214 * the list of allowed channels (already checked above).
216 if (iface
->current_mode
->mode
!= HOSTAPD_MODE_IEEE80211A
)
219 if (iface
->conf
->secondary_channel
> 0)
220 first
= iface
->conf
->channel
;
225 for (k
= 0; k
< sizeof(allowed
) / sizeof(allowed
[0]); k
++) {
226 if (first
== allowed
[k
]) {
232 wpa_printf(MSG_ERROR
, "HT40 channel pair (%d, %d) not allowed",
233 iface
->conf
->channel
,
234 iface
->conf
->secondary_channel
);
242 static void ieee80211n_switch_pri_sec(struct hostapd_iface
*iface
)
244 if (iface
->conf
->secondary_channel
> 0) {
245 iface
->conf
->channel
+= 4;
246 iface
->conf
->secondary_channel
= -1;
248 iface
->conf
->channel
-= 4;
249 iface
->conf
->secondary_channel
= 1;
254 static void ieee80211n_get_pri_sec_chan(struct wpa_scan_res
*bss
,
255 int *pri_chan
, int *sec_chan
)
257 struct ieee80211_ht_operation
*oper
;
258 struct ieee802_11_elems elems
;
260 *pri_chan
= *sec_chan
= 0;
262 ieee802_11_parse_elems((u8
*) (bss
+ 1), bss
->ie_len
, &elems
, 0);
263 if (elems
.ht_operation
&&
264 elems
.ht_operation_len
>= sizeof(*oper
)) {
265 oper
= (struct ieee80211_ht_operation
*) elems
.ht_operation
;
266 *pri_chan
= oper
->control_chan
;
267 if (oper
->ht_param
& HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH
) {
269 HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE
)
270 *sec_chan
= *pri_chan
+ 4;
271 else if (oper
->ht_param
&
272 HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW
)
273 *sec_chan
= *pri_chan
- 4;
279 static int ieee80211n_check_40mhz_5g(struct hostapd_iface
*iface
,
280 struct wpa_scan_results
*scan_res
)
282 int pri_chan
, sec_chan
, pri_freq
, sec_freq
, pri_bss
, sec_bss
;
283 int bss_pri_chan
, bss_sec_chan
;
287 pri_chan
= iface
->conf
->channel
;
288 sec_chan
= iface
->conf
->secondary_channel
* 4;
289 pri_freq
= hostapd_hw_get_freq(iface
->bss
[0], pri_chan
);
290 if (iface
->conf
->secondary_channel
> 0)
291 sec_freq
= pri_freq
+ 20;
293 sec_freq
= pri_freq
- 20;
296 * Switch PRI/SEC channels if Beacons were detected on selected SEC
297 * channel, but not on selected PRI channel.
299 pri_bss
= sec_bss
= 0;
300 for (i
= 0; i
< scan_res
->num
; i
++) {
301 struct wpa_scan_res
*bss
= scan_res
->res
[i
];
302 if (bss
->freq
== pri_freq
)
304 else if (bss
->freq
== sec_freq
)
307 if (sec_bss
&& !pri_bss
) {
308 wpa_printf(MSG_INFO
, "Switch own primary and secondary "
309 "channel to get secondary channel with no Beacons "
311 ieee80211n_switch_pri_sec(iface
);
315 * Match PRI/SEC channel with any existing HT40 BSS on the same
316 * channels that we are about to use (if already mixed order in
317 * existing BSSes, use own preference).
320 for (i
= 0; i
< scan_res
->num
; i
++) {
321 struct wpa_scan_res
*bss
= scan_res
->res
[i
];
322 ieee80211n_get_pri_sec_chan(bss
, &bss_pri_chan
, &bss_sec_chan
);
323 if (pri_chan
== bss_pri_chan
&&
324 sec_chan
== bss_sec_chan
) {
330 for (i
= 0; i
< scan_res
->num
; i
++) {
331 struct wpa_scan_res
*bss
= scan_res
->res
[i
];
332 ieee80211n_get_pri_sec_chan(bss
, &bss_pri_chan
,
334 if (pri_chan
== bss_sec_chan
&&
335 sec_chan
== bss_pri_chan
) {
336 wpa_printf(MSG_INFO
, "Switch own primary and "
337 "secondary channel due to BSS "
338 "overlap with " MACSTR
,
339 MAC2STR(bss
->bssid
));
340 ieee80211n_switch_pri_sec(iface
);
350 static int ieee80211n_check_40mhz_2g4(struct hostapd_iface
*iface
,
351 struct wpa_scan_results
*scan_res
)
353 int pri_freq
, sec_freq
;
354 int affected_start
, affected_end
;
357 pri_freq
= hostapd_hw_get_freq(iface
->bss
[0], iface
->conf
->channel
);
358 if (iface
->conf
->secondary_channel
> 0)
359 sec_freq
= pri_freq
+ 20;
361 sec_freq
= pri_freq
- 20;
362 affected_start
= (pri_freq
+ sec_freq
) / 2 - 25;
363 affected_end
= (pri_freq
+ sec_freq
) / 2 + 25;
364 wpa_printf(MSG_DEBUG
, "40 MHz affected channel range: [%d,%d] MHz",
365 affected_start
, affected_end
);
366 for (i
= 0; i
< scan_res
->num
; i
++) {
367 struct wpa_scan_res
*bss
= scan_res
->res
[i
];
370 int sec_chan
, pri_chan
;
372 ieee80211n_get_pri_sec_chan(bss
, &pri_chan
, &sec_chan
);
375 if (sec_chan
< pri_chan
)
381 if ((pri
< affected_start
|| pri
> affected_end
) &&
382 (sec
< affected_start
|| sec
> affected_end
))
383 continue; /* not within affected channel range */
385 wpa_printf(MSG_DEBUG
, "Neighboring BSS: " MACSTR
386 " freq=%d pri=%d sec=%d",
387 MAC2STR(bss
->bssid
), bss
->freq
, pri_chan
, sec_chan
);
390 if (pri_freq
!= pri
|| sec_freq
!= sec
) {
391 wpa_printf(MSG_DEBUG
, "40 MHz pri/sec "
392 "mismatch with BSS " MACSTR
393 " <%d,%d> (chan=%d%c) vs. <%d,%d>",
396 sec
> pri
? '+' : '-',
402 /* TODO: 40 MHz intolerant */
409 static void ieee80211n_check_scan(struct hostapd_iface
*iface
)
411 struct wpa_scan_results
*scan_res
;
414 /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is
415 * allowed per IEEE 802.11n/D7.0, 11.14.3.2 */
417 iface
->scan_cb
= NULL
;
419 scan_res
= hostapd_driver_get_scan_results(iface
->bss
[0]);
420 if (scan_res
== NULL
) {
421 hostapd_setup_interface_complete(iface
, 1);
425 if (iface
->current_mode
->mode
== HOSTAPD_MODE_IEEE80211A
)
426 oper40
= ieee80211n_check_40mhz_5g(iface
, scan_res
);
428 oper40
= ieee80211n_check_40mhz_2g4(iface
, scan_res
);
429 wpa_scan_results_free(scan_res
);
432 wpa_printf(MSG_INFO
, "20/40 MHz operation not permitted on "
433 "channel pri=%d sec=%d based on overlapping BSSes",
434 iface
->conf
->channel
,
435 iface
->conf
->channel
+
436 iface
->conf
->secondary_channel
* 4);
437 iface
->conf
->secondary_channel
= 0;
438 iface
->conf
->ht_capab
&= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
;
441 hostapd_setup_interface_complete(iface
, 0);
445 static int ieee80211n_check_40mhz(struct hostapd_iface
*iface
)
447 struct wpa_driver_scan_params params
;
449 if (!iface
->conf
->secondary_channel
)
450 return 0; /* HT40 not used */
452 wpa_printf(MSG_DEBUG
, "Scan for neighboring BSSes prior to enabling "
454 os_memset(¶ms
, 0, sizeof(params
));
455 /* TODO: scan only the needed frequency */
456 if (hostapd_driver_scan(iface
->bss
[0], ¶ms
) < 0) {
457 wpa_printf(MSG_ERROR
, "Failed to request a scan of "
458 "neighboring BSSes");
462 iface
->scan_cb
= ieee80211n_check_scan
;
467 static int ieee80211n_supported_ht_capab(struct hostapd_iface
*iface
)
469 u16 hw
= iface
->current_mode
->ht_capab
;
470 u16 conf
= iface
->conf
->ht_capab
;
472 if (!iface
->conf
->ieee80211n
)
475 if ((conf
& HT_CAP_INFO_LDPC_CODING_CAP
) &&
476 !(hw
& HT_CAP_INFO_LDPC_CODING_CAP
)) {
477 wpa_printf(MSG_ERROR
, "Driver does not support configured "
478 "HT capability [LDPC]");
482 if ((conf
& HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
) &&
483 !(hw
& HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET
)) {
484 wpa_printf(MSG_ERROR
, "Driver does not support configured "
485 "HT capability [HT40*]");
489 if ((conf
& HT_CAP_INFO_SMPS_MASK
) != (hw
& HT_CAP_INFO_SMPS_MASK
) &&
490 (conf
& HT_CAP_INFO_SMPS_MASK
) != HT_CAP_INFO_SMPS_DISABLED
) {
491 wpa_printf(MSG_ERROR
, "Driver does not support configured "
492 "HT capability [SMPS-*]");
496 if ((conf
& HT_CAP_INFO_GREEN_FIELD
) &&
497 !(hw
& HT_CAP_INFO_GREEN_FIELD
)) {
498 wpa_printf(MSG_ERROR
, "Driver does not support configured "
499 "HT capability [GF]");
503 if ((conf
& HT_CAP_INFO_SHORT_GI20MHZ
) &&
504 !(hw
& HT_CAP_INFO_SHORT_GI20MHZ
)) {
505 wpa_printf(MSG_ERROR
, "Driver does not support configured "
506 "HT capability [SHORT-GI-20]");
510 if ((conf
& HT_CAP_INFO_SHORT_GI40MHZ
) &&
511 !(hw
& HT_CAP_INFO_SHORT_GI40MHZ
)) {
512 wpa_printf(MSG_ERROR
, "Driver does not support configured "
513 "HT capability [SHORT-GI-40]");
517 if ((conf
& HT_CAP_INFO_TX_STBC
) && !(hw
& HT_CAP_INFO_TX_STBC
)) {
518 wpa_printf(MSG_ERROR
, "Driver does not support configured "
519 "HT capability [TX-STBC]");
523 if ((conf
& HT_CAP_INFO_RX_STBC_MASK
) >
524 (hw
& HT_CAP_INFO_RX_STBC_MASK
)) {
525 wpa_printf(MSG_ERROR
, "Driver does not support configured "
526 "HT capability [RX-STBC*]");
530 if ((conf
& HT_CAP_INFO_DELAYED_BA
) &&
531 !(hw
& HT_CAP_INFO_DELAYED_BA
)) {
532 wpa_printf(MSG_ERROR
, "Driver does not support configured "
533 "HT capability [DELAYED-BA]");
537 if ((conf
& HT_CAP_INFO_MAX_AMSDU_SIZE
) &&
538 !(hw
& HT_CAP_INFO_MAX_AMSDU_SIZE
)) {
539 wpa_printf(MSG_ERROR
, "Driver does not support configured "
540 "HT capability [MAX-AMSDU-7935]");
544 if ((conf
& HT_CAP_INFO_DSSS_CCK40MHZ
) &&
545 !(hw
& HT_CAP_INFO_DSSS_CCK40MHZ
)) {
546 wpa_printf(MSG_ERROR
, "Driver does not support configured "
547 "HT capability [DSSS_CCK-40]");
551 if ((conf
& HT_CAP_INFO_PSMP_SUPP
) && !(hw
& HT_CAP_INFO_PSMP_SUPP
)) {
552 wpa_printf(MSG_ERROR
, "Driver does not support configured "
553 "HT capability [PSMP]");
557 if ((conf
& HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT
) &&
558 !(hw
& HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT
)) {
559 wpa_printf(MSG_ERROR
, "Driver does not support configured "
560 "HT capability [LSIG-TXOP-PROT]");
567 #endif /* CONFIG_IEEE80211N */
570 int hostapd_check_ht_capab(struct hostapd_iface
*iface
)
572 #ifdef CONFIG_IEEE80211N
574 ret
= ieee80211n_check_40mhz(iface
);
577 if (!ieee80211n_allowed_ht40_channel_pair(iface
))
579 if (!ieee80211n_supported_ht_capab(iface
))
581 #endif /* CONFIG_IEEE80211N */
588 * hostapd_select_hw_mode - Select the hardware mode
589 * @iface: Pointer to interface data.
590 * Returns: 0 on success, -1 on failure
592 * Sets up the hardware mode, channel, rates, and passive scanning
593 * based on the configuration.
595 int hostapd_select_hw_mode(struct hostapd_iface
*iface
)
599 if (iface
->num_hw_features
< 1)
602 iface
->current_mode
= NULL
;
603 for (i
= 0; i
< iface
->num_hw_features
; i
++) {
604 struct hostapd_hw_modes
*mode
= &iface
->hw_features
[i
];
605 if (mode
->mode
== iface
->conf
->hw_mode
) {
606 iface
->current_mode
= mode
;
611 if (iface
->current_mode
== NULL
) {
612 wpa_printf(MSG_ERROR
, "Hardware does not support configured "
614 hostapd_logger(iface
->bss
[0], NULL
, HOSTAPD_MODULE_IEEE80211
,
615 HOSTAPD_LEVEL_WARNING
,
616 "Hardware does not support configured mode "
617 "(%d)", (int) iface
->conf
->hw_mode
);
622 for (j
= 0; j
< iface
->current_mode
->num_channels
; j
++) {
623 struct hostapd_channel_data
*chan
=
624 &iface
->current_mode
->channels
[j
];
625 if (!(chan
->flag
& HOSTAPD_CHAN_DISABLED
) &&
626 (chan
->chan
== iface
->conf
->channel
)) {
631 if (iface
->conf
->channel
== 0) {
632 /* TODO: could request a scan of neighboring BSSes and select
633 * the channel automatically */
634 wpa_printf(MSG_ERROR
, "Channel not configured "
635 "(hw_mode/channel in hostapd.conf)");
638 if (ok
== 0 && iface
->conf
->channel
!= 0) {
639 hostapd_logger(iface
->bss
[0], NULL
,
640 HOSTAPD_MODULE_IEEE80211
,
641 HOSTAPD_LEVEL_WARNING
,
642 "Configured channel (%d) not found from the "
643 "channel list of current mode (%d) %s",
644 iface
->conf
->channel
,
645 iface
->current_mode
->mode
,
646 hostapd_hw_mode_txt(iface
->current_mode
->mode
));
647 iface
->current_mode
= NULL
;
650 if (iface
->current_mode
== NULL
) {
651 hostapd_logger(iface
->bss
[0], NULL
, HOSTAPD_MODULE_IEEE80211
,
652 HOSTAPD_LEVEL_WARNING
,
653 "Hardware does not support configured channel");
657 if (hostapd_prepare_rates(iface
->bss
[0], iface
->current_mode
)) {
658 wpa_printf(MSG_ERROR
, "Failed to prepare rates table.");
659 hostapd_logger(iface
->bss
[0], NULL
, HOSTAPD_MODULE_IEEE80211
,
660 HOSTAPD_LEVEL_WARNING
,
661 "Failed to prepare rates table.");
669 const char * hostapd_hw_mode_txt(int mode
)
672 case HOSTAPD_MODE_IEEE80211A
:
673 return "IEEE 802.11a";
674 case HOSTAPD_MODE_IEEE80211B
:
675 return "IEEE 802.11b";
676 case HOSTAPD_MODE_IEEE80211G
:
677 return "IEEE 802.11g";
684 int hostapd_hw_get_freq(struct hostapd_data
*hapd
, int chan
)
688 if (!hapd
->iface
->current_mode
)
691 for (i
= 0; i
< hapd
->iface
->current_mode
->num_channels
; i
++) {
692 struct hostapd_channel_data
*ch
=
693 &hapd
->iface
->current_mode
->channels
[i
];
694 if (ch
->chan
== chan
)
702 int hostapd_hw_get_channel(struct hostapd_data
*hapd
, int freq
)
706 if (!hapd
->iface
->current_mode
)
709 for (i
= 0; i
< hapd
->iface
->current_mode
->num_channels
; i
++) {
710 struct hostapd_channel_data
*ch
=
711 &hapd
->iface
->current_mode
->channels
[i
];
712 if (ch
->freq
== freq
)