Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
dot11d.c
Go to the documentation of this file.
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 <[email protected]>
18 ******************************************************************************/
19 #include "dot11d.h"
20 
21 struct channel_list {
22  u8 Channel[32];
24 };
25 
26 static 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 
49 void dot11d_init(struct rtllib_device *ieee)
50 {
51  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
52  pDot11dInfo->bEnabled = false;
53 
54  pDot11dInfo->State = DOT11D_STATE_NONE;
55  pDot11dInfo->CountryIeLen = 0;
56  memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
57  memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
58  RESET_CIE_WATCHDOG(ieee);
59 
60 }
62 
64 {
65  int i, max_chan = 14, min_chan = 1;
66 
67  ieee->bGlobalDomain = false;
68 
69  if (ChannelPlan[channel_plan].Len != 0) {
71  sizeof(GET_DOT11D_INFO(ieee)->channel_map));
72  for (i = 0; i < ChannelPlan[channel_plan].Len; i++) {
73  if (ChannelPlan[channel_plan].Channel[i] < min_chan ||
74  ChannelPlan[channel_plan].Channel[i] > max_chan)
75  break;
76  GET_DOT11D_INFO(ieee)->channel_map[ChannelPlan
77  [channel_plan].Channel[i]] = 1;
78  }
79  }
80 
81  switch (channel_plan) {
83  ieee->bGlobalDomain = true;
84  for (i = 12; i <= 14; i++)
85  GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
86  ieee->IbssStartChnl = 10;
87  ieee->ibss_maxjoin_chal = 11;
88  break;
89 
91  for (i = 12; i <= 13; i++)
92  GET_DOT11D_INFO(ieee)->channel_map[i] = 2;
93  ieee->IbssStartChnl = 10;
94  ieee->ibss_maxjoin_chal = 11;
95  break;
96 
97  default:
98  ieee->IbssStartChnl = 1;
99  ieee->ibss_maxjoin_chal = 14;
100  break;
101  }
102 }
104 
105 
106 void Dot11d_Reset(struct rtllib_device *ieee)
107 {
108  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(ieee);
109  u32 i;
110 
111  memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
112  memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
113  for (i = 1; i <= 11; i++)
114  (pDot11dInfo->channel_map)[i] = 1;
115  for (i = 12; i <= 14; i++)
116  (pDot11dInfo->channel_map)[i] = 2;
117  pDot11dInfo->State = DOT11D_STATE_NONE;
118  pDot11dInfo->CountryIeLen = 0;
119  RESET_CIE_WATCHDOG(ieee);
120 }
121 
123  u16 CoutryIeLen, u8 *pCoutryIe)
124 {
125  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
126  u8 i, j, NumTriples, MaxChnlNum;
127  struct chnl_txpow_triple *pTriple;
128 
129  memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
130  memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
131  MaxChnlNum = 0;
132  NumTriples = (CoutryIeLen - 3) / 3;
133  pTriple = (struct chnl_txpow_triple *)(pCoutryIe + 3);
134  for (i = 0; i < NumTriples; i++) {
135  if (MaxChnlNum >= pTriple->FirstChnl) {
136  printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid"
137  " country IE, skip it........1\n");
138  return;
139  }
140  if (MAX_CHANNEL_NUMBER < (pTriple->FirstChnl +
141  pTriple->NumChnls)) {
142  printk(KERN_INFO "Dot11d_UpdateCountryIe(): Invalid "
143  "country IE, skip it........2\n");
144  return;
145  }
146 
147  for (j = 0 ; j < pTriple->NumChnls; j++) {
148  pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
149  pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] =
150  pTriple->MaxTxPowerInDbm;
151  MaxChnlNum = pTriple->FirstChnl + j;
152  }
153 
154  pTriple = (struct chnl_txpow_triple *)((u8*)pTriple + 3);
155  }
156 
157  UPDATE_CIE_SRC(dev, pTaddr);
158 
159  pDot11dInfo->CountryIeLen = CoutryIeLen;
160  memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe, CoutryIeLen);
161  pDot11dInfo->State = DOT11D_STATE_LEARNED;
162 }
163 
165 {
166  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
167  u8 MaxTxPwrInDbm = 255;
168 
169  if (MAX_CHANNEL_NUMBER < Channel) {
170  printk(KERN_INFO "DOT11D_GetMaxTxPwrInDbm(): Invalid "
171  "Channel\n");
172  return MaxTxPwrInDbm;
173  }
174  if (pDot11dInfo->channel_map[Channel])
175  MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
176 
177  return MaxTxPwrInDbm;
178 }
179 
181 {
182  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
183 
184  switch (pDot11dInfo->State) {
186  pDot11dInfo->State = DOT11D_STATE_DONE;
187  break;
188  case DOT11D_STATE_DONE:
189  Dot11d_Reset(dev);
190  break;
191  case DOT11D_STATE_NONE:
192  break;
193  }
194 }
195 
197 {
198  struct rt_dot11d_info *pDot11dInfo = GET_DOT11D_INFO(dev);
199  u8 default_chn = 0;
200  u32 i;
201 
202  for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
203  if (pDot11dInfo->channel_map[i] > 0) {
204  default_chn = i;
205  break;
206  }
207  }
208 
209  if (MAX_CHANNEL_NUMBER < channel) {
210  printk(KERN_ERR "%s(): Invalid Channel\n", __func__);
211  return default_chn;
212  }
213 
214  if (pDot11dInfo->channel_map[channel] > 0)
215  return channel;
216 
217  return default_chn;
218 }