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