blob: abae1631a4f04c6099de55c89dd41bbfb513a4f5 [file] [log] [blame]
Jerry Chuang8fc85982009-11-03 07:17:11 -02001/*
2 This file contains wireless extension handlers.
3
4 This is part of rtl8180 OpenSource driver.
Andrea Merello559a4c32013-08-26 13:53:30 +02005 Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com>
Jerry Chuang8fc85982009-11-03 07:17:11 -02006 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
Justin P. Mattockffae3052012-04-30 13:45:41 -070016 We want to thank the Authors of those projects and the Ndiswrapper
Jerry Chuang8fc85982009-11-03 07:17:11 -020017 project Authors.
18*/
19
20#include <linux/string.h>
21#include "r8192U.h"
22#include "r8192U_hw.h"
23
Jerry Chuang8fc85982009-11-03 07:17:11 -020024#include "dot11d.h"
Jerry Chuang8fc85982009-11-03 07:17:11 -020025
26#define RATE_COUNT 12
27u32 rtl8180_rates[] = {1000000,2000000,5500000,11000000,
28 6000000,9000000,12000000,18000000,24000000,36000000,48000000,54000000};
29
30
31#ifndef ENETDOWN
32#define ENETDOWN 1
33#endif
34
35static int r8192_wx_get_freq(struct net_device *dev,
36 struct iw_request_info *a,
37 union iwreq_data *wrqu, char *b)
38{
39 struct r8192_priv *priv = ieee80211_priv(dev);
40
41 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b);
42}
43
44
Jerry Chuang8fc85982009-11-03 07:17:11 -020045static int r8192_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
46 union iwreq_data *wrqu, char *b)
47{
48 struct r8192_priv *priv=ieee80211_priv(dev);
49
50 return ieee80211_wx_get_mode(priv->ieee80211,a,wrqu,b);
51}
52
53
54
55static int r8192_wx_get_rate(struct net_device *dev,
56 struct iw_request_info *info,
57 union iwreq_data *wrqu, char *extra)
58{
59 struct r8192_priv *priv = ieee80211_priv(dev);
60 return ieee80211_wx_get_rate(priv->ieee80211,info,wrqu,extra);
61}
62
63
64
65static int r8192_wx_set_rate(struct net_device *dev,
66 struct iw_request_info *info,
67 union iwreq_data *wrqu, char *extra)
68{
69 int ret;
70 struct r8192_priv *priv = ieee80211_priv(dev);
71
72 down(&priv->wx_sem);
73
74 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra);
75
76 up(&priv->wx_sem);
77
78 return ret;
79}
80
81
82static int r8192_wx_set_rts(struct net_device *dev,
83 struct iw_request_info *info,
84 union iwreq_data *wrqu, char *extra)
85{
86 int ret;
87 struct r8192_priv *priv = ieee80211_priv(dev);
88
89 down(&priv->wx_sem);
90
91 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra);
92
93 up(&priv->wx_sem);
94
95 return ret;
96}
97
98static int r8192_wx_get_rts(struct net_device *dev,
99 struct iw_request_info *info,
100 union iwreq_data *wrqu, char *extra)
101{
102 struct r8192_priv *priv = ieee80211_priv(dev);
103 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra);
104}
105
106static int r8192_wx_set_power(struct net_device *dev,
107 struct iw_request_info *info,
108 union iwreq_data *wrqu, char *extra)
109{
110 int ret;
111 struct r8192_priv *priv = ieee80211_priv(dev);
112
113 down(&priv->wx_sem);
114
115 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra);
116
117 up(&priv->wx_sem);
118
119 return ret;
120}
121
122static int r8192_wx_get_power(struct net_device *dev,
123 struct iw_request_info *info,
124 union iwreq_data *wrqu, char *extra)
125{
126 struct r8192_priv *priv = ieee80211_priv(dev);
127 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra);
128}
129
Jerry Chuang8fc85982009-11-03 07:17:11 -0200130static int r8192_wx_force_reset(struct net_device *dev,
131 struct iw_request_info *info,
132 union iwreq_data *wrqu, char *extra)
133{
134 struct r8192_priv *priv = ieee80211_priv(dev);
135
136 down(&priv->wx_sem);
137
138 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra);
139 priv->force_reset = *extra;
140 up(&priv->wx_sem);
141 return 0;
142
143}
144
145
146static int r8192_wx_set_rawtx(struct net_device *dev,
147 struct iw_request_info *info,
148 union iwreq_data *wrqu, char *extra)
149{
150 struct r8192_priv *priv = ieee80211_priv(dev);
151 int ret;
152
153 down(&priv->wx_sem);
154
155 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra);
156
157 up(&priv->wx_sem);
158
159 return ret;
160
161}
162
163static int r8192_wx_set_crcmon(struct net_device *dev,
164 struct iw_request_info *info,
165 union iwreq_data *wrqu, char *extra)
166{
167 struct r8192_priv *priv = ieee80211_priv(dev);
168 int *parms = (int *)extra;
169 int enable = (parms[0] > 0);
170 short prev = priv->crcmon;
171
172 down(&priv->wx_sem);
173
174 if(enable)
175 priv->crcmon=1;
176 else
177 priv->crcmon=0;
178
179 DMESG("bad CRC in monitor mode are %s",
180 priv->crcmon ? "accepted" : "rejected");
181
182 if(prev != priv->crcmon && priv->up){
183 //rtl8180_down(dev);
184 //rtl8180_up(dev);
185 }
186
187 up(&priv->wx_sem);
188
189 return 0;
190}
191
192static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a,
193 union iwreq_data *wrqu, char *b)
194{
195 struct r8192_priv *priv = ieee80211_priv(dev);
196 int ret;
197 down(&priv->wx_sem);
198
199 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b);
200
201 rtl8192_set_rxconf(dev);
202
203 up(&priv->wx_sem);
204 return ret;
205}
206
Jennifer Naumann0db7a342012-12-05 21:40:19 +0100207struct iw_range_with_scan_capa {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200208 /* Informative stuff (to choose between different interface) */
209 __u32 throughput; /* To give an idea... */
210 /* In theory this value should be the maximum benchmarked
211 * TCP/IP throughput, because with most of these devices the
212 * bit rate is meaningless (overhead an co) to estimate how
213 * fast the connection will go and pick the fastest one.
214 * I suggest people to play with Netperf or any benchmark...
215 */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200216
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200217 /* NWID (or domain id) */
218 __u32 min_nwid; /* Minimal NWID we are able to set */
219 __u32 max_nwid; /* Maximal NWID we are able to set */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200220
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200221 /* Old Frequency (backward compat - moved lower ) */
222 __u16 old_num_channels;
223 __u8 old_num_frequency;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200224
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200225 /* Scan capabilities */
226 __u8 scan_capa;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200227};
228static int rtl8180_wx_get_range(struct net_device *dev,
229 struct iw_request_info *info,
230 union iwreq_data *wrqu, char *extra)
231{
232 struct iw_range *range = (struct iw_range *)extra;
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300233 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200234 struct r8192_priv *priv = ieee80211_priv(dev);
235 u16 val;
236 int i;
237
238 wrqu->data.length = sizeof(*range);
239 memset(range, 0, sizeof(*range));
240
241 /* Let's try to keep this struct in the same order as in
242 * linux/include/wireless.h
243 */
244
245 /* TODO: See what values we can set, and remove the ones we can't
246 * set, or fill them with some default data.
247 */
248
249 /* ~5 Mb/s real (802.11b) */
250 range->throughput = 5 * 1000 * 1000;
251
252 // TODO: Not used in 802.11b?
253// range->min_nwid; /* Minimal NWID we are able to set */
254 // TODO: Not used in 802.11b?
255// range->max_nwid; /* Maximal NWID we are able to set */
256
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200257 /* Old Frequency (backward compat - moved lower ) */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200258// range->old_num_channels;
259// range->old_num_frequency;
260// range->old_freq[6]; /* Filler to keep "version" at the same offset */
261 if(priv->rf_set_sens != NULL)
262 range->sensitivity = priv->max_sens; /* signal level threshold range */
263
264 range->max_qual.qual = 100;
265 /* TODO: Find real max RSSI and stick here */
266 range->max_qual.level = 0;
267 range->max_qual.noise = -98;
268 range->max_qual.updated = 7; /* Updated all three */
269
270 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700271 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200272 range->avg_qual.level = 20 + -98;
273 range->avg_qual.noise = 0;
274 range->avg_qual.updated = 7; /* Updated all three */
275
276 range->num_bitrates = RATE_COUNT;
277
Rui Miguel Silva2930d0b92014-04-28 12:12:54 +0100278 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200279 range->bitrate[i] = rtl8180_rates[i];
Jerry Chuang8fc85982009-11-03 07:17:11 -0200280
281 range->min_frag = MIN_FRAG_THRESHOLD;
282 range->max_frag = MAX_FRAG_THRESHOLD;
283
284 range->min_pmp=0;
285 range->max_pmp = 5000000;
286 range->min_pmt = 0;
287 range->max_pmt = 65535*1000;
288 range->pmp_flags = IW_POWER_PERIOD;
289 range->pmt_flags = IW_POWER_TIMEOUT;
290 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
291
292 range->we_version_compiled = WIRELESS_EXT;
293 range->we_version_source = 16;
294
295// range->retry_capa; /* What retry options are supported */
296// range->retry_flags; /* How to decode max/min retry limit */
297// range->r_time_flags; /* How to decode max/min retry life */
298// range->min_retry; /* Minimal number of retries */
299// range->max_retry; /* Maximal number of retries */
300// range->min_r_time; /* Minimal retry lifetime */
301// range->max_r_time; /* Maximal retry lifetime */
302
303
304 for (i = 0, val = 0; i < 14; i++) {
305
306 // Include only legal frequencies for some countries
Jerry Chuang8fc85982009-11-03 07:17:11 -0200307 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) {
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200308 range->freq[val].i = i + 1;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200309 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
310 range->freq[val].e = 1;
311 val++;
312 } else {
313 // FIXME: do we need to set anything for channels
314 // we don't use ?
315 }
316
317 if (val == IW_MAX_FREQUENCIES)
318 break;
319 }
320 range->num_frequency = val;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200321 range->num_channels = val;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200322 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2|
323 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200324 tmp->scan_capa = 0x01;
325 return 0;
326}
327
328
329static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
330 union iwreq_data *wrqu, char *b)
331{
332 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300333 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200334 int ret = 0;
335
336 if(!priv->up) return -ENETDOWN;
337
338 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true)
339 return -EAGAIN;
340 if (wrqu->data.flags & IW_SCAN_THIS_ESSID)
341 {
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300342 struct iw_scan_req *req = (struct iw_scan_req *)b;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200343 if (req->essid_len)
344 {
345 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid);
346 ieee->current_network.ssid_len = req->essid_len;
347 memcpy(ieee->current_network.ssid, req->essid, req->essid_len);
348 //printk("=====>network ssid:%s\n", ieee->current_network.ssid);
349 }
350 }
351
352 down(&priv->wx_sem);
353 if(priv->ieee80211->state != IEEE80211_LINKED){
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200354 priv->ieee80211->scanning = 0;
355 ieee80211_softmac_scan_syncro(priv->ieee80211);
356 ret = 0;
357 }
Jerry Chuang8fc85982009-11-03 07:17:11 -0200358 else
359 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b);
360 up(&priv->wx_sem);
361 return ret;
362}
363
364
365static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
366 union iwreq_data *wrqu, char *b)
367{
368
369 int ret;
370 struct r8192_priv *priv = ieee80211_priv(dev);
371
372 if(!priv->up) return -ENETDOWN;
373
374 down(&priv->wx_sem);
375
376 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b);
377
378 up(&priv->wx_sem);
379
380 return ret;
381}
382
383static int r8192_wx_set_essid(struct net_device *dev,
384 struct iw_request_info *a,
385 union iwreq_data *wrqu, char *b)
386{
387 struct r8192_priv *priv = ieee80211_priv(dev);
388 int ret;
389 down(&priv->wx_sem);
390
391 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b);
392
393 up(&priv->wx_sem);
394
395 return ret;
396}
397
398
399
400
401static int r8192_wx_get_essid(struct net_device *dev,
402 struct iw_request_info *a,
403 union iwreq_data *wrqu, char *b)
404{
405 int ret;
406 struct r8192_priv *priv = ieee80211_priv(dev);
407
408 down(&priv->wx_sem);
409
410 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b);
411
412 up(&priv->wx_sem);
413
414 return ret;
415}
416
417
418static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a,
419 union iwreq_data *wrqu, char *b)
420{
421 int ret;
422 struct r8192_priv *priv = ieee80211_priv(dev);
423
424 down(&priv->wx_sem);
425
426 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b);
427
428 up(&priv->wx_sem);
429 return ret;
430}
431
432static int r8192_wx_get_name(struct net_device *dev,
433 struct iw_request_info *info,
434 union iwreq_data *wrqu, char *extra)
435{
436 struct r8192_priv *priv = ieee80211_priv(dev);
437 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra);
438}
439
440
441static int r8192_wx_set_frag(struct net_device *dev,
442 struct iw_request_info *info,
443 union iwreq_data *wrqu, char *extra)
444{
445 struct r8192_priv *priv = ieee80211_priv(dev);
446
447 if (wrqu->frag.disabled)
448 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD;
449 else {
450 if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
451 wrqu->frag.value > MAX_FRAG_THRESHOLD)
452 return -EINVAL;
453
454 priv->ieee80211->fts = wrqu->frag.value & ~0x1;
455 }
456
457 return 0;
458}
459
460
461static int r8192_wx_get_frag(struct net_device *dev,
462 struct iw_request_info *info,
463 union iwreq_data *wrqu, char *extra)
464{
465 struct r8192_priv *priv = ieee80211_priv(dev);
466
467 wrqu->frag.value = priv->ieee80211->fts;
468 wrqu->frag.fixed = 0; /* no auto select */
469 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD);
470
471 return 0;
472}
473
474
475static int r8192_wx_set_wap(struct net_device *dev,
476 struct iw_request_info *info,
477 union iwreq_data *awrq,
478 char *extra)
479{
480
481 int ret;
482 struct r8192_priv *priv = ieee80211_priv(dev);
483// struct sockaddr *temp = (struct sockaddr *)awrq;
484 down(&priv->wx_sem);
485
486 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra);
487
488 up(&priv->wx_sem);
489
490 return ret;
491
492}
493
494
495static int r8192_wx_get_wap(struct net_device *dev,
496 struct iw_request_info *info,
497 union iwreq_data *wrqu, char *extra)
498{
499 struct r8192_priv *priv = ieee80211_priv(dev);
500
501 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra);
502}
503
504
505static int r8192_wx_get_enc(struct net_device *dev,
506 struct iw_request_info *info,
507 union iwreq_data *wrqu, char *key)
508{
509 struct r8192_priv *priv = ieee80211_priv(dev);
510
511 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key);
512}
513
514static int r8192_wx_set_enc(struct net_device *dev,
515 struct iw_request_info *info,
516 union iwreq_data *wrqu, char *key)
517{
518 struct r8192_priv *priv = ieee80211_priv(dev);
519 struct ieee80211_device *ieee = priv->ieee80211;
520 int ret;
521
522 //u32 TargetContent;
523 u32 hwkey[4]={0,0,0,0};
524 u8 mask=0xff;
525 u32 key_idx=0;
526 //u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff};
527 u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00},
528 {0x00,0x00,0x00,0x00,0x00,0x01},
529 {0x00,0x00,0x00,0x00,0x00,0x02},
530 {0x00,0x00,0x00,0x00,0x00,0x03} };
531 int i;
532
533 if(!priv->up) return -ENETDOWN;
534
535 down(&priv->wx_sem);
536
537 RT_TRACE(COMP_SEC, "Setting SW wep key");
538 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key);
539
540 up(&priv->wx_sem);
541
542
543
544 //sometimes, the length is zero while we do not type key value
545 if(wrqu->encoding.length!=0){
546
547 for(i=0 ; i<4 ; i++){
548 hwkey[i] |= key[4*i+0]&mask;
549 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00;
550 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00;
551 hwkey[i] |= (key[4*i+1]&mask)<<8;
552 hwkey[i] |= (key[4*i+2]&mask)<<16;
553 hwkey[i] |= (key[4*i+3]&mask)<<24;
554 }
555
556 #define CONF_WEP40 0x4
557 #define CONF_WEP104 0x14
558
Xenia Ragiadakouad638452013-05-12 03:15:08 +0300559 switch (wrqu->encoding.flags & IW_ENCODE_INDEX){
Sebastian Hahn24fbe872012-12-05 21:40:22 +0100560 case 0: key_idx = ieee->tx_keyidx; break;
561 case 1: key_idx = 0; break;
562 case 2: key_idx = 1; break;
563 case 3: key_idx = 2; break;
564 case 4: key_idx = 3; break;
565 default: break;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200566 }
567
568 if(wrqu->encoding.length==0x5){
569 ieee->pairwise_key_type = KEY_TYPE_WEP40;
570 EnableHWSecurityConfig8192(dev);
571
572 setKey( dev,
573 key_idx, //EntryNo
574 key_idx, //KeyIndex
575 KEY_TYPE_WEP40, //KeyType
576 zero_addr[key_idx],
577 0, //DefaultKey
578 hwkey); //KeyContent
579
580 }
581
582 else if(wrqu->encoding.length==0xd){
583 ieee->pairwise_key_type = KEY_TYPE_WEP104;
584 EnableHWSecurityConfig8192(dev);
585
586 setKey( dev,
587 key_idx, //EntryNo
588 key_idx, //KeyIndex
589 KEY_TYPE_WEP104, //KeyType
590 zero_addr[key_idx],
591 0, //DefaultKey
592 hwkey); //KeyContent
593
594 }
595 else printk("wrong type in WEP, not WEP40 and WEP104\n");
596
597 }
598
599 return ret;
600}
601
602
603static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union
604 iwreq_data *wrqu, char *p){
605
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200606 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300607 int *parms=(int *)p;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200608 int mode=parms[0];
609
610 priv->ieee80211->active_scan = mode;
611
612 return 1;
613}
614
615
616
617static int r8192_wx_set_retry(struct net_device *dev,
618 struct iw_request_info *info,
619 union iwreq_data *wrqu, char *extra)
620{
621 struct r8192_priv *priv = ieee80211_priv(dev);
622 int err = 0;
623
624 down(&priv->wx_sem);
625
626 if (wrqu->retry.flags & IW_RETRY_LIFETIME ||
627 wrqu->retry.disabled){
628 err = -EINVAL;
629 goto exit;
630 }
631 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){
632 err = -EINVAL;
633 goto exit;
634 }
635
636 if(wrqu->retry.value > R8180_MAX_RETRY){
637 err= -EINVAL;
638 goto exit;
639 }
640 if (wrqu->retry.flags & IW_RETRY_MAX) {
641 priv->retry_rts = wrqu->retry.value;
642 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value);
643
644 }else {
645 priv->retry_data = wrqu->retry.value;
646 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value);
647 }
648
649 /* FIXME !
650 * We might try to write directly the TX config register
651 * or to restart just the (R)TX process.
652 * I'm unsure if whole reset is really needed
653 */
654
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200655 rtl8192_commit(dev);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200656 /*
657 if(priv->up){
658 rtl8180_rtx_disable(dev);
659 rtl8180_rx_enable(dev);
660 rtl8180_tx_enable(dev);
661
662 }
663 */
664exit:
665 up(&priv->wx_sem);
666
667 return err;
668}
669
670static int r8192_wx_get_retry(struct net_device *dev,
671 struct iw_request_info *info,
672 union iwreq_data *wrqu, char *extra)
673{
674 struct r8192_priv *priv = ieee80211_priv(dev);
675
676
677 wrqu->retry.disabled = 0; /* can't be disabled */
678
679 if ((wrqu->retry.flags & IW_RETRY_TYPE) ==
680 IW_RETRY_LIFETIME)
681 return -EINVAL;
682
683 if (wrqu->retry.flags & IW_RETRY_MAX) {
684 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
685 wrqu->retry.value = priv->retry_rts;
686 } else {
687 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN;
688 wrqu->retry.value = priv->retry_data;
689 }
690 //printk("returning %d",wrqu->retry.value);
691
692
693 return 0;
694}
695
696static int r8192_wx_get_sens(struct net_device *dev,
697 struct iw_request_info *info,
698 union iwreq_data *wrqu, char *extra)
699{
700 struct r8192_priv *priv = ieee80211_priv(dev);
701 if(priv->rf_set_sens == NULL)
702 return -1; /* we have not this support for this radio */
703 wrqu->sens.value = priv->sens;
704 return 0;
705}
706
707
708static int r8192_wx_set_sens(struct net_device *dev,
709 struct iw_request_info *info,
710 union iwreq_data *wrqu, char *extra)
711{
712
713 struct r8192_priv *priv = ieee80211_priv(dev);
714
715 short err = 0;
716 down(&priv->wx_sem);
717 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value);
718 if(priv->rf_set_sens == NULL) {
719 err= -1; /* we have not this support for this radio */
720 goto exit;
721 }
722 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0)
723 priv->sens = wrqu->sens.value;
724 else
725 err= -EINVAL;
726
727exit:
728 up(&priv->wx_sem);
729
730 return err;
731}
732
Jerry Chuang8fc85982009-11-03 07:17:11 -0200733//hw security need to reorganized.
734static int r8192_wx_set_enc_ext(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200735 struct iw_request_info *info,
736 union iwreq_data *wrqu, char *extra)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200737{
738 int ret=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200739 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300740 struct ieee80211_device *ieee = priv->ieee80211;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200741 //printk("===>%s()\n", __FUNCTION__);
742
743
744 down(&priv->wx_sem);
745 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra);
746
747 {
748 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
749 u8 zero[6] = {0};
750 u32 key[4] = {0};
751 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
752 struct iw_point *encoding = &wrqu->encoding;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200753 u8 idx = 0, alg = 0, group = 0;
754 if ((encoding->flags & IW_ENCODE_DISABLED) ||
755 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01
756 goto end_hw_sec;
757
758 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;
759 idx = encoding->flags & IW_ENCODE_INDEX;
760 if (idx)
761 idx --;
762 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY;
763
764 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40))
765 {
766 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) )
767 alg = KEY_TYPE_WEP104;
768 ieee->pairwise_key_type = alg;
769 EnableHWSecurityConfig8192(dev);
770 }
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300771 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1
Jerry Chuang8fc85982009-11-03 07:17:11 -0200772
773 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) )
774 {
775
776 setKey( dev,
777 idx,//EntryNo
778 idx, //KeyIndex
779 alg, //KeyType
780 zero, //MacAddr
781 0, //DefaultKey
782 key); //KeyContent
783 }
784 else if (group)
785 {
786 ieee->group_key_type = alg;
787 setKey( dev,
788 idx,//EntryNo
789 idx, //KeyIndex
790 alg, //KeyType
791 broadcast_addr, //MacAddr
792 0, //DefaultKey
793 key); //KeyContent
794 }
795 else //pairwise key
796 {
797 setKey( dev,
798 4,//EntryNo
799 idx, //KeyIndex
800 alg, //KeyType
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300801 (u8 *)ieee->ap_mac_addr, //MacAddr
Jerry Chuang8fc85982009-11-03 07:17:11 -0200802 0, //DefaultKey
803 key); //KeyContent
804 }
805
806
807 }
808
809end_hw_sec:
810
811 up(&priv->wx_sem);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200812 return ret;
813
814}
815static int r8192_wx_set_auth(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200816 struct iw_request_info *info,
817 union iwreq_data *data, char *extra)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200818{
819 int ret=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200820 //printk("====>%s()\n", __FUNCTION__);
821 struct r8192_priv *priv = ieee80211_priv(dev);
822 down(&priv->wx_sem);
823 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra);
824 up(&priv->wx_sem);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200825 return ret;
826}
827
828static int r8192_wx_set_mlme(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200829 struct iw_request_info *info,
830 union iwreq_data *wrqu, char *extra)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200831{
832 //printk("====>%s()\n", __FUNCTION__);
833
834 int ret=0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200835 struct r8192_priv *priv = ieee80211_priv(dev);
836 down(&priv->wx_sem);
837 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra);
838
839 up(&priv->wx_sem);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200840 return ret;
841}
Joel Pelaez Jorgee6c1ef62014-05-23 14:27:43 -0500842
Jerry Chuang8fc85982009-11-03 07:17:11 -0200843static int r8192_wx_set_gen_ie(struct net_device *dev,
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200844 struct iw_request_info *info,
845 union iwreq_data *data, char *extra)
Jerry Chuang8fc85982009-11-03 07:17:11 -0200846{
847 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length);
848 int ret=0;
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200849 struct r8192_priv *priv = ieee80211_priv(dev);
850 down(&priv->wx_sem);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200851 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200852 up(&priv->wx_sem);
Jerry Chuang8fc85982009-11-03 07:17:11 -0200853 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret);
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200854 return ret;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200855
856
857}
858
859static int dummy(struct net_device *dev, struct iw_request_info *a,
860 union iwreq_data *wrqu,char *b)
861{
862 return -1;
863}
864
865
866static iw_handler r8192_wx_handlers[] =
867{
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200868 NULL, /* SIOCSIWCOMMIT */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100869 r8192_wx_get_name, /* SIOCGIWNAME */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200870 dummy, /* SIOCSIWNWID */
871 dummy, /* SIOCGIWNWID */
872 r8192_wx_set_freq, /* SIOCSIWFREQ */
873 r8192_wx_get_freq, /* SIOCGIWFREQ */
874 r8192_wx_set_mode, /* SIOCSIWMODE */
875 r8192_wx_get_mode, /* SIOCGIWMODE */
876 r8192_wx_set_sens, /* SIOCSIWSENS */
877 r8192_wx_get_sens, /* SIOCGIWSENS */
878 NULL, /* SIOCSIWRANGE */
879 rtl8180_wx_get_range, /* SIOCGIWRANGE */
880 NULL, /* SIOCSIWPRIV */
881 NULL, /* SIOCGIWPRIV */
882 NULL, /* SIOCSIWSTATS */
883 NULL, /* SIOCGIWSTATS */
884 dummy, /* SIOCSIWSPY */
885 dummy, /* SIOCGIWSPY */
886 NULL, /* SIOCGIWTHRSPY */
887 NULL, /* SIOCWIWTHRSPY */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100888 r8192_wx_set_wap, /* SIOCSIWAP */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200889 r8192_wx_get_wap, /* SIOCGIWAP */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200890 r8192_wx_set_mlme, /* MLME-- */
Justin P. Mattock589b3d02012-04-30 07:41:36 -0700891 dummy, /* SIOCGIWAPLIST -- deprecated */
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -0200892 r8192_wx_set_scan, /* SIOCSIWSCAN */
893 r8192_wx_get_scan, /* SIOCGIWSCAN */
894 r8192_wx_set_essid, /* SIOCSIWESSID */
895 r8192_wx_get_essid, /* SIOCGIWESSID */
896 dummy, /* SIOCSIWNICKN */
897 dummy, /* SIOCGIWNICKN */
898 NULL, /* -- hole -- */
899 NULL, /* -- hole -- */
900 r8192_wx_set_rate, /* SIOCSIWRATE */
901 r8192_wx_get_rate, /* SIOCGIWRATE */
902 r8192_wx_set_rts, /* SIOCSIWRTS */
903 r8192_wx_get_rts, /* SIOCGIWRTS */
904 r8192_wx_set_frag, /* SIOCSIWFRAG */
905 r8192_wx_get_frag, /* SIOCGIWFRAG */
906 dummy, /* SIOCSIWTXPOW */
907 dummy, /* SIOCGIWTXPOW */
908 r8192_wx_set_retry, /* SIOCSIWRETRY */
909 r8192_wx_get_retry, /* SIOCGIWRETRY */
910 r8192_wx_set_enc, /* SIOCSIWENCODE */
911 r8192_wx_get_enc, /* SIOCGIWENCODE */
912 r8192_wx_set_power, /* SIOCSIWPOWER */
913 r8192_wx_get_power, /* SIOCGIWPOWER */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200914 NULL, /*---hole---*/
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100915 NULL, /*---hole---*/
916 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */
917 NULL, /* SIOCSIWGENIE */
Jerry Chuang8fc85982009-11-03 07:17:11 -0200918
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100919 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */
920 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */
921 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
922 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */
Sebastian Hahn35997ff2012-12-05 21:40:18 +0100923 NULL, /* SIOCSIWPMKSA */
924 NULL, /*---hole---*/
Jerry Chuang8fc85982009-11-03 07:17:11 -0200925
926};
927
928
929static const struct iw_priv_args r8192_private_args[] = {
930
931 {
932 SIOCIWFIRSTPRIV + 0x0,
933 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc"
934 },
935
936 {
937 SIOCIWFIRSTPRIV + 0x1,
938 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan"
939
940 },
941 {
942 SIOCIWFIRSTPRIV + 0x2,
943 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx"
Xenia Ragiadakouaa0cb592013-10-10 10:43:47 +0300944 },
Jerry Chuang8fc85982009-11-03 07:17:11 -0200945 {
946 SIOCIWFIRSTPRIV + 0x3,
947 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset"
948
949 }
950
951};
952
953
954static iw_handler r8192_private_handler[] = {
955// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */
956 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/
957// r8192_wx_set_forceassociate,
958// r8192_wx_set_beaconinterval,
959// r8192_wx_set_monitor_type,
960 r8192_wx_set_scan_type,
961 r8192_wx_set_rawtx,
Jerry Chuang8fc85982009-11-03 07:17:11 -0200962 //r8192_wx_null,
963 r8192_wx_force_reset,
964};
965
Jerry Chuang8fc85982009-11-03 07:17:11 -0200966struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev)
967{
968 struct r8192_priv *priv = ieee80211_priv(dev);
Xenia Ragiadakoub81c2b02013-05-11 17:22:24 +0300969 struct ieee80211_device *ieee = priv->ieee80211;
970 struct iw_statistics *wstats = &priv->wstats;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200971 int tmp_level = 0;
972 int tmp_qual = 0;
973 int tmp_noise = 0;
974 if(ieee->state < IEEE80211_LINKED)
975 {
976 wstats->qual.qual = 0;
977 wstats->qual.level = 0;
978 wstats->qual.noise = 0;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200979 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200980 return wstats;
981 }
982
983 tmp_level = (&ieee->current_network)->stats.rssi;
984 tmp_qual = (&ieee->current_network)->stats.signal;
985 tmp_noise = (&ieee->current_network)->stats.noise;
986 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise);
987
988 wstats->qual.level = tmp_level;
989 wstats->qual.qual = tmp_qual;
990 wstats->qual.noise = tmp_noise;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200991 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM;
Jerry Chuang8fc85982009-11-03 07:17:11 -0200992 return wstats;
993}
Jerry Chuang8fc85982009-11-03 07:17:11 -0200994
995
996struct iw_handler_def r8192_wx_handlers_def={
997 .standard = r8192_wx_handlers,
Jim Cromieb330f602012-04-10 16:06:41 -0600998 .num_standard = ARRAY_SIZE(r8192_wx_handlers),
Jerry Chuang8fc85982009-11-03 07:17:11 -0200999 .private = r8192_private_handler,
Jim Cromieb330f602012-04-10 16:06:41 -06001000 .num_private = ARRAY_SIZE(r8192_private_handler),
Mauro Carvalho Chehabe4063222009-11-03 07:42:46 -02001001 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args),
Jerry Chuang8fc85982009-11-03 07:17:11 -02001002 .get_wireless_stats = r8192_get_wireless_stats,
Jerry Chuang8fc85982009-11-03 07:17:11 -02001003 .private_args = (struct iw_priv_args *)r8192_private_args,
1004};