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