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