]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8187se/r8180_wx.c
Merge tag 'dm-3.6-changes' of git://git.kernel.org/pub/scm/linux/kernel/git/agk/linux-dm
[~andy/linux] / drivers / staging / rtl8187se / r8180_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 thanks the Authors of those projects and the Ndiswrapper
17         project Authors.
18 */
19
20
21 #include "r8180.h"
22 #include "r8180_hw.h"
23
24 #include "ieee80211/dot11d.h"
25
26 u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
27         6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
28
29 #define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
30
31 static CHANNEL_LIST DefaultChannelPlan[] = {
32         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 36, 40, 44, 48, 52, 56, 60, 64}, 19},              /* FCC */
33         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}, 11},                                              /* IC */
34         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},      /* ETSI */
35         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},      /* Spain. Change to ETSI. */
36         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},      /* France. Change to ETSI. */
37         {{14, 36, 40, 44, 48, 52, 56, 60, 64}, 9},                                              /* MKK */
38         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 36, 40, 44, 48, 52, 56, 60, 64}, 22},  /* MKK1 */
39         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 36, 40, 44, 48, 52, 56, 60, 64}, 21},      /* Israel */
40         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 34, 38, 42, 46}, 17},                      /* For 11a , TELEC */
41         {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}, 14}                                   /* For Global Domain. 1-11:active scan, 12-14 passive scan.*/   /* +YJ, 080626 */
42 };
43 static int r8180_wx_get_freq(struct net_device *dev,
44                              struct iw_request_info *a,
45                              union iwreq_data *wrqu, char *b)
46 {
47         struct r8180_priv *priv = ieee80211_priv(dev);
48
49         return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
50 }
51
52
53 int r8180_wx_set_key(struct net_device *dev, struct iw_request_info *info,
54                      union iwreq_data *wrqu, char *key)
55 {
56         struct r8180_priv *priv = ieee80211_priv(dev);
57         struct iw_point *erq = &(wrqu->encoding);
58
59         if (priv->ieee80211->bHwRadioOff)
60                 return 0;
61
62         if (erq->flags & IW_ENCODE_DISABLED)
63
64         if (erq->length > 0) {
65                 u32* tkey = (u32*) key;
66                 priv->key0[0] = tkey[0];
67                 priv->key0[1] = tkey[1];
68                 priv->key0[2] = tkey[2];
69                 priv->key0[3] = tkey[3] & 0xff;
70                 DMESG("Setting wep key to %x %x %x %x",
71                       tkey[0], tkey[1], tkey[2], tkey[3]);
72                 rtl8180_set_hw_wep(dev);
73         }
74         return 0;
75 }
76
77
78 static int r8180_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa,
79                           union iwreq_data *wrqu, char *b)
80 {
81         int *parms = (int *)b;
82         int bi = parms[0];
83
84         struct r8180_priv *priv = ieee80211_priv(dev);
85
86         if (priv->ieee80211->bHwRadioOff)
87                 return 0;
88
89         down(&priv->wx_sem);
90         DMESG("setting beacon interval to %x", bi);
91
92         priv->ieee80211->current_network.beacon_interval = bi;
93         rtl8180_commit(dev);
94         up(&priv->wx_sem);
95
96         return 0;
97 }
98
99
100
101 static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
102                              union iwreq_data *wrqu, char *b)
103 {
104         struct r8180_priv *priv = ieee80211_priv(dev);
105         return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
106 }
107
108
109
110 static int r8180_wx_get_rate(struct net_device *dev,
111                              struct iw_request_info *info,
112                              union iwreq_data *wrqu, char *extra)
113 {
114         struct r8180_priv *priv = ieee80211_priv(dev);
115         return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
116 }
117
118
119
120 static int r8180_wx_set_rate(struct net_device *dev,
121                              struct iw_request_info *info,
122                              union iwreq_data *wrqu, char *extra)
123 {
124         int ret;
125         struct r8180_priv *priv = ieee80211_priv(dev);
126
127
128         if (priv->ieee80211->bHwRadioOff)
129                 return 0;
130
131         down(&priv->wx_sem);
132
133         ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
134
135         up(&priv->wx_sem);
136
137         return ret;
138 }
139
140
141 static int r8180_wx_set_crcmon(struct net_device *dev,
142                                struct iw_request_info *info,
143                                union iwreq_data *wrqu, char *extra)
144 {
145         struct r8180_priv *priv = ieee80211_priv(dev);
146         int *parms = (int *)extra;
147         int enable = (parms[0] > 0);
148         short prev = priv->crcmon;
149
150
151         if (priv->ieee80211->bHwRadioOff)
152                 return 0;
153
154         down(&priv->wx_sem);
155
156         if (enable)
157                 priv->crcmon = 1;
158         else
159                 priv->crcmon = 0;
160
161         DMESG("bad CRC in monitor mode are %s",
162               priv->crcmon ? "accepted" : "rejected");
163
164         if (prev != priv->crcmon && priv->up)   {
165                 rtl8180_down(dev);
166                 rtl8180_up(dev);
167         }
168
169         up(&priv->wx_sem);
170
171         return 0;
172 }
173
174
175 static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
176                              union iwreq_data *wrqu, char *b)
177 {
178         struct r8180_priv *priv = ieee80211_priv(dev);
179         int ret;
180
181
182         if (priv->ieee80211->bHwRadioOff)
183                 return 0;
184
185         down(&priv->wx_sem);
186         if (priv->bInactivePs)  {
187                 if (wrqu->mode == IW_MODE_ADHOC)
188                         IPSLeave(dev);
189         }
190         ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
191
192         up(&priv->wx_sem);
193         return ret;
194 }
195
196 /* YJ,add,080819,for hidden ap */
197 struct  iw_range_with_scan_capa {
198                 /* Informative stuff (to choose between different interface) */
199
200                 __u32           throughput; /* To give an idea... */
201
202                 /* In theory this value should be the maximum benchmarked
203                  * TCP/IP throughput, because with most of these devices the
204                  * bit rate is meaningless (overhead an co) to estimate how
205                  * fast the connection will go and pick the fastest one.
206                  * I suggest people to play with Netperf or any benchmark...
207                  */
208
209                 /* NWID (or domain id)  */
210                 __u32           min_nwid; /* Minimal NWID we are able to set */
211                 __u32                   max_nwid; /* Maximal NWID we are able to set */
212
213                 /* Old Frequency (backward compat - moved lower ) */
214                 __u16                   old_num_channels;
215                 __u8                    old_num_frequency;
216
217                 /* Scan capabilities */
218                 __u8                    scan_capa;
219 };
220 /* YJ,add,080819,for hidden ap */
221
222
223 static int rtl8180_wx_get_range(struct net_device *dev,
224                                 struct iw_request_info *info,
225                                 union iwreq_data *wrqu, char *extra)
226 {
227         struct iw_range *range = (struct iw_range *)extra;
228         struct r8180_priv *priv = ieee80211_priv(dev);
229         u16 val;
230         int i;
231
232         wrqu->data.length = sizeof(*range);
233         memset(range, 0, sizeof(*range));
234
235         /* Let's try to keep this struct in the same order as in
236          * linux/include/wireless.h
237          */
238
239         /* TODO: See what values we can set, and remove the ones we can't
240          * set, or fill them with some default data.
241          */
242
243         /* ~5 Mb/s real (802.11b) */
244         range->throughput = 5 * 1000 * 1000;
245
246         /* TODO: Not used in 802.11b?   */
247 /*      range->min_nwid; */     /* Minimal NWID we are able to set */
248         /* TODO: Not used in 802.11b?   */
249 /*      range->max_nwid; */     /* Maximal NWID we are able to set */
250
251                 /* Old Frequency (backward compat - moved lower ) */
252 /*      range->old_num_channels; */
253 /*      range->old_num_frequency; */
254 /*      range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
255         if (priv->rf_set_sens != NULL)
256                 range->sensitivity = priv->max_sens;    /* signal level threshold range */
257
258         range->max_qual.qual = 100;
259         /* TODO: Find real max RSSI and stick here */
260         range->max_qual.level = 0;
261         range->max_qual.noise = -98;
262         range->max_qual.updated = 7; /* Updated all three */
263
264         range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
265         /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
266         range->avg_qual.level = 20 + -98;
267         range->avg_qual.noise = 0;
268         range->avg_qual.updated = 7; /* Updated all three */
269
270         range->num_bitrates = RATE_COUNT;
271
272         for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
273                 range->bitrate[i] = rtl8180_rates[i];
274
275         range->min_frag = MIN_FRAG_THRESHOLD;
276         range->max_frag = MAX_FRAG_THRESHOLD;
277
278         range->pm_capa = 0;
279
280         range->we_version_compiled = WIRELESS_EXT;
281         range->we_version_source = 16;
282
283                 range->num_channels = 14;
284
285         for (i = 0, val = 0; i < 14; i++) {
286
287                 /* Include only legal frequencies for some countries */
288                 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
289                                 range->freq[val].i = i + 1;
290                         range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
291                         range->freq[val].e = 1;
292                         val++;
293                 } else {
294                         /* FIXME: do we need to set anything for channels */
295                         /* we don't use ? */
296                 }
297
298                 if (val == IW_MAX_FREQUENCIES)
299                 break;
300         }
301
302         range->num_frequency = val;
303         range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 |
304                                                 IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP;
305
306         return 0;
307 }
308
309
310 static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
311                              union iwreq_data *wrqu, char *b)
312 {
313         struct r8180_priv *priv = ieee80211_priv(dev);
314         int ret;
315         struct ieee80211_device* ieee = priv->ieee80211;
316
317
318         if (priv->ieee80211->bHwRadioOff)
319                 return 0;
320
321         if (wrqu->data.flags & IW_SCAN_THIS_ESSID)      {
322                 struct iw_scan_req* req = (struct iw_scan_req*)b;
323                 if (req->essid_len)             {
324                         ieee->current_network.ssid_len = req->essid_len;
325                         memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
326                 }
327         }
328
329         down(&priv->wx_sem);
330         if (priv->up)   {
331                 priv->ieee80211->actscanning = true;
332                 if (priv->bInactivePs && (priv->ieee80211->state != IEEE80211_LINKED))  {
333                         IPSLeave(dev);
334                 ieee80211_softmac_ips_scan_syncro(priv->ieee80211);
335                         ret = 0;
336                 }       else    {
337                         /* prevent scan in BusyTraffic */
338                         /* FIXME: Need to consider last scan time */
339                         if ((priv->link_detect.bBusyTraffic) && (true)) {
340                                 ret = 0;
341                                 printk("Now traffic is busy, please try later!\n");
342                         }       else
343                                 /* prevent scan in BusyTraffic,end */
344                                 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
345                 }
346         }       else
347                         ret = -1;
348
349         up(&priv->wx_sem);
350
351         return ret;
352 }
353
354
355 static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
356                              union iwreq_data *wrqu, char *b)
357 {
358
359         int ret;
360         struct r8180_priv *priv = ieee80211_priv(dev);
361
362         down(&priv->wx_sem);
363         if (priv->up)
364                 ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
365         else
366                 ret = -1;
367
368         up(&priv->wx_sem);
369         return ret;
370 }
371
372
373 static int r8180_wx_set_essid(struct net_device *dev,
374                               struct iw_request_info *a,
375                               union iwreq_data *wrqu, char *b)
376 {
377         struct r8180_priv *priv = ieee80211_priv(dev);
378
379         int ret;
380
381         if (priv->ieee80211->bHwRadioOff)
382                 return 0;
383
384         down(&priv->wx_sem);
385         if (priv->bInactivePs)
386                 IPSLeave(dev);
387
388         ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
389
390         up(&priv->wx_sem);
391         return ret;
392 }
393
394
395 static int r8180_wx_get_essid(struct net_device *dev,
396                               struct iw_request_info *a,
397                               union iwreq_data *wrqu, char *b)
398 {
399         int ret;
400         struct r8180_priv *priv = ieee80211_priv(dev);
401
402         down(&priv->wx_sem);
403
404         ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
405
406         up(&priv->wx_sem);
407
408         return ret;
409 }
410
411
412 static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
413                              union iwreq_data *wrqu, char *b)
414 {
415         int ret;
416         struct r8180_priv *priv = ieee80211_priv(dev);
417
418
419         if (priv->ieee80211->bHwRadioOff)
420                 return 0;
421
422         down(&priv->wx_sem);
423
424         ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
425
426         up(&priv->wx_sem);
427         return ret;
428 }
429
430
431 static int r8180_wx_get_name(struct net_device *dev,
432                              struct iw_request_info *info,
433                              union iwreq_data *wrqu, char *extra)
434 {
435         struct r8180_priv *priv = ieee80211_priv(dev);
436         return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
437 }
438
439 static int r8180_wx_set_frag(struct net_device *dev,
440                              struct iw_request_info *info,
441                              union iwreq_data *wrqu, char *extra)
442 {
443         struct r8180_priv *priv = ieee80211_priv(dev);
444
445         if (priv->ieee80211->bHwRadioOff)
446                 return 0;
447
448         if (wrqu->frag.disabled)
449                 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
450         else {
451                 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
452                     wrqu->frag.value > MAX_FRAG_THRESHOLD)
453                         return -EINVAL;
454
455                 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
456         }
457
458         return 0;
459 }
460
461
462 static int r8180_wx_get_frag(struct net_device *dev,
463                              struct iw_request_info *info,
464                              union iwreq_data *wrqu, char *extra)
465 {
466         struct r8180_priv *priv = ieee80211_priv(dev);
467
468         wrqu->frag.value = priv->ieee80211->fts;
469         wrqu->frag.fixed = 0;   /* no auto select */
470         wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
471
472         return 0;
473 }
474
475
476 static int r8180_wx_set_wap(struct net_device *dev,
477                          struct iw_request_info *info,
478                          union iwreq_data *awrq,
479                          char *extra)
480 {
481         int ret;
482         struct r8180_priv *priv = ieee80211_priv(dev);
483
484         if (priv->ieee80211->bHwRadioOff)
485                 return 0;
486
487         down(&priv->wx_sem);
488
489         ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
490
491         up(&priv->wx_sem);
492         return ret;
493
494 }
495
496
497 static int r8180_wx_get_wap(struct net_device *dev,
498                             struct iw_request_info *info,
499                             union iwreq_data *wrqu, char *extra)
500 {
501         struct r8180_priv *priv = ieee80211_priv(dev);
502
503         return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
504 }
505
506
507 static int r8180_wx_set_enc(struct net_device *dev,
508                             struct iw_request_info *info,
509                             union iwreq_data *wrqu, char *key)
510 {
511         struct r8180_priv *priv = ieee80211_priv(dev);
512         int ret;
513
514         if (priv->ieee80211->bHwRadioOff)
515                 return 0;
516
517
518         down(&priv->wx_sem);
519
520         if (priv->hw_wep) ret = r8180_wx_set_key(dev, info, wrqu, key);
521         else    {
522                 DMESG("Setting SW wep key");
523                 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
524         }
525
526         up(&priv->wx_sem);
527         return ret;
528 }
529
530
531 static int r8180_wx_get_enc(struct net_device *dev,
532                             struct iw_request_info *info,
533                             union iwreq_data *wrqu, char *key)
534 {
535         struct r8180_priv *priv = ieee80211_priv(dev);
536
537         return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
538 }
539
540
541 static int r8180_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
542         iwreq_data *wrqu, char *p)      {
543
544         struct r8180_priv *priv = ieee80211_priv(dev);
545         int *parms = (int*)p;
546         int mode = parms[0];
547
548         if (priv->ieee80211->bHwRadioOff)
549                 return 0;
550
551         priv->ieee80211->active_scan = mode;
552
553         return 1;
554 }
555
556 static int r8180_wx_set_retry(struct net_device *dev,
557                                 struct iw_request_info *info,
558                                 union iwreq_data *wrqu, char *extra)
559 {
560         struct r8180_priv *priv = ieee80211_priv(dev);
561         int err = 0;
562
563         if (priv->ieee80211->bHwRadioOff)
564                 return 0;
565
566         down(&priv->wx_sem);
567
568         if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
569             wrqu->retry.disabled)       {
570                 err = -EINVAL;
571                 goto exit;
572         }
573         if (!(wrqu->retry.flags & IW_RETRY_LIMIT))      {
574                 err = -EINVAL;
575                 goto exit;
576         }
577
578         if (wrqu->retry.value > R8180_MAX_RETRY)        {
579                 err = -EINVAL;
580                 goto exit;
581         }
582         if (wrqu->retry.flags & IW_RETRY_MAX) {
583                 priv->retry_rts = wrqu->retry.value;
584                 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
585
586         }       else {
587                 priv->retry_data = wrqu->retry.value;
588                 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
589         }
590
591         /* FIXME !
592          * We might try to write directly the TX config register
593          * or to restart just the (R)TX process.
594          * I'm unsure if whole reset is really needed
595          */
596
597         rtl8180_commit(dev);
598 exit:
599         up(&priv->wx_sem);
600
601         return err;
602 }
603
604 static int r8180_wx_get_retry(struct net_device *dev,
605                                 struct iw_request_info *info,
606                                 union iwreq_data *wrqu, char *extra)
607 {
608         struct r8180_priv *priv = ieee80211_priv(dev);
609
610
611         wrqu->retry.disabled = 0; /* can't be disabled */
612
613         if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
614             IW_RETRY_LIFETIME)
615                 return -EINVAL;
616
617         if (wrqu->retry.flags & IW_RETRY_MAX) {
618                 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
619                 wrqu->retry.value = priv->retry_rts;
620         } else {
621                 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
622                 wrqu->retry.value = priv->retry_data;
623         }
624
625         return 0;
626 }
627
628 static int r8180_wx_get_sens(struct net_device *dev,
629                                 struct iw_request_info *info,
630                                 union iwreq_data *wrqu, char *extra)
631 {
632         struct r8180_priv *priv = ieee80211_priv(dev);
633         if (priv->rf_set_sens == NULL)
634                 return -1; /* we have not this support for this radio */
635         wrqu->sens.value = priv->sens;
636         return 0;
637 }
638
639
640 static int r8180_wx_set_sens(struct net_device *dev,
641                                 struct iw_request_info *info,
642                                 union iwreq_data *wrqu, char *extra)
643 {
644
645         struct r8180_priv *priv = ieee80211_priv(dev);
646
647         short err = 0;
648
649         if (priv->ieee80211->bHwRadioOff)
650                 return 0;
651
652         down(&priv->wx_sem);
653         if (priv->rf_set_sens == NULL) {
654                 err = -1; /* we have not this support for this radio */
655                 goto exit;
656         }
657         if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
658                 priv->sens = wrqu->sens.value;
659         else
660                 err = -EINVAL;
661
662 exit:
663         up(&priv->wx_sem);
664
665         return err;
666 }
667
668
669 static int r8180_wx_set_rawtx(struct net_device *dev,
670                                struct iw_request_info *info,
671                                union iwreq_data *wrqu, char *extra)
672 {
673         struct r8180_priv *priv = ieee80211_priv(dev);
674         int ret;
675
676         if (priv->ieee80211->bHwRadioOff)
677                 return 0;
678
679         down(&priv->wx_sem);
680
681         ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
682
683         up(&priv->wx_sem);
684
685         return ret;
686
687 }
688
689 static int r8180_wx_get_power(struct net_device *dev,
690                                struct iw_request_info *info,
691                                union iwreq_data *wrqu, char *extra)
692 {
693         int ret;
694         struct r8180_priv *priv = ieee80211_priv(dev);
695
696         down(&priv->wx_sem);
697
698         ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
699
700         up(&priv->wx_sem);
701
702         return ret;
703 }
704
705 static int r8180_wx_set_power(struct net_device *dev,
706                                struct iw_request_info *info,
707                                union iwreq_data *wrqu, char *extra)
708 {
709         int ret;
710         struct r8180_priv *priv = ieee80211_priv(dev);
711
712
713         if (priv->ieee80211->bHwRadioOff)
714                 return 0;
715
716         down(&priv->wx_sem);
717         printk("=>>>>>>>>>>=============================>set power:%d, %d!\n", wrqu->power.disabled, wrqu->power.flags);
718         if (wrqu->power.disabled == 0) {
719                 wrqu->power.flags |= IW_POWER_ALL_R;
720                 wrqu->power.flags |= IW_POWER_TIMEOUT;
721                 wrqu->power.value = 1000;
722         }
723
724         ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
725
726         up(&priv->wx_sem);
727
728         return ret;
729 }
730
731 static int r8180_wx_set_rts(struct net_device *dev,
732                              struct iw_request_info *info,
733                              union iwreq_data *wrqu, char *extra)
734 {
735         struct r8180_priv *priv = ieee80211_priv(dev);
736
737
738         if (priv->ieee80211->bHwRadioOff)
739                 return 0;
740
741         if (wrqu->rts.disabled)
742                 priv->rts = DEFAULT_RTS_THRESHOLD;
743         else {
744                 if (wrqu->rts.value < MIN_RTS_THRESHOLD ||
745                     wrqu->rts.value > MAX_RTS_THRESHOLD)
746                         return -EINVAL;
747
748                 priv->rts = wrqu->rts.value;
749         }
750
751         return 0;
752 }
753 static int r8180_wx_get_rts(struct net_device *dev,
754                              struct iw_request_info *info,
755                              union iwreq_data *wrqu, char *extra)
756 {
757         struct r8180_priv *priv = ieee80211_priv(dev);
758
759
760
761         wrqu->rts.value = priv->rts;
762         wrqu->rts.fixed = 0;    /* no auto select */
763         wrqu->rts.disabled = (wrqu->rts.value == 0);
764
765         return 0;
766 }
767 static int dummy(struct net_device *dev, struct iw_request_info *a,
768                  union iwreq_data *wrqu, char *b)
769 {
770         return -1;
771 }
772
773 static int r8180_wx_get_iwmode(struct net_device *dev,
774                                struct iw_request_info *info,
775                                union iwreq_data *wrqu, char *extra)
776 {
777         struct r8180_priv *priv = ieee80211_priv(dev);
778         struct ieee80211_device *ieee;
779         int ret = 0;
780
781
782
783         down(&priv->wx_sem);
784
785         ieee = priv->ieee80211;
786
787         strcpy(extra, "802.11");
788         if (ieee->modulation & IEEE80211_CCK_MODULATION) {
789                 strcat(extra, "b");
790                 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
791                         strcat(extra, "/g");
792         } else if (ieee->modulation & IEEE80211_OFDM_MODULATION)
793                 strcat(extra, "g");
794
795         up(&priv->wx_sem);
796
797         return ret;
798 }
799 static int r8180_wx_set_iwmode(struct net_device *dev,
800                                struct iw_request_info *info,
801                                union iwreq_data *wrqu, char *extra)
802 {
803         struct r8180_priv *priv = ieee80211_priv(dev);
804         struct ieee80211_device *ieee = priv->ieee80211;
805         int *param = (int *)extra;
806         int ret = 0;
807         int modulation = 0, mode = 0;
808
809
810         if (priv->ieee80211->bHwRadioOff)
811                 return 0;
812
813         down(&priv->wx_sem);
814
815         if (*param == 1) {
816                 modulation |= IEEE80211_CCK_MODULATION;
817                 mode = IEEE_B;
818         printk(KERN_INFO "B mode!\n");
819         } else if (*param == 2) {
820                 modulation |= IEEE80211_OFDM_MODULATION;
821                 mode = IEEE_G;
822         printk(KERN_INFO "G mode!\n");
823         } else if (*param == 3) {
824                 modulation |= IEEE80211_CCK_MODULATION;
825                 modulation |= IEEE80211_OFDM_MODULATION;
826                 mode = IEEE_B|IEEE_G;
827         printk(KERN_INFO "B/G mode!\n");
828         }
829
830         if (ieee->proto_started) {
831                 ieee80211_stop_protocol(ieee);
832                 ieee->mode = mode;
833                 ieee->modulation = modulation;
834                 ieee80211_start_protocol(ieee);
835         } else {
836                 ieee->mode = mode;
837                 ieee->modulation = modulation;
838         }
839
840         up(&priv->wx_sem);
841
842         return ret;
843 }
844 static int r8180_wx_get_preamble(struct net_device *dev,
845                              struct iw_request_info *info,
846                              union iwreq_data *wrqu, char *extra)
847 {
848         struct r8180_priv *priv = ieee80211_priv(dev);
849
850
851
852         down(&priv->wx_sem);
853
854
855
856         *extra = (char) priv->plcp_preamble_mode;       /* 0:auto 1:short 2:long */
857         up(&priv->wx_sem);
858
859         return 0;
860 }
861 static int r8180_wx_set_preamble(struct net_device *dev,
862                              struct iw_request_info *info,
863                              union iwreq_data *wrqu, char *extra)
864 {
865         struct r8180_priv *priv = ieee80211_priv(dev);
866         int ret = 0;
867
868
869         if (priv->ieee80211->bHwRadioOff)
870                 return 0;
871
872         down(&priv->wx_sem);
873         if (*extra < 0 || *extra > 2)
874                 ret = -1;
875         else
876                 priv->plcp_preamble_mode = *((short *)extra) ;
877
878
879
880         up(&priv->wx_sem);
881
882         return ret;
883 }
884 static int r8180_wx_get_siglevel(struct net_device *dev,
885                                struct iw_request_info *info,
886                                union iwreq_data *wrqu, char *extra)
887 {
888         struct r8180_priv *priv = ieee80211_priv(dev);
889         int ret = 0;
890
891
892
893         down(&priv->wx_sem);
894         /* Modify by hikaru 6.5 */
895         *((int *)extra) = priv->wstats.qual.level;/*for interface test ,it should be the priv->wstats.qual.level; */
896
897
898
899         up(&priv->wx_sem);
900
901         return ret;
902 }
903 static int r8180_wx_get_sigqual(struct net_device *dev,
904                                struct iw_request_info *info,
905                                union iwreq_data *wrqu, char *extra)
906 {
907         struct r8180_priv *priv = ieee80211_priv(dev);
908         int ret = 0;
909
910
911
912         down(&priv->wx_sem);
913         /* Modify by hikaru 6.5 */
914         *((int *)extra) = priv->wstats.qual.qual;/* for interface test ,it should be the priv->wstats.qual.qual; */
915
916
917
918         up(&priv->wx_sem);
919
920         return ret;
921 }
922 static int r8180_wx_reset_stats(struct net_device *dev,
923                                 struct iw_request_info *info,
924                                 union iwreq_data *wrqu, char *extra)
925 {
926         struct r8180_priv *priv = ieee80211_priv(dev);
927         down(&priv->wx_sem);
928
929         priv->stats.txrdu = 0;
930         priv->stats.rxrdu = 0;
931         priv->stats.rxnolast = 0;
932         priv->stats.rxnodata = 0;
933         priv->stats.rxnopointer = 0;
934         priv->stats.txnperr = 0;
935         priv->stats.txresumed = 0;
936         priv->stats.rxerr = 0;
937         priv->stats.rxoverflow = 0;
938         priv->stats.rxint = 0;
939
940         priv->stats.txnpokint = 0;
941         priv->stats.txhpokint = 0;
942         priv->stats.txhperr = 0;
943         priv->stats.ints = 0;
944         priv->stats.shints = 0;
945         priv->stats.txoverflow = 0;
946         priv->stats.rxdmafail = 0;
947         priv->stats.txbeacon = 0;
948         priv->stats.txbeaconerr = 0;
949         priv->stats.txlpokint = 0;
950         priv->stats.txlperr = 0;
951         priv->stats.txretry = 0;/* 20060601 */
952         priv->stats.rxcrcerrmin = 0 ;
953         priv->stats.rxcrcerrmid = 0;
954         priv->stats.rxcrcerrmax = 0;
955         priv->stats.rxicverr = 0;
956
957         up(&priv->wx_sem);
958
959         return 0;
960
961 }
962 static int r8180_wx_radio_on(struct net_device *dev,
963                                 struct iw_request_info *info,
964                                 union iwreq_data *wrqu, char *extra)
965 {
966         struct r8180_priv *priv = ieee80211_priv(dev);
967
968         if (priv->ieee80211->bHwRadioOff)
969                 return 0;
970
971
972         down(&priv->wx_sem);
973         priv->rf_wakeup(dev);
974
975         up(&priv->wx_sem);
976
977         return 0;
978
979 }
980
981 static int r8180_wx_radio_off(struct net_device *dev,
982                                 struct iw_request_info *info,
983                                 union iwreq_data *wrqu, char *extra)
984 {
985         struct r8180_priv *priv = ieee80211_priv(dev);
986
987         if (priv->ieee80211->bHwRadioOff)
988                 return 0;
989
990
991         down(&priv->wx_sem);
992         priv->rf_sleep(dev);
993
994         up(&priv->wx_sem);
995
996         return 0;
997
998 }
999 static int r8180_wx_get_channelplan(struct net_device *dev,
1000                              struct iw_request_info *info,
1001                              union iwreq_data *wrqu, char *extra)
1002 {
1003         struct r8180_priv *priv = ieee80211_priv(dev);
1004
1005
1006
1007         down(&priv->wx_sem);
1008         *extra = priv->channel_plan;
1009
1010
1011
1012         up(&priv->wx_sem);
1013
1014         return 0;
1015 }
1016 static int r8180_wx_set_channelplan(struct net_device *dev,
1017                              struct iw_request_info *info,
1018                              union iwreq_data *wrqu, char *extra)
1019 {
1020         struct r8180_priv *priv = ieee80211_priv(dev);
1021         int *val = (int *)extra;
1022         int i;
1023         printk("-----in fun %s\n", __func__);
1024
1025         if (priv->ieee80211->bHwRadioOff)
1026                 return 0;
1027
1028         /* unsigned long flags; */
1029         down(&priv->wx_sem);
1030         if (DefaultChannelPlan[*val].Len != 0)  {
1031                 priv->channel_plan = *val;
1032                 /* Clear old channel map 8 */
1033                 for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
1034                         GET_DOT11D_INFO(priv->ieee80211)->channel_map[i] = 0;
1035
1036                 /* Set new channel map */
1037                 for (i = 1; i <= DefaultChannelPlan[*val].Len; i++)
1038                         GET_DOT11D_INFO(priv->ieee80211)->channel_map[DefaultChannelPlan[*val].Channel[i-1]] = 1;
1039                 
1040         }
1041         up(&priv->wx_sem);
1042
1043         return 0;
1044 }
1045
1046 static int r8180_wx_get_version(struct net_device *dev,
1047                                struct iw_request_info *info,
1048                                union iwreq_data *wrqu, char *extra)
1049 {
1050         struct r8180_priv *priv = ieee80211_priv(dev);
1051         /* struct ieee80211_device *ieee; */
1052
1053         down(&priv->wx_sem);
1054         strcpy(extra, "1020.0808");
1055         up(&priv->wx_sem);
1056
1057         return 0;
1058 }
1059
1060 /* added by amy 080818 */
1061 /*receive datarate from user typing valid rate is from 2 to 108 (1 - 54M), if input 0, return to normal rate adaptive. */
1062 static int r8180_wx_set_forcerate(struct net_device *dev,
1063                              struct iw_request_info *info,
1064                              union iwreq_data *wrqu, char *extra)
1065 {
1066         struct r8180_priv *priv = ieee80211_priv(dev);
1067         u8 forcerate = *extra;
1068
1069         down(&priv->wx_sem);
1070
1071         printk("==============>%s(): forcerate is %d\n", __func__, forcerate);
1072         if ((forcerate == 2) || (forcerate == 4) || (forcerate == 11) || (forcerate == 22) || (forcerate == 12) ||
1073                 (forcerate == 18) || (forcerate == 24) || (forcerate == 36) || (forcerate == 48) || (forcerate == 72) ||
1074                 (forcerate == 96) || (forcerate == 108))
1075         {
1076                 priv->ForcedDataRate = 1;
1077                 priv->ieee80211->rate = forcerate * 5;
1078         }       else if (forcerate == 0)        {
1079                 priv->ForcedDataRate = 0;
1080                 printk("OK! return rate adaptive\n");
1081         }       else
1082                         printk("ERR: wrong rate\n");
1083         up(&priv->wx_sem);
1084         return 0;
1085 }
1086
1087 static int r8180_wx_set_enc_ext(struct net_device *dev,
1088                                                                                 struct iw_request_info *info,
1089                                                                                 union iwreq_data *wrqu, char *extra)
1090 {
1091
1092         struct r8180_priv *priv = ieee80211_priv(dev);
1093
1094         int ret = 0;
1095
1096         if (priv->ieee80211->bHwRadioOff)
1097                 return 0;
1098
1099         down(&priv->wx_sem);
1100         ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
1101         up(&priv->wx_sem);
1102         return ret;
1103
1104 }
1105 static int r8180_wx_set_auth(struct net_device *dev,
1106                              struct iw_request_info *info,
1107                              union iwreq_data *wrqu, char *extra)
1108 {
1109         struct r8180_priv *priv = ieee80211_priv(dev);
1110         int ret = 0;
1111
1112         if (priv->ieee80211->bHwRadioOff)
1113                 return 0;
1114
1115         down(&priv->wx_sem);
1116         ret = ieee80211_wx_set_auth(priv->ieee80211, info, &wrqu->param, extra);
1117         up(&priv->wx_sem);
1118         return ret;
1119 }
1120
1121 static int r8180_wx_set_mlme(struct net_device *dev,
1122                                                                                 struct iw_request_info *info,
1123                                                                                 union iwreq_data *wrqu, char *extra)
1124 {
1125         int ret = 0;
1126         struct r8180_priv *priv = ieee80211_priv(dev);
1127
1128
1129         if (priv->ieee80211->bHwRadioOff)
1130                 return 0;
1131
1132
1133         down(&priv->wx_sem);
1134 #if 1
1135         ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1136 #endif
1137         up(&priv->wx_sem);
1138         return ret;
1139 }
1140 static int r8180_wx_set_gen_ie(struct net_device *dev,
1141                                struct iw_request_info *info,
1142                                union iwreq_data *wrqu, char *extra)
1143 {
1144         int ret = 0;
1145                 struct r8180_priv *priv = ieee80211_priv(dev);
1146
1147
1148         if (priv->ieee80211->bHwRadioOff)
1149                 return 0;
1150
1151                 down(&priv->wx_sem);
1152 #if 1
1153                 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, wrqu->data.length);
1154 #endif
1155                 up(&priv->wx_sem);
1156                 return ret;
1157
1158
1159 }
1160 static iw_handler r8180_wx_handlers[] = {
1161                 NULL,                                   /* SIOCSIWCOMMIT */
1162                 r8180_wx_get_name,                      /* SIOCGIWNAME */
1163                 dummy,                                  /* SIOCSIWNWID */
1164                 dummy,                                  /* SIOCGIWNWID */
1165                 r8180_wx_set_freq,                      /* SIOCSIWFREQ */
1166                 r8180_wx_get_freq,                      /* SIOCGIWFREQ */
1167                 r8180_wx_set_mode,                      /* SIOCSIWMODE */
1168                 r8180_wx_get_mode,                      /* SIOCGIWMODE */
1169                 r8180_wx_set_sens,                      /* SIOCSIWSENS */
1170                 r8180_wx_get_sens,                      /* SIOCGIWSENS */
1171                 NULL,                                   /* SIOCSIWRANGE */
1172                 rtl8180_wx_get_range,                   /* SIOCGIWRANGE */
1173                 NULL,                                   /* SIOCSIWPRIV */
1174                 NULL,                                   /* SIOCGIWPRIV */
1175                 NULL,                                   /* SIOCSIWSTATS */
1176                 NULL,                                   /* SIOCGIWSTATS */
1177                 dummy,                                  /* SIOCSIWSPY */
1178                 dummy,                                  /* SIOCGIWSPY */
1179                 NULL,                                   /* SIOCGIWTHRSPY */
1180                 NULL,                                   /* SIOCWIWTHRSPY */
1181                 r8180_wx_set_wap,                       /* SIOCSIWAP */
1182                 r8180_wx_get_wap,                       /* SIOCGIWAP */
1183                 r8180_wx_set_mlme,                      /* SIOCSIWMLME*/
1184                 dummy,                                  /* SIOCGIWAPLIST -- deprecated */
1185                 r8180_wx_set_scan,                      /* SIOCSIWSCAN */
1186                 r8180_wx_get_scan,                      /* SIOCGIWSCAN */
1187                 r8180_wx_set_essid,                     /* SIOCSIWESSID */
1188                 r8180_wx_get_essid,                     /* SIOCGIWESSID */
1189                 dummy,                                  /* SIOCSIWNICKN */
1190                 dummy,                                  /* SIOCGIWNICKN */
1191                 NULL,                                   /* -- hole -- */
1192                 NULL,                                   /* -- hole -- */
1193                 r8180_wx_set_rate,                      /* SIOCSIWRATE */
1194                 r8180_wx_get_rate,                      /* SIOCGIWRATE */
1195                 r8180_wx_set_rts,                       /* SIOCSIWRTS */
1196                 r8180_wx_get_rts,                       /* SIOCGIWRTS */
1197                 r8180_wx_set_frag,                      /* SIOCSIWFRAG */
1198                 r8180_wx_get_frag,                      /* SIOCGIWFRAG */
1199                 dummy,                                  /* SIOCSIWTXPOW */
1200                 dummy,                                  /* SIOCGIWTXPOW */
1201                 r8180_wx_set_retry,                     /* SIOCSIWRETRY */
1202                 r8180_wx_get_retry,                     /* SIOCGIWRETRY */
1203                 r8180_wx_set_enc,                       /* SIOCSIWENCODE */
1204                 r8180_wx_get_enc,                       /* SIOCGIWENCODE */
1205                 r8180_wx_set_power,                     /* SIOCSIWPOWER */
1206                 r8180_wx_get_power,                     /* SIOCGIWPOWER */
1207                 NULL,                                   /*---hole---*/
1208                 NULL,                                   /*---hole---*/
1209                 r8180_wx_set_gen_ie,                    /* SIOCSIWGENIE */
1210                 NULL,                                   /* SIOCSIWGENIE */
1211                 r8180_wx_set_auth,                      /* SIOCSIWAUTH */
1212                 NULL,                                   /* SIOCSIWAUTH */
1213                 r8180_wx_set_enc_ext,                   /* SIOCSIWENCODEEXT */
1214                 NULL,                                   /* SIOCSIWENCODEEXT */
1215                 NULL,                                   /* SIOCSIWPMKSA */
1216                 NULL,                                   /*---hole---*/
1217 };
1218
1219
1220 static const struct iw_priv_args r8180_private_args[] = {
1221         {
1222                 SIOCIWFIRSTPRIV + 0x0,
1223                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1224         },
1225         {       SIOCIWFIRSTPRIV + 0x1,
1226                 0, 0, "dummy"
1227
1228         },
1229         {
1230                 SIOCIWFIRSTPRIV + 0x2,
1231                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint"
1232         },
1233         {       SIOCIWFIRSTPRIV + 0x3,
1234                 0, 0, "dummy"
1235
1236         },
1237         {
1238                 SIOCIWFIRSTPRIV + 0x4,
1239                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1240
1241         },
1242         {       SIOCIWFIRSTPRIV + 0x5,
1243                 0, 0, "dummy"
1244
1245         },
1246         {
1247                 SIOCIWFIRSTPRIV + 0x6,
1248                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1249
1250         },
1251         {       SIOCIWFIRSTPRIV + 0x7,
1252                 0, 0, "dummy"
1253
1254         },
1255         {
1256                 SIOCIWFIRSTPRIV + 0x8,
1257                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode"
1258         },
1259         {
1260                 SIOCIWFIRSTPRIV + 0x9,
1261                 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode"
1262         },
1263         {
1264                 SIOCIWFIRSTPRIV + 0xA,
1265                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble"
1266         },
1267         {
1268                 SIOCIWFIRSTPRIV + 0xB,
1269                 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble"
1270         },
1271         {       SIOCIWFIRSTPRIV + 0xC,
1272                 0, 0, "dummy"
1273         },
1274         {
1275                 SIOCIWFIRSTPRIV + 0xD,
1276                 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi"
1277         },
1278         {       SIOCIWFIRSTPRIV + 0xE,
1279                 0, 0, "dummy"
1280         },
1281         {
1282                 SIOCIWFIRSTPRIV + 0xF,
1283                 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual"
1284         },
1285         {
1286                 SIOCIWFIRSTPRIV + 0x10,
1287                 0, 0, "resetstats"
1288         },
1289         {
1290                 SIOCIWFIRSTPRIV + 0x11,
1291                 0, 0, "dummy"
1292         },
1293         {
1294                 SIOCIWFIRSTPRIV + 0x12,
1295                 0, 0, "radioon"
1296         },
1297         {
1298                 SIOCIWFIRSTPRIV + 0x13,
1299                 0, 0, "radiooff"
1300         },
1301         {
1302                 SIOCIWFIRSTPRIV + 0x14,
1303                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel"
1304         },
1305         {
1306                 SIOCIWFIRSTPRIV + 0x15,
1307                 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel"
1308         },
1309         {
1310                 SIOCIWFIRSTPRIV + 0x16,
1311                 0, 0, "dummy"
1312         },
1313         {
1314                 SIOCIWFIRSTPRIV + 0x17,
1315                 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion"
1316         },
1317         {
1318                 SIOCIWFIRSTPRIV + 0x18,
1319                 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate"
1320         },
1321 };
1322
1323
1324 static iw_handler r8180_private_handler[] = {
1325         r8180_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
1326         dummy,
1327         r8180_wx_set_beaconinterval,
1328         dummy,
1329         /* r8180_wx_set_monitor_type, */
1330         r8180_wx_set_scan_type,
1331         dummy,
1332         r8180_wx_set_rawtx,
1333         dummy,
1334         r8180_wx_set_iwmode,
1335         r8180_wx_get_iwmode,
1336         r8180_wx_set_preamble,
1337         r8180_wx_get_preamble,
1338         dummy,
1339         r8180_wx_get_siglevel,
1340         dummy,
1341         r8180_wx_get_sigqual,
1342         r8180_wx_reset_stats,
1343         dummy,/* r8180_wx_get_stats */
1344         r8180_wx_radio_on,
1345         r8180_wx_radio_off,
1346         r8180_wx_set_channelplan,
1347         r8180_wx_get_channelplan,
1348         dummy,
1349         r8180_wx_get_version,
1350         r8180_wx_set_forcerate,
1351 };
1352
1353 static inline int is_same_network(struct ieee80211_network *src,
1354                                                                         struct ieee80211_network *dst,
1355                                   struct ieee80211_device *ieee)
1356 {
1357                 /* A network is only a duplicate if the channel, BSSID, ESSID
1358                  * and the capability field (in particular IBSS and BSS) all match.
1359                  * We treat all <hidden> with the same BSSID and channel
1360                  * as one network
1361                  */
1362                 return (((src->ssid_len == dst->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) && /* YJ,mod, 080819,for hidden ap */
1363                         (src->channel == dst->channel) &&
1364                         !memcmp(src->bssid, dst->bssid, ETH_ALEN) &&
1365                         (!memcmp(src->ssid, dst->ssid, src->ssid_len) || (ieee->iw_mode == IW_MODE_INFRA)) &&  /* YJ,mod, 080819,for hidden ap */
1366                         ((src->capability & WLAN_CAPABILITY_IBSS) ==
1367                         (dst->capability & WLAN_CAPABILITY_IBSS)) &&
1368                         ((src->capability & WLAN_CAPABILITY_BSS) ==
1369                         (dst->capability & WLAN_CAPABILITY_BSS)));
1370 }
1371
1372 /* WB modified to show signal to GUI on 18-01-2008 */
1373 static struct iw_statistics *r8180_get_wireless_stats(struct net_device *dev)
1374 {
1375         struct r8180_priv *priv = ieee80211_priv(dev);
1376         struct ieee80211_device* ieee = priv->ieee80211;
1377         struct iw_statistics* wstats = &priv->wstats;
1378         int tmp_level = 0;
1379         int tmp_qual = 0;
1380         int tmp_noise = 0;
1381
1382         if (ieee->state < IEEE80211_LINKED)     {
1383                 wstats->qual.qual = 0;
1384                 wstats->qual.level = 0;
1385                 wstats->qual.noise = 0;
1386                 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1387                 return wstats;
1388         }
1389
1390         tmp_level = (&ieee->current_network)->stats.signal;
1391         tmp_qual = (&ieee->current_network)->stats.signalstrength;
1392         tmp_noise = (&ieee->current_network)->stats.noise;
1393
1394         wstats->qual.level = tmp_level;
1395         wstats->qual.qual = tmp_qual;
1396         wstats->qual.noise = tmp_noise;
1397         wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1398         return wstats;
1399 }
1400
1401 struct iw_handler_def  r8180_wx_handlers_def = {
1402         .standard = r8180_wx_handlers,
1403         .num_standard = ARRAY_SIZE(r8180_wx_handlers),
1404         .private = r8180_private_handler,
1405         .num_private = ARRAY_SIZE(r8180_private_handler),
1406         .num_private_args = sizeof(r8180_private_args) / sizeof(struct iw_priv_args),
1407         .get_wireless_stats = r8180_get_wireless_stats,
1408         .private_args = (struct iw_priv_args *)r8180_private_args,
1409 };
1410
1411