GNU Linux-libre 4.4.288-gnu1
[releases.git] / drivers / staging / rtl8192u / r8192U_wx.c
1 /*
2    This file contains wireless extension handlers.
3
4    This is part of rtl8180 OpenSource driver.
5    Copyright (C) Andrea Merello 2004-2005  <andrea.merello@gmail.com>
6    Released under the terms of GPL (General Public Licence)
7
8    Parts of this driver are based on the GPL part
9    of the official realtek driver.
10
11    Parts of this driver are based on the rtl8180 driver skeleton
12    from Patric Schenke & Andres Salomon.
13
14    Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
15
16    We want to thank the Authors of those projects and the Ndiswrapper
17    project Authors.
18 */
19
20 #include <linux/string.h>
21 #include "r8192U.h"
22 #include "r8192U_hw.h"
23
24 #include "dot11d.h"
25 #include "r8192U_wx.h"
26
27 #define RATE_COUNT 12
28 static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
29         6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
30
31
32 #ifndef ENETDOWN
33 #define ENETDOWN 1
34 #endif
35
36 static int r8192_wx_get_freq(struct net_device *dev,
37                              struct iw_request_info *a,
38                              union iwreq_data *wrqu, char *b)
39 {
40         struct r8192_priv *priv = ieee80211_priv(dev);
41
42         return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
43 }
44
45
46 static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47                              union iwreq_data *wrqu, char *b)
48 {
49         struct r8192_priv *priv = ieee80211_priv(dev);
50
51         return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
52 }
53
54
55
56 static int r8192_wx_get_rate(struct net_device *dev,
57                              struct iw_request_info *info,
58                              union iwreq_data *wrqu, char *extra)
59 {
60         struct r8192_priv *priv = ieee80211_priv(dev);
61
62         return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
63 }
64
65
66
67 static int r8192_wx_set_rate(struct net_device *dev,
68                              struct iw_request_info *info,
69                              union iwreq_data *wrqu, char *extra)
70 {
71         int ret;
72         struct r8192_priv *priv = ieee80211_priv(dev);
73
74         down(&priv->wx_sem);
75
76         ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
77
78         up(&priv->wx_sem);
79
80         return ret;
81 }
82
83
84 static int r8192_wx_set_rts(struct net_device *dev,
85                              struct iw_request_info *info,
86                              union iwreq_data *wrqu, char *extra)
87 {
88         int ret;
89         struct r8192_priv *priv = ieee80211_priv(dev);
90
91         down(&priv->wx_sem);
92
93         ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
94
95         up(&priv->wx_sem);
96
97         return ret;
98 }
99
100 static int r8192_wx_get_rts(struct net_device *dev,
101                              struct iw_request_info *info,
102                              union iwreq_data *wrqu, char *extra)
103 {
104         struct r8192_priv *priv = ieee80211_priv(dev);
105
106         return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
107 }
108
109 static int r8192_wx_set_power(struct net_device *dev,
110                              struct iw_request_info *info,
111                              union iwreq_data *wrqu, char *extra)
112 {
113         int ret;
114         struct r8192_priv *priv = ieee80211_priv(dev);
115
116         down(&priv->wx_sem);
117
118         ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
119
120         up(&priv->wx_sem);
121
122         return ret;
123 }
124
125 static int r8192_wx_get_power(struct net_device *dev,
126                              struct iw_request_info *info,
127                              union iwreq_data *wrqu, char *extra)
128 {
129         struct r8192_priv *priv = ieee80211_priv(dev);
130
131         return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
132 }
133
134 static int r8192_wx_force_reset(struct net_device *dev,
135                 struct iw_request_info *info,
136                 union iwreq_data *wrqu, char *extra)
137 {
138         struct r8192_priv *priv = ieee80211_priv(dev);
139
140         down(&priv->wx_sem);
141
142         netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
143         priv->force_reset = *extra;
144         up(&priv->wx_sem);
145         return 0;
146
147 }
148
149
150 static int r8192_wx_set_rawtx(struct net_device *dev,
151                                struct iw_request_info *info,
152                                union iwreq_data *wrqu, char *extra)
153 {
154         struct r8192_priv *priv = ieee80211_priv(dev);
155         int ret;
156
157         down(&priv->wx_sem);
158
159         ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
160
161         up(&priv->wx_sem);
162
163         return ret;
164
165 }
166
167 static int r8192_wx_set_crcmon(struct net_device *dev,
168                                struct iw_request_info *info,
169                                union iwreq_data *wrqu, char *extra)
170 {
171         struct r8192_priv *priv = ieee80211_priv(dev);
172         int *parms = (int *)extra;
173         int enable = (parms[0] > 0);
174
175         down(&priv->wx_sem);
176
177         if (enable)
178                 priv->crcmon = 1;
179         else
180                 priv->crcmon = 0;
181
182         DMESG("bad CRC in monitor mode are %s",
183               priv->crcmon ? "accepted" : "rejected");
184
185         up(&priv->wx_sem);
186
187         return 0;
188 }
189
190 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
191                              union iwreq_data *wrqu, char *b)
192 {
193         struct r8192_priv *priv = ieee80211_priv(dev);
194         int ret;
195
196         down(&priv->wx_sem);
197
198         ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
199
200         rtl8192_set_rxconf(dev);
201
202         up(&priv->wx_sem);
203         return ret;
204 }
205
206 struct  iw_range_with_scan_capa {
207         /* Informative stuff (to choose between different interface) */
208         __u32           throughput;     /* To give an idea... */
209         /* In theory this value should be the maximum benchmarked
210          * TCP/IP throughput, because with most of these devices the
211          * bit rate is meaningless (overhead an co) to estimate how
212          * fast the connection will go and pick the fastest one.
213          * I suggest people to play with Netperf or any benchmark...
214          */
215
216         /* NWID (or domain id) */
217         __u32           min_nwid;       /* Minimal NWID we are able to set */
218         __u32           max_nwid;       /* Maximal NWID we are able to set */
219
220         /* Old Frequency (backward compat - moved lower ) */
221         __u16           old_num_channels;
222         __u8            old_num_frequency;
223
224         /* Scan capabilities */
225         __u8            scan_capa;
226 };
227 static int rtl8180_wx_get_range(struct net_device *dev,
228                                 struct iw_request_info *info,
229                                 union iwreq_data *wrqu, char *extra)
230 {
231         struct iw_range *range = (struct iw_range *)extra;
232         struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
233         struct r8192_priv *priv = ieee80211_priv(dev);
234         u16 val;
235         int i;
236
237         wrqu->data.length = sizeof(*range);
238         memset(range, 0, sizeof(*range));
239
240         /* Let's try to keep this struct in the same order as in
241          * linux/include/wireless.h
242          */
243
244         /* TODO: See what values we can set, and remove the ones we can't
245          * set, or fill them with some default data.
246          */
247
248         /* ~5 Mb/s real (802.11b) */
249         range->throughput = 5 * 1000 * 1000;
250
251         /* TODO: Not used in 802.11b? */
252         /* range->min_nwid; */  /* Minimal NWID we are able to set */
253         /* TODO: Not used in 802.11b? */
254         /* range->max_nwid; */  /* Maximal NWID we are able to set */
255
256         /* Old Frequency (backward compat - moved lower ) */
257         /* range->old_num_channels; */
258         /* range->old_num_frequency; */
259         /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
260         if (priv->rf_set_sens != NULL)
261                 range->sensitivity = priv->max_sens;    /* signal level threshold range */
262
263         range->max_qual.qual = 100;
264         /* TODO: Find real max RSSI and stick here */
265         range->max_qual.level = 0;
266         range->max_qual.noise = 0x100 - 98;
267         range->max_qual.updated = 7; /* Updated all three */
268
269         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
270         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
271         range->avg_qual.level = 0x100 - 78;
272         range->avg_qual.noise = 0;
273         range->avg_qual.updated = 7; /* Updated all three */
274
275         range->num_bitrates = RATE_COUNT;
276
277         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
278                 range->bitrate[i] = rtl8180_rates[i];
279
280         range->min_frag = MIN_FRAG_THRESHOLD;
281         range->max_frag = MAX_FRAG_THRESHOLD;
282
283         range->min_pmp = 0;
284         range->max_pmp = 5000000;
285         range->min_pmt = 0;
286         range->max_pmt = 65535*1000;
287         range->pmp_flags = IW_POWER_PERIOD;
288         range->pmt_flags = IW_POWER_TIMEOUT;
289         range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
290
291         range->we_version_compiled = WIRELESS_EXT;
292         range->we_version_source = 16;
293
294         /* range->retry_capa; */        /* What retry options are supported */
295         /* range->retry_flags; */       /* How to decode max/min retry limit */
296         /* range->r_time_flags; */      /* How to decode max/min retry life */
297         /* range->min_retry; */         /* Minimal number of retries */
298         /* range->max_retry; */         /* Maximal number of retries */
299         /* range->min_r_time; */        /* Minimal retry lifetime */
300         /* range->max_r_time; */        /* Maximal retry lifetime */
301
302
303         for (i = 0, val = 0; i < 14; i++) {
304
305                 /* Include only legal frequencies for some countries */
306                 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
307                         range->freq[val].i = i + 1;
308                         range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
309                         range->freq[val].e = 1;
310                         val++;
311                 } else {
312                         /* FIXME: do we need to set anything for channels */
313                         /* we don't use ? */
314                 }
315
316                 if (val == IW_MAX_FREQUENCIES)
317                         break;
318         }
319         range->num_frequency = val;
320         range->num_channels = val;
321         range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
322                           IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
323         tmp->scan_capa = 0x01;
324         return 0;
325 }
326
327
328 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
329                              union iwreq_data *wrqu, char *b)
330 {
331         struct r8192_priv *priv = ieee80211_priv(dev);
332         struct ieee80211_device *ieee = priv->ieee80211;
333         int ret = 0;
334
335         if (!priv->up)
336                 return -ENETDOWN;
337
338         if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
339                 return -EAGAIN;
340         if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
341                 struct iw_scan_req *req = (struct iw_scan_req *)b;
342
343                 if (req->essid_len) {
344                         int len = min_t(int, req->essid_len, IW_ESSID_MAX_SIZE);
345
346                         ieee->current_network.ssid_len = len;
347                         memcpy(ieee->current_network.ssid, 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 };