r8192U_wx.c revision e00b8fdca8c04eb39bd2ff8a68c7154135e4e179
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", __func__, *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)
337		return -ENETDOWN;
338
339	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
340		return -EAGAIN;
341	if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
342		struct iw_scan_req *req = (struct iw_scan_req *)b;
343		if (req->essid_len) {
344			//printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
345			ieee->current_network.ssid_len = req->essid_len;
346			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
347			//printk("=====>network ssid:%s\n", ieee->current_network.ssid);
348		}
349	}
350
351	down(&priv->wx_sem);
352	if (priv->ieee80211->state != IEEE80211_LINKED) {
353		priv->ieee80211->scanning = 0;
354		ieee80211_softmac_scan_syncro(priv->ieee80211);
355		ret = 0;
356	} else {
357		ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
358	}
359	up(&priv->wx_sem);
360	return ret;
361}
362
363
364static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
365			     union iwreq_data *wrqu, char *b)
366{
367
368	int ret;
369	struct r8192_priv *priv = ieee80211_priv(dev);
370
371	if (!priv->up)
372		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)
534		return -ENETDOWN;
535
536	down(&priv->wx_sem);
537
538	RT_TRACE(COMP_SEC, "Setting SW wep key");
539	ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
540
541	up(&priv->wx_sem);
542
543
544
545	//sometimes, the length is zero while we do not type key value
546	if (wrqu->encoding.length != 0) {
547
548		for (i = 0; i < 4; i++) {
549			hwkey[i] |=  key[4*i+0]&mask;
550			if (i == 1 && (4*i+1) == wrqu->encoding.length)
551				mask = 0x00;
552			if (i == 3 && (4*i+1) == wrqu->encoding.length)
553				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:
564			key_idx = ieee->tx_keyidx;
565			break;
566		case 1:
567			key_idx = 0;
568			break;
569		case 2:
570			key_idx = 1;
571			break;
572		case 3:
573			key_idx = 2;
574			break;
575		case 4:
576			key_idx	= 3;
577			break;
578		default:
579			break;
580		}
581
582		if (wrqu->encoding.length == 0x5) {
583				ieee->pairwise_key_type = KEY_TYPE_WEP40;
584			EnableHWSecurityConfig8192(dev);
585
586			setKey(dev,
587				key_idx,                //EntryNo
588				key_idx,                //KeyIndex
589				KEY_TYPE_WEP40,         //KeyType
590				zero_addr[key_idx],
591				0,                      //DefaultKey
592				hwkey);                 //KeyContent
593
594		}
595
596		else if (wrqu->encoding.length == 0xd) {
597				ieee->pairwise_key_type = KEY_TYPE_WEP104;
598				EnableHWSecurityConfig8192(dev);
599
600			setKey(dev,
601				key_idx,                //EntryNo
602				key_idx,                //KeyIndex
603				KEY_TYPE_WEP104,        //KeyType
604				zero_addr[key_idx],
605				0,                      //DefaultKey
606				hwkey);                 //KeyContent
607
608		} else {
609			printk("wrong type in WEP, not WEP40 and WEP104\n");
610		}
611
612	}
613
614	return ret;
615}
616
617
618static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
619					union iwreq_data *wrqu, char *p)
620{
621
622	struct r8192_priv *priv = ieee80211_priv(dev);
623	int *parms = (int *)p;
624	int mode = parms[0];
625
626	priv->ieee80211->active_scan = mode;
627
628	return 1;
629}
630
631
632
633static int r8192_wx_set_retry(struct net_device *dev,
634				struct iw_request_info *info,
635				union iwreq_data *wrqu, char *extra)
636{
637	struct r8192_priv *priv = ieee80211_priv(dev);
638	int err = 0;
639
640	down(&priv->wx_sem);
641
642	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
643	    wrqu->retry.disabled){
644		err = -EINVAL;
645		goto exit;
646	}
647	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
648		err = -EINVAL;
649		goto exit;
650	}
651
652	if (wrqu->retry.value > R8180_MAX_RETRY) {
653		err = -EINVAL;
654		goto exit;
655	}
656	if (wrqu->retry.flags & IW_RETRY_MAX) {
657		priv->retry_rts = wrqu->retry.value;
658		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
659
660	} else {
661		priv->retry_data = wrqu->retry.value;
662		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
663	}
664
665	/* FIXME !
666	 * We might try to write directly the TX config register
667	 * or to restart just the (R)TX process.
668	 * I'm unsure if whole reset is really needed
669	 */
670
671	rtl8192_commit(dev);
672	/*
673	if(priv->up){
674		rtl8180_rtx_disable(dev);
675		rtl8180_rx_enable(dev);
676		rtl8180_tx_enable(dev);
677
678	}
679	*/
680exit:
681	up(&priv->wx_sem);
682
683	return err;
684}
685
686static int r8192_wx_get_retry(struct net_device *dev,
687				struct iw_request_info *info,
688				union iwreq_data *wrqu, char *extra)
689{
690	struct r8192_priv *priv = ieee80211_priv(dev);
691
692
693	wrqu->retry.disabled = 0; /* can't be disabled */
694
695	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
696	    IW_RETRY_LIFETIME)
697		return -EINVAL;
698
699	if (wrqu->retry.flags & IW_RETRY_MAX) {
700		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
701		wrqu->retry.value = priv->retry_rts;
702	} else {
703		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
704		wrqu->retry.value = priv->retry_data;
705	}
706	//printk("returning %d",wrqu->retry.value);
707
708
709	return 0;
710}
711
712static int r8192_wx_get_sens(struct net_device *dev,
713				struct iw_request_info *info,
714				union iwreq_data *wrqu, char *extra)
715{
716	struct r8192_priv *priv = ieee80211_priv(dev);
717	if (priv->rf_set_sens == NULL)
718		return -1; /* we have not this support for this radio */
719	wrqu->sens.value = priv->sens;
720	return 0;
721}
722
723
724static int r8192_wx_set_sens(struct net_device *dev,
725				struct iw_request_info *info,
726				union iwreq_data *wrqu, char *extra)
727{
728
729	struct r8192_priv *priv = ieee80211_priv(dev);
730
731	short err = 0;
732	down(&priv->wx_sem);
733	//DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
734	if (priv->rf_set_sens == NULL) {
735		err = -1; /* we have not this support for this radio */
736		goto exit;
737	}
738	if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
739		priv->sens = wrqu->sens.value;
740	else
741		err = -EINVAL;
742
743exit:
744	up(&priv->wx_sem);
745
746	return err;
747}
748
749//hw security need to reorganized.
750static int r8192_wx_set_enc_ext(struct net_device *dev,
751					struct iw_request_info *info,
752					union iwreq_data *wrqu, char *extra)
753{
754	int ret = 0;
755	struct r8192_priv *priv = ieee80211_priv(dev);
756	struct ieee80211_device *ieee = priv->ieee80211;
757	//printk("===>%s()\n", __func__);
758
759
760	down(&priv->wx_sem);
761	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
762
763	{
764		u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
765		u8 zero[6] = {0};
766		u32 key[4] = {0};
767		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
768		struct iw_point *encoding = &wrqu->encoding;
769		u8 idx = 0, alg = 0, group = 0;
770		if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
771			//none is not allowed to use hwsec WB 2008.07.01
772			goto end_hw_sec;
773
774		// as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
775		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
776		idx = encoding->flags & IW_ENCODE_INDEX;
777		if (idx)
778			idx--;
779		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
780
781		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40)) {
782			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
783				alg = KEY_TYPE_WEP104;
784			ieee->pairwise_key_type = alg;
785			EnableHWSecurityConfig8192(dev);
786		}
787		memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
788
789		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
790
791			setKey(dev,
792					idx,//EntryNo
793					idx, //KeyIndex
794					alg,  //KeyType
795					zero, //MacAddr
796					0,              //DefaultKey
797					key);           //KeyContent
798		} else if (group) {
799			ieee->group_key_type = alg;
800			setKey(dev,
801					idx,//EntryNo
802					idx, //KeyIndex
803					alg,  //KeyType
804					broadcast_addr, //MacAddr
805					0,              //DefaultKey
806					key);           //KeyContent
807		} else {//pairwise key
808			setKey(dev,
809					4,//EntryNo
810					idx, //KeyIndex
811					alg,  //KeyType
812					(u8 *)ieee->ap_mac_addr, //MacAddr
813					0,              //DefaultKey
814					key);           //KeyContent
815		}
816
817
818	}
819
820end_hw_sec:
821
822	up(&priv->wx_sem);
823	return ret;
824
825}
826static int r8192_wx_set_auth(struct net_device *dev,
827					struct iw_request_info *info,
828					union iwreq_data *data, char *extra)
829{
830	int ret = 0;
831	//printk("====>%s()\n", __func__);
832	struct r8192_priv *priv = ieee80211_priv(dev);
833	down(&priv->wx_sem);
834	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
835	up(&priv->wx_sem);
836	return ret;
837}
838
839static int r8192_wx_set_mlme(struct net_device *dev,
840					struct iw_request_info *info,
841					union iwreq_data *wrqu, char *extra)
842{
843	//printk("====>%s()\n", __func__);
844
845	int ret = 0;
846	struct r8192_priv *priv = ieee80211_priv(dev);
847	down(&priv->wx_sem);
848	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
849
850	up(&priv->wx_sem);
851	return ret;
852}
853
854static int r8192_wx_set_gen_ie(struct net_device *dev,
855					struct iw_request_info *info,
856					union iwreq_data *data, char *extra)
857{
858	   //printk("====>%s(), len:%d\n", __func__, data->length);
859	int ret = 0;
860	struct r8192_priv *priv = ieee80211_priv(dev);
861	down(&priv->wx_sem);
862	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
863	up(&priv->wx_sem);
864	//printk("<======%s(), ret:%d\n", __func__, ret);
865	return ret;
866
867
868}
869
870static int dummy(struct net_device *dev, struct iw_request_info *a,
871		 union iwreq_data *wrqu, char *b)
872{
873	return -1;
874}
875
876
877static iw_handler r8192_wx_handlers[] = {
878	NULL,                     /* SIOCSIWCOMMIT */
879	r8192_wx_get_name,	  /* SIOCGIWNAME */
880	dummy,                    /* SIOCSIWNWID */
881	dummy,                    /* SIOCGIWNWID */
882	r8192_wx_set_freq,        /* SIOCSIWFREQ */
883	r8192_wx_get_freq,        /* SIOCGIWFREQ */
884	r8192_wx_set_mode,        /* SIOCSIWMODE */
885	r8192_wx_get_mode,        /* SIOCGIWMODE */
886	r8192_wx_set_sens,        /* SIOCSIWSENS */
887	r8192_wx_get_sens,        /* SIOCGIWSENS */
888	NULL,                     /* SIOCSIWRANGE */
889	rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
890	NULL,                     /* SIOCSIWPRIV */
891	NULL,                     /* SIOCGIWPRIV */
892	NULL,                     /* SIOCSIWSTATS */
893	NULL,                     /* SIOCGIWSTATS */
894	dummy,                    /* SIOCSIWSPY */
895	dummy,                    /* SIOCGIWSPY */
896	NULL,                     /* SIOCGIWTHRSPY */
897	NULL,                     /* SIOCWIWTHRSPY */
898	r8192_wx_set_wap,	  /* SIOCSIWAP */
899	r8192_wx_get_wap,         /* SIOCGIWAP */
900	r8192_wx_set_mlme,                     /* MLME-- */
901	dummy,                     /* SIOCGIWAPLIST -- deprecated */
902	r8192_wx_set_scan,        /* SIOCSIWSCAN */
903	r8192_wx_get_scan,        /* SIOCGIWSCAN */
904	r8192_wx_set_essid,       /* SIOCSIWESSID */
905	r8192_wx_get_essid,       /* SIOCGIWESSID */
906	dummy,                    /* SIOCSIWNICKN */
907	dummy,                    /* SIOCGIWNICKN */
908	NULL,                     /* -- hole -- */
909	NULL,                     /* -- hole -- */
910	r8192_wx_set_rate,        /* SIOCSIWRATE */
911	r8192_wx_get_rate,        /* SIOCGIWRATE */
912	r8192_wx_set_rts,                    /* SIOCSIWRTS */
913	r8192_wx_get_rts,                    /* SIOCGIWRTS */
914	r8192_wx_set_frag,        /* SIOCSIWFRAG */
915	r8192_wx_get_frag,        /* SIOCGIWFRAG */
916	dummy,                    /* SIOCSIWTXPOW */
917	dummy,                    /* SIOCGIWTXPOW */
918	r8192_wx_set_retry,       /* SIOCSIWRETRY */
919	r8192_wx_get_retry,       /* SIOCGIWRETRY */
920	r8192_wx_set_enc,         /* SIOCSIWENCODE */
921	r8192_wx_get_enc,         /* SIOCGIWENCODE */
922	r8192_wx_set_power,                    /* SIOCSIWPOWER */
923	r8192_wx_get_power,                    /* SIOCGIWPOWER */
924	NULL,			/*---hole---*/
925	NULL,			/*---hole---*/
926	r8192_wx_set_gen_ie,//NULL,			/* SIOCSIWGENIE */
927	NULL,			/* SIOCSIWGENIE */
928
929	r8192_wx_set_auth,//NULL,			/* SIOCSIWAUTH */
930	NULL,//r8192_wx_get_auth,//NULL,			/* SIOCSIWAUTH */
931	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
932	NULL,//r8192_wx_get_enc_ext,//NULL,			/* SIOCSIWENCODEEXT */
933	NULL,			/* SIOCSIWPMKSA */
934	NULL,			 /*---hole---*/
935
936};
937
938
939static const struct iw_priv_args r8192_private_args[] = {
940
941	{
942		SIOCIWFIRSTPRIV + 0x0,
943		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
944	},
945
946	{
947		SIOCIWFIRSTPRIV + 0x1,
948		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
949
950	},
951	{
952		SIOCIWFIRSTPRIV + 0x2,
953		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
954	},
955	{
956		SIOCIWFIRSTPRIV + 0x3,
957		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
958
959	}
960
961};
962
963
964static iw_handler r8192_private_handler[] = {
965//	r8192_wx_set_monitor,  /* SIOCIWFIRSTPRIV */
966	r8192_wx_set_crcmon,   /*SIOCIWSECONDPRIV*/
967//	r8192_wx_set_forceassociate,
968//	r8192_wx_set_beaconinterval,
969//	r8192_wx_set_monitor_type,
970	r8192_wx_set_scan_type,
971	r8192_wx_set_rawtx,
972	//r8192_wx_null,
973	r8192_wx_force_reset,
974};
975
976struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
977{
978	struct r8192_priv *priv = ieee80211_priv(dev);
979	struct ieee80211_device *ieee = priv->ieee80211;
980	struct iw_statistics *wstats = &priv->wstats;
981	int tmp_level = 0;
982	int tmp_qual = 0;
983	int tmp_noise = 0;
984	if (ieee->state < IEEE80211_LINKED) {
985		wstats->qual.qual = 0;
986		wstats->qual.level = 0;
987		wstats->qual.noise = 0;
988		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
989		return wstats;
990	}
991
992	tmp_level = (&ieee->current_network)->stats.rssi;
993	tmp_qual = (&ieee->current_network)->stats.signal;
994	tmp_noise = (&ieee->current_network)->stats.noise;
995	//printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
996
997	wstats->qual.level = tmp_level;
998	wstats->qual.qual = tmp_qual;
999	wstats->qual.noise = tmp_noise;
1000	wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
1001	return wstats;
1002}
1003
1004
1005struct iw_handler_def  r8192_wx_handlers_def = {
1006	.standard = r8192_wx_handlers,
1007	.num_standard = ARRAY_SIZE(r8192_wx_handlers),
1008	.private = r8192_private_handler,
1009	.num_private = ARRAY_SIZE(r8192_private_handler),
1010	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1011	.get_wireless_stats = r8192_get_wireless_stats,
1012	.private_args = (struct iw_priv_args *)r8192_private_args,
1013};
1014