• 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/rtl8187se/ieee80211/
1//-----------------------------------------------------------------------------
2//	File:
3//		Dot11d.c
4//
5//	Description:
6//		Implement 802.11d.
7//
8//-----------------------------------------------------------------------------
9
10#include "dot11d.h"
11
12void
13Dot11d_Init(struct ieee80211_device *ieee)
14{
15	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
16
17	pDot11dInfo->bEnabled = 0;
18
19	pDot11dInfo->State = DOT11D_STATE_NONE;
20	pDot11dInfo->CountryIeLen = 0;
21	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
22	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
23	RESET_CIE_WATCHDOG(ieee);
24
25	printk("Dot11d_Init()\n");
26}
27
28//
29//	Description:
30//		Reset to the state as we are just entering a regulatory domain.
31//
32void
33Dot11d_Reset(struct ieee80211_device *ieee)
34{
35	u32 i;
36	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
37
38	// Clear old channel map
39	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
40	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
41	// Set new channel map
42	for (i=1; i<=11; i++) {
43		(pDot11dInfo->channel_map)[i] = 1;
44	}
45	for (i=12; i<=14; i++) {
46		(pDot11dInfo->channel_map)[i] = 2;
47	}
48
49	pDot11dInfo->State = DOT11D_STATE_NONE;
50	pDot11dInfo->CountryIeLen = 0;
51	RESET_CIE_WATCHDOG(ieee);
52
53	//printk("Dot11d_Reset()\n");
54}
55
56//
57//	Description:
58//		Update country IE from Beacon or Probe Resopnse
59//		and configure PHY for operation in the regulatory domain.
60//
61//	TODO:
62//		Configure Tx power.
63//
64//	Assumption:
65//		1. IS_DOT11D_ENABLE() is TRUE.
66//		2. Input IE is an valid one.
67//
68void
69Dot11d_UpdateCountryIe(
70	struct ieee80211_device *dev,
71	u8 *		pTaddr,
72	u16	CoutryIeLen,
73	u8 * pCoutryIe
74	)
75{
76	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
77	u8 i, j, NumTriples, MaxChnlNum;
78	PCHNL_TXPOWER_TRIPLE pTriple;
79
80	if((CoutryIeLen - 3)%3 != 0)
81	{
82		printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
83		Dot11d_Reset(dev);
84		return;
85	}
86
87	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
88	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
89	MaxChnlNum = 0;
90	NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
91	pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
92	for(i = 0; i < NumTriples; i++)
93	{
94		if(MaxChnlNum >= pTriple->FirstChnl)
95		{ // It is not in a monotonically increasing order, so stop processing.
96			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
97			Dot11d_Reset(dev);
98			return;
99		}
100		if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
101		{ // It is not a valid set of channel id, so stop processing.
102			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
103			Dot11d_Reset(dev);
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("Dot11d_UpdateCountryIe(): Channel List:\n");
117	printk("Channel List:");
118	for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
119		if(pDot11dInfo->channel_map[i] > 0)
120			printk(" %d", i);
121	printk("\n");
122
123	UPDATE_CIE_SRC(dev, pTaddr);
124
125	pDot11dInfo->CountryIeLen = CoutryIeLen;
126	memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
127	pDot11dInfo->State = DOT11D_STATE_LEARNED;
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