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