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