r8192U_wx.c revision c4d6b8fbea3895973eb6153c27cb2bc015a17fdd
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#include "r8192U_wx.h"
26
27#define RATE_COUNT 12
28static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
29	6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
30
31
32#ifndef ENETDOWN
33#define ENETDOWN 1
34#endif
35
36static int r8192_wx_get_freq(struct net_device *dev,
37			     struct iw_request_info *a,
38			     union iwreq_data *wrqu, char *b)
39{
40	struct r8192_priv *priv = ieee80211_priv(dev);
41
42	return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
43}
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
62	return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
63}
64
65
66
67static int r8192_wx_set_rate(struct net_device *dev,
68			     struct iw_request_info *info,
69			     union iwreq_data *wrqu, char *extra)
70{
71	int ret;
72	struct r8192_priv *priv = ieee80211_priv(dev);
73
74	down(&priv->wx_sem);
75
76	ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
77
78	up(&priv->wx_sem);
79
80	return ret;
81}
82
83
84static int r8192_wx_set_rts(struct net_device *dev,
85			     struct iw_request_info *info,
86			     union iwreq_data *wrqu, char *extra)
87{
88	int ret;
89	struct r8192_priv *priv = ieee80211_priv(dev);
90
91	down(&priv->wx_sem);
92
93	ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
94
95	up(&priv->wx_sem);
96
97	return ret;
98}
99
100static int r8192_wx_get_rts(struct net_device *dev,
101			     struct iw_request_info *info,
102			     union iwreq_data *wrqu, char *extra)
103{
104	struct r8192_priv *priv = ieee80211_priv(dev);
105
106	return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
107}
108
109static int r8192_wx_set_power(struct net_device *dev,
110			     struct iw_request_info *info,
111			     union iwreq_data *wrqu, char *extra)
112{
113	int ret;
114	struct r8192_priv *priv = ieee80211_priv(dev);
115
116	down(&priv->wx_sem);
117
118	ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
119
120	up(&priv->wx_sem);
121
122	return ret;
123}
124
125static int r8192_wx_get_power(struct net_device *dev,
126			     struct iw_request_info *info,
127			     union iwreq_data *wrqu, char *extra)
128{
129	struct r8192_priv *priv = ieee80211_priv(dev);
130
131	return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
132}
133
134static int r8192_wx_force_reset(struct net_device *dev,
135		struct iw_request_info *info,
136		union iwreq_data *wrqu, char *extra)
137{
138	struct r8192_priv *priv = ieee80211_priv(dev);
139
140	down(&priv->wx_sem);
141
142	printk("%s(): force reset ! extra is %d\n", __func__, *extra);
143	priv->force_reset = *extra;
144	up(&priv->wx_sem);
145	return 0;
146
147}
148
149
150static int r8192_wx_set_rawtx(struct net_device *dev,
151			       struct iw_request_info *info,
152			       union iwreq_data *wrqu, char *extra)
153{
154	struct r8192_priv *priv = ieee80211_priv(dev);
155	int ret;
156
157	down(&priv->wx_sem);
158
159	ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
160
161	up(&priv->wx_sem);
162
163	return ret;
164
165}
166
167static int r8192_wx_set_crcmon(struct net_device *dev,
168			       struct iw_request_info *info,
169			       union iwreq_data *wrqu, char *extra)
170{
171	struct r8192_priv *priv = ieee80211_priv(dev);
172	int *parms = (int *)extra;
173	int enable = (parms[0] > 0);
174	short prev = priv->crcmon;
175
176	down(&priv->wx_sem);
177
178	if (enable)
179		priv->crcmon = 1;
180	else
181		priv->crcmon = 0;
182
183	DMESG("bad CRC in monitor mode are %s",
184	      priv->crcmon ? "accepted" : "rejected");
185
186	if (prev != priv->crcmon && priv->up) {
187		/* rtl8180_down(dev); */
188		/* rtl8180_up(dev); */
189	}
190
191	up(&priv->wx_sem);
192
193	return 0;
194}
195
196static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
197			     union iwreq_data *wrqu, char *b)
198{
199	struct r8192_priv *priv = ieee80211_priv(dev);
200	int ret;
201
202	down(&priv->wx_sem);
203
204	ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
205
206	rtl8192_set_rxconf(dev);
207
208	up(&priv->wx_sem);
209	return ret;
210}
211
212struct  iw_range_with_scan_capa {
213	/* Informative stuff (to choose between different interface) */
214	__u32           throughput;     /* To give an idea... */
215	/* In theory this value should be the maximum benchmarked
216	 * TCP/IP throughput, because with most of these devices the
217	 * bit rate is meaningless (overhead an co) to estimate how
218	 * fast the connection will go and pick the fastest one.
219	 * I suggest people to play with Netperf or any benchmark...
220	 */
221
222	/* NWID (or domain id) */
223	__u32           min_nwid;       /* Minimal NWID we are able to set */
224	__u32           max_nwid;       /* Maximal NWID we are able to set */
225
226	/* Old Frequency (backward compat - moved lower ) */
227	__u16           old_num_channels;
228	__u8            old_num_frequency;
229
230	/* Scan capabilities */
231	__u8            scan_capa;
232};
233static int rtl8180_wx_get_range(struct net_device *dev,
234				struct iw_request_info *info,
235				union iwreq_data *wrqu, char *extra)
236{
237	struct iw_range *range = (struct iw_range *)extra;
238	struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
239	struct r8192_priv *priv = ieee80211_priv(dev);
240	u16 val;
241	int i;
242
243	wrqu->data.length = sizeof(*range);
244	memset(range, 0, sizeof(*range));
245
246	/* Let's try to keep this struct in the same order as in
247	 * linux/include/wireless.h
248	 */
249
250	/* TODO: See what values we can set, and remove the ones we can't
251	 * set, or fill them with some default data.
252	 */
253
254	/* ~5 Mb/s real (802.11b) */
255	range->throughput = 5 * 1000 * 1000;
256
257	/* TODO: Not used in 802.11b? */
258	/* range->min_nwid; */	/* Minimal NWID we are able to set */
259	/* TODO: Not used in 802.11b? */
260	/* range->max_nwid; */	/* Maximal NWID we are able to set */
261
262	/* Old Frequency (backward compat - moved lower ) */
263	/* range->old_num_channels; */
264	/* range->old_num_frequency; */
265	/* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
266	if (priv->rf_set_sens != NULL)
267		range->sensitivity = priv->max_sens;	/* signal level threshold range */
268
269	range->max_qual.qual = 100;
270	/* TODO: Find real max RSSI and stick here */
271	range->max_qual.level = 0;
272	range->max_qual.noise = -98;
273	range->max_qual.updated = 7; /* Updated all three */
274
275	range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
276	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
277	range->avg_qual.level = 20 + -98;
278	range->avg_qual.noise = 0;
279	range->avg_qual.updated = 7; /* Updated all three */
280
281	range->num_bitrates = RATE_COUNT;
282
283	for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
284		range->bitrate[i] = rtl8180_rates[i];
285
286	range->min_frag = MIN_FRAG_THRESHOLD;
287	range->max_frag = MAX_FRAG_THRESHOLD;
288
289	range->min_pmp = 0;
290	range->max_pmp = 5000000;
291	range->min_pmt = 0;
292	range->max_pmt = 65535*1000;
293	range->pmp_flags = IW_POWER_PERIOD;
294	range->pmt_flags = IW_POWER_TIMEOUT;
295	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
296
297	range->we_version_compiled = WIRELESS_EXT;
298	range->we_version_source = 16;
299
300	/* range->retry_capa; */	/* What retry options are supported */
301	/* range->retry_flags; */	/* How to decode max/min retry limit */
302	/* range->r_time_flags; */	/* How to decode max/min retry life */
303	/* range->min_retry; */		/* Minimal number of retries */
304	/* range->max_retry; */		/* Maximal number of retries */
305	/* range->min_r_time; */	/* Minimal retry lifetime */
306	/* range->max_r_time; */	/* Maximal retry lifetime */
307
308
309	for (i = 0, val = 0; i < 14; i++) {
310
311		/* Include only legal frequencies for some countries */
312		if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
313			range->freq[val].i = i + 1;
314			range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
315			range->freq[val].e = 1;
316			val++;
317		} else {
318			/* FIXME: do we need to set anything for channels */
319			/* we don't use ? */
320		}
321
322		if (val == IW_MAX_FREQUENCIES)
323			break;
324	}
325	range->num_frequency = val;
326	range->num_channels = val;
327	range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
328			  IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
329	tmp->scan_capa = 0x01;
330	return 0;
331}
332
333
334static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
335			     union iwreq_data *wrqu, char *b)
336{
337	struct r8192_priv *priv = ieee80211_priv(dev);
338	struct ieee80211_device *ieee = priv->ieee80211;
339	int ret = 0;
340
341	if (!priv->up)
342		return -ENETDOWN;
343
344	if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
345		return -EAGAIN;
346	if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
347		struct iw_scan_req *req = (struct iw_scan_req *)b;
348		if (req->essid_len) {
349			ieee->current_network.ssid_len = req->essid_len;
350			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
351		}
352	}
353
354	down(&priv->wx_sem);
355	if (priv->ieee80211->state != IEEE80211_LINKED) {
356		priv->ieee80211->scanning = 0;
357		ieee80211_softmac_scan_syncro(priv->ieee80211);
358		ret = 0;
359	} else {
360		ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
361	}
362	up(&priv->wx_sem);
363	return ret;
364}
365
366
367static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
368			     union iwreq_data *wrqu, char *b)
369{
370
371	int ret;
372	struct r8192_priv *priv = ieee80211_priv(dev);
373
374	if (!priv->up)
375		return -ENETDOWN;
376
377	down(&priv->wx_sem);
378
379	ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
380
381	up(&priv->wx_sem);
382
383	return ret;
384}
385
386static int r8192_wx_set_essid(struct net_device *dev,
387			      struct iw_request_info *a,
388			      union iwreq_data *wrqu, char *b)
389{
390	struct r8192_priv *priv = ieee80211_priv(dev);
391	int ret;
392
393	down(&priv->wx_sem);
394
395	ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
396
397	up(&priv->wx_sem);
398
399	return ret;
400}
401
402
403
404
405static int r8192_wx_get_essid(struct net_device *dev,
406			      struct iw_request_info *a,
407			      union iwreq_data *wrqu, char *b)
408{
409	int ret;
410	struct r8192_priv *priv = ieee80211_priv(dev);
411
412	down(&priv->wx_sem);
413
414	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
415
416	up(&priv->wx_sem);
417
418	return ret;
419}
420
421
422static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
423			     union iwreq_data *wrqu, char *b)
424{
425	int ret;
426	struct r8192_priv *priv = ieee80211_priv(dev);
427
428	down(&priv->wx_sem);
429
430	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
431
432	up(&priv->wx_sem);
433	return ret;
434}
435
436static int r8192_wx_get_name(struct net_device *dev,
437			     struct iw_request_info *info,
438			     union iwreq_data *wrqu, char *extra)
439{
440	struct r8192_priv *priv = ieee80211_priv(dev);
441
442	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
443}
444
445
446static int r8192_wx_set_frag(struct net_device *dev,
447			     struct iw_request_info *info,
448			     union iwreq_data *wrqu, char *extra)
449{
450	struct r8192_priv *priv = ieee80211_priv(dev);
451
452	if (wrqu->frag.disabled)
453		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
454	else {
455		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
456		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
457			return -EINVAL;
458
459		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
460	}
461
462	return 0;
463}
464
465
466static int r8192_wx_get_frag(struct net_device *dev,
467			     struct iw_request_info *info,
468			     union iwreq_data *wrqu, char *extra)
469{
470	struct r8192_priv *priv = ieee80211_priv(dev);
471
472	wrqu->frag.value = priv->ieee80211->fts;
473	wrqu->frag.fixed = 0;	/* no auto select */
474	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
475
476	return 0;
477}
478
479
480static int r8192_wx_set_wap(struct net_device *dev,
481			 struct iw_request_info *info,
482			 union iwreq_data *awrq,
483			 char *extra)
484{
485
486	int ret;
487	struct r8192_priv *priv = ieee80211_priv(dev);
488	/* struct sockaddr *temp = (struct sockaddr *)awrq; */
489	down(&priv->wx_sem);
490
491	ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
492
493	up(&priv->wx_sem);
494
495	return ret;
496
497}
498
499
500static int r8192_wx_get_wap(struct net_device *dev,
501			    struct iw_request_info *info,
502			    union iwreq_data *wrqu, char *extra)
503{
504	struct r8192_priv *priv = ieee80211_priv(dev);
505
506	return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
507}
508
509
510static int r8192_wx_get_enc(struct net_device *dev,
511			    struct iw_request_info *info,
512			    union iwreq_data *wrqu, char *key)
513{
514	struct r8192_priv *priv = ieee80211_priv(dev);
515
516	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
517}
518
519static int r8192_wx_set_enc(struct net_device *dev,
520			    struct iw_request_info *info,
521			    union iwreq_data *wrqu, char *key)
522{
523	struct r8192_priv *priv = ieee80211_priv(dev);
524	struct ieee80211_device *ieee = priv->ieee80211;
525	int ret;
526	u32 hwkey[4] = {0, 0, 0, 0};
527	u8 mask = 0xff;
528	u32 key_idx = 0;
529	u8 zero_addr[4][6] = {	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
530				{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
531				{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
532				{0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
533	int i;
534
535	if (!priv->up)
536		return -ENETDOWN;
537
538	down(&priv->wx_sem);
539
540	RT_TRACE(COMP_SEC, "Setting SW wep key");
541	ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
542
543	up(&priv->wx_sem);
544
545
546
547	/* sometimes, the length is zero while we do not type key value */
548	if (wrqu->encoding.length != 0) {
549
550		for (i = 0; i < 4; i++) {
551			hwkey[i] |=  key[4*i+0]&mask;
552			if (i == 1 && (4*i+1) == wrqu->encoding.length)
553				mask = 0x00;
554			if (i == 3 && (4*i+1) == wrqu->encoding.length)
555				mask = 0x00;
556			hwkey[i] |= (key[4*i+1]&mask)<<8;
557			hwkey[i] |= (key[4*i+2]&mask)<<16;
558			hwkey[i] |= (key[4*i+3]&mask)<<24;
559		}
560
561		#define CONF_WEP40  0x4
562		#define CONF_WEP104 0x14
563
564		switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
565		case 0:
566			key_idx = ieee->tx_keyidx;
567			break;
568		case 1:
569			key_idx = 0;
570			break;
571		case 2:
572			key_idx = 1;
573			break;
574		case 3:
575			key_idx = 2;
576			break;
577		case 4:
578			key_idx	= 3;
579			break;
580		default:
581			break;
582		}
583
584		if (wrqu->encoding.length == 0x5) {
585				ieee->pairwise_key_type = KEY_TYPE_WEP40;
586			EnableHWSecurityConfig8192(dev);
587
588			setKey(dev,
589				key_idx,                /* EntryNo */
590				key_idx,                /* KeyIndex */
591				KEY_TYPE_WEP40,         /* KeyType */
592				zero_addr[key_idx],
593				0,                      /* DefaultKey */
594				hwkey);                 /* KeyContent */
595
596		}
597
598		else if (wrqu->encoding.length == 0xd) {
599				ieee->pairwise_key_type = KEY_TYPE_WEP104;
600				EnableHWSecurityConfig8192(dev);
601
602			setKey(dev,
603				key_idx,                /* EntryNo */
604				key_idx,                /* KeyIndex */
605				KEY_TYPE_WEP104,        /* KeyType */
606				zero_addr[key_idx],
607				0,                      /* DefaultKey */
608				hwkey);                 /* KeyContent */
609
610		} else {
611			printk("wrong type in WEP, not WEP40 and WEP104\n");
612		}
613
614	}
615
616	return ret;
617}
618
619
620static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
621					union iwreq_data *wrqu, char *p)
622{
623
624	struct r8192_priv *priv = ieee80211_priv(dev);
625	int *parms = (int *)p;
626	int mode = parms[0];
627
628	priv->ieee80211->active_scan = mode;
629
630	return 1;
631}
632
633
634
635static int r8192_wx_set_retry(struct net_device *dev,
636				struct iw_request_info *info,
637				union iwreq_data *wrqu, char *extra)
638{
639	struct r8192_priv *priv = ieee80211_priv(dev);
640	int err = 0;
641
642	down(&priv->wx_sem);
643
644	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
645	    wrqu->retry.disabled){
646		err = -EINVAL;
647		goto exit;
648	}
649	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
650		err = -EINVAL;
651		goto exit;
652	}
653
654	if (wrqu->retry.value > R8180_MAX_RETRY) {
655		err = -EINVAL;
656		goto exit;
657	}
658	if (wrqu->retry.flags & IW_RETRY_MAX) {
659		priv->retry_rts = wrqu->retry.value;
660		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
661
662	} else {
663		priv->retry_data = wrqu->retry.value;
664		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
665	}
666
667	/* FIXME !
668	 * We might try to write directly the TX config register
669	 * or to restart just the (R)TX process.
670	 * I'm unsure if whole reset is really needed
671	 */
672
673	rtl8192_commit(dev);
674exit:
675	up(&priv->wx_sem);
676
677	return err;
678}
679
680static int r8192_wx_get_retry(struct net_device *dev,
681				struct iw_request_info *info,
682				union iwreq_data *wrqu, char *extra)
683{
684	struct r8192_priv *priv = ieee80211_priv(dev);
685
686
687	wrqu->retry.disabled = 0; /* can't be disabled */
688
689	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
690	    IW_RETRY_LIFETIME)
691		return -EINVAL;
692
693	if (wrqu->retry.flags & IW_RETRY_MAX) {
694		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
695		wrqu->retry.value = priv->retry_rts;
696	} else {
697		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
698		wrqu->retry.value = priv->retry_data;
699	}
700
701
702	return 0;
703}
704
705static int r8192_wx_get_sens(struct net_device *dev,
706				struct iw_request_info *info,
707				union iwreq_data *wrqu, char *extra)
708{
709	struct r8192_priv *priv = ieee80211_priv(dev);
710
711	if (priv->rf_set_sens == NULL)
712		return -1; /* we have not this support for this radio */
713	wrqu->sens.value = priv->sens;
714	return 0;
715}
716
717
718static int r8192_wx_set_sens(struct net_device *dev,
719				struct iw_request_info *info,
720				union iwreq_data *wrqu, char *extra)
721{
722
723	struct r8192_priv *priv = ieee80211_priv(dev);
724	short err = 0;
725
726	down(&priv->wx_sem);
727	if (priv->rf_set_sens == NULL) {
728		err = -1; /* we have not this support for this radio */
729		goto exit;
730	}
731	if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
732		priv->sens = wrqu->sens.value;
733	else
734		err = -EINVAL;
735
736exit:
737	up(&priv->wx_sem);
738
739	return err;
740}
741
742/* hw security need to reorganized. */
743static int r8192_wx_set_enc_ext(struct net_device *dev,
744					struct iw_request_info *info,
745					union iwreq_data *wrqu, char *extra)
746{
747	int ret = 0;
748	struct r8192_priv *priv = ieee80211_priv(dev);
749	struct ieee80211_device *ieee = priv->ieee80211;
750
751
752	down(&priv->wx_sem);
753	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
754
755	{
756		u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
757		u8 zero[6] = {0};
758		u32 key[4] = {0};
759		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
760		struct iw_point *encoding = &wrqu->encoding;
761		u8 idx = 0, alg = 0, group = 0;
762		if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
763			/* none is not allowed to use hwsec WB 2008.07.01 */
764			goto end_hw_sec;
765
766		/* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
767		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
768		idx = encoding->flags & IW_ENCODE_INDEX;
769		if (idx)
770			idx--;
771		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
772
773		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40)) {
774			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
775				alg = KEY_TYPE_WEP104;
776			ieee->pairwise_key_type = alg;
777			EnableHWSecurityConfig8192(dev);
778		}
779		memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
780
781		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
782
783			setKey(dev,
784					idx,	/* EntryNao */
785					idx,	/* KeyIndex */
786					alg,	/* KeyType */
787					zero,	/* MacAddr */
788					0,	/* DefaultKey */
789					key);	/* KeyContent */
790		} else if (group) {
791			ieee->group_key_type = alg;
792			setKey(dev,
793					idx,	/* EntryNo */
794					idx,	/* KeyIndex */
795					alg,	/* KeyType */
796					broadcast_addr,	/* MacAddr */
797					0,		/* DefaultKey */
798					key);		/* KeyContent */
799		} else {	/* pairwise key */
800			setKey(dev,
801					4,	/* EntryNo */
802					idx,	/* KeyIndex */
803					alg,	/* KeyType */
804					(u8 *)ieee->ap_mac_addr,/* MacAddr */
805					0,			/* DefaultKey */
806					key);			/* KeyContent */
807		}
808
809
810	}
811
812end_hw_sec:
813
814	up(&priv->wx_sem);
815	return ret;
816
817}
818static int r8192_wx_set_auth(struct net_device *dev,
819					struct iw_request_info *info,
820					union iwreq_data *data, char *extra)
821{
822	int ret = 0;
823	struct r8192_priv *priv = ieee80211_priv(dev);
824
825	down(&priv->wx_sem);
826	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
827	up(&priv->wx_sem);
828	return ret;
829}
830
831static int r8192_wx_set_mlme(struct net_device *dev,
832					struct iw_request_info *info,
833					union iwreq_data *wrqu, char *extra)
834{
835
836	int ret = 0;
837	struct r8192_priv *priv = ieee80211_priv(dev);
838
839	down(&priv->wx_sem);
840	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
841
842	up(&priv->wx_sem);
843	return ret;
844}
845
846static int r8192_wx_set_gen_ie(struct net_device *dev,
847					struct iw_request_info *info,
848					union iwreq_data *data, char *extra)
849{
850	int ret = 0;
851	struct r8192_priv *priv = ieee80211_priv(dev);
852
853	down(&priv->wx_sem);
854	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
855	up(&priv->wx_sem);
856	return ret;
857
858
859}
860
861static int dummy(struct net_device *dev, struct iw_request_info *a,
862		 union iwreq_data *wrqu, char *b)
863{
864	return -1;
865}
866
867
868static iw_handler r8192_wx_handlers[] = {
869	NULL,                     /* SIOCSIWCOMMIT */
870	r8192_wx_get_name,	  /* SIOCGIWNAME */
871	dummy,                    /* SIOCSIWNWID */
872	dummy,                    /* SIOCGIWNWID */
873	r8192_wx_set_freq,        /* SIOCSIWFREQ */
874	r8192_wx_get_freq,        /* SIOCGIWFREQ */
875	r8192_wx_set_mode,        /* SIOCSIWMODE */
876	r8192_wx_get_mode,        /* SIOCGIWMODE */
877	r8192_wx_set_sens,        /* SIOCSIWSENS */
878	r8192_wx_get_sens,        /* SIOCGIWSENS */
879	NULL,                     /* SIOCSIWRANGE */
880	rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
881	NULL,                     /* SIOCSIWPRIV */
882	NULL,                     /* SIOCGIWPRIV */
883	NULL,                     /* SIOCSIWSTATS */
884	NULL,                     /* SIOCGIWSTATS */
885	dummy,                    /* SIOCSIWSPY */
886	dummy,                    /* SIOCGIWSPY */
887	NULL,                     /* SIOCGIWTHRSPY */
888	NULL,                     /* SIOCWIWTHRSPY */
889	r8192_wx_set_wap,	  /* SIOCSIWAP */
890	r8192_wx_get_wap,         /* SIOCGIWAP */
891	r8192_wx_set_mlme,                     /* MLME-- */
892	dummy,                     /* SIOCGIWAPLIST -- deprecated */
893	r8192_wx_set_scan,        /* SIOCSIWSCAN */
894	r8192_wx_get_scan,        /* SIOCGIWSCAN */
895	r8192_wx_set_essid,       /* SIOCSIWESSID */
896	r8192_wx_get_essid,       /* SIOCGIWESSID */
897	dummy,                    /* SIOCSIWNICKN */
898	dummy,                    /* SIOCGIWNICKN */
899	NULL,                     /* -- hole -- */
900	NULL,                     /* -- hole -- */
901	r8192_wx_set_rate,        /* SIOCSIWRATE */
902	r8192_wx_get_rate,        /* SIOCGIWRATE */
903	r8192_wx_set_rts,                    /* SIOCSIWRTS */
904	r8192_wx_get_rts,                    /* SIOCGIWRTS */
905	r8192_wx_set_frag,        /* SIOCSIWFRAG */
906	r8192_wx_get_frag,        /* SIOCGIWFRAG */
907	dummy,                    /* SIOCSIWTXPOW */
908	dummy,                    /* SIOCGIWTXPOW */
909	r8192_wx_set_retry,       /* SIOCSIWRETRY */
910	r8192_wx_get_retry,       /* SIOCGIWRETRY */
911	r8192_wx_set_enc,         /* SIOCSIWENCODE */
912	r8192_wx_get_enc,         /* SIOCGIWENCODE */
913	r8192_wx_set_power,                    /* SIOCSIWPOWER */
914	r8192_wx_get_power,                    /* SIOCGIWPOWER */
915	NULL,			/*---hole---*/
916	NULL,			/*---hole---*/
917	r8192_wx_set_gen_ie, /* NULL, */		/* SIOCSIWGENIE */
918	NULL,			/* SIOCSIWGENIE */
919
920	r8192_wx_set_auth,/* NULL, */			/* SIOCSIWAUTH */
921	NULL,/* r8192_wx_get_auth, */ /* NULL, */	/* SIOCSIWAUTH */
922	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
923	NULL,/* r8192_wx_get_enc_ext, *//* NULL, */			/* SIOCSIWENCODEEXT */
924	NULL,			/* SIOCSIWPMKSA */
925	NULL,			 /*---hole---*/
926
927};
928
929
930static const struct iw_priv_args r8192_private_args[] = {
931
932	{
933		SIOCIWFIRSTPRIV + 0x0,
934		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
935	},
936
937	{
938		SIOCIWFIRSTPRIV + 0x1,
939		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
940
941	},
942	{
943		SIOCIWFIRSTPRIV + 0x2,
944		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
945	},
946	{
947		SIOCIWFIRSTPRIV + 0x3,
948		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
949
950	}
951
952};
953
954
955static iw_handler r8192_private_handler[] = {
956	r8192_wx_set_crcmon,
957	r8192_wx_set_scan_type,
958	r8192_wx_set_rawtx,
959	r8192_wx_force_reset,
960};
961
962struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
963{
964	struct r8192_priv *priv = ieee80211_priv(dev);
965	struct ieee80211_device *ieee = priv->ieee80211;
966	struct iw_statistics *wstats = &priv->wstats;
967	int tmp_level = 0;
968	int tmp_qual = 0;
969	int tmp_noise = 0;
970
971	if (ieee->state < IEEE80211_LINKED) {
972		wstats->qual.qual = 0;
973		wstats->qual.level = 0;
974		wstats->qual.noise = 0;
975		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
976		return wstats;
977	}
978
979	tmp_level = (&ieee->current_network)->stats.rssi;
980	tmp_qual = (&ieee->current_network)->stats.signal;
981	tmp_noise = (&ieee->current_network)->stats.noise;
982
983	wstats->qual.level = tmp_level;
984	wstats->qual.qual = tmp_qual;
985	wstats->qual.noise = tmp_noise;
986	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
987	return wstats;
988}
989
990
991struct iw_handler_def  r8192_wx_handlers_def = {
992	.standard = r8192_wx_handlers,
993	.num_standard = ARRAY_SIZE(r8192_wx_handlers),
994	.private = r8192_private_handler,
995	.num_private = ARRAY_SIZE(r8192_private_handler),
996	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
997	.get_wireless_stats = r8192_get_wireless_stats,
998	.private_args = (struct iw_priv_args *)r8192_private_args,
999};
1000