1//----------------------------------------------------------------------------- 2// File: 3// Dot11d.c 4// 5// Description: 6// Implement 802.11d. 7// 8//----------------------------------------------------------------------------- 9 10#include "dot11d.h" 11 12void 13Dot11d_Init(struct ieee80211_device *ieee) 14{ 15 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); 16 17 pDot11dInfo->bEnabled = 0; 18 19 pDot11dInfo->State = DOT11D_STATE_NONE; 20 pDot11dInfo->CountryIeLen = 0; 21 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 22 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 23 RESET_CIE_WATCHDOG(ieee); 24 25 printk("Dot11d_Init()\n"); 26} 27 28// 29// Description: 30// Reset to the state as we are just entering a regulatory domain. 31// 32void 33Dot11d_Reset(struct ieee80211_device *ieee) 34{ 35 u32 i; 36 PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee); 37 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 if((CoutryIeLen - 3)%3 != 0) 81 { 82 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); 83 Dot11d_Reset(dev); 84 return; 85 } 86 87 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 88 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 89 MaxChnlNum = 0; 90 NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string. 91 pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3); 92 for(i = 0; i < NumTriples; i++) 93 { 94 if(MaxChnlNum >= pTriple->FirstChnl) 95 { // It is not in a monotonically increasing order, so stop processing. 96 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); 97 Dot11d_Reset(dev); 98 return; 99 } 100 if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls)) 101 { // It is not a valid set of channel id, so stop processing. 102 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); 103 Dot11d_Reset(dev); 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("Dot11d_UpdateCountryIe(): Channel List:\n"); 117 printk("Channel List:"); 118 for(i=1; i<= MAX_CHANNEL_NUMBER; i++) 119 if(pDot11dInfo->channel_map[i] > 0) 120 printk(" %d", i); 121 printk("\n"); 122 123 UPDATE_CIE_SRC(dev, pTaddr); 124 125 pDot11dInfo->CountryIeLen = CoutryIeLen; 126 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen); 127 pDot11dInfo->State = DOT11D_STATE_LEARNED; 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