b5a26f34b864e98816e9bc78af0a123679baced3
[deliverable/linux.git] / drivers / staging / rtl8192u / r8192U_wx.c
1 /*
2 This file contains wireless extension handlers.
3
4 This is part of rtl8180 OpenSource driver.
5 Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
6 Released under the terms of GPL (General Public Licence)
7
8 Parts of this driver are based on the GPL part
9 of the official realtek driver.
10
11 Parts of this driver are based on the rtl8180 driver skeleton
12 from Patric Schenke & Andres Salomon.
13
14 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
15
16 We want to thank the Authors of those projects and the Ndiswrapper
17 project Authors.
18 */
19
20 #include <linux/string.h>
21 #include "r8192U.h"
22 #include "r8192U_hw.h"
23
24 #include "dot11d.h"
25 #include "r8192U_wx.h"
26
27 #define RATE_COUNT 12
28 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
29 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
30
31
32 #ifndef ENETDOWN
33 #define ENETDOWN 1
34 #endif
35
36 static int r8192_wx_get_freq(struct net_device *dev,
37 struct iw_request_info *a,
38 union iwreq_data *wrqu, char *b)
39 {
40 struct r8192_priv *priv = ieee80211_priv(dev);
41
42 return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
43 }
44
45
46 static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47 union iwreq_data *wrqu, char *b)
48 {
49 struct r8192_priv *priv = ieee80211_priv(dev);
50
51 return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
52 }
53
54
55
56 static int r8192_wx_get_rate(struct net_device *dev,
57 struct iw_request_info *info,
58 union iwreq_data *wrqu, char *extra)
59 {
60 struct r8192_priv *priv = ieee80211_priv(dev);
61
62 return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
63 }
64
65
66
67 static int r8192_wx_set_rate(struct net_device *dev,
68 struct iw_request_info *info,
69 union iwreq_data *wrqu, char *extra)
70 {
71 int ret;
72 struct r8192_priv *priv = ieee80211_priv(dev);
73
74 down(&priv->wx_sem);
75
76 ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
77
78 up(&priv->wx_sem);
79
80 return ret;
81 }
82
83
84 static int r8192_wx_set_rts(struct net_device *dev,
85 struct iw_request_info *info,
86 union iwreq_data *wrqu, char *extra)
87 {
88 int ret;
89 struct r8192_priv *priv = ieee80211_priv(dev);
90
91 down(&priv->wx_sem);
92
93 ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
94
95 up(&priv->wx_sem);
96
97 return ret;
98 }
99
100 static int r8192_wx_get_rts(struct net_device *dev,
101 struct iw_request_info *info,
102 union iwreq_data *wrqu, char *extra)
103 {
104 struct r8192_priv *priv = ieee80211_priv(dev);
105
106 return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
107 }
108
109 static int r8192_wx_set_power(struct net_device *dev,
110 struct iw_request_info *info,
111 union iwreq_data *wrqu, char *extra)
112 {
113 int ret;
114 struct r8192_priv *priv = ieee80211_priv(dev);
115
116 down(&priv->wx_sem);
117
118 ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
119
120 up(&priv->wx_sem);
121
122 return ret;
123 }
124
125 static int r8192_wx_get_power(struct net_device *dev,
126 struct iw_request_info *info,
127 union iwreq_data *wrqu, char *extra)
128 {
129 struct r8192_priv *priv = ieee80211_priv(dev);
130
131 return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
132 }
133
134 static int r8192_wx_force_reset(struct net_device *dev,
135 struct iw_request_info *info,
136 union iwreq_data *wrqu, char *extra)
137 {
138 struct r8192_priv *priv = ieee80211_priv(dev);
139
140 down(&priv->wx_sem);
141
142 netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
143 priv->force_reset = *extra;
144 up(&priv->wx_sem);
145 return 0;
146
147 }
148
149
150 static int r8192_wx_set_rawtx(struct net_device *dev,
151 struct iw_request_info *info,
152 union iwreq_data *wrqu, char *extra)
153 {
154 struct r8192_priv *priv = ieee80211_priv(dev);
155 int ret;
156
157 down(&priv->wx_sem);
158
159 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
160
161 up(&priv->wx_sem);
162
163 return ret;
164
165 }
166
167 static int r8192_wx_set_crcmon(struct net_device *dev,
168 struct iw_request_info *info,
169 union iwreq_data *wrqu, char *extra)
170 {
171 struct r8192_priv *priv = ieee80211_priv(dev);
172 int *parms = (int *)extra;
173 int enable = (parms[0] > 0);
174
175 down(&priv->wx_sem);
176
177 if (enable)
178 priv->crcmon = 1;
179 else
180 priv->crcmon = 0;
181
182 DMESG("bad CRC in monitor mode are %s",
183 priv->crcmon ? "accepted" : "rejected");
184
185 up(&priv->wx_sem);
186
187 return 0;
188 }
189
190 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
191 union iwreq_data *wrqu, char *b)
192 {
193 struct r8192_priv *priv = ieee80211_priv(dev);
194 int ret;
195
196 down(&priv->wx_sem);
197
198 ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
199
200 rtl8192_set_rxconf(dev);
201
202 up(&priv->wx_sem);
203 return ret;
204 }
205
206 struct iw_range_with_scan_capa {
207 /* Informative stuff (to choose between different interface) */
208 __u32 throughput; /* To give an idea... */
209 /* In theory this value should be the maximum benchmarked
210 * TCP/IP throughput, because with most of these devices the
211 * bit rate is meaningless (overhead an co) to estimate how
212 * fast the connection will go and pick the fastest one.
213 * I suggest people to play with Netperf or any benchmark...
214 */
215
216 /* NWID (or domain id) */
217 __u32 min_nwid; /* Minimal NWID we are able to set */
218 __u32 max_nwid; /* Maximal NWID we are able to set */
219
220 /* Old Frequency (backward compat - moved lower ) */
221 __u16 old_num_channels;
222 __u8 old_num_frequency;
223
224 /* Scan capabilities */
225 __u8 scan_capa;
226 };
227 static int rtl8180_wx_get_range(struct net_device *dev,
228 struct iw_request_info *info,
229 union iwreq_data *wrqu, char *extra)
230 {
231 struct iw_range *range = (struct iw_range *)extra;
232 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
233 struct r8192_priv *priv = ieee80211_priv(dev);
234 u16 val;
235 int i;
236
237 wrqu->data.length = sizeof(*range);
238 memset(range, 0, sizeof(*range));
239
240 /* Let's try to keep this struct in the same order as in
241 * linux/include/wireless.h
242 */
243
244 /* TODO: See what values we can set, and remove the ones we can't
245 * set, or fill them with some default data.
246 */
247
248 /* ~5 Mb/s real (802.11b) */
249 range->throughput = 5 * 1000 * 1000;
250
251 /* TODO: Not used in 802.11b? */
252 /* range->min_nwid; */ /* Minimal NWID we are able to set */
253 /* TODO: Not used in 802.11b? */
254 /* range->max_nwid; */ /* Maximal NWID we are able to set */
255
256 /* Old Frequency (backward compat - moved lower ) */
257 /* range->old_num_channels; */
258 /* range->old_num_frequency; */
259 /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
260 if (priv->rf_set_sens != NULL)
261 range->sensitivity = priv->max_sens; /* signal level threshold range */
262
263 range->max_qual.qual = 100;
264 /* TODO: Find real max RSSI and stick here */
265 range->max_qual.level = 0;
266 range->max_qual.noise = -98;
267 range->max_qual.updated = 7; /* Updated all three */
268
269 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
270 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
271 range->avg_qual.level = 20 + -98;
272 range->avg_qual.noise = 0;
273 range->avg_qual.updated = 7; /* Updated all three */
274
275 range->num_bitrates = RATE_COUNT;
276
277 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
278 range->bitrate[i] = rtl8180_rates[i];
279
280 range->min_frag = MIN_FRAG_THRESHOLD;
281 range->max_frag = MAX_FRAG_THRESHOLD;
282
283 range->min_pmp = 0;
284 range->max_pmp = 5000000;
285 range->min_pmt = 0;
286 range->max_pmt = 65535*1000;
287 range->pmp_flags = IW_POWER_PERIOD;
288 range->pmt_flags = IW_POWER_TIMEOUT;
289 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
290
291 range->we_version_compiled = WIRELESS_EXT;
292 range->we_version_source = 16;
293
294 /* range->retry_capa; */ /* What retry options are supported */
295 /* range->retry_flags; */ /* How to decode max/min retry limit */
296 /* range->r_time_flags; */ /* How to decode max/min retry life */
297 /* range->min_retry; */ /* Minimal number of retries */
298 /* range->max_retry; */ /* Maximal number of retries */
299 /* range->min_r_time; */ /* Minimal retry lifetime */
300 /* range->max_r_time; */ /* Maximal retry lifetime */
301
302
303 for (i = 0, val = 0; i < 14; i++) {
304
305 /* Include only legal frequencies for some countries */
306 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
307 range->freq[val].i = i + 1;
308 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
309 range->freq[val].e = 1;
310 val++;
311 } else {
312 /* FIXME: do we need to set anything for channels */
313 /* we don't use ? */
314 }
315
316 if (val == IW_MAX_FREQUENCIES)
317 break;
318 }
319 range->num_frequency = val;
320 range->num_channels = val;
321 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
322 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
323 tmp->scan_capa = 0x01;
324 return 0;
325 }
326
327
328 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
329 union iwreq_data *wrqu, char *b)
330 {
331 struct r8192_priv *priv = ieee80211_priv(dev);
332 struct ieee80211_device *ieee = priv->ieee80211;
333 int ret = 0;
334
335 if (!priv->up)
336 return -ENETDOWN;
337
338 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
339 return -EAGAIN;
340 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
341 struct iw_scan_req *req = (struct iw_scan_req *)b;
342
343 if (req->essid_len) {
344 ieee->current_network.ssid_len = req->essid_len;
345 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
346 }
347 }
348
349 down(&priv->wx_sem);
350 if (priv->ieee80211->state != IEEE80211_LINKED) {
351 priv->ieee80211->scanning = 0;
352 ieee80211_softmac_scan_syncro(priv->ieee80211);
353 ret = 0;
354 } else {
355 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
356 }
357 up(&priv->wx_sem);
358 return ret;
359 }
360
361
362 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
363 union iwreq_data *wrqu, char *b)
364 {
365
366 int ret;
367 struct r8192_priv *priv = ieee80211_priv(dev);
368
369 if (!priv->up)
370 return -ENETDOWN;
371
372 down(&priv->wx_sem);
373
374 ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
375
376 up(&priv->wx_sem);
377
378 return ret;
379 }
380
381 static int r8192_wx_set_essid(struct net_device *dev,
382 struct iw_request_info *a,
383 union iwreq_data *wrqu, char *b)
384 {
385 struct r8192_priv *priv = ieee80211_priv(dev);
386 int ret;
387
388 down(&priv->wx_sem);
389
390 ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
391
392 up(&priv->wx_sem);
393
394 return ret;
395 }
396
397
398
399
400 static int r8192_wx_get_essid(struct net_device *dev,
401 struct iw_request_info *a,
402 union iwreq_data *wrqu, char *b)
403 {
404 int ret;
405 struct r8192_priv *priv = ieee80211_priv(dev);
406
407 down(&priv->wx_sem);
408
409 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
410
411 up(&priv->wx_sem);
412
413 return ret;
414 }
415
416
417 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
418 union iwreq_data *wrqu, char *b)
419 {
420 int ret;
421 struct r8192_priv *priv = ieee80211_priv(dev);
422
423 down(&priv->wx_sem);
424
425 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
426
427 up(&priv->wx_sem);
428 return ret;
429 }
430
431 static int r8192_wx_get_name(struct net_device *dev,
432 struct iw_request_info *info,
433 union iwreq_data *wrqu, char *extra)
434 {
435 struct r8192_priv *priv = ieee80211_priv(dev);
436
437 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
438 }
439
440
441 static int r8192_wx_set_frag(struct net_device *dev,
442 struct iw_request_info *info,
443 union iwreq_data *wrqu, char *extra)
444 {
445 struct r8192_priv *priv = ieee80211_priv(dev);
446
447 if (wrqu->frag.disabled)
448 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
449 else {
450 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
451 wrqu->frag.value > MAX_FRAG_THRESHOLD)
452 return -EINVAL;
453
454 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
455 }
456
457 return 0;
458 }
459
460
461 static int r8192_wx_get_frag(struct net_device *dev,
462 struct iw_request_info *info,
463 union iwreq_data *wrqu, char *extra)
464 {
465 struct r8192_priv *priv = ieee80211_priv(dev);
466
467 wrqu->frag.value = priv->ieee80211->fts;
468 wrqu->frag.fixed = 0; /* no auto select */
469 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
470
471 return 0;
472 }
473
474
475 static int r8192_wx_set_wap(struct net_device *dev,
476 struct iw_request_info *info,
477 union iwreq_data *awrq,
478 char *extra)
479 {
480
481 int ret;
482 struct r8192_priv *priv = ieee80211_priv(dev);
483 /* struct sockaddr *temp = (struct sockaddr *)awrq; */
484 down(&priv->wx_sem);
485
486 ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
487
488 up(&priv->wx_sem);
489
490 return ret;
491
492 }
493
494
495 static int r8192_wx_get_wap(struct net_device *dev,
496 struct iw_request_info *info,
497 union iwreq_data *wrqu, char *extra)
498 {
499 struct r8192_priv *priv = ieee80211_priv(dev);
500
501 return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
502 }
503
504
505 static int r8192_wx_get_enc(struct net_device *dev,
506 struct iw_request_info *info,
507 union iwreq_data *wrqu, char *key)
508 {
509 struct r8192_priv *priv = ieee80211_priv(dev);
510
511 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
512 }
513
514 static int r8192_wx_set_enc(struct net_device *dev,
515 struct iw_request_info *info,
516 union iwreq_data *wrqu, char *key)
517 {
518 struct r8192_priv *priv = ieee80211_priv(dev);
519 struct ieee80211_device *ieee = priv->ieee80211;
520 int ret;
521 u32 hwkey[4] = {0, 0, 0, 0};
522 u8 mask = 0xff;
523 u32 key_idx = 0;
524 u8 zero_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
525 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
526 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
527 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
528 int i;
529
530 if (!priv->up)
531 return -ENETDOWN;
532
533 down(&priv->wx_sem);
534
535 RT_TRACE(COMP_SEC, "Setting SW wep key");
536 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
537
538 up(&priv->wx_sem);
539
540
541
542 /* sometimes, the length is zero while we do not type key value */
543 if (wrqu->encoding.length != 0) {
544
545 for (i = 0; i < 4; i++) {
546 hwkey[i] |= key[4*i+0]&mask;
547 if (i == 1 && (4*i+1) == wrqu->encoding.length)
548 mask = 0x00;
549 if (i == 3 && (4*i+1) == wrqu->encoding.length)
550 mask = 0x00;
551 hwkey[i] |= (key[4*i+1]&mask)<<8;
552 hwkey[i] |= (key[4*i+2]&mask)<<16;
553 hwkey[i] |= (key[4*i+3]&mask)<<24;
554 }
555
556 #define CONF_WEP40 0x4
557 #define CONF_WEP104 0x14
558
559 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
560 case 0:
561 key_idx = ieee->tx_keyidx;
562 break;
563 case 1:
564 key_idx = 0;
565 break;
566 case 2:
567 key_idx = 1;
568 break;
569 case 3:
570 key_idx = 2;
571 break;
572 case 4:
573 key_idx = 3;
574 break;
575 default:
576 break;
577 }
578
579 if (wrqu->encoding.length == 0x5) {
580 ieee->pairwise_key_type = KEY_TYPE_WEP40;
581 EnableHWSecurityConfig8192(dev);
582
583 setKey(dev,
584 key_idx, /* EntryNo */
585 key_idx, /* KeyIndex */
586 KEY_TYPE_WEP40, /* KeyType */
587 zero_addr[key_idx],
588 0, /* DefaultKey */
589 hwkey); /* KeyContent */
590
591 }
592
593 else if (wrqu->encoding.length == 0xd) {
594 ieee->pairwise_key_type = KEY_TYPE_WEP104;
595 EnableHWSecurityConfig8192(dev);
596
597 setKey(dev,
598 key_idx, /* EntryNo */
599 key_idx, /* KeyIndex */
600 KEY_TYPE_WEP104, /* KeyType */
601 zero_addr[key_idx],
602 0, /* DefaultKey */
603 hwkey); /* KeyContent */
604
605 } else {
606 printk("wrong type in WEP, not WEP40 and WEP104\n");
607 }
608
609 }
610
611 return ret;
612 }
613
614
615 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
616 union iwreq_data *wrqu, char *p)
617 {
618
619 struct r8192_priv *priv = ieee80211_priv(dev);
620 int *parms = (int *)p;
621 int mode = parms[0];
622
623 priv->ieee80211->active_scan = mode;
624
625 return 1;
626 }
627
628
629
630 static int r8192_wx_set_retry(struct net_device *dev,
631 struct iw_request_info *info,
632 union iwreq_data *wrqu, char *extra)
633 {
634 struct r8192_priv *priv = ieee80211_priv(dev);
635 int err = 0;
636
637 down(&priv->wx_sem);
638
639 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
640 wrqu->retry.disabled){
641 err = -EINVAL;
642 goto exit;
643 }
644 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
645 err = -EINVAL;
646 goto exit;
647 }
648
649 if (wrqu->retry.value > R8180_MAX_RETRY) {
650 err = -EINVAL;
651 goto exit;
652 }
653 if (wrqu->retry.flags & IW_RETRY_MAX) {
654 priv->retry_rts = wrqu->retry.value;
655 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
656
657 } else {
658 priv->retry_data = wrqu->retry.value;
659 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
660 }
661
662 /* FIXME !
663 * We might try to write directly the TX config register
664 * or to restart just the (R)TX process.
665 * I'm unsure if whole reset is really needed
666 */
667
668 rtl8192_commit(dev);
669 exit:
670 up(&priv->wx_sem);
671
672 return err;
673 }
674
675 static int r8192_wx_get_retry(struct net_device *dev,
676 struct iw_request_info *info,
677 union iwreq_data *wrqu, char *extra)
678 {
679 struct r8192_priv *priv = ieee80211_priv(dev);
680
681
682 wrqu->retry.disabled = 0; /* can't be disabled */
683
684 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
685 IW_RETRY_LIFETIME)
686 return -EINVAL;
687
688 if (wrqu->retry.flags & IW_RETRY_MAX) {
689 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
690 wrqu->retry.value = priv->retry_rts;
691 } else {
692 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
693 wrqu->retry.value = priv->retry_data;
694 }
695
696
697 return 0;
698 }
699
700 static int r8192_wx_get_sens(struct net_device *dev,
701 struct iw_request_info *info,
702 union iwreq_data *wrqu, char *extra)
703 {
704 struct r8192_priv *priv = ieee80211_priv(dev);
705
706 if (priv->rf_set_sens == NULL)
707 return -1; /* we have not this support for this radio */
708 wrqu->sens.value = priv->sens;
709 return 0;
710 }
711
712
713 static int r8192_wx_set_sens(struct net_device *dev,
714 struct iw_request_info *info,
715 union iwreq_data *wrqu, char *extra)
716 {
717
718 struct r8192_priv *priv = ieee80211_priv(dev);
719 short err = 0;
720
721 down(&priv->wx_sem);
722 if (priv->rf_set_sens == NULL) {
723 err = -1; /* we have not this support for this radio */
724 goto exit;
725 }
726 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
727 priv->sens = wrqu->sens.value;
728 else
729 err = -EINVAL;
730
731 exit:
732 up(&priv->wx_sem);
733
734 return err;
735 }
736
737 /* hw security need to reorganized. */
738 static int r8192_wx_set_enc_ext(struct net_device *dev,
739 struct iw_request_info *info,
740 union iwreq_data *wrqu, char *extra)
741 {
742 int ret = 0;
743 struct r8192_priv *priv = ieee80211_priv(dev);
744 struct ieee80211_device *ieee = priv->ieee80211;
745
746
747 down(&priv->wx_sem);
748 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
749
750 {
751 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
752 u8 zero[6] = {0};
753 u32 key[4] = {0};
754 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
755 struct iw_point *encoding = &wrqu->encoding;
756 u8 idx = 0, alg = 0, group = 0;
757
758 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
759 /* none is not allowed to use hwsec WB 2008.07.01 */
760 goto end_hw_sec;
761
762 /* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
763 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
764 idx = encoding->flags & IW_ENCODE_INDEX;
765 if (idx)
766 idx--;
767 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
768
769 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) {
770 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
771 alg = KEY_TYPE_WEP104;
772 ieee->pairwise_key_type = alg;
773 EnableHWSecurityConfig8192(dev);
774 }
775 memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
776
777 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
778
779 setKey(dev,
780 idx, /* EntryNao */
781 idx, /* KeyIndex */
782 alg, /* KeyType */
783 zero, /* MacAddr */
784 0, /* DefaultKey */
785 key); /* KeyContent */
786 } else if (group) {
787 ieee->group_key_type = alg;
788 setKey(dev,
789 idx, /* EntryNo */
790 idx, /* KeyIndex */
791 alg, /* KeyType */
792 broadcast_addr, /* MacAddr */
793 0, /* DefaultKey */
794 key); /* KeyContent */
795 } else { /* pairwise key */
796 setKey(dev,
797 4, /* EntryNo */
798 idx, /* KeyIndex */
799 alg, /* KeyType */
800 (u8 *)ieee->ap_mac_addr,/* MacAddr */
801 0, /* DefaultKey */
802 key); /* KeyContent */
803 }
804
805
806 }
807
808 end_hw_sec:
809
810 up(&priv->wx_sem);
811 return ret;
812
813 }
814 static int r8192_wx_set_auth(struct net_device *dev,
815 struct iw_request_info *info,
816 union iwreq_data *data, char *extra)
817 {
818 int ret = 0;
819 struct r8192_priv *priv = ieee80211_priv(dev);
820
821 down(&priv->wx_sem);
822 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
823 up(&priv->wx_sem);
824 return ret;
825 }
826
827 static int r8192_wx_set_mlme(struct net_device *dev,
828 struct iw_request_info *info,
829 union iwreq_data *wrqu, char *extra)
830 {
831
832 int ret = 0;
833 struct r8192_priv *priv = ieee80211_priv(dev);
834
835 down(&priv->wx_sem);
836 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
837
838 up(&priv->wx_sem);
839 return ret;
840 }
841
842 static int r8192_wx_set_gen_ie(struct net_device *dev,
843 struct iw_request_info *info,
844 union iwreq_data *data, char *extra)
845 {
846 int ret = 0;
847 struct r8192_priv *priv = ieee80211_priv(dev);
848
849 down(&priv->wx_sem);
850 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
851 up(&priv->wx_sem);
852 return ret;
853
854
855 }
856
857 static int dummy(struct net_device *dev, struct iw_request_info *a,
858 union iwreq_data *wrqu, char *b)
859 {
860 return -1;
861 }
862
863
864 static iw_handler r8192_wx_handlers[] = {
865 NULL, /* SIOCSIWCOMMIT */
866 r8192_wx_get_name, /* SIOCGIWNAME */
867 dummy, /* SIOCSIWNWID */
868 dummy, /* SIOCGIWNWID */
869 r8192_wx_set_freq, /* SIOCSIWFREQ */
870 r8192_wx_get_freq, /* SIOCGIWFREQ */
871 r8192_wx_set_mode, /* SIOCSIWMODE */
872 r8192_wx_get_mode, /* SIOCGIWMODE */
873 r8192_wx_set_sens, /* SIOCSIWSENS */
874 r8192_wx_get_sens, /* SIOCGIWSENS */
875 NULL, /* SIOCSIWRANGE */
876 rtl8180_wx_get_range, /* SIOCGIWRANGE */
877 NULL, /* SIOCSIWPRIV */
878 NULL, /* SIOCGIWPRIV */
879 NULL, /* SIOCSIWSTATS */
880 NULL, /* SIOCGIWSTATS */
881 dummy, /* SIOCSIWSPY */
882 dummy, /* SIOCGIWSPY */
883 NULL, /* SIOCGIWTHRSPY */
884 NULL, /* SIOCWIWTHRSPY */
885 r8192_wx_set_wap, /* SIOCSIWAP */
886 r8192_wx_get_wap, /* SIOCGIWAP */
887 r8192_wx_set_mlme, /* MLME-- */
888 dummy, /* SIOCGIWAPLIST -- deprecated */
889 r8192_wx_set_scan, /* SIOCSIWSCAN */
890 r8192_wx_get_scan, /* SIOCGIWSCAN */
891 r8192_wx_set_essid, /* SIOCSIWESSID */
892 r8192_wx_get_essid, /* SIOCGIWESSID */
893 dummy, /* SIOCSIWNICKN */
894 dummy, /* SIOCGIWNICKN */
895 NULL, /* -- hole -- */
896 NULL, /* -- hole -- */
897 r8192_wx_set_rate, /* SIOCSIWRATE */
898 r8192_wx_get_rate, /* SIOCGIWRATE */
899 r8192_wx_set_rts, /* SIOCSIWRTS */
900 r8192_wx_get_rts, /* SIOCGIWRTS */
901 r8192_wx_set_frag, /* SIOCSIWFRAG */
902 r8192_wx_get_frag, /* SIOCGIWFRAG */
903 dummy, /* SIOCSIWTXPOW */
904 dummy, /* SIOCGIWTXPOW */
905 r8192_wx_set_retry, /* SIOCSIWRETRY */
906 r8192_wx_get_retry, /* SIOCGIWRETRY */
907 r8192_wx_set_enc, /* SIOCSIWENCODE */
908 r8192_wx_get_enc, /* SIOCGIWENCODE */
909 r8192_wx_set_power, /* SIOCSIWPOWER */
910 r8192_wx_get_power, /* SIOCGIWPOWER */
911 NULL, /*---hole---*/
912 NULL, /*---hole---*/
913 r8192_wx_set_gen_ie, /* NULL, */ /* SIOCSIWGENIE */
914 NULL, /* SIOCSIWGENIE */
915
916 r8192_wx_set_auth,/* NULL, */ /* SIOCSIWAUTH */
917 NULL,/* r8192_wx_get_auth, */ /* NULL, */ /* SIOCSIWAUTH */
918 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
919 NULL,/* r8192_wx_get_enc_ext, *//* NULL, */ /* SIOCSIWENCODEEXT */
920 NULL, /* SIOCSIWPMKSA */
921 NULL, /*---hole---*/
922
923 };
924
925
926 static const struct iw_priv_args r8192_private_args[] = {
927
928 {
929 SIOCIWFIRSTPRIV + 0x0,
930 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
931 },
932
933 {
934 SIOCIWFIRSTPRIV + 0x1,
935 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
936
937 },
938 {
939 SIOCIWFIRSTPRIV + 0x2,
940 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
941 },
942 {
943 SIOCIWFIRSTPRIV + 0x3,
944 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
945
946 }
947
948 };
949
950
951 static iw_handler r8192_private_handler[] = {
952 r8192_wx_set_crcmon,
953 r8192_wx_set_scan_type,
954 r8192_wx_set_rawtx,
955 r8192_wx_force_reset,
956 };
957
958 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
959 {
960 struct r8192_priv *priv = ieee80211_priv(dev);
961 struct ieee80211_device *ieee = priv->ieee80211;
962 struct iw_statistics *wstats = &priv->wstats;
963 int tmp_level = 0;
964 int tmp_qual = 0;
965 int tmp_noise = 0;
966
967 if (ieee->state < IEEE80211_LINKED) {
968 wstats->qual.qual = 0;
969 wstats->qual.level = 0;
970 wstats->qual.noise = 0;
971 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
972 return wstats;
973 }
974
975 tmp_level = (&ieee->current_network)->stats.rssi;
976 tmp_qual = (&ieee->current_network)->stats.signal;
977 tmp_noise = (&ieee->current_network)->stats.noise;
978
979 wstats->qual.level = tmp_level;
980 wstats->qual.qual = tmp_qual;
981 wstats->qual.noise = tmp_noise;
982 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
983 return wstats;
984 }
985
986
987 struct iw_handler_def r8192_wx_handlers_def = {
988 .standard = r8192_wx_handlers,
989 .num_standard = ARRAY_SIZE(r8192_wx_handlers),
990 .private = r8192_private_handler,
991 .num_private = ARRAY_SIZE(r8192_private_handler),
992 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
993 .get_wireless_stats = r8192_get_wireless_stats,
994 .private_args = (struct iw_priv_args *)r8192_private_args,
995 };
This page took 0.051457 seconds and 4 git commands to generate.