Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[linux-2.6.git] / drivers / staging / rtl8187se / r8180_wx.c
blob156b75882290f7a0526ad48f56082c14a7d3cccd
1 /*
2 This file contains wireless extension handlers.
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)
8 Parts of this driver are based on the GPL part
9 of the official realtek driver.
11 Parts of this driver are based on the rtl8180 driver skeleton
12 from Patric Schenke & Andres Salomon.
14 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
16 We want to thanks the Authors of those projects and the Ndiswrapper
17 project Authors.
21 #include "r8180.h"
22 #include "r8180_hw.h"
24 #include "ieee80211/dot11d.h"
26 u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
27 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
29 #define RATE_COUNT ARRAY_SIZE(rtl8180_rates)
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 */
43 static int r8180_wx_get_freq(struct net_device *dev,
44 struct iw_request_info *a,
45 union iwreq_data *wrqu, char *b)
47 struct r8180_priv *priv = ieee80211_priv(dev);
49 return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
53 int r8180_wx_set_key(struct net_device *dev, struct iw_request_info *info,
54 union iwreq_data *wrqu, char *key)
56 struct r8180_priv *priv = ieee80211_priv(dev);
57 struct iw_point *erq = &(wrqu->encoding);
59 if (priv->ieee80211->bHwRadioOff)
60 return 0;
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);
72 return 0;
76 static int r8180_wx_set_beaconinterval(struct net_device *dev, struct iw_request_info *aa,
77 union iwreq_data *wrqu, char *b)
79 int *parms = (int *)b;
80 int bi = parms[0];
82 struct r8180_priv *priv = ieee80211_priv(dev);
84 if (priv->ieee80211->bHwRadioOff)
85 return 0;
87 down(&priv->wx_sem);
88 DMESG("setting beacon interval to %x", bi);
90 priv->ieee80211->current_network.beacon_interval = bi;
91 rtl8180_commit(dev);
92 up(&priv->wx_sem);
94 return 0;
99 static int r8180_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
100 union iwreq_data *wrqu, char *b)
102 struct r8180_priv *priv = ieee80211_priv(dev);
103 return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
108 static int r8180_wx_get_rate(struct net_device *dev,
109 struct iw_request_info *info,
110 union iwreq_data *wrqu, char *extra)
112 struct r8180_priv *priv = ieee80211_priv(dev);
113 return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
118 static int r8180_wx_set_rate(struct net_device *dev,
119 struct iw_request_info *info,
120 union iwreq_data *wrqu, char *extra)
122 int ret;
123 struct r8180_priv *priv = ieee80211_priv(dev);
126 if (priv->ieee80211->bHwRadioOff)
127 return 0;
129 down(&priv->wx_sem);
131 ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
133 up(&priv->wx_sem);
135 return ret;
139 static int r8180_wx_set_crcmon(struct net_device *dev,
140 struct iw_request_info *info,
141 union iwreq_data *wrqu, char *extra)
143 struct r8180_priv *priv = ieee80211_priv(dev);
144 int *parms = (int *)extra;
145 int enable = (parms[0] > 0);
146 short prev = priv->crcmon;
149 if (priv->ieee80211->bHwRadioOff)
150 return 0;
152 down(&priv->wx_sem);
154 if (enable)
155 priv->crcmon = 1;
156 else
157 priv->crcmon = 0;
159 DMESG("bad CRC in monitor mode are %s",
160 priv->crcmon ? "accepted" : "rejected");
162 if (prev != priv->crcmon && priv->up) {
163 rtl8180_down(dev);
164 rtl8180_up(dev);
167 up(&priv->wx_sem);
169 return 0;
173 static int r8180_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
174 union iwreq_data *wrqu, char *b)
176 struct r8180_priv *priv = ieee80211_priv(dev);
177 int ret;
180 if (priv->ieee80211->bHwRadioOff)
181 return 0;
183 down(&priv->wx_sem);
184 if (priv->bInactivePs) {
185 if (wrqu->mode == IW_MODE_ADHOC)
186 IPSLeave(dev);
188 ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
190 up(&priv->wx_sem);
191 return ret;
194 /* YJ,add,080819,for hidden ap */
195 struct iw_range_with_scan_capa {
196 /* Informative stuff (to choose between different interface) */
198 __u32 throughput; /* To give an idea... */
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...
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 */
211 /* Old Frequency (backward compat - moved lower ) */
212 __u16 old_num_channels;
213 __u8 old_num_frequency;
215 /* Scan capabilities */
216 __u8 scan_capa;
218 /* YJ,add,080819,for hidden ap */
221 static int rtl8180_wx_get_range(struct net_device *dev,
222 struct iw_request_info *info,
223 union iwreq_data *wrqu, char *extra)
225 struct iw_range *range = (struct iw_range *)extra;
226 struct r8180_priv *priv = ieee80211_priv(dev);
227 u16 val;
228 int i;
230 wrqu->data.length = sizeof(*range);
231 memset(range, 0, sizeof(*range));
233 /* Let's try to keep this struct in the same order as in
234 * linux/include/wireless.h
237 /* TODO: See what values we can set, and remove the ones we can't
238 * set, or fill them with some default data.
241 /* ~5 Mb/s real (802.11b) */
242 range->throughput = 5 * 1000 * 1000;
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 */
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 */
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 */
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 */
268 range->num_bitrates = RATE_COUNT;
270 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
271 range->bitrate[i] = rtl8180_rates[i];
273 range->min_frag = MIN_FRAG_THRESHOLD;
274 range->max_frag = MAX_FRAG_THRESHOLD;
276 range->pm_capa = 0;
278 range->we_version_compiled = WIRELESS_EXT;
279 range->we_version_source = 16;
281 range->num_channels = 14;
283 for (i = 0, val = 0; i < 14; i++) {
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 ? */
296 if (val == IW_MAX_FREQUENCIES)
297 break;
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;
304 return 0;
308 static int r8180_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
309 union iwreq_data *wrqu, char *b)
311 struct r8180_priv *priv = ieee80211_priv(dev);
312 int ret;
313 struct ieee80211_device* ieee = priv->ieee80211;
316 if (priv->ieee80211->bHwRadioOff)
317 return 0;
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);
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);
344 } else
345 ret = -1;
347 up(&priv->wx_sem);
349 return ret;
353 static int r8180_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
354 union iwreq_data *wrqu, char *b)
357 int ret;
358 struct r8180_priv *priv = ieee80211_priv(dev);
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;
366 up(&priv->wx_sem);
367 return ret;
371 static int r8180_wx_set_essid(struct net_device *dev,
372 struct iw_request_info *a,
373 union iwreq_data *wrqu, char *b)
375 struct r8180_priv *priv = ieee80211_priv(dev);
377 int ret;
379 if (priv->ieee80211->bHwRadioOff)
380 return 0;
382 down(&priv->wx_sem);
383 if (priv->bInactivePs)
384 IPSLeave(dev);
386 ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
388 up(&priv->wx_sem);
389 return ret;
393 static int r8180_wx_get_essid(struct net_device *dev,
394 struct iw_request_info *a,
395 union iwreq_data *wrqu, char *b)
397 int ret;
398 struct r8180_priv *priv = ieee80211_priv(dev);
400 down(&priv->wx_sem);
402 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
404 up(&priv->wx_sem);
406 return ret;
410 static int r8180_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
411 union iwreq_data *wrqu, char *b)
413 int ret;
414 struct r8180_priv *priv = ieee80211_priv(dev);
417 if (priv->ieee80211->bHwRadioOff)
418 return 0;
420 down(&priv->wx_sem);
422 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
424 up(&priv->wx_sem);
425 return ret;
429 static int r8180_wx_get_name(struct net_device *dev,
430 struct iw_request_info *info,
431 union iwreq_data *wrqu, char *extra)
433 struct r8180_priv *priv = ieee80211_priv(dev);
434 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
437 static int r8180_wx_set_frag(struct net_device *dev,
438 struct iw_request_info *info,
439 union iwreq_data *wrqu, char *extra)
441 struct r8180_priv *priv = ieee80211_priv(dev);
443 if (priv->ieee80211->bHwRadioOff)
444 return 0;
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;
453 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
456 return 0;
460 static int r8180_wx_get_frag(struct net_device *dev,
461 struct iw_request_info *info,
462 union iwreq_data *wrqu, char *extra)
464 struct r8180_priv *priv = ieee80211_priv(dev);
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);
470 return 0;
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)
479 int ret;
480 struct r8180_priv *priv = ieee80211_priv(dev);
482 if (priv->ieee80211->bHwRadioOff)
483 return 0;
485 down(&priv->wx_sem);
487 ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
489 up(&priv->wx_sem);
490 return ret;
495 static int r8180_wx_get_wap(struct net_device *dev,
496 struct iw_request_info *info,
497 union iwreq_data *wrqu, char *extra)
499 struct r8180_priv *priv = ieee80211_priv(dev);
501 return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
505 static int r8180_wx_set_enc(struct net_device *dev,
506 struct iw_request_info *info,
507 union iwreq_data *wrqu, char *key)
509 struct r8180_priv *priv = ieee80211_priv(dev);
510 int ret;
512 if (priv->ieee80211->bHwRadioOff)
513 return 0;
516 down(&priv->wx_sem);
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);
524 up(&priv->wx_sem);
525 return ret;
529 static int r8180_wx_get_enc(struct net_device *dev,
530 struct iw_request_info *info,
531 union iwreq_data *wrqu, char *key)
533 struct r8180_priv *priv = ieee80211_priv(dev);
535 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
539 static int r8180_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
540 iwreq_data *wrqu, char *p) {
542 struct r8180_priv *priv = ieee80211_priv(dev);
543 int *parms = (int*)p;
544 int mode = parms[0];
546 if (priv->ieee80211->bHwRadioOff)
547 return 0;
549 priv->ieee80211->active_scan = mode;
551 return 1;
554 static int r8180_wx_set_retry(struct net_device *dev,
555 struct iw_request_info *info,
556 union iwreq_data *wrqu, char *extra)
558 struct r8180_priv *priv = ieee80211_priv(dev);
559 int err = 0;
561 if (priv->ieee80211->bHwRadioOff)
562 return 0;
564 down(&priv->wx_sem);
566 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
567 wrqu->retry.disabled) {
568 err = -EINVAL;
569 goto exit;
571 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
572 err = -EINVAL;
573 goto exit;
576 if (wrqu->retry.value > R8180_MAX_RETRY) {
577 err = -EINVAL;
578 goto exit;
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);
584 } else {
585 priv->retry_data = wrqu->retry.value;
586 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
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
595 rtl8180_commit(dev);
596 exit:
597 up(&priv->wx_sem);
599 return err;
602 static int r8180_wx_get_retry(struct net_device *dev,
603 struct iw_request_info *info,
604 union iwreq_data *wrqu, char *extra)
606 struct r8180_priv *priv = ieee80211_priv(dev);
609 wrqu->retry.disabled = 0; /* can't be disabled */
611 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
612 IW_RETRY_LIFETIME)
613 return -EINVAL;
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;
623 return 0;
626 static int r8180_wx_get_sens(struct net_device *dev,
627 struct iw_request_info *info,
628 union iwreq_data *wrqu, char *extra)
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;
638 static int r8180_wx_set_sens(struct net_device *dev,
639 struct iw_request_info *info,
640 union iwreq_data *wrqu, char *extra)
643 struct r8180_priv *priv = ieee80211_priv(dev);
645 short err = 0;
647 if (priv->ieee80211->bHwRadioOff)
648 return 0;
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;
655 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
656 priv->sens = wrqu->sens.value;
657 else
658 err = -EINVAL;
660 exit:
661 up(&priv->wx_sem);
663 return err;
667 static int r8180_wx_set_rawtx(struct net_device *dev,
668 struct iw_request_info *info,
669 union iwreq_data *wrqu, char *extra)
671 struct r8180_priv *priv = ieee80211_priv(dev);
672 int ret;
674 if (priv->ieee80211->bHwRadioOff)
675 return 0;
677 down(&priv->wx_sem);
679 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
681 up(&priv->wx_sem);
683 return ret;
687 static int r8180_wx_get_power(struct net_device *dev,
688 struct iw_request_info *info,
689 union iwreq_data *wrqu, char *extra)
691 int ret;
692 struct r8180_priv *priv = ieee80211_priv(dev);
694 down(&priv->wx_sem);
696 ret = ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
698 up(&priv->wx_sem);
700 return ret;
703 static int r8180_wx_set_power(struct net_device *dev,
704 struct iw_request_info *info,
705 union iwreq_data *wrqu, char *extra)
707 int ret;
708 struct r8180_priv *priv = ieee80211_priv(dev);
711 if (priv->ieee80211->bHwRadioOff)
712 return 0;
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;
722 ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
724 up(&priv->wx_sem);
726 return ret;
729 static int r8180_wx_set_rts(struct net_device *dev,
730 struct iw_request_info *info,
731 union iwreq_data *wrqu, char *extra)
733 struct r8180_priv *priv = ieee80211_priv(dev);
736 if (priv->ieee80211->bHwRadioOff)
737 return 0;
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;
746 priv->rts = wrqu->rts.value;
749 return 0;
751 static int r8180_wx_get_rts(struct net_device *dev,
752 struct iw_request_info *info,
753 union iwreq_data *wrqu, char *extra)
755 struct r8180_priv *priv = ieee80211_priv(dev);
759 wrqu->rts.value = priv->rts;
760 wrqu->rts.fixed = 0; /* no auto select */
761 wrqu->rts.disabled = (wrqu->rts.value == 0);
763 return 0;
765 static int dummy(struct net_device *dev, struct iw_request_info *a,
766 union iwreq_data *wrqu, char *b)
768 return -1;
771 static int r8180_wx_get_iwmode(struct net_device *dev,
772 struct iw_request_info *info,
773 union iwreq_data *wrqu, char *extra)
775 struct r8180_priv *priv = ieee80211_priv(dev);
776 struct ieee80211_device *ieee;
777 int ret = 0;
781 down(&priv->wx_sem);
783 ieee = priv->ieee80211;
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");
793 up(&priv->wx_sem);
795 return ret;
797 static int r8180_wx_set_iwmode(struct net_device *dev,
798 struct iw_request_info *info,
799 union iwreq_data *wrqu, char *extra)
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;
808 if (priv->ieee80211->bHwRadioOff)
809 return 0;
811 down(&priv->wx_sem);
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");
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;
838 up(&priv->wx_sem);
840 return ret;
842 static int r8180_wx_get_preamble(struct net_device *dev,
843 struct iw_request_info *info,
844 union iwreq_data *wrqu, char *extra)
846 struct r8180_priv *priv = ieee80211_priv(dev);
850 down(&priv->wx_sem);
854 *extra = (char) priv->plcp_preamble_mode; /* 0:auto 1:short 2:long */
855 up(&priv->wx_sem);
857 return 0;
859 static int r8180_wx_set_preamble(struct net_device *dev,
860 struct iw_request_info *info,
861 union iwreq_data *wrqu, char *extra)
863 struct r8180_priv *priv = ieee80211_priv(dev);
864 int ret = 0;
867 if (priv->ieee80211->bHwRadioOff)
868 return 0;
870 down(&priv->wx_sem);
871 if (*extra < 0 || *extra > 2)
872 ret = -1;
873 else
874 priv->plcp_preamble_mode = *((short *)extra) ;
878 up(&priv->wx_sem);
880 return ret;
882 static int r8180_wx_get_siglevel(struct net_device *dev,
883 struct iw_request_info *info,
884 union iwreq_data *wrqu, char *extra)
886 struct r8180_priv *priv = ieee80211_priv(dev);
887 int ret = 0;
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; */
897 up(&priv->wx_sem);
899 return ret;
901 static int r8180_wx_get_sigqual(struct net_device *dev,
902 struct iw_request_info *info,
903 union iwreq_data *wrqu, char *extra)
905 struct r8180_priv *priv = ieee80211_priv(dev);
906 int ret = 0;
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; */
916 up(&priv->wx_sem);
918 return ret;
920 static int r8180_wx_reset_stats(struct net_device *dev,
921 struct iw_request_info *info,
922 union iwreq_data *wrqu, char *extra)
924 struct r8180_priv *priv = ieee80211_priv(dev);
925 down(&priv->wx_sem);
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;
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;
955 up(&priv->wx_sem);
957 return 0;
960 static int r8180_wx_radio_on(struct net_device *dev,
961 struct iw_request_info *info,
962 union iwreq_data *wrqu, char *extra)
964 struct r8180_priv *priv = ieee80211_priv(dev);
966 if (priv->ieee80211->bHwRadioOff)
967 return 0;
970 down(&priv->wx_sem);
971 priv->rf_wakeup(dev);
973 up(&priv->wx_sem);
975 return 0;
979 static int r8180_wx_radio_off(struct net_device *dev,
980 struct iw_request_info *info,
981 union iwreq_data *wrqu, char *extra)
983 struct r8180_priv *priv = ieee80211_priv(dev);
985 if (priv->ieee80211->bHwRadioOff)
986 return 0;
989 down(&priv->wx_sem);
990 priv->rf_sleep(dev);
992 up(&priv->wx_sem);
994 return 0;
997 static int r8180_wx_get_channelplan(struct net_device *dev,
998 struct iw_request_info *info,
999 union iwreq_data *wrqu, char *extra)
1001 struct r8180_priv *priv = ieee80211_priv(dev);
1005 down(&priv->wx_sem);
1006 *extra = priv->channel_plan;
1010 up(&priv->wx_sem);
1012 return 0;
1014 static int r8180_wx_set_channelplan(struct net_device *dev,
1015 struct iw_request_info *info,
1016 union iwreq_data *wrqu, char *extra)
1018 struct r8180_priv *priv = ieee80211_priv(dev);
1019 int *val = (int *)extra;
1020 int i;
1021 printk("-----in fun %s\n", __func__);
1023 if (priv->ieee80211->bHwRadioOff)
1024 return 0;
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;
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;
1039 up(&priv->wx_sem);
1041 return 0;
1044 static int r8180_wx_get_version(struct net_device *dev,
1045 struct iw_request_info *info,
1046 union iwreq_data *wrqu, char *extra)
1048 struct r8180_priv *priv = ieee80211_priv(dev);
1049 /* struct ieee80211_device *ieee; */
1051 down(&priv->wx_sem);
1052 strcpy(extra, "1020.0808");
1053 up(&priv->wx_sem);
1055 return 0;
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)
1064 struct r8180_priv *priv = ieee80211_priv(dev);
1065 u8 forcerate = *extra;
1067 down(&priv->wx_sem);
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))
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;
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)
1090 struct r8180_priv *priv = ieee80211_priv(dev);
1092 int ret = 0;
1094 if (priv->ieee80211->bHwRadioOff)
1095 return 0;
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;
1103 static int r8180_wx_set_auth(struct net_device *dev,
1104 struct iw_request_info *info,
1105 union iwreq_data *wrqu, char *extra)
1107 struct r8180_priv *priv = ieee80211_priv(dev);
1108 int ret = 0;
1110 if (priv->ieee80211->bHwRadioOff)
1111 return 0;
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;
1119 static int r8180_wx_set_mlme(struct net_device *dev,
1120 struct iw_request_info *info,
1121 union iwreq_data *wrqu, char *extra)
1123 int ret = 0;
1124 struct r8180_priv *priv = ieee80211_priv(dev);
1127 if (priv->ieee80211->bHwRadioOff)
1128 return 0;
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;
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)
1142 int ret = 0;
1143 struct r8180_priv *priv = ieee80211_priv(dev);
1146 if (priv->ieee80211->bHwRadioOff)
1147 return 0;
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;
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---*/
1218 static const struct iw_priv_args r8180_private_args[] = {
1220 SIOCIWFIRSTPRIV + 0x0,
1221 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1223 { SIOCIWFIRSTPRIV + 0x1,
1224 0, 0, "dummy"
1228 SIOCIWFIRSTPRIV + 0x2,
1229 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beaconint"
1231 { SIOCIWFIRSTPRIV + 0x3,
1232 0, 0, "dummy"
1236 SIOCIWFIRSTPRIV + 0x4,
1237 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1240 { SIOCIWFIRSTPRIV + 0x5,
1241 0, 0, "dummy"
1245 SIOCIWFIRSTPRIV + 0x6,
1246 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1249 { SIOCIWFIRSTPRIV + 0x7,
1250 0, 0, "dummy"
1254 SIOCIWFIRSTPRIV + 0x8,
1255 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setiwmode"
1258 SIOCIWFIRSTPRIV + 0x9,
1259 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getiwmode"
1262 SIOCIWFIRSTPRIV + 0xA,
1263 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpreamble"
1266 SIOCIWFIRSTPRIV + 0xB,
1267 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpreamble"
1269 { SIOCIWFIRSTPRIV + 0xC,
1270 0, 0, "dummy"
1273 SIOCIWFIRSTPRIV + 0xD,
1274 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getrssi"
1276 { SIOCIWFIRSTPRIV + 0xE,
1277 0, 0, "dummy"
1280 SIOCIWFIRSTPRIV + 0xF,
1281 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getlinkqual"
1284 SIOCIWFIRSTPRIV + 0x10,
1285 0, 0, "resetstats"
1288 SIOCIWFIRSTPRIV + 0x11,
1289 0, 0, "dummy"
1292 SIOCIWFIRSTPRIV + 0x12,
1293 0, 0, "radioon"
1296 SIOCIWFIRSTPRIV + 0x13,
1297 0, 0, "radiooff"
1300 SIOCIWFIRSTPRIV + 0x14,
1301 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setchannel"
1304 SIOCIWFIRSTPRIV + 0x15,
1305 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getchannel"
1308 SIOCIWFIRSTPRIV + 0x16,
1309 0, 0, "dummy"
1312 SIOCIWFIRSTPRIV + 0x17,
1313 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 32, "getversion"
1316 SIOCIWFIRSTPRIV + 0x18,
1317 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setrate"
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,
1351 static inline int is_same_network(struct ieee80211_network *src,
1352 struct ieee80211_network *dst,
1353 struct ieee80211_device *ieee)
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
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)));
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)
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;
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;
1388 tmp_level = (&ieee->current_network)->stats.signal;
1389 tmp_qual = (&ieee->current_network)->stats.signalstrength;
1390 tmp_noise = (&ieee->current_network)->stats.noise;
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;
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,