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 * The full GNU General Public License is included in this distribution in the 10 * file called LICENSE. 11 * 12 * Contact Information: 13 * wlanfae <wlanfae@realtek.com> 14 ******************************************************************************/ 15 #include "dot11d.h" 16 17 struct channel_list { 18 u8 Channel[32]; 19 u8 Len; 20 }; 21 22 static struct channel_list ChannelPlan[] = { 23 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 24 149, 153, 157, 161, 165}, 24}, 25 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, 26 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 27 60, 64}, 21}, 28 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 29 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 30 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 31 56, 60, 64}, 22}, 32 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 33 56, 60, 64}, 22}, 34 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 35 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 36 56, 60, 64}, 22}, 37 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 38 56, 60, 64}, 22}, 39 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, 40 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 41 {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 42 56, 60, 64}, 21} 43 }; 44 45 void dot11d_init(struct rtllib_device *ieee) 46 { 47 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 48 49 pDot11dInfo->bEnabled = false; 50 51 pDot11dInfo->State = DOT11D_STATE_NONE; 52 pDot11dInfo->CountryIeLen = 0; 53 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 54 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); 55 RESET_CIE_WATCHDOG(ieee); 56 } 57 EXPORT_SYMBOL(dot11d_init); 58 59 void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) 60 { 61 int i, max_chan = 14, min_chan = 1; 62 63 ieee->bGlobalDomain = false; 64 65 if (ChannelPlan[channel_plan].Len != 0) { 66 memset(GET_DOT11D_INFO(ieee)->channel_map, 0, 67 sizeof(GET_DOT11D_INFO(ieee)->channel_map)); 68 for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { 69 if (ChannelPlan[channel_plan].Channel[i] < min_chan || 70 ChannelPlan[channel_plan].Channel[i] > max_chan) 71 break; 72 GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan 73 [channel_plan].Channel[i]] = 1; 74 } 75 } 76 77 switch (channel_plan) { 78 case COUNTRY_CODE_GLOBAL_DOMAIN: 79 ieee->bGlobalDomain = true; 80 for (i = 12; i <= 14; i++) 81 GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 82 ieee->IbssStartChnl = 10; 83 ieee->ibss_maxjoin_chal = 11; 84 break; 85 86 case COUNTRY_CODE_WORLD_WIDE_13: 87 for (i = 12; i <= 13; i++) 88 GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 89 ieee->IbssStartChnl = 10; 90 ieee->ibss_maxjoin_chal = 11; 91 break; 92 93 default: 94 ieee->IbssStartChnl = 1; 95 ieee->ibss_maxjoin_chal = 14; 96 break; 97 } 98 } 99 EXPORT_SYMBOL(Dot11d_Channelmap); 100 101 void Dot11d_Reset(struct rtllib_device *ieee) 102 { 103 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 104 u32 i; 105 106 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); 107 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); 108 for (i = 1; i <= 11; i++) 109 (pDot11dInfo->channel_map)[i] = 1; 110 for (i = 12; i <= 14; i++) 111 (pDot11dInfo->channel_map)[i] = 2; 112 pDot11dInfo->State = DOT11D_STATE_NONE; 113 pDot11dInfo->CountryIeLen = 0; 114 RESET_CIE_WATCHDOG(ieee); 115 } 116 117 void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, 118 u16 CoutryIeLen, u8 *pCoutryIe) 119 { 120 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 121 u8 i, j, NumTriples, MaxChnlNum; 122 struct chnl_txpow_triple *pTriple; 123 124 memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER + 1); 125 memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER + 1); 126 MaxChnlNum = 0; 127 NumTriples = (CoutryIeLen - 3) / 3; 128 pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); 129 for (i = 0; i < NumTriples; i++) { 130 if (MaxChnlNum >= pTriple->FirstChnl) { 131 netdev_info(dev->dev, 132 "%s: Invalid country IE, skip it......1\n", 133 __func__); 134 return; 135 } 136 if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + 137 pTriple->NumChnls)) { 138 netdev_info(dev->dev, 139 "%s: Invalid country IE, skip it......2\n", 140 __func__); 141 return; 142 } 143 144 for (j = 0; j < pTriple->NumChnls; j++) { 145 pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; 146 pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = 147 pTriple->MaxTxPowerInDbm; 148 MaxChnlNum = pTriple->FirstChnl + j; 149 } 150 151 pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3); 152 } 153 154 UPDATE_CIE_SRC(dev, pTaddr); 155 156 pDot11dInfo->CountryIeLen = CoutryIeLen; 157 memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen); 158 pDot11dInfo->State = DOT11D_STATE_LEARNED; 159 } 160 161 void DOT11D_ScanComplete(struct rtllib_device *dev) 162 { 163 struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 164 165 switch (pDot11dInfo->State) { 166 case DOT11D_STATE_LEARNED: 167 pDot11dInfo->State = DOT11D_STATE_DONE; 168 break; 169 case DOT11D_STATE_DONE: 170 Dot11d_Reset(dev); 171 break; 172 case DOT11D_STATE_NONE: 173 break; 174 } 175 } 176