Merge remote-tracking branch 'origin' into spi/next
[firefly-linux-kernel-4.4.55.git] / 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->eRFPowerState;
219         down(&priv->wx_sem);
220 #ifdef ENABLE_IPS
221         if(wrqu->mode == IW_MODE_ADHOC){
222
223                 if (priv->PowerSaveControl.bInactivePs) {
224                         if(rtState == eRfOff){
225                                 if(priv->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(priv);
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->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->PowerSaveControl.bInactivePs) {
410                         if(rtState == eRfOff){
411                                 if(priv->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(priv);
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->eRFPowerState;
479         down(&priv->wx_sem);
480
481 #ifdef ENABLE_IPS
482         down(&priv->ieee80211->ips_sem);
483         IPSLeave(priv);
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(priv);
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(priv);
651         up(&priv->ieee80211->ips_sem);
652 #endif
653
654         down(&priv->wx_sem);
655
656         RT_TRACE(COMP_SEC, "Setting SW wep key\n");
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(priv);
689                         setKey(priv, key_idx, key_idx, KEY_TYPE_WEP40,
690                                zero_addr[key_idx], 0, hwkey);
691                 }
692
693                 else if(wrqu->encoding.length==0xd){
694                         ieee->pairwise_key_type = KEY_TYPE_WEP104;
695                                 EnableHWSecurityConfig8192(priv);
696                         setKey(priv, key_idx, key_idx, KEY_TYPE_WEP104,
697                                zero_addr[key_idx], 0, hwkey);
698                 }
699                 else printk("wrong type in WEP, not WEP40 and WEP104\n");
700         }
701
702         priv->ieee80211->wx_set_enc = 0;
703
704         return ret;
705 }
706
707
708 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
709  iwreq_data *wrqu, char *p){
710
711         struct r8192_priv *priv = ieee80211_priv(dev);
712         int *parms=(int*)p;
713         int mode=parms[0];
714
715         priv->ieee80211->active_scan = mode;
716
717         return 1;
718 }
719
720
721
722 static int r8192_wx_set_retry(struct net_device *dev,
723                                 struct iw_request_info *info,
724                                 union iwreq_data *wrqu, char *extra)
725 {
726         struct r8192_priv *priv = ieee80211_priv(dev);
727         int err = 0;
728
729         if (priv->bHwRadioOff)
730                 return 0;
731
732         down(&priv->wx_sem);
733
734         if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
735             wrqu->retry.disabled){
736                 err = -EINVAL;
737                 goto exit;
738         }
739         if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
740                 err = -EINVAL;
741                 goto exit;
742         }
743
744         if(wrqu->retry.value > R8180_MAX_RETRY){
745                 err= -EINVAL;
746                 goto exit;
747         }
748         if (wrqu->retry.flags & IW_RETRY_MAX) {
749                 priv->retry_rts = wrqu->retry.value;
750                 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
751
752         }else {
753                 priv->retry_data = wrqu->retry.value;
754                 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
755         }
756
757         /* FIXME !
758          * We might try to write directly the TX config register
759          * or to restart just the (R)TX process.
760          * I'm unsure if whole reset is really needed
761          */
762
763         rtl8192_commit(priv);
764         /*
765         if(priv->up){
766                 rtl8180_rtx_disable(dev);
767                 rtl8180_rx_enable(dev);
768                 rtl8180_tx_enable(dev);
769
770         }
771         */
772 exit:
773         up(&priv->wx_sem);
774
775         return err;
776 }
777
778 static int r8192_wx_get_retry(struct net_device *dev,
779                                 struct iw_request_info *info,
780                                 union iwreq_data *wrqu, char *extra)
781 {
782         struct r8192_priv *priv = ieee80211_priv(dev);
783
784
785         wrqu->retry.disabled = 0; /* can't be disabled */
786
787         if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
788             IW_RETRY_LIFETIME)
789                 return -EINVAL;
790
791         if (wrqu->retry.flags & IW_RETRY_MAX) {
792                 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
793                 wrqu->retry.value = priv->retry_rts;
794         } else {
795                 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
796                 wrqu->retry.value = priv->retry_data;
797         }
798         //DMESG("returning %d",wrqu->retry.value);
799
800
801         return 0;
802 }
803
804 static int r8192_wx_get_sens(struct net_device *dev,
805                                 struct iw_request_info *info,
806                                 union iwreq_data *wrqu, char *extra)
807 {
808         struct r8192_priv *priv = ieee80211_priv(dev);
809         if(priv->rf_set_sens == NULL)
810                 return -1; /* we have not this support for this radio */
811         wrqu->sens.value = priv->sens;
812         return 0;
813 }
814
815
816 static int r8192_wx_set_sens(struct net_device *dev,
817                                 struct iw_request_info *info,
818                                 union iwreq_data *wrqu, char *extra)
819 {
820
821         struct r8192_priv *priv = ieee80211_priv(dev);
822
823         short err = 0;
824
825         if (priv->bHwRadioOff)
826                 return 0;
827
828         down(&priv->wx_sem);
829         //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
830         if(priv->rf_set_sens == NULL) {
831                 err= -1; /* we have not this support for this radio */
832                 goto exit;
833         }
834         if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
835                 priv->sens = wrqu->sens.value;
836         else
837                 err= -EINVAL;
838
839 exit:
840         up(&priv->wx_sem);
841
842         return err;
843 }
844
845 static int r8192_wx_set_enc_ext(struct net_device *dev,
846                                         struct iw_request_info *info,
847                                         union iwreq_data *wrqu, char *extra)
848 {
849         int ret=0;
850         struct r8192_priv *priv = ieee80211_priv(dev);
851         struct ieee80211_device* ieee = priv->ieee80211;
852
853         if (priv->bHwRadioOff)
854                 return 0;
855
856         down(&priv->wx_sem);
857
858         priv->ieee80211->wx_set_enc = 1;
859
860 #ifdef ENABLE_IPS
861         down(&priv->ieee80211->ips_sem);
862         IPSLeave(priv);
863         up(&priv->ieee80211->ips_sem);
864 #endif
865
866         ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
867
868         {
869                 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
870                 u8 zero[6] = {0};
871                 u32 key[4] = {0};
872                 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
873                 struct iw_point *encoding = &wrqu->encoding;
874                 u8 idx = 0, alg = 0, group = 0;
875
876                 if ((encoding->flags & IW_ENCODE_DISABLED) ||
877                 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
878                 {
879                         ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
880                         CamResetAllEntry(priv);
881                         goto end_hw_sec;
882                 }
883                 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;
884                 idx = encoding->flags & IW_ENCODE_INDEX;
885                 if (idx)
886                         idx --;
887                 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
888
889                 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
890                 {
891                         if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
892                                 alg = KEY_TYPE_WEP104;
893                         ieee->pairwise_key_type = alg;
894                         EnableHWSecurityConfig8192(priv);
895                 }
896                 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
897
898                 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
899                 {
900                         if (ext->key_len == 13)
901                                 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
902                         setKey(priv, idx, idx, alg, zero, 0, key);
903                 }
904                 else if (group)
905                 {
906                         ieee->group_key_type = alg;
907                         setKey(priv, idx, idx, alg, broadcast_addr, 0, key);
908                 }
909                 else //pairwise key
910                 {
911                         if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
912                                                         write_nic_byte(priv, 0x173, 1); //fix aes bug
913                         }
914                         setKey(priv, 4, idx, alg,
915                                (u8*)ieee->ap_mac_addr, 0, key);
916                 }
917
918
919         }
920
921 end_hw_sec:
922         priv->ieee80211->wx_set_enc = 0;
923         up(&priv->wx_sem);
924         return ret;
925
926 }
927 static int r8192_wx_set_auth(struct net_device *dev,
928                                         struct iw_request_info *info,
929                                         union iwreq_data *data, char *extra)
930 {
931         int ret=0;
932         //printk("====>%s()\n", __FUNCTION__);
933         struct r8192_priv *priv = ieee80211_priv(dev);
934
935         if (priv->bHwRadioOff)
936                 return 0;
937
938         down(&priv->wx_sem);
939         ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
940         up(&priv->wx_sem);
941         return ret;
942 }
943
944 static int r8192_wx_set_mlme(struct net_device *dev,
945                                         struct iw_request_info *info,
946                                         union iwreq_data *wrqu, char *extra)
947 {
948         //printk("====>%s()\n", __FUNCTION__);
949
950         int ret=0;
951         struct r8192_priv *priv = ieee80211_priv(dev);
952
953         if (priv->bHwRadioOff)
954                 return 0;
955
956         down(&priv->wx_sem);
957         ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
958         up(&priv->wx_sem);
959         return ret;
960 }
961
962 static int r8192_wx_set_gen_ie(struct net_device *dev,
963                                         struct iw_request_info *info,
964                                         union iwreq_data *data, char *extra)
965 {
966            //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
967         int ret=0;
968         struct r8192_priv *priv = ieee80211_priv(dev);
969
970         if (priv->bHwRadioOff)
971                 return 0;
972
973         down(&priv->wx_sem);
974         ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
975         up(&priv->wx_sem);
976         //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
977         return ret;
978 }
979
980 static int dummy(struct net_device *dev, struct iw_request_info *a,
981                  union iwreq_data *wrqu,char *b)
982 {
983         return -1;
984 }
985
986 // check ac/dc status with the help of user space application */
987 static int r8192_wx_adapter_power_status(struct net_device *dev,
988                 struct iw_request_info *info,
989                 union iwreq_data *wrqu, char *extra)
990 {
991         struct r8192_priv *priv = ieee80211_priv(dev);
992 #ifdef ENABLE_LPS
993         PRT_POWER_SAVE_CONTROL pPSC = &priv->PowerSaveControl;
994         struct ieee80211_device* ieee = priv->ieee80211;
995 #endif
996         down(&priv->wx_sem);
997
998 #ifdef ENABLE_LPS
999         RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
1000         // ieee->ps shall not be set under DC mode, otherwise it conflict
1001         // with Leisure power save mode setting.
1002         //
1003         if(*extra || priv->force_lps) {
1004                 priv->ps_force = false;
1005                 pPSC->bLeisurePs = true;
1006         } else {
1007                 //LZM for PS-Poll AID issue. 090429
1008                 if(priv->ieee80211->state == IEEE80211_LINKED)
1009                         LeisurePSLeave(priv->ieee80211);
1010
1011                 priv->ps_force = true;
1012                 pPSC->bLeisurePs = false;
1013                 ieee->ps = *extra;
1014         }
1015
1016 #endif
1017         up(&priv->wx_sem);
1018         return 0;
1019
1020 }
1021
1022
1023 static iw_handler r8192_wx_handlers[] =
1024 {
1025         NULL,                     /* SIOCSIWCOMMIT */
1026         r8192_wx_get_name,        /* SIOCGIWNAME */
1027         dummy,                    /* SIOCSIWNWID */
1028         dummy,                    /* SIOCGIWNWID */
1029         r8192_wx_set_freq,        /* SIOCSIWFREQ */
1030         r8192_wx_get_freq,        /* SIOCGIWFREQ */
1031         r8192_wx_set_mode,        /* SIOCSIWMODE */
1032         r8192_wx_get_mode,        /* SIOCGIWMODE */
1033         r8192_wx_set_sens,        /* SIOCSIWSENS */
1034         r8192_wx_get_sens,        /* SIOCGIWSENS */
1035         NULL,                     /* SIOCSIWRANGE */
1036         rtl8180_wx_get_range,     /* SIOCGIWRANGE */
1037         NULL,                     /* SIOCSIWPRIV */
1038         NULL,                     /* SIOCGIWPRIV */
1039         NULL,                     /* SIOCSIWSTATS */
1040         NULL,                     /* SIOCGIWSTATS */
1041         dummy,                    /* SIOCSIWSPY */
1042         dummy,                    /* SIOCGIWSPY */
1043         NULL,                     /* SIOCGIWTHRSPY */
1044         NULL,                     /* SIOCWIWTHRSPY */
1045         r8192_wx_set_wap,         /* SIOCSIWAP */
1046         r8192_wx_get_wap,         /* SIOCGIWAP */
1047         r8192_wx_set_mlme,        /* MLME-- */
1048         dummy,                     /* SIOCGIWAPLIST -- depricated */
1049         r8192_wx_set_scan,        /* SIOCSIWSCAN */
1050         r8192_wx_get_scan,        /* SIOCGIWSCAN */
1051         r8192_wx_set_essid,       /* SIOCSIWESSID */
1052         r8192_wx_get_essid,       /* SIOCGIWESSID */
1053         dummy,                    /* SIOCSIWNICKN */
1054         dummy,                    /* SIOCGIWNICKN */
1055         NULL,                     /* -- hole -- */
1056         NULL,                     /* -- hole -- */
1057         r8192_wx_set_rate,        /* SIOCSIWRATE */
1058         r8192_wx_get_rate,        /* SIOCGIWRATE */
1059         r8192_wx_set_rts,                    /* SIOCSIWRTS */
1060         r8192_wx_get_rts,                    /* SIOCGIWRTS */
1061         r8192_wx_set_frag,        /* SIOCSIWFRAG */
1062         r8192_wx_get_frag,        /* SIOCGIWFRAG */
1063         dummy,                    /* SIOCSIWTXPOW */
1064         dummy,                    /* SIOCGIWTXPOW */
1065         r8192_wx_set_retry,       /* SIOCSIWRETRY */
1066         r8192_wx_get_retry,       /* SIOCGIWRETRY */
1067         r8192_wx_set_enc,         /* SIOCSIWENCODE */
1068         r8192_wx_get_enc,         /* SIOCGIWENCODE */
1069         r8192_wx_set_power,                    /* SIOCSIWPOWER */
1070         r8192_wx_get_power,                    /* SIOCGIWPOWER */
1071         NULL,                   /*---hole---*/
1072         NULL,                   /*---hole---*/
1073         r8192_wx_set_gen_ie,//NULL,                     /* SIOCSIWGENIE */
1074         NULL,                   /* SIOCSIWGENIE */
1075         r8192_wx_set_auth,//NULL,                       /* SIOCSIWAUTH */
1076         NULL,//r8192_wx_get_auth,//NULL,                        /* SIOCSIWAUTH */
1077         r8192_wx_set_enc_ext,                   /* SIOCSIWENCODEEXT */
1078         NULL,//r8192_wx_get_enc_ext,//NULL,                     /* SIOCSIWENCODEEXT */
1079         NULL,                   /* SIOCSIWPMKSA */
1080         NULL,                    /*---hole---*/
1081
1082 };
1083
1084
1085 static const struct iw_priv_args r8192_private_args[] = {
1086
1087         {
1088                 SIOCIWFIRSTPRIV + 0x0,
1089                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1090         },
1091
1092         {
1093                 SIOCIWFIRSTPRIV + 0x1,
1094                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1095
1096         },
1097         {
1098                 SIOCIWFIRSTPRIV + 0x2,
1099                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1100         }
1101         ,
1102         {
1103                 SIOCIWFIRSTPRIV + 0x3,
1104                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1105
1106         }
1107         ,
1108         {
1109                 SIOCIWFIRSTPRIV + 0x4,
1110                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1111                 "set_power"
1112         }
1113
1114 };
1115
1116
1117 static iw_handler r8192_private_handler[] = {
1118         r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
1119         r8192_wx_set_scan_type,
1120         r8192_wx_set_rawtx,
1121         r8192_wx_force_reset,
1122         r8192_wx_adapter_power_status,
1123 };
1124
1125 static struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1126 {
1127        struct r8192_priv *priv = ieee80211_priv(dev);
1128         struct ieee80211_device* ieee = priv->ieee80211;
1129         struct iw_statistics* wstats = &priv->wstats;
1130         int tmp_level = 0;
1131         int tmp_qual = 0;
1132         int tmp_noise = 0;
1133         if(ieee->state < IEEE80211_LINKED)
1134         {
1135                 wstats->qual.qual = 0;
1136                 wstats->qual.level = 0;
1137                 wstats->qual.noise = 0;
1138                 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1139                 return wstats;
1140         }
1141
1142        tmp_level = (&ieee->current_network)->stats.rssi;
1143         tmp_qual = (&ieee->current_network)->stats.signal;
1144         tmp_noise = (&ieee->current_network)->stats.noise;
1145         //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1146
1147         wstats->qual.level = tmp_level;
1148         wstats->qual.qual = tmp_qual;
1149         wstats->qual.noise = tmp_noise;
1150         wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1151         return wstats;
1152 }
1153
1154
1155 struct iw_handler_def  r8192_wx_handlers_def={
1156         .standard = r8192_wx_handlers,
1157         .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1158         .private = r8192_private_handler,
1159         .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1160         .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1161         .get_wireless_stats = r8192_get_wireless_stats,
1162         .private_args = (struct iw_priv_args *)r8192_private_args,
1163 };