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