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 * The full GNU General Public License is included in this distribution in the 1094a79942SLarry Finger * file called LICENSE. 1194a79942SLarry Finger * 1294a79942SLarry Finger * Contact Information: 1394a79942SLarry Finger * wlanfae <wlanfae@realtek.com> 1494a79942SLarry Finger ******************************************************************************/ 1594a79942SLarry Finger #include "dot11d.h" 1694a79942SLarry Finger 1794a79942SLarry Finger struct channel_list { 185f98ddc9SHimadri Pandya u8 channel[32]; 1975752154SHimadri Pandya u8 len; 2094a79942SLarry Finger }; 2194a79942SLarry Finger 223262af00SHimadri Pandya static struct channel_list channel_array[] = { 2394a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64, 2494a79942SLarry Finger 149, 153, 157, 161, 165}, 24}, 2594a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11}, 2694a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 2794a79942SLarry Finger 60, 64}, 21}, 2894a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 2994a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 3094a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3194a79942SLarry Finger 56, 60, 64}, 22}, 3294a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3394a79942SLarry Finger 56, 60, 64}, 22}, 3494a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 3594a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3694a79942SLarry Finger 56, 60, 64}, 22}, 3794a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 3894a79942SLarry Finger 56, 60, 64}, 22}, 3994a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}, 4094a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, 13}, 4194a79942SLarry Finger {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 4294a79942SLarry Finger 56, 60, 64}, 21} 4394a79942SLarry Finger }; 4494a79942SLarry Finger 45976d5341SSean MacLennan void dot11d_init(struct rtllib_device *ieee) 4694a79942SLarry Finger { 47a180ef30SHimadri Pandya struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee); 483a6b70c3SMatthew Casey 49a180ef30SHimadri Pandya dot11d_info->enabled = false; 5094a79942SLarry Finger 51a180ef30SHimadri Pandya dot11d_info->state = DOT11D_STATE_NONE; 52a180ef30SHimadri Pandya dot11d_info->country_len = 0; 53a180ef30SHimadri Pandya memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); 54a180ef30SHimadri Pandya memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1); 5594a79942SLarry Finger RESET_CIE_WATCHDOG(ieee); 5694a79942SLarry Finger } 57976d5341SSean MacLennan EXPORT_SYMBOL(dot11d_init); 5894a79942SLarry Finger 5930c311a2SHimadri Pandya void dot11d_channel_map(u8 channel_plan, struct rtllib_device *ieee) 6094a79942SLarry Finger { 6194a79942SLarry Finger int i, max_chan = 14, min_chan = 1; 6294a79942SLarry Finger 63a180ef30SHimadri Pandya ieee->global_domain = false; 6494a79942SLarry Finger 6575752154SHimadri Pandya if (channel_array[channel_plan].len != 0) { 6694a79942SLarry Finger memset(GET_DOT11D_INFO(ieee)->channel_map, 0, 6794a79942SLarry Finger sizeof(GET_DOT11D_INFO(ieee)->channel_map)); 6875752154SHimadri Pandya for (i = 0; i < channel_array[channel_plan].len; i++) { 693262af00SHimadri Pandya if (channel_array[channel_plan].channel[i] < min_chan || 703262af00SHimadri Pandya channel_array[channel_plan].channel[i] > max_chan) 7194a79942SLarry Finger break; 723262af00SHimadri Pandya GET_DOT11D_INFO(ieee)->channel_map[channel_array 735f98ddc9SHimadri Pandya [channel_plan].channel[i]] = 1; 7494a79942SLarry Finger } 7594a79942SLarry Finger } 7694a79942SLarry Finger 7794a79942SLarry Finger switch (channel_plan) { 7894a79942SLarry Finger case COUNTRY_CODE_GLOBAL_DOMAIN: 79a180ef30SHimadri Pandya ieee->global_domain = true; 8094a79942SLarry Finger for (i = 12; i <= 14; i++) 8194a79942SLarry Finger GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 82a180ef30SHimadri Pandya ieee->bss_start_channel = 10; 8394a79942SLarry Finger ieee->ibss_maxjoin_chal = 11; 8494a79942SLarry Finger break; 8594a79942SLarry Finger 8694a79942SLarry Finger case COUNTRY_CODE_WORLD_WIDE_13: 8794a79942SLarry Finger for (i = 12; i <= 13; i++) 8894a79942SLarry Finger GET_DOT11D_INFO(ieee)->channel_map[i] = 2; 89a180ef30SHimadri Pandya ieee->bss_start_channel = 10; 9094a79942SLarry Finger ieee->ibss_maxjoin_chal = 11; 9194a79942SLarry Finger break; 9294a79942SLarry Finger 9394a79942SLarry Finger default: 94a180ef30SHimadri Pandya ieee->bss_start_channel = 1; 9594a79942SLarry Finger ieee->ibss_maxjoin_chal = 14; 9694a79942SLarry Finger break; 9794a79942SLarry Finger } 9894a79942SLarry Finger } 9930c311a2SHimadri Pandya EXPORT_SYMBOL(dot11d_channel_map); 10094a79942SLarry Finger 1018e9f5da2SHimadri Pandya void dot11d_reset(struct rtllib_device *ieee) 10294a79942SLarry Finger { 103a180ef30SHimadri Pandya struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee); 10494a79942SLarry Finger u32 i; 10594a79942SLarry Finger 106a180ef30SHimadri Pandya memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); 107a180ef30SHimadri Pandya memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1); 10894a79942SLarry Finger for (i = 1; i <= 11; i++) 109a180ef30SHimadri Pandya (dot11d_info->channel_map)[i] = 1; 11094a79942SLarry Finger for (i = 12; i <= 14; i++) 111a180ef30SHimadri Pandya (dot11d_info->channel_map)[i] = 2; 112a180ef30SHimadri Pandya dot11d_info->state = DOT11D_STATE_NONE; 113a180ef30SHimadri Pandya dot11d_info->country_len = 0; 11494a79942SLarry Finger RESET_CIE_WATCHDOG(ieee); 11594a79942SLarry Finger } 11694a79942SLarry Finger 11794a79942SLarry Finger void Dot11d_UpdateCountryIe(struct rtllib_device *dev, u8 *pTaddr, 11894a79942SLarry Finger u16 CoutryIeLen, u8 *pCoutryIe) 11994a79942SLarry Finger { 120a180ef30SHimadri Pandya struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev); 12194a79942SLarry Finger u8 i, j, NumTriples, MaxChnlNum; 12294a79942SLarry Finger struct chnl_txpow_triple *pTriple; 12394a79942SLarry Finger 124a180ef30SHimadri Pandya memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1); 125a180ef30SHimadri Pandya memset(dot11d_info->max_tx_power_list, 0xFF, MAX_CHANNEL_NUMBER + 1); 12694a79942SLarry Finger MaxChnlNum = 0; 12794a79942SLarry Finger NumTriples = (CoutryIeLen - 3) / 3; 12894a79942SLarry Finger pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3); 12994a79942SLarry Finger for (i = 0; i < NumTriples; i++) { 130cc7834fbSHimadri Pandya if (MaxChnlNum >= pTriple->first_channel) { 131c476b2ecSMihaela Muraru netdev_info(dev->dev, 132c476b2ecSMihaela Muraru "%s: Invalid country IE, skip it......1\n", 133c476b2ecSMihaela Muraru __func__); 13494a79942SLarry Finger return; 13594a79942SLarry Finger } 136cc7834fbSHimadri Pandya if (MAX_CHANNEL_NUMBER < (pTriple->first_channel + 137cc7834fbSHimadri Pandya pTriple->num_channels)) { 138c476b2ecSMihaela Muraru netdev_info(dev->dev, 139c476b2ecSMihaela Muraru "%s: Invalid country IE, skip it......2\n", 140c476b2ecSMihaela Muraru __func__); 14194a79942SLarry Finger return; 14294a79942SLarry Finger } 14394a79942SLarry Finger 144cc7834fbSHimadri Pandya for (j = 0; j < pTriple->num_channels; j++) { 145a180ef30SHimadri Pandya dot11d_info->channel_map[pTriple->first_channel + j] = 1; 146a180ef30SHimadri Pandya dot11d_info->max_tx_power_list[pTriple->first_channel + j] = 147cc7834fbSHimadri Pandya pTriple->max_tx_power; 148cc7834fbSHimadri Pandya MaxChnlNum = pTriple->first_channel + j; 14994a79942SLarry Finger } 15094a79942SLarry Finger 15194a79942SLarry Finger pTriple = (struct chnl_txpow_triple *)((u8 *)pTriple + 3); 15294a79942SLarry Finger } 15394a79942SLarry Finger 15494a79942SLarry Finger UPDATE_CIE_SRC(dev, pTaddr); 15594a79942SLarry Finger 156a180ef30SHimadri Pandya dot11d_info->country_len = CoutryIeLen; 157a180ef30SHimadri Pandya memcpy(dot11d_info->country_buffer, pCoutryIe, CoutryIeLen); 158a180ef30SHimadri Pandya dot11d_info->state = DOT11D_STATE_LEARNED; 15994a79942SLarry Finger } 16094a79942SLarry Finger 16194a79942SLarry Finger void DOT11D_ScanComplete(struct rtllib_device *dev) 16294a79942SLarry Finger { 163a180ef30SHimadri Pandya struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev); 16494a79942SLarry Finger 165a180ef30SHimadri Pandya switch (dot11d_info->state) { 16694a79942SLarry Finger case DOT11D_STATE_LEARNED: 167a180ef30SHimadri Pandya dot11d_info->state = DOT11D_STATE_DONE; 16894a79942SLarry Finger break; 16994a79942SLarry Finger case DOT11D_STATE_DONE: 1708e9f5da2SHimadri Pandya dot11d_reset(dev); 17194a79942SLarry Finger break; 17294a79942SLarry Finger case DOT11D_STATE_NONE: 17394a79942SLarry Finger break; 17494a79942SLarry Finger } 17594a79942SLarry Finger } 176