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