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