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