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