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