Staging: rtl8192e: Remove support for legacy wireless extentions
[deliverable/linux.git] / drivers / staging / rtl8192e / r8192E_wx.c
CommitLineData
ecdfa446
GKH
1/*
2 This file contains wireless extension handlers.
3
4 This is part of rtl8180 OpenSource driver.
5 Copyright (C) Andrea Merello 2004-2005 <andreamrl@tiscali.it>
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 tanks the Authors of those projects and the Ndiswrapper
17 project Authors.
18*/
19
20#include <linux/string.h>
21#include "r8192E.h"
22#include "r8192E_hw.h"
5e1ad18a 23#include "r8192E_wx.h"
ecdfa446 24#ifdef ENABLE_DOT11D
65a43784 25#include "ieee80211/dot11d.h"
ecdfa446
GKH
26#endif
27
28#define RATE_COUNT 12
ab2161a0 29static const u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
ecdfa446
GKH
30 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
31
32
33#ifndef ENETDOWN
34#define ENETDOWN 1
35#endif
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
42 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
43}
44
45
ecdfa446
GKH
46static 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
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);
61 return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
62}
63
64
65
66static int r8192_wx_set_rate(struct net_device *dev,
67 struct iw_request_info *info,
68 union iwreq_data *wrqu, char *extra)
69{
70 int ret;
71 struct r8192_priv *priv = ieee80211_priv(dev);
72
f500e256 73 if (priv->bHwRadioOff)
65a43784 74 return 0;
75
ecdfa446
GKH
76 down(&priv->wx_sem);
77
78 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
79
80 up(&priv->wx_sem);
81
82 return ret;
83}
84
85
86static int r8192_wx_set_rts(struct net_device *dev,
87 struct iw_request_info *info,
88 union iwreq_data *wrqu, char *extra)
89{
90 int ret;
91 struct r8192_priv *priv = ieee80211_priv(dev);
92
f500e256 93 if (priv->bHwRadioOff)
65a43784 94 return 0;
95
ecdfa446
GKH
96 down(&priv->wx_sem);
97
98 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
99
100 up(&priv->wx_sem);
101
102 return ret;
103}
104
105static int r8192_wx_get_rts(struct net_device *dev,
106 struct iw_request_info *info,
107 union iwreq_data *wrqu, char *extra)
108{
109 struct r8192_priv *priv = ieee80211_priv(dev);
110 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
111}
112
113static int r8192_wx_set_power(struct net_device *dev,
114 struct iw_request_info *info,
115 union iwreq_data *wrqu, char *extra)
116{
117 int ret;
118 struct r8192_priv *priv = ieee80211_priv(dev);
119
f500e256 120 if (priv->bHwRadioOff)
65a43784 121 return 0;
122
ecdfa446
GKH
123 down(&priv->wx_sem);
124
125 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
126
127 up(&priv->wx_sem);
128
129 return ret;
130}
131
132static int r8192_wx_get_power(struct net_device *dev,
133 struct iw_request_info *info,
134 union iwreq_data *wrqu, char *extra)
135{
136 struct r8192_priv *priv = ieee80211_priv(dev);
137 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
138}
139
ecdfa446
GKH
140static int r8192_wx_set_rawtx(struct net_device *dev,
141 struct iw_request_info *info,
142 union iwreq_data *wrqu, char *extra)
143{
144 struct r8192_priv *priv = ieee80211_priv(dev);
145 int ret;
146
f500e256 147 if (priv->bHwRadioOff)
65a43784 148 return 0;
149
ecdfa446
GKH
150 down(&priv->wx_sem);
151
152 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
153
154 up(&priv->wx_sem);
155
156 return ret;
157
158}
159
160static int r8192_wx_force_reset(struct net_device *dev,
161 struct iw_request_info *info,
162 union iwreq_data *wrqu, char *extra)
163{
164 struct r8192_priv *priv = ieee80211_priv(dev);
165
166 down(&priv->wx_sem);
167
168 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
169 priv->force_reset = *extra;
170 up(&priv->wx_sem);
171 return 0;
172
173}
174
175
176static int r8192_wx_set_crcmon(struct net_device *dev,
177 struct iw_request_info *info,
178 union iwreq_data *wrqu, char *extra)
179{
180 struct r8192_priv *priv = ieee80211_priv(dev);
181 int *parms = (int *)extra;
182 int enable = (parms[0] > 0);
183 short prev = priv->crcmon;
184
f500e256 185 if (priv->bHwRadioOff)
65a43784 186 return 0;
187
ecdfa446
GKH
188 down(&priv->wx_sem);
189
190 if(enable)
191 priv->crcmon=1;
192 else
193 priv->crcmon=0;
194
195 DMESG("bad CRC in monitor mode are %s",
196 priv->crcmon ? "accepted" : "rejected");
197
198 if(prev != priv->crcmon && priv->up){
199 //rtl8180_down(dev);
200 //rtl8180_up(dev);
201 }
202
203 up(&priv->wx_sem);
204
205 return 0;
206}
207
208static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
209 union iwreq_data *wrqu, char *b)
210{
211 struct r8192_priv *priv = ieee80211_priv(dev);
212 RT_RF_POWER_STATE rtState;
213 int ret;
214
f500e256 215 if (priv->bHwRadioOff)
65a43784 216 return 0;
217
ecdfa446
GKH
218 rtState = priv->ieee80211->eRFPowerState;
219 down(&priv->wx_sem);
220#ifdef ENABLE_IPS
221 if(wrqu->mode == IW_MODE_ADHOC){
222
223 if(priv->ieee80211->PowerSaveControl.bInactivePs){
224 if(rtState == eRfOff){
225 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
226 {
227 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
228 up(&priv->wx_sem);
229 return -1;
230 }
231 else{
65a43784 232 RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
233 down(&priv->ieee80211->ips_sem);
ecdfa446 234 IPSLeave(dev);
65a43784 235 up(&priv->ieee80211->ips_sem);
ecdfa446
GKH
236 }
237 }
238 }
239 }
240#endif
241 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
242
243 //rtl8187_set_rxconf(dev);
244
245 up(&priv->wx_sem);
246 return ret;
247}
248
249struct iw_range_with_scan_capa
250{
251 /* Informative stuff (to choose between different interface) */
252 __u32 throughput; /* To give an idea... */
253 /* In theory this value should be the maximum benchmarked
254 * TCP/IP throughput, because with most of these devices the
255 * bit rate is meaningless (overhead an co) to estimate how
256 * fast the connection will go and pick the fastest one.
257 * I suggest people to play with Netperf or any benchmark...
258 */
259
260 /* NWID (or domain id) */
261 __u32 min_nwid; /* Minimal NWID we are able to set */
262 __u32 max_nwid; /* Maximal NWID we are able to set */
263
264 /* Old Frequency (backward compat - moved lower ) */
265 __u16 old_num_channels;
266 __u8 old_num_frequency;
267
268 /* Scan capabilities */
269 __u8 scan_capa;
270};
271static int rtl8180_wx_get_range(struct net_device *dev,
272 struct iw_request_info *info,
273 union iwreq_data *wrqu, char *extra)
274{
275 struct iw_range *range = (struct iw_range *)extra;
276 struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
277 struct r8192_priv *priv = ieee80211_priv(dev);
278 u16 val;
279 int i;
280
281 wrqu->data.length = sizeof(*range);
282 memset(range, 0, sizeof(*range));
283
284 /* Let's try to keep this struct in the same order as in
285 * linux/include/wireless.h
286 */
287
288 /* TODO: See what values we can set, and remove the ones we can't
289 * set, or fill them with some default data.
290 */
291
292 /* ~5 Mb/s real (802.11b) */
65a43784 293 range->throughput = 130 * 1000 * 1000;
ecdfa446
GKH
294
295 // TODO: Not used in 802.11b?
296// range->min_nwid; /* Minimal NWID we are able to set */
297 // TODO: Not used in 802.11b?
298// range->max_nwid; /* Maximal NWID we are able to set */
299
300 /* Old Frequency (backward compat - moved lower ) */
301// range->old_num_channels;
302// range->old_num_frequency;
303// range->old_freq[6]; /* Filler to keep "version" at the same offset */
ecdfa446
GKH
304
305 range->max_qual.qual = 100;
306 /* TODO: Find real max RSSI and stick here */
307 range->max_qual.level = 0;
308 range->max_qual.noise = -98;
309 range->max_qual.updated = 7; /* Updated all three */
310
311 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
bbc9a991 312 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
ecdfa446
GKH
313 range->avg_qual.level = 20 + -98;
314 range->avg_qual.noise = 0;
315 range->avg_qual.updated = 7; /* Updated all three */
316
317 range->num_bitrates = RATE_COUNT;
318
319 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
320 range->bitrate[i] = rtl8180_rates[i];
321 }
322
323 range->min_frag = MIN_FRAG_THRESHOLD;
324 range->max_frag = MAX_FRAG_THRESHOLD;
325
326 range->min_pmp=0;
327 range->max_pmp = 5000000;
328 range->min_pmt = 0;
329 range->max_pmt = 65535*1000;
330 range->pmp_flags = IW_POWER_PERIOD;
331 range->pmt_flags = IW_POWER_TIMEOUT;
332 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
333 range->we_version_compiled = WIRELESS_EXT;
65a43784 334 range->we_version_source = 18;
ecdfa446
GKH
335
336// range->retry_capa; /* What retry options are supported */
337// range->retry_flags; /* How to decode max/min retry limit */
338// range->r_time_flags; /* How to decode max/min retry life */
339// range->min_retry; /* Minimal number of retries */
340// range->max_retry; /* Maximal number of retries */
341// range->min_r_time; /* Minimal retry lifetime */
342// range->max_r_time; /* Maximal retry lifetime */
343
344
345 for (i = 0, val = 0; i < 14; i++) {
346
347 // Include only legal frequencies for some countries
348#ifdef ENABLE_DOT11D
349 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
350#else
351 if ((priv->ieee80211->channel_map)[i+1]) {
352#endif
353 range->freq[val].i = i + 1;
354 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
355 range->freq[val].e = 1;
356 val++;
357 } else {
358 // FIXME: do we need to set anything for channels
359 // we don't use ?
360 }
361
362 if (val == IW_MAX_FREQUENCIES)
363 break;
364 }
365 range->num_frequency = val;
366 range->num_channels = val;
890a6850 367
ecdfa446
GKH
368 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
369 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
890a6850 370
ecdfa446
GKH
371 tmp->scan_capa = 0x01;
372 return 0;
373}
374
375
376static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
377 union iwreq_data *wrqu, char *b)
378{
379 struct r8192_priv *priv = ieee80211_priv(dev);
380 struct ieee80211_device* ieee = priv->ieee80211;
381 RT_RF_POWER_STATE rtState;
382 int ret;
65a43784 383
f500e256 384 if (priv->bHwRadioOff)
65a43784 385 return 0;
386
ecdfa446 387 rtState = priv->ieee80211->eRFPowerState;
65a43784 388
ecdfa446
GKH
389 if(!priv->up) return -ENETDOWN;
390 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
391 return -EAGAIN;
392
393 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
394 {
395 struct iw_scan_req* req = (struct iw_scan_req*)b;
396 if (req->essid_len)
397 {
398 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
399 ieee->current_network.ssid_len = req->essid_len;
400 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
401 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
402 }
403 }
404
405 down(&priv->wx_sem);
406#ifdef ENABLE_IPS
407 priv->ieee80211->actscanning = true;
408 if(priv->ieee80211->state != IEEE80211_LINKED){
409 if(priv->ieee80211->PowerSaveControl.bInactivePs){
410 if(rtState == eRfOff){
411 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
412 {
413 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
414 up(&priv->wx_sem);
415 return -1;
416 }
417 else{
65a43784 418 //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
419 down(&priv->ieee80211->ips_sem);
ecdfa446 420 IPSLeave(dev);
65a43784 421 up(&priv->ieee80211->ips_sem);
ecdfa446
GKH
422 }
423 }
424 }
425 priv->ieee80211->scanning = 0;
426 ieee80211_softmac_scan_syncro(priv->ieee80211);
427 ret = 0;
428 }
429 else
430#else
431
432 if(priv->ieee80211->state != IEEE80211_LINKED){
433 priv->ieee80211->scanning = 0;
434 ieee80211_softmac_scan_syncro(priv->ieee80211);
435 ret = 0;
436 }
437 else
438#endif
439 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
440
441 up(&priv->wx_sem);
442 return ret;
443}
444
445
446static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
447 union iwreq_data *wrqu, char *b)
448{
449
450 int ret;
451 struct r8192_priv *priv = ieee80211_priv(dev);
452
f500e256 453 if (priv->bHwRadioOff)
65a43784 454 return 0;
455
ecdfa446
GKH
456 if(!priv->up) return -ENETDOWN;
457
458 down(&priv->wx_sem);
459
460 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
461
462 up(&priv->wx_sem);
463
464 return ret;
465}
466
467static int r8192_wx_set_essid(struct net_device *dev,
468 struct iw_request_info *a,
469 union iwreq_data *wrqu, char *b)
470{
471 struct r8192_priv *priv = ieee80211_priv(dev);
472 RT_RF_POWER_STATE rtState;
473 int ret;
474
f500e256 475 if (priv->bHwRadioOff)
65a43784 476 return 0;
477
ecdfa446
GKH
478 rtState = priv->ieee80211->eRFPowerState;
479 down(&priv->wx_sem);
65a43784 480
ecdfa446 481#ifdef ENABLE_IPS
65a43784 482 down(&priv->ieee80211->ips_sem);
483 IPSLeave(dev);
484 up(&priv->ieee80211->ips_sem);
ecdfa446
GKH
485#endif
486 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
487
488 up(&priv->wx_sem);
489
490 return ret;
491}
492
493
494
495
496static int r8192_wx_get_essid(struct net_device *dev,
497 struct iw_request_info *a,
498 union iwreq_data *wrqu, char *b)
499{
500 int ret;
501 struct r8192_priv *priv = ieee80211_priv(dev);
502
503 down(&priv->wx_sem);
504
505 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
506
507 up(&priv->wx_sem);
508
509 return ret;
510}
511
512
513static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
514 union iwreq_data *wrqu, char *b)
515{
516 int ret;
517 struct r8192_priv *priv = ieee80211_priv(dev);
518
f500e256 519 if (priv->bHwRadioOff)
65a43784 520 return 0;
521
ecdfa446
GKH
522 down(&priv->wx_sem);
523
524 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
525
526 up(&priv->wx_sem);
527 return ret;
528}
529
530static int r8192_wx_get_name(struct net_device *dev,
531 struct iw_request_info *info,
532 union iwreq_data *wrqu, char *extra)
533{
534 struct r8192_priv *priv = ieee80211_priv(dev);
535 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
536}
537
538
539static int r8192_wx_set_frag(struct net_device *dev,
540 struct iw_request_info *info,
541 union iwreq_data *wrqu, char *extra)
542{
543 struct r8192_priv *priv = ieee80211_priv(dev);
544
f500e256 545 if (priv->bHwRadioOff)
65a43784 546 return 0;
547
ecdfa446
GKH
548 if (wrqu->frag.disabled)
549 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
550 else {
551 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
552 wrqu->frag.value > MAX_FRAG_THRESHOLD)
553 return -EINVAL;
554
555 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
556 }
557
558 return 0;
559}
560
561
562static int r8192_wx_get_frag(struct net_device *dev,
563 struct iw_request_info *info,
564 union iwreq_data *wrqu, char *extra)
565{
566 struct r8192_priv *priv = ieee80211_priv(dev);
567
568 wrqu->frag.value = priv->ieee80211->fts;
569 wrqu->frag.fixed = 0; /* no auto select */
570 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
571
572 return 0;
573}
574
575
576static int r8192_wx_set_wap(struct net_device *dev,
577 struct iw_request_info *info,
578 union iwreq_data *awrq,
579 char *extra)
580{
581
582 int ret;
583 struct r8192_priv *priv = ieee80211_priv(dev);
584// struct sockaddr *temp = (struct sockaddr *)awrq;
585
f500e256 586 if (priv->bHwRadioOff)
65a43784 587 return 0;
588
ecdfa446
GKH
589 down(&priv->wx_sem);
590
65a43784 591#ifdef ENABLE_IPS
592 down(&priv->ieee80211->ips_sem);
593 IPSLeave(dev);
594 up(&priv->ieee80211->ips_sem);
595#endif
ecdfa446
GKH
596 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
597
598 up(&priv->wx_sem);
599
600 return ret;
601
602}
603
604
605static int r8192_wx_get_wap(struct net_device *dev,
606 struct iw_request_info *info,
607 union iwreq_data *wrqu, char *extra)
608{
609 struct r8192_priv *priv = ieee80211_priv(dev);
610
611 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
612}
613
614
615static int r8192_wx_get_enc(struct net_device *dev,
616 struct iw_request_info *info,
617 union iwreq_data *wrqu, char *key)
618{
619 struct r8192_priv *priv = ieee80211_priv(dev);
620
621 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
622}
623
624static int r8192_wx_set_enc(struct net_device *dev,
625 struct iw_request_info *info,
626 union iwreq_data *wrqu, char *key)
627{
628 struct r8192_priv *priv = ieee80211_priv(dev);
629 int ret;
630
631 struct ieee80211_device *ieee = priv->ieee80211;
632 //u32 TargetContent;
633 u32 hwkey[4]={0,0,0,0};
634 u8 mask=0xff;
635 u32 key_idx=0;
65a43784 636 u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
ecdfa446
GKH
637 {0x00,0x00,0x00,0x00,0x00,0x01},
638 {0x00,0x00,0x00,0x00,0x00,0x02},
639 {0x00,0x00,0x00,0x00,0x00,0x03} };
640 int i;
641
f500e256 642 if (priv->bHwRadioOff)
65a43784 643 return 0;
644
ecdfa446
GKH
645 if(!priv->up) return -ENETDOWN;
646
65a43784 647 priv->ieee80211->wx_set_enc = 1;
648#ifdef ENABLE_IPS
649 down(&priv->ieee80211->ips_sem);
650 IPSLeave(dev);
651 up(&priv->ieee80211->ips_sem);
652#endif
653
ecdfa446
GKH
654 down(&priv->wx_sem);
655
656 RT_TRACE(COMP_SEC, "Setting SW wep key");
657 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
658
659 up(&priv->wx_sem);
660
ecdfa446
GKH
661 //sometimes, the length is zero while we do not type key value
662 if(wrqu->encoding.length!=0){
663
664 for(i=0 ; i<4 ; i++){
665 hwkey[i] |= key[4*i+0]&mask;
666 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
667 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
668 hwkey[i] |= (key[4*i+1]&mask)<<8;
669 hwkey[i] |= (key[4*i+2]&mask)<<16;
670 hwkey[i] |= (key[4*i+3]&mask)<<24;
671 }
672
673 #define CONF_WEP40 0x4
674 #define CONF_WEP104 0x14
675
676 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
677 case 0: key_idx = ieee->tx_keyidx; break;
678 case 1: key_idx = 0; break;
679 case 2: key_idx = 1; break;
680 case 3: key_idx = 2; break;
681 case 4: key_idx = 3; break;
682 default: break;
683 }
684
685 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
686 if(wrqu->encoding.length==0x5){
687 ieee->pairwise_key_type = KEY_TYPE_WEP40;
688 EnableHWSecurityConfig8192(dev);
689 setKey( dev,
690 key_idx, //EntryNo
691 key_idx, //KeyIndex
692 KEY_TYPE_WEP40, //KeyType
693 zero_addr[key_idx],
694 0, //DefaultKey
695 hwkey); //KeyContent
696
697#if 0
698 if(key_idx == 0){
699
700 //write_nic_byte(dev, SECR, 7);
701 setKey( dev,
702 4, //EntryNo
703 key_idx, //KeyIndex
704 KEY_TYPE_WEP40, //KeyType
705 broadcast_addr, //addr
706 0, //DefaultKey
707 hwkey); //KeyContent
708 }
709#endif
710 }
711
712 else if(wrqu->encoding.length==0xd){
713 ieee->pairwise_key_type = KEY_TYPE_WEP104;
714 EnableHWSecurityConfig8192(dev);
715 setKey( dev,
716 key_idx, //EntryNo
717 key_idx, //KeyIndex
718 KEY_TYPE_WEP104, //KeyType
719 zero_addr[key_idx],
720 0, //DefaultKey
721 hwkey); //KeyContent
722#if 0
723 if(key_idx == 0){
724
725 //write_nic_byte(dev, SECR, 7);
726 setKey( dev,
727 4, //EntryNo
728 key_idx, //KeyIndex
729 KEY_TYPE_WEP104, //KeyType
730 broadcast_addr, //addr
731 0, //DefaultKey
732 hwkey); //KeyContent
733 }
734#endif
735 }
736 else printk("wrong type in WEP, not WEP40 and WEP104\n");
737
738
739 }
740
741#if 0
742 //consider the setting different key index situation
743 //wrqu->encoding.flags = 801 means that we set key with index "1"
744 if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
745 printk("===>1\n");
746 //write_nic_byte(dev, SECR, 7);
747 EnableHWSecurityConfig8192(dev);
748 //copy wpa config from default key(key0~key3) to broadcast key(key5)
749 //
750 key_idx = (wrqu->encoding.flags & 0xf)-1 ;
751 write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) );
752 write_cam(dev, (4*6)+1, 0xffffffff);
753 write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
754 write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
755 write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
756 write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
757 }
758#endif
759
65a43784 760 priv->ieee80211->wx_set_enc = 0;
761
ecdfa446
GKH
762 return ret;
763}
764
765
766static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
767 iwreq_data *wrqu, char *p){
768
769 struct r8192_priv *priv = ieee80211_priv(dev);
770 int *parms=(int*)p;
771 int mode=parms[0];
772
773 priv->ieee80211->active_scan = mode;
774
775 return 1;
776}
777
778
779
780static int r8192_wx_set_retry(struct net_device *dev,
781 struct iw_request_info *info,
782 union iwreq_data *wrqu, char *extra)
783{
784 struct r8192_priv *priv = ieee80211_priv(dev);
785 int err = 0;
786
f500e256 787 if (priv->bHwRadioOff)
65a43784 788 return 0;
789
ecdfa446
GKH
790 down(&priv->wx_sem);
791
792 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
793 wrqu->retry.disabled){
794 err = -EINVAL;
795 goto exit;
796 }
797 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
798 err = -EINVAL;
799 goto exit;
800 }
801
802 if(wrqu->retry.value > R8180_MAX_RETRY){
803 err= -EINVAL;
804 goto exit;
805 }
806 if (wrqu->retry.flags & IW_RETRY_MAX) {
807 priv->retry_rts = wrqu->retry.value;
808 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
809
810 }else {
811 priv->retry_data = wrqu->retry.value;
812 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
813 }
814
815 /* FIXME !
816 * We might try to write directly the TX config register
817 * or to restart just the (R)TX process.
818 * I'm unsure if whole reset is really needed
819 */
820
821 rtl8192_commit(dev);
822 /*
823 if(priv->up){
824 rtl8180_rtx_disable(dev);
825 rtl8180_rx_enable(dev);
826 rtl8180_tx_enable(dev);
827
828 }
829 */
830exit:
831 up(&priv->wx_sem);
832
833 return err;
834}
835
836static int r8192_wx_get_retry(struct net_device *dev,
837 struct iw_request_info *info,
838 union iwreq_data *wrqu, char *extra)
839{
840 struct r8192_priv *priv = ieee80211_priv(dev);
841
842
843 wrqu->retry.disabled = 0; /* can't be disabled */
844
845 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
846 IW_RETRY_LIFETIME)
847 return -EINVAL;
848
849 if (wrqu->retry.flags & IW_RETRY_MAX) {
850 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
851 wrqu->retry.value = priv->retry_rts;
852 } else {
853 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
854 wrqu->retry.value = priv->retry_data;
855 }
856 //DMESG("returning %d",wrqu->retry.value);
857
858
859 return 0;
860}
861
862static int r8192_wx_get_sens(struct net_device *dev,
863 struct iw_request_info *info,
864 union iwreq_data *wrqu, char *extra)
865{
866 struct r8192_priv *priv = ieee80211_priv(dev);
867 if(priv->rf_set_sens == NULL)
868 return -1; /* we have not this support for this radio */
869 wrqu->sens.value = priv->sens;
870 return 0;
871}
872
873
874static int r8192_wx_set_sens(struct net_device *dev,
875 struct iw_request_info *info,
876 union iwreq_data *wrqu, char *extra)
877{
878
879 struct r8192_priv *priv = ieee80211_priv(dev);
880
881 short err = 0;
65a43784 882
f500e256 883 if (priv->bHwRadioOff)
65a43784 884 return 0;
885
ecdfa446
GKH
886 down(&priv->wx_sem);
887 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
888 if(priv->rf_set_sens == NULL) {
889 err= -1; /* we have not this support for this radio */
890 goto exit;
891 }
892 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
893 priv->sens = wrqu->sens.value;
894 else
895 err= -EINVAL;
896
897exit:
898 up(&priv->wx_sem);
899
900 return err;
901}
902
ecdfa446
GKH
903static int r8192_wx_set_enc_ext(struct net_device *dev,
904 struct iw_request_info *info,
905 union iwreq_data *wrqu, char *extra)
906{
907 int ret=0;
ecdfa446
GKH
908 struct r8192_priv *priv = ieee80211_priv(dev);
909 struct ieee80211_device* ieee = priv->ieee80211;
910
f500e256 911 if (priv->bHwRadioOff)
65a43784 912 return 0;
913
ecdfa446 914 down(&priv->wx_sem);
65a43784 915
916 priv->ieee80211->wx_set_enc = 1;
917
918#ifdef ENABLE_IPS
919 down(&priv->ieee80211->ips_sem);
920 IPSLeave(dev);
921 up(&priv->ieee80211->ips_sem);
922#endif
923
ecdfa446
GKH
924 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
925
926 {
927 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
928 u8 zero[6] = {0};
929 u32 key[4] = {0};
930 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
931 struct iw_point *encoding = &wrqu->encoding;
932#if 0
933 static u8 CAM_CONST_ADDR[4][6] = {
934 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
935 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
936 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
937 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
938#endif
939 u8 idx = 0, alg = 0, group = 0;
940 if ((encoding->flags & IW_ENCODE_DISABLED) ||
941 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
942 {
943 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
944 CamResetAllEntry(dev);
945 goto end_hw_sec;
946 }
947 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4;
948 idx = encoding->flags & IW_ENCODE_INDEX;
949 if (idx)
950 idx --;
951 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
952
953 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
954 {
955 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
956 alg = KEY_TYPE_WEP104;
957 ieee->pairwise_key_type = alg;
958 EnableHWSecurityConfig8192(dev);
959 }
960 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
961
962 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
963 {
964 if (ext->key_len == 13)
965 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
966 setKey( dev,
967 idx,//EntryNo
968 idx, //KeyIndex
969 alg, //KeyType
970 zero, //MacAddr
971 0, //DefaultKey
972 key); //KeyContent
973 }
974 else if (group)
975 {
976 ieee->group_key_type = alg;
977 setKey( dev,
978 idx,//EntryNo
979 idx, //KeyIndex
980 alg, //KeyType
981 broadcast_addr, //MacAddr
982 0, //DefaultKey
983 key); //KeyContent
984 }
985 else //pairwise key
986 {
987 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
988 write_nic_byte(dev, 0x173, 1); //fix aes bug
989 }
990 setKey( dev,
991 4,//EntryNo
992 idx, //KeyIndex
993 alg, //KeyType
994 (u8*)ieee->ap_mac_addr, //MacAddr
995 0, //DefaultKey
996 key); //KeyContent
997 }
998
999
1000 }
1001
1002end_hw_sec:
65a43784 1003 priv->ieee80211->wx_set_enc = 0;
ecdfa446 1004 up(&priv->wx_sem);
ecdfa446
GKH
1005 return ret;
1006
1007}
1008static int r8192_wx_set_auth(struct net_device *dev,
1009 struct iw_request_info *info,
1010 union iwreq_data *data, char *extra)
1011{
1012 int ret=0;
ecdfa446
GKH
1013 //printk("====>%s()\n", __FUNCTION__);
1014 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1015
f500e256 1016 if (priv->bHwRadioOff)
65a43784 1017 return 0;
1018
ecdfa446
GKH
1019 down(&priv->wx_sem);
1020 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
1021 up(&priv->wx_sem);
ecdfa446
GKH
1022 return ret;
1023}
1024
1025static int r8192_wx_set_mlme(struct net_device *dev,
1026 struct iw_request_info *info,
1027 union iwreq_data *wrqu, char *extra)
1028{
1029 //printk("====>%s()\n", __FUNCTION__);
1030
1031 int ret=0;
ecdfa446 1032 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1033
f500e256 1034 if (priv->bHwRadioOff)
65a43784 1035 return 0;
1036
ecdfa446
GKH
1037 down(&priv->wx_sem);
1038 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1039 up(&priv->wx_sem);
ecdfa446
GKH
1040 return ret;
1041}
890a6850 1042
ecdfa446
GKH
1043static int r8192_wx_set_gen_ie(struct net_device *dev,
1044 struct iw_request_info *info,
1045 union iwreq_data *data, char *extra)
1046{
1047 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1048 int ret=0;
ecdfa446 1049 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1050
f500e256 1051 if (priv->bHwRadioOff)
65a43784 1052 return 0;
1053
ecdfa446 1054 down(&priv->wx_sem);
ecdfa446 1055 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
ecdfa446
GKH
1056 up(&priv->wx_sem);
1057 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
ecdfa446 1058 return ret;
ecdfa446
GKH
1059}
1060
1061static int dummy(struct net_device *dev, struct iw_request_info *a,
1062 union iwreq_data *wrqu,char *b)
1063{
1064 return -1;
1065}
1066
65a43784 1067// check ac/dc status with the help of user space application */
1068static int r8192_wx_adapter_power_status(struct net_device *dev,
1069 struct iw_request_info *info,
1070 union iwreq_data *wrqu, char *extra)
1071{
1072 struct r8192_priv *priv = ieee80211_priv(dev);
1073#ifdef ENABLE_LPS
1074 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
1075 struct ieee80211_device* ieee = priv->ieee80211;
1076#endif
1077 down(&priv->wx_sem);
1078
1079#ifdef ENABLE_LPS
1080 RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power");
1081 // ieee->ps shall not be set under DC mode, otherwise it conflict
1082 // with Leisure power save mode setting.
1083 //
1084 if(*extra || priv->force_lps) {
1085 priv->ps_force = false;
1086 pPSC->bLeisurePs = true;
1087 } else {
1088 //LZM for PS-Poll AID issue. 090429
1089 if(priv->ieee80211->state == IEEE80211_LINKED)
1090 LeisurePSLeave(dev);
1091
1092 priv->ps_force = true;
1093 pPSC->bLeisurePs = false;
1094 ieee->ps = *extra;
1095 }
1096
1097#endif
1098 up(&priv->wx_sem);
1099 return 0;
1100
1101}
1102
ecdfa446
GKH
1103
1104static iw_handler r8192_wx_handlers[] =
1105{
1106 NULL, /* SIOCSIWCOMMIT */
1107 r8192_wx_get_name, /* SIOCGIWNAME */
1108 dummy, /* SIOCSIWNWID */
1109 dummy, /* SIOCGIWNWID */
1110 r8192_wx_set_freq, /* SIOCSIWFREQ */
1111 r8192_wx_get_freq, /* SIOCGIWFREQ */
1112 r8192_wx_set_mode, /* SIOCSIWMODE */
1113 r8192_wx_get_mode, /* SIOCGIWMODE */
1114 r8192_wx_set_sens, /* SIOCSIWSENS */
1115 r8192_wx_get_sens, /* SIOCGIWSENS */
1116 NULL, /* SIOCSIWRANGE */
1117 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1118 NULL, /* SIOCSIWPRIV */
1119 NULL, /* SIOCGIWPRIV */
1120 NULL, /* SIOCSIWSTATS */
1121 NULL, /* SIOCGIWSTATS */
1122 dummy, /* SIOCSIWSPY */
1123 dummy, /* SIOCGIWSPY */
1124 NULL, /* SIOCGIWTHRSPY */
1125 NULL, /* SIOCWIWTHRSPY */
1126 r8192_wx_set_wap, /* SIOCSIWAP */
1127 r8192_wx_get_wap, /* SIOCGIWAP */
890a6850 1128 r8192_wx_set_mlme, /* MLME-- */
ecdfa446
GKH
1129 dummy, /* SIOCGIWAPLIST -- depricated */
1130 r8192_wx_set_scan, /* SIOCSIWSCAN */
1131 r8192_wx_get_scan, /* SIOCGIWSCAN */
1132 r8192_wx_set_essid, /* SIOCSIWESSID */
1133 r8192_wx_get_essid, /* SIOCGIWESSID */
1134 dummy, /* SIOCSIWNICKN */
1135 dummy, /* SIOCGIWNICKN */
1136 NULL, /* -- hole -- */
1137 NULL, /* -- hole -- */
1138 r8192_wx_set_rate, /* SIOCSIWRATE */
1139 r8192_wx_get_rate, /* SIOCGIWRATE */
1140 r8192_wx_set_rts, /* SIOCSIWRTS */
1141 r8192_wx_get_rts, /* SIOCGIWRTS */
1142 r8192_wx_set_frag, /* SIOCSIWFRAG */
1143 r8192_wx_get_frag, /* SIOCGIWFRAG */
1144 dummy, /* SIOCSIWTXPOW */
1145 dummy, /* SIOCGIWTXPOW */
1146 r8192_wx_set_retry, /* SIOCSIWRETRY */
1147 r8192_wx_get_retry, /* SIOCGIWRETRY */
1148 r8192_wx_set_enc, /* SIOCSIWENCODE */
1149 r8192_wx_get_enc, /* SIOCGIWENCODE */
1150 r8192_wx_set_power, /* SIOCSIWPOWER */
1151 r8192_wx_get_power, /* SIOCGIWPOWER */
1152 NULL, /*---hole---*/
1153 NULL, /*---hole---*/
1154 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1155 NULL, /* SIOCSIWGENIE */
ecdfa446
GKH
1156 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1157 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1158 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
ecdfa446
GKH
1159 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1160 NULL, /* SIOCSIWPMKSA */
1161 NULL, /*---hole---*/
1162
1163};
1164
1165
1166static const struct iw_priv_args r8192_private_args[] = {
1167
1168 {
1169 SIOCIWFIRSTPRIV + 0x0,
1170 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1171 },
1172
1173 {
1174 SIOCIWFIRSTPRIV + 0x1,
1175 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1176
1177 },
1178 {
1179 SIOCIWFIRSTPRIV + 0x2,
1180 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1181 }
ecdfa446
GKH
1182 ,
1183 {
1184 SIOCIWFIRSTPRIV + 0x3,
65a43784 1185 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1186
ecdfa446
GKH
1187 }
1188 ,
1189 {
1190 SIOCIWFIRSTPRIV + 0x4,
65a43784 1191 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1192 "set_power"
ecdfa446
GKH
1193 }
1194
1195};
1196
1197
1198static iw_handler r8192_private_handler[] = {
ecdfa446 1199 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
ecdfa446
GKH
1200 r8192_wx_set_scan_type,
1201 r8192_wx_set_rawtx,
ecdfa446 1202 r8192_wx_force_reset,
65a43784 1203 r8192_wx_adapter_power_status,
ecdfa446
GKH
1204};
1205
ecdfa446
GKH
1206struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1207{
1208 struct r8192_priv *priv = ieee80211_priv(dev);
1209 struct ieee80211_device* ieee = priv->ieee80211;
1210 struct iw_statistics* wstats = &priv->wstats;
1211 int tmp_level = 0;
1212 int tmp_qual = 0;
1213 int tmp_noise = 0;
1214 if(ieee->state < IEEE80211_LINKED)
1215 {
1216 wstats->qual.qual = 0;
1217 wstats->qual.level = 0;
1218 wstats->qual.noise = 0;
ecdfa446 1219 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
ecdfa446
GKH
1220 return wstats;
1221 }
1222
1223 tmp_level = (&ieee->current_network)->stats.rssi;
1224 tmp_qual = (&ieee->current_network)->stats.signal;
1225 tmp_noise = (&ieee->current_network)->stats.noise;
1226 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1227
1228 wstats->qual.level = tmp_level;
1229 wstats->qual.qual = tmp_qual;
1230 wstats->qual.noise = tmp_noise;
ecdfa446 1231 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
ecdfa446
GKH
1232 return wstats;
1233}
ecdfa446
GKH
1234
1235
1236struct iw_handler_def r8192_wx_handlers_def={
1237 .standard = r8192_wx_handlers,
1238 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1239 .private = r8192_private_handler,
1240 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1241 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
ecdfa446 1242 .get_wireless_stats = r8192_get_wireless_stats,
ecdfa446
GKH
1243 .private_args = (struct iw_priv_args *)r8192_private_args,
1244};
This page took 0.290014 seconds and 5 git commands to generate.