Merge branch 'fixes' of git://git.linaro.org/people/rmk/linux-arm
[linux-2.6.git] / drivers / staging / rtl8192u / r8192U_wx.c
blob3e2576347d29ee73df1d22a7d42e0e5cd36b8624
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 thank the Authors of those projects and the Ndiswrapper
17 project Authors.
20 #include <linux/string.h>
21 #include "r8192U.h"
22 #include "r8192U_hw.h"
24 #include "dot11d.h"
26 #define RATE_COUNT 12
27 u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
28 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
31 #ifndef ENETDOWN
32 #define ENETDOWN 1
33 #endif
35 static int r8192_wx_get_freq(struct net_device *dev,
36 struct iw_request_info *a,
37 union iwreq_data *wrqu, char *b)
39 struct r8192_priv *priv = ieee80211_priv(dev);
41 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
45 static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
46 union iwreq_data *wrqu, char *b)
48 struct r8192_priv *priv=ieee80211_priv(dev);
50 return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b);
55 static int r8192_wx_get_rate(struct net_device *dev,
56 struct iw_request_info *info,
57 union iwreq_data *wrqu, char *extra)
59 struct r8192_priv *priv = ieee80211_priv(dev);
60 return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
65 static int r8192_wx_set_rate(struct net_device *dev,
66 struct iw_request_info *info,
67 union iwreq_data *wrqu, char *extra)
69 int ret;
70 struct r8192_priv *priv = ieee80211_priv(dev);
72 down(&priv->wx_sem);
74 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
76 up(&priv->wx_sem);
78 return ret;
82 static int r8192_wx_set_rts(struct net_device *dev,
83 struct iw_request_info *info,
84 union iwreq_data *wrqu, char *extra)
86 int ret;
87 struct r8192_priv *priv = ieee80211_priv(dev);
89 down(&priv->wx_sem);
91 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
93 up(&priv->wx_sem);
95 return ret;
98 static int r8192_wx_get_rts(struct net_device *dev,
99 struct iw_request_info *info,
100 union iwreq_data *wrqu, char *extra)
102 struct r8192_priv *priv = ieee80211_priv(dev);
103 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
106 static int r8192_wx_set_power(struct net_device *dev,
107 struct iw_request_info *info,
108 union iwreq_data *wrqu, char *extra)
110 int ret;
111 struct r8192_priv *priv = ieee80211_priv(dev);
113 down(&priv->wx_sem);
115 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
117 up(&priv->wx_sem);
119 return ret;
122 static int r8192_wx_get_power(struct net_device *dev,
123 struct iw_request_info *info,
124 union iwreq_data *wrqu, char *extra)
126 struct r8192_priv *priv = ieee80211_priv(dev);
127 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
130 #ifdef JOHN_IOCTL
131 u16 read_rtl8225(struct net_device *dev, u8 addr);
132 void write_rtl8225(struct net_device *dev, u8 adr, u16 data);
133 u32 john_read_rtl8225(struct net_device *dev, u8 adr);
134 void _write_rtl8225(struct net_device *dev, u8 adr, u16 data);
136 static int r8192_wx_read_regs(struct net_device *dev,
137 struct iw_request_info *info,
138 union iwreq_data *wrqu, char *extra)
140 struct r8192_priv *priv = ieee80211_priv(dev);
141 u8 addr;
142 u16 data1;
144 down(&priv->wx_sem);
147 get_user(addr,(u8 *)wrqu->data.pointer);
148 data1 = read_rtl8225(dev, addr);
149 wrqu->data.length = data1;
151 up(&priv->wx_sem);
152 return 0;
156 static int r8192_wx_write_regs(struct net_device *dev,
157 struct iw_request_info *info,
158 union iwreq_data *wrqu, char *extra)
160 struct r8192_priv *priv = ieee80211_priv(dev);
161 u8 addr;
163 down(&priv->wx_sem);
165 get_user(addr, (u8 *)wrqu->data.pointer);
166 write_rtl8225(dev, addr, wrqu->data.length);
168 up(&priv->wx_sem);
169 return 0;
173 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
174 u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data);
176 static int r8192_wx_read_bb(struct net_device *dev,
177 struct iw_request_info *info,
178 union iwreq_data *wrqu, char *extra)
180 struct r8192_priv *priv = ieee80211_priv(dev);
181 u8 databb;
183 down(&priv->wx_sem);
185 databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000);
186 wrqu->data.length = databb;
188 up(&priv->wx_sem);
189 return 0;
192 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
193 static int r8192_wx_write_bb(struct net_device *dev,
194 struct iw_request_info *info,
195 union iwreq_data *wrqu, char *extra)
197 struct r8192_priv *priv = ieee80211_priv(dev);
198 u8 databb;
200 down(&priv->wx_sem);
202 get_user(databb, (u8 *)wrqu->data.pointer);
203 rtl8187_write_phy(dev, wrqu->data.length, databb);
205 up(&priv->wx_sem);
206 return 0;
211 static int r8192_wx_write_nicb(struct net_device *dev,
212 struct iw_request_info *info,
213 union iwreq_data *wrqu, char *extra)
215 struct r8192_priv *priv = ieee80211_priv(dev);
216 u32 addr;
218 down(&priv->wx_sem);
220 get_user(addr, (u32 *)wrqu->data.pointer);
221 write_nic_byte(dev, addr, wrqu->data.length);
223 up(&priv->wx_sem);
224 return 0;
227 static int r8192_wx_read_nicb(struct net_device *dev,
228 struct iw_request_info *info,
229 union iwreq_data *wrqu, char *extra)
231 struct r8192_priv *priv = ieee80211_priv(dev);
232 u32 addr;
233 u16 data1;
235 down(&priv->wx_sem);
237 get_user(addr,(u32 *)wrqu->data.pointer);
238 read_nic_byte(dev, addr, &data1);
239 wrqu->data.length = data1;
241 up(&priv->wx_sem);
242 return 0;
245 static int r8192_wx_get_ap_status(struct net_device *dev,
246 struct iw_request_info *info,
247 union iwreq_data *wrqu, char *extra)
249 struct r8192_priv *priv = ieee80211_priv(dev);
250 struct ieee80211_device *ieee = priv->ieee80211;
251 struct ieee80211_network *target;
252 int name_len;
254 down(&priv->wx_sem);
256 //count the length of input ssid
257 for(name_len=0 ; ((char *)wrqu->data.pointer)[name_len]!='\0' ; name_len++);
259 //search for the corresponding info which is received
260 list_for_each_entry(target, &ieee->network_list, list) {
261 if ( (target->ssid_len == name_len) &&
262 (strncmp(target->ssid, (char *)wrqu->data.pointer, name_len)==0)){
263 if(target->wpa_ie_len>0 || target->rsn_ie_len>0 )
264 //set flags=1 to indicate this ap is WPA
265 wrqu->data.flags = 1;
266 else wrqu->data.flags = 0;
269 break;
273 up(&priv->wx_sem);
274 return 0;
279 #endif
280 static int r8192_wx_force_reset(struct net_device *dev,
281 struct iw_request_info *info,
282 union iwreq_data *wrqu, char *extra)
284 struct r8192_priv *priv = ieee80211_priv(dev);
286 down(&priv->wx_sem);
288 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
289 priv->force_reset = *extra;
290 up(&priv->wx_sem);
291 return 0;
296 static int r8192_wx_set_rawtx(struct net_device *dev,
297 struct iw_request_info *info,
298 union iwreq_data *wrqu, char *extra)
300 struct r8192_priv *priv = ieee80211_priv(dev);
301 int ret;
303 down(&priv->wx_sem);
305 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
307 up(&priv->wx_sem);
309 return ret;
313 static int r8192_wx_set_crcmon(struct net_device *dev,
314 struct iw_request_info *info,
315 union iwreq_data *wrqu, char *extra)
317 struct r8192_priv *priv = ieee80211_priv(dev);
318 int *parms = (int *)extra;
319 int enable = (parms[0] > 0);
320 short prev = priv->crcmon;
322 down(&priv->wx_sem);
324 if(enable)
325 priv->crcmon=1;
326 else
327 priv->crcmon=0;
329 DMESG("bad CRC in monitor mode are %s",
330 priv->crcmon ? "accepted" : "rejected");
332 if(prev != priv->crcmon && priv->up){
333 //rtl8180_down(dev);
334 //rtl8180_up(dev);
337 up(&priv->wx_sem);
339 return 0;
342 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
343 union iwreq_data *wrqu, char *b)
345 struct r8192_priv *priv = ieee80211_priv(dev);
346 int ret;
347 down(&priv->wx_sem);
349 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
351 rtl8192_set_rxconf(dev);
353 up(&priv->wx_sem);
354 return ret;
357 struct iw_range_with_scan_capa {
358 /* Informative stuff (to choose between different interface) */
359 __u32 throughput; /* To give an idea... */
360 /* In theory this value should be the maximum benchmarked
361 * TCP/IP throughput, because with most of these devices the
362 * bit rate is meaningless (overhead an co) to estimate how
363 * fast the connection will go and pick the fastest one.
364 * I suggest people to play with Netperf or any benchmark...
367 /* NWID (or domain id) */
368 __u32 min_nwid; /* Minimal NWID we are able to set */
369 __u32 max_nwid; /* Maximal NWID we are able to set */
371 /* Old Frequency (backward compat - moved lower ) */
372 __u16 old_num_channels;
373 __u8 old_num_frequency;
375 /* Scan capabilities */
376 __u8 scan_capa;
378 static int rtl8180_wx_get_range(struct net_device *dev,
379 struct iw_request_info *info,
380 union iwreq_data *wrqu, char *extra)
382 struct iw_range *range = (struct iw_range *)extra;
383 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
384 struct r8192_priv *priv = ieee80211_priv(dev);
385 u16 val;
386 int i;
388 wrqu->data.length = sizeof(*range);
389 memset(range, 0, sizeof(*range));
391 /* Let's try to keep this struct in the same order as in
392 * linux/include/wireless.h
395 /* TODO: See what values we can set, and remove the ones we can't
396 * set, or fill them with some default data.
399 /* ~5 Mb/s real (802.11b) */
400 range->throughput = 5 * 1000 * 1000;
402 // TODO: Not used in 802.11b?
403 // range->min_nwid; /* Minimal NWID we are able to set */
404 // TODO: Not used in 802.11b?
405 // range->max_nwid; /* Maximal NWID we are able to set */
407 /* Old Frequency (backward compat - moved lower ) */
408 // range->old_num_channels;
409 // range->old_num_frequency;
410 // range->old_freq[6]; /* Filler to keep "version" at the same offset */
411 if(priv->rf_set_sens != NULL)
412 range->sensitivity = priv->max_sens; /* signal level threshold range */
414 range->max_qual.qual = 100;
415 /* TODO: Find real max RSSI and stick here */
416 range->max_qual.level = 0;
417 range->max_qual.noise = -98;
418 range->max_qual.updated = 7; /* Updated all three */
420 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
421 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
422 range->avg_qual.level = 20 + -98;
423 range->avg_qual.noise = 0;
424 range->avg_qual.updated = 7; /* Updated all three */
426 range->num_bitrates = RATE_COUNT;
428 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
429 range->bitrate[i] = rtl8180_rates[i];
432 range->min_frag = MIN_FRAG_THRESHOLD;
433 range->max_frag = MAX_FRAG_THRESHOLD;
435 range->min_pmp=0;
436 range->max_pmp = 5000000;
437 range->min_pmt = 0;
438 range->max_pmt = 65535*1000;
439 range->pmp_flags = IW_POWER_PERIOD;
440 range->pmt_flags = IW_POWER_TIMEOUT;
441 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
443 range->we_version_compiled = WIRELESS_EXT;
444 range->we_version_source = 16;
446 // range->retry_capa; /* What retry options are supported */
447 // range->retry_flags; /* How to decode max/min retry limit */
448 // range->r_time_flags; /* How to decode max/min retry life */
449 // range->min_retry; /* Minimal number of retries */
450 // range->max_retry; /* Maximal number of retries */
451 // range->min_r_time; /* Minimal retry lifetime */
452 // range->max_r_time; /* Maximal retry lifetime */
455 for (i = 0, val = 0; i < 14; i++) {
457 // Include only legal frequencies for some countries
458 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
459 range->freq[val].i = i + 1;
460 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
461 range->freq[val].e = 1;
462 val++;
463 } else {
464 // FIXME: do we need to set anything for channels
465 // we don't use ?
468 if (val == IW_MAX_FREQUENCIES)
469 break;
471 range->num_frequency = val;
472 range->num_channels = val;
473 #if WIRELESS_EXT > 17
474 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
475 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
476 #endif
477 tmp->scan_capa = 0x01;
478 return 0;
482 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
483 union iwreq_data *wrqu, char *b)
485 struct r8192_priv *priv = ieee80211_priv(dev);
486 struct ieee80211_device *ieee = priv->ieee80211;
487 int ret = 0;
489 if(!priv->up) return -ENETDOWN;
491 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
492 return -EAGAIN;
493 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
495 struct iw_scan_req *req = (struct iw_scan_req *)b;
496 if (req->essid_len)
498 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
499 ieee->current_network.ssid_len = req->essid_len;
500 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
501 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
505 down(&priv->wx_sem);
506 if(priv->ieee80211->state != IEEE80211_LINKED){
507 priv->ieee80211->scanning = 0;
508 ieee80211_softmac_scan_syncro(priv->ieee80211);
509 ret = 0;
511 else
512 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
513 up(&priv->wx_sem);
514 return ret;
518 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
519 union iwreq_data *wrqu, char *b)
522 int ret;
523 struct r8192_priv *priv = ieee80211_priv(dev);
525 if(!priv->up) return -ENETDOWN;
527 down(&priv->wx_sem);
529 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
531 up(&priv->wx_sem);
533 return ret;
536 static int r8192_wx_set_essid(struct net_device *dev,
537 struct iw_request_info *a,
538 union iwreq_data *wrqu, char *b)
540 struct r8192_priv *priv = ieee80211_priv(dev);
541 int ret;
542 down(&priv->wx_sem);
544 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
546 up(&priv->wx_sem);
548 return ret;
554 static int r8192_wx_get_essid(struct net_device *dev,
555 struct iw_request_info *a,
556 union iwreq_data *wrqu, char *b)
558 int ret;
559 struct r8192_priv *priv = ieee80211_priv(dev);
561 down(&priv->wx_sem);
563 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
565 up(&priv->wx_sem);
567 return ret;
571 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
572 union iwreq_data *wrqu, char *b)
574 int ret;
575 struct r8192_priv *priv = ieee80211_priv(dev);
577 down(&priv->wx_sem);
579 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
581 up(&priv->wx_sem);
582 return ret;
585 static int r8192_wx_get_name(struct net_device *dev,
586 struct iw_request_info *info,
587 union iwreq_data *wrqu, char *extra)
589 struct r8192_priv *priv = ieee80211_priv(dev);
590 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
594 static int r8192_wx_set_frag(struct net_device *dev,
595 struct iw_request_info *info,
596 union iwreq_data *wrqu, char *extra)
598 struct r8192_priv *priv = ieee80211_priv(dev);
600 if (wrqu->frag.disabled)
601 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
602 else {
603 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
604 wrqu->frag.value > MAX_FRAG_THRESHOLD)
605 return -EINVAL;
607 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
610 return 0;
614 static int r8192_wx_get_frag(struct net_device *dev,
615 struct iw_request_info *info,
616 union iwreq_data *wrqu, char *extra)
618 struct r8192_priv *priv = ieee80211_priv(dev);
620 wrqu->frag.value = priv->ieee80211->fts;
621 wrqu->frag.fixed = 0; /* no auto select */
622 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
624 return 0;
628 static int r8192_wx_set_wap(struct net_device *dev,
629 struct iw_request_info *info,
630 union iwreq_data *awrq,
631 char *extra)
634 int ret;
635 struct r8192_priv *priv = ieee80211_priv(dev);
636 // struct sockaddr *temp = (struct sockaddr *)awrq;
637 down(&priv->wx_sem);
639 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
641 up(&priv->wx_sem);
643 return ret;
648 static int r8192_wx_get_wap(struct net_device *dev,
649 struct iw_request_info *info,
650 union iwreq_data *wrqu, char *extra)
652 struct r8192_priv *priv = ieee80211_priv(dev);
654 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
658 static int r8192_wx_get_enc(struct net_device *dev,
659 struct iw_request_info *info,
660 union iwreq_data *wrqu, char *key)
662 struct r8192_priv *priv = ieee80211_priv(dev);
664 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
667 static int r8192_wx_set_enc(struct net_device *dev,
668 struct iw_request_info *info,
669 union iwreq_data *wrqu, char *key)
671 struct r8192_priv *priv = ieee80211_priv(dev);
672 struct ieee80211_device *ieee = priv->ieee80211;
673 int ret;
675 //u32 TargetContent;
676 u32 hwkey[4]={0,0,0,0};
677 u8 mask=0xff;
678 u32 key_idx=0;
679 //u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff};
680 u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00},
681 {0x00,0x00,0x00,0x00,0x00,0x01},
682 {0x00,0x00,0x00,0x00,0x00,0x02},
683 {0x00,0x00,0x00,0x00,0x00,0x03} };
684 int i;
686 if(!priv->up) return -ENETDOWN;
688 down(&priv->wx_sem);
690 RT_TRACE(COMP_SEC, "Setting SW wep key");
691 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
693 up(&priv->wx_sem);
697 //sometimes, the length is zero while we do not type key value
698 if(wrqu->encoding.length!=0){
700 for(i=0 ; i<4 ; i++){
701 hwkey[i] |= key[4*i+0]&mask;
702 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
703 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
704 hwkey[i] |= (key[4*i+1]&mask)<<8;
705 hwkey[i] |= (key[4*i+2]&mask)<<16;
706 hwkey[i] |= (key[4*i+3]&mask)<<24;
709 #define CONF_WEP40 0x4
710 #define CONF_WEP104 0x14
712 switch (wrqu->encoding.flags & IW_ENCODE_INDEX){
713 case 0: key_idx = ieee->tx_keyidx; break;
714 case 1: key_idx = 0; break;
715 case 2: key_idx = 1; break;
716 case 3: key_idx = 2; break;
717 case 4: key_idx = 3; break;
718 default: break;
721 if(wrqu->encoding.length==0x5){
722 ieee->pairwise_key_type = KEY_TYPE_WEP40;
723 EnableHWSecurityConfig8192(dev);
725 setKey( dev,
726 key_idx, //EntryNo
727 key_idx, //KeyIndex
728 KEY_TYPE_WEP40, //KeyType
729 zero_addr[key_idx],
730 0, //DefaultKey
731 hwkey); //KeyContent
735 else if(wrqu->encoding.length==0xd){
736 ieee->pairwise_key_type = KEY_TYPE_WEP104;
737 EnableHWSecurityConfig8192(dev);
739 setKey( dev,
740 key_idx, //EntryNo
741 key_idx, //KeyIndex
742 KEY_TYPE_WEP104, //KeyType
743 zero_addr[key_idx],
744 0, //DefaultKey
745 hwkey); //KeyContent
748 else printk("wrong type in WEP, not WEP40 and WEP104\n");
752 return ret;
756 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
757 iwreq_data *wrqu, char *p){
759 struct r8192_priv *priv = ieee80211_priv(dev);
760 int *parms=(int *)p;
761 int mode=parms[0];
763 priv->ieee80211->active_scan = mode;
765 return 1;
770 static int r8192_wx_set_retry(struct net_device *dev,
771 struct iw_request_info *info,
772 union iwreq_data *wrqu, char *extra)
774 struct r8192_priv *priv = ieee80211_priv(dev);
775 int err = 0;
777 down(&priv->wx_sem);
779 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
780 wrqu->retry.disabled){
781 err = -EINVAL;
782 goto exit;
784 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
785 err = -EINVAL;
786 goto exit;
789 if(wrqu->retry.value > R8180_MAX_RETRY){
790 err= -EINVAL;
791 goto exit;
793 if (wrqu->retry.flags & IW_RETRY_MAX) {
794 priv->retry_rts = wrqu->retry.value;
795 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
797 }else {
798 priv->retry_data = wrqu->retry.value;
799 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
802 /* FIXME !
803 * We might try to write directly the TX config register
804 * or to restart just the (R)TX process.
805 * I'm unsure if whole reset is really needed
808 rtl8192_commit(dev);
810 if(priv->up){
811 rtl8180_rtx_disable(dev);
812 rtl8180_rx_enable(dev);
813 rtl8180_tx_enable(dev);
817 exit:
818 up(&priv->wx_sem);
820 return err;
823 static int r8192_wx_get_retry(struct net_device *dev,
824 struct iw_request_info *info,
825 union iwreq_data *wrqu, char *extra)
827 struct r8192_priv *priv = ieee80211_priv(dev);
830 wrqu->retry.disabled = 0; /* can't be disabled */
832 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
833 IW_RETRY_LIFETIME)
834 return -EINVAL;
836 if (wrqu->retry.flags & IW_RETRY_MAX) {
837 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
838 wrqu->retry.value = priv->retry_rts;
839 } else {
840 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
841 wrqu->retry.value = priv->retry_data;
843 //printk("returning %d",wrqu->retry.value);
846 return 0;
849 static int r8192_wx_get_sens(struct net_device *dev,
850 struct iw_request_info *info,
851 union iwreq_data *wrqu, char *extra)
853 struct r8192_priv *priv = ieee80211_priv(dev);
854 if(priv->rf_set_sens == NULL)
855 return -1; /* we have not this support for this radio */
856 wrqu->sens.value = priv->sens;
857 return 0;
861 static int r8192_wx_set_sens(struct net_device *dev,
862 struct iw_request_info *info,
863 union iwreq_data *wrqu, char *extra)
866 struct r8192_priv *priv = ieee80211_priv(dev);
868 short err = 0;
869 down(&priv->wx_sem);
870 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
871 if(priv->rf_set_sens == NULL) {
872 err= -1; /* we have not this support for this radio */
873 goto exit;
875 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
876 priv->sens = wrqu->sens.value;
877 else
878 err= -EINVAL;
880 exit:
881 up(&priv->wx_sem);
883 return err;
886 #if (WIRELESS_EXT >= 18)
887 //hw security need to reorganized.
888 static int r8192_wx_set_enc_ext(struct net_device *dev,
889 struct iw_request_info *info,
890 union iwreq_data *wrqu, char *extra)
892 int ret=0;
893 struct r8192_priv *priv = ieee80211_priv(dev);
894 struct ieee80211_device *ieee = priv->ieee80211;
895 //printk("===>%s()\n", __FUNCTION__);
898 down(&priv->wx_sem);
899 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
902 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
903 u8 zero[6] = {0};
904 u32 key[4] = {0};
905 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
906 struct iw_point *encoding = &wrqu->encoding;
907 u8 idx = 0, alg = 0, group = 0;
908 if ((encoding->flags & IW_ENCODE_DISABLED) ||
909 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
910 goto end_hw_sec;
912 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;
913 idx = encoding->flags & IW_ENCODE_INDEX;
914 if (idx)
915 idx --;
916 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
918 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
920 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
921 alg = KEY_TYPE_WEP104;
922 ieee->pairwise_key_type = alg;
923 EnableHWSecurityConfig8192(dev);
925 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
927 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
930 setKey( dev,
931 idx,//EntryNo
932 idx, //KeyIndex
933 alg, //KeyType
934 zero, //MacAddr
935 0, //DefaultKey
936 key); //KeyContent
938 else if (group)
940 ieee->group_key_type = alg;
941 setKey( dev,
942 idx,//EntryNo
943 idx, //KeyIndex
944 alg, //KeyType
945 broadcast_addr, //MacAddr
946 0, //DefaultKey
947 key); //KeyContent
949 else //pairwise key
951 setKey( dev,
952 4,//EntryNo
953 idx, //KeyIndex
954 alg, //KeyType
955 (u8 *)ieee->ap_mac_addr, //MacAddr
956 0, //DefaultKey
957 key); //KeyContent
963 end_hw_sec:
965 up(&priv->wx_sem);
966 return ret;
969 static int r8192_wx_set_auth(struct net_device *dev,
970 struct iw_request_info *info,
971 union iwreq_data *data, char *extra)
973 int ret=0;
974 //printk("====>%s()\n", __FUNCTION__);
975 struct r8192_priv *priv = ieee80211_priv(dev);
976 down(&priv->wx_sem);
977 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
978 up(&priv->wx_sem);
979 return ret;
982 static int r8192_wx_set_mlme(struct net_device *dev,
983 struct iw_request_info *info,
984 union iwreq_data *wrqu, char *extra)
986 //printk("====>%s()\n", __FUNCTION__);
988 int ret=0;
989 struct r8192_priv *priv = ieee80211_priv(dev);
990 down(&priv->wx_sem);
991 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
993 up(&priv->wx_sem);
994 return ret;
996 #endif
997 static int r8192_wx_set_gen_ie(struct net_device *dev,
998 struct iw_request_info *info,
999 union iwreq_data *data, char *extra)
1001 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1002 int ret=0;
1003 struct r8192_priv *priv = ieee80211_priv(dev);
1004 down(&priv->wx_sem);
1005 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1006 up(&priv->wx_sem);
1007 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1008 return ret;
1013 static int dummy(struct net_device *dev, struct iw_request_info *a,
1014 union iwreq_data *wrqu,char *b)
1016 return -1;
1020 static iw_handler r8192_wx_handlers[] =
1022 NULL, /* SIOCSIWCOMMIT */
1023 r8192_wx_get_name, /* SIOCGIWNAME */
1024 dummy, /* SIOCSIWNWID */
1025 dummy, /* SIOCGIWNWID */
1026 r8192_wx_set_freq, /* SIOCSIWFREQ */
1027 r8192_wx_get_freq, /* SIOCGIWFREQ */
1028 r8192_wx_set_mode, /* SIOCSIWMODE */
1029 r8192_wx_get_mode, /* SIOCGIWMODE */
1030 r8192_wx_set_sens, /* SIOCSIWSENS */
1031 r8192_wx_get_sens, /* SIOCGIWSENS */
1032 NULL, /* SIOCSIWRANGE */
1033 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1034 NULL, /* SIOCSIWPRIV */
1035 NULL, /* SIOCGIWPRIV */
1036 NULL, /* SIOCSIWSTATS */
1037 NULL, /* SIOCGIWSTATS */
1038 dummy, /* SIOCSIWSPY */
1039 dummy, /* SIOCGIWSPY */
1040 NULL, /* SIOCGIWTHRSPY */
1041 NULL, /* SIOCWIWTHRSPY */
1042 r8192_wx_set_wap, /* SIOCSIWAP */
1043 r8192_wx_get_wap, /* SIOCGIWAP */
1044 #if (WIRELESS_EXT >= 18)
1045 r8192_wx_set_mlme, /* MLME-- */
1046 #else
1047 NULL,
1048 #endif
1049 dummy, /* SIOCGIWAPLIST -- deprecated */
1050 r8192_wx_set_scan, /* SIOCSIWSCAN */
1051 r8192_wx_get_scan, /* SIOCGIWSCAN */
1052 r8192_wx_set_essid, /* SIOCSIWESSID */
1053 r8192_wx_get_essid, /* SIOCGIWESSID */
1054 dummy, /* SIOCSIWNICKN */
1055 dummy, /* SIOCGIWNICKN */
1056 NULL, /* -- hole -- */
1057 NULL, /* -- hole -- */
1058 r8192_wx_set_rate, /* SIOCSIWRATE */
1059 r8192_wx_get_rate, /* SIOCGIWRATE */
1060 r8192_wx_set_rts, /* SIOCSIWRTS */
1061 r8192_wx_get_rts, /* SIOCGIWRTS */
1062 r8192_wx_set_frag, /* SIOCSIWFRAG */
1063 r8192_wx_get_frag, /* SIOCGIWFRAG */
1064 dummy, /* SIOCSIWTXPOW */
1065 dummy, /* SIOCGIWTXPOW */
1066 r8192_wx_set_retry, /* SIOCSIWRETRY */
1067 r8192_wx_get_retry, /* SIOCGIWRETRY */
1068 r8192_wx_set_enc, /* SIOCSIWENCODE */
1069 r8192_wx_get_enc, /* SIOCGIWENCODE */
1070 r8192_wx_set_power, /* SIOCSIWPOWER */
1071 r8192_wx_get_power, /* SIOCGIWPOWER */
1072 NULL, /*---hole---*/
1073 NULL, /*---hole---*/
1074 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1075 NULL, /* SIOCSIWGENIE */
1077 #if (WIRELESS_EXT >= 18)
1078 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1079 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1080 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
1081 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1082 #else
1083 NULL,
1084 NULL,
1085 NULL,
1086 NULL,
1087 #endif
1088 NULL, /* SIOCSIWPMKSA */
1089 NULL, /*---hole---*/
1094 static const struct iw_priv_args r8192_private_args[] = {
1097 SIOCIWFIRSTPRIV + 0x0,
1098 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1102 SIOCIWFIRSTPRIV + 0x1,
1103 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1107 SIOCIWFIRSTPRIV + 0x2,
1108 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1110 #ifdef JOHN_IOCTL
1113 SIOCIWFIRSTPRIV + 0x3,
1114 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
1118 SIOCIWFIRSTPRIV + 0x4,
1119 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
1123 SIOCIWFIRSTPRIV + 0x5,
1124 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
1128 SIOCIWFIRSTPRIV + 0x6,
1129 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
1133 SIOCIWFIRSTPRIV + 0x7,
1134 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
1138 SIOCIWFIRSTPRIV + 0x8,
1139 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
1143 SIOCIWFIRSTPRIV + 0x9,
1144 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
1147 #endif
1150 SIOCIWFIRSTPRIV + 0x3,
1151 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1158 static iw_handler r8192_private_handler[] = {
1159 // r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */
1160 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
1161 // r8192_wx_set_forceassociate,
1162 // r8192_wx_set_beaconinterval,
1163 // r8192_wx_set_monitor_type,
1164 r8192_wx_set_scan_type,
1165 r8192_wx_set_rawtx,
1166 #ifdef JOHN_IOCTL
1167 r8192_wx_read_regs,
1168 r8192_wx_write_regs,
1169 r8192_wx_read_bb,
1170 r8192_wx_write_bb,
1171 r8192_wx_read_nicb,
1172 r8192_wx_write_nicb,
1173 r8192_wx_get_ap_status,
1174 #endif
1175 //r8192_wx_null,
1176 r8192_wx_force_reset,
1179 //#if WIRELESS_EXT >= 17
1180 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1182 struct r8192_priv *priv = ieee80211_priv(dev);
1183 struct ieee80211_device *ieee = priv->ieee80211;
1184 struct iw_statistics *wstats = &priv->wstats;
1185 int tmp_level = 0;
1186 int tmp_qual = 0;
1187 int tmp_noise = 0;
1188 if(ieee->state < IEEE80211_LINKED)
1190 wstats->qual.qual = 0;
1191 wstats->qual.level = 0;
1192 wstats->qual.noise = 0;
1193 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1194 return wstats;
1197 tmp_level = (&ieee->current_network)->stats.rssi;
1198 tmp_qual = (&ieee->current_network)->stats.signal;
1199 tmp_noise = (&ieee->current_network)->stats.noise;
1200 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1202 wstats->qual.level = tmp_level;
1203 wstats->qual.qual = tmp_qual;
1204 wstats->qual.noise = tmp_noise;
1205 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
1206 return wstats;
1208 //#endif
1211 struct iw_handler_def r8192_wx_handlers_def={
1212 .standard = r8192_wx_handlers,
1213 .num_standard = ARRAY_SIZE(r8192_wx_handlers),
1214 .private = r8192_private_handler,
1215 .num_private = ARRAY_SIZE(r8192_private_handler),
1216 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1217 #if WIRELESS_EXT >= 17
1218 .get_wireless_stats = r8192_get_wireless_stats,
1219 #endif
1220 .private_args = (struct iw_priv_args *)r8192_private_args,