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