r8192U_wx.c revision aa0cb59cfa781d5cb44dd981153d67168d34f91b
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
282	range->min_frag = MIN_FRAG_THRESHOLD;
283	range->max_frag = MAX_FRAG_THRESHOLD;
284
285	range->min_pmp=0;
286	range->max_pmp = 5000000;
287	range->min_pmt = 0;
288	range->max_pmt = 65535*1000;
289	range->pmp_flags = IW_POWER_PERIOD;
290	range->pmt_flags = IW_POWER_TIMEOUT;
291	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
292
293	range->we_version_compiled = WIRELESS_EXT;
294	range->we_version_source = 16;
295
296//	range->retry_capa;	/* What retry options are supported */
297//	range->retry_flags;	/* How to decode max/min retry limit */
298//	range->r_time_flags;	/* How to decode max/min retry life */
299//	range->min_retry;	/* Minimal number of retries */
300//	range->max_retry;	/* Maximal number of retries */
301//	range->min_r_time;	/* Minimal retry lifetime */
302//	range->max_r_time;	/* Maximal retry lifetime */
303
304
305	for (i = 0, val = 0; i < 14; i++) {
306
307		// Include only legal frequencies for some countries
308		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
309			range->freq[val].i = i + 1;
310			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
311			range->freq[val].e = 1;
312			val++;
313		} else {
314			// FIXME: do we need to set anything for channels
315			// we don't use ?
316		}
317
318		if (val == IW_MAX_FREQUENCIES)
319		break;
320	}
321	range->num_frequency = val;
322	range->num_channels = val;
323#if WIRELESS_EXT > 17
324	range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
325			  IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
326#endif
327	tmp->scan_capa = 0x01;
328	return 0;
329}
330
331
332static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
333			     union iwreq_data *wrqu, char *b)
334{
335	struct r8192_priv *priv = ieee80211_priv(dev);
336	struct ieee80211_device *ieee = priv->ieee80211;
337	int ret = 0;
338
339	if(!priv->up) return -ENETDOWN;
340
341	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
342		return -EAGAIN;
343	if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
344	{
345		struct iw_scan_req *req = (struct iw_scan_req *)b;
346		if (req->essid_len)
347		{
348			//printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
349			ieee->current_network.ssid_len = req->essid_len;
350			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
351			//printk("=====>network ssid:%s\n", ieee->current_network.ssid);
352		}
353	}
354
355	down(&priv->wx_sem);
356	if(priv->ieee80211->state != IEEE80211_LINKED){
357		priv->ieee80211->scanning = 0;
358		ieee80211_softmac_scan_syncro(priv->ieee80211);
359		ret = 0;
360	}
361	else
362	ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
363	up(&priv->wx_sem);
364	return ret;
365}
366
367
368static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
369			     union iwreq_data *wrqu, char *b)
370{
371
372	int ret;
373	struct r8192_priv *priv = ieee80211_priv(dev);
374
375	if(!priv->up) return -ENETDOWN;
376
377	down(&priv->wx_sem);
378
379	ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
380
381	up(&priv->wx_sem);
382
383	return ret;
384}
385
386static int r8192_wx_set_essid(struct net_device *dev,
387			      struct iw_request_info *a,
388			      union iwreq_data *wrqu, char *b)
389{
390	struct r8192_priv *priv = ieee80211_priv(dev);
391	int ret;
392	down(&priv->wx_sem);
393
394	ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
395
396	up(&priv->wx_sem);
397
398	return ret;
399}
400
401
402
403
404static int r8192_wx_get_essid(struct net_device *dev,
405			      struct iw_request_info *a,
406			      union iwreq_data *wrqu, char *b)
407{
408	int ret;
409	struct r8192_priv *priv = ieee80211_priv(dev);
410
411	down(&priv->wx_sem);
412
413	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
414
415	up(&priv->wx_sem);
416
417	return ret;
418}
419
420
421static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
422			     union iwreq_data *wrqu, char *b)
423{
424	int ret;
425	struct r8192_priv *priv = ieee80211_priv(dev);
426
427	down(&priv->wx_sem);
428
429	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
430
431	up(&priv->wx_sem);
432	return ret;
433}
434
435static int r8192_wx_get_name(struct net_device *dev,
436			     struct iw_request_info *info,
437			     union iwreq_data *wrqu, char *extra)
438{
439	struct r8192_priv *priv = ieee80211_priv(dev);
440	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
441}
442
443
444static int r8192_wx_set_frag(struct net_device *dev,
445			     struct iw_request_info *info,
446			     union iwreq_data *wrqu, char *extra)
447{
448	struct r8192_priv *priv = ieee80211_priv(dev);
449
450	if (wrqu->frag.disabled)
451		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
452	else {
453		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
454		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
455			return -EINVAL;
456
457		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
458	}
459
460	return 0;
461}
462
463
464static int r8192_wx_get_frag(struct net_device *dev,
465			     struct iw_request_info *info,
466			     union iwreq_data *wrqu, char *extra)
467{
468	struct r8192_priv *priv = ieee80211_priv(dev);
469
470	wrqu->frag.value = priv->ieee80211->fts;
471	wrqu->frag.fixed = 0;	/* no auto select */
472	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
473
474	return 0;
475}
476
477
478static int r8192_wx_set_wap(struct net_device *dev,
479			 struct iw_request_info *info,
480			 union iwreq_data *awrq,
481			 char *extra)
482{
483
484	int ret;
485	struct r8192_priv *priv = ieee80211_priv(dev);
486//        struct sockaddr *temp = (struct sockaddr *)awrq;
487	down(&priv->wx_sem);
488
489	ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
490
491	up(&priv->wx_sem);
492
493	return ret;
494
495}
496
497
498static int r8192_wx_get_wap(struct net_device *dev,
499			    struct iw_request_info *info,
500			    union iwreq_data *wrqu, char *extra)
501{
502	struct r8192_priv *priv = ieee80211_priv(dev);
503
504	return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
505}
506
507
508static int r8192_wx_get_enc(struct net_device *dev,
509			    struct iw_request_info *info,
510			    union iwreq_data *wrqu, char *key)
511{
512	struct r8192_priv *priv = ieee80211_priv(dev);
513
514	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
515}
516
517static int r8192_wx_set_enc(struct net_device *dev,
518			    struct iw_request_info *info,
519			    union iwreq_data *wrqu, char *key)
520{
521	struct r8192_priv *priv = ieee80211_priv(dev);
522	struct ieee80211_device *ieee = priv->ieee80211;
523	int ret;
524
525	//u32 TargetContent;
526	u32 hwkey[4]={0,0,0,0};
527	u8 mask=0xff;
528	u32 key_idx=0;
529	//u8 broadcast_addr[6] ={	0xff,0xff,0xff,0xff,0xff,0xff};
530	u8 zero_addr[4][6] ={	{0x00,0x00,0x00,0x00,0x00,0x00},
531				{0x00,0x00,0x00,0x00,0x00,0x01},
532				{0x00,0x00,0x00,0x00,0x00,0x02},
533				{0x00,0x00,0x00,0x00,0x00,0x03} };
534	int i;
535
536       if(!priv->up) return -ENETDOWN;
537
538	down(&priv->wx_sem);
539
540	RT_TRACE(COMP_SEC, "Setting SW wep key");
541	ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
542
543	up(&priv->wx_sem);
544
545
546
547	//sometimes, the length is zero while we do not type key value
548	if(wrqu->encoding.length!=0){
549
550		for(i=0 ; i<4 ; i++){
551			hwkey[i] |=  key[4*i+0]&mask;
552			if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
553			if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
554			hwkey[i] |= (key[4*i+1]&mask)<<8;
555			hwkey[i] |= (key[4*i+2]&mask)<<16;
556			hwkey[i] |= (key[4*i+3]&mask)<<24;
557		}
558
559		#define CONF_WEP40  0x4
560		#define CONF_WEP104 0x14
561
562		switch (wrqu->encoding.flags & IW_ENCODE_INDEX){
563		case 0: key_idx = ieee->tx_keyidx; break;
564		case 1:	key_idx = 0; break;
565		case 2:	key_idx = 1; break;
566		case 3:	key_idx = 2; break;
567		case 4:	key_idx	= 3; break;
568		default: break;
569		}
570
571		if(wrqu->encoding.length==0x5){
572				ieee->pairwise_key_type = KEY_TYPE_WEP40;
573			EnableHWSecurityConfig8192(dev);
574
575			setKey( dev,
576				key_idx,                //EntryNo
577				key_idx,                //KeyIndex
578				KEY_TYPE_WEP40,         //KeyType
579				zero_addr[key_idx],
580				0,                      //DefaultKey
581				hwkey);                 //KeyContent
582
583		}
584
585		else if(wrqu->encoding.length==0xd){
586				ieee->pairwise_key_type = KEY_TYPE_WEP104;
587				EnableHWSecurityConfig8192(dev);
588
589			setKey( dev,
590				key_idx,                //EntryNo
591				key_idx,                //KeyIndex
592				KEY_TYPE_WEP104,        //KeyType
593				zero_addr[key_idx],
594				0,                      //DefaultKey
595				hwkey);                 //KeyContent
596
597		}
598		else printk("wrong type in WEP, not WEP40 and WEP104\n");
599
600	}
601
602	return ret;
603}
604
605
606static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
607 iwreq_data *wrqu, char *p){
608
609	struct r8192_priv *priv = ieee80211_priv(dev);
610	int *parms=(int *)p;
611	int mode=parms[0];
612
613	priv->ieee80211->active_scan = mode;
614
615	return 1;
616}
617
618
619
620static int r8192_wx_set_retry(struct net_device *dev,
621				struct iw_request_info *info,
622				union iwreq_data *wrqu, char *extra)
623{
624	struct r8192_priv *priv = ieee80211_priv(dev);
625	int err = 0;
626
627	down(&priv->wx_sem);
628
629	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
630	    wrqu->retry.disabled){
631		err = -EINVAL;
632		goto exit;
633	}
634	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
635		err = -EINVAL;
636		goto exit;
637	}
638
639	if(wrqu->retry.value > R8180_MAX_RETRY){
640		err= -EINVAL;
641		goto exit;
642	}
643	if (wrqu->retry.flags & IW_RETRY_MAX) {
644		priv->retry_rts = wrqu->retry.value;
645		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
646
647	}else {
648		priv->retry_data = wrqu->retry.value;
649		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
650	}
651
652	/* FIXME !
653	 * We might try to write directly the TX config register
654	 * or to restart just the (R)TX process.
655	 * I'm unsure if whole reset is really needed
656	 */
657
658	rtl8192_commit(dev);
659	/*
660	if(priv->up){
661		rtl8180_rtx_disable(dev);
662		rtl8180_rx_enable(dev);
663		rtl8180_tx_enable(dev);
664
665	}
666	*/
667exit:
668	up(&priv->wx_sem);
669
670	return err;
671}
672
673static int r8192_wx_get_retry(struct net_device *dev,
674				struct iw_request_info *info,
675				union iwreq_data *wrqu, char *extra)
676{
677	struct r8192_priv *priv = ieee80211_priv(dev);
678
679
680	wrqu->retry.disabled = 0; /* can't be disabled */
681
682	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
683	    IW_RETRY_LIFETIME)
684		return -EINVAL;
685
686	if (wrqu->retry.flags & IW_RETRY_MAX) {
687		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
688		wrqu->retry.value = priv->retry_rts;
689	} else {
690		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
691		wrqu->retry.value = priv->retry_data;
692	}
693	//printk("returning %d",wrqu->retry.value);
694
695
696	return 0;
697}
698
699static int r8192_wx_get_sens(struct net_device *dev,
700				struct iw_request_info *info,
701				union iwreq_data *wrqu, char *extra)
702{
703	struct r8192_priv *priv = ieee80211_priv(dev);
704	if(priv->rf_set_sens == NULL)
705		return -1; /* we have not this support for this radio */
706	wrqu->sens.value = priv->sens;
707	return 0;
708}
709
710
711static int r8192_wx_set_sens(struct net_device *dev,
712				struct iw_request_info *info,
713				union iwreq_data *wrqu, char *extra)
714{
715
716	struct r8192_priv *priv = ieee80211_priv(dev);
717
718	short err = 0;
719	down(&priv->wx_sem);
720	//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
721	if(priv->rf_set_sens == NULL) {
722		err= -1; /* we have not this support for this radio */
723		goto exit;
724	}
725	if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
726		priv->sens = wrqu->sens.value;
727	else
728		err= -EINVAL;
729
730exit:
731	up(&priv->wx_sem);
732
733	return err;
734}
735
736#if (WIRELESS_EXT >= 18)
737//hw security need to reorganized.
738static int r8192_wx_set_enc_ext(struct net_device *dev,
739					struct iw_request_info *info,
740					union iwreq_data *wrqu, char *extra)
741{
742	int ret=0;
743	struct r8192_priv *priv = ieee80211_priv(dev);
744	struct ieee80211_device *ieee = priv->ieee80211;
745	//printk("===>%s()\n", __FUNCTION__);
746
747
748	down(&priv->wx_sem);
749	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
750
751	{
752		u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
753		u8 zero[6] = {0};
754		u32 key[4] = {0};
755		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
756		struct iw_point *encoding = &wrqu->encoding;
757		u8 idx = 0, alg = 0, group = 0;
758		if ((encoding->flags & IW_ENCODE_DISABLED) ||
759		ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
760			goto end_hw_sec;
761
762		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;
763		idx = encoding->flags & IW_ENCODE_INDEX;
764		if (idx)
765			idx --;
766		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
767
768		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40))
769		{
770			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
771				alg = KEY_TYPE_WEP104;
772			ieee->pairwise_key_type = alg;
773			EnableHWSecurityConfig8192(dev);
774		}
775		memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
776
777		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
778		{
779
780			setKey( dev,
781					idx,//EntryNo
782					idx, //KeyIndex
783					alg,  //KeyType
784					zero, //MacAddr
785					0,              //DefaultKey
786					key);           //KeyContent
787		}
788		else if (group)
789		{
790			ieee->group_key_type = alg;
791			setKey( dev,
792					idx,//EntryNo
793					idx, //KeyIndex
794					alg,  //KeyType
795					broadcast_addr, //MacAddr
796					0,              //DefaultKey
797					key);           //KeyContent
798		}
799		else //pairwise key
800		{
801			setKey( dev,
802					4,//EntryNo
803					idx, //KeyIndex
804					alg,  //KeyType
805					(u8 *)ieee->ap_mac_addr, //MacAddr
806					0,              //DefaultKey
807					key);           //KeyContent
808		}
809
810
811	}
812
813end_hw_sec:
814
815	up(&priv->wx_sem);
816	return ret;
817
818}
819static int r8192_wx_set_auth(struct net_device *dev,
820					struct iw_request_info *info,
821					union iwreq_data *data, char *extra)
822{
823	int ret=0;
824	//printk("====>%s()\n", __FUNCTION__);
825	struct r8192_priv *priv = ieee80211_priv(dev);
826	down(&priv->wx_sem);
827	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
828	up(&priv->wx_sem);
829	return ret;
830}
831
832static int r8192_wx_set_mlme(struct net_device *dev,
833					struct iw_request_info *info,
834					union iwreq_data *wrqu, char *extra)
835{
836	//printk("====>%s()\n", __FUNCTION__);
837
838	int ret=0;
839	struct r8192_priv *priv = ieee80211_priv(dev);
840	down(&priv->wx_sem);
841	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
842
843	up(&priv->wx_sem);
844	return ret;
845}
846#endif
847static int r8192_wx_set_gen_ie(struct net_device *dev,
848					struct iw_request_info *info,
849					union iwreq_data *data, char *extra)
850{
851	   //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
852	int ret=0;
853	struct r8192_priv *priv = ieee80211_priv(dev);
854	down(&priv->wx_sem);
855	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
856	up(&priv->wx_sem);
857	//printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
858	return ret;
859
860
861}
862
863static int dummy(struct net_device *dev, struct iw_request_info *a,
864		 union iwreq_data *wrqu,char *b)
865{
866	return -1;
867}
868
869
870static iw_handler r8192_wx_handlers[] =
871{
872	NULL,                     /* SIOCSIWCOMMIT */
873	r8192_wx_get_name,	  /* SIOCGIWNAME */
874	dummy,                    /* SIOCSIWNWID */
875	dummy,                    /* SIOCGIWNWID */
876	r8192_wx_set_freq,        /* SIOCSIWFREQ */
877	r8192_wx_get_freq,        /* SIOCGIWFREQ */
878	r8192_wx_set_mode,        /* SIOCSIWMODE */
879	r8192_wx_get_mode,        /* SIOCGIWMODE */
880	r8192_wx_set_sens,        /* SIOCSIWSENS */
881	r8192_wx_get_sens,        /* SIOCGIWSENS */
882	NULL,                     /* SIOCSIWRANGE */
883	rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
884	NULL,                     /* SIOCSIWPRIV */
885	NULL,                     /* SIOCGIWPRIV */
886	NULL,                     /* SIOCSIWSTATS */
887	NULL,                     /* SIOCGIWSTATS */
888	dummy,                    /* SIOCSIWSPY */
889	dummy,                    /* SIOCGIWSPY */
890	NULL,                     /* SIOCGIWTHRSPY */
891	NULL,                     /* SIOCWIWTHRSPY */
892	r8192_wx_set_wap,	  /* SIOCSIWAP */
893	r8192_wx_get_wap,         /* SIOCGIWAP */
894#if (WIRELESS_EXT >= 18)
895	r8192_wx_set_mlme,                     /* MLME-- */
896#else
897	 NULL,
898#endif
899	dummy,                     /* SIOCGIWAPLIST -- deprecated */
900	r8192_wx_set_scan,        /* SIOCSIWSCAN */
901	r8192_wx_get_scan,        /* SIOCGIWSCAN */
902	r8192_wx_set_essid,       /* SIOCSIWESSID */
903	r8192_wx_get_essid,       /* SIOCGIWESSID */
904	dummy,                    /* SIOCSIWNICKN */
905	dummy,                    /* SIOCGIWNICKN */
906	NULL,                     /* -- hole -- */
907	NULL,                     /* -- hole -- */
908	r8192_wx_set_rate,        /* SIOCSIWRATE */
909	r8192_wx_get_rate,        /* SIOCGIWRATE */
910	r8192_wx_set_rts,                    /* SIOCSIWRTS */
911	r8192_wx_get_rts,                    /* SIOCGIWRTS */
912	r8192_wx_set_frag,        /* SIOCSIWFRAG */
913	r8192_wx_get_frag,        /* SIOCGIWFRAG */
914	dummy,                    /* SIOCSIWTXPOW */
915	dummy,                    /* SIOCGIWTXPOW */
916	r8192_wx_set_retry,       /* SIOCSIWRETRY */
917	r8192_wx_get_retry,       /* SIOCGIWRETRY */
918	r8192_wx_set_enc,         /* SIOCSIWENCODE */
919	r8192_wx_get_enc,         /* SIOCGIWENCODE */
920	r8192_wx_set_power,                    /* SIOCSIWPOWER */
921	r8192_wx_get_power,                    /* SIOCGIWPOWER */
922	NULL,			/*---hole---*/
923	NULL,			/*---hole---*/
924	r8192_wx_set_gen_ie,//NULL,			/* SIOCSIWGENIE */
925	NULL,			/* SIOCSIWGENIE */
926
927#if (WIRELESS_EXT >= 18)
928	r8192_wx_set_auth,//NULL,			/* SIOCSIWAUTH */
929	NULL,//r8192_wx_get_auth,//NULL,			/* SIOCSIWAUTH */
930	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
931	NULL,//r8192_wx_get_enc_ext,//NULL,			/* SIOCSIWENCODEEXT */
932#else
933	NULL,
934	NULL,
935	NULL,
936	NULL,
937#endif
938	NULL,			/* SIOCSIWPMKSA */
939	NULL,			 /*---hole---*/
940
941};
942
943
944static const struct iw_priv_args r8192_private_args[] = {
945
946	{
947		SIOCIWFIRSTPRIV + 0x0,
948		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
949	},
950
951	{
952		SIOCIWFIRSTPRIV + 0x1,
953		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
954
955	},
956	{
957		SIOCIWFIRSTPRIV + 0x2,
958		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
959	},
960	{
961		SIOCIWFIRSTPRIV + 0x3,
962		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
963
964	}
965
966};
967
968
969static iw_handler r8192_private_handler[] = {
970//	r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
971	r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
972//	r8192_wx_set_forceassociate,
973//	r8192_wx_set_beaconinterval,
974//	r8192_wx_set_monitor_type,
975	r8192_wx_set_scan_type,
976	r8192_wx_set_rawtx,
977	//r8192_wx_null,
978	r8192_wx_force_reset,
979};
980
981//#if WIRELESS_EXT >= 17
982struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
983{
984       struct r8192_priv *priv = ieee80211_priv(dev);
985	struct ieee80211_device *ieee = priv->ieee80211;
986	struct iw_statistics *wstats = &priv->wstats;
987	int tmp_level = 0;
988	int tmp_qual = 0;
989	int tmp_noise = 0;
990	if(ieee->state < IEEE80211_LINKED)
991	{
992		wstats->qual.qual = 0;
993		wstats->qual.level = 0;
994		wstats->qual.noise = 0;
995		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
996		return wstats;
997	}
998
999       tmp_level = (&ieee->current_network)->stats.rssi;
1000	tmp_qual = (&ieee->current_network)->stats.signal;
1001	tmp_noise = (&ieee->current_network)->stats.noise;
1002	//printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1003
1004	wstats->qual.level = tmp_level;
1005	wstats->qual.qual = tmp_qual;
1006	wstats->qual.noise = tmp_noise;
1007	wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
1008	return wstats;
1009}
1010//#endif
1011
1012
1013struct iw_handler_def  r8192_wx_handlers_def={
1014	.standard = r8192_wx_handlers,
1015	.num_standard = ARRAY_SIZE(r8192_wx_handlers),
1016	.private = r8192_private_handler,
1017	.num_private = ARRAY_SIZE(r8192_private_handler),
1018	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1019#if WIRELESS_EXT >= 17
1020	.get_wireless_stats = r8192_get_wireless_stats,
1021#endif
1022	.private_args = (struct iw_priv_args *)r8192_private_args,
1023};
1024