• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/drivers/staging/rtl8192e/
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#include <linux/string.h>
21#include "r8192E.h"
22#include "r8192E_hw.h"
23#include "r8192E_wx.h"
24#ifdef ENABLE_DOT11D
25#include "ieee80211/dot11d.h"
26#endif
27
28#define RATE_COUNT 12
29static const u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
30	6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
31
32
33#ifndef ENETDOWN
34#define ENETDOWN 1
35#endif
36static int r8192_wx_get_freq(struct net_device *dev,
37			     struct iw_request_info *a,
38			     union iwreq_data *wrqu, char *b)
39{
40	struct r8192_priv *priv = ieee80211_priv(dev);
41
42	return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
43}
44
45
46static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47			     union iwreq_data *wrqu, char *b)
48{
49	struct r8192_priv *priv=ieee80211_priv(dev);
50
51	return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b);
52}
53
54
55
56static int r8192_wx_get_rate(struct net_device *dev,
57			     struct iw_request_info *info,
58			     union iwreq_data *wrqu, char *extra)
59{
60	struct r8192_priv *priv = ieee80211_priv(dev);
61	return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
62}
63
64
65
66static int r8192_wx_set_rate(struct net_device *dev,
67			     struct iw_request_info *info,
68			     union iwreq_data *wrqu, char *extra)
69{
70	int ret;
71	struct r8192_priv *priv = ieee80211_priv(dev);
72
73	if(priv->bHwRadioOff == true)
74		return 0;
75
76	down(&priv->wx_sem);
77
78	ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
79
80	up(&priv->wx_sem);
81
82	return ret;
83}
84
85
86static int r8192_wx_set_rts(struct net_device *dev,
87			     struct iw_request_info *info,
88			     union iwreq_data *wrqu, char *extra)
89{
90	int ret;
91	struct r8192_priv *priv = ieee80211_priv(dev);
92
93	if(priv->bHwRadioOff == true)
94		return 0;
95
96	down(&priv->wx_sem);
97
98	ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
99
100	up(&priv->wx_sem);
101
102	return ret;
103}
104
105static int r8192_wx_get_rts(struct net_device *dev,
106			     struct iw_request_info *info,
107			     union iwreq_data *wrqu, char *extra)
108{
109	struct r8192_priv *priv = ieee80211_priv(dev);
110	return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
111}
112
113static int r8192_wx_set_power(struct net_device *dev,
114			     struct iw_request_info *info,
115			     union iwreq_data *wrqu, char *extra)
116{
117	int ret;
118	struct r8192_priv *priv = ieee80211_priv(dev);
119
120	if(priv->bHwRadioOff == true)
121		return 0;
122
123	down(&priv->wx_sem);
124
125	ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
126
127	up(&priv->wx_sem);
128
129	return ret;
130}
131
132static int r8192_wx_get_power(struct net_device *dev,
133			     struct iw_request_info *info,
134			     union iwreq_data *wrqu, char *extra)
135{
136	struct r8192_priv *priv = ieee80211_priv(dev);
137	return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
138}
139
140static int r8192_wx_set_rawtx(struct net_device *dev,
141			       struct iw_request_info *info,
142			       union iwreq_data *wrqu, char *extra)
143{
144	struct r8192_priv *priv = ieee80211_priv(dev);
145	int ret;
146
147	if(priv->bHwRadioOff == true)
148		return 0;
149
150	down(&priv->wx_sem);
151
152	ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
153
154	up(&priv->wx_sem);
155
156	return ret;
157
158}
159
160static int r8192_wx_force_reset(struct net_device *dev,
161		struct iw_request_info *info,
162		union iwreq_data *wrqu, char *extra)
163{
164	struct r8192_priv *priv = ieee80211_priv(dev);
165
166	down(&priv->wx_sem);
167
168	printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
169	priv->force_reset = *extra;
170	up(&priv->wx_sem);
171	return 0;
172
173}
174
175
176static int r8192_wx_set_crcmon(struct net_device *dev,
177			       struct iw_request_info *info,
178			       union iwreq_data *wrqu, char *extra)
179{
180	struct r8192_priv *priv = ieee80211_priv(dev);
181	int *parms = (int *)extra;
182	int enable = (parms[0] > 0);
183	short prev = priv->crcmon;
184
185	if(priv->bHwRadioOff == true)
186		return 0;
187
188	down(&priv->wx_sem);
189
190	if(enable)
191		priv->crcmon=1;
192	else
193		priv->crcmon=0;
194
195	DMESG("bad CRC in monitor mode are %s",
196	      priv->crcmon ? "accepted" : "rejected");
197
198	if(prev != priv->crcmon && priv->up){
199		//rtl8180_down(dev);
200		//rtl8180_up(dev);
201	}
202
203	up(&priv->wx_sem);
204
205	return 0;
206}
207
208static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
209			     union iwreq_data *wrqu, char *b)
210{
211	struct r8192_priv *priv = ieee80211_priv(dev);
212	RT_RF_POWER_STATE	rtState;
213	int ret;
214
215	if(priv->bHwRadioOff == true)
216		return 0;
217
218	rtState = priv->ieee80211->eRFPowerState;
219	down(&priv->wx_sem);
220#ifdef ENABLE_IPS
221	if(wrqu->mode == IW_MODE_ADHOC){
222
223		if(priv->ieee80211->PowerSaveControl.bInactivePs){
224			if(rtState == eRfOff){
225				if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
226				{
227					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
228					up(&priv->wx_sem);
229					return -1;
230				}
231				else{
232					RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
233					down(&priv->ieee80211->ips_sem);
234					IPSLeave(dev);
235					up(&priv->ieee80211->ips_sem);
236				}
237			}
238		}
239	}
240#endif
241	ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
242
243	//rtl8187_set_rxconf(dev);
244
245	up(&priv->wx_sem);
246	return ret;
247}
248
249struct  iw_range_with_scan_capa
250{
251        /* Informative stuff (to choose between different interface) */
252        __u32           throughput;     /* To give an idea... */
253        /* In theory this value should be the maximum benchmarked
254         * TCP/IP throughput, because with most of these devices the
255         * bit rate is meaningless (overhead an co) to estimate how
256         * fast the connection will go and pick the fastest one.
257         * I suggest people to play with Netperf or any benchmark...
258         */
259
260        /* NWID (or domain id) */
261        __u32           min_nwid;       /* Minimal NWID we are able to set */
262        __u32           max_nwid;       /* Maximal NWID we are able to set */
263
264        /* Old Frequency (backward compat - moved lower ) */
265        __u16           old_num_channels;
266        __u8            old_num_frequency;
267
268        /* Scan capabilities */
269        __u8            scan_capa;
270};
271static int rtl8180_wx_get_range(struct net_device *dev,
272				struct iw_request_info *info,
273				union iwreq_data *wrqu, char *extra)
274{
275	struct iw_range *range = (struct iw_range *)extra;
276	struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
277	struct r8192_priv *priv = ieee80211_priv(dev);
278	u16 val;
279	int i;
280
281	wrqu->data.length = sizeof(*range);
282	memset(range, 0, sizeof(*range));
283
284	/* Let's try to keep this struct in the same order as in
285	 * linux/include/wireless.h
286	 */
287
288	/* TODO: See what values we can set, and remove the ones we can't
289	 * set, or fill them with some default data.
290	 */
291
292	/* ~5 Mb/s real (802.11b) */
293	range->throughput = 130 * 1000 * 1000;
294
295	// TODO: Not used in 802.11b?
296//	range->min_nwid;	/* Minimal NWID we are able to set */
297	// TODO: Not used in 802.11b?
298//	range->max_nwid;	/* Maximal NWID we are able to set */
299
300        /* Old Frequency (backward compat - moved lower ) */
301//	range->old_num_channels;
302//	range->old_num_frequency;
303//	range->old_freq[6]; /* Filler to keep "version" at the same offset */
304	if(priv->rf_set_sens != NULL)
305		range->sensitivity = priv->max_sens;	/* signal level threshold range */
306
307	range->max_qual.qual = 100;
308	/* TODO: Find real max RSSI and stick here */
309	range->max_qual.level = 0;
310	range->max_qual.noise = -98;
311	range->max_qual.updated = 7; /* Updated all three */
312
313	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
314	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
315	range->avg_qual.level = 20 + -98;
316	range->avg_qual.noise = 0;
317	range->avg_qual.updated = 7; /* Updated all three */
318
319	range->num_bitrates = RATE_COUNT;
320
321	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
322		range->bitrate[i] = rtl8180_rates[i];
323	}
324
325	range->min_frag = MIN_FRAG_THRESHOLD;
326	range->max_frag = MAX_FRAG_THRESHOLD;
327
328	range->min_pmp=0;
329	range->max_pmp = 5000000;
330	range->min_pmt = 0;
331	range->max_pmt = 65535*1000;
332	range->pmp_flags = IW_POWER_PERIOD;
333	range->pmt_flags = IW_POWER_TIMEOUT;
334	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
335	range->we_version_compiled = WIRELESS_EXT;
336	range->we_version_source = 18;
337
338//	range->retry_capa;	/* What retry options are supported */
339//	range->retry_flags;	/* How to decode max/min retry limit */
340//	range->r_time_flags;	/* How to decode max/min retry life */
341//	range->min_retry;	/* Minimal number of retries */
342//	range->max_retry;	/* Maximal number of retries */
343//	range->min_r_time;	/* Minimal retry lifetime */
344//	range->max_r_time;	/* Maximal retry lifetime */
345
346
347	for (i = 0, val = 0; i < 14; i++) {
348
349		// Include only legal frequencies for some countries
350#ifdef ENABLE_DOT11D
351		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
352#else
353		if ((priv->ieee80211->channel_map)[i+1]) {
354#endif
355		        range->freq[val].i = i + 1;
356			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
357			range->freq[val].e = 1;
358			val++;
359		} else {
360			// we don't use ?
361		}
362
363		if (val == IW_MAX_FREQUENCIES)
364		break;
365	}
366	range->num_frequency = val;
367	range->num_channels = val;
368#if WIRELESS_EXT > 17
369	range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
370			  IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
371#endif
372	tmp->scan_capa = 0x01;
373	return 0;
374}
375
376
377static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
378			     union iwreq_data *wrqu, char *b)
379{
380	struct r8192_priv *priv = ieee80211_priv(dev);
381	struct ieee80211_device* ieee = priv->ieee80211;
382	RT_RF_POWER_STATE	rtState;
383	int ret;
384
385	if(priv->bHwRadioOff == true)
386		return 0;
387
388	rtState = priv->ieee80211->eRFPowerState;
389
390	if(!priv->up) return -ENETDOWN;
391	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
392		return -EAGAIN;
393
394	if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
395	{
396		struct iw_scan_req* req = (struct iw_scan_req*)b;
397		if (req->essid_len)
398		{
399			//printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
400			ieee->current_network.ssid_len = req->essid_len;
401			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
402			//printk("=====>network ssid:%s\n", ieee->current_network.ssid);
403		}
404	}
405
406	down(&priv->wx_sem);
407#ifdef ENABLE_IPS
408	priv->ieee80211->actscanning = true;
409	if(priv->ieee80211->state != IEEE80211_LINKED){
410		if(priv->ieee80211->PowerSaveControl.bInactivePs){
411			if(rtState == eRfOff){
412				if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
413				{
414					RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
415					up(&priv->wx_sem);
416					return -1;
417				}
418				else{
419					//RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
420					down(&priv->ieee80211->ips_sem);
421					IPSLeave(dev);
422					up(&priv->ieee80211->ips_sem);
423				}
424			}
425		}
426		priv->ieee80211->scanning = 0;
427		ieee80211_softmac_scan_syncro(priv->ieee80211);
428		ret = 0;
429	}
430	else
431#else
432
433	if(priv->ieee80211->state != IEEE80211_LINKED){
434		priv->ieee80211->scanning = 0;
435		ieee80211_softmac_scan_syncro(priv->ieee80211);
436		ret = 0;
437	}
438	else
439#endif
440	ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
441
442	up(&priv->wx_sem);
443	return ret;
444}
445
446
447static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
448			     union iwreq_data *wrqu, char *b)
449{
450
451	int ret;
452	struct r8192_priv *priv = ieee80211_priv(dev);
453
454	if(priv->bHwRadioOff == true)
455		return 0;
456
457	if(!priv->up) return -ENETDOWN;
458
459	down(&priv->wx_sem);
460
461	ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
462
463	up(&priv->wx_sem);
464
465	return ret;
466}
467
468static int r8192_wx_set_essid(struct net_device *dev,
469			      struct iw_request_info *a,
470			      union iwreq_data *wrqu, char *b)
471{
472	struct r8192_priv *priv = ieee80211_priv(dev);
473	RT_RF_POWER_STATE	rtState;
474	int ret;
475
476	if(priv->bHwRadioOff == true)
477		return 0;
478
479	rtState = priv->ieee80211->eRFPowerState;
480	down(&priv->wx_sem);
481
482#ifdef ENABLE_IPS
483        down(&priv->ieee80211->ips_sem);
484        IPSLeave(dev);
485        up(&priv->ieee80211->ips_sem);
486#endif
487	ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
488
489	up(&priv->wx_sem);
490
491	return ret;
492}
493
494
495
496
497static int r8192_wx_get_essid(struct net_device *dev,
498			      struct iw_request_info *a,
499			      union iwreq_data *wrqu, char *b)
500{
501	int ret;
502	struct r8192_priv *priv = ieee80211_priv(dev);
503
504	down(&priv->wx_sem);
505
506	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
507
508	up(&priv->wx_sem);
509
510	return ret;
511}
512
513
514static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
515			     union iwreq_data *wrqu, char *b)
516{
517	int ret;
518	struct r8192_priv *priv = ieee80211_priv(dev);
519
520	if(priv->bHwRadioOff == true)
521		return 0;
522
523	down(&priv->wx_sem);
524
525	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
526
527	up(&priv->wx_sem);
528	return ret;
529}
530
531static int r8192_wx_get_name(struct net_device *dev,
532			     struct iw_request_info *info,
533			     union iwreq_data *wrqu, char *extra)
534{
535	struct r8192_priv *priv = ieee80211_priv(dev);
536	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
537}
538
539
540static int r8192_wx_set_frag(struct net_device *dev,
541			     struct iw_request_info *info,
542			     union iwreq_data *wrqu, char *extra)
543{
544	struct r8192_priv *priv = ieee80211_priv(dev);
545
546	if(priv->bHwRadioOff == true)
547		return 0;
548
549	if (wrqu->frag.disabled)
550		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
551	else {
552		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
553		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
554			return -EINVAL;
555
556		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
557	}
558
559	return 0;
560}
561
562
563static int r8192_wx_get_frag(struct net_device *dev,
564			     struct iw_request_info *info,
565			     union iwreq_data *wrqu, char *extra)
566{
567	struct r8192_priv *priv = ieee80211_priv(dev);
568
569	wrqu->frag.value = priv->ieee80211->fts;
570	wrqu->frag.fixed = 0;	/* no auto select */
571	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
572
573	return 0;
574}
575
576
577static int r8192_wx_set_wap(struct net_device *dev,
578			 struct iw_request_info *info,
579			 union iwreq_data *awrq,
580			 char *extra)
581{
582
583	int ret;
584	struct r8192_priv *priv = ieee80211_priv(dev);
585//        struct sockaddr *temp = (struct sockaddr *)awrq;
586
587	if(priv->bHwRadioOff == true)
588		return 0;
589
590	down(&priv->wx_sem);
591
592#ifdef ENABLE_IPS
593        down(&priv->ieee80211->ips_sem);
594        IPSLeave(dev);
595        up(&priv->ieee80211->ips_sem);
596#endif
597	ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
598
599	up(&priv->wx_sem);
600
601	return ret;
602
603}
604
605
606static int r8192_wx_get_wap(struct net_device *dev,
607			    struct iw_request_info *info,
608			    union iwreq_data *wrqu, char *extra)
609{
610	struct r8192_priv *priv = ieee80211_priv(dev);
611
612	return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
613}
614
615
616static int r8192_wx_get_enc(struct net_device *dev,
617			    struct iw_request_info *info,
618			    union iwreq_data *wrqu, char *key)
619{
620	struct r8192_priv *priv = ieee80211_priv(dev);
621
622	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
623}
624
625static int r8192_wx_set_enc(struct net_device *dev,
626			    struct iw_request_info *info,
627			    union iwreq_data *wrqu, char *key)
628{
629	struct r8192_priv *priv = ieee80211_priv(dev);
630	int ret;
631
632	struct ieee80211_device *ieee = priv->ieee80211;
633	//u32 TargetContent;
634	u32 hwkey[4]={0,0,0,0};
635	u8 mask=0xff;
636	u32 key_idx=0;
637	u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
638				{0x00,0x00,0x00,0x00,0x00,0x01},
639				{0x00,0x00,0x00,0x00,0x00,0x02},
640				{0x00,0x00,0x00,0x00,0x00,0x03} };
641	int i;
642
643	if(priv->bHwRadioOff == true)
644		return 0;
645
646       if(!priv->up) return -ENETDOWN;
647
648        priv->ieee80211->wx_set_enc = 1;
649#ifdef ENABLE_IPS
650        down(&priv->ieee80211->ips_sem);
651        IPSLeave(dev);
652        up(&priv->ieee80211->ips_sem);
653#endif
654
655	down(&priv->wx_sem);
656
657	RT_TRACE(COMP_SEC, "Setting SW wep key");
658	ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
659
660	up(&priv->wx_sem);
661
662	//sometimes, the length is zero while we do not type key value
663	if(wrqu->encoding.length!=0){
664
665		for(i=0 ; i<4 ; i++){
666			hwkey[i] |=  key[4*i+0]&mask;
667			if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
668			if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
669			hwkey[i] |= (key[4*i+1]&mask)<<8;
670			hwkey[i] |= (key[4*i+2]&mask)<<16;
671			hwkey[i] |= (key[4*i+3]&mask)<<24;
672		}
673
674		#define CONF_WEP40  0x4
675		#define CONF_WEP104 0x14
676
677		switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
678			case 0: key_idx = ieee->tx_keyidx; break;
679			case 1:	key_idx = 0; break;
680			case 2:	key_idx = 1; break;
681			case 3:	key_idx = 2; break;
682			case 4:	key_idx	= 3; break;
683			default: break;
684		}
685
686		//printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
687		if(wrqu->encoding.length==0x5){
688		ieee->pairwise_key_type = KEY_TYPE_WEP40;
689			EnableHWSecurityConfig8192(dev);
690			setKey( dev,
691				key_idx,                //EntryNo
692				key_idx,                //KeyIndex
693				KEY_TYPE_WEP40,         //KeyType
694				zero_addr[key_idx],
695				0,                      //DefaultKey
696				hwkey);                 //KeyContent
697
698		}
699
700		else if(wrqu->encoding.length==0xd){
701			ieee->pairwise_key_type = KEY_TYPE_WEP104;
702				EnableHWSecurityConfig8192(dev);
703			setKey( dev,
704				key_idx,                //EntryNo
705				key_idx,                //KeyIndex
706				KEY_TYPE_WEP104,        //KeyType
707				zero_addr[key_idx],
708				0,                      //DefaultKey
709				hwkey);                 //KeyContent
710		}
711		else printk("wrong type in WEP, not WEP40 and WEP104\n");
712
713
714	}
715
716
717	priv->ieee80211->wx_set_enc = 0;
718
719	return ret;
720}
721
722
723static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
724 iwreq_data *wrqu, char *p){
725
726 	struct r8192_priv *priv = ieee80211_priv(dev);
727	int *parms=(int*)p;
728	int mode=parms[0];
729
730	priv->ieee80211->active_scan = mode;
731
732	return 1;
733}
734
735
736
737static int r8192_wx_set_retry(struct net_device *dev,
738				struct iw_request_info *info,
739				union iwreq_data *wrqu, char *extra)
740{
741	struct r8192_priv *priv = ieee80211_priv(dev);
742	int err = 0;
743
744	if(priv->bHwRadioOff == true)
745		return 0;
746
747	down(&priv->wx_sem);
748
749	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
750	    wrqu->retry.disabled){
751		err = -EINVAL;
752		goto exit;
753	}
754	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
755		err = -EINVAL;
756		goto exit;
757	}
758
759	if(wrqu->retry.value > R8180_MAX_RETRY){
760		err= -EINVAL;
761		goto exit;
762	}
763	if (wrqu->retry.flags & IW_RETRY_MAX) {
764		priv->retry_rts = wrqu->retry.value;
765		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
766
767	}else {
768		priv->retry_data = wrqu->retry.value;
769		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
770	}
771
772
773 	rtl8192_commit(dev);
774	/*
775	if(priv->up){
776		rtl8180_rtx_disable(dev);
777		rtl8180_rx_enable(dev);
778		rtl8180_tx_enable(dev);
779
780	}
781	*/
782exit:
783	up(&priv->wx_sem);
784
785	return err;
786}
787
788static int r8192_wx_get_retry(struct net_device *dev,
789				struct iw_request_info *info,
790				union iwreq_data *wrqu, char *extra)
791{
792	struct r8192_priv *priv = ieee80211_priv(dev);
793
794
795	wrqu->retry.disabled = 0; /* can't be disabled */
796
797	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
798	    IW_RETRY_LIFETIME)
799		return -EINVAL;
800
801	if (wrqu->retry.flags & IW_RETRY_MAX) {
802		wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
803		wrqu->retry.value = priv->retry_rts;
804	} else {
805		wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
806		wrqu->retry.value = priv->retry_data;
807	}
808	//DMESG("returning %d",wrqu->retry.value);
809
810
811	return 0;
812}
813
814static int r8192_wx_get_sens(struct net_device *dev,
815				struct iw_request_info *info,
816				union iwreq_data *wrqu, char *extra)
817{
818	struct r8192_priv *priv = ieee80211_priv(dev);
819	if(priv->rf_set_sens == NULL)
820		return -1; /* we have not this support for this radio */
821	wrqu->sens.value = priv->sens;
822	return 0;
823}
824
825
826static int r8192_wx_set_sens(struct net_device *dev,
827				struct iw_request_info *info,
828				union iwreq_data *wrqu, char *extra)
829{
830
831	struct r8192_priv *priv = ieee80211_priv(dev);
832
833	short err = 0;
834
835	if(priv->bHwRadioOff == true)
836		return 0;
837
838	down(&priv->wx_sem);
839	//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
840	if(priv->rf_set_sens == NULL) {
841		err= -1; /* we have not this support for this radio */
842		goto exit;
843	}
844	if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
845		priv->sens = wrqu->sens.value;
846	else
847		err= -EINVAL;
848
849exit:
850	up(&priv->wx_sem);
851
852	return err;
853}
854
855#if (WIRELESS_EXT >= 18)
856static int r8192_wx_set_enc_ext(struct net_device *dev,
857                                        struct iw_request_info *info,
858                                        union iwreq_data *wrqu, char *extra)
859{
860	int ret=0;
861	struct r8192_priv *priv = ieee80211_priv(dev);
862	struct ieee80211_device* ieee = priv->ieee80211;
863
864	if(priv->bHwRadioOff == true)
865		return 0;
866
867	down(&priv->wx_sem);
868
869	priv->ieee80211->wx_set_enc = 1;
870
871#ifdef ENABLE_IPS
872        down(&priv->ieee80211->ips_sem);
873        IPSLeave(dev);
874        up(&priv->ieee80211->ips_sem);
875#endif
876
877	ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
878
879	{
880		u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
881		u8 zero[6] = {0};
882		u32 key[4] = {0};
883		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
884		struct iw_point *encoding = &wrqu->encoding;
885		u8 idx = 0, alg = 0, group = 0;
886		if ((encoding->flags & IW_ENCODE_DISABLED) ||
887		ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
888		{
889			ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
890			CamResetAllEntry(dev);
891			goto end_hw_sec;
892		}
893		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
894		idx = encoding->flags & IW_ENCODE_INDEX;
895		if (idx)
896			idx --;
897		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
898
899		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
900		{
901			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
902				alg = KEY_TYPE_WEP104;
903			ieee->pairwise_key_type = alg;
904			EnableHWSecurityConfig8192(dev);
905		}
906		memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
907
908		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
909		{
910			if (ext->key_len == 13)
911				ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
912			setKey( dev,
913					idx,//EntryNo
914					idx, //KeyIndex
915					alg,  //KeyType
916					zero, //MacAddr
917					0,              //DefaultKey
918					key);           //KeyContent
919		}
920		else if (group)
921		{
922			ieee->group_key_type = alg;
923			setKey( dev,
924					idx,//EntryNo
925					idx, //KeyIndex
926					alg,  //KeyType
927					broadcast_addr, //MacAddr
928					0,              //DefaultKey
929					key);           //KeyContent
930		}
931		else //pairwise key
932		{
933			if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
934							write_nic_byte(dev, 0x173, 1); //fix aes bug
935			}
936			setKey( dev,
937					4,//EntryNo
938					idx, //KeyIndex
939					alg,  //KeyType
940					(u8*)ieee->ap_mac_addr, //MacAddr
941					0,              //DefaultKey
942					key);           //KeyContent
943		}
944
945
946	}
947
948end_hw_sec:
949	priv->ieee80211->wx_set_enc = 0;
950	up(&priv->wx_sem);
951	return ret;
952
953}
954static int r8192_wx_set_auth(struct net_device *dev,
955                                        struct iw_request_info *info,
956                                        union iwreq_data *data, char *extra)
957{
958	int ret=0;
959	//printk("====>%s()\n", __FUNCTION__);
960	struct r8192_priv *priv = ieee80211_priv(dev);
961
962	if(priv->bHwRadioOff == true)
963		return 0;
964
965	down(&priv->wx_sem);
966	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
967	up(&priv->wx_sem);
968	return ret;
969}
970
971static int r8192_wx_set_mlme(struct net_device *dev,
972                                        struct iw_request_info *info,
973                                        union iwreq_data *wrqu, char *extra)
974{
975	//printk("====>%s()\n", __FUNCTION__);
976
977	int ret=0;
978	struct r8192_priv *priv = ieee80211_priv(dev);
979
980	if(priv->bHwRadioOff == true)
981		return 0;
982
983	down(&priv->wx_sem);
984	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
985	up(&priv->wx_sem);
986	return ret;
987}
988#endif
989static int r8192_wx_set_gen_ie(struct net_device *dev,
990                                        struct iw_request_info *info,
991                                        union iwreq_data *data, char *extra)
992{
993	   //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
994	int ret=0;
995        struct r8192_priv *priv = ieee80211_priv(dev);
996
997	if(priv->bHwRadioOff == true)
998		return 0;
999
1000        down(&priv->wx_sem);
1001        ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1002        up(&priv->wx_sem);
1003	//printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1004        return ret;
1005}
1006
1007static int dummy(struct net_device *dev, struct iw_request_info *a,
1008		 union iwreq_data *wrqu,char *b)
1009{
1010	return -1;
1011}
1012
1013// check ac/dc status with the help of user space application */
1014static int r8192_wx_adapter_power_status(struct net_device *dev,
1015		struct iw_request_info *info,
1016		union iwreq_data *wrqu, char *extra)
1017{
1018	struct r8192_priv *priv = ieee80211_priv(dev);
1019#ifdef ENABLE_LPS
1020	PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
1021	struct ieee80211_device* ieee = priv->ieee80211;
1022#endif
1023	down(&priv->wx_sem);
1024
1025#ifdef ENABLE_LPS
1026	RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra ==  6)?"DC power":"AC power");
1027	// ieee->ps shall not be set under DC mode, otherwise it conflict
1028	// with Leisure power save mode setting.
1029	//
1030	if(*extra || priv->force_lps) {
1031		priv->ps_force = false;
1032		pPSC->bLeisurePs = true;
1033	} else {
1034		//LZM for PS-Poll AID issue. 090429
1035		if(priv->ieee80211->state == IEEE80211_LINKED)
1036			LeisurePSLeave(dev);
1037
1038		priv->ps_force = true;
1039		pPSC->bLeisurePs = false;
1040		ieee->ps = *extra;
1041	}
1042
1043#endif
1044	up(&priv->wx_sem);
1045	return 0;
1046
1047}
1048
1049
1050static iw_handler r8192_wx_handlers[] =
1051{
1052        NULL,                     /* SIOCSIWCOMMIT */
1053        r8192_wx_get_name,   	  /* SIOCGIWNAME */
1054        dummy,                    /* SIOCSIWNWID */
1055        dummy,                    /* SIOCGIWNWID */
1056        r8192_wx_set_freq,        /* SIOCSIWFREQ */
1057        r8192_wx_get_freq,        /* SIOCGIWFREQ */
1058        r8192_wx_set_mode,        /* SIOCSIWMODE */
1059        r8192_wx_get_mode,        /* SIOCGIWMODE */
1060        r8192_wx_set_sens,        /* SIOCSIWSENS */
1061        r8192_wx_get_sens,        /* SIOCGIWSENS */
1062        NULL,                     /* SIOCSIWRANGE */
1063        rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
1064        NULL,                     /* SIOCSIWPRIV */
1065        NULL,                     /* SIOCGIWPRIV */
1066        NULL,                     /* SIOCSIWSTATS */
1067        NULL,                     /* SIOCGIWSTATS */
1068        dummy,                    /* SIOCSIWSPY */
1069        dummy,                    /* SIOCGIWSPY */
1070        NULL,                     /* SIOCGIWTHRSPY */
1071        NULL,                     /* SIOCWIWTHRSPY */
1072        r8192_wx_set_wap,      	  /* SIOCSIWAP */
1073        r8192_wx_get_wap,         /* SIOCGIWAP */
1074#if (WIRELESS_EXT >= 18)
1075        r8192_wx_set_mlme,                     /* MLME-- */
1076#else
1077	 NULL,
1078#endif
1079        dummy,                     /* SIOCGIWAPLIST -- depricated */
1080        r8192_wx_set_scan,        /* SIOCSIWSCAN */
1081        r8192_wx_get_scan,        /* SIOCGIWSCAN */
1082        r8192_wx_set_essid,       /* SIOCSIWESSID */
1083        r8192_wx_get_essid,       /* SIOCGIWESSID */
1084        dummy,                    /* SIOCSIWNICKN */
1085        dummy,                    /* SIOCGIWNICKN */
1086        NULL,                     /* -- hole -- */
1087        NULL,                     /* -- hole -- */
1088        r8192_wx_set_rate,        /* SIOCSIWRATE */
1089        r8192_wx_get_rate,        /* SIOCGIWRATE */
1090        r8192_wx_set_rts,                    /* SIOCSIWRTS */
1091        r8192_wx_get_rts,                    /* SIOCGIWRTS */
1092        r8192_wx_set_frag,        /* SIOCSIWFRAG */
1093        r8192_wx_get_frag,        /* SIOCGIWFRAG */
1094        dummy,                    /* SIOCSIWTXPOW */
1095        dummy,                    /* SIOCGIWTXPOW */
1096        r8192_wx_set_retry,       /* SIOCSIWRETRY */
1097        r8192_wx_get_retry,       /* SIOCGIWRETRY */
1098        r8192_wx_set_enc,         /* SIOCSIWENCODE */
1099        r8192_wx_get_enc,         /* SIOCGIWENCODE */
1100        r8192_wx_set_power,                    /* SIOCSIWPOWER */
1101        r8192_wx_get_power,                    /* SIOCGIWPOWER */
1102	NULL,			/*---hole---*/
1103	NULL, 			/*---hole---*/
1104	r8192_wx_set_gen_ie,//NULL, 			/* SIOCSIWGENIE */
1105	NULL, 			/* SIOCSIWGENIE */
1106#if (WIRELESS_EXT >= 18)
1107	r8192_wx_set_auth,//NULL, 			/* SIOCSIWAUTH */
1108	NULL,//r8192_wx_get_auth,//NULL, 			/* SIOCSIWAUTH */
1109	r8192_wx_set_enc_ext, 			/* SIOCSIWENCODEEXT */
1110#else
1111	NULL,
1112	NULL,
1113	NULL,
1114#endif
1115	NULL,//r8192_wx_get_enc_ext,//NULL, 			/* SIOCSIWENCODEEXT */
1116	NULL, 			/* SIOCSIWPMKSA */
1117	NULL, 			 /*---hole---*/
1118
1119};
1120
1121
1122static const struct iw_priv_args r8192_private_args[] = {
1123
1124	{
1125		SIOCIWFIRSTPRIV + 0x0,
1126		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1127	},
1128
1129	{
1130		SIOCIWFIRSTPRIV + 0x1,
1131		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1132
1133	},
1134	{
1135		SIOCIWFIRSTPRIV + 0x2,
1136		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1137	}
1138	,
1139	{
1140		SIOCIWFIRSTPRIV + 0x3,
1141		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1142
1143	}
1144	,
1145	{
1146		SIOCIWFIRSTPRIV + 0x4,
1147		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1148		"set_power"
1149	}
1150
1151};
1152
1153
1154static iw_handler r8192_private_handler[] = {
1155	r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
1156	r8192_wx_set_scan_type,
1157	r8192_wx_set_rawtx,
1158	r8192_wx_force_reset,
1159	r8192_wx_adapter_power_status,
1160};
1161
1162//#if WIRELESS_EXT >= 17
1163struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1164{
1165       struct r8192_priv *priv = ieee80211_priv(dev);
1166	struct ieee80211_device* ieee = priv->ieee80211;
1167	struct iw_statistics* wstats = &priv->wstats;
1168	int tmp_level = 0;
1169	int tmp_qual = 0;
1170	int tmp_noise = 0;
1171	if(ieee->state < IEEE80211_LINKED)
1172	{
1173		wstats->qual.qual = 0;
1174		wstats->qual.level = 0;
1175		wstats->qual.noise = 0;
1176		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1177		return wstats;
1178	}
1179
1180       tmp_level = (&ieee->current_network)->stats.rssi;
1181	tmp_qual = (&ieee->current_network)->stats.signal;
1182	tmp_noise = (&ieee->current_network)->stats.noise;
1183	//printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1184
1185	wstats->qual.level = tmp_level;
1186	wstats->qual.qual = tmp_qual;
1187	wstats->qual.noise = tmp_noise;
1188	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1189	return wstats;
1190}
1191//#endif
1192
1193
1194struct iw_handler_def  r8192_wx_handlers_def={
1195	.standard = r8192_wx_handlers,
1196	.num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1197	.private = r8192_private_handler,
1198	.num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1199 	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1200#if WIRELESS_EXT >= 17
1201	.get_wireless_stats = r8192_get_wireless_stats,
1202#endif
1203	.private_args = (struct iw_priv_args *)r8192_private_args,
1204};
1205