hw_features.c revision f21452aea786ac056eb01f1cbba4f553bd502747
19085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org/* 29085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * hostapd / Hardware feature query and different modes 39085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * Copyright 2002-2003, Instant802 Networks, Inc. 45ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Copyright 2005-2006, Devicescape Software, Inc. 55ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi> 65ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * 75ec4892aef9cca42940d7d92302abf674365f6b7ager@chromium.org * This software may be distributed under the terms of the BSD license. 89085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * See README for more details. 99085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "utils/includes.h" 129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "utils/common.h" 149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "utils/eloop.h" 159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "common/ieee802_11_defs.h" 169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "common/ieee802_11_common.h" 179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "common/wpa_ctrl.h" 189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "hostapd.h" 199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "ap_config.h" 209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "ap_drv_ops.h" 219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "acs.h" 229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#include "hw_features.h" 239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgvoid hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, 269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org size_t num_hw_features) 279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org size_t i; 299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (hw_features == NULL) 319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return; 329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 335d6c1f5b20195b800bc6db146920fd6f878d1fd4vegorov@chromium.org for (i = 0; i < num_hw_features; i++) { 349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org os_free(hw_features[i].channels); 359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org os_free(hw_features[i].rates); 369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org os_free(hw_features); 399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 40c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 41c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 4271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org#ifndef CONFIG_NO_STDOUT_DEBUG 4371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgstatic char * dfs_info(struct hostapd_channel_data *chan) 449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 45e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org static char info[256]; 46e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org char *state; 47e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 48e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { 4940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org case HOSTAPD_CHAN_DFS_UNKNOWN: 5040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org state = "unknown"; 51e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org break; 52e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org case HOSTAPD_CHAN_DFS_USABLE: 53e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org state = "usable"; 5440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org break; 5540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org case HOSTAPD_CHAN_DFS_UNAVAILABLE: 56b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org state = "unavailable"; 57b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org break; 58b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org case HOSTAPD_CHAN_DFS_AVAILABLE: 5940b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org state = "available"; 6040b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org break; 61b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org default: 62b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org return ""; 63b9d7da12d4486aa0a9d6660de46d977198076e77sgjesse@chromium.org } 6440b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org os_snprintf(info, sizeof(info), " (DFS state = %s)", state); 6540b9da37a45dabf86bd82a39e885f2921f47fc08fschneider@chromium.org info[sizeof(info) - 1] = '\0'; 66e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 67e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return info; 689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org#endif /* CONFIG_NO_STDOUT_DEBUG */ 709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgint hostapd_get_hw_features(struct hostapd_iface *iface) 739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct hostapd_data *hapd = iface->bss[0]; 759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int ret = 0, i, j; 769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org u16 num_modes, flags; 779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct hostapd_hw_modes *modes; 789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (hostapd_drv_none(hapd)) 809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return -1; 819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); 829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (modes == NULL) { 839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, 849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org HOSTAPD_LEVEL_DEBUG, 859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "Fetching hardware channel/rate support not " 869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "supported."); 879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return -1; 889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->hw_flags = flags; 91a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 92a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); 93a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org iface->hw_features = modes; 94a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org iface->num_hw_features = num_modes; 95a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 96a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org for (i = 0; i < num_modes; i++) { 97a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org struct hostapd_hw_modes *feature = &modes[i]; 98a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org int dfs_enabled = hapd->iconf->ieee80211h && 99a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); 100a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 101c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org /* set flag for channels we can use in current regulatory 1023a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org * domain */ 103c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org for (j = 0; j < feature->num_channels; j++) { 104c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org int dfs = 0; 105c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org 106c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org /* 1073a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org * Disable all channels that are marked not to allow 108c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org * IBSS operation or active scanning. 109c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org * Use radar channels only if the driver supports DFS. 110c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org */ 111a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if ((feature->channels[j].flag & 112a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org HOSTAPD_CHAN_RADAR) && dfs_enabled) { 113a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org dfs = 1; 114a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } else if (feature->channels[j].flag & 115a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org (HOSTAPD_CHAN_NO_IBSS | 116c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org HOSTAPD_CHAN_PASSIVE_SCAN | 117c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org HOSTAPD_CHAN_RADAR)) { 118a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org feature->channels[j].flag |= 119a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org HOSTAPD_CHAN_DISABLED; 120a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 121a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 122c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) 123c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org continue; 124a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 125a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " 126a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org "chan=%d freq=%d MHz max_tx_power=%d dBm%s", 127a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org feature->mode, 128755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org feature->channels[j].chan, 129eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org feature->channels[j].freq, 130755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org feature->channels[j].max_tx_power, 131755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org dfs ? dfs_info(&feature->channels[j]) : ""); 132a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 1334a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org } 1344a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 1359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return ret; 1369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 1379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 1384a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org 139eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgint hostapd_prepare_rates(struct hostapd_iface *iface, 1409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct hostapd_hw_modes *mode) 1419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 1425aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org int i, num_basic_rates = 0; 1435aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org int basic_rates_a[] = { 60, 120, 240, -1 }; 1445aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org int basic_rates_b[] = { 10, 20, -1 }; 1455aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org int basic_rates_g[] = { 10, 20, 55, 110, -1 }; 1465aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org int *basic_rates; 1475aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1485aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org if (iface->conf->basic_rates) 1495aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org basic_rates = iface->conf->basic_rates; 1505aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org else switch (mode->mode) { 1515aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org case HOSTAPD_MODE_IEEE80211A: 1525aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org basic_rates = basic_rates_a; 1535c838251403b0be9a882540f1922577abba4c872ager@chromium.org break; 1545c838251403b0be9a882540f1922577abba4c872ager@chromium.org case HOSTAPD_MODE_IEEE80211B: 1559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org basic_rates = basic_rates_b; 1560ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org break; 157c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org case HOSTAPD_MODE_IEEE80211G: 1583a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org basic_rates = basic_rates_g; 1593a5fd78f0ca6c2827bb05f69a373d152a9ce6ff3fschneider@chromium.org break; 1609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org case HOSTAPD_MODE_IEEE80211AD: 1619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 0; /* No basic rates for 11ad */ 162b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org default: 163b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org return -1; 164b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 165b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org 166b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org i = 0; 167b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org while (basic_rates[i] >= 0) 168b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org i++; 169b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org if (i) 170b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org i++; /* -1 termination */ 171b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org os_free(iface->basic_rates); 172b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org iface->basic_rates = os_malloc(i * sizeof(int)); 173b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org if (iface->basic_rates) 174b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); 175b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org 176b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org os_free(iface->current_rates); 177b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org iface->num_rates = 0; 178b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org 1795aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org iface->current_rates = 1805aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); 1819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (!iface->current_rates) { 182a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " 183a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org "table."); 184a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return -1; 185a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 186a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 187a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org for (i = 0; i < mode->num_rates; i++) { 188a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org struct hostapd_rate_data *rate; 189a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 190c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org if (iface->conf->supported_rates && 191c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org !hostapd_rate_found(iface->conf->supported_rates, 192c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org mode->rates[i])) 193c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org continue; 194c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org 195c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.org rate = &iface->current_rates[iface->num_rates]; 196a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org rate->rate = mode->rates[i]; 197a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (hostapd_rate_found(basic_rates, rate->rate)) { 198a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org rate->flags |= HOSTAPD_RATE_BASIC; 199a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org num_basic_rates++; 200a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 201a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", 202a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org iface->num_rates, rate->rate, rate->flags); 203a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org iface->num_rates++; 204a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 205a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 206a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if ((iface->num_rates == 0 || num_basic_rates == 0) && 207a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org (!iface->conf->ieee80211n || !iface->conf->require_ht)) { 208a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " 209a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org "rate sets (%d,%d).", 210a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org iface->num_rates, num_basic_rates); 211a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return -1; 212a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org } 213a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 214a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return 0; 215a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org} 216a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 217a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org 218a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org#ifdef CONFIG_IEEE80211N 219c6c5718277d4047fad1e034396228ce15571b5a4sgjesse@chromium.orgstatic int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) 2204a1fe7d5e92fdb673d5f05d5ddf7b1ed703ba18dwhesse@chromium.org{ 2219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int sec_chan, ok, j, first; 2229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, 2239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 184, 192 }; 2249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org size_t k; 22586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org 22686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org if (!iface->conf->secondary_channel) 22786f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org return 1; /* HT40 not used */ 22886f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org 22986f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org sec_chan = iface->conf->channel + iface->conf->secondary_channel * 4; 23086f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org wpa_printf(MSG_DEBUG, "HT40: control channel: %d " 23186f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org "secondary channel: %d", 23286f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org iface->conf->channel, sec_chan); 23386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org 23486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org /* Verify that HT40 secondary channel is an allowed 20 MHz 23586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org * channel */ 2369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ok = 0; 2379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (j = 0; j < iface->current_mode->num_channels; j++) { 2389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct hostapd_channel_data *chan = 239b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org &iface->current_mode->channels[j]; 240b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && 241b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org chan->chan == sec_chan) { 242b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org ok = 1; 243b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org break; 244b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 245b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 246b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org if (!ok) { 247b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", 248b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org sec_chan); 249b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org return 0; 250b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org } 251b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org 252b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org /* 253b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org * Verify that HT40 primary,secondary channel pair is allowed per 254b95b98b0c30bcd40b657aa45f6cd75a46a4772adfschneider@chromium.org * IEEE 802.11n Annex J. This is only needed for 5 GHz band since 2559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * 2.4 GHz rules allow all cases where the secondary channel fits into 256a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org * the list of allowed channels (already checked above). 257a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org */ 258a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) 259a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org return 1; 2609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->conf->secondary_channel > 0) 2629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org first = iface->conf->channel; 2639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else 2649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org first = sec_chan; 2659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ok = 0; 2679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (k = 0; k < ARRAY_SIZE(allowed); k++) { 2689085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (first == allowed[k]) { 2699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ok = 1; 2709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org break; 2719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 2729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 2739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (!ok) { 2749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", 2759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->channel, 2769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->secondary_channel); 2779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 0; 2789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 2799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 1; 2819d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com} 2829d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 2839d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 2849d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comstatic void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) 2859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 2869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->conf->secondary_channel > 0) { 2879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->channel += 4; 2889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->secondary_channel = -1; 2899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } else { 2909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->channel -= 4; 2919d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com iface->conf->secondary_channel = 1; 2929d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com } 2939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 2949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 2969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstatic void ieee80211n_get_pri_sec_chan(struct wpa_scan_res *bss, 2979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int *pri_chan, int *sec_chan) 2989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 2999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct ieee80211_ht_operation *oper; 3005ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org struct ieee802_11_elems elems; 3015ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org 3025ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org *pri_chan = *sec_chan = 0; 3035ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org 3049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); 3059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (elems.ht_operation && 3069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org elems.ht_operation_len >= sizeof(*oper)) { 3079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org oper = (struct ieee80211_ht_operation *) elems.ht_operation; 3089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org *pri_chan = oper->control_chan; 3099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (oper->ht_param & HT_INFO_HT_PARAM_REC_TRANS_CHNL_WIDTH) { 3109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int sec = oper->ht_param & 3119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; 3129085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) 3139085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org *sec_chan = *pri_chan + 4; 3149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) 3159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org *sec_chan = *pri_chan - 4; 3169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 3199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstatic int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, 3229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct wpa_scan_results *scan_res) 3239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 3249085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int pri_chan, sec_chan, pri_freq, sec_freq, pri_bss, sec_bss; 3259085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int bss_pri_chan, bss_sec_chan; 3269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org size_t i; 3279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int match; 3289085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3295ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org pri_chan = iface->conf->channel; 3309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_chan = iface->conf->secondary_channel * 4; 3319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_freq = hostapd_hw_get_freq(iface->bss[0], pri_chan); 3329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->conf->secondary_channel > 0) 3339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_freq = pri_freq + 20; 3349085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else 3359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_freq = pri_freq - 20; 3369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3379085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /* 3389085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * Switch PRI/SEC channels if Beacons were detected on selected SEC 3399085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * channel, but not on selected PRI channel. 3409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 3419085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_bss = sec_bss = 0; 3429085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (i = 0; i < scan_res->num; i++) { 3439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct wpa_scan_res *bss = scan_res->res[i]; 3449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (bss->freq == pri_freq) 3459085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_bss++; 3469085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else if (bss->freq == sec_freq) 3479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_bss++; 3489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (sec_bss && !pri_bss) { 3509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_INFO, "Switch own primary and secondary " 351755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "channel to get secondary channel with no Beacons " 3529085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "from other BSSes"); 3539085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ieee80211n_switch_pri_sec(iface); 354755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 3559085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /* 3579085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * Match PRI/SEC channel with any existing HT40 BSS on the same 3589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * channels that we are about to use (if already mixed order in 3599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * existing BSSes, use own preference). 3609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org */ 3619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org match = 0; 3629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (i = 0; i < scan_res->num; i++) { 3639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct wpa_scan_res *bss = scan_res->res[i]; 3643e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); 3653e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org if (pri_chan == bss_pri_chan && 3663e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org sec_chan == bss_sec_chan) { 3673e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org match = 1; 3683e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org break; 3693e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org } 3709085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 3719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (!match) { 3729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (i = 0; i < scan_res->num; i++) { 3739085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct wpa_scan_res *bss = scan_res->res[i]; 3749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ieee80211n_get_pri_sec_chan(bss, &bss_pri_chan, 3759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org &bss_sec_chan); 376eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org if (pri_chan == bss_sec_chan && 3779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_chan == bss_pri_chan) { 3789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_INFO, "Switch own primary and " 379755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "secondary channel due to BSS " 380755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "overlap with " MACSTR, 381755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org MAC2STR(bss->bssid)); 382755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org ieee80211n_switch_pri_sec(iface); 3839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org break; 3849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 385755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 386755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 387755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 3889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 1; 3899155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org} 3909155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org 3919155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org 3929155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.orgstatic int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, 3939155e252524a2bf92aecd27493feafed86702312kmillikin@chromium.org struct wpa_scan_results *scan_res) 3940ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org{ 3950ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org int pri_freq, sec_freq; 3960ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org int affected_start, affected_end; 3970ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org size_t i; 3989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 3999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 40030ce411529579186181838984710b0b0980857aaricow@chromium.org if (iface->conf->secondary_channel > 0) 4010ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org sec_freq = pri_freq + 20; 4020ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org else 4039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_freq = pri_freq - 20; 404e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org affected_start = (pri_freq + sec_freq) / 2 - 25; 4059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org affected_end = (pri_freq + sec_freq) / 2 + 25; 406755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 4079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org affected_start, affected_end); 4089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (i = 0; i < scan_res->num; i++) { 409755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org struct wpa_scan_res *bss = scan_res->res[i]; 4109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int pri = bss->freq; 4119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int sec = pri; 412755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org int sec_chan, pri_chan; 413755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 414755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org ieee80211n_get_pri_sec_chan(bss, &pri_chan, &sec_chan); 415755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 4169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (sec_chan) { 417755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (sec_chan < pri_chan) 4189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec = pri - 20; 4199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else 4209085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec = pri + 20; 4219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 4229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if ((pri < affected_start || pri > affected_end) && 4243e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org (sec < affected_start || sec > affected_end)) 4253e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org continue; /* not within affected channel range */ 4263e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 4279085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR 4283e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org " freq=%d pri=%d sec=%d", 4299085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); 4309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4319085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (sec_chan) { 4329085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (pri_freq != pri || sec_freq != sec) { 4339085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_DEBUG, "40 MHz pri/sec " 434a55512615f5adc085d23bc8589d155c4b579fb7bkasperl@chromium.org "mismatch with BSS " MACSTR 4359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org " <%d,%d> (chan=%d%c) vs. <%d,%d>", 436c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org MAC2STR(bss->bssid), 4379d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com pri, sec, pri_chan, 4389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com sec > pri ? '+' : '-', 4399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com pri_freq, sec_freq); 4409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com return 0; 4419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com } 442e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 4439085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4449085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /* TODO: 40 MHz intolerant */ 445c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org } 446e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 4479085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 1; 4489085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 4499085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4509085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstatic void ieee80211n_check_scan(struct hostapd_iface *iface) 452c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org{ 453c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org struct wpa_scan_results *scan_res; 4549085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int oper40; 455c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org int res; 4569085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 457c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is 4589085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ 4599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4609085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->scan_cb = NULL; 4619085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4629085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org scan_res = hostapd_driver_get_scan_results(iface->bss[0]); 4639085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (scan_res == NULL) { 464c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org hostapd_setup_interface_complete(iface, 1); 4659085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return; 4669085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 4679085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4683e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) 4693e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); 470c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org else 4719085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); 4729085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_scan_results_free(scan_res); 473c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 4749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (!oper40) { 4759085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " 4769085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "channel pri=%d sec=%d based on overlapping BSSes", 4779085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->channel, 4789085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->channel + 4793e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org iface->conf->secondary_channel * 4); 4803e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org iface->conf->secondary_channel = 0; 4813e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org } 4829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org res = ieee80211n_allowed_ht40_channel_pair(iface); 4843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org hostapd_setup_interface_complete(iface, !res); 4853e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org} 4863e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 4873e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 4889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgstatic void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, 4899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct wpa_driver_scan_params *params) 4909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 4919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org /* Scan only the affected frequency range */ 4929085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int pri_freq, sec_freq; 4939085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int affected_start, affected_end; 4949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int i, pos; 4959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org struct hostapd_hw_modes *mode; 4969085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 4979085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->current_mode == NULL) 4989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return; 4999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 5009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 5019085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->conf->secondary_channel > 0) 5029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_freq = pri_freq + 20; 5039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else 5049085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org sec_freq = pri_freq - 20; 5059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org affected_start = (pri_freq + sec_freq) / 2 - 25; 5069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org affected_end = (pri_freq + sec_freq) / 2 + 25; 5079085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 5089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org affected_start, affected_end); 5099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 5109085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org mode = iface->current_mode; 5119085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 512c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (params->freqs == NULL) 513c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org return; 514c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org pos = 0; 515c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 516c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org for (i = 0; i < mode->num_channels; i++) { 517c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org struct hostapd_channel_data *chan = &mode->channels[i]; 518c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (chan->flag & HOSTAPD_CHAN_DISABLED) 519e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org continue; 520e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if (chan->freq < affected_start || 521c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org chan->freq > affected_end) 5223811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org continue; 523c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org params->freqs[pos++] = chan->freq; 5243811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 5253811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org} 5263811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org 5273811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org 528c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.orgstatic void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, 529c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org struct wpa_driver_scan_params *params) 530c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org{ 531c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org /* Scan only the affected frequency range */ 532c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org int pri_freq; 533c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org int affected_start, affected_end; 534c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org int i, pos; 535c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org struct hostapd_hw_modes *mode; 536c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 5373811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org if (iface->current_mode == NULL) 538c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org return; 539c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 5409085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); 541c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (iface->conf->secondary_channel > 0) { 542c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org affected_start = pri_freq - 10; 543c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org affected_end = pri_freq + 30; 544c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org } else { 545c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org affected_start = pri_freq - 30; 546c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org affected_end = pri_freq + 10; 547c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org } 5482356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", 5492356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org affected_start, affected_end); 5502356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org 5512356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org mode = iface->current_mode; 5522356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); 553c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (params->freqs == NULL) 554c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org return; 555ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org pos = 0; 55683aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 55783aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org for (i = 0; i < mode->num_channels; i++) { 55883aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org struct hostapd_channel_data *chan = &mode->channels[i]; 559ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org if (chan->flag & HOSTAPD_CHAN_DISABLED) 560ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org continue; 56183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org if (chan->freq < affected_start || 562ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org chan->freq > affected_end) 5632356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org continue; 5642356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org params->freqs[pos++] = chan->freq; 5652356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org } 5665d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org} 5675d00b60c201d860c74821f553fdc34f4e057b411lrn@chromium.org 568d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com 569d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.comstatic int ieee80211n_check_40mhz(struct hostapd_iface *iface) 570496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org{ 571496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org struct wpa_driver_scan_params params; 572496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org 573496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org if (!iface->conf->secondary_channel) 574496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org return 0; /* HT40 not used */ 575496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org 576496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); 577496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " 578496c03a64f12710e837204e261ef155601247895sgjesse@chromium.org "40 MHz channel"); 5792356e6fbe66ac3aa027b61cb43a3c3619b3c3a5evegorov@chromium.org os_memset(¶ms, 0, sizeof(params)); 5809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) 5819085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org ieee80211n_scan_channels_2g4(iface, ¶ms); 5829085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org else 58371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org ieee80211n_scan_channels_5g(iface, ¶ms); 58471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org if (hostapd_driver_scan(iface->bss[0], ¶ms) < 0) { 58571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org wpa_printf(MSG_ERROR, "Failed to request a scan of " 58671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org "neighboring BSSes"); 58771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org os_free(params.freqs); 588eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org return -1; 589eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org } 59071affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org os_free(params.freqs); 59171affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 59271affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org iface->scan_cb = ieee80211n_check_scan; 59371affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org return 1; 59471affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org} 59571affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 59671affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.org 59771affb54842da76b24f0bb3184e9f0960523f89dkasperl@chromium.orgstatic int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) 5989085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 5999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org u16 hw = iface->current_mode->ht_capab; 6009085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org u16 conf = iface->conf->ht_capab; 60183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org 6029085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && 6035ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { 6045ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 6059085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "HT capability [LDPC]"); 6069085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 0; 607e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 608e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 6099085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if ((conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && 610e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { 6110ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 6120ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org "HT capability [HT40*]"); 6130ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org return 0; 6149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 6159085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 6169085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if ((conf & HT_CAP_INFO_SMPS_MASK) != (hw & HT_CAP_INFO_SMPS_MASK) && 6179085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org (conf & HT_CAP_INFO_SMPS_MASK) != HT_CAP_INFO_SMPS_DISABLED) { 6189085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 6199085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "HT capability [SMPS-*]"); 620e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return 0; 6219085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 6229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 6239085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if ((conf & HT_CAP_INFO_GREEN_FIELD) && 624755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org !(hw & HT_CAP_INFO_GREEN_FIELD)) { 625e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 626755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "HT capability [GF]"); 627755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 6283811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 6293811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org 6303811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && 6313811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { 632e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 633e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org "HT capability [SHORT-GI-20]"); 634e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return 0; 635eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org } 636e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 637e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && 638e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { 639911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 640911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org "HT capability [SHORT-GI-40]"); 641911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org return 0; 642755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 643911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org 644e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { 645e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 646911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org "HT capability [TX-STBC]"); 647911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org return 0; 648911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org } 649e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 650eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org if ((conf & HT_CAP_INFO_RX_STBC_MASK) > 651eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org (hw & HT_CAP_INFO_RX_STBC_MASK)) { 652755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 653755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "HT capability [RX-STBC*]"); 654755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 655755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 656755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 657e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if ((conf & HT_CAP_INFO_DELAYED_BA) && 658e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org !(hw & HT_CAP_INFO_DELAYED_BA)) { 659755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 660755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "HT capability [DELAYED-BA]"); 6613811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org return 0; 6623811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org } 6635aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 6643e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && 6655aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { 6665a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com wpa_printf(MSG_ERROR, "Driver does not support configured " 6673811b436bf328d2ace6fe79ce99aeda71f9f06d3ager@chromium.org "HT capability [MAX-AMSDU-7935]"); 6685a6af92a1549c81fb61855518f43b712e4c0e469christian.plesner.hansen@gmail.com return 0; 6695aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org } 670b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org 671b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && 672b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { 673b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 674b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org "HT capability [DSSS_CCK-40]"); 675b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org return 0; 676b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org } 677755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 678755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if ((conf & HT_CAP_INFO_PSMP_SUPP) && !(hw & HT_CAP_INFO_PSMP_SUPP)) { 679e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 6809085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "HT capability [PSMP]"); 6813e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org return 0; 6823e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org } 6833e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 6843e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && 6853e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { 6869085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured " 6879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "HT capability [LSIG-TXOP-PROT]"); 6889085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return 0; 6899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 6909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 6915aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org return 1; 6929dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com} 6935aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 6945aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 6953e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org#ifdef CONFIG_IEEE80211AC 6963e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 6973e87580939cb78c5802369f723680d4a16cc2902ager@chromium.orgstatic int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name) 6983e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org{ 699e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org u32 req_cap = conf & cap; 700e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 701e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org /* 702e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org * Make sure we support all requested capabilities. 70386f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org * NOTE: We assume that 'cap' represents a capability mask, 70486f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org * not a discrete value. 70586f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org */ 70686f77b7fe492ed2bdfbf4e1147dab2f09c7d7003kasperl@chromium.org if ((hw & req_cap) != req_cap) { 707e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org wpa_printf(MSG_ERROR, "Driver does not support configured VHT capability [%s]", 708755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org name); 709755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 710755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 711e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org return 1; 712e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org} 713e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 714755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 715eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.orgstatic int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 cap, 716755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org const char *name) 717755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org{ 718755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org u32 hw_max = hw & cap; 719eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org u32 conf_val = conf & cap; 720755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 721755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (conf_val > hw_max) { 7229085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int offset = find_first_bit(cap); 723eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)", 724755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org name, conf_val >> offset, hw_max >> offset); 725755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 726755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 727dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org return 1; 7289dfbea4c7d423c7bc1db94425cb78e7f7cf41f78erik.corry@gmail.com} 729dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org 730dff694e8cc18aa9640e92962de2699b9d07a7690vegorov@chromium.org 7310a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.orgstatic int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) 7320a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org{ 7330a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org u32 hw = iface->current_mode->vht_capab; 7340a4e901cdfb5505a896d30aa8c2e04fce0fbe069vegorov@chromium.org u32 conf = iface->conf->vht_capab; 7353e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 7363e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", 7373e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org hw, conf); 7383e87580939cb78c5802369f723680d4a16cc2902ager@chromium.org 739911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org#define VHT_CAP_CHECK(cap) \ 740911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org do { \ 741911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \ 742911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org return 0; \ 743911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org } while (0) 744911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org 745911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org#define VHT_CAP_CHECK_MAX(cap) \ 746911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org do { \ 747911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org if (!ieee80211ac_cap_check_max(hw, conf, cap, #cap)) \ 748911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org return 0; \ 749911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org } while (0) 750911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org 751911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK); 752911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ); 753eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); 754eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org VHT_CAP_CHECK(VHT_CAP_RXLDPC); 755eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80); 756eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160); 757911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_TXSTBC); 758911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK); 759911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE); 760911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE); 761911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX); 762911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX); 763911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE); 764911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE); 765911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS); 766911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_HTC_VHT); 767911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT); 768911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB); 769911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); 770911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); 771911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); 772911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org 773911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org#undef VHT_CAP_CHECK 774911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org#undef VHT_CAP_CHECK_MAX 775911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org 776911335cff40a2630bbe1dfb77b1897be991241bfsgjesse@chromium.org return 1; 77768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org} 77868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#endif /* CONFIG_IEEE80211AC */ 77968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org 78068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#endif /* CONFIG_IEEE80211N */ 78168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org 782e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 78368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.orgint hostapd_check_ht_capab(struct hostapd_iface *iface) 78468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org{ 78568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#ifdef CONFIG_IEEE80211N 786e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org int ret; 78768ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org if (!iface->conf->ieee80211n) 78868ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org return 0; 78968ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org if (!ieee80211n_supported_ht_capab(iface)) 79068ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org return -1; 79168ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#ifdef CONFIG_IEEE80211AC 79268ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org if (!ieee80211ac_supported_vht_capab(iface)) 79368ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org return -1; 79468ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org#endif /* CONFIG_IEEE80211AC */ 79568ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org ret = ieee80211n_check_40mhz(iface); 79668ac009f55a85e6891742d58914eaf717f667b26kasperl@chromium.org if (ret) 797eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org return ret; 798755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (!ieee80211n_allowed_ht40_channel_pair(iface)) 799755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return -1; 800755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org#endif /* CONFIG_IEEE80211N */ 801eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 802755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 803755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org} 804755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 805eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 806755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgstatic int hostapd_is_usable_chan(struct hostapd_iface *iface, 807755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org int channel, int primary) 8089085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 809eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org int i; 810755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org struct hostapd_channel_data *chan; 811755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 812755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org for (i = 0; i < iface->current_mode->num_channels; i++) { 813eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org chan = &iface->current_mode->channels[i]; 814755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (chan->chan != channel) 815755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org continue; 816755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 817755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) 818755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 1; 819755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 820755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_printf(MSG_DEBUG, 821755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s%s", 822755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org primary ? "" : "Configured HT40 secondary ", 823755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org i, chan->chan, chan->flag, 824755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org chan->flag & HOSTAPD_CHAN_NO_IBSS ? " NO-IBSS" : "", 825755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org chan->flag & HOSTAPD_CHAN_PASSIVE_SCAN ? 826755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org " PASSIVE-SCAN" : "", 827755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); 828755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 829755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 830755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 831755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org} 832755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 833755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 834755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgstatic int hostapd_is_usable_chans(struct hostapd_iface *iface) 835755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org{ 8369085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) 837c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org return 0; 838c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org 839c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org if (!iface->conf->secondary_channel) 840c514574143c1bf74d4fb6e7dccb175fe9ff2f5d3sgjesse@chromium.org return 1; 8419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 8429d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com return hostapd_is_usable_chan(iface, iface->conf->channel + 8439d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com iface->conf->secondary_channel * 4, 0); 8449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com} 8450ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org 8460ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.org 8470ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orgstatic enum hostapd_chan_status 8480ee099beef2c2b38743d657b84a30b626d9178ecager@chromium.orghostapd_check_chans(struct hostapd_iface *iface) 849b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org{ 850b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (iface->conf->channel) { 851b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org if (hostapd_is_usable_chans(iface)) 8529d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com return HOSTAPD_CHAN_VALID; 853eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org else 854eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org return HOSTAPD_CHAN_INVALID; 855e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org } 856eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 8579d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com /* 8589d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * The user set channel=0 or channel=acs_survey 8599085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * which is used to trigger ACS. 860e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org */ 861e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 8620b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org switch (acs_init(iface)) { 8630b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org case HOSTAPD_CHAN_ACS: 8649085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return HOSTAPD_CHAN_ACS; 865e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org case HOSTAPD_CHAN_VALID: 8660b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org case HOSTAPD_CHAN_INVALID: 8670b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org default: 8680b6db5975a9d1ebcf3de7b18603380d99f789e66sgjesse@chromium.org return HOSTAPD_CHAN_INVALID; 8699085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 8702abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org} 8712abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org 8722abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org 8732abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.orgstatic void hostapd_notify_bad_chans(struct hostapd_iface *iface) 8742abc450936e88b5c98a5e9d43ee6230ccc748272kasperl@chromium.org{ 875cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org hostapd_logger(iface->bss[0], NULL, 876cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org HOSTAPD_MODULE_IEEE80211, 877d91075f76b836c2cfa4f4e4cc0fb31170df864ccerik.corry@gmail.com HOSTAPD_LEVEL_WARNING, 878cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org "Configured channel (%d) not found from the " 8799085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "channel list of current mode (%d) %s", 880eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org iface->conf->channel, 881eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org iface->current_mode->mode, 8825ad5acef6bd4ebc785f946d8bcc2a88b1e031827ricow@chromium.org hostapd_hw_mode_txt(iface->current_mode->mode)); 883eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 8849085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org HOSTAPD_LEVEL_WARNING, 8859085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org "Hardware does not support configured channel"); 886cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org} 8879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 888e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 8899085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.orgint hostapd_acs_completed(struct hostapd_iface *iface, int err) 8909085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 8919085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org int ret = -1; 892755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 8934af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org if (err) 8949085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org goto out; 8959085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 896755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org switch (hostapd_check_chans(iface)) { 897cec079d8ed1f0920a0ea3dc9a3e81966013287c1whesse@chromium.org case HOSTAPD_CHAN_VALID: 898755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, 899755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org ACS_EVENT_COMPLETED "freq=%d channel=%d", 900755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org hostapd_hw_get_freq(iface->bss[0], 901755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org iface->conf->channel), 902755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org iface->conf->channel); 9034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org break; 9044af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org case HOSTAPD_CHAN_ACS: 9054af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); 9064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 907755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org hostapd_notify_bad_chans(iface); 908755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org goto out; 909755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org case HOSTAPD_CHAN_INVALID: 910755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org default: 91183aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org wpa_printf(MSG_ERROR, "ACS picked unusable channels"); 91283aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); 91383aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org hostapd_notify_bad_chans(iface); 91483aa54905e559090bea7771b83f188762cfcf082ricow@chromium.org goto out; 915755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org } 916755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 917755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org ret = hostapd_check_ht_capab(iface); 918755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (ret < 0) 919755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org goto out; 920755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (ret == 1) { 921755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); 922755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 9239d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com } 9249d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 9259d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com ret = 0; 9269d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comout: 927755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return hostapd_setup_interface_complete(iface, ret); 928755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org} 929755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 9309085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 9319d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com/** 9329d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * hostapd_select_hw_mode - Select the hardware mode 9339d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * @iface: Pointer to interface data. 9349d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * Returns: 0 on success, < 0 on failure 9359085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org * 9369d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * Sets up the hardware mode, channel, rates, and passive scanning 9379d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com * based on the configuration. 9389d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com */ 9399d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.comint hostapd_select_hw_mode(struct hostapd_iface *iface) 9409d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com{ 9419d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com int i; 9429d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 9439d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com if (iface->num_hw_features < 1) 9449d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com return -1; 9459d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com 9469d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || 9479d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com iface->conf->ieee80211n || iface->conf->ieee80211ac) && 9489d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com iface->conf->channel == 14) { 9499d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14"); 9509d58c2b1c27d8b2890b9bd46e57d3842b09e0292christian.plesner.hansen@gmail.com iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; 9519085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org iface->conf->ieee80211n = 0; 952e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org iface->conf->ieee80211ac = 0; 953e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 954e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 955e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org iface->current_mode = NULL; 956e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org for (i = 0; i < iface->num_hw_features; i++) { 957e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org struct hostapd_hw_modes *mode = &iface->hw_features[i]; 958e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org if (mode->mode == iface->conf->hw_mode) { 959e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org iface->current_mode = mode; 960e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org break; 961e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 962e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 963e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 964defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org if (iface->current_mode == NULL) { 965defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org wpa_printf(MSG_ERROR, "Hardware does not support configured " 966defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org "mode"); 967defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, 968defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org HOSTAPD_LEVEL_WARNING, 969defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org "Hardware does not support configured mode " 970e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org "(%d) (hw_mode in hostapd.conf)", 971c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org (int) iface->conf->hw_mode); 972e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return -2; 973e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org } 9749085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org 975defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org switch (hostapd_check_chans(iface)) { 976c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org case HOSTAPD_CHAN_VALID: 977defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org return 0; 978defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ 979defbd109bb9bd556bb8ece103c3b340d3552155ekasperl@chromium.org return 1; 980e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org case HOSTAPD_CHAN_INVALID: 981e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org default: 982e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org hostapd_notify_bad_chans(iface); 9839085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org return -3; 984c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org } 985e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 986e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return 0; 9879085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org} 988c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org 9895aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 9905aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgconst char * hostapd_hw_mode_txt(int mode) 9915aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org{ 992e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org switch (mode) { 993e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org case HOSTAPD_MODE_IEEE80211A: 994e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org return "IEEE 802.11a"; 995e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org case HOSTAPD_MODE_IEEE80211B: 996e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return "IEEE 802.11b"; 997e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org case HOSTAPD_MODE_IEEE80211G: 998e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return "IEEE 802.11g"; 9999085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org case HOSTAPD_MODE_IEEE80211AD: 1000c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org return "IEEE 802.11ad"; 1001e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org default: 1002e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return "UNKNOWN"; 10039085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org } 1004c4c927273ae2b690c4a015b4640a2a469c9a1a69ager@chromium.org} 10055aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 10065aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 10075aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.orgint hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) 1008e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org{ 1009e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org int i; 1010e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org 1011e959c18cf7193e2f021245584a3c8f1f32f82c92kasperl@chromium.org if (!hapd->iface->current_mode) 1012e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org return 0; 1013e2902be65446e26fd63a3b4eab2f14257cf4ebafager@chromium.org 10149085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 1015eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org struct hostapd_channel_data *ch = 1016755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org &hapd->iface->current_mode->channels[i]; 1017755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (ch->chan == chan) 1018755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return ch->freq; 1019eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org } 1020755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 1021755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 1022755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org} 1023eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 1024755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 1025755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.orgint hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) 10269085a016223a6b72bf580d5781c93ec7b9e54422ager@chromium.org{ 1027eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org int i; 1028755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org 1029755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org if (!hapd->iface->current_mode) 1030755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org return 0; 1031eadaf2282ee421d7a63a21d71369b029105341ccager@chromium.org 1032755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org for (i = 0; i < hapd->iface->current_mode->num_channels; i++) { 1033755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org struct hostapd_channel_data *ch = 1034755c5b1cc880bc54405d2652f934a941e8fcda4asgjesse@chromium.org &hapd->iface->current_mode->channels[i]; 10355aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org if (ch->freq == freq) 10365aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org return ch->chan; 10375aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org } 10385aa501ca9fb4dfb30f4191aac135202fe8d80e4aager@chromium.org 1039b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org return 0; 1040b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org} 1041b302e56e5b70c4504faa2adf4ec3efb64a9d3e38sgjesse@chromium.org