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