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