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