- patches.suse/slab-handle-memoryless-nodes-v2a.patch: Refresh.
[linux-flexiantxendom0-3.2.10.git] / drivers / staging / rtl8192u / 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         // 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 //
68 void
69 Dot11d_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
122 u8
123 DOT11D_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
145 void
146 DOT11D_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
169 int 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
186 int 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 EXPORT_SYMBOL(Dot11d_Init);
216 EXPORT_SYMBOL(Dot11d_Reset);
217 EXPORT_SYMBOL(Dot11d_UpdateCountryIe);
218 EXPORT_SYMBOL(DOT11D_GetMaxTxPwrInDbm);
219 EXPORT_SYMBOL(DOT11D_ScanComplete);
220 EXPORT_SYMBOL(IsLegalChannel);
221 EXPORT_SYMBOL(ToLegalChannel);
222
223 #endif