Merge branch 'for-linus' of git://android.kernel.org/kernel/tegra
[GitHub/mt8127/android_kernel_alcatel_ttab.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
65a43784 73 if(priv->bHwRadioOff == true)
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
65a43784 93 if(priv->bHwRadioOff == true)
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
65a43784 120 if(priv->bHwRadioOff == true)
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
65a43784 147 if(priv->bHwRadioOff == true)
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
65a43784 185 if(priv->bHwRadioOff == true)
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
65a43784 215 if(priv->bHwRadioOff == true)
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 */
304 if(priv->rf_set_sens != NULL)
305 range->sensitivity = priv->max_sens; /* signal level threshold range */
306
307 range->max_qual.qual = 100;
308 /* TODO: Find real max RSSI and stick here */
309 range->max_qual.level = 0;
310 range->max_qual.noise = -98;
311 range->max_qual.updated = 7; /* Updated all three */
312
313 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
bbc9a991 314 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
ecdfa446
GKH
315 range->avg_qual.level = 20 + -98;
316 range->avg_qual.noise = 0;
317 range->avg_qual.updated = 7; /* Updated all three */
318
319 range->num_bitrates = RATE_COUNT;
320
321 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
322 range->bitrate[i] = rtl8180_rates[i];
323 }
324
325 range->min_frag = MIN_FRAG_THRESHOLD;
326 range->max_frag = MAX_FRAG_THRESHOLD;
327
328 range->min_pmp=0;
329 range->max_pmp = 5000000;
330 range->min_pmt = 0;
331 range->max_pmt = 65535*1000;
332 range->pmp_flags = IW_POWER_PERIOD;
333 range->pmt_flags = IW_POWER_TIMEOUT;
334 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
335 range->we_version_compiled = WIRELESS_EXT;
65a43784 336 range->we_version_source = 18;
ecdfa446
GKH
337
338// range->retry_capa; /* What retry options are supported */
339// range->retry_flags; /* How to decode max/min retry limit */
340// range->r_time_flags; /* How to decode max/min retry life */
341// range->min_retry; /* Minimal number of retries */
342// range->max_retry; /* Maximal number of retries */
343// range->min_r_time; /* Minimal retry lifetime */
344// range->max_r_time; /* Maximal retry lifetime */
345
346
347 for (i = 0, val = 0; i < 14; i++) {
348
349 // Include only legal frequencies for some countries
350#ifdef ENABLE_DOT11D
351 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
352#else
353 if ((priv->ieee80211->channel_map)[i+1]) {
354#endif
355 range->freq[val].i = i + 1;
356 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
357 range->freq[val].e = 1;
358 val++;
359 } else {
360 // FIXME: do we need to set anything for channels
361 // we don't use ?
362 }
363
364 if (val == IW_MAX_FREQUENCIES)
365 break;
366 }
367 range->num_frequency = val;
368 range->num_channels = val;
369#if WIRELESS_EXT > 17
370 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
371 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
372#endif
373 tmp->scan_capa = 0x01;
374 return 0;
375}
376
377
378static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
379 union iwreq_data *wrqu, char *b)
380{
381 struct r8192_priv *priv = ieee80211_priv(dev);
382 struct ieee80211_device* ieee = priv->ieee80211;
383 RT_RF_POWER_STATE rtState;
384 int ret;
65a43784 385
386 if(priv->bHwRadioOff == true)
387 return 0;
388
ecdfa446 389 rtState = priv->ieee80211->eRFPowerState;
65a43784 390
ecdfa446
GKH
391 if(!priv->up) return -ENETDOWN;
392 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
393 return -EAGAIN;
394
395 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
396 {
397 struct iw_scan_req* req = (struct iw_scan_req*)b;
398 if (req->essid_len)
399 {
400 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
401 ieee->current_network.ssid_len = req->essid_len;
402 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
403 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
404 }
405 }
406
407 down(&priv->wx_sem);
408#ifdef ENABLE_IPS
409 priv->ieee80211->actscanning = true;
410 if(priv->ieee80211->state != IEEE80211_LINKED){
411 if(priv->ieee80211->PowerSaveControl.bInactivePs){
412 if(rtState == eRfOff){
413 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
414 {
415 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
416 up(&priv->wx_sem);
417 return -1;
418 }
419 else{
65a43784 420 //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
421 down(&priv->ieee80211->ips_sem);
ecdfa446 422 IPSLeave(dev);
65a43784 423 up(&priv->ieee80211->ips_sem);
ecdfa446
GKH
424 }
425 }
426 }
427 priv->ieee80211->scanning = 0;
428 ieee80211_softmac_scan_syncro(priv->ieee80211);
429 ret = 0;
430 }
431 else
432#else
433
434 if(priv->ieee80211->state != IEEE80211_LINKED){
435 priv->ieee80211->scanning = 0;
436 ieee80211_softmac_scan_syncro(priv->ieee80211);
437 ret = 0;
438 }
439 else
440#endif
441 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
442
443 up(&priv->wx_sem);
444 return ret;
445}
446
447
448static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
449 union iwreq_data *wrqu, char *b)
450{
451
452 int ret;
453 struct r8192_priv *priv = ieee80211_priv(dev);
454
65a43784 455 if(priv->bHwRadioOff == true)
456 return 0;
457
ecdfa446
GKH
458 if(!priv->up) return -ENETDOWN;
459
460 down(&priv->wx_sem);
461
462 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
463
464 up(&priv->wx_sem);
465
466 return ret;
467}
468
469static int r8192_wx_set_essid(struct net_device *dev,
470 struct iw_request_info *a,
471 union iwreq_data *wrqu, char *b)
472{
473 struct r8192_priv *priv = ieee80211_priv(dev);
474 RT_RF_POWER_STATE rtState;
475 int ret;
476
65a43784 477 if(priv->bHwRadioOff == true)
478 return 0;
479
ecdfa446
GKH
480 rtState = priv->ieee80211->eRFPowerState;
481 down(&priv->wx_sem);
65a43784 482
ecdfa446 483#ifdef ENABLE_IPS
65a43784 484 down(&priv->ieee80211->ips_sem);
485 IPSLeave(dev);
486 up(&priv->ieee80211->ips_sem);
ecdfa446
GKH
487#endif
488 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
489
490 up(&priv->wx_sem);
491
492 return ret;
493}
494
495
496
497
498static int r8192_wx_get_essid(struct net_device *dev,
499 struct iw_request_info *a,
500 union iwreq_data *wrqu, char *b)
501{
502 int ret;
503 struct r8192_priv *priv = ieee80211_priv(dev);
504
505 down(&priv->wx_sem);
506
507 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
508
509 up(&priv->wx_sem);
510
511 return ret;
512}
513
514
515static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
516 union iwreq_data *wrqu, char *b)
517{
518 int ret;
519 struct r8192_priv *priv = ieee80211_priv(dev);
520
65a43784 521 if(priv->bHwRadioOff == true)
522 return 0;
523
ecdfa446
GKH
524 down(&priv->wx_sem);
525
526 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
527
528 up(&priv->wx_sem);
529 return ret;
530}
531
532static int r8192_wx_get_name(struct net_device *dev,
533 struct iw_request_info *info,
534 union iwreq_data *wrqu, char *extra)
535{
536 struct r8192_priv *priv = ieee80211_priv(dev);
537 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
538}
539
540
541static int r8192_wx_set_frag(struct net_device *dev,
542 struct iw_request_info *info,
543 union iwreq_data *wrqu, char *extra)
544{
545 struct r8192_priv *priv = ieee80211_priv(dev);
546
65a43784 547 if(priv->bHwRadioOff == true)
548 return 0;
549
ecdfa446
GKH
550 if (wrqu->frag.disabled)
551 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
552 else {
553 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
554 wrqu->frag.value > MAX_FRAG_THRESHOLD)
555 return -EINVAL;
556
557 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
558 }
559
560 return 0;
561}
562
563
564static int r8192_wx_get_frag(struct net_device *dev,
565 struct iw_request_info *info,
566 union iwreq_data *wrqu, char *extra)
567{
568 struct r8192_priv *priv = ieee80211_priv(dev);
569
570 wrqu->frag.value = priv->ieee80211->fts;
571 wrqu->frag.fixed = 0; /* no auto select */
572 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
573
574 return 0;
575}
576
577
578static int r8192_wx_set_wap(struct net_device *dev,
579 struct iw_request_info *info,
580 union iwreq_data *awrq,
581 char *extra)
582{
583
584 int ret;
585 struct r8192_priv *priv = ieee80211_priv(dev);
586// struct sockaddr *temp = (struct sockaddr *)awrq;
587
65a43784 588 if(priv->bHwRadioOff == true)
589 return 0;
590
ecdfa446
GKH
591 down(&priv->wx_sem);
592
65a43784 593#ifdef ENABLE_IPS
594 down(&priv->ieee80211->ips_sem);
595 IPSLeave(dev);
596 up(&priv->ieee80211->ips_sem);
597#endif
ecdfa446
GKH
598 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
599
600 up(&priv->wx_sem);
601
602 return ret;
603
604}
605
606
607static int r8192_wx_get_wap(struct net_device *dev,
608 struct iw_request_info *info,
609 union iwreq_data *wrqu, char *extra)
610{
611 struct r8192_priv *priv = ieee80211_priv(dev);
612
613 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
614}
615
616
617static int r8192_wx_get_enc(struct net_device *dev,
618 struct iw_request_info *info,
619 union iwreq_data *wrqu, char *key)
620{
621 struct r8192_priv *priv = ieee80211_priv(dev);
622
623 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
624}
625
626static int r8192_wx_set_enc(struct net_device *dev,
627 struct iw_request_info *info,
628 union iwreq_data *wrqu, char *key)
629{
630 struct r8192_priv *priv = ieee80211_priv(dev);
631 int ret;
632
633 struct ieee80211_device *ieee = priv->ieee80211;
634 //u32 TargetContent;
635 u32 hwkey[4]={0,0,0,0};
636 u8 mask=0xff;
637 u32 key_idx=0;
65a43784 638 u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
ecdfa446
GKH
639 {0x00,0x00,0x00,0x00,0x00,0x01},
640 {0x00,0x00,0x00,0x00,0x00,0x02},
641 {0x00,0x00,0x00,0x00,0x00,0x03} };
642 int i;
643
65a43784 644 if(priv->bHwRadioOff == true)
645 return 0;
646
ecdfa446
GKH
647 if(!priv->up) return -ENETDOWN;
648
65a43784 649 priv->ieee80211->wx_set_enc = 1;
650#ifdef ENABLE_IPS
651 down(&priv->ieee80211->ips_sem);
652 IPSLeave(dev);
653 up(&priv->ieee80211->ips_sem);
654#endif
655
ecdfa446
GKH
656 down(&priv->wx_sem);
657
658 RT_TRACE(COMP_SEC, "Setting SW wep key");
659 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
660
661 up(&priv->wx_sem);
662
ecdfa446
GKH
663 //sometimes, the length is zero while we do not type key value
664 if(wrqu->encoding.length!=0){
665
666 for(i=0 ; i<4 ; i++){
667 hwkey[i] |= key[4*i+0]&mask;
668 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
669 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
670 hwkey[i] |= (key[4*i+1]&mask)<<8;
671 hwkey[i] |= (key[4*i+2]&mask)<<16;
672 hwkey[i] |= (key[4*i+3]&mask)<<24;
673 }
674
675 #define CONF_WEP40 0x4
676 #define CONF_WEP104 0x14
677
678 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
679 case 0: key_idx = ieee->tx_keyidx; break;
680 case 1: key_idx = 0; break;
681 case 2: key_idx = 1; break;
682 case 3: key_idx = 2; break;
683 case 4: key_idx = 3; break;
684 default: break;
685 }
686
687 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
688 if(wrqu->encoding.length==0x5){
689 ieee->pairwise_key_type = KEY_TYPE_WEP40;
690 EnableHWSecurityConfig8192(dev);
691 setKey( dev,
692 key_idx, //EntryNo
693 key_idx, //KeyIndex
694 KEY_TYPE_WEP40, //KeyType
695 zero_addr[key_idx],
696 0, //DefaultKey
697 hwkey); //KeyContent
698
699#if 0
700 if(key_idx == 0){
701
702 //write_nic_byte(dev, SECR, 7);
703 setKey( dev,
704 4, //EntryNo
705 key_idx, //KeyIndex
706 KEY_TYPE_WEP40, //KeyType
707 broadcast_addr, //addr
708 0, //DefaultKey
709 hwkey); //KeyContent
710 }
711#endif
712 }
713
714 else if(wrqu->encoding.length==0xd){
715 ieee->pairwise_key_type = KEY_TYPE_WEP104;
716 EnableHWSecurityConfig8192(dev);
717 setKey( dev,
718 key_idx, //EntryNo
719 key_idx, //KeyIndex
720 KEY_TYPE_WEP104, //KeyType
721 zero_addr[key_idx],
722 0, //DefaultKey
723 hwkey); //KeyContent
724#if 0
725 if(key_idx == 0){
726
727 //write_nic_byte(dev, SECR, 7);
728 setKey( dev,
729 4, //EntryNo
730 key_idx, //KeyIndex
731 KEY_TYPE_WEP104, //KeyType
732 broadcast_addr, //addr
733 0, //DefaultKey
734 hwkey); //KeyContent
735 }
736#endif
737 }
738 else printk("wrong type in WEP, not WEP40 and WEP104\n");
739
740
741 }
742
743#if 0
744 //consider the setting different key index situation
745 //wrqu->encoding.flags = 801 means that we set key with index "1"
746 if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
747 printk("===>1\n");
748 //write_nic_byte(dev, SECR, 7);
749 EnableHWSecurityConfig8192(dev);
750 //copy wpa config from default key(key0~key3) to broadcast key(key5)
751 //
752 key_idx = (wrqu->encoding.flags & 0xf)-1 ;
753 write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) );
754 write_cam(dev, (4*6)+1, 0xffffffff);
755 write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
756 write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
757 write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
758 write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
759 }
760#endif
761
65a43784 762 priv->ieee80211->wx_set_enc = 0;
763
ecdfa446
GKH
764 return ret;
765}
766
767
768static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
769 iwreq_data *wrqu, char *p){
770
771 struct r8192_priv *priv = ieee80211_priv(dev);
772 int *parms=(int*)p;
773 int mode=parms[0];
774
775 priv->ieee80211->active_scan = mode;
776
777 return 1;
778}
779
780
781
782static int r8192_wx_set_retry(struct net_device *dev,
783 struct iw_request_info *info,
784 union iwreq_data *wrqu, char *extra)
785{
786 struct r8192_priv *priv = ieee80211_priv(dev);
787 int err = 0;
788
65a43784 789 if(priv->bHwRadioOff == true)
790 return 0;
791
ecdfa446
GKH
792 down(&priv->wx_sem);
793
794 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
795 wrqu->retry.disabled){
796 err = -EINVAL;
797 goto exit;
798 }
799 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
800 err = -EINVAL;
801 goto exit;
802 }
803
804 if(wrqu->retry.value > R8180_MAX_RETRY){
805 err= -EINVAL;
806 goto exit;
807 }
808 if (wrqu->retry.flags & IW_RETRY_MAX) {
809 priv->retry_rts = wrqu->retry.value;
810 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
811
812 }else {
813 priv->retry_data = wrqu->retry.value;
814 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
815 }
816
817 /* FIXME !
818 * We might try to write directly the TX config register
819 * or to restart just the (R)TX process.
820 * I'm unsure if whole reset is really needed
821 */
822
823 rtl8192_commit(dev);
824 /*
825 if(priv->up){
826 rtl8180_rtx_disable(dev);
827 rtl8180_rx_enable(dev);
828 rtl8180_tx_enable(dev);
829
830 }
831 */
832exit:
833 up(&priv->wx_sem);
834
835 return err;
836}
837
838static int r8192_wx_get_retry(struct net_device *dev,
839 struct iw_request_info *info,
840 union iwreq_data *wrqu, char *extra)
841{
842 struct r8192_priv *priv = ieee80211_priv(dev);
843
844
845 wrqu->retry.disabled = 0; /* can't be disabled */
846
847 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
848 IW_RETRY_LIFETIME)
849 return -EINVAL;
850
851 if (wrqu->retry.flags & IW_RETRY_MAX) {
852 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
853 wrqu->retry.value = priv->retry_rts;
854 } else {
855 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
856 wrqu->retry.value = priv->retry_data;
857 }
858 //DMESG("returning %d",wrqu->retry.value);
859
860
861 return 0;
862}
863
864static int r8192_wx_get_sens(struct net_device *dev,
865 struct iw_request_info *info,
866 union iwreq_data *wrqu, char *extra)
867{
868 struct r8192_priv *priv = ieee80211_priv(dev);
869 if(priv->rf_set_sens == NULL)
870 return -1; /* we have not this support for this radio */
871 wrqu->sens.value = priv->sens;
872 return 0;
873}
874
875
876static int r8192_wx_set_sens(struct net_device *dev,
877 struct iw_request_info *info,
878 union iwreq_data *wrqu, char *extra)
879{
880
881 struct r8192_priv *priv = ieee80211_priv(dev);
882
883 short err = 0;
65a43784 884
885 if(priv->bHwRadioOff == true)
886 return 0;
887
ecdfa446
GKH
888 down(&priv->wx_sem);
889 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
890 if(priv->rf_set_sens == NULL) {
891 err= -1; /* we have not this support for this radio */
892 goto exit;
893 }
894 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
895 priv->sens = wrqu->sens.value;
896 else
897 err= -EINVAL;
898
899exit:
900 up(&priv->wx_sem);
901
902 return err;
903}
904
905#if (WIRELESS_EXT >= 18)
ecdfa446
GKH
906static int r8192_wx_set_enc_ext(struct net_device *dev,
907 struct iw_request_info *info,
908 union iwreq_data *wrqu, char *extra)
909{
910 int ret=0;
ecdfa446
GKH
911 struct r8192_priv *priv = ieee80211_priv(dev);
912 struct ieee80211_device* ieee = priv->ieee80211;
913
65a43784 914 if(priv->bHwRadioOff == true)
915 return 0;
916
ecdfa446 917 down(&priv->wx_sem);
65a43784 918
919 priv->ieee80211->wx_set_enc = 1;
920
921#ifdef ENABLE_IPS
922 down(&priv->ieee80211->ips_sem);
923 IPSLeave(dev);
924 up(&priv->ieee80211->ips_sem);
925#endif
926
ecdfa446
GKH
927 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
928
929 {
930 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
931 u8 zero[6] = {0};
932 u32 key[4] = {0};
933 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
934 struct iw_point *encoding = &wrqu->encoding;
935#if 0
936 static u8 CAM_CONST_ADDR[4][6] = {
937 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
938 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
939 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
940 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
941#endif
942 u8 idx = 0, alg = 0, group = 0;
943 if ((encoding->flags & IW_ENCODE_DISABLED) ||
944 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
945 {
946 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
947 CamResetAllEntry(dev);
948 goto end_hw_sec;
949 }
950 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;
951 idx = encoding->flags & IW_ENCODE_INDEX;
952 if (idx)
953 idx --;
954 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
955
956 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
957 {
958 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
959 alg = KEY_TYPE_WEP104;
960 ieee->pairwise_key_type = alg;
961 EnableHWSecurityConfig8192(dev);
962 }
963 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
964
965 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
966 {
967 if (ext->key_len == 13)
968 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
969 setKey( dev,
970 idx,//EntryNo
971 idx, //KeyIndex
972 alg, //KeyType
973 zero, //MacAddr
974 0, //DefaultKey
975 key); //KeyContent
976 }
977 else if (group)
978 {
979 ieee->group_key_type = alg;
980 setKey( dev,
981 idx,//EntryNo
982 idx, //KeyIndex
983 alg, //KeyType
984 broadcast_addr, //MacAddr
985 0, //DefaultKey
986 key); //KeyContent
987 }
988 else //pairwise key
989 {
990 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
991 write_nic_byte(dev, 0x173, 1); //fix aes bug
992 }
993 setKey( dev,
994 4,//EntryNo
995 idx, //KeyIndex
996 alg, //KeyType
997 (u8*)ieee->ap_mac_addr, //MacAddr
998 0, //DefaultKey
999 key); //KeyContent
1000 }
1001
1002
1003 }
1004
1005end_hw_sec:
65a43784 1006 priv->ieee80211->wx_set_enc = 0;
ecdfa446 1007 up(&priv->wx_sem);
ecdfa446
GKH
1008 return ret;
1009
1010}
1011static int r8192_wx_set_auth(struct net_device *dev,
1012 struct iw_request_info *info,
1013 union iwreq_data *data, char *extra)
1014{
1015 int ret=0;
ecdfa446
GKH
1016 //printk("====>%s()\n", __FUNCTION__);
1017 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1018
1019 if(priv->bHwRadioOff == true)
1020 return 0;
1021
ecdfa446
GKH
1022 down(&priv->wx_sem);
1023 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
1024 up(&priv->wx_sem);
ecdfa446
GKH
1025 return ret;
1026}
1027
1028static int r8192_wx_set_mlme(struct net_device *dev,
1029 struct iw_request_info *info,
1030 union iwreq_data *wrqu, char *extra)
1031{
1032 //printk("====>%s()\n", __FUNCTION__);
1033
1034 int ret=0;
ecdfa446 1035 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1036
1037 if(priv->bHwRadioOff == true)
1038 return 0;
1039
ecdfa446
GKH
1040 down(&priv->wx_sem);
1041 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1042 up(&priv->wx_sem);
ecdfa446
GKH
1043 return ret;
1044}
1045#endif
1046static int r8192_wx_set_gen_ie(struct net_device *dev,
1047 struct iw_request_info *info,
1048 union iwreq_data *data, char *extra)
1049{
1050 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1051 int ret=0;
ecdfa446 1052 struct r8192_priv *priv = ieee80211_priv(dev);
65a43784 1053
1054 if(priv->bHwRadioOff == true)
1055 return 0;
1056
ecdfa446 1057 down(&priv->wx_sem);
ecdfa446 1058 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
ecdfa446
GKH
1059 up(&priv->wx_sem);
1060 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
ecdfa446 1061 return ret;
ecdfa446
GKH
1062}
1063
1064static int dummy(struct net_device *dev, struct iw_request_info *a,
1065 union iwreq_data *wrqu,char *b)
1066{
1067 return -1;
1068}
1069
65a43784 1070// check ac/dc status with the help of user space application */
1071static int r8192_wx_adapter_power_status(struct net_device *dev,
1072 struct iw_request_info *info,
1073 union iwreq_data *wrqu, char *extra)
1074{
1075 struct r8192_priv *priv = ieee80211_priv(dev);
1076#ifdef ENABLE_LPS
1077 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
1078 struct ieee80211_device* ieee = priv->ieee80211;
1079#endif
1080 down(&priv->wx_sem);
1081
1082#ifdef ENABLE_LPS
1083 RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power");
1084 // ieee->ps shall not be set under DC mode, otherwise it conflict
1085 // with Leisure power save mode setting.
1086 //
1087 if(*extra || priv->force_lps) {
1088 priv->ps_force = false;
1089 pPSC->bLeisurePs = true;
1090 } else {
1091 //LZM for PS-Poll AID issue. 090429
1092 if(priv->ieee80211->state == IEEE80211_LINKED)
1093 LeisurePSLeave(dev);
1094
1095 priv->ps_force = true;
1096 pPSC->bLeisurePs = false;
1097 ieee->ps = *extra;
1098 }
1099
1100#endif
1101 up(&priv->wx_sem);
1102 return 0;
1103
1104}
1105
ecdfa446
GKH
1106
1107static iw_handler r8192_wx_handlers[] =
1108{
1109 NULL, /* SIOCSIWCOMMIT */
1110 r8192_wx_get_name, /* SIOCGIWNAME */
1111 dummy, /* SIOCSIWNWID */
1112 dummy, /* SIOCGIWNWID */
1113 r8192_wx_set_freq, /* SIOCSIWFREQ */
1114 r8192_wx_get_freq, /* SIOCGIWFREQ */
1115 r8192_wx_set_mode, /* SIOCSIWMODE */
1116 r8192_wx_get_mode, /* SIOCGIWMODE */
1117 r8192_wx_set_sens, /* SIOCSIWSENS */
1118 r8192_wx_get_sens, /* SIOCGIWSENS */
1119 NULL, /* SIOCSIWRANGE */
1120 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1121 NULL, /* SIOCSIWPRIV */
1122 NULL, /* SIOCGIWPRIV */
1123 NULL, /* SIOCSIWSTATS */
1124 NULL, /* SIOCGIWSTATS */
1125 dummy, /* SIOCSIWSPY */
1126 dummy, /* SIOCGIWSPY */
1127 NULL, /* SIOCGIWTHRSPY */
1128 NULL, /* SIOCWIWTHRSPY */
1129 r8192_wx_set_wap, /* SIOCSIWAP */
1130 r8192_wx_get_wap, /* SIOCGIWAP */
1131#if (WIRELESS_EXT >= 18)
1132 r8192_wx_set_mlme, /* MLME-- */
1133#else
1134 NULL,
1135#endif
1136 dummy, /* SIOCGIWAPLIST -- depricated */
1137 r8192_wx_set_scan, /* SIOCSIWSCAN */
1138 r8192_wx_get_scan, /* SIOCGIWSCAN */
1139 r8192_wx_set_essid, /* SIOCSIWESSID */
1140 r8192_wx_get_essid, /* SIOCGIWESSID */
1141 dummy, /* SIOCSIWNICKN */
1142 dummy, /* SIOCGIWNICKN */
1143 NULL, /* -- hole -- */
1144 NULL, /* -- hole -- */
1145 r8192_wx_set_rate, /* SIOCSIWRATE */
1146 r8192_wx_get_rate, /* SIOCGIWRATE */
1147 r8192_wx_set_rts, /* SIOCSIWRTS */
1148 r8192_wx_get_rts, /* SIOCGIWRTS */
1149 r8192_wx_set_frag, /* SIOCSIWFRAG */
1150 r8192_wx_get_frag, /* SIOCGIWFRAG */
1151 dummy, /* SIOCSIWTXPOW */
1152 dummy, /* SIOCGIWTXPOW */
1153 r8192_wx_set_retry, /* SIOCSIWRETRY */
1154 r8192_wx_get_retry, /* SIOCGIWRETRY */
1155 r8192_wx_set_enc, /* SIOCSIWENCODE */
1156 r8192_wx_get_enc, /* SIOCGIWENCODE */
1157 r8192_wx_set_power, /* SIOCSIWPOWER */
1158 r8192_wx_get_power, /* SIOCGIWPOWER */
1159 NULL, /*---hole---*/
1160 NULL, /*---hole---*/
1161 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1162 NULL, /* SIOCSIWGENIE */
1163#if (WIRELESS_EXT >= 18)
1164 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1165 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1166 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
1167#else
1168 NULL,
1169 NULL,
1170 NULL,
1171#endif
1172 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1173 NULL, /* SIOCSIWPMKSA */
1174 NULL, /*---hole---*/
1175
1176};
1177
1178
1179static const struct iw_priv_args r8192_private_args[] = {
1180
1181 {
1182 SIOCIWFIRSTPRIV + 0x0,
1183 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1184 },
1185
1186 {
1187 SIOCIWFIRSTPRIV + 0x1,
1188 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1189
1190 },
1191 {
1192 SIOCIWFIRSTPRIV + 0x2,
1193 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1194 }
ecdfa446
GKH
1195 ,
1196 {
1197 SIOCIWFIRSTPRIV + 0x3,
65a43784 1198 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1199
ecdfa446
GKH
1200 }
1201 ,
1202 {
1203 SIOCIWFIRSTPRIV + 0x4,
65a43784 1204 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1205 "set_power"
ecdfa446
GKH
1206 }
1207
1208};
1209
1210
1211static iw_handler r8192_private_handler[] = {
ecdfa446 1212 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
ecdfa446
GKH
1213 r8192_wx_set_scan_type,
1214 r8192_wx_set_rawtx,
ecdfa446 1215 r8192_wx_force_reset,
65a43784 1216 r8192_wx_adapter_power_status,
ecdfa446
GKH
1217};
1218
1219//#if WIRELESS_EXT >= 17
1220struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1221{
1222 struct r8192_priv *priv = ieee80211_priv(dev);
1223 struct ieee80211_device* ieee = priv->ieee80211;
1224 struct iw_statistics* wstats = &priv->wstats;
1225 int tmp_level = 0;
1226 int tmp_qual = 0;
1227 int tmp_noise = 0;
1228 if(ieee->state < IEEE80211_LINKED)
1229 {
1230 wstats->qual.qual = 0;
1231 wstats->qual.level = 0;
1232 wstats->qual.noise = 0;
ecdfa446 1233 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
ecdfa446
GKH
1234 return wstats;
1235 }
1236
1237 tmp_level = (&ieee->current_network)->stats.rssi;
1238 tmp_qual = (&ieee->current_network)->stats.signal;
1239 tmp_noise = (&ieee->current_network)->stats.noise;
1240 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1241
1242 wstats->qual.level = tmp_level;
1243 wstats->qual.qual = tmp_qual;
1244 wstats->qual.noise = tmp_noise;
ecdfa446 1245 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
ecdfa446
GKH
1246 return wstats;
1247}
1248//#endif
1249
1250
1251struct iw_handler_def r8192_wx_handlers_def={
1252 .standard = r8192_wx_handlers,
1253 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1254 .private = r8192_private_handler,
1255 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1256 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1257#if WIRELESS_EXT >= 17
1258 .get_wireless_stats = r8192_get_wireless_stats,
1259#endif
1260 .private_args = (struct iw_priv_args *)r8192_private_args,
1261};