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#include <linux/string.h> 21#include "r8192E.h" 22#include "r8192E_hw.h" 23#include "r8192E_wx.h" 24#ifdef ENABLE_DOT11D 25#include "ieee80211/dot11d.h" 26#endif 27 28#define RATE_COUNT 12 29static const u32 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 36static int r8192_wx_get_freq(struct net_device *dev, 37 struct iw_request_info *a, 38 union iwreq_data *wrqu, char *b) 39{ 40 struct r8192_priv *priv = ieee80211_priv(dev); 41 42 return ieee80211_wx_get_freq(priv->ieee80211,a,wrqu,b); 43} 44 45 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 if(priv->bHwRadioOff == true) 74 return 0; 75 76 down(&priv->wx_sem); 77 78 ret = ieee80211_wx_set_rate(priv->ieee80211,info,wrqu,extra); 79 80 up(&priv->wx_sem); 81 82 return ret; 83} 84 85 86static int r8192_wx_set_rts(struct net_device *dev, 87 struct iw_request_info *info, 88 union iwreq_data *wrqu, char *extra) 89{ 90 int ret; 91 struct r8192_priv *priv = ieee80211_priv(dev); 92 93 if(priv->bHwRadioOff == true) 94 return 0; 95 96 down(&priv->wx_sem); 97 98 ret = ieee80211_wx_set_rts(priv->ieee80211,info,wrqu,extra); 99 100 up(&priv->wx_sem); 101 102 return ret; 103} 104 105static int r8192_wx_get_rts(struct net_device *dev, 106 struct iw_request_info *info, 107 union iwreq_data *wrqu, char *extra) 108{ 109 struct r8192_priv *priv = ieee80211_priv(dev); 110 return ieee80211_wx_get_rts(priv->ieee80211,info,wrqu,extra); 111} 112 113static int r8192_wx_set_power(struct net_device *dev, 114 struct iw_request_info *info, 115 union iwreq_data *wrqu, char *extra) 116{ 117 int ret; 118 struct r8192_priv *priv = ieee80211_priv(dev); 119 120 if(priv->bHwRadioOff == true) 121 return 0; 122 123 down(&priv->wx_sem); 124 125 ret = ieee80211_wx_set_power(priv->ieee80211,info,wrqu,extra); 126 127 up(&priv->wx_sem); 128 129 return ret; 130} 131 132static int r8192_wx_get_power(struct net_device *dev, 133 struct iw_request_info *info, 134 union iwreq_data *wrqu, char *extra) 135{ 136 struct r8192_priv *priv = ieee80211_priv(dev); 137 return ieee80211_wx_get_power(priv->ieee80211,info,wrqu,extra); 138} 139 140static int r8192_wx_set_rawtx(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 int ret; 146 147 if(priv->bHwRadioOff == true) 148 return 0; 149 150 down(&priv->wx_sem); 151 152 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); 153 154 up(&priv->wx_sem); 155 156 return ret; 157 158} 159 160static int r8192_wx_force_reset(struct net_device *dev, 161 struct iw_request_info *info, 162 union iwreq_data *wrqu, char *extra) 163{ 164 struct r8192_priv *priv = ieee80211_priv(dev); 165 166 down(&priv->wx_sem); 167 168 printk("%s(): force reset ! extra is %d\n",__FUNCTION__, *extra); 169 priv->force_reset = *extra; 170 up(&priv->wx_sem); 171 return 0; 172 173} 174 175 176static int r8192_wx_set_crcmon(struct net_device *dev, 177 struct iw_request_info *info, 178 union iwreq_data *wrqu, char *extra) 179{ 180 struct r8192_priv *priv = ieee80211_priv(dev); 181 int *parms = (int *)extra; 182 int enable = (parms[0] > 0); 183 short prev = priv->crcmon; 184 185 if(priv->bHwRadioOff == true) 186 return 0; 187 188 down(&priv->wx_sem); 189 190 if(enable) 191 priv->crcmon=1; 192 else 193 priv->crcmon=0; 194 195 DMESG("bad CRC in monitor mode are %s", 196 priv->crcmon ? "accepted" : "rejected"); 197 198 if(prev != priv->crcmon && priv->up){ 199 //rtl8180_down(dev); 200 //rtl8180_up(dev); 201 } 202 203 up(&priv->wx_sem); 204 205 return 0; 206} 207 208static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a, 209 union iwreq_data *wrqu, char *b) 210{ 211 struct r8192_priv *priv = ieee80211_priv(dev); 212 RT_RF_POWER_STATE rtState; 213 int ret; 214 215 if(priv->bHwRadioOff == true) 216 return 0; 217 218 rtState = priv->ieee80211->eRFPowerState; 219 down(&priv->wx_sem); 220#ifdef ENABLE_IPS 221 if(wrqu->mode == IW_MODE_ADHOC){ 222 223 if(priv->ieee80211->PowerSaveControl.bInactivePs){ 224 if(rtState == eRfOff){ 225 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS) 226 { 227 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); 228 up(&priv->wx_sem); 229 return -1; 230 } 231 else{ 232 RT_TRACE(COMP_ERR, "%s(): IPSLeave\n",__FUNCTION__); 233 down(&priv->ieee80211->ips_sem); 234 IPSLeave(dev); 235 up(&priv->ieee80211->ips_sem); 236 } 237 } 238 } 239 } 240#endif 241 ret = ieee80211_wx_set_mode(priv->ieee80211,a,wrqu,b); 242 243 //rtl8187_set_rxconf(dev); 244 245 up(&priv->wx_sem); 246 return ret; 247} 248 249struct iw_range_with_scan_capa 250{ 251 /* Informative stuff (to choose between different interface) */ 252 __u32 throughput; /* To give an idea... */ 253 /* In theory this value should be the maximum benchmarked 254 * TCP/IP throughput, because with most of these devices the 255 * bit rate is meaningless (overhead an co) to estimate how 256 * fast the connection will go and pick the fastest one. 257 * I suggest people to play with Netperf or any benchmark... 258 */ 259 260 /* NWID (or domain id) */ 261 __u32 min_nwid; /* Minimal NWID we are able to set */ 262 __u32 max_nwid; /* Maximal NWID we are able to set */ 263 264 /* Old Frequency (backward compat - moved lower ) */ 265 __u16 old_num_channels; 266 __u8 old_num_frequency; 267 268 /* Scan capabilities */ 269 __u8 scan_capa; 270}; 271static int rtl8180_wx_get_range(struct net_device *dev, 272 struct iw_request_info *info, 273 union iwreq_data *wrqu, char *extra) 274{ 275 struct iw_range *range = (struct iw_range *)extra; 276 struct iw_range_with_scan_capa* tmp = (struct iw_range_with_scan_capa*)range; 277 struct r8192_priv *priv = ieee80211_priv(dev); 278 u16 val; 279 int i; 280 281 wrqu->data.length = sizeof(*range); 282 memset(range, 0, sizeof(*range)); 283 284 /* Let's try to keep this struct in the same order as in 285 * linux/include/wireless.h 286 */ 287 288 /* TODO: See what values we can set, and remove the ones we can't 289 * set, or fill them with some default data. 290 */ 291 292 /* ~5 Mb/s real (802.11b) */ 293 range->throughput = 130 * 1000 * 1000; 294 295 // TODO: Not used in 802.11b? 296// range->min_nwid; /* Minimal NWID we are able to set */ 297 // TODO: Not used in 802.11b? 298// range->max_nwid; /* Maximal NWID we are able to set */ 299 300 /* Old Frequency (backward compat - moved lower ) */ 301// range->old_num_channels; 302// range->old_num_frequency; 303// range->old_freq[6]; /* Filler to keep "version" at the same offset */ 304 if(priv->rf_set_sens != NULL) 305 range->sensitivity = priv->max_sens; /* signal level threshold range */ 306 307 range->max_qual.qual = 100; 308 /* TODO: Find real max RSSI and stick here */ 309 range->max_qual.level = 0; 310 range->max_qual.noise = -98; 311 range->max_qual.updated = 7; /* Updated all three */ 312 313 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ 314 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ 315 range->avg_qual.level = 20 + -98; 316 range->avg_qual.noise = 0; 317 range->avg_qual.updated = 7; /* Updated all three */ 318 319 range->num_bitrates = RATE_COUNT; 320 321 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { 322 range->bitrate[i] = rtl8180_rates[i]; 323 } 324 325 range->min_frag = MIN_FRAG_THRESHOLD; 326 range->max_frag = MAX_FRAG_THRESHOLD; 327 328 range->min_pmp=0; 329 range->max_pmp = 5000000; 330 range->min_pmt = 0; 331 range->max_pmt = 65535*1000; 332 range->pmp_flags = IW_POWER_PERIOD; 333 range->pmt_flags = IW_POWER_TIMEOUT; 334 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; 335 range->we_version_compiled = WIRELESS_EXT; 336 range->we_version_source = 18; 337 338// range->retry_capa; /* What retry options are supported */ 339// range->retry_flags; /* How to decode max/min retry limit */ 340// range->r_time_flags; /* How to decode max/min retry life */ 341// range->min_retry; /* Minimal number of retries */ 342// range->max_retry; /* Maximal number of retries */ 343// range->min_r_time; /* Minimal retry lifetime */ 344// range->max_r_time; /* Maximal retry lifetime */ 345 346 347 for (i = 0, val = 0; i < 14; i++) { 348 349 // Include only legal frequencies for some countries 350#ifdef ENABLE_DOT11D 351 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { 352#else 353 if ((priv->ieee80211->channel_map)[i+1]) { 354#endif 355 range->freq[val].i = i + 1; 356 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; 357 range->freq[val].e = 1; 358 val++; 359 } else { 360 // we don't use ? 361 } 362 363 if (val == IW_MAX_FREQUENCIES) 364 break; 365 } 366 range->num_frequency = val; 367 range->num_channels = val; 368#if WIRELESS_EXT > 17 369 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 370 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 371#endif 372 tmp->scan_capa = 0x01; 373 return 0; 374} 375 376 377static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 378 union iwreq_data *wrqu, char *b) 379{ 380 struct r8192_priv *priv = ieee80211_priv(dev); 381 struct ieee80211_device* ieee = priv->ieee80211; 382 RT_RF_POWER_STATE rtState; 383 int ret; 384 385 if(priv->bHwRadioOff == true) 386 return 0; 387 388 rtState = priv->ieee80211->eRFPowerState; 389 390 if(!priv->up) return -ENETDOWN; 391 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true) 392 return -EAGAIN; 393 394 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) 395 { 396 struct iw_scan_req* req = (struct iw_scan_req*)b; 397 if (req->essid_len) 398 { 399 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid); 400 ieee->current_network.ssid_len = req->essid_len; 401 memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 402 //printk("=====>network ssid:%s\n", ieee->current_network.ssid); 403 } 404 } 405 406 down(&priv->wx_sem); 407#ifdef ENABLE_IPS 408 priv->ieee80211->actscanning = true; 409 if(priv->ieee80211->state != IEEE80211_LINKED){ 410 if(priv->ieee80211->PowerSaveControl.bInactivePs){ 411 if(rtState == eRfOff){ 412 if(priv->ieee80211->RfOffReason > RF_CHANGE_BY_IPS) 413 { 414 RT_TRACE(COMP_ERR, "%s(): RF is OFF.\n",__FUNCTION__); 415 up(&priv->wx_sem); 416 return -1; 417 } 418 else{ 419 //RT_TRACE(COMP_PS, "%s(): IPSLeave\n",__FUNCTION__); 420 down(&priv->ieee80211->ips_sem); 421 IPSLeave(dev); 422 up(&priv->ieee80211->ips_sem); 423 } 424 } 425 } 426 priv->ieee80211->scanning = 0; 427 ieee80211_softmac_scan_syncro(priv->ieee80211); 428 ret = 0; 429 } 430 else 431#else 432 433 if(priv->ieee80211->state != IEEE80211_LINKED){ 434 priv->ieee80211->scanning = 0; 435 ieee80211_softmac_scan_syncro(priv->ieee80211); 436 ret = 0; 437 } 438 else 439#endif 440 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b); 441 442 up(&priv->wx_sem); 443 return ret; 444} 445 446 447static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 448 union iwreq_data *wrqu, char *b) 449{ 450 451 int ret; 452 struct r8192_priv *priv = ieee80211_priv(dev); 453 454 if(priv->bHwRadioOff == true) 455 return 0; 456 457 if(!priv->up) return -ENETDOWN; 458 459 down(&priv->wx_sem); 460 461 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b); 462 463 up(&priv->wx_sem); 464 465 return ret; 466} 467 468static int r8192_wx_set_essid(struct net_device *dev, 469 struct iw_request_info *a, 470 union iwreq_data *wrqu, char *b) 471{ 472 struct r8192_priv *priv = ieee80211_priv(dev); 473 RT_RF_POWER_STATE rtState; 474 int ret; 475 476 if(priv->bHwRadioOff == true) 477 return 0; 478 479 rtState = priv->ieee80211->eRFPowerState; 480 down(&priv->wx_sem); 481 482#ifdef ENABLE_IPS 483 down(&priv->ieee80211->ips_sem); 484 IPSLeave(dev); 485 up(&priv->ieee80211->ips_sem); 486#endif 487 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b); 488 489 up(&priv->wx_sem); 490 491 return ret; 492} 493 494 495 496 497static int r8192_wx_get_essid(struct net_device *dev, 498 struct iw_request_info *a, 499 union iwreq_data *wrqu, char *b) 500{ 501 int ret; 502 struct r8192_priv *priv = ieee80211_priv(dev); 503 504 down(&priv->wx_sem); 505 506 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); 507 508 up(&priv->wx_sem); 509 510 return ret; 511} 512 513 514static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, 515 union iwreq_data *wrqu, char *b) 516{ 517 int ret; 518 struct r8192_priv *priv = ieee80211_priv(dev); 519 520 if(priv->bHwRadioOff == true) 521 return 0; 522 523 down(&priv->wx_sem); 524 525 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); 526 527 up(&priv->wx_sem); 528 return ret; 529} 530 531static int r8192_wx_get_name(struct net_device *dev, 532 struct iw_request_info *info, 533 union iwreq_data *wrqu, char *extra) 534{ 535 struct r8192_priv *priv = ieee80211_priv(dev); 536 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); 537} 538 539 540static int r8192_wx_set_frag(struct net_device *dev, 541 struct iw_request_info *info, 542 union iwreq_data *wrqu, char *extra) 543{ 544 struct r8192_priv *priv = ieee80211_priv(dev); 545 546 if(priv->bHwRadioOff == true) 547 return 0; 548 549 if (wrqu->frag.disabled) 550 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; 551 else { 552 if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 553 wrqu->frag.value > MAX_FRAG_THRESHOLD) 554 return -EINVAL; 555 556 priv->ieee80211->fts = wrqu->frag.value & ~0x1; 557 } 558 559 return 0; 560} 561 562 563static int r8192_wx_get_frag(struct net_device *dev, 564 struct iw_request_info *info, 565 union iwreq_data *wrqu, char *extra) 566{ 567 struct r8192_priv *priv = ieee80211_priv(dev); 568 569 wrqu->frag.value = priv->ieee80211->fts; 570 wrqu->frag.fixed = 0; /* no auto select */ 571 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); 572 573 return 0; 574} 575 576 577static int r8192_wx_set_wap(struct net_device *dev, 578 struct iw_request_info *info, 579 union iwreq_data *awrq, 580 char *extra) 581{ 582 583 int ret; 584 struct r8192_priv *priv = ieee80211_priv(dev); 585// struct sockaddr *temp = (struct sockaddr *)awrq; 586 587 if(priv->bHwRadioOff == true) 588 return 0; 589 590 down(&priv->wx_sem); 591 592#ifdef ENABLE_IPS 593 down(&priv->ieee80211->ips_sem); 594 IPSLeave(dev); 595 up(&priv->ieee80211->ips_sem); 596#endif 597 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra); 598 599 up(&priv->wx_sem); 600 601 return ret; 602 603} 604 605 606static int r8192_wx_get_wap(struct net_device *dev, 607 struct iw_request_info *info, 608 union iwreq_data *wrqu, char *extra) 609{ 610 struct r8192_priv *priv = ieee80211_priv(dev); 611 612 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra); 613} 614 615 616static int r8192_wx_get_enc(struct net_device *dev, 617 struct iw_request_info *info, 618 union iwreq_data *wrqu, char *key) 619{ 620 struct r8192_priv *priv = ieee80211_priv(dev); 621 622 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); 623} 624 625static int r8192_wx_set_enc(struct net_device *dev, 626 struct iw_request_info *info, 627 union iwreq_data *wrqu, char *key) 628{ 629 struct r8192_priv *priv = ieee80211_priv(dev); 630 int ret; 631 632 struct ieee80211_device *ieee = priv->ieee80211; 633 //u32 TargetContent; 634 u32 hwkey[4]={0,0,0,0}; 635 u8 mask=0xff; 636 u32 key_idx=0; 637 u8 zero_addr[4][6] ={{0x00,0x00,0x00,0x00,0x00,0x00}, 638 {0x00,0x00,0x00,0x00,0x00,0x01}, 639 {0x00,0x00,0x00,0x00,0x00,0x02}, 640 {0x00,0x00,0x00,0x00,0x00,0x03} }; 641 int i; 642 643 if(priv->bHwRadioOff == true) 644 return 0; 645 646 if(!priv->up) return -ENETDOWN; 647 648 priv->ieee80211->wx_set_enc = 1; 649#ifdef ENABLE_IPS 650 down(&priv->ieee80211->ips_sem); 651 IPSLeave(dev); 652 up(&priv->ieee80211->ips_sem); 653#endif 654 655 down(&priv->wx_sem); 656 657 RT_TRACE(COMP_SEC, "Setting SW wep key"); 658 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key); 659 660 up(&priv->wx_sem); 661 662 //sometimes, the length is zero while we do not type key value 663 if(wrqu->encoding.length!=0){ 664 665 for(i=0 ; i<4 ; i++){ 666 hwkey[i] |= key[4*i+0]&mask; 667 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; 668 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; 669 hwkey[i] |= (key[4*i+1]&mask)<<8; 670 hwkey[i] |= (key[4*i+2]&mask)<<16; 671 hwkey[i] |= (key[4*i+3]&mask)<<24; 672 } 673 674 #define CONF_WEP40 0x4 675 #define CONF_WEP104 0x14 676 677 switch(wrqu->encoding.flags & IW_ENCODE_INDEX){ 678 case 0: key_idx = ieee->tx_keyidx; break; 679 case 1: key_idx = 0; break; 680 case 2: key_idx = 1; break; 681 case 3: key_idx = 2; break; 682 case 4: key_idx = 3; break; 683 default: break; 684 } 685 686 //printk("-------====>length:%d, key_idx:%d, flag:%x\n", wrqu->encoding.length, key_idx, wrqu->encoding.flags); 687 if(wrqu->encoding.length==0x5){ 688 ieee->pairwise_key_type = KEY_TYPE_WEP40; 689 EnableHWSecurityConfig8192(dev); 690 setKey( dev, 691 key_idx, //EntryNo 692 key_idx, //KeyIndex 693 KEY_TYPE_WEP40, //KeyType 694 zero_addr[key_idx], 695 0, //DefaultKey 696 hwkey); //KeyContent 697 698 } 699 700 else if(wrqu->encoding.length==0xd){ 701 ieee->pairwise_key_type = KEY_TYPE_WEP104; 702 EnableHWSecurityConfig8192(dev); 703 setKey( dev, 704 key_idx, //EntryNo 705 key_idx, //KeyIndex 706 KEY_TYPE_WEP104, //KeyType 707 zero_addr[key_idx], 708 0, //DefaultKey 709 hwkey); //KeyContent 710 } 711 else printk("wrong type in WEP, not WEP40 and WEP104\n"); 712 713 714 } 715 716 717 priv->ieee80211->wx_set_enc = 0; 718 719 return ret; 720} 721 722 723static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union 724 iwreq_data *wrqu, char *p){ 725 726 struct r8192_priv *priv = ieee80211_priv(dev); 727 int *parms=(int*)p; 728 int mode=parms[0]; 729 730 priv->ieee80211->active_scan = mode; 731 732 return 1; 733} 734 735 736 737static int r8192_wx_set_retry(struct net_device *dev, 738 struct iw_request_info *info, 739 union iwreq_data *wrqu, char *extra) 740{ 741 struct r8192_priv *priv = ieee80211_priv(dev); 742 int err = 0; 743 744 if(priv->bHwRadioOff == true) 745 return 0; 746 747 down(&priv->wx_sem); 748 749 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 750 wrqu->retry.disabled){ 751 err = -EINVAL; 752 goto exit; 753 } 754 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){ 755 err = -EINVAL; 756 goto exit; 757 } 758 759 if(wrqu->retry.value > R8180_MAX_RETRY){ 760 err= -EINVAL; 761 goto exit; 762 } 763 if (wrqu->retry.flags & IW_RETRY_MAX) { 764 priv->retry_rts = wrqu->retry.value; 765 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 766 767 }else { 768 priv->retry_data = wrqu->retry.value; 769 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 770 } 771 772 773 rtl8192_commit(dev); 774 /* 775 if(priv->up){ 776 rtl8180_rtx_disable(dev); 777 rtl8180_rx_enable(dev); 778 rtl8180_tx_enable(dev); 779 780 } 781 */ 782exit: 783 up(&priv->wx_sem); 784 785 return err; 786} 787 788static int r8192_wx_get_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 794 795 wrqu->retry.disabled = 0; /* can't be disabled */ 796 797 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 798 IW_RETRY_LIFETIME) 799 return -EINVAL; 800 801 if (wrqu->retry.flags & IW_RETRY_MAX) { 802 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MAX; 803 wrqu->retry.value = priv->retry_rts; 804 } else { 805 wrqu->retry.flags = IW_RETRY_LIMIT & IW_RETRY_MIN; 806 wrqu->retry.value = priv->retry_data; 807 } 808 //DMESG("returning %d",wrqu->retry.value); 809 810 811 return 0; 812} 813 814static int r8192_wx_get_sens(struct net_device *dev, 815 struct iw_request_info *info, 816 union iwreq_data *wrqu, char *extra) 817{ 818 struct r8192_priv *priv = ieee80211_priv(dev); 819 if(priv->rf_set_sens == NULL) 820 return -1; /* we have not this support for this radio */ 821 wrqu->sens.value = priv->sens; 822 return 0; 823} 824 825 826static int r8192_wx_set_sens(struct net_device *dev, 827 struct iw_request_info *info, 828 union iwreq_data *wrqu, char *extra) 829{ 830 831 struct r8192_priv *priv = ieee80211_priv(dev); 832 833 short err = 0; 834 835 if(priv->bHwRadioOff == true) 836 return 0; 837 838 down(&priv->wx_sem); 839 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value); 840 if(priv->rf_set_sens == NULL) { 841 err= -1; /* we have not this support for this radio */ 842 goto exit; 843 } 844 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0) 845 priv->sens = wrqu->sens.value; 846 else 847 err= -EINVAL; 848 849exit: 850 up(&priv->wx_sem); 851 852 return err; 853} 854 855#if (WIRELESS_EXT >= 18) 856static int r8192_wx_set_enc_ext(struct net_device *dev, 857 struct iw_request_info *info, 858 union iwreq_data *wrqu, char *extra) 859{ 860 int ret=0; 861 struct r8192_priv *priv = ieee80211_priv(dev); 862 struct ieee80211_device* ieee = priv->ieee80211; 863 864 if(priv->bHwRadioOff == true) 865 return 0; 866 867 down(&priv->wx_sem); 868 869 priv->ieee80211->wx_set_enc = 1; 870 871#ifdef ENABLE_IPS 872 down(&priv->ieee80211->ips_sem); 873 IPSLeave(dev); 874 up(&priv->ieee80211->ips_sem); 875#endif 876 877 ret = ieee80211_wx_set_encode_ext(ieee, info, wrqu, extra); 878 879 { 880 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; 881 u8 zero[6] = {0}; 882 u32 key[4] = {0}; 883 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 884 struct iw_point *encoding = &wrqu->encoding; 885 u8 idx = 0, alg = 0, group = 0; 886 if ((encoding->flags & IW_ENCODE_DISABLED) || 887 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01 888 { 889 ieee->pairwise_key_type = ieee->group_key_type = KEY_TYPE_NA; 890 CamResetAllEntry(dev); 891 goto end_hw_sec; 892 } 893 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; 894 idx = encoding->flags & IW_ENCODE_INDEX; 895 if (idx) 896 idx --; 897 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 898 899 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) 900 { 901 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) ) 902 alg = KEY_TYPE_WEP104; 903 ieee->pairwise_key_type = alg; 904 EnableHWSecurityConfig8192(dev); 905 } 906 memcpy((u8*)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 907 908 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) ) 909 { 910 if (ext->key_len == 13) 911 ieee->pairwise_key_type = alg = KEY_TYPE_WEP104; 912 setKey( dev, 913 idx,//EntryNo 914 idx, //KeyIndex 915 alg, //KeyType 916 zero, //MacAddr 917 0, //DefaultKey 918 key); //KeyContent 919 } 920 else if (group) 921 { 922 ieee->group_key_type = alg; 923 setKey( dev, 924 idx,//EntryNo 925 idx, //KeyIndex 926 alg, //KeyType 927 broadcast_addr, //MacAddr 928 0, //DefaultKey 929 key); //KeyContent 930 } 931 else //pairwise key 932 { 933 if ((ieee->pairwise_key_type == KEY_TYPE_CCMP) && ieee->pHTInfo->bCurrentHTSupport){ 934 write_nic_byte(dev, 0x173, 1); //fix aes bug 935 } 936 setKey( dev, 937 4,//EntryNo 938 idx, //KeyIndex 939 alg, //KeyType 940 (u8*)ieee->ap_mac_addr, //MacAddr 941 0, //DefaultKey 942 key); //KeyContent 943 } 944 945 946 } 947 948end_hw_sec: 949 priv->ieee80211->wx_set_enc = 0; 950 up(&priv->wx_sem); 951 return ret; 952 953} 954static int r8192_wx_set_auth(struct net_device *dev, 955 struct iw_request_info *info, 956 union iwreq_data *data, char *extra) 957{ 958 int ret=0; 959 //printk("====>%s()\n", __FUNCTION__); 960 struct r8192_priv *priv = ieee80211_priv(dev); 961 962 if(priv->bHwRadioOff == true) 963 return 0; 964 965 down(&priv->wx_sem); 966 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 967 up(&priv->wx_sem); 968 return ret; 969} 970 971static int r8192_wx_set_mlme(struct net_device *dev, 972 struct iw_request_info *info, 973 union iwreq_data *wrqu, char *extra) 974{ 975 //printk("====>%s()\n", __FUNCTION__); 976 977 int ret=0; 978 struct r8192_priv *priv = ieee80211_priv(dev); 979 980 if(priv->bHwRadioOff == true) 981 return 0; 982 983 down(&priv->wx_sem); 984 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); 985 up(&priv->wx_sem); 986 return ret; 987} 988#endif 989static int r8192_wx_set_gen_ie(struct net_device *dev, 990 struct iw_request_info *info, 991 union iwreq_data *data, char *extra) 992{ 993 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length); 994 int ret=0; 995 struct r8192_priv *priv = ieee80211_priv(dev); 996 997 if(priv->bHwRadioOff == true) 998 return 0; 999 1000 down(&priv->wx_sem); 1001 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 1002 up(&priv->wx_sem); 1003 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret); 1004 return ret; 1005} 1006 1007static int dummy(struct net_device *dev, struct iw_request_info *a, 1008 union iwreq_data *wrqu,char *b) 1009{ 1010 return -1; 1011} 1012 1013// check ac/dc status with the help of user space application */ 1014static int r8192_wx_adapter_power_status(struct net_device *dev, 1015 struct iw_request_info *info, 1016 union iwreq_data *wrqu, char *extra) 1017{ 1018 struct r8192_priv *priv = ieee80211_priv(dev); 1019#ifdef ENABLE_LPS 1020 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(priv->ieee80211->PowerSaveControl)); 1021 struct ieee80211_device* ieee = priv->ieee80211; 1022#endif 1023 down(&priv->wx_sem); 1024 1025#ifdef ENABLE_LPS 1026 RT_TRACE(COMP_POWER, "%s(): %s\n",__FUNCTION__, (*extra == 6)?"DC power":"AC power"); 1027 // ieee->ps shall not be set under DC mode, otherwise it conflict 1028 // with Leisure power save mode setting. 1029 // 1030 if(*extra || priv->force_lps) { 1031 priv->ps_force = false; 1032 pPSC->bLeisurePs = true; 1033 } else { 1034 //LZM for PS-Poll AID issue. 090429 1035 if(priv->ieee80211->state == IEEE80211_LINKED) 1036 LeisurePSLeave(dev); 1037 1038 priv->ps_force = true; 1039 pPSC->bLeisurePs = false; 1040 ieee->ps = *extra; 1041 } 1042 1043#endif 1044 up(&priv->wx_sem); 1045 return 0; 1046 1047} 1048 1049 1050static iw_handler r8192_wx_handlers[] = 1051{ 1052 NULL, /* SIOCSIWCOMMIT */ 1053 r8192_wx_get_name, /* SIOCGIWNAME */ 1054 dummy, /* SIOCSIWNWID */ 1055 dummy, /* SIOCGIWNWID */ 1056 r8192_wx_set_freq, /* SIOCSIWFREQ */ 1057 r8192_wx_get_freq, /* SIOCGIWFREQ */ 1058 r8192_wx_set_mode, /* SIOCSIWMODE */ 1059 r8192_wx_get_mode, /* SIOCGIWMODE */ 1060 r8192_wx_set_sens, /* SIOCSIWSENS */ 1061 r8192_wx_get_sens, /* SIOCGIWSENS */ 1062 NULL, /* SIOCSIWRANGE */ 1063 rtl8180_wx_get_range, /* SIOCGIWRANGE */ 1064 NULL, /* SIOCSIWPRIV */ 1065 NULL, /* SIOCGIWPRIV */ 1066 NULL, /* SIOCSIWSTATS */ 1067 NULL, /* SIOCGIWSTATS */ 1068 dummy, /* SIOCSIWSPY */ 1069 dummy, /* SIOCGIWSPY */ 1070 NULL, /* SIOCGIWTHRSPY */ 1071 NULL, /* SIOCWIWTHRSPY */ 1072 r8192_wx_set_wap, /* SIOCSIWAP */ 1073 r8192_wx_get_wap, /* SIOCGIWAP */ 1074#if (WIRELESS_EXT >= 18) 1075 r8192_wx_set_mlme, /* MLME-- */ 1076#else 1077 NULL, 1078#endif 1079 dummy, /* SIOCGIWAPLIST -- depricated */ 1080 r8192_wx_set_scan, /* SIOCSIWSCAN */ 1081 r8192_wx_get_scan, /* SIOCGIWSCAN */ 1082 r8192_wx_set_essid, /* SIOCSIWESSID */ 1083 r8192_wx_get_essid, /* SIOCGIWESSID */ 1084 dummy, /* SIOCSIWNICKN */ 1085 dummy, /* SIOCGIWNICKN */ 1086 NULL, /* -- hole -- */ 1087 NULL, /* -- hole -- */ 1088 r8192_wx_set_rate, /* SIOCSIWRATE */ 1089 r8192_wx_get_rate, /* SIOCGIWRATE */ 1090 r8192_wx_set_rts, /* SIOCSIWRTS */ 1091 r8192_wx_get_rts, /* SIOCGIWRTS */ 1092 r8192_wx_set_frag, /* SIOCSIWFRAG */ 1093 r8192_wx_get_frag, /* SIOCGIWFRAG */ 1094 dummy, /* SIOCSIWTXPOW */ 1095 dummy, /* SIOCGIWTXPOW */ 1096 r8192_wx_set_retry, /* SIOCSIWRETRY */ 1097 r8192_wx_get_retry, /* SIOCGIWRETRY */ 1098 r8192_wx_set_enc, /* SIOCSIWENCODE */ 1099 r8192_wx_get_enc, /* SIOCGIWENCODE */ 1100 r8192_wx_set_power, /* SIOCSIWPOWER */ 1101 r8192_wx_get_power, /* SIOCGIWPOWER */ 1102 NULL, /*---hole---*/ 1103 NULL, /*---hole---*/ 1104 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ 1105 NULL, /* SIOCSIWGENIE */ 1106#if (WIRELESS_EXT >= 18) 1107 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */ 1108 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */ 1109 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 1110#else 1111 NULL, 1112 NULL, 1113 NULL, 1114#endif 1115 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ 1116 NULL, /* SIOCSIWPMKSA */ 1117 NULL, /*---hole---*/ 1118 1119}; 1120 1121 1122static const struct iw_priv_args r8192_private_args[] = { 1123 1124 { 1125 SIOCIWFIRSTPRIV + 0x0, 1126 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" 1127 }, 1128 1129 { 1130 SIOCIWFIRSTPRIV + 0x1, 1131 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" 1132 1133 }, 1134 { 1135 SIOCIWFIRSTPRIV + 0x2, 1136 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 1137 } 1138 , 1139 { 1140 SIOCIWFIRSTPRIV + 0x3, 1141 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" 1142 1143 } 1144 , 1145 { 1146 SIOCIWFIRSTPRIV + 0x4, 1147 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED|1, IW_PRIV_TYPE_NONE, 1148 "set_power" 1149 } 1150 1151}; 1152 1153 1154static iw_handler r8192_private_handler[] = { 1155 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ 1156 r8192_wx_set_scan_type, 1157 r8192_wx_set_rawtx, 1158 r8192_wx_force_reset, 1159 r8192_wx_adapter_power_status, 1160}; 1161 1162//#if WIRELESS_EXT >= 17 1163struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 1164{ 1165 struct r8192_priv *priv = ieee80211_priv(dev); 1166 struct ieee80211_device* ieee = priv->ieee80211; 1167 struct iw_statistics* wstats = &priv->wstats; 1168 int tmp_level = 0; 1169 int tmp_qual = 0; 1170 int tmp_noise = 0; 1171 if(ieee->state < IEEE80211_LINKED) 1172 { 1173 wstats->qual.qual = 0; 1174 wstats->qual.level = 0; 1175 wstats->qual.noise = 0; 1176 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 1177 return wstats; 1178 } 1179 1180 tmp_level = (&ieee->current_network)->stats.rssi; 1181 tmp_qual = (&ieee->current_network)->stats.signal; 1182 tmp_noise = (&ieee->current_network)->stats.noise; 1183 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); 1184 1185 wstats->qual.level = tmp_level; 1186 wstats->qual.qual = tmp_qual; 1187 wstats->qual.noise = tmp_noise; 1188 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 1189 return wstats; 1190} 1191//#endif 1192 1193 1194struct iw_handler_def r8192_wx_handlers_def={ 1195 .standard = r8192_wx_handlers, 1196 .num_standard = sizeof(r8192_wx_handlers) / sizeof(iw_handler), 1197 .private = r8192_private_handler, 1198 .num_private = sizeof(r8192_private_handler) / sizeof(iw_handler), 1199 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 1200#if WIRELESS_EXT >= 17 1201 .get_wireless_stats = r8192_get_wireless_stats, 1202#endif 1203 .private_args = (struct iw_priv_args *)r8192_private_args, 1204}; 1205