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