hw_features.c revision 351611
1/*
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>
6 *
7 * This software may be distributed under the terms of the BSD license.
8 * See README for more details.
9 */
10
11#include "utils/includes.h"
12
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"
19#include "hostapd.h"
20#include "ap_config.h"
21#include "ap_drv_ops.h"
22#include "acs.h"
23#include "ieee802_11.h"
24#include "beacon.h"
25#include "hw_features.h"
26
27
28void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features,
29			      size_t num_hw_features)
30{
31	size_t i;
32
33	if (hw_features == NULL)
34		return;
35
36	for (i = 0; i < num_hw_features; i++) {
37		os_free(hw_features[i].channels);
38		os_free(hw_features[i].rates);
39	}
40
41	os_free(hw_features);
42}
43
44
45#ifndef CONFIG_NO_STDOUT_DEBUG
46static char * dfs_info(struct hostapd_channel_data *chan)
47{
48	static char info[256];
49	char *state;
50
51	switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) {
52	case HOSTAPD_CHAN_DFS_UNKNOWN:
53		state = "unknown";
54		break;
55	case HOSTAPD_CHAN_DFS_USABLE:
56		state = "usable";
57		break;
58	case HOSTAPD_CHAN_DFS_UNAVAILABLE:
59		state = "unavailable";
60		break;
61	case HOSTAPD_CHAN_DFS_AVAILABLE:
62		state = "available";
63		break;
64	default:
65		return "";
66	}
67	os_snprintf(info, sizeof(info), " (DFS state = %s)", state);
68	info[sizeof(info) - 1] = '\0';
69
70	return info;
71}
72#endif /* CONFIG_NO_STDOUT_DEBUG */
73
74
75int hostapd_get_hw_features(struct hostapd_iface *iface)
76{
77	struct hostapd_data *hapd = iface->bss[0];
78	int i, j;
79	u16 num_modes, flags;
80	struct hostapd_hw_modes *modes;
81	u8 dfs_domain;
82
83	if (hostapd_drv_none(hapd))
84		return -1;
85	modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags,
86					    &dfs_domain);
87	if (modes == NULL) {
88		hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211,
89			       HOSTAPD_LEVEL_DEBUG,
90			       "Fetching hardware channel/rate support not "
91			       "supported.");
92		return -1;
93	}
94
95	iface->hw_flags = flags;
96	iface->dfs_domain = dfs_domain;
97
98	hostapd_free_hw_features(iface->hw_features, iface->num_hw_features);
99	iface->hw_features = modes;
100	iface->num_hw_features = num_modes;
101
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);
106
107		/* set flag for channels we can use in current regulatory
108		 * domain */
109		for (j = 0; j < feature->num_channels; j++) {
110			int dfs = 0;
111
112			/*
113			 * Disable all channels that are marked not to allow
114			 * to initiate radiation (a.k.a. passive scan and no
115			 * IBSS).
116			 * Use radar channels only if the driver supports DFS.
117			 */
118			if ((feature->channels[j].flag &
119			     HOSTAPD_CHAN_RADAR) && dfs_enabled) {
120				dfs = 1;
121			} else if (((feature->channels[j].flag &
122				     HOSTAPD_CHAN_RADAR) &&
123				    !(iface->drv_flags &
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;
129			}
130
131			if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED)
132				continue;
133
134			wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d "
135				   "chan=%d freq=%d MHz max_tx_power=%d dBm%s",
136				   feature->mode,
137				   feature->channels[j].chan,
138				   feature->channels[j].freq,
139				   feature->channels[j].max_tx_power,
140				   dfs ? dfs_info(&feature->channels[j]) : "");
141		}
142	}
143
144	return 0;
145}
146
147
148int hostapd_prepare_rates(struct hostapd_iface *iface,
149			  struct hostapd_hw_modes *mode)
150{
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 };
155	int *basic_rates;
156
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;
162		break;
163	case HOSTAPD_MODE_IEEE80211B:
164		basic_rates = basic_rates_b;
165		break;
166	case HOSTAPD_MODE_IEEE80211G:
167		basic_rates = basic_rates_g;
168		break;
169	case HOSTAPD_MODE_IEEE80211AD:
170		return 0; /* No basic rates for 11ad */
171	default:
172		return -1;
173	}
174
175	i = 0;
176	while (basic_rates[i] >= 0)
177		i++;
178	if (i)
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));
184
185	os_free(iface->current_rates);
186	iface->num_rates = 0;
187
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 "
192			   "table.");
193		return -1;
194	}
195
196	for (i = 0; i < mode->num_rates; i++) {
197		struct hostapd_rate_data *rate;
198
199		if (iface->conf->supported_rates &&
200		    !hostapd_rate_found(iface->conf->supported_rates,
201					mode->rates[i]))
202			continue;
203
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;
208			num_basic_rates++;
209		}
210		wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x",
211			   iface->num_rates, rate->rate, rate->flags);
212		iface->num_rates++;
213	}
214
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);
220		return -1;
221	}
222
223	return 0;
224}
225
226
227#ifdef CONFIG_IEEE80211N
228static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface)
229{
230	int pri_chan, sec_chan;
231
232	pri_chan = iface->conf->channel;
233	sec_chan = pri_chan + iface->conf->secondary_channel * 4;
234
235	return allowed_ht40_channel_pair(iface->current_mode, pri_chan,
236					 sec_chan);
237}
238
239
240static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface)
241{
242	if (iface->conf->secondary_channel > 0) {
243		iface->conf->channel += 4;
244		iface->conf->secondary_channel = -1;
245	} else {
246		iface->conf->channel -= 4;
247		iface->conf->secondary_channel = 1;
248	}
249}
250
251
252static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface,
253				     struct wpa_scan_results *scan_res)
254{
255	int pri_chan, sec_chan;
256	int res;
257
258	pri_chan = iface->conf->channel;
259	sec_chan = pri_chan + iface->conf->secondary_channel * 4;
260
261	res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan);
262
263	if (res == 2) {
264		if (iface->conf->no_pri_sec_switch) {
265			wpa_printf(MSG_DEBUG,
266				   "Cannot switch PRI/SEC channels due to local constraint");
267		} else {
268			ieee80211n_switch_pri_sec(iface);
269		}
270	}
271
272	return !!res;
273}
274
275
276static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface,
277				      struct wpa_scan_results *scan_res)
278{
279	int pri_chan, sec_chan;
280
281	pri_chan = iface->conf->channel;
282	sec_chan = pri_chan + iface->conf->secondary_channel * 4;
283
284	return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan,
285			       sec_chan);
286}
287
288
289static void ieee80211n_check_scan(struct hostapd_iface *iface)
290{
291	struct wpa_scan_results *scan_res;
292	int oper40;
293	int res;
294
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 */
297
298	iface->scan_cb = NULL;
299
300	scan_res = hostapd_driver_get_scan_results(iface->bss[0]);
301	if (scan_res == NULL) {
302		hostapd_setup_interface_complete(iface, 1);
303		return;
304	}
305
306	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A)
307		oper40 = ieee80211n_check_40mhz_5g(iface, scan_res);
308	else
309		oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res);
310	wpa_scan_results_free(scan_res);
311
312	iface->secondary_ch = iface->conf->secondary_channel;
313	if (!oper40) {
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) {
321			/*
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.
325			 */
326		}
327	}
328
329	res = ieee80211n_allowed_ht40_channel_pair(iface);
330	if (!res) {
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);
335		res = 1;
336		wpa_printf(MSG_INFO, "Fallback to 20 MHz");
337	}
338
339	hostapd_setup_interface_complete(iface, !res);
340}
341
342
343static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface,
344					 struct wpa_driver_scan_params *params)
345{
346	/* Scan only the affected frequency range */
347	int pri_freq, sec_freq;
348	int affected_start, affected_end;
349	int i, pos;
350	struct hostapd_hw_modes *mode;
351
352	if (iface->current_mode == NULL)
353		return;
354
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;
358	else
359		sec_freq = pri_freq - 20;
360	/*
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.
364	 */
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);
369
370	mode = iface->current_mode;
371	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
372	if (params->freqs == NULL)
373		return;
374	pos = 0;
375
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)
379			continue;
380		if (chan->freq < affected_start ||
381		    chan->freq > affected_end)
382			continue;
383		params->freqs[pos++] = chan->freq;
384	}
385}
386
387
388static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface,
389					struct wpa_driver_scan_params *params)
390{
391	/* Scan only the affected frequency range */
392	int pri_freq;
393	int affected_start, affected_end;
394	int i, pos;
395	struct hostapd_hw_modes *mode;
396
397	if (iface->current_mode == NULL)
398		return;
399
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;
404	} else {
405		affected_start = pri_freq - 30;
406		affected_end = pri_freq + 10;
407	}
408	wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz",
409		   affected_start, affected_end);
410
411	mode = iface->current_mode;
412	params->freqs = os_calloc(mode->num_channels + 1, sizeof(int));
413	if (params->freqs == NULL)
414		return;
415	pos = 0;
416
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)
420			continue;
421		if (chan->freq < affected_start ||
422		    chan->freq > affected_end)
423			continue;
424		params->freqs[pos++] = chan->freq;
425	}
426}
427
428
429static void ap_ht40_scan_retry(void *eloop_data, void *user_data)
430{
431#define HT2040_COEX_SCAN_RETRY 15
432	struct hostapd_iface *iface = eloop_data;
433	struct wpa_driver_scan_params params;
434	int ret;
435
436	os_memset(&params, 0, sizeof(params));
437	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
438		ieee80211n_scan_channels_2g4(iface, &params);
439	else
440		ieee80211n_scan_channels_5g(iface, &params);
441
442	ret = hostapd_driver_scan(iface->bss[0], &params);
443	iface->num_ht40_scan_tries++;
444	os_free(params.freqs);
445
446	if (ret == -EBUSY &&
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);
452		return;
453	}
454
455	if (ret == 0) {
456		iface->scan_cb = ieee80211n_check_scan;
457		return;
458	}
459
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);
465}
466
467
468void hostapd_stop_setup_timers(struct hostapd_iface *iface)
469{
470	eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL);
471}
472
473
474static int ieee80211n_check_40mhz(struct hostapd_iface *iface)
475{
476	struct wpa_driver_scan_params params;
477	int ret;
478
479	/* Check that HT40 is used and PRI / SEC switch is allowed */
480	if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch)
481		return 0;
482
483	hostapd_set_state(iface, HAPD_IFACE_HT_SCAN);
484	wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling "
485		   "40 MHz channel");
486	os_memset(&params, 0, sizeof(params));
487	if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
488		ieee80211n_scan_channels_2g4(iface, &params);
489	else
490		ieee80211n_scan_channels_5g(iface, &params);
491
492	ret = hostapd_driver_scan(iface->bss[0], &params);
493	os_free(params.freqs);
494
495	if (ret == -EBUSY) {
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);
502		return 1;
503	}
504
505	if (ret < 0) {
506		wpa_printf(MSG_ERROR,
507			   "Failed to request a scan of neighboring BSSes ret=%d (%s)",
508			   ret, strerror(-ret));
509		return -1;
510	}
511
512	iface->scan_cb = ieee80211n_check_scan;
513	return 1;
514}
515
516
517static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface)
518{
519	u16 hw = iface->current_mode->ht_capab;
520	u16 conf = iface->conf->ht_capab;
521
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]");
526		return 0;
527	}
528
529	/*
530	 * Driver ACS chosen channel may not be HT40 due to internal driver
531	 * restrictions.
532	 */
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*]");
537		return 0;
538	}
539
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]");
545			return 0;
546		}
547		break;
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]");
552			return 0;
553		}
554		break;
555	case HT_CAP_INFO_SMPS_DISABLED:
556	default:
557		break;
558	}
559
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]");
564		return 0;
565	}
566
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]");
571		return 0;
572	}
573
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]");
578		return 0;
579	}
580
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]");
584		return 0;
585	}
586
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*]");
591		return 0;
592	}
593
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]");
598		return 0;
599	}
600
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]");
605		return 0;
606	}
607
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]");
612		return 0;
613	}
614
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]");
619		return 0;
620	}
621
622	return 1;
623}
624
625
626#ifdef CONFIG_IEEE80211AC
627static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface)
628{
629	struct hostapd_hw_modes *mode = iface->current_mode;
630	u32 hw = mode->vht_capab;
631	u32 conf = iface->conf->vht_capab;
632
633	wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x",
634		   hw, conf);
635
636	if (mode->mode == HOSTAPD_MODE_IEEE80211G &&
637	    iface->conf->bss[0]->vendor_vht &&
638	    mode->vht_capab == 0 && iface->hw_features) {
639		int i;
640
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",
648					   hw);
649				break;
650			}
651		}
652	}
653
654	return ieee80211ac_cap_check(hw, conf);
655}
656#endif /* CONFIG_IEEE80211AC */
657
658
659#ifdef CONFIG_IEEE80211AX
660static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface)
661{
662	return 1;
663}
664#endif /* CONFIG_IEEE80211AX */
665
666#endif /* CONFIG_IEEE80211N */
667
668
669int hostapd_check_ht_capab(struct hostapd_iface *iface)
670{
671#ifdef CONFIG_IEEE80211N
672	int ret;
673	if (!iface->conf->ieee80211n)
674		return 0;
675
676	if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B &&
677	    iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G &&
678	    (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) {
679		wpa_printf(MSG_DEBUG,
680			   "Disable HT capability [DSSS_CCK-40] on 5 GHz band");
681		iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ;
682	}
683
684	if (!ieee80211n_supported_ht_capab(iface))
685		return -1;
686#ifdef CONFIG_IEEE80211AX
687	if (iface->conf->ieee80211ax &&
688	    !ieee80211ax_supported_he_capab(iface))
689		return -1;
690#endif /* CONFIG_IEEE80211AX */
691#ifdef CONFIG_IEEE80211AC
692	if (iface->conf->ieee80211ac &&
693	    !ieee80211ac_supported_vht_capab(iface))
694		return -1;
695#endif /* CONFIG_IEEE80211AC */
696	ret = ieee80211n_check_40mhz(iface);
697	if (ret)
698		return ret;
699	if (!ieee80211n_allowed_ht40_channel_pair(iface))
700		return -1;
701#endif /* CONFIG_IEEE80211N */
702
703	return 0;
704}
705
706
707static int hostapd_is_usable_chan(struct hostapd_iface *iface,
708				  int channel, int primary)
709{
710	struct hostapd_channel_data *chan;
711
712	if (!iface->current_mode)
713		return 0;
714
715	chan = hw_get_channel_chan(iface->current_mode, channel, NULL);
716	if (!chan)
717		return 0;
718
719	if ((primary && chan_pri_allowed(chan)) ||
720	    (!primary && !(chan->flag & HOSTAPD_CHAN_DISABLED)))
721		return 1;
722
723	wpa_printf(MSG_INFO,
724		   "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s",
725		   channel, primary ? "primary" : "secondary",
726		   chan->flag,
727		   chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "",
728		   chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : "");
729	return 0;
730}
731
732
733static int hostapd_is_usable_chans(struct hostapd_iface *iface)
734{
735	int secondary_chan;
736	struct hostapd_channel_data *pri_chan;
737
738	pri_chan = hw_get_channel_chan(iface->current_mode,
739				       iface->conf->channel, NULL);
740	if (!pri_chan)
741		return 0;
742
743	if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1))
744		return 0;
745
746	if (!iface->conf->secondary_channel)
747		return 1;
748
749	if (!iface->conf->ht40_plus_minus_allowed)
750		return hostapd_is_usable_chan(
751			iface, iface->conf->channel +
752			iface->conf->secondary_channel * 4, 0);
753
754	/* Both HT40+ and HT40- are set, pick a valid secondary channel */
755	secondary_chan = iface->conf->channel + 4;
756	if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
757	    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) {
758		iface->conf->secondary_channel = 1;
759		return 1;
760	}
761
762	secondary_chan = iface->conf->channel - 4;
763	if (hostapd_is_usable_chan(iface, secondary_chan, 0) &&
764	    (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) {
765		iface->conf->secondary_channel = -1;
766		return 1;
767	}
768
769	return 0;
770}
771
772
773static enum hostapd_chan_status
774hostapd_check_chans(struct hostapd_iface *iface)
775{
776	if (iface->conf->channel) {
777		if (hostapd_is_usable_chans(iface))
778			return HOSTAPD_CHAN_VALID;
779		else
780			return HOSTAPD_CHAN_INVALID;
781	}
782
783	/*
784	 * The user set channel=0 or channel=acs_survey
785	 * which is used to trigger ACS.
786	 */
787
788	switch (acs_init(iface)) {
789	case HOSTAPD_CHAN_ACS:
790		return HOSTAPD_CHAN_ACS;
791	case HOSTAPD_CHAN_VALID:
792	case HOSTAPD_CHAN_INVALID:
793	default:
794		return HOSTAPD_CHAN_INVALID;
795	}
796}
797
798
799static void hostapd_notify_bad_chans(struct hostapd_iface *iface)
800{
801	if (!iface->current_mode) {
802		hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
803			       HOSTAPD_LEVEL_WARNING,
804			       "Hardware does not support configured mode");
805		return;
806	}
807	hostapd_logger(iface->bss[0], NULL,
808		       HOSTAPD_MODULE_IEEE80211,
809		       HOSTAPD_LEVEL_WARNING,
810		       "Configured channel (%d) not found from the "
811		       "channel list of current mode (%d) %s",
812		       iface->conf->channel,
813		       iface->current_mode->mode,
814		       hostapd_hw_mode_txt(iface->current_mode->mode));
815	hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211,
816		       HOSTAPD_LEVEL_WARNING,
817		       "Hardware does not support configured channel");
818}
819
820
821int hostapd_acs_completed(struct hostapd_iface *iface, int err)
822{
823	int ret = -1;
824
825	if (err)
826		goto out;
827
828	switch (hostapd_check_chans(iface)) {
829	case HOSTAPD_CHAN_VALID:
830		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO,
831			ACS_EVENT_COMPLETED "freq=%d channel=%d",
832			hostapd_hw_get_freq(iface->bss[0],
833					    iface->conf->channel),
834			iface->conf->channel);
835		break;
836	case HOSTAPD_CHAN_ACS:
837		wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available");
838		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
839		hostapd_notify_bad_chans(iface);
840		goto out;
841	case HOSTAPD_CHAN_INVALID:
842	default:
843		wpa_printf(MSG_ERROR, "ACS picked unusable channels");
844		wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED);
845		hostapd_notify_bad_chans(iface);
846		goto out;
847	}
848
849	ret = hostapd_check_ht_capab(iface);
850	if (ret < 0)
851		goto out;
852	if (ret == 1) {
853		wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback");
854		return 0;
855	}
856
857	ret = 0;
858out:
859	return hostapd_setup_interface_complete(iface, ret);
860}
861
862
863/**
864 * hostapd_select_hw_mode - Select the hardware mode
865 * @iface: Pointer to interface data.
866 * Returns: 0 on success, < 0 on failure
867 *
868 * Sets up the hardware mode, channel, rates, and passive scanning
869 * based on the configuration.
870 */
871int hostapd_select_hw_mode(struct hostapd_iface *iface)
872{
873	int i;
874
875	if (iface->num_hw_features < 1)
876		return -1;
877
878	if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G ||
879	     iface->conf->ieee80211n || iface->conf->ieee80211ac ||
880	     iface->conf->ieee80211ax) &&
881	    iface->conf->channel == 14) {
882		wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE on channel 14");
883		iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B;
884		iface->conf->ieee80211n = 0;
885		iface->conf->ieee80211ac = 0;
886		iface->conf->ieee80211ax = 0;
887	}
888
889	iface->current_mode = NULL;
890	for (i = 0; i < iface->num_hw_features; i++) {
891		struct hostapd_hw_modes *mode = &iface->hw_features[i];
892		if (mode->mode == iface->conf->hw_mode) {
893			iface->current_mode = mode;
894			break;
895		}
896	}
897
898	if (iface->current_mode == NULL) {
899		if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) ||
900		    !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY))
901		{
902			wpa_printf(MSG_ERROR,
903				   "Hardware does not support configured mode");
904			hostapd_logger(iface->bss[0], NULL,
905				       HOSTAPD_MODULE_IEEE80211,
906				       HOSTAPD_LEVEL_WARNING,
907				       "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)",
908				       (int) iface->conf->hw_mode);
909			return -2;
910		}
911	}
912
913	switch (hostapd_check_chans(iface)) {
914	case HOSTAPD_CHAN_VALID:
915		return 0;
916	case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */
917		return 1;
918	case HOSTAPD_CHAN_INVALID:
919	default:
920		hostapd_notify_bad_chans(iface);
921		return -3;
922	}
923}
924
925
926const char * hostapd_hw_mode_txt(int mode)
927{
928	switch (mode) {
929	case HOSTAPD_MODE_IEEE80211A:
930		return "IEEE 802.11a";
931	case HOSTAPD_MODE_IEEE80211B:
932		return "IEEE 802.11b";
933	case HOSTAPD_MODE_IEEE80211G:
934		return "IEEE 802.11g";
935	case HOSTAPD_MODE_IEEE80211AD:
936		return "IEEE 802.11ad";
937	default:
938		return "UNKNOWN";
939	}
940}
941
942
943int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan)
944{
945	return hw_get_freq(hapd->iface->current_mode, chan);
946}
947
948
949int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq)
950{
951	int i, channel;
952	struct hostapd_hw_modes *mode;
953
954	if (hapd->iface->current_mode) {
955		channel = hw_get_chan(hapd->iface->current_mode, freq);
956		if (channel)
957			return channel;
958	}
959
960	/* Check other available modes since the channel list for the current
961	 * mode did not include the specified frequency. */
962	if (!hapd->iface->hw_features)
963		return 0;
964	for (i = 0; i < hapd->iface->num_hw_features; i++) {
965		mode = &hapd->iface->hw_features[i];
966		channel = hw_get_chan(mode, freq);
967		if (channel)
968			return channel;
969	}
970	return 0;
971}
972