194a79942SLarry Finger /****************************************************************************** 294a79942SLarry Finger * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved. 394a79942SLarry Finger * 494a79942SLarry Finger * This program is distributed in the hope that it will be useful, but WITHOUT 594a79942SLarry Finger * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 694a79942SLarry Finger * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 794a79942SLarry Finger * more details. 894a79942SLarry Finger * 994a79942SLarry Finger * You should have received a copy of the GNU General Public License along with 1094a79942SLarry Finger * this program; if not, write to the Free Software Foundation, Inc., 1194a79942SLarry Finger * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA 1294a79942SLarry Finger * 1394a79942SLarry Finger * The full GNU General Public License is included in this distribution in the 1494a79942SLarry Finger * file called LICENSE. 1594a79942SLarry Finger * 1694a79942SLarry Finger * Contact Information: 1794a79942SLarry Finger * wlanfae <wlanfae@realtek.com> 1894a79942SLarry Finger ******************************************************************************/ 1994a79942SLarry Finger #include "dot11d.h" 2094a79942SLarry Finger 2194a79942SLarry Finger struct channel_list { 2294a79942SLarry Finger u8 Channel[32]; 2394a79942SLarry Finger u8 Len; 2494a79942SLarry Finger }; 2594a79942SLarry Finger 2694a79942SLarry Finger static struct channel_list ChannelPlan[] = { 2794a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 2894a79942SLarry Finger 149, 153, 157, 161, 165}, 24}, 2994a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, 3094a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 3194a79942SLarry Finger 60, 64}, 21}, 3294a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 3394a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 3494a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3594a79942SLarry Finger 56, 60, 64}, 22}, 3694a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3794a79942SLarry Finger 56, 60, 64}, 22}, 3894a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 3994a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 4094a79942SLarry Finger 56, 60, 64}, 22}, 4194a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 4294a79942SLarry Finger 56, 60, 64}, 22}, 4394a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, 4494a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 4594a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 4694a79942SLarry Finger 56, 60, 64}, 21} 4794a79942SLarry Finger }; 4894a79942SLarry Finger 4994a79942SLarry Finger void Dot11d_Init(struct rtllib_device *ieee) 5094a79942SLarry Finger { 5194a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 5294a79942SLarry Finger pDot11dInfo->bEnabled = false; 5394a79942SLarry Finger 5494a79942SLarry Finger pDot11dInfo->State = DOT11D_STATE_NONE; 5594a79942SLarry Finger pDot11dInfo->CountryIeLen = 0; 5694a79942SLarry Finger memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 5794a79942SLarry Finger memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 5894a79942SLarry Finger RESET_CIE_WATCHDOG(ieee); 5994a79942SLarry Finger 6094a79942SLarry Finger } 6194a79942SLarry Finger 6294a79942SLarry Finger void Dot11d_Channelmap(u8 channel_plan, struct rtllib_device *ieee) 6394a79942SLarry Finger { 6494a79942SLarry Finger int i, max_chan = 14, min_chan = 1; 6594a79942SLarry Finger 6694a79942SLarry Finger ieee->bGlobalDomain = false; 6794a79942SLarry Finger 6894a79942SLarry Finger if (ChannelPlan[channel_plan].Len != 0) { 6994a79942SLarry Finger memset(GET_DOT11D_INFO(ieee)->channel_map, 0, 7094a79942SLarry Finger sizeof(GET_DOT11D_INFO(ieee)->channel_map)); 7194a79942SLarry Finger for (i = 0; i < ChannelPlan[channel_plan].Len; i++) { 7294a79942SLarry Finger if (ChannelPlan[channel_plan].Channel[i] < min_chan || 7394a79942SLarry Finger ChannelPlan[channel_plan].Channel[i] > max_chan) 7494a79942SLarry Finger break; 7594a79942SLarry Finger GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan 7694a79942SLarry Finger [channel_plan].Channel[i]] = 1; 7794a79942SLarry Finger } 7894a79942SLarry Finger } 7994a79942SLarry Finger 8094a79942SLarry Finger switch (channel_plan) { 8194a79942SLarry Finger case COUNTRY_CODE_GLOBAL_DOMAIN: 8294a79942SLarry Finger ieee->bGlobalDomain = true; 8394a79942SLarry Finger for (i = 12; i <= 14; i++) 8494a79942SLarry Finger GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 8594a79942SLarry Finger ieee->IbssStartChnl = 10; 8694a79942SLarry Finger ieee->ibss_maxjoin_chal = 11; 8794a79942SLarry Finger break; 8894a79942SLarry Finger 8994a79942SLarry Finger case COUNTRY_CODE_WORLD_WIDE_13: 9094a79942SLarry Finger for (i = 12; i <= 13; i++) 9194a79942SLarry Finger GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 9294a79942SLarry Finger ieee->IbssStartChnl = 10; 9394a79942SLarry Finger ieee->ibss_maxjoin_chal = 11; 9494a79942SLarry Finger break; 9594a79942SLarry Finger 9694a79942SLarry Finger default: 9794a79942SLarry Finger ieee->IbssStartChnl = 1; 9894a79942SLarry Finger ieee->ibss_maxjoin_chal = 14; 9994a79942SLarry Finger break; 10094a79942SLarry Finger } 10194a79942SLarry Finger } 10294a79942SLarry Finger 10394a79942SLarry Finger 10494a79942SLarry Finger void Dot11d_Reset(struct rtllib_device *ieee) 10594a79942SLarry Finger { 10694a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee); 10794a79942SLarry Finger u32 i; 10894a79942SLarry Finger 10994a79942SLarry Finger memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 11094a79942SLarry Finger memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 11194a79942SLarry Finger for (i = 1; i <= 11; i++) 11294a79942SLarry Finger (pDot11dInfo->channel_map)[i] = 1; 11394a79942SLarry Finger for (i = 12; i <= 14; i++) 11494a79942SLarry Finger (pDot11dInfo->channel_map)[i] = 2; 11594a79942SLarry Finger pDot11dInfo->State = DOT11D_STATE_NONE; 11694a79942SLarry Finger pDot11dInfo->CountryIeLen = 0; 11794a79942SLarry Finger RESET_CIE_WATCHDOG(ieee); 11894a79942SLarry Finger } 11994a79942SLarry Finger 12094a79942SLarry Finger void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, 12194a79942SLarry Finger u16 CoutryIeLen, u8 *pCoutryIe) 12294a79942SLarry Finger { 12394a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 12494a79942SLarry Finger u8 i, j, NumTriples, MaxChnlNum; 12594a79942SLarry Finger struct chnl_txpow_triple *pTriple; 12694a79942SLarry Finger 12794a79942SLarry Finger memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1); 12894a79942SLarry Finger memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1); 12994a79942SLarry Finger MaxChnlNum = 0; 13094a79942SLarry Finger NumTriples = (CoutryIeLen - 3) / 3; 13194a79942SLarry Finger pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); 13294a79942SLarry Finger for (i = 0; i < NumTriples; i++) { 13394a79942SLarry Finger if (MaxChnlNum >= pTriple->FirstChnl) { 13494a79942SLarry Finger printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid" 13594a79942SLarry Finger " country IE, skip it........1\n"); 13694a79942SLarry Finger return; 13794a79942SLarry Finger } 13894a79942SLarry Finger if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + 13994a79942SLarry Finger pTriple->NumChnls)) { 14094a79942SLarry Finger printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid " 14194a79942SLarry Finger "country IE, skip it........2\n"); 14294a79942SLarry Finger return; 14394a79942SLarry Finger } 14494a79942SLarry Finger 14594a79942SLarry Finger for (j = 0 ; j < pTriple->NumChnls; j++) { 14694a79942SLarry Finger pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1; 14794a79942SLarry Finger pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = 14894a79942SLarry Finger pTriple->MaxTxPowerInDbm; 14994a79942SLarry Finger MaxChnlNum = pTriple->FirstChnl + j; 15094a79942SLarry Finger } 15194a79942SLarry Finger 15294a79942SLarry Finger pTriple = (struct chnl_txpow_triple *)((u8*)pTriple + 3); 15394a79942SLarry Finger } 15494a79942SLarry Finger 15594a79942SLarry Finger UPDATE_CIE_SRC(dev, pTaddr); 15694a79942SLarry Finger 15794a79942SLarry Finger pDot11dInfo->CountryIeLen = CoutryIeLen; 15894a79942SLarry Finger memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen); 15994a79942SLarry Finger pDot11dInfo->State = DOT11D_STATE_LEARNED; 16094a79942SLarry Finger } 16194a79942SLarry Finger 16294a79942SLarry Finger u8 DOT11D_GetMaxTxPwrInDbm(struct rtllib_device *dev, u8 Channel) 16394a79942SLarry Finger { 16494a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 16594a79942SLarry Finger u8 MaxTxPwrInDbm = 255; 16694a79942SLarry Finger 16794a79942SLarry Finger if (MAX_CHANNEL_NUMBER < Channel) { 16894a79942SLarry Finger printk(KERN_INFO "DOT11D_GetMaxTxPwrInDbm(): Invalid " 16994a79942SLarry Finger "Channel\n"); 17094a79942SLarry Finger return MaxTxPwrInDbm; 17194a79942SLarry Finger } 17294a79942SLarry Finger if (pDot11dInfo->channel_map[Channel]) 17394a79942SLarry Finger MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel]; 17494a79942SLarry Finger 17594a79942SLarry Finger return MaxTxPwrInDbm; 17694a79942SLarry Finger } 17794a79942SLarry Finger 17894a79942SLarry Finger void DOT11D_ScanComplete(struct rtllib_device *dev) 17994a79942SLarry Finger { 18094a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 18194a79942SLarry Finger 18294a79942SLarry Finger switch (pDot11dInfo->State) { 18394a79942SLarry Finger case DOT11D_STATE_LEARNED: 18494a79942SLarry Finger pDot11dInfo->State = DOT11D_STATE_DONE; 18594a79942SLarry Finger break; 18694a79942SLarry Finger case DOT11D_STATE_DONE: 18794a79942SLarry Finger Dot11d_Reset(dev); 18894a79942SLarry Finger break; 18994a79942SLarry Finger case DOT11D_STATE_NONE: 19094a79942SLarry Finger break; 19194a79942SLarry Finger } 19294a79942SLarry Finger } 19394a79942SLarry Finger 19494a79942SLarry Finger int ToLegalChannel(struct rtllib_device *dev, u8 channel) 19594a79942SLarry Finger { 19694a79942SLarry Finger struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev); 19794a79942SLarry Finger u8 default_chn = 0; 19894a79942SLarry Finger u32 i; 19994a79942SLarry Finger 20094a79942SLarry Finger for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) { 20194a79942SLarry Finger if (pDot11dInfo->channel_map[i] > 0) { 20294a79942SLarry Finger default_chn = i; 20394a79942SLarry Finger break; 20494a79942SLarry Finger } 20594a79942SLarry Finger } 20694a79942SLarry Finger 20794a79942SLarry Finger if (MAX_CHANNEL_NUMBER < channel) { 20894a79942SLarry Finger printk(KERN_ERR "%s(): Invalid Channel\n", __func__); 20994a79942SLarry Finger return default_chn; 21094a79942SLarry Finger } 21194a79942SLarry Finger 21294a79942SLarry Finger if (pDot11dInfo->channel_map[channel] > 0) 21394a79942SLarry Finger return channel; 21494a79942SLarry Finger 21594a79942SLarry Finger return default_chn; 21694a79942SLarry Finger } 217