Merge branch 'stable/for-jens-4.5' of git://git.kernel.org/pub/scm/linux/kernel/git...
[deliverable/linux.git] / drivers / staging / rtl8192u / r8192U_wx.c
CommitLineData
8fc8598e
JC
1/*
2 This file contains wireless extension handlers.
3
4 This is part of rtl8180 OpenSource driver.
559a4c31 5 Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
8fc8598e
JC
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
ffae3055 16 We want to thank the Authors of those projects and the Ndiswrapper
8fc8598e
JC
17 project Authors.
18*/
19
20#include <linux/string.h>
21#include "r8192U.h"
22#include "r8192U_hw.h"
23
8fc8598e 24#include "dot11d.h"
c4d6b8fb 25#include "r8192U_wx.h"
8fc8598e
JC
26
27#define RATE_COUNT 12
c4d6b8fb 28static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
654d1ce9 29 6000000, 9000000, 12000000, 18000000, 24000000, 36000000, 48000000, 54000000};
8fc8598e
JC
30
31
32#ifndef ENETDOWN
33#define ENETDOWN 1
34#endif
35
36static int r8192_wx_get_freq(struct net_device *dev,
37 struct iw_request_info *a,
38 union iwreq_data *wrqu, char *b)
39{
40 struct r8192_priv *priv = ieee80211_priv(dev);
41
654d1ce9 42 return ieee80211_wx_get_freq(priv->ieee80211, a, wrqu, b);
8fc8598e
JC
43}
44
45
8fc8598e
JC
46static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47 union iwreq_data *wrqu, char *b)
48{
654d1ce9 49 struct r8192_priv *priv = ieee80211_priv(dev);
8fc8598e 50
654d1ce9 51 return ieee80211_wx_get_mode(priv->ieee80211, a, wrqu, b);
8fc8598e
JC
52}
53
54
55
56static int r8192_wx_get_rate(struct net_device *dev,
57 struct iw_request_info *info,
58 union iwreq_data *wrqu, char *extra)
59{
60 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 61
654d1ce9 62 return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
63}
64
65
66
67static int r8192_wx_set_rate(struct net_device *dev,
68 struct iw_request_info *info,
69 union iwreq_data *wrqu, char *extra)
70{
71 int ret;
72 struct r8192_priv *priv = ieee80211_priv(dev);
73
74 down(&priv->wx_sem);
75
654d1ce9 76 ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
77
78 up(&priv->wx_sem);
79
80 return ret;
81}
82
83
84static int r8192_wx_set_rts(struct net_device *dev,
85 struct iw_request_info *info,
86 union iwreq_data *wrqu, char *extra)
87{
88 int ret;
89 struct r8192_priv *priv = ieee80211_priv(dev);
90
91 down(&priv->wx_sem);
92
654d1ce9 93 ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
94
95 up(&priv->wx_sem);
96
97 return ret;
98}
99
100static int r8192_wx_get_rts(struct net_device *dev,
101 struct iw_request_info *info,
102 union iwreq_data *wrqu, char *extra)
103{
104 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 105
654d1ce9 106 return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
107}
108
109static int r8192_wx_set_power(struct net_device *dev,
110 struct iw_request_info *info,
111 union iwreq_data *wrqu, char *extra)
112{
113 int ret;
114 struct r8192_priv *priv = ieee80211_priv(dev);
115
116 down(&priv->wx_sem);
117
654d1ce9 118 ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
119
120 up(&priv->wx_sem);
121
122 return ret;
123}
124
125static int r8192_wx_get_power(struct net_device *dev,
126 struct iw_request_info *info,
127 union iwreq_data *wrqu, char *extra)
128{
129 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 130
654d1ce9 131 return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
132}
133
8fc8598e
JC
134static int r8192_wx_force_reset(struct net_device *dev,
135 struct iw_request_info *info,
136 union iwreq_data *wrqu, char *extra)
137{
138 struct r8192_priv *priv = ieee80211_priv(dev);
139
140 down(&priv->wx_sem);
141
54160729 142 netdev_dbg(dev, "%s(): force reset ! extra is %d\n", __func__, *extra);
8fc8598e
JC
143 priv->force_reset = *extra;
144 up(&priv->wx_sem);
145 return 0;
146
147}
148
149
150static int r8192_wx_set_rawtx(struct net_device *dev,
151 struct iw_request_info *info,
152 union iwreq_data *wrqu, char *extra)
153{
154 struct r8192_priv *priv = ieee80211_priv(dev);
155 int ret;
156
157 down(&priv->wx_sem);
158
159 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
160
161 up(&priv->wx_sem);
162
163 return ret;
164
165}
166
167static int r8192_wx_set_crcmon(struct net_device *dev,
168 struct iw_request_info *info,
169 union iwreq_data *wrqu, char *extra)
170{
171 struct r8192_priv *priv = ieee80211_priv(dev);
172 int *parms = (int *)extra;
173 int enable = (parms[0] > 0);
8fc8598e
JC
174
175 down(&priv->wx_sem);
176
654d1ce9
CH
177 if (enable)
178 priv->crcmon = 1;
8fc8598e 179 else
654d1ce9 180 priv->crcmon = 0;
8fc8598e
JC
181
182 DMESG("bad CRC in monitor mode are %s",
183 priv->crcmon ? "accepted" : "rejected");
184
8fc8598e
JC
185 up(&priv->wx_sem);
186
187 return 0;
188}
189
190static 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;
a08d541a 195
8fc8598e
JC
196 down(&priv->wx_sem);
197
654d1ce9 198 ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b);
8fc8598e
JC
199
200 rtl8192_set_rxconf(dev);
201
202 up(&priv->wx_sem);
203 return ret;
204}
205
0db7a34e 206struct iw_range_with_scan_capa {
e406322b
MCC
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;
8fc8598e
JC
226};
227static 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;
b81c2b0a 232 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
8fc8598e
JC
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
0bb927cf
CH
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 */
8fc8598e 255
e406322b 256 /* Old Frequency (backward compat - moved lower ) */
0bb927cf
CH
257 /* range->old_num_channels; */
258 /* range->old_num_frequency; */
259 /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */
654d1ce9 260 if (priv->rf_set_sens != NULL)
8fc8598e
JC
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;
3cd66a18 266 range->max_qual.noise = 0x100 - 98;
8fc8598e
JC
267 range->max_qual.updated = 7; /* Updated all three */
268
269 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
589b3d06 270 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
3cd66a18 271 range->avg_qual.level = 0x100 - 78;
8fc8598e
JC
272 range->avg_qual.noise = 0;
273 range->avg_qual.updated = 7; /* Updated all three */
274
275 range->num_bitrates = RATE_COUNT;
276
2930d0b9 277 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
8fc8598e 278 range->bitrate[i] = rtl8180_rates[i];
8fc8598e
JC
279
280 range->min_frag = MIN_FRAG_THRESHOLD;
281 range->max_frag = MAX_FRAG_THRESHOLD;
282
654d1ce9 283 range->min_pmp = 0;
8fc8598e
JC
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
0bb927cf
CH
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 */
0b5b4e22 297 /* range->min_retry; */ /* Minimal number of retries */
0bb927cf
CH
298 /* range->max_retry; */ /* Maximal number of retries */
299 /* range->min_r_time; */ /* Minimal retry lifetime */
300 /* range->max_r_time; */ /* Maximal retry lifetime */
8fc8598e
JC
301
302
303 for (i = 0, val = 0; i < 14; i++) {
304
0bb927cf 305 /* Include only legal frequencies for some countries */
8fc8598e 306 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
e406322b 307 range->freq[val].i = i + 1;
8fc8598e
JC
308 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
309 range->freq[val].e = 1;
310 val++;
311 } else {
0bb927cf
CH
312 /* FIXME: do we need to set anything for channels */
313 /* we don't use ? */
8fc8598e
JC
314 }
315
316 if (val == IW_MAX_FREQUENCIES)
28cda5ae 317 break;
8fc8598e
JC
318 }
319 range->num_frequency = val;
e406322b 320 range->num_channels = val;
8fc8598e
JC
321 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
322 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
8fc8598e
JC
323 tmp->scan_capa = 0x01;
324 return 0;
325}
326
327
328static 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);
b81c2b0a 332 struct ieee80211_device *ieee = priv->ieee80211;
8fc8598e
JC
333 int ret = 0;
334
28cda5ae
CH
335 if (!priv->up)
336 return -ENETDOWN;
8fc8598e 337
956ff821 338 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic)
8fc8598e 339 return -EAGAIN;
28cda5ae 340 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
b81c2b0a 341 struct iw_scan_req *req = (struct iw_scan_req *)b;
95c0bab2 342
28cda5ae 343 if (req->essid_len) {
8fc8598e
JC
344 ieee->current_network.ssid_len = req->essid_len;
345 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
8fc8598e
JC
346 }
347 }
348
349 down(&priv->wx_sem);
654d1ce9 350 if (priv->ieee80211->state != IEEE80211_LINKED) {
e406322b
MCC
351 priv->ieee80211->scanning = 0;
352 ieee80211_softmac_scan_syncro(priv->ieee80211);
353 ret = 0;
28cda5ae
CH
354 } else {
355 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b);
e406322b 356 }
8fc8598e
JC
357 up(&priv->wx_sem);
358 return ret;
359}
360
361
362static 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
28cda5ae
CH
369 if (!priv->up)
370 return -ENETDOWN;
8fc8598e
JC
371
372 down(&priv->wx_sem);
373
654d1ce9 374 ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b);
8fc8598e
JC
375
376 up(&priv->wx_sem);
377
378 return ret;
379}
380
381static 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;
a08d541a 387
8fc8598e
JC
388 down(&priv->wx_sem);
389
654d1ce9 390 ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b);
8fc8598e
JC
391
392 up(&priv->wx_sem);
393
394 return ret;
395}
396
397
398
399
400static 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
417static 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
431static 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);
a08d541a 436
8fc8598e
JC
437 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
438}
439
440
441static 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
461static 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
475static 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);
0bb927cf 483 /* struct sockaddr *temp = (struct sockaddr *)awrq; */
8fc8598e
JC
484 down(&priv->wx_sem);
485
654d1ce9 486 ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra);
8fc8598e
JC
487
488 up(&priv->wx_sem);
489
490 return ret;
491
492}
493
494
495static 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
654d1ce9 501 return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra);
8fc8598e
JC
502}
503
504
505static 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
514static 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;
654d1ce9
CH
521 u32 hwkey[4] = {0, 0, 0, 0};
522 u8 mask = 0xff;
523 u32 key_idx = 0;
654d1ce9
CH
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} };
8fc8598e
JC
528 int i;
529
28cda5ae
CH
530 if (!priv->up)
531 return -ENETDOWN;
8fc8598e
JC
532
533 down(&priv->wx_sem);
534
535 RT_TRACE(COMP_SEC, "Setting SW wep key");
654d1ce9 536 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key);
8fc8598e
JC
537
538 up(&priv->wx_sem);
539
540
541
0bb927cf 542 /* sometimes, the length is zero while we do not type key value */
654d1ce9 543 if (wrqu->encoding.length != 0) {
8fc8598e 544
654d1ce9 545 for (i = 0; i < 4; i++) {
8fc8598e 546 hwkey[i] |= key[4*i+0]&mask;
28cda5ae
CH
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;
8fc8598e
JC
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
654d1ce9 559 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) {
28cda5ae
CH
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;
8fc8598e
JC
577 }
578
654d1ce9 579 if (wrqu->encoding.length == 0x5) {
8fc8598e
JC
580 ieee->pairwise_key_type = KEY_TYPE_WEP40;
581 EnableHWSecurityConfig8192(dev);
582
654d1ce9 583 setKey(dev,
0bb927cf
CH
584 key_idx, /* EntryNo */
585 key_idx, /* KeyIndex */
586 KEY_TYPE_WEP40, /* KeyType */
8fc8598e 587 zero_addr[key_idx],
0bb927cf
CH
588 0, /* DefaultKey */
589 hwkey); /* KeyContent */
8fc8598e
JC
590
591 }
592
654d1ce9 593 else if (wrqu->encoding.length == 0xd) {
8fc8598e
JC
594 ieee->pairwise_key_type = KEY_TYPE_WEP104;
595 EnableHWSecurityConfig8192(dev);
596
654d1ce9 597 setKey(dev,
0bb927cf
CH
598 key_idx, /* EntryNo */
599 key_idx, /* KeyIndex */
600 KEY_TYPE_WEP104, /* KeyType */
8fc8598e 601 zero_addr[key_idx],
0bb927cf
CH
602 0, /* DefaultKey */
603 hwkey); /* KeyContent */
8fc8598e 604
28cda5ae
CH
605 } else {
606 printk("wrong type in WEP, not WEP40 and WEP104\n");
8fc8598e 607 }
8fc8598e
JC
608
609 }
610
611 return ret;
612}
613
614
28cda5ae 615static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa,
e00b8fdc
CH
616 union iwreq_data *wrqu, char *p)
617{
8fc8598e 618
e406322b 619 struct r8192_priv *priv = ieee80211_priv(dev);
654d1ce9
CH
620 int *parms = (int *)p;
621 int mode = parms[0];
8fc8598e
JC
622
623 priv->ieee80211->active_scan = mode;
624
625 return 1;
626}
627
628
629
630static 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 }
654d1ce9 644 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) {
8fc8598e
JC
645 err = -EINVAL;
646 goto exit;
647 }
648
654d1ce9
CH
649 if (wrqu->retry.value > R8180_MAX_RETRY) {
650 err = -EINVAL;
8fc8598e
JC
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
654d1ce9 657 } else {
8fc8598e
JC
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
e406322b 668 rtl8192_commit(dev);
8fc8598e
JC
669exit:
670 up(&priv->wx_sem);
671
672 return err;
673}
674
675static 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 }
8fc8598e
JC
695
696
697 return 0;
698}
699
700static 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);
a08d541a 705
654d1ce9 706 if (priv->rf_set_sens == NULL)
8fc8598e
JC
707 return -1; /* we have not this support for this radio */
708 wrqu->sens.value = priv->sens;
709 return 0;
710}
711
712
713static 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);
8fc8598e 719 short err = 0;
a08d541a 720
8fc8598e 721 down(&priv->wx_sem);
654d1ce9
CH
722 if (priv->rf_set_sens == NULL) {
723 err = -1; /* we have not this support for this radio */
8fc8598e
JC
724 goto exit;
725 }
654d1ce9 726 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0)
8fc8598e
JC
727 priv->sens = wrqu->sens.value;
728 else
654d1ce9 729 err = -EINVAL;
8fc8598e
JC
730
731exit:
732 up(&priv->wx_sem);
733
734 return err;
735}
736
0bb927cf 737/* hw security need to reorganized. */
8fc8598e 738static int r8192_wx_set_enc_ext(struct net_device *dev,
e406322b
MCC
739 struct iw_request_info *info,
740 union iwreq_data *wrqu, char *extra)
8fc8598e 741{
654d1ce9 742 int ret = 0;
8fc8598e 743 struct r8192_priv *priv = ieee80211_priv(dev);
b81c2b0a 744 struct ieee80211_device *ieee = priv->ieee80211;
8fc8598e
JC
745
746
747 down(&priv->wx_sem);
748 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
749
750 {
654d1ce9 751 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
8fc8598e
JC
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;
8fc8598e 756 u8 idx = 0, alg = 0, group = 0;
95c0bab2 757
28cda5ae 758 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE)
0bb927cf 759 /* none is not allowed to use hwsec WB 2008.07.01 */
8fc8598e
JC
760 goto end_hw_sec;
761
0bb927cf 762 /* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */
28cda5ae 763 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg;
8fc8598e
JC
764 idx = encoding->flags & IW_ENCODE_INDEX;
765 if (idx)
654d1ce9 766 idx--;
8fc8598e
JC
767 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
768
28cda5ae 769 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) {
654d1ce9 770 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40))
8fc8598e
JC
771 alg = KEY_TYPE_WEP104;
772 ieee->pairwise_key_type = alg;
773 EnableHWSecurityConfig8192(dev);
774 }
0bb927cf 775 memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */
8fc8598e 776
28cda5ae 777 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) {
8fc8598e 778
654d1ce9 779 setKey(dev,
0bb927cf
CH
780 idx, /* EntryNao */
781 idx, /* KeyIndex */
782 alg, /* KeyType */
783 zero, /* MacAddr */
784 0, /* DefaultKey */
785 key); /* KeyContent */
28cda5ae 786 } else if (group) {
8fc8598e 787 ieee->group_key_type = alg;
654d1ce9 788 setKey(dev,
0bb927cf
CH
789 idx, /* EntryNo */
790 idx, /* KeyIndex */
791 alg, /* KeyType */
792 broadcast_addr, /* MacAddr */
793 0, /* DefaultKey */
794 key); /* KeyContent */
795 } else { /* pairwise key */
654d1ce9 796 setKey(dev,
0bb927cf
CH
797 4, /* EntryNo */
798 idx, /* KeyIndex */
799 alg, /* KeyType */
800 (u8 *)ieee->ap_mac_addr,/* MacAddr */
801 0, /* DefaultKey */
0b5b4e22 802 key); /* KeyContent */
8fc8598e
JC
803 }
804
805
806 }
807
808end_hw_sec:
809
810 up(&priv->wx_sem);
8fc8598e
JC
811 return ret;
812
813}
814static int r8192_wx_set_auth(struct net_device *dev,
e406322b
MCC
815 struct iw_request_info *info,
816 union iwreq_data *data, char *extra)
8fc8598e 817{
654d1ce9 818 int ret = 0;
8fc8598e 819 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 820
8fc8598e
JC
821 down(&priv->wx_sem);
822 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
823 up(&priv->wx_sem);
8fc8598e
JC
824 return ret;
825}
826
827static int r8192_wx_set_mlme(struct net_device *dev,
e406322b
MCC
828 struct iw_request_info *info,
829 union iwreq_data *wrqu, char *extra)
8fc8598e 830{
8fc8598e 831
654d1ce9 832 int ret = 0;
8fc8598e 833 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 834
8fc8598e
JC
835 down(&priv->wx_sem);
836 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
837
838 up(&priv->wx_sem);
8fc8598e
JC
839 return ret;
840}
e6c1ef6c 841
8fc8598e 842static int r8192_wx_set_gen_ie(struct net_device *dev,
e406322b
MCC
843 struct iw_request_info *info,
844 union iwreq_data *data, char *extra)
8fc8598e 845{
654d1ce9 846 int ret = 0;
e406322b 847 struct r8192_priv *priv = ieee80211_priv(dev);
a08d541a 848
e406322b 849 down(&priv->wx_sem);
e406322b 850 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
e406322b 851 up(&priv->wx_sem);
e406322b 852 return ret;
8fc8598e
JC
853
854
855}
856
857static int dummy(struct net_device *dev, struct iw_request_info *a,
654d1ce9 858 union iwreq_data *wrqu, char *b)
8fc8598e
JC
859{
860 return -1;
861}
862
863
28cda5ae 864static iw_handler r8192_wx_handlers[] = {
e406322b 865 NULL, /* SIOCSIWCOMMIT */
35997ff0 866 r8192_wx_get_name, /* SIOCGIWNAME */
e406322b
MCC
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 */
35997ff0 885 r8192_wx_set_wap, /* SIOCSIWAP */
e406322b 886 r8192_wx_get_wap, /* SIOCGIWAP */
e406322b 887 r8192_wx_set_mlme, /* MLME-- */
589b3d06 888 dummy, /* SIOCGIWAPLIST -- deprecated */
e406322b
MCC
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 */
8fc8598e 911 NULL, /*---hole---*/
35997ff0 912 NULL, /*---hole---*/
0bb927cf 913 r8192_wx_set_gen_ie, /* NULL, */ /* SIOCSIWGENIE */
35997ff0 914 NULL, /* SIOCSIWGENIE */
8fc8598e 915
0bb927cf
CH
916 r8192_wx_set_auth,/* NULL, */ /* SIOCSIWAUTH */
917 NULL,/* r8192_wx_get_auth, */ /* NULL, */ /* SIOCSIWAUTH */
35997ff0 918 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
0bb927cf 919 NULL,/* r8192_wx_get_enc_ext, *//* NULL, */ /* SIOCSIWENCODEEXT */
35997ff0
SH
920 NULL, /* SIOCSIWPMKSA */
921 NULL, /*---hole---*/
8fc8598e
JC
922
923};
924
925
926static 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"
aa0cb59c 941 },
8fc8598e
JC
942 {
943 SIOCIWFIRSTPRIV + 0x3,
944 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
945
946 }
947
948};
949
950
951static iw_handler r8192_private_handler[] = {
a2581a4a 952 r8192_wx_set_crcmon,
8fc8598e
JC
953 r8192_wx_set_scan_type,
954 r8192_wx_set_rawtx,
8fc8598e
JC
955 r8192_wx_force_reset,
956};
957
8fc8598e
JC
958struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
959{
654d1ce9 960 struct r8192_priv *priv = ieee80211_priv(dev);
b81c2b0a
XR
961 struct ieee80211_device *ieee = priv->ieee80211;
962 struct iw_statistics *wstats = &priv->wstats;
8fc8598e
JC
963 int tmp_level = 0;
964 int tmp_qual = 0;
965 int tmp_noise = 0;
a08d541a 966
28cda5ae 967 if (ieee->state < IEEE80211_LINKED) {
8fc8598e
JC
968 wstats->qual.qual = 0;
969 wstats->qual.level = 0;
970 wstats->qual.noise = 0;
8fc8598e 971 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
8fc8598e
JC
972 return wstats;
973 }
974
654d1ce9 975 tmp_level = (&ieee->current_network)->stats.rssi;
8fc8598e
JC
976 tmp_qual = (&ieee->current_network)->stats.signal;
977 tmp_noise = (&ieee->current_network)->stats.noise;
8fc8598e
JC
978
979 wstats->qual.level = tmp_level;
980 wstats->qual.qual = tmp_qual;
981 wstats->qual.noise = tmp_noise;
31c207f4 982 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
8fc8598e
JC
983 return wstats;
984}
8fc8598e
JC
985
986
654d1ce9 987struct iw_handler_def r8192_wx_handlers_def = {
8fc8598e 988 .standard = r8192_wx_handlers,
b330f606 989 .num_standard = ARRAY_SIZE(r8192_wx_handlers),
8fc8598e 990 .private = r8192_private_handler,
b330f606 991 .num_private = ARRAY_SIZE(r8192_private_handler),
e406322b 992 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
8fc8598e 993 .get_wireless_stats = r8192_get_wireless_stats,
8fc8598e
JC
994 .private_args = (struct iw_priv_args *)r8192_private_args,
995};
This page took 0.683219 seconds and 5 git commands to generate.