]> rtime.felk.cvut.cz Git - mcf548x/linux.git/blob - drivers/staging/rtl8192e/r8192E_wx.c
Initial 2.6.37
[mcf548x/linux.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->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         if(priv->rf_set_sens != NULL)
305                 range->sensitivity = priv->max_sens;    /* signal level threshold range */
306
307         range->max_qual.qual = 100;
308         /* TODO: Find real max RSSI and stick here */
309         range->max_qual.level = 0;
310         range->max_qual.noise = -98;
311         range->max_qual.updated = 7; /* Updated all three */
312
313         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
314         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
315         range->avg_qual.level = 20 + -98;
316         range->avg_qual.noise = 0;
317         range->avg_qual.updated = 7; /* Updated all three */
318
319         range->num_bitrates = RATE_COUNT;
320
321         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
322                 range->bitrate[i] = rtl8180_rates[i];
323         }
324
325         range->min_frag = MIN_FRAG_THRESHOLD;
326         range->max_frag = MAX_FRAG_THRESHOLD;
327
328         range->min_pmp=0;
329         range->max_pmp = 5000000;
330         range->min_pmt = 0;
331         range->max_pmt = 65535*1000;
332         range->pmp_flags = IW_POWER_PERIOD;
333         range->pmt_flags = IW_POWER_TIMEOUT;
334         range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
335         range->we_version_compiled = WIRELESS_EXT;
336         range->we_version_source = 18;
337
338 //      range->retry_capa;      /* What retry options are supported */
339 //      range->retry_flags;     /* How to decode max/min retry limit */
340 //      range->r_time_flags;    /* How to decode max/min retry life */
341 //      range->min_retry;       /* Minimal number of retries */
342 //      range->max_retry;       /* Maximal number of retries */
343 //      range->min_r_time;      /* Minimal retry lifetime */
344 //      range->max_r_time;      /* Maximal retry lifetime */
345
346
347         for (i = 0, val = 0; i < 14; i++) {
348
349                 // Include only legal frequencies for some countries
350 #ifdef ENABLE_DOT11D
351                 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
352 #else
353                 if ((priv->ieee80211->channel_map)[i+1]) {
354 #endif
355                         range->freq[val].i = i + 1;
356                         range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
357                         range->freq[val].e = 1;
358                         val++;
359                 } else {
360                         // FIXME: do we need to set anything for channels
361                         // we don't use ?
362                 }
363
364                 if (val == IW_MAX_FREQUENCIES)
365                 break;
366         }
367         range->num_frequency = val;
368         range->num_channels = val;
369 #if WIRELESS_EXT > 17
370         range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
371                           IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
372 #endif
373         tmp->scan_capa = 0x01;
374         return 0;
375 }
376
377
378 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
379                              union iwreq_data *wrqu, char *b)
380 {
381         struct r8192_priv *priv = ieee80211_priv(dev);
382         struct ieee80211_device* ieee = priv->ieee80211;
383         RT_RF_POWER_STATE       rtState;
384         int ret;
385
386         if (priv->bHwRadioOff)
387                 return 0;
388
389         rtState = priv->ieee80211->eRFPowerState;
390
391         if(!priv->up) return -ENETDOWN;
392         if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
393                 return -EAGAIN;
394
395         if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
396         {
397                 struct iw_scan_req* req = (struct iw_scan_req*)b;
398                 if (req->essid_len)
399                 {
400                         //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
401                         ieee->current_network.ssid_len = req->essid_len;
402                         memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
403                         //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
404                 }
405         }
406
407         down(&priv->wx_sem);
408 #ifdef ENABLE_IPS
409         priv->ieee80211->actscanning = true;
410         if(priv->ieee80211->state != IEEE80211_LINKED){
411                 if(priv->ieee80211->PowerSaveControl.bInactivePs){
412                         if(rtState == eRfOff){
413                                 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
414                                 {
415                                         RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
416                                         up(&priv->wx_sem);
417                                         return -1;
418                                 }
419                                 else{
420                                         //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
421                                         down(&priv->ieee80211->ips_sem);
422                                         IPSLeave(dev);
423                                         up(&priv->ieee80211->ips_sem);
424                                 }
425                         }
426                 }
427                 priv->ieee80211->scanning = 0;
428                 ieee80211_softmac_scan_syncro(priv->ieee80211);
429                 ret = 0;
430         }
431         else
432 #else
433
434         if(priv->ieee80211->state != IEEE80211_LINKED){
435                 priv->ieee80211->scanning = 0;
436                 ieee80211_softmac_scan_syncro(priv->ieee80211);
437                 ret = 0;
438         }
439         else
440 #endif
441         ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
442
443         up(&priv->wx_sem);
444         return ret;
445 }
446
447
448 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
449                              union iwreq_data *wrqu, char *b)
450 {
451
452         int ret;
453         struct r8192_priv *priv = ieee80211_priv(dev);
454
455         if (priv->bHwRadioOff)
456                 return 0;
457
458         if(!priv->up) return -ENETDOWN;
459
460         down(&priv->wx_sem);
461
462         ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
463
464         up(&priv->wx_sem);
465
466         return ret;
467 }
468
469 static int r8192_wx_set_essid(struct net_device *dev,
470                               struct iw_request_info *a,
471                               union iwreq_data *wrqu, char *b)
472 {
473         struct r8192_priv *priv = ieee80211_priv(dev);
474         RT_RF_POWER_STATE       rtState;
475         int ret;
476
477         if (priv->bHwRadioOff)
478                 return 0;
479
480         rtState = priv->ieee80211->eRFPowerState;
481         down(&priv->wx_sem);
482
483 #ifdef ENABLE_IPS
484         down(&priv->ieee80211->ips_sem);
485         IPSLeave(dev);
486         up(&priv->ieee80211->ips_sem);
487 #endif
488         ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
489
490         up(&priv->wx_sem);
491
492         return ret;
493 }
494
495
496
497
498 static int r8192_wx_get_essid(struct net_device *dev,
499                               struct iw_request_info *a,
500                               union iwreq_data *wrqu, char *b)
501 {
502         int ret;
503         struct r8192_priv *priv = ieee80211_priv(dev);
504
505         down(&priv->wx_sem);
506
507         ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
508
509         up(&priv->wx_sem);
510
511         return ret;
512 }
513
514
515 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
516                              union iwreq_data *wrqu, char *b)
517 {
518         int ret;
519         struct r8192_priv *priv = ieee80211_priv(dev);
520
521         if (priv->bHwRadioOff)
522                 return 0;
523
524         down(&priv->wx_sem);
525
526         ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
527
528         up(&priv->wx_sem);
529         return ret;
530 }
531
532 static int r8192_wx_get_name(struct net_device *dev,
533                              struct iw_request_info *info,
534                              union iwreq_data *wrqu, char *extra)
535 {
536         struct r8192_priv *priv = ieee80211_priv(dev);
537         return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
538 }
539
540
541 static int r8192_wx_set_frag(struct net_device *dev,
542                              struct iw_request_info *info,
543                              union iwreq_data *wrqu, char *extra)
544 {
545         struct r8192_priv *priv = ieee80211_priv(dev);
546
547         if (priv->bHwRadioOff)
548                 return 0;
549
550         if (wrqu->frag.disabled)
551                 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
552         else {
553                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
554                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
555                         return -EINVAL;
556
557                 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
558         }
559
560         return 0;
561 }
562
563
564 static int r8192_wx_get_frag(struct net_device *dev,
565                              struct iw_request_info *info,
566                              union iwreq_data *wrqu, char *extra)
567 {
568         struct r8192_priv *priv = ieee80211_priv(dev);
569
570         wrqu->frag.value = priv->ieee80211->fts;
571         wrqu->frag.fixed = 0;   /* no auto select */
572         wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
573
574         return 0;
575 }
576
577
578 static int r8192_wx_set_wap(struct net_device *dev,
579                          struct iw_request_info *info,
580                          union iwreq_data *awrq,
581                          char *extra)
582 {
583
584         int ret;
585         struct r8192_priv *priv = ieee80211_priv(dev);
586 //        struct sockaddr *temp = (struct sockaddr *)awrq;
587
588         if (priv->bHwRadioOff)
589                 return 0;
590
591         down(&priv->wx_sem);
592
593 #ifdef ENABLE_IPS
594         down(&priv->ieee80211->ips_sem);
595         IPSLeave(dev);
596         up(&priv->ieee80211->ips_sem);
597 #endif
598         ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
599
600         up(&priv->wx_sem);
601
602         return ret;
603
604 }
605
606
607 static int r8192_wx_get_wap(struct net_device *dev,
608                             struct iw_request_info *info,
609                             union iwreq_data *wrqu, char *extra)
610 {
611         struct r8192_priv *priv = ieee80211_priv(dev);
612
613         return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
614 }
615
616
617 static int r8192_wx_get_enc(struct net_device *dev,
618                             struct iw_request_info *info,
619                             union iwreq_data *wrqu, char *key)
620 {
621         struct r8192_priv *priv = ieee80211_priv(dev);
622
623         return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
624 }
625
626 static int r8192_wx_set_enc(struct net_device *dev,
627                             struct iw_request_info *info,
628                             union iwreq_data *wrqu, char *key)
629 {
630         struct r8192_priv *priv = ieee80211_priv(dev);
631         int ret;
632
633         struct ieee80211_device *ieee = priv->ieee80211;
634         //u32 TargetContent;
635         u32 hwkey[4]={0,0,0,0};
636         u8 mask=0xff;
637         u32 key_idx=0;
638         u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
639                                 {0x00,0x00,0x00,0x00,0x00,0x01},
640                                 {0x00,0x00,0x00,0x00,0x00,0x02},
641                                 {0x00,0x00,0x00,0x00,0x00,0x03} };
642         int i;
643
644         if (priv->bHwRadioOff)
645                 return 0;
646
647        if(!priv->up) return -ENETDOWN;
648
649         priv->ieee80211->wx_set_enc = 1;
650 #ifdef ENABLE_IPS
651         down(&priv->ieee80211->ips_sem);
652         IPSLeave(dev);
653         up(&priv->ieee80211->ips_sem);
654 #endif
655
656         down(&priv->wx_sem);
657
658         RT_TRACE(COMP_SEC, "Setting SW wep key");
659         ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
660
661         up(&priv->wx_sem);
662
663         //sometimes, the length is zero while we do not type key value
664         if(wrqu->encoding.length!=0){
665
666                 for(i=0 ; i<4 ; i++){
667                         hwkey[i] |=  key[4*i+0]&mask;
668                         if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
669                         if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
670                         hwkey[i] |= (key[4*i+1]&mask)<<8;
671                         hwkey[i] |= (key[4*i+2]&mask)<<16;
672                         hwkey[i] |= (key[4*i+3]&mask)<<24;
673                 }
674
675                 #define CONF_WEP40  0x4
676                 #define CONF_WEP104 0x14
677
678                 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
679                         case 0: key_idx = ieee->tx_keyidx; break;
680                         case 1: key_idx = 0; break;
681                         case 2: key_idx = 1; break;
682                         case 3: key_idx = 2; break;
683                         case 4: key_idx = 3; break;
684                         default: break;
685                 }
686
687                 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
688                 if(wrqu->encoding.length==0x5){
689                 ieee->pairwise_key_type = KEY_TYPE_WEP40;
690                         EnableHWSecurityConfig8192(dev);
691                         setKey( dev,
692                                 key_idx,                //EntryNo
693                                 key_idx,                //KeyIndex
694                                 KEY_TYPE_WEP40,         //KeyType
695                                 zero_addr[key_idx],
696                                 0,                      //DefaultKey
697                                 hwkey);                 //KeyContent
698
699 #if 0
700                         if(key_idx == 0){
701
702                                 //write_nic_byte(dev, SECR, 7);
703                                 setKey( dev,
704                                         4,                      //EntryNo
705                                         key_idx,                      //KeyIndex
706                                         KEY_TYPE_WEP40,        //KeyType
707                                         broadcast_addr,         //addr
708                                         0,                      //DefaultKey
709                                         hwkey);                 //KeyContent
710                         }
711 #endif
712                 }
713
714                 else if(wrqu->encoding.length==0xd){
715                         ieee->pairwise_key_type = KEY_TYPE_WEP104;
716                                 EnableHWSecurityConfig8192(dev);
717                         setKey( dev,
718                                 key_idx,                //EntryNo
719                                 key_idx,                //KeyIndex
720                                 KEY_TYPE_WEP104,        //KeyType
721                                 zero_addr[key_idx],
722                                 0,                      //DefaultKey
723                                 hwkey);                 //KeyContent
724 #if 0
725                         if(key_idx == 0){
726
727                                 //write_nic_byte(dev, SECR, 7);
728                                 setKey( dev,
729                                         4,                      //EntryNo
730                                         key_idx,                      //KeyIndex
731                                         KEY_TYPE_WEP104,        //KeyType
732                                         broadcast_addr,         //addr
733                                         0,                      //DefaultKey
734                                         hwkey);                 //KeyContent
735                         }
736 #endif
737                 }
738                 else printk("wrong type in WEP, not WEP40 and WEP104\n");
739
740
741         }
742
743 #if 0
744         //consider the setting different key index situation
745         //wrqu->encoding.flags = 801 means that we set key with index "1"
746         if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
747                 printk("===>1\n");
748                 //write_nic_byte(dev, SECR, 7);
749                 EnableHWSecurityConfig8192(dev);
750                 //copy wpa config from default key(key0~key3) to broadcast key(key5)
751                 //
752                 key_idx = (wrqu->encoding.flags & 0xf)-1 ;
753                 write_cam(dev, (4*6),   0xffff0000|read_cam(dev, key_idx*6) );
754                 write_cam(dev, (4*6)+1, 0xffffffff);
755                 write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
756                 write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
757                 write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
758                 write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
759         }
760 #endif
761
762         priv->ieee80211->wx_set_enc = 0;
763
764         return ret;
765 }
766
767
768 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
769  iwreq_data *wrqu, char *p){
770
771         struct r8192_priv *priv = ieee80211_priv(dev);
772         int *parms=(int*)p;
773         int mode=parms[0];
774
775         priv->ieee80211->active_scan = mode;
776
777         return 1;
778 }
779
780
781
782 static int r8192_wx_set_retry(struct net_device *dev,
783                                 struct iw_request_info *info,
784                                 union iwreq_data *wrqu, char *extra)
785 {
786         struct r8192_priv *priv = ieee80211_priv(dev);
787         int err = 0;
788
789         if (priv->bHwRadioOff)
790                 return 0;
791
792         down(&priv->wx_sem);
793
794         if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
795             wrqu->retry.disabled){
796                 err = -EINVAL;
797                 goto exit;
798         }
799         if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
800                 err = -EINVAL;
801                 goto exit;
802         }
803
804         if(wrqu->retry.value > R8180_MAX_RETRY){
805                 err= -EINVAL;
806                 goto exit;
807         }
808         if (wrqu->retry.flags & IW_RETRY_MAX) {
809                 priv->retry_rts = wrqu->retry.value;
810                 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
811
812         }else {
813                 priv->retry_data = wrqu->retry.value;
814                 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
815         }
816
817         /* FIXME !
818          * We might try to write directly the TX config register
819          * or to restart just the (R)TX process.
820          * I'm unsure if whole reset is really needed
821          */
822
823         rtl8192_commit(dev);
824         /*
825         if(priv->up){
826                 rtl8180_rtx_disable(dev);
827                 rtl8180_rx_enable(dev);
828                 rtl8180_tx_enable(dev);
829
830         }
831         */
832 exit:
833         up(&priv->wx_sem);
834
835         return err;
836 }
837
838 static int r8192_wx_get_retry(struct net_device *dev,
839                                 struct iw_request_info *info,
840                                 union iwreq_data *wrqu, char *extra)
841 {
842         struct r8192_priv *priv = ieee80211_priv(dev);
843
844
845         wrqu->retry.disabled = 0; /* can't be disabled */
846
847         if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
848             IW_RETRY_LIFETIME)
849                 return -EINVAL;
850
851         if (wrqu->retry.flags & IW_RETRY_MAX) {
852                 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
853                 wrqu->retry.value = priv->retry_rts;
854         } else {
855                 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
856                 wrqu->retry.value = priv->retry_data;
857         }
858         //DMESG("returning %d",wrqu->retry.value);
859
860
861         return 0;
862 }
863
864 static int r8192_wx_get_sens(struct net_device *dev,
865                                 struct iw_request_info *info,
866                                 union iwreq_data *wrqu, char *extra)
867 {
868         struct r8192_priv *priv = ieee80211_priv(dev);
869         if(priv->rf_set_sens == NULL)
870                 return -1; /* we have not this support for this radio */
871         wrqu->sens.value = priv->sens;
872         return 0;
873 }
874
875
876 static int r8192_wx_set_sens(struct net_device *dev,
877                                 struct iw_request_info *info,
878                                 union iwreq_data *wrqu, char *extra)
879 {
880
881         struct r8192_priv *priv = ieee80211_priv(dev);
882
883         short err = 0;
884
885         if (priv->bHwRadioOff)
886                 return 0;
887
888         down(&priv->wx_sem);
889         //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
890         if(priv->rf_set_sens == NULL) {
891                 err= -1; /* we have not this support for this radio */
892                 goto exit;
893         }
894         if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
895                 priv->sens = wrqu->sens.value;
896         else
897                 err= -EINVAL;
898
899 exit:
900         up(&priv->wx_sem);
901
902         return err;
903 }
904
905 #if (WIRELESS_EXT >= 18)
906 static int r8192_wx_set_enc_ext(struct net_device *dev,
907                                         struct iw_request_info *info,
908                                         union iwreq_data *wrqu, char *extra)
909 {
910         int ret=0;
911         struct r8192_priv *priv = ieee80211_priv(dev);
912         struct ieee80211_device* ieee = priv->ieee80211;
913
914         if (priv->bHwRadioOff)
915                 return 0;
916
917         down(&priv->wx_sem);
918
919         priv->ieee80211->wx_set_enc = 1;
920
921 #ifdef ENABLE_IPS
922         down(&priv->ieee80211->ips_sem);
923         IPSLeave(dev);
924         up(&priv->ieee80211->ips_sem);
925 #endif
926
927         ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
928
929         {
930                 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
931                 u8 zero[6] = {0};
932                 u32 key[4] = {0};
933                 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
934                 struct iw_point *encoding = &wrqu->encoding;
935 #if 0
936                 static u8 CAM_CONST_ADDR[4][6] = {
937                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
938                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
939                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
940                         {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
941 #endif
942                 u8 idx = 0, alg = 0, group = 0;
943                 if ((encoding->flags & IW_ENCODE_DISABLED) ||
944                 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
945                 {
946                         ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
947                         CamResetAllEntry(dev);
948                         goto end_hw_sec;
949                 }
950                 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;
951                 idx = encoding->flags & IW_ENCODE_INDEX;
952                 if (idx)
953                         idx --;
954                 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
955
956                 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
957                 {
958                         if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
959                                 alg = KEY_TYPE_WEP104;
960                         ieee->pairwise_key_type = alg;
961                         EnableHWSecurityConfig8192(dev);
962                 }
963                 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
964
965                 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
966                 {
967                         if (ext->key_len == 13)
968                                 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
969                         setKey( dev,
970                                         idx,//EntryNo
971                                         idx, //KeyIndex
972                                         alg,  //KeyType
973                                         zero, //MacAddr
974                                         0,              //DefaultKey
975                                         key);           //KeyContent
976                 }
977                 else if (group)
978                 {
979                         ieee->group_key_type = alg;
980                         setKey( dev,
981                                         idx,//EntryNo
982                                         idx, //KeyIndex
983                                         alg,  //KeyType
984                                         broadcast_addr, //MacAddr
985                                         0,              //DefaultKey
986                                         key);           //KeyContent
987                 }
988                 else //pairwise key
989                 {
990                         if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
991                                                         write_nic_byte(dev, 0x173, 1); //fix aes bug
992                         }
993                         setKey( dev,
994                                         4,//EntryNo
995                                         idx, //KeyIndex
996                                         alg,  //KeyType
997                                         (u8*)ieee->ap_mac_addr, //MacAddr
998                                         0,              //DefaultKey
999                                         key);           //KeyContent
1000                 }
1001
1002
1003         }
1004
1005 end_hw_sec:
1006         priv->ieee80211->wx_set_enc = 0;
1007         up(&priv->wx_sem);
1008         return ret;
1009
1010 }
1011 static int r8192_wx_set_auth(struct net_device *dev,
1012                                         struct iw_request_info *info,
1013                                         union iwreq_data *data, char *extra)
1014 {
1015         int ret=0;
1016         //printk("====>%s()\n", __FUNCTION__);
1017         struct r8192_priv *priv = ieee80211_priv(dev);
1018
1019         if (priv->bHwRadioOff)
1020                 return 0;
1021
1022         down(&priv->wx_sem);
1023         ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
1024         up(&priv->wx_sem);
1025         return ret;
1026 }
1027
1028 static int r8192_wx_set_mlme(struct net_device *dev,
1029                                         struct iw_request_info *info,
1030                                         union iwreq_data *wrqu, char *extra)
1031 {
1032         //printk("====>%s()\n", __FUNCTION__);
1033
1034         int ret=0;
1035         struct r8192_priv *priv = ieee80211_priv(dev);
1036
1037         if (priv->bHwRadioOff)
1038                 return 0;
1039
1040         down(&priv->wx_sem);
1041         ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1042         up(&priv->wx_sem);
1043         return ret;
1044 }
1045 #endif
1046 static int r8192_wx_set_gen_ie(struct net_device *dev,
1047                                         struct iw_request_info *info,
1048                                         union iwreq_data *data, char *extra)
1049 {
1050            //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1051         int ret=0;
1052         struct r8192_priv *priv = ieee80211_priv(dev);
1053
1054         if (priv->bHwRadioOff)
1055                 return 0;
1056
1057         down(&priv->wx_sem);
1058         ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1059         up(&priv->wx_sem);
1060         //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1061         return ret;
1062 }
1063
1064 static int dummy(struct net_device *dev, struct iw_request_info *a,
1065                  union iwreq_data *wrqu,char *b)
1066 {
1067         return -1;
1068 }
1069
1070 // check ac/dc status with the help of user space application */
1071 static int r8192_wx_adapter_power_status(struct net_device *dev,
1072                 struct iw_request_info *info,
1073                 union iwreq_data *wrqu, char *extra)
1074 {
1075         struct r8192_priv *priv = ieee80211_priv(dev);
1076 #ifdef ENABLE_LPS
1077         PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
1078         struct ieee80211_device* ieee = priv->ieee80211;
1079 #endif
1080         down(&priv->wx_sem);
1081
1082 #ifdef ENABLE_LPS
1083         RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
1084         // ieee->ps shall not be set under DC mode, otherwise it conflict
1085         // with Leisure power save mode setting.
1086         //
1087         if(*extra || priv->force_lps) {
1088                 priv->ps_force = false;
1089                 pPSC->bLeisurePs = true;
1090         } else {
1091                 //LZM for PS-Poll AID issue. 090429
1092                 if(priv->ieee80211->state == IEEE80211_LINKED)
1093                         LeisurePSLeave(dev);
1094
1095                 priv->ps_force = true;
1096                 pPSC->bLeisurePs = false;
1097                 ieee->ps = *extra;
1098         }
1099
1100 #endif
1101         up(&priv->wx_sem);
1102         return 0;
1103
1104 }
1105
1106
1107 static iw_handler r8192_wx_handlers[] =
1108 {
1109         NULL,                     /* SIOCSIWCOMMIT */
1110         r8192_wx_get_name,        /* SIOCGIWNAME */
1111         dummy,                    /* SIOCSIWNWID */
1112         dummy,                    /* SIOCGIWNWID */
1113         r8192_wx_set_freq,        /* SIOCSIWFREQ */
1114         r8192_wx_get_freq,        /* SIOCGIWFREQ */
1115         r8192_wx_set_mode,        /* SIOCSIWMODE */
1116         r8192_wx_get_mode,        /* SIOCGIWMODE */
1117         r8192_wx_set_sens,        /* SIOCSIWSENS */
1118         r8192_wx_get_sens,        /* SIOCGIWSENS */
1119         NULL,                     /* SIOCSIWRANGE */
1120         rtl8180_wx_get_range,     /* SIOCGIWRANGE */
1121         NULL,                     /* SIOCSIWPRIV */
1122         NULL,                     /* SIOCGIWPRIV */
1123         NULL,                     /* SIOCSIWSTATS */
1124         NULL,                     /* SIOCGIWSTATS */
1125         dummy,                    /* SIOCSIWSPY */
1126         dummy,                    /* SIOCGIWSPY */
1127         NULL,                     /* SIOCGIWTHRSPY */
1128         NULL,                     /* SIOCWIWTHRSPY */
1129         r8192_wx_set_wap,         /* SIOCSIWAP */
1130         r8192_wx_get_wap,         /* SIOCGIWAP */
1131 #if (WIRELESS_EXT >= 18)
1132         r8192_wx_set_mlme,                     /* MLME-- */
1133 #else
1134          NULL,
1135 #endif
1136         dummy,                     /* SIOCGIWAPLIST -- depricated */
1137         r8192_wx_set_scan,        /* SIOCSIWSCAN */
1138         r8192_wx_get_scan,        /* SIOCGIWSCAN */
1139         r8192_wx_set_essid,       /* SIOCSIWESSID */
1140         r8192_wx_get_essid,       /* SIOCGIWESSID */
1141         dummy,                    /* SIOCSIWNICKN */
1142         dummy,                    /* SIOCGIWNICKN */
1143         NULL,                     /* -- hole -- */
1144         NULL,                     /* -- hole -- */
1145         r8192_wx_set_rate,        /* SIOCSIWRATE */
1146         r8192_wx_get_rate,        /* SIOCGIWRATE */
1147         r8192_wx_set_rts,                    /* SIOCSIWRTS */
1148         r8192_wx_get_rts,                    /* SIOCGIWRTS */
1149         r8192_wx_set_frag,        /* SIOCSIWFRAG */
1150         r8192_wx_get_frag,        /* SIOCGIWFRAG */
1151         dummy,                    /* SIOCSIWTXPOW */
1152         dummy,                    /* SIOCGIWTXPOW */
1153         r8192_wx_set_retry,       /* SIOCSIWRETRY */
1154         r8192_wx_get_retry,       /* SIOCGIWRETRY */
1155         r8192_wx_set_enc,         /* SIOCSIWENCODE */
1156         r8192_wx_get_enc,         /* SIOCGIWENCODE */
1157         r8192_wx_set_power,                    /* SIOCSIWPOWER */
1158         r8192_wx_get_power,                    /* SIOCGIWPOWER */
1159         NULL,                   /*---hole---*/
1160         NULL,                   /*---hole---*/
1161         r8192_wx_set_gen_ie,//NULL,                     /* SIOCSIWGENIE */
1162         NULL,                   /* SIOCSIWGENIE */
1163 #if (WIRELESS_EXT >= 18)
1164         r8192_wx_set_auth,//NULL,                       /* SIOCSIWAUTH */
1165         NULL,//r8192_wx_get_auth,//NULL,                        /* SIOCSIWAUTH */
1166         r8192_wx_set_enc_ext,                   /* SIOCSIWENCODEEXT */
1167 #else
1168         NULL,
1169         NULL,
1170         NULL,
1171 #endif
1172         NULL,//r8192_wx_get_enc_ext,//NULL,                     /* SIOCSIWENCODEEXT */
1173         NULL,                   /* SIOCSIWPMKSA */
1174         NULL,                    /*---hole---*/
1175
1176 };
1177
1178
1179 static const struct iw_priv_args r8192_private_args[] = {
1180
1181         {
1182                 SIOCIWFIRSTPRIV + 0x0,
1183                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1184         },
1185
1186         {
1187                 SIOCIWFIRSTPRIV + 0x1,
1188                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1189
1190         },
1191         {
1192                 SIOCIWFIRSTPRIV + 0x2,
1193                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1194         }
1195         ,
1196         {
1197                 SIOCIWFIRSTPRIV + 0x3,
1198                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1199
1200         }
1201         ,
1202         {
1203                 SIOCIWFIRSTPRIV + 0x4,
1204                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1205                 "set_power"
1206         }
1207
1208 };
1209
1210
1211 static iw_handler r8192_private_handler[] = {
1212         r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
1213         r8192_wx_set_scan_type,
1214         r8192_wx_set_rawtx,
1215         r8192_wx_force_reset,
1216         r8192_wx_adapter_power_status,
1217 };
1218
1219 //#if WIRELESS_EXT >= 17
1220 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1221 {
1222        struct r8192_priv *priv = ieee80211_priv(dev);
1223         struct ieee80211_device* ieee = priv->ieee80211;
1224         struct iw_statistics* wstats = &priv->wstats;
1225         int tmp_level = 0;
1226         int tmp_qual = 0;
1227         int tmp_noise = 0;
1228         if(ieee->state < IEEE80211_LINKED)
1229         {
1230                 wstats->qual.qual = 0;
1231                 wstats->qual.level = 0;
1232                 wstats->qual.noise = 0;
1233                 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1234                 return wstats;
1235         }
1236
1237        tmp_level = (&ieee->current_network)->stats.rssi;
1238         tmp_qual = (&ieee->current_network)->stats.signal;
1239         tmp_noise = (&ieee->current_network)->stats.noise;
1240         //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1241
1242         wstats->qual.level = tmp_level;
1243         wstats->qual.qual = tmp_qual;
1244         wstats->qual.noise = tmp_noise;
1245         wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1246         return wstats;
1247 }
1248 //#endif
1249
1250
1251 struct iw_handler_def  r8192_wx_handlers_def={
1252         .standard = r8192_wx_handlers,
1253         .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1254         .private = r8192_private_handler,
1255         .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1256         .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1257 #if WIRELESS_EXT >= 17
1258         .get_wireless_stats = r8192_get_wireless_stats,
1259 #endif
1260         .private_args = (struct iw_priv_args *)r8192_private_args,
1261 };