• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	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 
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 	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 
r8192_wx_set_mode(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)196 static 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 
212 struct  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 };
rtl8180_wx_get_range(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)233 static 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 
r8192_wx_set_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)334 static 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 
349 		if (req->essid_len) {
350 			ieee->current_network.ssid_len = req->essid_len;
351 			memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
352 		}
353 	}
354 
355 	down(&priv->wx_sem);
356 	if (priv->ieee80211->state != IEEE80211_LINKED) {
357 		priv->ieee80211->scanning = 0;
358 		ieee80211_softmac_scan_syncro(priv->ieee80211);
359 		ret = 0;
360 	} else {
361 		ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
362 	}
363 	up(&priv->wx_sem);
364 	return ret;
365 }
366 
367 
r8192_wx_get_scan(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)368 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
369 			     union iwreq_data *wrqu, char *b)
370 {
371 
372 	int ret;
373 	struct r8192_priv *priv = ieee80211_priv(dev);
374 
375 	if (!priv->up)
376 		return -ENETDOWN;
377 
378 	down(&priv->wx_sem);
379 
380 	ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
381 
382 	up(&priv->wx_sem);
383 
384 	return ret;
385 }
386 
r8192_wx_set_essid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)387 static int r8192_wx_set_essid(struct net_device *dev,
388 			      struct iw_request_info *a,
389 			      union iwreq_data *wrqu, char *b)
390 {
391 	struct r8192_priv *priv = ieee80211_priv(dev);
392 	int ret;
393 
394 	down(&priv->wx_sem);
395 
396 	ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
397 
398 	up(&priv->wx_sem);
399 
400 	return ret;
401 }
402 
403 
404 
405 
r8192_wx_get_essid(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)406 static int r8192_wx_get_essid(struct net_device *dev,
407 			      struct iw_request_info *a,
408 			      union iwreq_data *wrqu, char *b)
409 {
410 	int ret;
411 	struct r8192_priv *priv = ieee80211_priv(dev);
412 
413 	down(&priv->wx_sem);
414 
415 	ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
416 
417 	up(&priv->wx_sem);
418 
419 	return ret;
420 }
421 
422 
r8192_wx_set_freq(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)423 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
424 			     union iwreq_data *wrqu, char *b)
425 {
426 	int ret;
427 	struct r8192_priv *priv = ieee80211_priv(dev);
428 
429 	down(&priv->wx_sem);
430 
431 	ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
432 
433 	up(&priv->wx_sem);
434 	return ret;
435 }
436 
r8192_wx_get_name(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)437 static int r8192_wx_get_name(struct net_device *dev,
438 			     struct iw_request_info *info,
439 			     union iwreq_data *wrqu, char *extra)
440 {
441 	struct r8192_priv *priv = ieee80211_priv(dev);
442 
443 	return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
444 }
445 
446 
r8192_wx_set_frag(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)447 static int r8192_wx_set_frag(struct net_device *dev,
448 			     struct iw_request_info *info,
449 			     union iwreq_data *wrqu, char *extra)
450 {
451 	struct r8192_priv *priv = ieee80211_priv(dev);
452 
453 	if (wrqu->frag.disabled)
454 		priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
455 	else {
456 		if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
457 		    wrqu->frag.value > MAX_FRAG_THRESHOLD)
458 			return -EINVAL;
459 
460 		priv->ieee80211->fts = wrqu->frag.value & ~0x1;
461 	}
462 
463 	return 0;
464 }
465 
466 
r8192_wx_get_frag(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)467 static int r8192_wx_get_frag(struct net_device *dev,
468 			     struct iw_request_info *info,
469 			     union iwreq_data *wrqu, char *extra)
470 {
471 	struct r8192_priv *priv = ieee80211_priv(dev);
472 
473 	wrqu->frag.value = priv->ieee80211->fts;
474 	wrqu->frag.fixed = 0;	/* no auto select */
475 	wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
476 
477 	return 0;
478 }
479 
480 
r8192_wx_set_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * awrq,char * extra)481 static int r8192_wx_set_wap(struct net_device *dev,
482 			 struct iw_request_info *info,
483 			 union iwreq_data *awrq,
484 			 char *extra)
485 {
486 
487 	int ret;
488 	struct r8192_priv *priv = ieee80211_priv(dev);
489 	/* struct sockaddr *temp = (struct sockaddr *)awrq; */
490 	down(&priv->wx_sem);
491 
492 	ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
493 
494 	up(&priv->wx_sem);
495 
496 	return ret;
497 
498 }
499 
500 
r8192_wx_get_wap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)501 static int r8192_wx_get_wap(struct net_device *dev,
502 			    struct iw_request_info *info,
503 			    union iwreq_data *wrqu, char *extra)
504 {
505 	struct r8192_priv *priv = ieee80211_priv(dev);
506 
507 	return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
508 }
509 
510 
r8192_wx_get_enc(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * key)511 static int r8192_wx_get_enc(struct net_device *dev,
512 			    struct iw_request_info *info,
513 			    union iwreq_data *wrqu, char *key)
514 {
515 	struct r8192_priv *priv = ieee80211_priv(dev);
516 
517 	return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
518 }
519 
r8192_wx_set_enc(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * key)520 static int r8192_wx_set_enc(struct net_device *dev,
521 			    struct iw_request_info *info,
522 			    union iwreq_data *wrqu, char *key)
523 {
524 	struct r8192_priv *priv = ieee80211_priv(dev);
525 	struct ieee80211_device *ieee = priv->ieee80211;
526 	int ret;
527 	u32 hwkey[4] = {0, 0, 0, 0};
528 	u8 mask = 0xff;
529 	u32 key_idx = 0;
530 	u8 zero_addr[4][6] = {	{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
531 				{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
532 				{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
533 				{0x00, 0x00, 0x00, 0x00, 0x00, 0x03} };
534 	int i;
535 
536 	if (!priv->up)
537 		return -ENETDOWN;
538 
539 	down(&priv->wx_sem);
540 
541 	RT_TRACE(COMP_SEC, "Setting SW wep key");
542 	ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
543 
544 	up(&priv->wx_sem);
545 
546 
547 
548 	/* sometimes, the length is zero while we do not type key value */
549 	if (wrqu->encoding.length != 0) {
550 
551 		for (i = 0; i < 4; i++) {
552 			hwkey[i] |=  key[4*i+0]&mask;
553 			if (i == 1 && (4*i+1) == wrqu->encoding.length)
554 				mask = 0x00;
555 			if (i == 3 && (4*i+1) == wrqu->encoding.length)
556 				mask = 0x00;
557 			hwkey[i] |= (key[4*i+1]&mask)<<8;
558 			hwkey[i] |= (key[4*i+2]&mask)<<16;
559 			hwkey[i] |= (key[4*i+3]&mask)<<24;
560 		}
561 
562 		#define CONF_WEP40  0x4
563 		#define CONF_WEP104 0x14
564 
565 		switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
566 		case 0:
567 			key_idx = ieee->tx_keyidx;
568 			break;
569 		case 1:
570 			key_idx = 0;
571 			break;
572 		case 2:
573 			key_idx = 1;
574 			break;
575 		case 3:
576 			key_idx = 2;
577 			break;
578 		case 4:
579 			key_idx	= 3;
580 			break;
581 		default:
582 			break;
583 		}
584 
585 		if (wrqu->encoding.length == 0x5) {
586 				ieee->pairwise_key_type = KEY_TYPE_WEP40;
587 			EnableHWSecurityConfig8192(dev);
588 
589 			setKey(dev,
590 				key_idx,                /* EntryNo */
591 				key_idx,                /* KeyIndex */
592 				KEY_TYPE_WEP40,         /* KeyType */
593 				zero_addr[key_idx],
594 				0,                      /* DefaultKey */
595 				hwkey);                 /* KeyContent */
596 
597 		}
598 
599 		else if (wrqu->encoding.length == 0xd) {
600 				ieee->pairwise_key_type = KEY_TYPE_WEP104;
601 				EnableHWSecurityConfig8192(dev);
602 
603 			setKey(dev,
604 				key_idx,                /* EntryNo */
605 				key_idx,                /* KeyIndex */
606 				KEY_TYPE_WEP104,        /* KeyType */
607 				zero_addr[key_idx],
608 				0,                      /* DefaultKey */
609 				hwkey);                 /* KeyContent */
610 
611 		} else {
612 			printk("wrong type in WEP, not WEP40 and WEP104\n");
613 		}
614 
615 	}
616 
617 	return ret;
618 }
619 
620 
r8192_wx_set_scan_type(struct net_device * dev,struct iw_request_info * aa,union iwreq_data * wrqu,char * p)621 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
622 					union iwreq_data *wrqu, char *p)
623 {
624 
625 	struct r8192_priv *priv = ieee80211_priv(dev);
626 	int *parms = (int *)p;
627 	int mode = parms[0];
628 
629 	priv->ieee80211->active_scan = mode;
630 
631 	return 1;
632 }
633 
634 
635 
r8192_wx_set_retry(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)636 static int r8192_wx_set_retry(struct net_device *dev,
637 				struct iw_request_info *info,
638 				union iwreq_data *wrqu, char *extra)
639 {
640 	struct r8192_priv *priv = ieee80211_priv(dev);
641 	int err = 0;
642 
643 	down(&priv->wx_sem);
644 
645 	if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
646 	    wrqu->retry.disabled){
647 		err = -EINVAL;
648 		goto exit;
649 	}
650 	if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
651 		err = -EINVAL;
652 		goto exit;
653 	}
654 
655 	if (wrqu->retry.value > R8180_MAX_RETRY) {
656 		err = -EINVAL;
657 		goto exit;
658 	}
659 	if (wrqu->retry.flags & IW_RETRY_MAX) {
660 		priv->retry_rts = wrqu->retry.value;
661 		DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
662 
663 	} else {
664 		priv->retry_data = wrqu->retry.value;
665 		DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
666 	}
667 
668 	/* FIXME !
669 	 * We might try to write directly the TX config register
670 	 * or to restart just the (R)TX process.
671 	 * I'm unsure if whole reset is really needed
672 	 */
673 
674 	rtl8192_commit(dev);
675 exit:
676 	up(&priv->wx_sem);
677 
678 	return err;
679 }
680 
r8192_wx_get_retry(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)681 static int r8192_wx_get_retry(struct net_device *dev,
682 				struct iw_request_info *info,
683 				union iwreq_data *wrqu, char *extra)
684 {
685 	struct r8192_priv *priv = ieee80211_priv(dev);
686 
687 
688 	wrqu->retry.disabled = 0; /* can't be disabled */
689 
690 	if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
691 	    IW_RETRY_LIFETIME)
692 		return -EINVAL;
693 
694 	if (wrqu->retry.flags & IW_RETRY_MAX) {
695 		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
696 		wrqu->retry.value = priv->retry_rts;
697 	} else {
698 		wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
699 		wrqu->retry.value = priv->retry_data;
700 	}
701 
702 
703 	return 0;
704 }
705 
r8192_wx_get_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)706 static int r8192_wx_get_sens(struct net_device *dev,
707 				struct iw_request_info *info,
708 				union iwreq_data *wrqu, char *extra)
709 {
710 	struct r8192_priv *priv = ieee80211_priv(dev);
711 
712 	if (priv->rf_set_sens == NULL)
713 		return -1; /* we have not this support for this radio */
714 	wrqu->sens.value = priv->sens;
715 	return 0;
716 }
717 
718 
r8192_wx_set_sens(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)719 static int r8192_wx_set_sens(struct net_device *dev,
720 				struct iw_request_info *info,
721 				union iwreq_data *wrqu, char *extra)
722 {
723 
724 	struct r8192_priv *priv = ieee80211_priv(dev);
725 	short err = 0;
726 
727 	down(&priv->wx_sem);
728 	if (priv->rf_set_sens == NULL) {
729 		err = -1; /* we have not this support for this radio */
730 		goto exit;
731 	}
732 	if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
733 		priv->sens = wrqu->sens.value;
734 	else
735 		err = -EINVAL;
736 
737 exit:
738 	up(&priv->wx_sem);
739 
740 	return err;
741 }
742 
743 /* 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)744 static int r8192_wx_set_enc_ext(struct net_device *dev,
745 					struct iw_request_info *info,
746 					union iwreq_data *wrqu, char *extra)
747 {
748 	int ret = 0;
749 	struct r8192_priv *priv = ieee80211_priv(dev);
750 	struct ieee80211_device *ieee = priv->ieee80211;
751 
752 
753 	down(&priv->wx_sem);
754 	ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
755 
756 	{
757 		u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
758 		u8 zero[6] = {0};
759 		u32 key[4] = {0};
760 		struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
761 		struct iw_point *encoding = &wrqu->encoding;
762 		u8 idx = 0, alg = 0, group = 0;
763 
764 		if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
765 			/* none is not allowed to use hwsec WB 2008.07.01 */
766 			goto end_hw_sec;
767 
768 		/* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
769 		alg =  (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
770 		idx = encoding->flags & IW_ENCODE_INDEX;
771 		if (idx)
772 			idx--;
773 		group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
774 
775 		if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg ==  KEY_TYPE_WEP40)) {
776 			if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
777 				alg = KEY_TYPE_WEP104;
778 			ieee->pairwise_key_type = alg;
779 			EnableHWSecurityConfig8192(dev);
780 		}
781 		memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
782 
783 		if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
784 
785 			setKey(dev,
786 					idx,	/* EntryNao */
787 					idx,	/* KeyIndex */
788 					alg,	/* KeyType */
789 					zero,	/* MacAddr */
790 					0,	/* DefaultKey */
791 					key);	/* KeyContent */
792 		} else if (group) {
793 			ieee->group_key_type = alg;
794 			setKey(dev,
795 					idx,	/* EntryNo */
796 					idx,	/* KeyIndex */
797 					alg,	/* KeyType */
798 					broadcast_addr,	/* MacAddr */
799 					0,		/* DefaultKey */
800 					key);		/* KeyContent */
801 		} else {	/* pairwise key */
802 			setKey(dev,
803 					4,	/* EntryNo */
804 					idx,	/* KeyIndex */
805 					alg,	/* KeyType */
806 					(u8 *)ieee->ap_mac_addr,/* MacAddr */
807 					0,			/* DefaultKey */
808 					key);			/* KeyContent */
809 		}
810 
811 
812 	}
813 
814 end_hw_sec:
815 
816 	up(&priv->wx_sem);
817 	return ret;
818 
819 }
r8192_wx_set_auth(struct net_device * dev,struct iw_request_info * info,union iwreq_data * data,char * extra)820 static int r8192_wx_set_auth(struct net_device *dev,
821 					struct iw_request_info *info,
822 					union iwreq_data *data, char *extra)
823 {
824 	int ret = 0;
825 	struct r8192_priv *priv = ieee80211_priv(dev);
826 
827 	down(&priv->wx_sem);
828 	ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
829 	up(&priv->wx_sem);
830 	return ret;
831 }
832 
r8192_wx_set_mlme(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)833 static int r8192_wx_set_mlme(struct net_device *dev,
834 					struct iw_request_info *info,
835 					union iwreq_data *wrqu, char *extra)
836 {
837 
838 	int ret = 0;
839 	struct r8192_priv *priv = ieee80211_priv(dev);
840 
841 	down(&priv->wx_sem);
842 	ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
843 
844 	up(&priv->wx_sem);
845 	return ret;
846 }
847 
r8192_wx_set_gen_ie(struct net_device * dev,struct iw_request_info * info,union iwreq_data * data,char * extra)848 static int r8192_wx_set_gen_ie(struct net_device *dev,
849 					struct iw_request_info *info,
850 					union iwreq_data *data, char *extra)
851 {
852 	int ret = 0;
853 	struct r8192_priv *priv = ieee80211_priv(dev);
854 
855 	down(&priv->wx_sem);
856 	ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
857 	up(&priv->wx_sem);
858 	return ret;
859 
860 
861 }
862 
dummy(struct net_device * dev,struct iw_request_info * a,union iwreq_data * wrqu,char * b)863 static int dummy(struct net_device *dev, struct iw_request_info *a,
864 		 union iwreq_data *wrqu, char *b)
865 {
866 	return -1;
867 }
868 
869 
870 static iw_handler r8192_wx_handlers[] = {
871 	NULL,                     /* SIOCSIWCOMMIT */
872 	r8192_wx_get_name,	  /* SIOCGIWNAME */
873 	dummy,                    /* SIOCSIWNWID */
874 	dummy,                    /* SIOCGIWNWID */
875 	r8192_wx_set_freq,        /* SIOCSIWFREQ */
876 	r8192_wx_get_freq,        /* SIOCGIWFREQ */
877 	r8192_wx_set_mode,        /* SIOCSIWMODE */
878 	r8192_wx_get_mode,        /* SIOCGIWMODE */
879 	r8192_wx_set_sens,        /* SIOCSIWSENS */
880 	r8192_wx_get_sens,        /* SIOCGIWSENS */
881 	NULL,                     /* SIOCSIWRANGE */
882 	rtl8180_wx_get_range,	  /* SIOCGIWRANGE */
883 	NULL,                     /* SIOCSIWPRIV */
884 	NULL,                     /* SIOCGIWPRIV */
885 	NULL,                     /* SIOCSIWSTATS */
886 	NULL,                     /* SIOCGIWSTATS */
887 	dummy,                    /* SIOCSIWSPY */
888 	dummy,                    /* SIOCGIWSPY */
889 	NULL,                     /* SIOCGIWTHRSPY */
890 	NULL,                     /* SIOCWIWTHRSPY */
891 	r8192_wx_set_wap,	  /* SIOCSIWAP */
892 	r8192_wx_get_wap,         /* SIOCGIWAP */
893 	r8192_wx_set_mlme,                     /* MLME-- */
894 	dummy,                     /* SIOCGIWAPLIST -- deprecated */
895 	r8192_wx_set_scan,        /* SIOCSIWSCAN */
896 	r8192_wx_get_scan,        /* SIOCGIWSCAN */
897 	r8192_wx_set_essid,       /* SIOCSIWESSID */
898 	r8192_wx_get_essid,       /* SIOCGIWESSID */
899 	dummy,                    /* SIOCSIWNICKN */
900 	dummy,                    /* SIOCGIWNICKN */
901 	NULL,                     /* -- hole -- */
902 	NULL,                     /* -- hole -- */
903 	r8192_wx_set_rate,        /* SIOCSIWRATE */
904 	r8192_wx_get_rate,        /* SIOCGIWRATE */
905 	r8192_wx_set_rts,                    /* SIOCSIWRTS */
906 	r8192_wx_get_rts,                    /* SIOCGIWRTS */
907 	r8192_wx_set_frag,        /* SIOCSIWFRAG */
908 	r8192_wx_get_frag,        /* SIOCGIWFRAG */
909 	dummy,                    /* SIOCSIWTXPOW */
910 	dummy,                    /* SIOCGIWTXPOW */
911 	r8192_wx_set_retry,       /* SIOCSIWRETRY */
912 	r8192_wx_get_retry,       /* SIOCGIWRETRY */
913 	r8192_wx_set_enc,         /* SIOCSIWENCODE */
914 	r8192_wx_get_enc,         /* SIOCGIWENCODE */
915 	r8192_wx_set_power,                    /* SIOCSIWPOWER */
916 	r8192_wx_get_power,                    /* SIOCGIWPOWER */
917 	NULL,			/*---hole---*/
918 	NULL,			/*---hole---*/
919 	r8192_wx_set_gen_ie, /* NULL, */		/* SIOCSIWGENIE */
920 	NULL,			/* SIOCSIWGENIE */
921 
922 	r8192_wx_set_auth,/* NULL, */			/* SIOCSIWAUTH */
923 	NULL,/* r8192_wx_get_auth, */ /* NULL, */	/* SIOCSIWAUTH */
924 	r8192_wx_set_enc_ext,			/* SIOCSIWENCODEEXT */
925 	NULL,/* r8192_wx_get_enc_ext, *//* NULL, */			/* SIOCSIWENCODEEXT */
926 	NULL,			/* SIOCSIWPMKSA */
927 	NULL,			 /*---hole---*/
928 
929 };
930 
931 
932 static const struct iw_priv_args r8192_private_args[] = {
933 
934 	{
935 		SIOCIWFIRSTPRIV + 0x0,
936 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
937 	},
938 
939 	{
940 		SIOCIWFIRSTPRIV + 0x1,
941 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
942 
943 	},
944 	{
945 		SIOCIWFIRSTPRIV + 0x2,
946 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
947 	},
948 	{
949 		SIOCIWFIRSTPRIV + 0x3,
950 		IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
951 
952 	}
953 
954 };
955 
956 
957 static iw_handler r8192_private_handler[] = {
958 	r8192_wx_set_crcmon,
959 	r8192_wx_set_scan_type,
960 	r8192_wx_set_rawtx,
961 	r8192_wx_force_reset,
962 };
963 
r8192_get_wireless_stats(struct net_device * dev)964 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
965 {
966 	struct r8192_priv *priv = ieee80211_priv(dev);
967 	struct ieee80211_device *ieee = priv->ieee80211;
968 	struct iw_statistics *wstats = &priv->wstats;
969 	int tmp_level = 0;
970 	int tmp_qual = 0;
971 	int tmp_noise = 0;
972 
973 	if (ieee->state < IEEE80211_LINKED) {
974 		wstats->qual.qual = 0;
975 		wstats->qual.level = 0;
976 		wstats->qual.noise = 0;
977 		wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
978 		return wstats;
979 	}
980 
981 	tmp_level = (&ieee->current_network)->stats.rssi;
982 	tmp_qual = (&ieee->current_network)->stats.signal;
983 	tmp_noise = (&ieee->current_network)->stats.noise;
984 
985 	wstats->qual.level = tmp_level;
986 	wstats->qual.qual = tmp_qual;
987 	wstats->qual.noise = tmp_noise;
988 	wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
989 	return wstats;
990 }
991 
992 
993 struct iw_handler_def  r8192_wx_handlers_def = {
994 	.standard = r8192_wx_handlers,
995 	.num_standard = ARRAY_SIZE(r8192_wx_handlers),
996 	.private = r8192_private_handler,
997 	.num_private = ARRAY_SIZE(r8192_private_handler),
998 	.num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
999 	.get_wireless_stats = r8192_get_wireless_stats,
1000 	.private_args = (struct iw_priv_args *)r8192_private_args,
1001 };
1002