aboutsummaryrefslogtreecommitdiffstats
path: root/net/ieee80211/softmac/ieee80211softmac_wx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ieee80211/softmac/ieee80211softmac_wx.c')
-rw-r--r--net/ieee80211/softmac/ieee80211softmac_wx.c390
1 files changed, 390 insertions, 0 deletions
diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c
new file mode 100644
index 000000000000..bae5fcc11967
--- /dev/null
+++ b/net/ieee80211/softmac/ieee80211softmac_wx.c
@@ -0,0 +1,390 @@
1/*
2 * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them
3 */
4
5#include "ieee80211softmac_priv.h"
6
7#include <net/iw_handler.h>
8
9
10int
11ieee80211softmac_wx_trigger_scan(struct net_device *net_dev,
12 struct iw_request_info *info,
13 union iwreq_data *data,
14 char *extra)
15{
16 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
17 return ieee80211softmac_start_scan(sm);
18}
19EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan);
20
21
22int
23ieee80211softmac_wx_get_scan_results(struct net_device *net_dev,
24 struct iw_request_info *info,
25 union iwreq_data *data,
26 char *extra)
27{
28 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
29 return ieee80211_wx_get_scan(sm->ieee, info, data, extra);
30}
31EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results);
32
33int
34ieee80211softmac_wx_set_essid(struct net_device *net_dev,
35 struct iw_request_info *info,
36 union iwreq_data *data,
37 char *extra)
38{
39 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
40 int length = 0;
41 unsigned long flags;
42
43 spin_lock_irqsave(&sm->lock, flags);
44
45 sm->associnfo.static_essid = 0;
46
47 if (data->essid.flags && data->essid.length && extra /*required?*/) {
48 length = min(data->essid.length - 1, IW_ESSID_MAX_SIZE);
49 if (length) {
50 memcpy(sm->associnfo.req_essid.data, extra, length);
51 sm->associnfo.static_essid = 1;
52 }
53 }
54 sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT;
55
56 /* set our requested ESSID length.
57 * If applicable, we have already copied the data in */
58 sm->associnfo.req_essid.len = length;
59
60 /* queue lower level code to do work (if necessary) */
61 queue_work(sm->workqueue, &sm->associnfo.work);
62
63 spin_unlock_irqrestore(&sm->lock, flags);
64 return 0;
65}
66EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid);
67
68int
69ieee80211softmac_wx_get_essid(struct net_device *net_dev,
70 struct iw_request_info *info,
71 union iwreq_data *data,
72 char *extra)
73{
74 struct ieee80211softmac_device *sm = ieee80211_priv(net_dev);
75 unsigned long flags;
76
77 /* avoid getting inconsistent information */
78 spin_lock_irqsave(&sm->lock, flags);
79 /* If all fails, return ANY (empty) */
80 data->essid.length = 0;
81 data->essid.flags = 0; /* active */
82
83 /* If we have a statically configured ESSID then return it */
84 if (sm->associnfo.static_essid) {
85 data->essid.length = sm->associnfo.req_essid.len;
86 data->essid.flags = 1; /* active */
87 memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len);
88 }
89
90 /* If we're associating/associated, return that */
91 if (sm->associated || sm->associnfo.associating) {
92 data->essid.length = sm->associnfo.associate_essid.len;
93 data->essid.flags = 1; /* active */
94 memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len);
95 }
96 spin_unlock_irqrestore(&sm->lock, flags);
97 return 0;
98}
99EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid);
100
101int
102ieee80211softmac_wx_set_rate(struct net_device *net_dev,
103 struct iw_request_info *info,
104 union iwreq_data *data,
105 char *extra)
106{
107 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
108 struct ieee80211_device *ieee = mac->ieee;
109 unsigned long flags;
110 s32 in_rate = data->bitrate.value;
111 u8 rate;
112 int is_ofdm = 0;
113 int err = -EINVAL;
114
115 if (in_rate == -1) {
116 /* automatic detect */
117 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
118 in_rate = 54000000;
119 else
120 in_rate = 11000000;
121 }
122
123 switch (in_rate) {
124 case 1000000:
125 rate = IEEE80211_CCK_RATE_1MB;
126 break;
127 case 2000000:
128 rate = IEEE80211_CCK_RATE_2MB;
129 break;
130 case 5500000:
131 rate = IEEE80211_CCK_RATE_5MB;
132 break;
133 case 11000000:
134 rate = IEEE80211_CCK_RATE_11MB;
135 break;
136 case 6000000:
137 rate = IEEE80211_OFDM_RATE_6MB;
138 is_ofdm = 1;
139 break;
140 case 9000000:
141 rate = IEEE80211_OFDM_RATE_9MB;
142 is_ofdm = 1;
143 break;
144 case 12000000:
145 rate = IEEE80211_OFDM_RATE_12MB;
146 is_ofdm = 1;
147 break;
148 case 18000000:
149 rate = IEEE80211_OFDM_RATE_18MB;
150 is_ofdm = 1;
151 break;
152 case 24000000:
153 rate = IEEE80211_OFDM_RATE_24MB;
154 is_ofdm = 1;
155 break;
156 case 36000000:
157 rate = IEEE80211_OFDM_RATE_36MB;
158 is_ofdm = 1;
159 break;
160 case 48000000:
161 rate = IEEE80211_OFDM_RATE_48MB;
162 is_ofdm = 1;
163 break;
164 case 54000000:
165 rate = IEEE80211_OFDM_RATE_54MB;
166 is_ofdm = 1;
167 break;
168 default:
169 goto out;
170 }
171
172 spin_lock_irqsave(&mac->lock, flags);
173
174 /* Check if correct modulation for this PHY. */
175 if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION))
176 goto out_unlock;
177
178 mac->txrates.default_rate = rate;
179 mac->txrates.default_fallback = lower_rate(mac, rate);
180 err = 0;
181
182out_unlock:
183 spin_unlock_irqrestore(&mac->lock, flags);
184out:
185 return err;
186}
187EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate);
188
189int
190ieee80211softmac_wx_get_rate(struct net_device *net_dev,
191 struct iw_request_info *info,
192 union iwreq_data *data,
193 char *extra)
194{
195 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
196 unsigned long flags;
197 int err = -EINVAL;
198
199 spin_lock_irqsave(&mac->lock, flags);
200 switch (mac->txrates.default_rate) {
201 case IEEE80211_CCK_RATE_1MB:
202 data->bitrate.value = 1000000;
203 break;
204 case IEEE80211_CCK_RATE_2MB:
205 data->bitrate.value = 2000000;
206 break;
207 case IEEE80211_CCK_RATE_5MB:
208 data->bitrate.value = 5500000;
209 break;
210 case IEEE80211_CCK_RATE_11MB:
211 data->bitrate.value = 11000000;
212 break;
213 case IEEE80211_OFDM_RATE_6MB:
214 data->bitrate.value = 6000000;
215 break;
216 case IEEE80211_OFDM_RATE_9MB:
217 data->bitrate.value = 9000000;
218 break;
219 case IEEE80211_OFDM_RATE_12MB:
220 data->bitrate.value = 12000000;
221 break;
222 case IEEE80211_OFDM_RATE_18MB:
223 data->bitrate.value = 18000000;
224 break;
225 case IEEE80211_OFDM_RATE_24MB:
226 data->bitrate.value = 24000000;
227 break;
228 case IEEE80211_OFDM_RATE_36MB:
229 data->bitrate.value = 36000000;
230 break;
231 case IEEE80211_OFDM_RATE_48MB:
232 data->bitrate.value = 48000000;
233 break;
234 case IEEE80211_OFDM_RATE_54MB:
235 data->bitrate.value = 54000000;
236 break;
237 default:
238 assert(0);
239 goto out_unlock;
240 }
241 err = 0;
242out_unlock:
243 spin_unlock_irqrestore(&mac->lock, flags);
244
245 return err;
246}
247EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate);
248
249int
250ieee80211softmac_wx_get_wap(struct net_device *net_dev,
251 struct iw_request_info *info,
252 union iwreq_data *data,
253 char *extra)
254{
255 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
256 int err = 0;
257 unsigned long flags;
258
259 spin_lock_irqsave(&mac->lock, flags);
260 if (mac->associnfo.bssvalid)
261 memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN);
262 else
263 memset(data->ap_addr.sa_data, 0xff, ETH_ALEN);
264 data->ap_addr.sa_family = ARPHRD_ETHER;
265 spin_unlock_irqrestore(&mac->lock, flags);
266 return err;
267}
268EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap);
269
270int
271ieee80211softmac_wx_set_wap(struct net_device *net_dev,
272 struct iw_request_info *info,
273 union iwreq_data *data,
274 char *extra)
275{
276 struct ieee80211softmac_device *mac = ieee80211_priv(net_dev);
277 static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
278 static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
279 unsigned long flags;
280
281 /* sanity check */
282 if (data->ap_addr.sa_family != ARPHRD_ETHER) {
283 return -EINVAL;
284 }
285
286 spin_lock_irqsave(&mac->lock, flags);
287 if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) ||
288 !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) {
289 queue_work(mac->workqueue, &mac->associnfo.work);
290 goto out;
291 } else {
292 if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) {
293 if (mac->associnfo.associating || mac->associated) {
294 /* bssid unchanged and associated or associating - just return */
295 goto out;
296 }
297 } else {
298 /* copy new value in data->ap_addr.sa_data to bssid */
299 memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN);
300 }
301 /* queue associate if new bssid or (old one again and not associated) */
302 queue_work(mac->workqueue,&mac->associnfo.work);
303 }
304
305out:
306 spin_unlock_irqrestore(&mac->lock, flags);
307 return 0;
308}
309EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap);
310
311int
312ieee80211softmac_wx_set_genie(struct net_device *dev,
313 struct iw_request_info *info,
314 union iwreq_data *wrqu,
315 char *extra)
316{
317 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
318 unsigned long flags;
319 int err = 0;
320 char *buf;
321 int i;
322
323 spin_lock_irqsave(&mac->lock, flags);
324 /* bleh. shouldn't be locked for that kmalloc... */
325
326 if (wrqu->data.length) {
327 if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) {
328 /* this is an IE, so the length must be
329 * correct. Is it possible though that
330 * more than one IE is passed in?
331 */
332 err = -EINVAL;
333 goto out;
334 }
335 if (mac->wpa.IEbuflen <= wrqu->data.length) {
336 buf = kmalloc(wrqu->data.length, GFP_ATOMIC);
337 if (!buf) {
338 err = -ENOMEM;
339 goto out;
340 }
341 kfree(mac->wpa.IE);
342 mac->wpa.IE = buf;
343 mac->wpa.IEbuflen = wrqu->data.length;
344 }
345 memcpy(mac->wpa.IE, extra, wrqu->data.length);
346 dprintk(KERN_INFO PFX "generic IE set to ");
347 for (i=0;i<wrqu->data.length;i++)
348 dprintk("%.2x", mac->wpa.IE[i]);
349 dprintk("\n");
350 mac->wpa.IElen = wrqu->data.length;
351 } else {
352 kfree(mac->wpa.IE);
353 mac->wpa.IE = NULL;
354 mac->wpa.IElen = 0;
355 mac->wpa.IEbuflen = 0;
356 }
357
358 out:
359 spin_unlock_irqrestore(&mac->lock, flags);
360 return err;
361}
362EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie);
363
364int
365ieee80211softmac_wx_get_genie(struct net_device *dev,
366 struct iw_request_info *info,
367 union iwreq_data *wrqu,
368 char *extra)
369{
370 struct ieee80211softmac_device *mac = ieee80211_priv(dev);
371 unsigned long flags;
372 int err = 0;
373 int space = wrqu->data.length;
374
375 spin_lock_irqsave(&mac->lock, flags);
376
377 wrqu->data.length = 0;
378
379 if (mac->wpa.IE && mac->wpa.IElen) {
380 wrqu->data.length = mac->wpa.IElen;
381 if (mac->wpa.IElen <= space)
382 memcpy(extra, mac->wpa.IE, mac->wpa.IElen);
383 else
384 err = -E2BIG;
385 }
386 spin_unlock_irqrestore(&mac->lock, flags);
387 return err;
388}
389EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie);
390