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