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#include "dot11d.h" 20 21struct channel_list { 22 u8 Channel[32]; 23 u8 Len; 24}; 25 26static struct channel_list ChannelPlan[] = { 27 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 28 149, 153, 157, 161, 165}, 24}, 29 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, 30 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 31 60, 64}, 21}, 32 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 33 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 34 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 35 56, 60, 64}, 22}, 36 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 37 56, 60, 64}, 22}, 38 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 39 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 40 56, 60, 64}, 22}, 41 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 42 56, 60, 64}, 22}, 43 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, 44 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 45 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 46 56, 60, 64}, 21} 47}; 48 49void dot11d_init(struct rtllib_device *ieee) 50{ 51 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 52 53 pDot11dInfo->bEnabled = false; 54 55 pDot11dInfo->State = DOT11D_STATE_NONE; 56 pDot11dInfo->CountryIeLen = 0; 57 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 58 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 59 RESET_CIE_WATCHDOG(ieee); 60 61} 62EXPORT_SYMBOL(dot11d_init); 63 64void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) 65{ 66 int i, max_chan = 14, min_chan = 1; 67 68 ieee->bGlobalDomain = false; 69 70 if (ChannelPlan[channel_plan].Len != 0) { 71 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, 72 sizeof(GET_DOT11D_INFO(ieee)->channel_map)); 73 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { 74 if (ChannelPlan[channel_plan].Channel[i] < min_chan || 75 ChannelPlan[channel_plan].Channel[i] > max_chan) 76 break; 77 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan 78 [channel_plan].Channel[i]] = 1; 79 } 80 } 81 82 switch (channel_plan) { 83 case COUNTRY_CODE_GLOBAL_DOMAIN: 84 ieee->bGlobalDomain = true; 85 for (i = 12; i <= 14; i++) 86 GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 87 ieee->IbssStartChnl = 10; 88 ieee->ibss_maxjoin_chal = 11; 89 break; 90 91 case COUNTRY_CODE_WORLD_WIDE_13: 92 for (i = 12; i <= 13; i++) 93 GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 94 ieee->IbssStartChnl = 10; 95 ieee->ibss_maxjoin_chal = 11; 96 break; 97 98 default: 99 ieee->IbssStartChnl = 1; 100 ieee->ibss_maxjoin_chal = 14; 101 break; 102 } 103} 104EXPORT_SYMBOL(Dot11d_Channelmap); 105 106 107void Dot11d_Reset(struct rtllib_device *ieee) 108{ 109 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 110 u32 i; 111 112 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 113 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 114 for (i = 1; i <= 11; i++) 115 (pDot11dInfo->channel_map)[i] = 1; 116 for (i = 12; i <= 14; i++) 117 (pDot11dInfo->channel_map)[i] = 2; 118 pDot11dInfo->State = DOT11D_STATE_NONE; 119 pDot11dInfo->CountryIeLen = 0; 120 RESET_CIE_WATCHDOG(ieee); 121} 122 123void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, 124 u16 CoutryIeLen, u8 *pCoutryIe) 125{ 126 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 127 u8 i, j, NumTriples, MaxChnlNum; 128 struct chnl_txpow_triple *pTriple; 129 130 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 131 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 132 MaxChnlNum = 0; 133 NumTriples = (CoutryIeLen - 3) / 3; 134 pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); 135 for (i = 0; i < NumTriples; i++) { 136 if (MaxChnlNum >= pTriple->FirstChnl) { 137 netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n"); 138 return; 139 } 140 if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + 141 pTriple->NumChnls)) { 142 netdev_info(dev->dev, "Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n"); 143 return; 144 } 145 146 for (j = 0; j < pTriple->NumChnls; j++) { 147 pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; 148 pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = 149 pTriple->MaxTxPowerInDbm; 150 MaxChnlNum = pTriple->FirstChnl + j; 151 } 152 153 pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3); 154 } 155 156 UPDATE_CIE_SRC(dev, pTaddr); 157 158 pDot11dInfo->CountryIeLen = CoutryIeLen; 159 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen); 160 pDot11dInfo->State = DOT11D_STATE_LEARNED; 161} 162 163u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel) 164{ 165 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 166 u8 MaxTxPwrInDbm = 255; 167 168 if (MAX_CHANNEL_NUMBER < Channel) { 169 netdev_info(dev->dev, "DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n"); 170 return MaxTxPwrInDbm; 171 } 172 if (pDot11dInfo->channel_map[Channel]) 173 MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; 174 175 return MaxTxPwrInDbm; 176} 177 178void DOT11D_ScanComplete(struct rtllib_device *dev) 179{ 180 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 181 182 switch (pDot11dInfo->State) { 183 case DOT11D_STATE_LEARNED: 184 pDot11dInfo->State = DOT11D_STATE_DONE; 185 break; 186 case DOT11D_STATE_DONE: 187 Dot11d_Reset(dev); 188 break; 189 case DOT11D_STATE_NONE: 190 break; 191 } 192} 193 194int ToLegalChannel(struct rtllib_device *dev, u8 channel) 195{ 196 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 197 u8 default_chn = 0; 198 u32 i; 199 200 for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) { 201 if (pDot11dInfo->channel_map[i] > 0) { 202 default_chn = i; 203 break; 204 } 205 } 206 207 if (MAX_CHANNEL_NUMBER < channel) { 208 netdev_err(dev->dev, "%s(): Invalid Channel\n", __func__); 209 return default_chn; 210 } 211 212 if (pDot11dInfo->channel_map[channel] > 0) 213 return channel; 214 215 return default_chn; 216} 217