Merge branch 'topic/asoc' into for-linus
[linux-2.6] / drivers / staging / rtl8187se / ieee80211 / dot11d.c
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
13 void
14 Dot11d_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 //
33 void
34 Dot11d_Reset(struct ieee80211_device *ieee)
35 {
36         u32 i;
37         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(ieee);
38
39         // Clear old channel map
40         memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
41         memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
42         // Set new channel map
43         for (i=1; i<=11; i++) {
44                 (pDot11dInfo->channel_map)[i] = 1;
45         }
46         for (i=12; i<=14; i++) {
47                 (pDot11dInfo->channel_map)[i] = 2;
48         }
49
50         pDot11dInfo->State = DOT11D_STATE_NONE;
51         pDot11dInfo->CountryIeLen = 0;
52         RESET_CIE_WATCHDOG(ieee);
53
54         //printk("Dot11d_Reset()\n");
55 }
56
57 //
58 //      Description:
59 //              Update country IE from Beacon or Probe Resopnse
60 //              and configure PHY for operation in the regulatory domain.
61 //
62 //      TODO:
63 //              Configure Tx power.
64 //
65 //      Assumption:
66 //              1. IS_DOT11D_ENABLE() is TRUE.
67 //              2. Input IE is an valid one.
68 //
69 void
70 Dot11d_UpdateCountryIe(
71         struct ieee80211_device *dev,
72         u8 *            pTaddr,
73         u16     CoutryIeLen,
74         u8 * pCoutryIe
75         )
76 {
77         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
78         u8 i, j, NumTriples, MaxChnlNum;
79         PCHNL_TXPOWER_TRIPLE pTriple;
80
81         if((CoutryIeLen - 3)%3 != 0)
82         {
83                 printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
84                 Dot11d_Reset(dev);
85                 return;
86         }
87
88         memset(pDot11dInfo->channel_map, 0, MAX_CHANNEL_NUMBER+1);
89         memset(pDot11dInfo->MaxTxPwrDbmList, 0xFF, MAX_CHANNEL_NUMBER+1);
90         MaxChnlNum = 0;
91         NumTriples = (CoutryIeLen - 3) / 3; // skip 3-byte country string.
92         pTriple = (PCHNL_TXPOWER_TRIPLE)(pCoutryIe + 3);
93         for(i = 0; i < NumTriples; i++)
94         {
95                 if(MaxChnlNum >= pTriple->FirstChnl)
96                 { // It is not in a monotonically increasing order, so stop processing.
97                         printk("Dot11d_UpdateCountryIe(): Invalid country IE, skip it........1\n");
98                         Dot11d_Reset(dev);
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                         Dot11d_Reset(dev);
105                         return;
106                 }
107
108                 for(j = 0 ; j < pTriple->NumChnls; j++)
109                 {
110                         pDot11dInfo->channel_map[pTriple->FirstChnl + j] = 1;
111                         pDot11dInfo->MaxTxPwrDbmList[pTriple->FirstChnl + j] = pTriple->MaxTxPowerInDbm;
112                         MaxChnlNum = pTriple->FirstChnl + j;
113                 }
114
115                 pTriple = (PCHNL_TXPOWER_TRIPLE)((u8*)pTriple + 3);
116         }
117 #if 1
118         //printk("Dot11d_UpdateCountryIe(): Channel List:\n");
119         printk("Channel List:");
120         for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
121                 if(pDot11dInfo->channel_map[i] > 0)
122                         printk(" %d", i);
123         printk("\n");
124 #endif
125
126         UPDATE_CIE_SRC(dev, pTaddr);
127
128         pDot11dInfo->CountryIeLen = CoutryIeLen;
129         memcpy(pDot11dInfo->CountryIeBuf, pCoutryIe,CoutryIeLen);
130         pDot11dInfo->State = DOT11D_STATE_LEARNED;
131 }
132
133 void dump_chnl_map(u8 * channel_map)
134 {
135         int i;
136         printk("Channel List:");
137         for(i=1; i<= MAX_CHANNEL_NUMBER; i++)
138                 if(channel_map[i] > 0)
139                         printk(" %d(%d)", i, channel_map[i]);
140         printk("\n");
141 }
142
143 u8
144 DOT11D_GetMaxTxPwrInDbm(
145         struct ieee80211_device *dev,
146         u8 Channel
147         )
148 {
149         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
150         u8 MaxTxPwrInDbm = 255;
151
152         if(MAX_CHANNEL_NUMBER < Channel)
153         {
154                 printk("DOT11D_GetMaxTxPwrInDbm(): Invalid Channel\n");
155                 return MaxTxPwrInDbm;
156         }
157         if(pDot11dInfo->channel_map[Channel])
158         {
159                 MaxTxPwrInDbm = pDot11dInfo->MaxTxPwrDbmList[Channel];
160         }
161
162         return MaxTxPwrInDbm;
163 }
164
165
166 void
167 DOT11D_ScanComplete(
168         struct ieee80211_device * dev
169         )
170 {
171         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
172
173         switch(pDot11dInfo->State)
174         {
175         case DOT11D_STATE_LEARNED:
176                 pDot11dInfo->State = DOT11D_STATE_DONE;
177                 break;
178
179         case DOT11D_STATE_DONE:
180                 if( GET_CIE_WATCHDOG(dev) == 0 )
181                 { // Reset country IE if previous one is gone.
182                         Dot11d_Reset(dev);
183                 }
184                 break;
185         case DOT11D_STATE_NONE:
186                 break;
187         }
188 }
189
190 int IsLegalChannel(
191         struct ieee80211_device * dev,
192         u8 channel
193 )
194 {
195         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
196
197         if(MAX_CHANNEL_NUMBER < channel)
198         {
199                 printk("IsLegalChannel(): Invalid Channel\n");
200                 return 0;
201         }
202         if(pDot11dInfo->channel_map[channel] > 0)
203                 return 1;
204         return 0;
205 }
206
207 int ToLegalChannel(
208         struct ieee80211_device * dev,
209         u8 channel
210 )
211 {
212         PRT_DOT11D_INFO pDot11dInfo = GET_DOT11D_INFO(dev);
213         u8 default_chn = 0;
214         u32 i = 0;
215
216         for (i=1; i<= MAX_CHANNEL_NUMBER; i++)
217         {
218                 if(pDot11dInfo->channel_map[i] > 0)
219                 {
220                         default_chn = i;
221                         break;
222                 }
223         }
224
225         if(MAX_CHANNEL_NUMBER < channel)
226         {
227                 printk("IsLegalChannel(): Invalid Channel\n");
228                 return default_chn;
229         }
230
231         if(pDot11dInfo->channel_map[channel] > 0)
232                 return channel;
233
234         return default_chn;
235 }
236
237 #if 0
238 EXPORT_SYMBOL(Dot11d_Init);
239 EXPORT_SYMBOL(Dot11d_Reset);
240 EXPORT_SYMBOL(Dot11d_UpdateCountryIe);
241 EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm);
242 EXPORT_SYMBOL(DOT11D_ScanComplete);
243 EXPORT_SYMBOL(IsLegalChannel);
244 EXPORT_SYMBOL(ToLegalChannel);
245 #endif
246 #endif