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