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