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