• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/drivers/staging/rtl8192e/ieee80211/
1#ifdef ENABLE_DOT11D
2//-----------------------------------------------------------------------------
3//	File:
4//		Dot11d.c
5//
6//	Description:
7//		Implement 802.11d.
8//
9//-----------------------------------------------------------------------------
10
11#include "dot11d.h"
12
13void
14Dot11d_Init(struct ieee80211_device *ieee)
15{
16	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
17
18	pDot11dInfo->bEnabled = 0;
19
20	pDot11dInfo->State = DOT11D_STATE_NONE;
21	pDot11dInfo->CountryIeLen = 0;
22	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
23	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
24	RESET_CIE_WATCHDOG(ieee);
25
26	printk("Dot11d_Init()\n");
27}
28
29//
30//	Description:
31//		Reset to the state as we are just entering a regulatory domain.
32//
33void
34Dot11d_Reset(struct ieee80211_device *ieee)
35{
36	u32 i;
37	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
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	memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
81	memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
82	MaxChnlNum = 0;
83	NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
84	pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
85	for(i = 0; i < NumTriples; i++)
86	{
87		if(MaxChnlNum >= pTriple->FirstChnl)
88		{ // It is not in a monotonically increasing order, so stop processing.
89			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
90			return;
91		}
92		if(MAX_CHANNEL_NUMBER < (pTriple->FirstChnl + pTriple->NumChnls))
93		{ // It is not a valid set of channel id, so stop processing.
94			printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........2\n");
95			return;
96		}
97
98		for(j = 0 ; j < pTriple->NumChnls; j++)
99		{
100			pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
101			pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
102			MaxChnlNum = pTriple->FirstChnl + j;
103		}
104
105		pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
106	}
107	//printk("Dot11d_UpdateCountryIe(): Channel List:\n");
108	printk("Channel List:");
109	for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
110		if(pDot11dInfo->channel_map[i] > 0)
111			printk(" %d", i);
112	printk("\n");
113
114	UPDATE_CIE_SRC(dev, pTaddr);
115
116	pDot11dInfo->CountryIeLen = CoutryIeLen;
117	memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
118	pDot11dInfo->State = DOT11D_STATE_LEARNED;
119}
120
121
122u8
123DOT11D_GetMaxTxPwrInDbm(
124	struct ieee80211_device *dev,
125	u8 Channel
126	)
127{
128	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
129	u8 MaxTxPwrInDbm = 255;
130
131	if(MAX_CHANNEL_NUMBER < Channel)
132	{
133		printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
134		return MaxTxPwrInDbm;
135	}
136	if(pDot11dInfo->channel_map[Channel])
137	{
138		MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
139	}
140
141	return MaxTxPwrInDbm;
142}
143
144
145void
146DOT11D_ScanComplete(
147	struct ieee80211_device * dev
148	)
149{
150	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
151
152	switch(pDot11dInfo->State)
153	{
154	case DOT11D_STATE_LEARNED:
155		pDot11dInfo->State = DOT11D_STATE_DONE;
156		break;
157
158	case DOT11D_STATE_DONE:
159		if( GET_CIE_WATCHDOG(dev) == 0 )
160		{ // Reset country IE if previous one is gone.
161			Dot11d_Reset(dev);
162		}
163		break;
164	case DOT11D_STATE_NONE:
165		break;
166	}
167}
168
169int IsLegalChannel(
170	struct ieee80211_device * dev,
171	u8 channel
172)
173{
174	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
175
176	if(MAX_CHANNEL_NUMBER < channel)
177	{
178		printk("IsLegalChannel(): Invalid Channel\n");
179		return 0;
180	}
181	if(pDot11dInfo->channel_map[channel] > 0)
182		return 1;
183	return 0;
184}
185
186int ToLegalChannel(
187	struct ieee80211_device * dev,
188	u8 channel
189)
190{
191	PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
192	u8 default_chn = 0;
193	u32 i = 0;
194
195	for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
196	{
197		if(pDot11dInfo->channel_map[i] > 0)
198		{
199			default_chn = i;
200			break;
201		}
202	}
203
204	if(MAX_CHANNEL_NUMBER < channel)
205	{
206		printk("IsLegalChannel(): Invalid Channel\n");
207		return default_chn;
208	}
209
210	if(pDot11dInfo->channel_map[channel] > 0)
211		return channel;
212
213	return default_chn;
214}
215#endif
216