Staging: rtl8192e: remove #if 0 sections
[wandboard.git] / drivers / staging / rtl8192e / r8192E_wx.c
blob88ad00db056e3804101fa38f3014bfac3a7101fa
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 "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 down(&priv->wx_sem);
75 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
77 up(&priv->wx_sem);
79 return ret;
83 static int r8192_wx_set_rts(struct net_device *dev,
84 struct iw_request_info *info,
85 union iwreq_data *wrqu, char *extra)
87 int ret;
88 struct r8192_priv *priv = ieee80211_priv(dev);
90 down(&priv->wx_sem);
92 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
94 up(&priv->wx_sem);
96 return ret;
99 static int r8192_wx_get_rts(struct net_device *dev,
100 struct iw_request_info *info,
101 union iwreq_data *wrqu, char *extra)
103 struct r8192_priv *priv = ieee80211_priv(dev);
104 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
107 static int r8192_wx_set_power(struct net_device *dev,
108 struct iw_request_info *info,
109 union iwreq_data *wrqu, char *extra)
111 int ret;
112 struct r8192_priv *priv = ieee80211_priv(dev);
114 down(&priv->wx_sem);
116 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
118 up(&priv->wx_sem);
120 return ret;
123 static int r8192_wx_get_power(struct net_device *dev,
124 struct iw_request_info *info,
125 union iwreq_data *wrqu, char *extra)
127 struct r8192_priv *priv = ieee80211_priv(dev);
128 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
131 #ifdef JOHN_IOCTL
132 u16 read_rtl8225(struct net_device *dev, u8 addr);
133 void write_rtl8225(struct net_device *dev, u8 adr, u16 data);
134 u32 john_read_rtl8225(struct net_device *dev, u8 adr);
135 void _write_rtl8225(struct net_device *dev, u8 adr, u16 data);
137 static int r8192_wx_read_regs(struct net_device *dev,
138 struct iw_request_info *info,
139 union iwreq_data *wrqu, char *extra)
141 struct r8192_priv *priv = ieee80211_priv(dev);
142 u8 addr;
143 u16 data1;
145 down(&priv->wx_sem);
148 get_user(addr,(u8*)wrqu->data.pointer);
149 data1 = read_rtl8225(dev, addr);
150 wrqu->data.length = data1;
152 up(&priv->wx_sem);
153 return 0;
157 static int r8192_wx_write_regs(struct net_device *dev,
158 struct iw_request_info *info,
159 union iwreq_data *wrqu, char *extra)
161 struct r8192_priv *priv = ieee80211_priv(dev);
162 u8 addr;
164 down(&priv->wx_sem);
166 get_user(addr, (u8*)wrqu->data.pointer);
167 write_rtl8225(dev, addr, wrqu->data.length);
169 up(&priv->wx_sem);
170 return 0;
174 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
175 u8 rtl8187_read_phy(struct net_device *dev,u8 adr, u32 data);
177 static int r8192_wx_read_bb(struct net_device *dev,
178 struct iw_request_info *info,
179 union iwreq_data *wrqu, char *extra)
181 struct r8192_priv *priv = ieee80211_priv(dev);
182 u8 databb;
183 #if 0
184 int i;
185 for(i=0;i<12;i++) printk("%8x\n", read_cam(dev, i) );
186 #endif
188 down(&priv->wx_sem);
190 databb = rtl8187_read_phy(dev, (u8)wrqu->data.length, 0x00000000);
191 wrqu->data.length = databb;
193 up(&priv->wx_sem);
194 return 0;
197 void rtl8187_write_phy(struct net_device *dev, u8 adr, u32 data);
198 static int r8192_wx_write_bb(struct net_device *dev,
199 struct iw_request_info *info,
200 union iwreq_data *wrqu, char *extra)
202 struct r8192_priv *priv = ieee80211_priv(dev);
203 u8 databb;
205 down(&priv->wx_sem);
207 get_user(databb, (u8*)wrqu->data.pointer);
208 rtl8187_write_phy(dev, wrqu->data.length, databb);
210 up(&priv->wx_sem);
211 return 0;
216 static int r8192_wx_write_nicb(struct net_device *dev,
217 struct iw_request_info *info,
218 union iwreq_data *wrqu, char *extra)
220 struct r8192_priv *priv = ieee80211_priv(dev);
221 u32 addr;
223 down(&priv->wx_sem);
225 get_user(addr, (u32*)wrqu->data.pointer);
226 write_nic_byte(dev, addr, wrqu->data.length);
228 up(&priv->wx_sem);
229 return 0;
232 static int r8192_wx_read_nicb(struct net_device *dev,
233 struct iw_request_info *info,
234 union iwreq_data *wrqu, char *extra)
236 struct r8192_priv *priv = ieee80211_priv(dev);
237 u32 addr;
238 u16 data1;
240 down(&priv->wx_sem);
242 get_user(addr,(u32*)wrqu->data.pointer);
243 data1 = read_nic_byte(dev, addr);
244 wrqu->data.length = data1;
246 up(&priv->wx_sem);
247 return 0;
250 static int r8192_wx_get_ap_status(struct net_device *dev,
251 struct iw_request_info *info,
252 union iwreq_data *wrqu, char *extra)
254 struct r8192_priv *priv = ieee80211_priv(dev);
255 struct ieee80211_device *ieee = priv->ieee80211;
256 struct ieee80211_network *target;
257 int name_len;
259 down(&priv->wx_sem);
261 //count the length of input ssid
262 for(name_len=0 ; ((char*)wrqu->data.pointer)[name_len]!='\0' ; name_len++);
264 //search for the correspoding info which is received
265 list_for_each_entry(target, &ieee->network_list, list) {
266 if ( (target->ssid_len == name_len) &&
267 (strncmp(target->ssid, (char*)wrqu->data.pointer, name_len)==0)){
268 if(target->wpa_ie_len>0 || target->rsn_ie_len>0 )
269 //set flags=1 to indicate this ap is WPA
270 wrqu->data.flags = 1;
271 else wrqu->data.flags = 0;
274 break;
278 up(&priv->wx_sem);
279 return 0;
284 #endif
286 static int r8192_wx_set_rawtx(struct net_device *dev,
287 struct iw_request_info *info,
288 union iwreq_data *wrqu, char *extra)
290 struct r8192_priv *priv = ieee80211_priv(dev);
291 int ret;
293 down(&priv->wx_sem);
295 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
297 up(&priv->wx_sem);
299 return ret;
303 static int r8192_wx_force_reset(struct net_device *dev,
304 struct iw_request_info *info,
305 union iwreq_data *wrqu, char *extra)
307 struct r8192_priv *priv = ieee80211_priv(dev);
309 down(&priv->wx_sem);
311 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
312 priv->force_reset = *extra;
313 up(&priv->wx_sem);
314 return 0;
319 static int r8192_wx_set_crcmon(struct net_device *dev,
320 struct iw_request_info *info,
321 union iwreq_data *wrqu, char *extra)
323 struct r8192_priv *priv = ieee80211_priv(dev);
324 int *parms = (int *)extra;
325 int enable = (parms[0] > 0);
326 short prev = priv->crcmon;
328 down(&priv->wx_sem);
330 if(enable)
331 priv->crcmon=1;
332 else
333 priv->crcmon=0;
335 DMESG("bad CRC in monitor mode are %s",
336 priv->crcmon ? "accepted" : "rejected");
338 if(prev != priv->crcmon && priv->up){
339 //rtl8180_down(dev);
340 //rtl8180_up(dev);
343 up(&priv->wx_sem);
345 return 0;
348 static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
349 union iwreq_data *wrqu, char *b)
351 struct r8192_priv *priv = ieee80211_priv(dev);
352 RT_RF_POWER_STATE rtState;
353 int ret;
355 rtState = priv->ieee80211->eRFPowerState;
356 down(&priv->wx_sem);
357 #ifdef ENABLE_IPS
358 if(wrqu->mode == IW_MODE_ADHOC){
360 if(priv->ieee80211->PowerSaveControl.bInactivePs){
361 if(rtState == eRfOff){
362 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
364 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
365 up(&priv->wx_sem);
366 return -1;
368 else{
369 printk("=========>%s(): IPSLeave\n",__FUNCTION__);
370 IPSLeave(dev);
375 #endif
376 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
378 //rtl8187_set_rxconf(dev);
380 up(&priv->wx_sem);
381 return ret;
384 struct iw_range_with_scan_capa
386 /* Informative stuff (to choose between different interface) */
387 __u32 throughput; /* To give an idea... */
388 /* In theory this value should be the maximum benchmarked
389 * TCP/IP throughput, because with most of these devices the
390 * bit rate is meaningless (overhead an co) to estimate how
391 * fast the connection will go and pick the fastest one.
392 * I suggest people to play with Netperf or any benchmark...
395 /* NWID (or domain id) */
396 __u32 min_nwid; /* Minimal NWID we are able to set */
397 __u32 max_nwid; /* Maximal NWID we are able to set */
399 /* Old Frequency (backward compat - moved lower ) */
400 __u16 old_num_channels;
401 __u8 old_num_frequency;
403 /* Scan capabilities */
404 __u8 scan_capa;
406 static int rtl8180_wx_get_range(struct net_device *dev,
407 struct iw_request_info *info,
408 union iwreq_data *wrqu, char *extra)
410 struct iw_range *range = (struct iw_range *)extra;
411 struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range;
412 struct r8192_priv *priv = ieee80211_priv(dev);
413 u16 val;
414 int i;
416 wrqu->data.length = sizeof(*range);
417 memset(range, 0, sizeof(*range));
419 /* Let's try to keep this struct in the same order as in
420 * linux/include/wireless.h
423 /* TODO: See what values we can set, and remove the ones we can't
424 * set, or fill them with some default data.
427 /* ~5 Mb/s real (802.11b) */
428 range->throughput = 5 * 1000 * 1000;
430 // TODO: Not used in 802.11b?
431 // range->min_nwid; /* Minimal NWID we are able to set */
432 // TODO: Not used in 802.11b?
433 // range->max_nwid; /* Maximal NWID we are able to set */
435 /* Old Frequency (backward compat - moved lower ) */
436 // range->old_num_channels;
437 // range->old_num_frequency;
438 // range->old_freq[6]; /* Filler to keep "version" at the same offset */
439 if(priv->rf_set_sens != NULL)
440 range->sensitivity = priv->max_sens; /* signal level threshold range */
442 range->max_qual.qual = 100;
443 /* TODO: Find real max RSSI and stick here */
444 range->max_qual.level = 0;
445 range->max_qual.noise = -98;
446 range->max_qual.updated = 7; /* Updated all three */
448 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
449 /* TODO: Find real 'good' to 'bad' threshol value for RSSI */
450 range->avg_qual.level = 20 + -98;
451 range->avg_qual.noise = 0;
452 range->avg_qual.updated = 7; /* Updated all three */
454 range->num_bitrates = RATE_COUNT;
456 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) {
457 range->bitrate[i] = rtl8180_rates[i];
460 range->min_frag = MIN_FRAG_THRESHOLD;
461 range->max_frag = MAX_FRAG_THRESHOLD;
463 range->min_pmp=0;
464 range->max_pmp = 5000000;
465 range->min_pmt = 0;
466 range->max_pmt = 65535*1000;
467 range->pmp_flags = IW_POWER_PERIOD;
468 range->pmt_flags = IW_POWER_TIMEOUT;
469 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
470 range->we_version_compiled = WIRELESS_EXT;
471 range->we_version_source = 16;
473 // range->retry_capa; /* What retry options are supported */
474 // range->retry_flags; /* How to decode max/min retry limit */
475 // range->r_time_flags; /* How to decode max/min retry life */
476 // range->min_retry; /* Minimal number of retries */
477 // range->max_retry; /* Maximal number of retries */
478 // range->min_r_time; /* Minimal retry lifetime */
479 // range->max_r_time; /* Maximal retry lifetime */
482 for (i = 0, val = 0; i < 14; i++) {
484 // Include only legal frequencies for some countries
485 #ifdef ENABLE_DOT11D
486 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
487 #else
488 if ((priv->ieee80211->channel_map)[i+1]) {
489 #endif
490 range->freq[val].i = i + 1;
491 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
492 range->freq[val].e = 1;
493 val++;
494 } else {
495 // FIXME: do we need to set anything for channels
496 // we don't use ?
499 if (val == IW_MAX_FREQUENCIES)
500 break;
502 range->num_frequency = val;
503 range->num_channels = val;
504 #if WIRELESS_EXT > 17
505 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
506 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
507 #endif
508 tmp->scan_capa = 0x01;
509 return 0;
513 static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
514 union iwreq_data *wrqu, char *b)
516 struct r8192_priv *priv = ieee80211_priv(dev);
517 struct ieee80211_device* ieee = priv->ieee80211;
518 RT_RF_POWER_STATE rtState;
519 int ret;
520 rtState = priv->ieee80211->eRFPowerState;
521 if(!priv->up) return -ENETDOWN;
522 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
523 return -EAGAIN;
525 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
527 struct iw_scan_req* req = (struct iw_scan_req*)b;
528 if (req->essid_len)
530 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
531 ieee->current_network.ssid_len = req->essid_len;
532 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
533 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
537 down(&priv->wx_sem);
538 #ifdef ENABLE_IPS
539 priv->ieee80211->actscanning = true;
540 if(priv->ieee80211->state != IEEE80211_LINKED){
541 if(priv->ieee80211->PowerSaveControl.bInactivePs){
542 if(rtState == eRfOff){
543 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
545 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
546 up(&priv->wx_sem);
547 return -1;
549 else{
550 printk("=========>%s(): IPSLeave\n",__FUNCTION__);
551 IPSLeave(dev);
555 priv->ieee80211->scanning = 0;
556 ieee80211_softmac_scan_syncro(priv->ieee80211);
557 ret = 0;
559 else
560 #else
562 if(priv->ieee80211->state != IEEE80211_LINKED){
563 priv->ieee80211->scanning = 0;
564 ieee80211_softmac_scan_syncro(priv->ieee80211);
565 ret = 0;
567 else
568 #endif
569 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
571 up(&priv->wx_sem);
572 return ret;
576 static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
577 union iwreq_data *wrqu, char *b)
580 int ret;
581 struct r8192_priv *priv = ieee80211_priv(dev);
583 if(!priv->up) return -ENETDOWN;
585 down(&priv->wx_sem);
587 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
589 up(&priv->wx_sem);
591 return ret;
594 static int r8192_wx_set_essid(struct net_device *dev,
595 struct iw_request_info *a,
596 union iwreq_data *wrqu, char *b)
598 struct r8192_priv *priv = ieee80211_priv(dev);
599 RT_RF_POWER_STATE rtState;
600 int ret;
602 rtState = priv->ieee80211->eRFPowerState;
603 down(&priv->wx_sem);
604 #ifdef ENABLE_IPS
605 if(priv->ieee80211->PowerSaveControl.bInactivePs){
606 if(rtState == eRfOff){
607 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS)
609 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__);
610 up(&priv->wx_sem);
611 return -1;
613 else{
614 printk("=========>%s(): IPSLeave\n",__FUNCTION__);
615 IPSLeave(dev);
619 #endif
620 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
622 up(&priv->wx_sem);
624 return ret;
630 static int r8192_wx_get_essid(struct net_device *dev,
631 struct iw_request_info *a,
632 union iwreq_data *wrqu, char *b)
634 int ret;
635 struct r8192_priv *priv = ieee80211_priv(dev);
637 down(&priv->wx_sem);
639 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
641 up(&priv->wx_sem);
643 return ret;
647 static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
648 union iwreq_data *wrqu, char *b)
650 int ret;
651 struct r8192_priv *priv = ieee80211_priv(dev);
653 down(&priv->wx_sem);
655 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
657 up(&priv->wx_sem);
658 return ret;
661 static int r8192_wx_get_name(struct net_device *dev,
662 struct iw_request_info *info,
663 union iwreq_data *wrqu, char *extra)
665 struct r8192_priv *priv = ieee80211_priv(dev);
666 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
670 static int r8192_wx_set_frag(struct net_device *dev,
671 struct iw_request_info *info,
672 union iwreq_data *wrqu, char *extra)
674 struct r8192_priv *priv = ieee80211_priv(dev);
676 if (wrqu->frag.disabled)
677 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
678 else {
679 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
680 wrqu->frag.value > MAX_FRAG_THRESHOLD)
681 return -EINVAL;
683 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
686 return 0;
690 static int r8192_wx_get_frag(struct net_device *dev,
691 struct iw_request_info *info,
692 union iwreq_data *wrqu, char *extra)
694 struct r8192_priv *priv = ieee80211_priv(dev);
696 wrqu->frag.value = priv->ieee80211->fts;
697 wrqu->frag.fixed = 0; /* no auto select */
698 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
700 return 0;
704 static int r8192_wx_set_wap(struct net_device *dev,
705 struct iw_request_info *info,
706 union iwreq_data *awrq,
707 char *extra)
710 int ret;
711 struct r8192_priv *priv = ieee80211_priv(dev);
712 // struct sockaddr *temp = (struct sockaddr *)awrq;
714 down(&priv->wx_sem);
716 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
718 up(&priv->wx_sem);
720 return ret;
725 static int r8192_wx_get_wap(struct net_device *dev,
726 struct iw_request_info *info,
727 union iwreq_data *wrqu, char *extra)
729 struct r8192_priv *priv = ieee80211_priv(dev);
731 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
735 static int r8192_wx_get_enc(struct net_device *dev,
736 struct iw_request_info *info,
737 union iwreq_data *wrqu, char *key)
739 struct r8192_priv *priv = ieee80211_priv(dev);
741 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
744 static int r8192_wx_set_enc(struct net_device *dev,
745 struct iw_request_info *info,
746 union iwreq_data *wrqu, char *key)
748 struct r8192_priv *priv = ieee80211_priv(dev);
749 int ret;
751 struct ieee80211_device *ieee = priv->ieee80211;
752 //u32 TargetContent;
753 u32 hwkey[4]={0,0,0,0};
754 u8 mask=0xff;
755 u32 key_idx=0;
756 u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00},
757 {0x00,0x00,0x00,0x00,0x00,0x01},
758 {0x00,0x00,0x00,0x00,0x00,0x02},
759 {0x00,0x00,0x00,0x00,0x00,0x03} };
760 int i;
762 if(!priv->up) return -ENETDOWN;
764 down(&priv->wx_sem);
766 RT_TRACE(COMP_SEC, "Setting SW wep key");
767 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
769 up(&priv->wx_sem);
772 //sometimes, the length is zero while we do not type key value
773 if(wrqu->encoding.length!=0){
775 for(i=0 ; i<4 ; i++){
776 hwkey[i] |= key[4*i+0]&mask;
777 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
778 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
779 hwkey[i] |= (key[4*i+1]&mask)<<8;
780 hwkey[i] |= (key[4*i+2]&mask)<<16;
781 hwkey[i] |= (key[4*i+3]&mask)<<24;
784 #define CONF_WEP40 0x4
785 #define CONF_WEP104 0x14
787 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){
788 case 0: key_idx = ieee->tx_keyidx; break;
789 case 1: key_idx = 0; break;
790 case 2: key_idx = 1; break;
791 case 3: key_idx = 2; break;
792 case 4: key_idx = 3; break;
793 default: break;
796 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags);
797 if(wrqu->encoding.length==0x5){
798 ieee->pairwise_key_type = KEY_TYPE_WEP40;
799 EnableHWSecurityConfig8192(dev);
800 setKey( dev,
801 key_idx, //EntryNo
802 key_idx, //KeyIndex
803 KEY_TYPE_WEP40, //KeyType
804 zero_addr[key_idx],
805 0, //DefaultKey
806 hwkey); //KeyContent
808 #if 0
809 if(key_idx == 0){
811 //write_nic_byte(dev, SECR, 7);
812 setKey( dev,
813 4, //EntryNo
814 key_idx, //KeyIndex
815 KEY_TYPE_WEP40, //KeyType
816 broadcast_addr, //addr
817 0, //DefaultKey
818 hwkey); //KeyContent
820 #endif
823 else if(wrqu->encoding.length==0xd){
824 ieee->pairwise_key_type = KEY_TYPE_WEP104;
825 EnableHWSecurityConfig8192(dev);
826 setKey( dev,
827 key_idx, //EntryNo
828 key_idx, //KeyIndex
829 KEY_TYPE_WEP104, //KeyType
830 zero_addr[key_idx],
831 0, //DefaultKey
832 hwkey); //KeyContent
833 #if 0
834 if(key_idx == 0){
836 //write_nic_byte(dev, SECR, 7);
837 setKey( dev,
838 4, //EntryNo
839 key_idx, //KeyIndex
840 KEY_TYPE_WEP104, //KeyType
841 broadcast_addr, //addr
842 0, //DefaultKey
843 hwkey); //KeyContent
845 #endif
847 else printk("wrong type in WEP, not WEP40 and WEP104\n");
852 #if 0
853 //consider the setting different key index situation
854 //wrqu->encoding.flags = 801 means that we set key with index "1"
855 if(wrqu->encoding.length==0 && (wrqu->encoding.flags >>8) == 0x8 ){
856 printk("===>1\n");
857 //write_nic_byte(dev, SECR, 7);
858 EnableHWSecurityConfig8192(dev);
859 //copy wpa config from default key(key0~key3) to broadcast key(key5)
861 key_idx = (wrqu->encoding.flags & 0xf)-1 ;
862 write_cam(dev, (4*6), 0xffff0000|read_cam(dev, key_idx*6) );
863 write_cam(dev, (4*6)+1, 0xffffffff);
864 write_cam(dev, (4*6)+2, read_cam(dev, (key_idx*6)+2) );
865 write_cam(dev, (4*6)+3, read_cam(dev, (key_idx*6)+3) );
866 write_cam(dev, (4*6)+4, read_cam(dev, (key_idx*6)+4) );
867 write_cam(dev, (4*6)+5, read_cam(dev, (key_idx*6)+5) );
869 #endif
871 return ret;
875 static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
876 iwreq_data *wrqu, char *p){
878 struct r8192_priv *priv = ieee80211_priv(dev);
879 int *parms=(int*)p;
880 int mode=parms[0];
882 priv->ieee80211->active_scan = mode;
884 return 1;
889 static int r8192_wx_set_retry(struct net_device *dev,
890 struct iw_request_info *info,
891 union iwreq_data *wrqu, char *extra)
893 struct r8192_priv *priv = ieee80211_priv(dev);
894 int err = 0;
896 down(&priv->wx_sem);
898 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
899 wrqu->retry.disabled){
900 err = -EINVAL;
901 goto exit;
903 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
904 err = -EINVAL;
905 goto exit;
908 if(wrqu->retry.value > R8180_MAX_RETRY){
909 err= -EINVAL;
910 goto exit;
912 if (wrqu->retry.flags & IW_RETRY_MAX) {
913 priv->retry_rts = wrqu->retry.value;
914 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
916 }else {
917 priv->retry_data = wrqu->retry.value;
918 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
921 /* FIXME !
922 * We might try to write directly the TX config register
923 * or to restart just the (R)TX process.
924 * I'm unsure if whole reset is really needed
927 rtl8192_commit(dev);
929 if(priv->up){
930 rtl8180_rtx_disable(dev);
931 rtl8180_rx_enable(dev);
932 rtl8180_tx_enable(dev);
936 exit:
937 up(&priv->wx_sem);
939 return err;
942 static int r8192_wx_get_retry(struct net_device *dev,
943 struct iw_request_info *info,
944 union iwreq_data *wrqu, char *extra)
946 struct r8192_priv *priv = ieee80211_priv(dev);
949 wrqu->retry.disabled = 0; /* can't be disabled */
951 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
952 IW_RETRY_LIFETIME)
953 return -EINVAL;
955 if (wrqu->retry.flags & IW_RETRY_MAX) {
956 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX;
957 wrqu->retry.value = priv->retry_rts;
958 } else {
959 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN;
960 wrqu->retry.value = priv->retry_data;
962 //DMESG("returning %d",wrqu->retry.value);
965 return 0;
968 static int r8192_wx_get_sens(struct net_device *dev,
969 struct iw_request_info *info,
970 union iwreq_data *wrqu, char *extra)
972 struct r8192_priv *priv = ieee80211_priv(dev);
973 if(priv->rf_set_sens == NULL)
974 return -1; /* we have not this support for this radio */
975 wrqu->sens.value = priv->sens;
976 return 0;
980 static int r8192_wx_set_sens(struct net_device *dev,
981 struct iw_request_info *info,
982 union iwreq_data *wrqu, char *extra)
985 struct r8192_priv *priv = ieee80211_priv(dev);
987 short err = 0;
988 down(&priv->wx_sem);
989 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
990 if(priv->rf_set_sens == NULL) {
991 err= -1; /* we have not this support for this radio */
992 goto exit;
994 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
995 priv->sens = wrqu->sens.value;
996 else
997 err= -EINVAL;
999 exit:
1000 up(&priv->wx_sem);
1002 return err;
1005 #if (WIRELESS_EXT >= 18)
1006 static int r8192_wx_set_enc_ext(struct net_device *dev,
1007 struct iw_request_info *info,
1008 union iwreq_data *wrqu, char *extra)
1010 int ret=0;
1011 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1012 struct r8192_priv *priv = ieee80211_priv(dev);
1013 struct ieee80211_device* ieee = priv->ieee80211;
1015 down(&priv->wx_sem);
1016 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra);
1019 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
1020 u8 zero[6] = {0};
1021 u32 key[4] = {0};
1022 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
1023 struct iw_point *encoding = &wrqu->encoding;
1024 #if 0
1025 static u8 CAM_CONST_ADDR[4][6] = {
1026 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
1027 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
1028 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
1029 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03}};
1030 #endif
1031 u8 idx = 0, alg = 0, group = 0;
1032 if ((encoding->flags & IW_ENCODE_DISABLED) ||
1033 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
1035 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA;
1036 CamResetAllEntry(dev);
1037 goto end_hw_sec;
1039 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;
1040 idx = encoding->flags & IW_ENCODE_INDEX;
1041 if (idx)
1042 idx --;
1043 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
1045 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
1047 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
1048 alg = KEY_TYPE_WEP104;
1049 ieee->pairwise_key_type = alg;
1050 EnableHWSecurityConfig8192(dev);
1052 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
1054 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
1056 if (ext->key_len == 13)
1057 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104;
1058 setKey( dev,
1059 idx,//EntryNo
1060 idx, //KeyIndex
1061 alg, //KeyType
1062 zero, //MacAddr
1063 0, //DefaultKey
1064 key); //KeyContent
1066 else if (group)
1068 ieee->group_key_type = alg;
1069 setKey( dev,
1070 idx,//EntryNo
1071 idx, //KeyIndex
1072 alg, //KeyType
1073 broadcast_addr, //MacAddr
1074 0, //DefaultKey
1075 key); //KeyContent
1077 else //pairwise key
1079 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){
1080 write_nic_byte(dev, 0x173, 1); //fix aes bug
1082 setKey( dev,
1083 4,//EntryNo
1084 idx, //KeyIndex
1085 alg, //KeyType
1086 (u8*)ieee->ap_mac_addr, //MacAddr
1087 0, //DefaultKey
1088 key); //KeyContent
1094 end_hw_sec:
1095 up(&priv->wx_sem);
1096 #endif
1097 return ret;
1100 static int r8192_wx_set_auth(struct net_device *dev,
1101 struct iw_request_info *info,
1102 union iwreq_data *data, char *extra)
1104 int ret=0;
1105 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1106 //printk("====>%s()\n", __FUNCTION__);
1107 struct r8192_priv *priv = ieee80211_priv(dev);
1108 down(&priv->wx_sem);
1109 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
1110 up(&priv->wx_sem);
1111 #endif
1112 return ret;
1115 static int r8192_wx_set_mlme(struct net_device *dev,
1116 struct iw_request_info *info,
1117 union iwreq_data *wrqu, char *extra)
1119 //printk("====>%s()\n", __FUNCTION__);
1121 int ret=0;
1122 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1123 struct r8192_priv *priv = ieee80211_priv(dev);
1124 down(&priv->wx_sem);
1125 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
1126 up(&priv->wx_sem);
1127 #endif
1128 return ret;
1130 #endif
1131 static int r8192_wx_set_gen_ie(struct net_device *dev,
1132 struct iw_request_info *info,
1133 union iwreq_data *data, char *extra)
1135 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
1136 int ret=0;
1137 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1138 struct r8192_priv *priv = ieee80211_priv(dev);
1139 down(&priv->wx_sem);
1140 #if 1
1141 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
1142 #endif
1143 up(&priv->wx_sem);
1144 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
1145 #endif
1146 return ret;
1151 static int dummy(struct net_device *dev, struct iw_request_info *a,
1152 union iwreq_data *wrqu,char *b)
1154 return -1;
1158 static iw_handler r8192_wx_handlers[] =
1160 NULL, /* SIOCSIWCOMMIT */
1161 r8192_wx_get_name, /* SIOCGIWNAME */
1162 dummy, /* SIOCSIWNWID */
1163 dummy, /* SIOCGIWNWID */
1164 r8192_wx_set_freq, /* SIOCSIWFREQ */
1165 r8192_wx_get_freq, /* SIOCGIWFREQ */
1166 r8192_wx_set_mode, /* SIOCSIWMODE */
1167 r8192_wx_get_mode, /* SIOCGIWMODE */
1168 r8192_wx_set_sens, /* SIOCSIWSENS */
1169 r8192_wx_get_sens, /* SIOCGIWSENS */
1170 NULL, /* SIOCSIWRANGE */
1171 rtl8180_wx_get_range, /* SIOCGIWRANGE */
1172 NULL, /* SIOCSIWPRIV */
1173 NULL, /* SIOCGIWPRIV */
1174 NULL, /* SIOCSIWSTATS */
1175 NULL, /* SIOCGIWSTATS */
1176 dummy, /* SIOCSIWSPY */
1177 dummy, /* SIOCGIWSPY */
1178 NULL, /* SIOCGIWTHRSPY */
1179 NULL, /* SIOCWIWTHRSPY */
1180 r8192_wx_set_wap, /* SIOCSIWAP */
1181 r8192_wx_get_wap, /* SIOCGIWAP */
1182 #if (WIRELESS_EXT >= 18)
1183 r8192_wx_set_mlme, /* MLME-- */
1184 #else
1185 NULL,
1186 #endif
1187 dummy, /* SIOCGIWAPLIST -- depricated */
1188 r8192_wx_set_scan, /* SIOCSIWSCAN */
1189 r8192_wx_get_scan, /* SIOCGIWSCAN */
1190 r8192_wx_set_essid, /* SIOCSIWESSID */
1191 r8192_wx_get_essid, /* SIOCGIWESSID */
1192 dummy, /* SIOCSIWNICKN */
1193 dummy, /* SIOCGIWNICKN */
1194 NULL, /* -- hole -- */
1195 NULL, /* -- hole -- */
1196 r8192_wx_set_rate, /* SIOCSIWRATE */
1197 r8192_wx_get_rate, /* SIOCGIWRATE */
1198 r8192_wx_set_rts, /* SIOCSIWRTS */
1199 r8192_wx_get_rts, /* SIOCGIWRTS */
1200 r8192_wx_set_frag, /* SIOCSIWFRAG */
1201 r8192_wx_get_frag, /* SIOCGIWFRAG */
1202 dummy, /* SIOCSIWTXPOW */
1203 dummy, /* SIOCGIWTXPOW */
1204 r8192_wx_set_retry, /* SIOCSIWRETRY */
1205 r8192_wx_get_retry, /* SIOCGIWRETRY */
1206 r8192_wx_set_enc, /* SIOCSIWENCODE */
1207 r8192_wx_get_enc, /* SIOCGIWENCODE */
1208 r8192_wx_set_power, /* SIOCSIWPOWER */
1209 r8192_wx_get_power, /* SIOCGIWPOWER */
1210 NULL, /*---hole---*/
1211 NULL, /*---hole---*/
1212 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
1213 NULL, /* SIOCSIWGENIE */
1214 #if (WIRELESS_EXT >= 18)
1215 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
1216 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
1217 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
1218 #else
1219 NULL,
1220 NULL,
1221 NULL,
1222 #endif
1223 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
1224 NULL, /* SIOCSIWPMKSA */
1225 NULL, /*---hole---*/
1230 static const struct iw_priv_args r8192_private_args[] = {
1233 SIOCIWFIRSTPRIV + 0x0,
1234 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
1238 SIOCIWFIRSTPRIV + 0x1,
1239 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
1243 SIOCIWFIRSTPRIV + 0x2,
1244 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
1246 #ifdef JOHN_IOCTL
1249 SIOCIWFIRSTPRIV + 0x3,
1250 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readRF"
1254 SIOCIWFIRSTPRIV + 0x4,
1255 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeRF"
1259 SIOCIWFIRSTPRIV + 0x5,
1260 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readBB"
1264 SIOCIWFIRSTPRIV + 0x6,
1265 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writeBB"
1269 SIOCIWFIRSTPRIV + 0x7,
1270 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "readnicb"
1274 SIOCIWFIRSTPRIV + 0x8,
1275 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "writenicb"
1279 SIOCIWFIRSTPRIV + 0x9,
1280 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
1283 #endif
1286 SIOCIWFIRSTPRIV + 0x3,
1287 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
1294 static iw_handler r8192_private_handler[] = {
1295 // r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */
1296 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
1297 // r8192_wx_set_forceassociate,
1298 // r8192_wx_set_beaconinterval,
1299 // r8192_wx_set_monitor_type,
1300 r8192_wx_set_scan_type,
1301 r8192_wx_set_rawtx,
1302 #ifdef JOHN_IOCTL
1303 r8192_wx_read_regs,
1304 r8192_wx_write_regs,
1305 r8192_wx_read_bb,
1306 r8192_wx_write_bb,
1307 r8192_wx_read_nicb,
1308 r8192_wx_write_nicb,
1309 r8192_wx_get_ap_status
1310 #endif
1311 r8192_wx_force_reset,
1314 //#if WIRELESS_EXT >= 17
1315 struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
1317 struct r8192_priv *priv = ieee80211_priv(dev);
1318 struct ieee80211_device* ieee = priv->ieee80211;
1319 struct iw_statistics* wstats = &priv->wstats;
1320 int tmp_level = 0;
1321 int tmp_qual = 0;
1322 int tmp_noise = 0;
1323 if(ieee->state < IEEE80211_LINKED)
1325 wstats->qual.qual = 0;
1326 wstats->qual.level = 0;
1327 wstats->qual.noise = 0;
1328 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
1329 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1330 #else
1331 wstats->qual.updated = 0x0f;
1332 #endif
1333 return wstats;
1336 tmp_level = (&ieee->current_network)->stats.rssi;
1337 tmp_qual = (&ieee->current_network)->stats.signal;
1338 tmp_noise = (&ieee->current_network)->stats.noise;
1339 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
1341 wstats->qual.level = tmp_level;
1342 wstats->qual.qual = tmp_qual;
1343 wstats->qual.noise = tmp_noise;
1344 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
1345 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
1346 #else
1347 wstats->qual.updated = 0x0f;
1348 #endif
1349 return wstats;
1351 //#endif
1354 struct iw_handler_def r8192_wx_handlers_def={
1355 .standard = r8192_wx_handlers,
1356 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler),
1357 .private = r8192_private_handler,
1358 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler),
1359 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
1360 #if WIRELESS_EXT >= 17
1361 .get_wireless_stats = r8192_get_wireless_stats,
1362 #endif
1363 .private_args = (struct iw_priv_args *)r8192_private_args,