1/****************************************************************************** 2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. 3 * 4 * This program is distributed in the hope that it will be useful, but WITHOUT 5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 7 * more details. 8 * 9 * You should have received a copy of the GNU General Public License along with 10 * this program; if not, write to the Free Software Foundation, Inc., 11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 12 * 13 * The full GNU General Public License is included in this distribution in the 14 * file called LICENSE. 15 * 16 * Contact Information: 17 * wlanfae <wlanfae@realtek.com> 18******************************************************************************/ 19 20#include "dot11d.h" 21 22void 23Dot11d_Init(struct ieee80211_device *ieee) 24{ 25 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); 26 27 pDot11dInfo->bEnabled = 0; 28 29 pDot11dInfo->State = DOT11D_STATE_NONE; 30 pDot11dInfo->CountryIeLen = 0; 31 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 32 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 33 RESET_CIE_WATCHDOG(ieee); 34 35 printk("Dot11d_Init()\n"); 36} 37 38// 39// Description: 40// Reset to the state as we are just entering a regulatory domain. 41// 42void 43Dot11d_Reset(struct ieee80211_device *ieee) 44{ 45 u32 i; 46 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); 47 48 // Clear old channel map 49 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 50 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 51 // Set new channel map 52 for (i=1; i<=11; i++) { 53 (pDot11dInfo->channel_map)[i] = 1; 54 } 55 for (i=12; i<=14; i++) { 56 (pDot11dInfo->channel_map)[i] = 2; 57 } 58 59 pDot11dInfo->State = DOT11D_STATE_NONE; 60 pDot11dInfo->CountryIeLen = 0; 61 RESET_CIE_WATCHDOG(ieee); 62 63} 64 65// 66// Description: 67// Update country IE from Beacon or Probe Resopnse 68// and configure PHY for operation in the regulatory domain. 69// 70// TODO: 71// Configure Tx power. 72// 73// Assumption: 74// 1. IS_DOT11D_ENABLE() is TRUE. 75// 2. Input IE is an valid one. 76// 77void 78Dot11d_UpdateCountryIe( 79 struct ieee80211_device *dev, 80 u8 * pTaddr, 81 u16 CoutryIeLen, 82 u8 * pCoutryIe 83 ) 84{ 85 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); 86 u8 i, j, NumTriples, MaxChnlNum; 87 PCHNL_TXPOWER_TRIPLE pTriple; 88 89 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 90 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 91 MaxChnlNum = 0; 92 NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. 93 pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); 94 for(i = 0; i < NumTriples; i++) 95 { 96 if(MaxChnlNum >= pTriple->FirstChnl) 97 { // It is not in a monotonically increasing order, so stop processing. 98 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); 99 return; 100 } 101 if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) 102 { // It is not a valid set of channel id, so stop processing. 103 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); 104 return; 105 } 106 107 for(j = 0 ; j < pTriple->NumChnls; j++) 108 { 109 pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; 110 pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm; 111 MaxChnlNum = pTriple->FirstChnl + j; 112 } 113 114 pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3); 115 } 116 printk("Channel List:"); 117 for(i=1; i<= MAX_CHANNEL_NUMBER; i++) 118 if(pDot11dInfo->channel_map[i] > 0) 119 printk(" %d", i); 120 printk("\n"); 121 122 UPDATE_CIE_SRC(dev, pTaddr); 123 124 pDot11dInfo->CountryIeLen = CoutryIeLen; 125 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); 126 pDot11dInfo->State = DOT11D_STATE_LEARNED; 127} 128 129 130u8 131DOT11D_GetMaxTxPwrInDbm( 132 struct ieee80211_device *dev, 133 u8 Channel 134 ) 135{ 136 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); 137 u8 MaxTxPwrInDbm = 255; 138 139 if(MAX_CHANNEL_NUMBER < Channel) 140 { 141 printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); 142 return MaxTxPwrInDbm; 143 } 144 if(pDot11dInfo->channel_map[Channel]) 145 { 146 MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; 147 } 148 149 return MaxTxPwrInDbm; 150} 151 152 153void 154DOT11D_ScanComplete( 155 struct ieee80211_device * dev 156 ) 157{ 158 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); 159 160 switch(pDot11dInfo->State) 161 { 162 case DOT11D_STATE_LEARNED: 163 pDot11dInfo->State = DOT11D_STATE_DONE; 164 break; 165 166 case DOT11D_STATE_DONE: 167 if( GET_CIE_WATCHDOG(dev) == 0 ) 168 { // Reset country IE if previous one is gone. 169 Dot11d_Reset(dev); 170 } 171 break; 172 case DOT11D_STATE_NONE: 173 break; 174 } 175} 176 177int IsLegalChannel( 178 struct ieee80211_device * dev, 179 u8 channel 180) 181{ 182 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); 183 184 if(MAX_CHANNEL_NUMBER < channel) 185 { 186 printk("IsLegalChannel(): Invalid Channel\n"); 187 return 0; 188 } 189 if(pDot11dInfo->channel_map[channel] > 0) 190 return 1; 191 return 0; 192} 193 194int ToLegalChannel( 195 struct ieee80211_device * dev, 196 u8 channel 197) 198{ 199 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev); 200 u8 default_chn = 0; 201 u32 i = 0; 202 203 for (i=1; i<= MAX_CHANNEL_NUMBER; i++) 204 { 205 if(pDot11dInfo->channel_map[i] > 0) 206 { 207 default_chn = i; 208 break; 209 } 210 } 211 212 if(MAX_CHANNEL_NUMBER < channel) 213 { 214 printk("IsLegalChannel(): Invalid Channel\n"); 215 return default_chn; 216 } 217 218 if(pDot11dInfo->channel_map[channel] > 0) 219 return channel; 220 221 return default_chn; 222} 223