• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192su/ieee80211/
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
20#include "dot11d.h"
21
22void
23Dot11d_Init(struct ieee80211_device *ieee)
24{
25	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
26
27	pDot11dInfo->bEnabled = 0;
28
29	pDot11dInfo->State = DOT11D_STATE_NONE;
30	pDot11dInfo->CountryIeLen = 0;
31	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
32	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
33	RESET_CIE_WATCHDOG(ieee);
34
35	printk("Dot11d_Init()\n");
36}
37
38//
39//	Description:
40//		Reset to the state as we are just entering a regulatory domain.
41//
42void
43Dot11d_Reset(struct ieee80211_device *ieee)
44{
45	u32 i;
46	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
47
48	// Clear old channel map
49	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
50	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
51	// Set new channel map
52	for (i=1; i<=11; i++) {
53		(pDot11dInfo->channel_map)[i] = 1;
54	}
55	for (i=12; i<=14; i++) {
56		(pDot11dInfo->channel_map)[i] = 2;
57	}
58
59	pDot11dInfo->State = DOT11D_STATE_NONE;
60	pDot11dInfo->CountryIeLen = 0;
61	RESET_CIE_WATCHDOG(ieee);
62
63}
64
65//
66//	Description:
67//		Update country IE from Beacon or Probe Resopnse
68//		and configure PHY for operation in the regulatory domain.
69//
70//	TODO:
71//		Configure Tx power.
72//
73//	Assumption:
74//		1. IS_DOT11D_ENABLE() is TRUE.
75//		2. Input IE is an valid one.
76//
77void
78Dot11d_UpdateCountryIe(
79	struct ieee80211_device *dev,
80	u8 *		pTaddr,
81	u16	CoutryIeLen,
82	u8 * pCoutryIe
83	)
84{
85	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
86	u8 i, j, NumTriples, MaxChnlNum;
87	PCHNL_TXPOWER_TRIPLE pTriple;
88
89	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
90	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
91	MaxChnlNum = 0;
92	NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
93	pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
94	for(i = 0; i < NumTriples; i++)
95	{
96		if(MaxChnlNum >= pTriple->FirstChnl)
97		{ // It is not in a monotonically increasing order, so stop processing.
98			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
99			return;
100		}
101		if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
102		{ // It is not a valid set of channel id, so stop processing.
103			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
104			return;
105		}
106
107		for(j = 0 ; j < pTriple->NumChnls; j++)
108		{
109			pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
110			pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
111			MaxChnlNum = pTriple->FirstChnl + j;
112		}
113
114		pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
115	}
116	printk("Channel List:");
117	for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
118		if(pDot11dInfo->channel_map[i] > 0)
119			printk(" %d", i);
120	printk("\n");
121
122	UPDATE_CIE_SRC(dev, pTaddr);
123
124	pDot11dInfo->CountryIeLen = CoutryIeLen;
125	memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
126	pDot11dInfo->State = DOT11D_STATE_LEARNED;
127}
128
129
130u8
131DOT11D_GetMaxTxPwrInDbm(
132	struct ieee80211_device *dev,
133	u8 Channel
134	)
135{
136	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
137	u8 MaxTxPwrInDbm = 255;
138
139	if(MAX_CHANNEL_NUMBER < Channel)
140	{
141		printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
142		return MaxTxPwrInDbm;
143	}
144	if(pDot11dInfo->channel_map[Channel])
145	{
146		MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
147	}
148
149	return MaxTxPwrInDbm;
150}
151
152
153void
154DOT11D_ScanComplete(
155	struct ieee80211_device * dev
156	)
157{
158	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
159
160	switch(pDot11dInfo->State)
161	{
162	case DOT11D_STATE_LEARNED:
163		pDot11dInfo->State = DOT11D_STATE_DONE;
164		break;
165
166	case DOT11D_STATE_DONE:
167		if( GET_CIE_WATCHDOG(dev) == 0 )
168		{ // Reset country IE if previous one is gone.
169			Dot11d_Reset(dev);
170		}
171		break;
172	case DOT11D_STATE_NONE:
173		break;
174	}
175}
176
177int IsLegalChannel(
178	struct ieee80211_device * dev,
179	u8 channel
180)
181{
182	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
183
184	if(MAX_CHANNEL_NUMBER < channel)
185	{
186		printk("IsLegalChannel(): Invalid Channel\n");
187		return 0;
188	}
189	if(pDot11dInfo->channel_map[channel] > 0)
190		return 1;
191	return 0;
192}
193
194int ToLegalChannel(
195	struct ieee80211_device * dev,
196	u8 channel
197)
198{
199	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
200	u8 default_chn = 0;
201	u32 i = 0;
202
203	for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
204	{
205		if(pDot11dInfo->channel_map[i] > 0)
206		{
207			default_chn = i;
208			break;
209		}
210	}
211
212	if(MAX_CHANNEL_NUMBER < channel)
213	{
214		printk("IsLegalChannel(): Invalid Channel\n");
215		return default_chn;
216	}
217
218	if(pDot11dInfo->channel_map[channel] > 0)
219		return channel;
220
221	return default_chn;
222}
223