Staging: rtl9192e: fix power usage issues
[linux-2.6/btrfs-unstable.git] / drivers / staging / rtl8192e / r8192E_wx.c
blob0b0f39ce3ced93f41271d82f3bedd4ec57e72bdd
1 /*
2 This file contains wireless extension handlers.
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)
8 Parts of this driver are based on the GPL part
9 of the official realtek driver.
11 Parts of this driver are based on the rtl8180 driver skeleton
12 from Patric Schenke & Andres Salomon.
14 Parts of this driver are based on the Intel Pro Wireless 2100 GPL driver.
16 We want to tanks the Authors of those projects and the Ndiswrapper
17 project Authors.
20 #include <linux/string.h>
21 #include "r8192E.h"
22 #include "r8192E_hw.h"
23 #include "r8192E_wx.h"
24 #ifdef ENABLE_DOT11D
25 #include "ieee80211/dot11d.h"
26 #endif
28 #define RATE_COUNT 12
29 static u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
30 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
33 #ifndef ENETDOWN
34 #define ENETDOWN 1
35 #endif
36 static int r8192_wx_get_freq(struct net_device *dev,
37 struct iw_request_info *a,
38 union iwreq_data *wrqu, char *b)
40 struct r8192_priv *priv = ieee80211_priv(dev);
42 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
46 static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
47 union iwreq_data *wrqu, char *b)
49 struct r8192_priv *priv=ieee80211_priv(dev);
51 return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b);
56 static int r8192_wx_get_rate(struct net_device *dev,
57 struct iw_request_info *info,
58 union iwreq_data *wrqu, char *extra)
60 struct r8192_priv *priv = ieee80211_priv(dev);
61 return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
66 static int r8192_wx_set_rate(struct net_device *dev,
67 struct iw_request_info *info,
68 union iwreq_data *wrqu, char *extra)
70 int ret;
71 struct r8192_priv *priv = ieee80211_priv(dev);
73 if(priv->bHwRadioOff == true)
74 return 0;
76 down(&priv->wx_sem);
78 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
80 up(&priv->wx_sem);
82 return ret;
86 static int r8192_wx_set_rts(struct net_device *dev,
87 struct iw_request_info *info,
88 union iwreq_data *wrqu, char *extra)
90 int ret;
91 struct r8192_priv *priv = ieee80211_priv(dev);
93 if(priv->bHwRadioOff == true)
94 return 0;
96 down(&priv->wx_sem);
98 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
100 up(&priv->wx_sem);
102 return ret;
105 static int r8192_wx_get_rts(struct net_device *dev,
106 struct iw_request_info *info,
107 union iwreq_data *wrqu, char *extra)
109 struct r8192_priv *priv = ieee80211_priv(dev);
110 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
113 static int r8192_wx_set_power(struct net_device *dev,
114 struct iw_request_info *info,
115 union iwreq_data *wrqu, char *extra)
117 int ret;
118 struct r8192_priv *priv = ieee80211_priv(dev);
120 if(priv->bHwRadioOff == true)
121 return 0;
123 down(&priv->wx_sem);
125 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
127 up(&priv->wx_sem);
129 return ret;
132 static int r8192_wx_get_power(struct net_device *dev,
133 struct iw_request_info *info,
134 union iwreq_data *wrqu, char *extra)
136 struct r8192_priv *priv = ieee80211_priv(dev);
137 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
140 #ifdef JOHN_IOCTL
141 u16 read_rtl8225(struct net_device *dev, u8 addr);
142 void write_rtl8225(struct net_device *dev, u8 adr, u16 data);
143 u32 john_read_rtl8225(struct net_device *dev, u8 adr);
144 void _write_rtl8225(struct net_device *dev, u8 adr, u16 data);
146 static int r8192_wx_read_regs(struct net_device *dev,
147 struct iw_request_info *info,
148 union iwreq_data *wrqu, char *extra)
150 struct r8192_priv *priv = ieee80211_priv(dev);
151 u8 addr;
152 u16 data1;
154 down(&priv->wx_sem);
157 get_user(addr,(u8*)wrqu->data.pointer);
158 data1 = read_rtl8225(dev, addr);
159 wrqu->data.length = data1;
161 up(&priv->wx_sem);
162 return 0;
166 static int r8192_wx_write_regs(struct net_device *dev,
167 struct iw_request_info *info,
168 union iwreq_data *wrqu, char *extra)
170 struct r8192_priv *priv = ieee80211_priv(dev);
171 u8 addr;
173 down(&priv->wx_sem);
175 get_user(addr, (u8*)wrqu->data.pointer);
176 write_rtl8225(dev, addr, wrqu->data.length);
178 up(&priv->wx_sem);
179 return 0;
183 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
184 u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data);
186 static int r8192_wx_read_bb(struct net_device *dev,
187 struct iw_request_info *info,
188 union iwreq_data *wrqu, char *extra)
190 struct r8192_priv *priv = ieee80211_priv(dev);
191 u8 databb;
192 #if 0
193 int i;
194 for(i=0;i<12;i++) printk("%8x\n", read_cam(dev, i) );
195 #endif
197 down(&priv->wx_sem);
199 databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000);
200 wrqu->data.length = databb;
202 up(&priv->wx_sem);
203 return 0;
206 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
207 static int r8192_wx_write_bb(struct net_device *dev,
208 struct iw_request_info *info,
209 union iwreq_data *wrqu, char *extra)
211 struct r8192_priv *priv = ieee80211_priv(dev);
212 u8 databb;
214 down(&priv->wx_sem);
216 get_user(databb, (u8*)wrqu->data.pointer);
217 rtl8187_write_phy(dev, wrqu->data.length, databb);
219 up(&priv->wx_sem);
220 return 0;
225 static int r8192_wx_write_nicb(struct net_device *dev,
226 struct iw_request_info *info,
227 union iwreq_data *wrqu, char *extra)
229 struct r8192_priv *priv = ieee80211_priv(dev);
230 u32 addr;
232 down(&priv->wx_sem);
234 get_user(addr, (u32*)wrqu->data.pointer);
235 write_nic_byte(dev, addr, wrqu->data.length);
237 up(&priv->wx_sem);
238 return 0;
241 static int r8192_wx_read_nicb(struct net_device *dev,
242 struct iw_request_info *info,
243 union iwreq_data *wrqu, char *extra)
245 struct r8192_priv *priv = ieee80211_priv(dev);
246 u32 addr;
247 u16 data1;
249 down(&priv->wx_sem);
251 get_user(addr,(u32*)wrqu->data.pointer);
252 data1 = read_nic_byte(dev, addr);
253 wrqu->data.length = data1;
255 up(&priv->wx_sem);
256 return 0;
259 static int r8192_wx_get_ap_status(struct net_device *dev,
260 struct iw_request_info *info,
261 union iwreq_data *wrqu, char *extra)
263 struct r8192_priv *priv = ieee80211_priv(dev);
264 struct ieee80211_device *ieee = priv->ieee80211;
265 struct ieee80211_network *target;
266 int name_len;
268 down(&priv->wx_sem);
270 //count the length of input ssid
271 for(name_len=0 ; ((char*)wrqu->data.pointer)[name_len]!='\0' ; name_len++);
273 //search for the correspoding info which is received
274 list_for_each_entry(target, &ieee->network_list, list) {
275 if ( (target->ssid_len == name_len) &&
276 (strncmp(target->ssid, (char*)wrqu->data.pointer, name_len)==0)){
277 if(target->wpa_ie_len>0 || target->rsn_ie_len>0 )
278 //set flags=1 to indicate this ap is WPA
279 wrqu->data.flags = 1;
280 else wrqu->data.flags = 0;
283 break;
287 up(&priv->wx_sem);
288 return 0;
293 #endif
295 static int r8192_wx_set_rawtx(struct net_device *dev,
296 struct iw_request_info *info,
297 union iwreq_data *wrqu, char *extra)
299 struct r8192_priv *priv = ieee80211_priv(dev);
300 int ret;
302 if(priv->bHwRadioOff == true)
303 return 0;
305 down(&priv->wx_sem);
307 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
309 up(&priv->wx_sem);
311 return ret;
315 static int r8192_wx_force_reset(struct net_device *dev,
316 struct iw_request_info *info,
317 union iwreq_data *wrqu, char *extra)
319 struct r8192_priv *priv = ieee80211_priv(dev);
321 down(&priv->wx_sem);
323 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
324 priv->force_reset = *extra;
325 up(&priv->wx_sem);
326 return 0;
331 static int r8192_wx_set_crcmon(struct net_device *dev,
332 struct iw_request_info *info,
333 union iwreq_data *wrqu, char *extra)
335 struct r8192_priv *priv = ieee80211_priv(dev);
336 int *parms = (int *)extra;
337 int enable = (parms[0] > 0);
338 short prev = priv->crcmon;
340 if(priv->bHwRadioOff == true)
341 return 0;
343 down(&priv->wx_sem);
345 if(enable)
346 priv->crcmon=1;
347 else
348 priv->crcmon=0;
350 DMESG("bad CRC in monitor mode are %s",
351 priv->crcmon ? "accepted" : "rejected");
353 if(prev != priv->crcmon && priv->up){
354 //rtl8180_down(dev);
355 //rtl8180_up(dev);
358 up(&priv->wx_sem);
360 return 0;
363 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
364 union iwreq_data *wrqu, char *b)
366 struct r8192_priv *priv = ieee80211_priv(dev);
367 RT_RF_POWER_STATE rtState;
368 int ret;
370 if(priv->bHwRadioOff == true)
371 return 0;
373 rtState = priv->ieee80211->eRFPowerState;
374 down(&priv->wx_sem);
375 #ifdef ENABLE_IPS
376 if(wrqu->mode == IW_MODE_ADHOC){
378 if(priv->ieee80211->PowerSaveControl.bInactivePs){
379 if(rtState == eRfOff){
380 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
382 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
383 up(&priv->wx_sem);
384 return -1;
386 else{
387 RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__);
388 down(&priv->ieee80211->ips_sem);
389 IPSLeave(dev);
390 up(&priv->ieee80211->ips_sem);
395 #endif
396 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
398 //rtl8187_set_rxconf(dev);
400 up(&priv->wx_sem);
401 return ret;
404 struct iw_range_with_scan_capa
406 /* Informative stuff (to choose between different interface) */
407 __u32 throughput; /* To give an idea... */
408 /* In theory this value should be the maximum benchmarked
409 * TCP/IP throughput, because with most of these devices the
410 * bit rate is meaningless (overhead an co) to estimate how
411 * fast the connection will go and pick the fastest one.
412 * I suggest people to play with Netperf or any benchmark...
415 /* NWID (or domain id) */
416 __u32 min_nwid; /* Minimal NWID we are able to set */
417 __u32 max_nwid; /* Maximal NWID we are able to set */
419 /* Old Frequency (backward compat - moved lower ) */
420 __u16 old_num_channels;
421 __u8 old_num_frequency;
423 /* Scan capabilities */
424 __u8 scan_capa;
426 static int rtl8180_wx_get_range(struct net_device *dev,
427 struct iw_request_info *info,
428 union iwreq_data *wrqu, char *extra)
430 struct iw_range *range = (struct iw_range *)extra;
431 struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
432 struct r8192_priv *priv = ieee80211_priv(dev);
433 u16 val;
434 int i;
436 wrqu->data.length = sizeof(*range);
437 memset(range, 0, sizeof(*range));
439 /* Let's try to keep this struct in the same order as in
440 * linux/include/wireless.h
443 /* TODO: See what values we can set, and remove the ones we can't
444 * set, or fill them with some default data.
447 /* ~5 Mb/s real (802.11b) */
448 range->throughput = 130 * 1000 * 1000;
450 // TODO: Not used in 802.11b?
451 // range->min_nwid; /* Minimal NWID we are able to set */
452 // TODO: Not used in 802.11b?
453 // range->max_nwid; /* Maximal NWID we are able to set */
455 /* Old Frequency (backward compat - moved lower ) */
456 // range->old_num_channels;
457 // range->old_num_frequency;
458 // range->old_freq[6]; /* Filler to keep "version" at the same offset */
459 if(priv->rf_set_sens != NULL)
460 range->sensitivity = priv->max_sens; /* signal level threshold range */
462 range->max_qual.qual = 100;
463 /* TODO: Find real max RSSI and stick here */
464 range->max_qual.level = 0;
465 range->max_qual.noise = -98;
466 range->max_qual.updated = 7; /* Updated all three */
468 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
469 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
470 range->avg_qual.level = 20 + -98;
471 range->avg_qual.noise = 0;
472 range->avg_qual.updated = 7; /* Updated all three */
474 range->num_bitrates = RATE_COUNT;
476 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
477 range->bitrate[i] = rtl8180_rates[i];
480 range->min_frag = MIN_FRAG_THRESHOLD;
481 range->max_frag = MAX_FRAG_THRESHOLD;
483 range->min_pmp=0;
484 range->max_pmp = 5000000;
485 range->min_pmt = 0;
486 range->max_pmt = 65535*1000;
487 range->pmp_flags = IW_POWER_PERIOD;
488 range->pmt_flags = IW_POWER_TIMEOUT;
489 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
490 range->we_version_compiled = WIRELESS_EXT;
491 range->we_version_source = 18;
493 // range->retry_capa; /* What retry options are supported */
494 // range->retry_flags; /* How to decode max/min retry limit */
495 // range->r_time_flags; /* How to decode max/min retry life */
496 // range->min_retry; /* Minimal number of retries */
497 // range->max_retry; /* Maximal number of retries */
498 // range->min_r_time; /* Minimal retry lifetime */
499 // range->max_r_time; /* Maximal retry lifetime */
502 for (i = 0, val = 0; i < 14; i++) {
504 // Include only legal frequencies for some countries
505 #ifdef ENABLE_DOT11D
506 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
507 #else
508 if ((priv->ieee80211->channel_map)[i+1]) {
509 #endif
510 range->freq[val].i = i + 1;
511 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
512 range->freq[val].e = 1;
513 val++;
514 } else {
515 // FIXME: do we need to set anything for channels
516 // we don't use ?
519 if (val == IW_MAX_FREQUENCIES)
520 break;
522 range->num_frequency = val;
523 range->num_channels = val;
524 #if WIRELESS_EXT > 17
525 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
526 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
527 #endif
528 tmp->scan_capa = 0x01;
529 return 0;
533 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
534 union iwreq_data *wrqu, char *b)
536 struct r8192_priv *priv = ieee80211_priv(dev);
537 struct ieee80211_device* ieee = priv->ieee80211;
538 RT_RF_POWER_STATE rtState;
539 int ret;
541 if(priv->bHwRadioOff == true)
542 return 0;
544 rtState = priv->ieee80211->eRFPowerState;
546 if(!priv->up) return -ENETDOWN;
547 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
548 return -EAGAIN;
550 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
552 struct iw_scan_req* req = (struct iw_scan_req*)b;
553 if (req->essid_len)
555 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
556 ieee->current_network.ssid_len = req->essid_len;
557 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
558 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
562 down(&priv->wx_sem);
563 #ifdef ENABLE_IPS
564 priv->ieee80211->actscanning = true;
565 if(priv->ieee80211->state != IEEE80211_LINKED){
566 if(priv->ieee80211->PowerSaveControl.bInactivePs){
567 if(rtState == eRfOff){
568 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
570 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
571 up(&priv->wx_sem);
572 return -1;
574 else{
575 //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__);
576 down(&priv->ieee80211->ips_sem);
577 IPSLeave(dev);
578 up(&priv->ieee80211->ips_sem);
582 priv->ieee80211->scanning = 0;
583 ieee80211_softmac_scan_syncro(priv->ieee80211);
584 ret = 0;
586 else
587 #else
589 if(priv->ieee80211->state != IEEE80211_LINKED){
590 priv->ieee80211->scanning = 0;
591 ieee80211_softmac_scan_syncro(priv->ieee80211);
592 ret = 0;
594 else
595 #endif
596 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
598 up(&priv->wx_sem);
599 return ret;
603 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
604 union iwreq_data *wrqu, char *b)
607 int ret;
608 struct r8192_priv *priv = ieee80211_priv(dev);
610 if(priv->bHwRadioOff == true)
611 return 0;
613 if(!priv->up) return -ENETDOWN;
615 down(&priv->wx_sem);
617 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
619 up(&priv->wx_sem);
621 return ret;
624 static int r8192_wx_set_essid(struct net_device *dev,
625 struct iw_request_info *a,
626 union iwreq_data *wrqu, char *b)
628 struct r8192_priv *priv = ieee80211_priv(dev);
629 RT_RF_POWER_STATE rtState;
630 int ret;
632 if(priv->bHwRadioOff == true)
633 return 0;
635 rtState = priv->ieee80211->eRFPowerState;
636 down(&priv->wx_sem);
638 #ifdef ENABLE_IPS
639 down(&priv->ieee80211->ips_sem);
640 IPSLeave(dev);
641 up(&priv->ieee80211->ips_sem);
642 #endif
643 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
645 up(&priv->wx_sem);
647 return ret;
653 static int r8192_wx_get_essid(struct net_device *dev,
654 struct iw_request_info *a,
655 union iwreq_data *wrqu, char *b)
657 int ret;
658 struct r8192_priv *priv = ieee80211_priv(dev);
660 down(&priv->wx_sem);
662 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
664 up(&priv->wx_sem);
666 return ret;
670 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
671 union iwreq_data *wrqu, char *b)
673 int ret;
674 struct r8192_priv *priv = ieee80211_priv(dev);
676 if(priv->bHwRadioOff == true)
677 return 0;
679 down(&priv->wx_sem);
681 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
683 up(&priv->wx_sem);
684 return ret;
687 static int r8192_wx_get_name(struct net_device *dev,
688 struct iw_request_info *info,
689 union iwreq_data *wrqu, char *extra)
691 struct r8192_priv *priv = ieee80211_priv(dev);
692 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
696 static int r8192_wx_set_frag(struct net_device *dev,
697 struct iw_request_info *info,
698 union iwreq_data *wrqu, char *extra)
700 struct r8192_priv *priv = ieee80211_priv(dev);
702 if(priv->bHwRadioOff == true)
703 return 0;
705 if (wrqu->frag.disabled)
706 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
707 else {
708 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
709 wrqu->frag.value > MAX_FRAG_THRESHOLD)
710 return -EINVAL;
712 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
715 return 0;
719 static int r8192_wx_get_frag(struct net_device *dev,
720 struct iw_request_info *info,
721 union iwreq_data *wrqu, char *extra)
723 struct r8192_priv *priv = ieee80211_priv(dev);
725 wrqu->frag.value = priv->ieee80211->fts;
726 wrqu->frag.fixed = 0; /* no auto select */
727 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
729 return 0;
733 static int r8192_wx_set_wap(struct net_device *dev,
734 struct iw_request_info *info,
735 union iwreq_data *awrq,
736 char *extra)
739 int ret;
740 struct r8192_priv *priv = ieee80211_priv(dev);
741 // struct sockaddr *temp = (struct sockaddr *)awrq;
743 if(priv->bHwRadioOff == true)
744 return 0;
746 down(&priv->wx_sem);
748 #ifdef ENABLE_IPS
749 down(&priv->ieee80211->ips_sem);
750 IPSLeave(dev);
751 up(&priv->ieee80211->ips_sem);
752 #endif
753 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
755 up(&priv->wx_sem);
757 return ret;
762 static int r8192_wx_get_wap(struct net_device *dev,
763 struct iw_request_info *info,
764 union iwreq_data *wrqu, char *extra)
766 struct r8192_priv *priv = ieee80211_priv(dev);
768 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
772 static int r8192_wx_get_enc(struct net_device *dev,
773 struct iw_request_info *info,
774 union iwreq_data *wrqu, char *key)
776 struct r8192_priv *priv = ieee80211_priv(dev);
778 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
781 static int r8192_wx_set_enc(struct net_device *dev,
782 struct iw_request_info *info,
783 union iwreq_data *wrqu, char *key)
785 struct r8192_priv *priv = ieee80211_priv(dev);
786 int ret;
788 struct ieee80211_device *ieee = priv->ieee80211;
789 //u32 TargetContent;
790 u32 hwkey[4]={0,0,0,0};
791 u8 mask=0xff;
792 u32 key_idx=0;
793 u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00},
794 {0x00,0x00,0x00,0x00,0x00,0x01},
795 {0x00,0x00,0x00,0x00,0x00,0x02},
796 {0x00,0x00,0x00,0x00,0x00,0x03} };
797 int i;
799 if(priv->bHwRadioOff == true)
800 return 0;
802 if(!priv->up) return -ENETDOWN;
804 priv->ieee80211->wx_set_enc = 1;
805 #ifdef ENABLE_IPS
806 down(&priv->ieee80211->ips_sem);
807 IPSLeave(dev);
808 up(&priv->ieee80211->ips_sem);
809 #endif
811 down(&priv->wx_sem);
813 RT_TRACE(COMP_SEC, "Setting SW wep key");
814 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
816 up(&priv->wx_sem);
818 //sometimes, the length is zero while we do not type key value
819 if(wrqu->encoding.length!=0){
821 for(i=0 ; i<4 ; i++){
822 hwkey[i] |= key[4*i+0]&mask;
823 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
824 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
825 hwkey[i] |= (key[4*i+1]&mask)<<8;
826 hwkey[i] |= (key[4*i+2]&mask)<<16;
827 hwkey[i] |= (key[4*i+3]&mask)<<24;
830 #define CONF_WEP40 0x4
831 #define CONF_WEP104 0x14
833 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
834 case 0: key_idx = ieee->tx_keyidx; break;
835 case 1: key_idx = 0; break;
836 case 2: key_idx = 1; break;
837 case 3: key_idx = 2; break;
838 case 4: key_idx = 3; break;
839 default: break;
842 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
843 if(wrqu->encoding.length==0x5){
844 ieee->pairwise_key_type = KEY_TYPE_WEP40;
845 EnableHWSecurityConfig8192(dev);
846 setKey( dev,
847 key_idx, //EntryNo
848 key_idx, //KeyIndex
849 KEY_TYPE_WEP40, //KeyType
850 zero_addr[key_idx],
851 0, //DefaultKey
852 hwkey); //KeyContent
854 #if 0
855 if(key_idx == 0){
857 //write_nic_byte(dev, SECR, 7);
858 setKey( dev,
859 4, //EntryNo
860 key_idx, //KeyIndex
861 KEY_TYPE_WEP40, //KeyType
862 broadcast_addr, //addr
863 0, //DefaultKey
864 hwkey); //KeyContent
866 #endif
869 else if(wrqu->encoding.length==0xd){
870 ieee->pairwise_key_type = KEY_TYPE_WEP104;
871 EnableHWSecurityConfig8192(dev);
872 setKey( dev,
873 key_idx, //EntryNo
874 key_idx, //KeyIndex
875 KEY_TYPE_WEP104, //KeyType
876 zero_addr[key_idx],
877 0, //DefaultKey
878 hwkey); //KeyContent
879 #if 0
880 if(key_idx == 0){
882 //write_nic_byte(dev, SECR, 7);
883 setKey( dev,
884 4, //EntryNo
885 key_idx, //KeyIndex
886 KEY_TYPE_WEP104, //KeyType
887 broadcast_addr, //addr
888 0, //DefaultKey
889 hwkey); //KeyContent
891 #endif
893 else printk("wrong type in WEP, not WEP40 and WEP104\n");
898 #if 0
899 //consider the setting different key index situation
900 //wrqu->encoding.flags = 801 means that we set key with index "1"
901 if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
902 printk("===>1\n");
903 //write_nic_byte(dev, SECR, 7);
904 EnableHWSecurityConfig8192(dev);
905 //copy wpa config from default key(key0~key3) to broadcast key(key5)
907 key_idx = (wrqu->encoding.flags & 0xf)-1 ;
908 write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) );
909 write_cam(dev, (4*6)+1, 0xffffffff);
910 write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
911 write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
912 write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
913 write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
915 #endif
917 priv->ieee80211->wx_set_enc = 0;
919 return ret;
923 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
924 iwreq_data *wrqu, char *p){
926 struct r8192_priv *priv = ieee80211_priv(dev);
927 int *parms=(int*)p;
928 int mode=parms[0];
930 priv->ieee80211->active_scan = mode;
932 return 1;
937 static int r8192_wx_set_retry(struct net_device *dev,
938 struct iw_request_info *info,
939 union iwreq_data *wrqu, char *extra)
941 struct r8192_priv *priv = ieee80211_priv(dev);
942 int err = 0;
944 if(priv->bHwRadioOff == true)
945 return 0;
947 down(&priv->wx_sem);
949 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
950 wrqu->retry.disabled){
951 err = -EINVAL;
952 goto exit;
954 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
955 err = -EINVAL;
956 goto exit;
959 if(wrqu->retry.value > R8180_MAX_RETRY){
960 err= -EINVAL;
961 goto exit;
963 if (wrqu->retry.flags & IW_RETRY_MAX) {
964 priv->retry_rts = wrqu->retry.value;
965 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
967 }else {
968 priv->retry_data = wrqu->retry.value;
969 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
972 /* FIXME !
973 * We might try to write directly the TX config register
974 * or to restart just the (R)TX process.
975 * I'm unsure if whole reset is really needed
978 rtl8192_commit(dev);
980 if(priv->up){
981 rtl8180_rtx_disable(dev);
982 rtl8180_rx_enable(dev);
983 rtl8180_tx_enable(dev);
987 exit:
988 up(&priv->wx_sem);
990 return err;
993 static int r8192_wx_get_retry(struct net_device *dev,
994 struct iw_request_info *info,
995 union iwreq_data *wrqu, char *extra)
997 struct r8192_priv *priv = ieee80211_priv(dev);
1000 wrqu->retry.disabled = 0; /* can't be disabled */
1002 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
1003 IW_RETRY_LIFETIME)
1004 return -EINVAL;
1006 if (wrqu->retry.flags & IW_RETRY_MAX) {
1007 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
1008 wrqu->retry.value = priv->retry_rts;
1009 } else {
1010 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
1011 wrqu->retry.value = priv->retry_data;
1013 //DMESG("returning %d",wrqu->retry.value);
1016 return 0;
1019 static int r8192_wx_get_sens(struct net_device *dev,
1020 struct iw_request_info *info,
1021 union iwreq_data *wrqu, char *extra)
1023 struct r8192_priv *priv = ieee80211_priv(dev);
1024 if(priv->rf_set_sens == NULL)
1025 return -1; /* we have not this support for this radio */
1026 wrqu->sens.value = priv->sens;
1027 return 0;
1031 static int r8192_wx_set_sens(struct net_device *dev,
1032 struct iw_request_info *info,
1033 union iwreq_data *wrqu, char *extra)
1036 struct r8192_priv *priv = ieee80211_priv(dev);
1038 short err = 0;
1040 if(priv->bHwRadioOff == true)
1041 return 0;
1043 down(&priv->wx_sem);
1044 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
1045 if(priv->rf_set_sens == NULL) {
1046 err= -1; /* we have not this support for this radio */
1047 goto exit;
1049 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
1050 priv->sens = wrqu->sens.value;
1051 else
1052 err= -EINVAL;
1054 exit:
1055 up(&priv->wx_sem);
1057 return err;
1060 #if (WIRELESS_EXT >= 18)
1061 static int r8192_wx_set_enc_ext(struct net_device *dev,
1062 struct iw_request_info *info,
1063 union iwreq_data *wrqu, char *extra)
1065 int ret=0;
1066 struct r8192_priv *priv = ieee80211_priv(dev);
1067 struct ieee80211_device* ieee = priv->ieee80211;
1069 if(priv->bHwRadioOff == true)
1070 return 0;
1072 down(&priv->wx_sem);
1074 priv->ieee80211->wx_set_enc = 1;
1076 #ifdef ENABLE_IPS
1077 down(&priv->ieee80211->ips_sem);
1078 IPSLeave(dev);
1079 up(&priv->ieee80211->ips_sem);
1080 #endif
1082 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
1085 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
1086 u8 zero[6] = {0};
1087 u32 key[4] = {0};
1088 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1089 struct iw_point *encoding = &wrqu->encoding;
1090 #if 0
1091 static u8 CAM_CONST_ADDR[4][6] = {
1092 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1093 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
1094 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
1095 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
1096 #endif
1097 u8 idx = 0, alg = 0, group = 0;
1098 if ((encoding->flags & IW_ENCODE_DISABLED) ||
1099 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
1101 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
1102 CamResetAllEntry(dev);
1103 goto end_hw_sec;
1105 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;
1106 idx = encoding->flags & IW_ENCODE_INDEX;
1107 if (idx)
1108 idx --;
1109 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
1111 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
1113 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
1114 alg = KEY_TYPE_WEP104;
1115 ieee->pairwise_key_type = alg;
1116 EnableHWSecurityConfig8192(dev);
1118 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
1120 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
1122 if (ext->key_len == 13)
1123 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
1124 setKey( dev,
1125 idx,//EntryNo
1126 idx, //KeyIndex
1127 alg, //KeyType
1128 zero, //MacAddr
1129 0, //DefaultKey
1130 key); //KeyContent
1132 else if (group)
1134 ieee->group_key_type = alg;
1135 setKey( dev,
1136 idx,//EntryNo
1137 idx, //KeyIndex
1138 alg, //KeyType
1139 broadcast_addr, //MacAddr
1140 0, //DefaultKey
1141 key); //KeyContent
1143 else //pairwise key
1145 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
1146 write_nic_byte(dev, 0x173, 1); //fix aes bug
1148 setKey( dev,
1149 4,//EntryNo
1150 idx, //KeyIndex
1151 alg, //KeyType
1152 (u8*)ieee->ap_mac_addr, //MacAddr
1153 0, //DefaultKey
1154 key); //KeyContent
1160 end_hw_sec:
1161 priv->ieee80211->wx_set_enc = 0;
1162 up(&priv->wx_sem);
1163 return ret;
1166 static int r8192_wx_set_auth(struct net_device *dev,
1167 struct iw_request_info *info,
1168 union iwreq_data *data, char *extra)
1170 int ret=0;
1171 //printk("====>%s()\n", __FUNCTION__);
1172 struct r8192_priv *priv = ieee80211_priv(dev);
1174 if(priv->bHwRadioOff == true)
1175 return 0;
1177 down(&priv->wx_sem);
1178 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
1179 up(&priv->wx_sem);
1180 return ret;
1183 static int r8192_wx_set_mlme(struct net_device *dev,
1184 struct iw_request_info *info,
1185 union iwreq_data *wrqu, char *extra)
1187 //printk("====>%s()\n", __FUNCTION__);
1189 int ret=0;
1190 struct r8192_priv *priv = ieee80211_priv(dev);
1192 if(priv->bHwRadioOff == true)
1193 return 0;
1195 down(&priv->wx_sem);
1196 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1197 up(&priv->wx_sem);
1198 return ret;
1200 #endif
1201 static int r8192_wx_set_gen_ie(struct net_device *dev,
1202 struct iw_request_info *info,
1203 union iwreq_data *data, char *extra)
1205 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1206 int ret=0;
1207 struct r8192_priv *priv = ieee80211_priv(dev);
1209 if(priv->bHwRadioOff == true)
1210 return 0;
1212 down(&priv->wx_sem);
1213 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1214 up(&priv->wx_sem);
1215 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1216 return ret;
1219 static int dummy(struct net_device *dev, struct iw_request_info *a,
1220 union iwreq_data *wrqu,char *b)
1222 return -1;
1225 // check ac/dc status with the help of user space application */
1226 static int r8192_wx_adapter_power_status(struct net_device *dev,
1227 struct iw_request_info *info,
1228 union iwreq_data *wrqu, char *extra)
1230 struct r8192_priv *priv = ieee80211_priv(dev);
1231 #ifdef ENABLE_LPS
1232 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl));
1233 struct ieee80211_device* ieee = priv->ieee80211;
1234 #endif
1235 down(&priv->wx_sem);
1237 #ifdef ENABLE_LPS
1238 RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power");
1239 // ieee->ps shall not be set under DC mode, otherwise it conflict
1240 // with Leisure power save mode setting.
1242 if(*extra || priv->force_lps) {
1243 priv->ps_force = false;
1244 pPSC->bLeisurePs = true;
1245 } else {
1246 //LZM for PS-Poll AID issue. 090429
1247 if(priv->ieee80211->state == IEEE80211_LINKED)
1248 LeisurePSLeave(dev);
1250 priv->ps_force = true;
1251 pPSC->bLeisurePs = false;
1252 ieee->ps = *extra;
1255 #endif
1256 up(&priv->wx_sem);
1257 return 0;
1262 static iw_handler r8192_wx_handlers[] =
1264 NULL, /* SIOCSIWCOMMIT */
1265 r8192_wx_get_name, /* SIOCGIWNAME */
1266 dummy, /* SIOCSIWNWID */
1267 dummy, /* SIOCGIWNWID */
1268 r8192_wx_set_freq, /* SIOCSIWFREQ */
1269 r8192_wx_get_freq, /* SIOCGIWFREQ */
1270 r8192_wx_set_mode, /* SIOCSIWMODE */
1271 r8192_wx_get_mode, /* SIOCGIWMODE */
1272 r8192_wx_set_sens, /* SIOCSIWSENS */
1273 r8192_wx_get_sens, /* SIOCGIWSENS */
1274 NULL, /* SIOCSIWRANGE */
1275 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1276 NULL, /* SIOCSIWPRIV */
1277 NULL, /* SIOCGIWPRIV */
1278 NULL, /* SIOCSIWSTATS */
1279 NULL, /* SIOCGIWSTATS */
1280 dummy, /* SIOCSIWSPY */
1281 dummy, /* SIOCGIWSPY */
1282 NULL, /* SIOCGIWTHRSPY */
1283 NULL, /* SIOCWIWTHRSPY */
1284 r8192_wx_set_wap, /* SIOCSIWAP */
1285 r8192_wx_get_wap, /* SIOCGIWAP */
1286 #if (WIRELESS_EXT >= 18)
1287 r8192_wx_set_mlme, /* MLME-- */
1288 #else
1289 NULL,
1290 #endif
1291 dummy, /* SIOCGIWAPLIST -- depricated */
1292 r8192_wx_set_scan, /* SIOCSIWSCAN */
1293 r8192_wx_get_scan, /* SIOCGIWSCAN */
1294 r8192_wx_set_essid, /* SIOCSIWESSID */
1295 r8192_wx_get_essid, /* SIOCGIWESSID */
1296 dummy, /* SIOCSIWNICKN */
1297 dummy, /* SIOCGIWNICKN */
1298 NULL, /* -- hole -- */
1299 NULL, /* -- hole -- */
1300 r8192_wx_set_rate, /* SIOCSIWRATE */
1301 r8192_wx_get_rate, /* SIOCGIWRATE */
1302 r8192_wx_set_rts, /* SIOCSIWRTS */
1303 r8192_wx_get_rts, /* SIOCGIWRTS */
1304 r8192_wx_set_frag, /* SIOCSIWFRAG */
1305 r8192_wx_get_frag, /* SIOCGIWFRAG */
1306 dummy, /* SIOCSIWTXPOW */
1307 dummy, /* SIOCGIWTXPOW */
1308 r8192_wx_set_retry, /* SIOCSIWRETRY */
1309 r8192_wx_get_retry, /* SIOCGIWRETRY */
1310 r8192_wx_set_enc, /* SIOCSIWENCODE */
1311 r8192_wx_get_enc, /* SIOCGIWENCODE */
1312 r8192_wx_set_power, /* SIOCSIWPOWER */
1313 r8192_wx_get_power, /* SIOCGIWPOWER */
1314 NULL, /*---hole---*/
1315 NULL, /*---hole---*/
1316 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1317 NULL, /* SIOCSIWGENIE */
1318 #if (WIRELESS_EXT >= 18)
1319 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1320 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1321 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
1322 #else
1323 NULL,
1324 NULL,
1325 NULL,
1326 #endif
1327 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1328 NULL, /* SIOCSIWPMKSA */
1329 NULL, /*---hole---*/
1334 static const struct iw_priv_args r8192_private_args[] = {
1337 SIOCIWFIRSTPRIV + 0x0,
1338 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1342 SIOCIWFIRSTPRIV + 0x1,
1343 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1347 SIOCIWFIRSTPRIV + 0x2,
1348 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1352 SIOCIWFIRSTPRIV + 0x3,
1353 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1358 SIOCIWFIRSTPRIV + 0x4,
1359 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE,
1360 "set_power"
1366 static iw_handler r8192_private_handler[] = {
1367 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
1368 r8192_wx_set_scan_type,
1369 r8192_wx_set_rawtx,
1370 r8192_wx_force_reset,
1371 r8192_wx_adapter_power_status,
1374 //#if WIRELESS_EXT >= 17
1375 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1377 struct r8192_priv *priv = ieee80211_priv(dev);
1378 struct ieee80211_device* ieee = priv->ieee80211;
1379 struct iw_statistics* wstats = &priv->wstats;
1380 int tmp_level = 0;
1381 int tmp_qual = 0;
1382 int tmp_noise = 0;
1383 if(ieee->state < IEEE80211_LINKED)
1385 wstats->qual.qual = 0;
1386 wstats->qual.level = 0;
1387 wstats->qual.noise = 0;
1388 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1389 return wstats;
1392 tmp_level = (&ieee->current_network)->stats.rssi;
1393 tmp_qual = (&ieee->current_network)->stats.signal;
1394 tmp_noise = (&ieee->current_network)->stats.noise;
1395 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1397 wstats->qual.level = tmp_level;
1398 wstats->qual.qual = tmp_qual;
1399 wstats->qual.noise = tmp_noise;
1400 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1401 return wstats;
1403 //#endif
1406 struct iw_handler_def r8192_wx_handlers_def={
1407 .standard = r8192_wx_handlers,
1408 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1409 .private = r8192_private_handler,
1410 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1411 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1412 #if WIRELESS_EXT >= 17
1413 .get_wireless_stats = r8192_get_wireless_stats,
1414 #endif
1415 .private_args = (struct iw_priv_args *)r8192_private_args,