hw_features.c revision 2f74e36e84064ffa32f82f3decf36b653c7e4fad
18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/* 28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd / Hardware feature query and different modes 38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2002-2003, Instant802 Networks, Inc. 48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright 2005-2006, Devicescape Software, Inc. 504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi> 68d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 7fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 8fb79edc9df1f20461e90e478363d207348213d35Dmitry Shmidt * See README for more details. 98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/includes.h" 128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/common.h" 148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "utils/eloop.h" 158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_defs.h" 168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common/ieee802_11_common.h" 17cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt#include "common/wpa_ctrl.h" 18ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt#include "common/hw_features_common.h" 198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hostapd.h" 208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_config.h" 218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "ap_drv_ops.h" 22391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt#include "acs.h" 237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "ieee802_11.h" 247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#include "beacon.h" 258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "hw_features.h" 268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtvoid hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t num_hw_features) 308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt size_t i; 328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hw_features == NULL) 348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_hw_features; i++) { 378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features[i].channels); 388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features[i].rates); 398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_free(hw_features); 428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 45051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#ifndef CONFIG_NO_STDOUT_DEBUG 46051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidtstatic char * dfs_info(struct hostapd_channel_data *chan) 47051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt{ 48051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt static char info[256]; 49051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt char *state; 50051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 51051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { 52051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_UNKNOWN: 53051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "unknown"; 54051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 55051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_USABLE: 56051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "usable"; 57051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 58051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_UNAVAILABLE: 59051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "unavailable"; 60051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 61051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt case HOSTAPD_CHAN_DFS_AVAILABLE: 62051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt state = "available"; 63051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt break; 64051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt default: 65051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return ""; 66051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 67051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt os_snprintf(info, sizeof(info), " (DFS state = %s)", state); 68051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt info[sizeof(info) - 1] = '\0'; 69051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 70051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt return info; 71051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt} 72051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt#endif /* CONFIG_NO_STDOUT_DEBUG */ 73051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 74051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_get_hw_features(struct hostapd_iface *iface) 768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_data *hapd = iface->bss[0]; 782f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int i, j; 798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 num_modes, flags; 808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *modes; 818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_drv_none(hapd)) 838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); 858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (modes == NULL) { 868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_DEBUG, 888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Fetching hardware channel/rate support not " 898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "supported."); 908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->hw_flags = flags; 948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->hw_features = modes; 978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->num_hw_features = num_modes; 988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < num_modes; i++) { 1008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *feature = &modes[i]; 101051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int dfs_enabled = hapd->iconf->ieee80211h && 102051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); 103051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* set flag for channels we can use in current regulatory 1058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * domain */ 1068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (j = 0; j < feature->num_channels; j++) { 107051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt int dfs = 0; 108051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* 1108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Disable all channels that are marked not to allow 1116c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * to initiate radiation (a.k.a. passive scan and no 1126c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt * IBSS). 113051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt * Use radar channels only if the driver supports DFS. 1148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 115051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt if ((feature->channels[j].flag & 116051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt HOSTAPD_CHAN_RADAR) && dfs_enabled) { 117051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt dfs = 1; 118d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt } else if (((feature->channels[j].flag & 119d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt HOSTAPD_CHAN_RADAR) && 120d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt !(iface->drv_flags & 121d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || 122d11f019d62a42a8fc4c4d1f2ec17cf35b0763153Dmitry Shmidt (feature->channels[j].flag & 1236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt HOSTAPD_CHAN_NO_IR)) { 1248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].flag |= 1258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_CHAN_DISABLED; 126051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt } 127051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 1298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 130051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt 1318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 132051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt "chan=%d freq=%d MHz max_tx_power=%d dBm%s", 1338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->mode, 1348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].chan, 1358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt feature->channels[j].freq, 136051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt feature->channels[j].max_tx_power, 137051af73b8f8014eff33330aead0f36944b3403e6Dmitry Shmidt dfs ? dfs_info(&feature->channels[j]) : ""); 1388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1412f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt return 0; 1428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 1438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtint hostapd_prepare_rates(struct hostapd_iface *iface, 1468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode) 1478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 1488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int i, num_basic_rates = 0; 1498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_a[] = { 60, 120, 240, -1 }; 1508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_b[] = { 10, 20, -1 }; 1518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 1528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int *basic_rates; 1538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->conf->basic_rates) 1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt basic_rates = iface->conf->basic_rates; 1568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else switch (mode->mode) { 1578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 1588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_a; 1598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 1618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_b; 1628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 1638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 1648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt basic_rates = basic_rates_g; 1658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 166a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 167a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return 0; /* No basic rates for 11ad */ 1688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 1698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i = 0; 1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt while (basic_rates[i] >= 0) 1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt i++; 1754530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt if (i) 1764530cfd4d14a77c58e35393b91e40f8dd9d62697Dmitry Shmidt i++; /* -1 termination */ 1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(iface->basic_rates); 1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->basic_rates = os_malloc(i * sizeof(int)); 1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->basic_rates) 1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 1818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt os_free(iface->current_rates); 1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates = 0; 1848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->current_rates = 18661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (!iface->current_rates) { 1888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 1898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "table."); 1908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 1918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 1928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < mode->num_rates; i++) { 1948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_rate_data *rate; 1958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (iface->conf->supported_rates && 1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt !hostapd_rate_found(iface->conf->supported_rates, 1988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt mode->rates[i])) 1998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt continue; 2008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt rate = &iface->current_rates[iface->num_rates]; 2028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate->rate = mode->rates[i]; 2038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (hostapd_rate_found(basic_rates, rate->rate)) { 2048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt rate->flags |= HOSTAPD_RATE_BASIC; 2058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt num_basic_rates++; 2068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates, rate->rate, rate->flags); 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates++; 2108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if ((iface->num_rates == 0 || num_basic_rates == 0) && 2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 2148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 2158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "rate sets (%d,%d).", 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt iface->num_rates, num_basic_rates); 2178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 2188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 2218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 2258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 2268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 227ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 2288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->conf->secondary_channel) 2308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; /* HT40 not used */ 2318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 232ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt pri_chan = iface->conf->channel; 233ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 235ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return allowed_ht40_channel_pair(iface->current_mode, pri_chan, 236ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan); 2378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 2418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->conf->secondary_channel > 0) { 2438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel += 4; 2448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = -1; 2458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } else { 2468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel -= 4; 2478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = 1; 2488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 2538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res) 2548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 255ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 256ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int res; 2578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt pri_chan = iface->conf->channel; 259b36ed7cd946148d829f311de8fe53ea3ffaaffe3Dmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 261ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan); 2628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 263ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt if (res == 2) 264ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt ieee80211n_switch_pri_sec(iface); 2656dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 266ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return !!res; 2676dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt} 2686dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 2696dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 2708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 2718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res) 2728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 273ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt int pri_chan, sec_chan; 2746dc03bd757d3befd2c03a543a402338db03914d6Dmitry Shmidt 275ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt pri_chan = iface->conf->channel; 276ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan = pri_chan + iface->conf->secondary_channel * 4; 2778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 278ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan, 279ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt sec_chan); 2808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 2818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic void ieee80211n_check_scan(struct hostapd_iface *iface) 2848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 2858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_scan_results *scan_res; 2868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int oper40; 2878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int res; 2888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 29004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 2918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->scan_cb = NULL; 2938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 2948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 2958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (scan_res == NULL) { 2968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_setup_interface_complete(iface, 1); 2978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return; 2988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 2998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 3018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 3028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt else 3038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 3048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_scan_results_free(scan_res); 3058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3067832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->secondary_ch = iface->conf->secondary_channel; 3078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!oper40) { 3088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 3098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "channel pri=%d sec=%d based on overlapping BSSes", 3108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel, 3118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->channel + 3128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel * 4); 3138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->conf->secondary_channel = 0; 3147832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { 3157832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt /* 3167832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * TODO: Could consider scheduling another scan to check 3177832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * if channel width can be changed if no coex reports 3187832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt * are received from associating stations. 3197832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt */ 3207832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 3218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 3228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt res = ieee80211n_allowed_ht40_channel_pair(iface); 3247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (!res) { 3257832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->secondary_channel = 0; 3267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_INFO, "Fallback to 20 MHz"); 3277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 3287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 3298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_setup_interface_complete(iface, !res); 3308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 3318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 3328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 33304949598a23f501be6eec21697465fd46a28840aDmitry Shmidtstatic void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, 33404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct wpa_driver_scan_params *params) 33504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt{ 33604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt /* Scan only the affected frequency range */ 33704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int pri_freq, sec_freq; 33804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int affected_start, affected_end; 33904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt int i, pos; 34004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_hw_modes *mode; 34104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->current_mode == NULL) 34304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 34404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 34504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 34604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->conf->secondary_channel > 0) 34704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sec_freq = pri_freq + 20; 34804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt else 34904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt sec_freq = pri_freq - 20; 35004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt affected_start = (pri_freq + sec_freq) / 2 - 25; 35104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt affected_end = (pri_freq + sec_freq) / 2 + 25; 35204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 35304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt affected_start, affected_end); 35404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 35504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt mode = iface->current_mode; 35661d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 35704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (params->freqs == NULL) 35804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt return; 35904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt pos = 0; 36004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 36104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 36204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[i]; 36304949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 36404949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 36504949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (chan->freq < affected_start || 36604949598a23f501be6eec21697465fd46a28840aDmitry Shmidt chan->freq > affected_end) 36704949598a23f501be6eec21697465fd46a28840aDmitry Shmidt continue; 36804949598a23f501be6eec21697465fd46a28840aDmitry Shmidt params->freqs[pos++] = chan->freq; 36904949598a23f501be6eec21697465fd46a28840aDmitry Shmidt } 37004949598a23f501be6eec21697465fd46a28840aDmitry Shmidt} 37104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 37204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt 373cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidtstatic void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, 374cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct wpa_driver_scan_params *params) 375cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt{ 376cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt /* Scan only the affected frequency range */ 377cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int pri_freq; 378cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int affected_start, affected_end; 379cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt int i, pos; 380cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_hw_modes *mode; 381cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 382cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->current_mode == NULL) 383cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return; 384cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 385cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 386cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (iface->conf->secondary_channel > 0) { 387cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start = pri_freq - 10; 388cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_end = pri_freq + 30; 389cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } else { 390cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start = pri_freq - 30; 391cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_end = pri_freq + 10; 392cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 393cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 394cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt affected_start, affected_end); 395cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 396cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt mode = iface->current_mode; 397cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 398cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (params->freqs == NULL) 399cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt return; 400cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt pos = 0; 401cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 402cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt for (i = 0; i < mode->num_channels; i++) { 403cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt struct hostapd_channel_data *chan = &mode->channels[i]; 404cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (chan->flag & HOSTAPD_CHAN_DISABLED) 405cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt continue; 406cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt if (chan->freq < affected_start || 407cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt chan->freq > affected_end) 408cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt continue; 409cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt params->freqs[pos++] = chan->freq; 410cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt } 411cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt} 412cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 413cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt 4147832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtstatic void ap_ht40_scan_retry(void *eloop_data, void *user_data) 4157832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt{ 4167832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt#define HT2040_COEX_SCAN_RETRY 15 4177832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct hostapd_iface *iface = eloop_data; 4187832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt struct wpa_driver_scan_params params; 4197832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt int ret; 4207832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4217832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 4227832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 4237832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ieee80211n_scan_channels_2g4(iface, ¶ms); 4247832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt else 4257832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ieee80211n_scan_channels_5g(iface, ¶ms); 4267832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4277832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret = hostapd_driver_scan(iface->bss[0], ¶ms); 4287832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries++; 4297832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_free(params.freqs); 4307832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4317832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == -EBUSY && 4327832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { 4337832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 4347832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", 4357832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret), iface->num_ht40_scan_tries); 4367832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 4377832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return; 4387832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 4397832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4407832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == 0) { 4417832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->scan_cb = ieee80211n_check_scan; 4427832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return; 4437832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 4447832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4457832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_DEBUG, 4467832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan in device, bringing up in HT20 mode"); 4477832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->secondary_channel = 0; 4487832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; 4497832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt hostapd_setup_interface_complete(iface, 0); 4507832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt} 4517832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4527832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4537832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidtvoid hostapd_stop_setup_timers(struct hostapd_iface *iface) 4547832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt{ 4557832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 4567832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt} 4577832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4587832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_check_40mhz(struct hostapd_iface *iface) 4608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 4618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct wpa_driver_scan_params params; 4627832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt int ret; 4638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->conf->secondary_channel) 4658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; /* HT40 not used */ 4668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 467cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); 4688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 4698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "40 MHz channel"); 4708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt os_memset(¶ms, 0, sizeof(params)); 47104949598a23f501be6eec21697465fd46a28840aDmitry Shmidt if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 47204949598a23f501be6eec21697465fd46a28840aDmitry Shmidt ieee80211n_scan_channels_2g4(iface, ¶ms); 473cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt else 474cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ieee80211n_scan_channels_5g(iface, ¶ms); 4757832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4767832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret = hostapd_driver_scan(iface->bss[0], ¶ms); 4777832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt os_free(params.freqs); 4787832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4797832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret == -EBUSY) { 4807832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 4817832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", 4827832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret)); 4837832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt iface->num_ht40_scan_tries = 1; 4847832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); 4857832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); 4867832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt return 1; 4877832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt } 4887832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt 4897832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt if (ret < 0) { 4907832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt wpa_printf(MSG_ERROR, 4917832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt "Failed to request a scan of neighboring BSSes ret=%d (%s)", 4927832adbbd72a1b784b7fb74a71a5d4085b0cb0d3Dmitry Shmidt ret, strerror(-ret)); 4938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 4948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 4958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 4968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->scan_cb = ieee80211n_check_scan; 4978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 4988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 4998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtstatic int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 5028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 5038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 hw = iface->current_mode->ht_capab; 5048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt u16 conf = iface->conf->ht_capab; 5058d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5068d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 5078d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 5088d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5098d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [LDPC]"); 5108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 5148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 5158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [HT40*]"); 5178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5206c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt switch (conf & HT_CAP_INFO_SMPS_MASK) { 5216c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_STATIC: 5226c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { 5236c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, 5246c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "Driver does not support configured HT capability [SMPS-STATIC]"); 5256c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 5266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5286c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DYNAMIC: 5296c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { 5306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt wpa_printf(MSG_ERROR, 5316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "Driver does not support configured HT capability [SMPS-DYNAMIC]"); 5326c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt return 0; 5336c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt } 5346c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt case HT_CAP_INFO_SMPS_DISABLED: 5366c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt default: 5376c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt break; 5388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_GREEN_FIELD) && 5418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_GREEN_FIELD)) { 5428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [GF]"); 5448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 5488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 5498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [SHORT-GI-20]"); 5518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 5558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 5568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [SHORT-GI-40]"); 5588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 5628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [TX-STBC]"); 5648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 5688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt (hw & HT_CAP_INFO_RX_STBC_MASK)) { 5698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [RX-STBC*]"); 5718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_DELAYED_BA) && 5758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_DELAYED_BA)) { 5768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [DELAYED-BA]"); 5788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5818d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 5828d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 5838d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [MAX-AMSDU-7935]"); 5858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 5898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 5908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [DSSS_CCK-40]"); 5928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 5938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 5948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 5958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 5968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 5978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured " 5988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "HT capability [LSIG-TXOP-PROT]"); 5998d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 6008d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 6018d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 6028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 1; 6038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 6048d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 60568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 60668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#ifdef CONFIG_IEEE80211AC 60768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 60868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name) 60968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 61068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u32 req_cap = conf & cap; 61168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 61268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt /* 61368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * Make sure we support all requested capabilities. 61468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * NOTE: We assume that 'cap' represents a capability mask, 61568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt * not a discrete value. 61668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt */ 61768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if ((hw & req_cap) != req_cap) { 61868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "Driver does not support configured VHT capability [%s]", 61968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt name); 62068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; 62168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 62268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 1; 62368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 62468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 62568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6266c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidtstatic int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 mask, 6276c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt unsigned int shift, 62868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt const char *name) 62968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 6306c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 hw_max = hw & mask; 6316c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt u32 conf_val = conf & mask; 63268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 63368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (conf_val > hw_max) { 63468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)", 6356c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt name, conf_val >> shift, hw_max >> shift); 63668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; 63768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } 63868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 1; 63968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 64068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 64168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 64268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidtstatic int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) 64368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt{ 6442f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt struct hostapd_hw_modes *mode = iface->current_mode; 6452f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt u32 hw = mode->vht_capab; 64668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt u32 conf = iface->conf->vht_capab; 64768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 64868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", 64968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt hw, conf); 65068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 6512f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (mode->mode == HOSTAPD_MODE_IEEE80211G && 6522f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt iface->conf->bss[0]->vendor_vht && 6532f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt mode->vht_capab == 0 && iface->hw_features) { 6542f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt int i; 6552f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 6562f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt for (i = 0; i < iface->num_hw_features; i++) { 6572f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt if (iface->hw_features[i].mode == 6582f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt HOSTAPD_MODE_IEEE80211A) { 6592f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt mode = &iface->hw_features[i]; 6602f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt hw = mode->vht_capab; 6612f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt wpa_printf(MSG_DEBUG, 6622f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt "update hw vht capab based on 5 GHz band: 0x%x", 6632f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt hw); 6642f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt break; 6652f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6662f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6672f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt } 6682f74e36e84064ffa32f82f3decf36b653c7e4fadDmitry Shmidt 66968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define VHT_CAP_CHECK(cap) \ 67068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt do { \ 67168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \ 67268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; \ 67368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } while (0) 67468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 67568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#define VHT_CAP_CHECK_MAX(cap) \ 67668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt do { \ 6776c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt if (!ieee80211ac_cap_check_max(hw, conf, cap, cap ## _SHIFT, \ 6786c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt #cap)) \ 67968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 0; \ 68068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt } while (0) 68168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 68268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK); 68368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ); 68468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); 68568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_RXLDPC); 68668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80); 68768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160); 68868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_TXSTBC); 68968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK); 69068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE); 69168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE); 69268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX); 69368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX); 69468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE); 69568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE); 69668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS); 69768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_HTC_VHT); 698a38abf9af7bec7e89dbfb39ac7bb77223fe47c72Dmitry Shmidt VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX); 69968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB); 70068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); 70168d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); 70268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); 70368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 70468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#undef VHT_CAP_CHECK 70568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#undef VHT_CAP_CHECK_MAX 70668d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 70768d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return 1; 70868d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt} 70968d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif /* CONFIG_IEEE80211AC */ 71068d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt 7118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 7128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_check_ht_capab(struct hostapd_iface *iface) 7158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 7168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#ifdef CONFIG_IEEE80211N 7178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt int ret; 7188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!iface->conf->ieee80211n) 7198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ieee80211n_supported_ht_capab(iface)) 7218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 72268d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#ifdef CONFIG_IEEE80211AC 72368d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt if (!ieee80211ac_supported_vht_capab(iface)) 72468d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt return -1; 72568d0e3ed07847339aedfac8e02f50db68c702e52Dmitry Shmidt#endif /* CONFIG_IEEE80211AC */ 7268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt ret = ieee80211n_check_40mhz(iface); 7278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (ret) 7288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return ret; 7298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (!ieee80211n_allowed_ht40_channel_pair(iface)) 7308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 7318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#endif /* CONFIG_IEEE80211N */ 7328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return 0; 7348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 7358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 7368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 737b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_is_usable_chan(struct hostapd_iface *iface, 738b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int channel, int primary) 739b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 740b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int i; 741b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt struct hostapd_channel_data *chan; 742b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 743b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt for (i = 0; i < iface->current_mode->num_channels; i++) { 744b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt chan = &iface->current_mode->channels[i]; 745b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (chan->chan != channel) 746b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt continue; 747b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 748b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) 749b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 1; 750b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 751b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt wpa_printf(MSG_DEBUG, 7526c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s", 753b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt primary ? "" : "Configured HT40 secondary ", 754b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt i, chan->chan, chan->flag, 7556c0da2bb83f6915d8260912362692d1a742e057bDmitry Shmidt chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", 756b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); 757b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 758b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 759b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 760b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 761b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 762b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 763b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic int hostapd_is_usable_chans(struct hostapd_iface *iface) 764b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 765b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) 766b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 767b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 768b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (!iface->conf->secondary_channel) 769b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 1; 770b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 771b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return hostapd_is_usable_chan(iface, iface->conf->channel + 772b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt iface->conf->secondary_channel * 4, 0); 773b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 774b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 775b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 776b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic enum hostapd_chan_status 777b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidthostapd_check_chans(struct hostapd_iface *iface) 778b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 779b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (iface->conf->channel) { 780b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt if (hostapd_is_usable_chans(iface)) 781b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return HOSTAPD_CHAN_VALID; 782b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt else 783b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 784b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt } 785b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 786b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt /* 787391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * The user set channel=0 or channel=acs_survey 788391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt * which is used to trigger ACS. 789b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt */ 790391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 791391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (acs_init(iface)) { 792391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: 793391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_ACS; 794391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_VALID: 795391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 796391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 797391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return HOSTAPD_CHAN_INVALID; 798391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 799b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 800b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 801b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 802b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidtstatic void hostapd_notify_bad_chans(struct hostapd_iface *iface) 803b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt{ 804b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, 805b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_MODULE_IEEE80211, 806b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 807b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "Configured channel (%d) not found from the " 808b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "channel list of current mode (%d) %s", 809b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt iface->conf->channel, 810b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt iface->current_mode->mode, 811b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_hw_mode_txt(iface->current_mode->mode)); 812b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 813b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 814b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt "Hardware does not support configured channel"); 815b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt} 816b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 817b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt 8184ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtint hostapd_acs_completed(struct hostapd_iface *iface, int err) 819391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt{ 8204ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt int ret = -1; 8214ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt 8224ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt if (err) 8234ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 824391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 825391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt switch (hostapd_check_chans(iface)) { 826391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_VALID: 827cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, 828cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt ACS_EVENT_COMPLETED "freq=%d channel=%d", 829cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt hostapd_hw_get_freq(iface->bss[0], 830cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel), 831cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt iface->conf->channel); 832391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt break; 833391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: 834391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); 835cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 836391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt hostapd_notify_bad_chans(iface); 8374ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 838391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 839391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt default: 840391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_ERROR, "ACS picked unusable channels"); 841cce06667447b5aec83452adb0c15100ada531095Dmitry Shmidt wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 842391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt hostapd_notify_bad_chans(iface); 8434ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 844391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 845391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 846391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt ret = hostapd_check_ht_capab(iface); 847391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (ret < 0) 8484ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt goto out; 849391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt if (ret == 1) { 850391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); 851391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 0; 852391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt } 853391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8544ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt ret = 0; 8554ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidtout: 8564ce9c87407c036fc83eb5a6044ddf976c86f53fcDmitry Shmidt return hostapd_setup_interface_complete(iface, ret); 857391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt} 858391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 859391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt 8608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/** 8618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * hostapd_select_hw_mode - Select the hardware mode 8628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iface: Pointer to interface data. 86387fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen * Returns: 0 on success, < 0 on failure 8648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * 8658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Sets up the hardware mode, channel, rates, and passive scanning 8668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * based on the configuration. 8678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */ 8688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_select_hw_mode(struct hostapd_iface *iface) 8698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 870b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt int i; 8718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->num_hw_features < 1) 8738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return -1; 8748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 875f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || 876f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211n || iface->conf->ieee80211ac) && 877f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->channel == 14) { 878f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14"); 879f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 880f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211n = 0; 881f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt iface->conf->ieee80211ac = 0; 882f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt } 883f21452aea786ac056eb01f1cbba4f553bd502747Dmitry Shmidt 8848d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->current_mode = NULL; 8858d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt for (i = 0; i < iface->num_hw_features; i++) { 8868d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt struct hostapd_hw_modes *mode = &iface->hw_features[i]; 8878d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (mode->mode == iface->conf->hw_mode) { 8888d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt iface->current_mode = mode; 8898d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt break; 8908d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8918d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 8928d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 8938d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt if (iface->current_mode == NULL) { 8948d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt wpa_printf(MSG_ERROR, "Hardware does not support configured " 8958d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "mode"); 8968d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 8978d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt HOSTAPD_LEVEL_WARNING, 8988d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt "Hardware does not support configured mode " 8991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt "(%d) (hw_mode in hostapd.conf)", 9001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (int) iface->conf->hw_mode); 90187fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return -2; 9028d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9038d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 904b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt switch (hostapd_check_chans(iface)) { 905b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt case HOSTAPD_CHAN_VALID: 906b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt return 0; 907391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ 908391c59f0632df8db1c325da1d31d479b2eedce45Dmitry Shmidt return 1; 909b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt case HOSTAPD_CHAN_INVALID: 910b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt default: 911b7b4d0ec07161a6d76c40ba7ef1306e82fbb7e15Dmitry Shmidt hostapd_notify_bad_chans(iface); 91287fd279308af3f806848c8f2ab65ef18c6ac4c30Jouni Malinen return -3; 9138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtconst char * hostapd_hw_mode_txt(int mode) 9188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 9198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt switch (mode) { 9208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211A: 9218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11a"; 9228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211B: 9238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11b"; 9248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt case HOSTAPD_MODE_IEEE80211G: 9258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "IEEE 802.11g"; 926a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt case HOSTAPD_MODE_IEEE80211AD: 927a54fa5fb807eaeff45464139b5a7759f060cec68Dmitry Shmidt return "IEEE 802.11ad"; 9288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt default: 9298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt return "UNKNOWN"; 9308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt } 9318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 9358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 936ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return hw_get_freq(hapd->iface->current_mode, chan); 9378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 9388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt 9408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 9418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{ 942ff787d557db719adea0fdf2679667500c65cf74dDmitry Shmidt return hw_get_chan(hapd->iface->current_mode, freq); 9438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt} 944