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