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