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