r8192U_wx.c revision aa0cb59cfa781d5cb44dd981153d67168d34f91b
1/* 2 This file contains wireless extension handlers. 3 4 This is part of rtl8180 OpenSource driver. 5 Copyright (C) Andrea Merello 2004-2005 <andrea.merello@gmail.com> 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 thank the Authors of those projects and the Ndiswrapper 17 project Authors. 18*/ 19 20#include <linux/string.h> 21#include "r8192U.h" 22#include "r8192U_hw.h" 23 24#include "dot11d.h" 25 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 45static 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 130static 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 207struct iw_range_with_scan_capa { 208 /* 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 */ 216 217 /* 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 */ 220 221 /* Old Frequency (backward compat - moved lower ) */ 222 __u16 old_num_channels; 223 __u8 old_num_frequency; 224 225 /* Scan capabilities */ 226 __u8 scan_capa; 227}; 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; 233 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range; 234 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 257 /* Old Frequency (backward compat - moved lower ) */ 258// 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' */ 271 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ 272 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 278 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { 279 range->bitrate[i] = rtl8180_rates[i]; 280 } 281 282 range->min_frag = MIN_FRAG_THRESHOLD; 283 range->max_frag = MAX_FRAG_THRESHOLD; 284 285 range->min_pmp=0; 286 range->max_pmp = 5000000; 287 range->min_pmt = 0; 288 range->max_pmt = 65535*1000; 289 range->pmp_flags = IW_POWER_PERIOD; 290 range->pmt_flags = IW_POWER_TIMEOUT; 291 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; 292 293 range->we_version_compiled = WIRELESS_EXT; 294 range->we_version_source = 16; 295 296// range->retry_capa; /* What retry options are supported */ 297// range->retry_flags; /* How to decode max/min retry limit */ 298// range->r_time_flags; /* How to decode max/min retry life */ 299// range->min_retry; /* Minimal number of retries */ 300// range->max_retry; /* Maximal number of retries */ 301// range->min_r_time; /* Minimal retry lifetime */ 302// range->max_r_time; /* Maximal retry lifetime */ 303 304 305 for (i = 0, val = 0; i < 14; i++) { 306 307 // Include only legal frequencies for some countries 308 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { 309 range->freq[val].i = i + 1; 310 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; 311 range->freq[val].e = 1; 312 val++; 313 } else { 314 // FIXME: do we need to set anything for channels 315 // we don't use ? 316 } 317 318 if (val == IW_MAX_FREQUENCIES) 319 break; 320 } 321 range->num_frequency = val; 322 range->num_channels = val; 323#if WIRELESS_EXT > 17 324 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 325 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 326#endif 327 tmp->scan_capa = 0x01; 328 return 0; 329} 330 331 332static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 333 union iwreq_data *wrqu, char *b) 334{ 335 struct r8192_priv *priv = ieee80211_priv(dev); 336 struct ieee80211_device *ieee = priv->ieee80211; 337 int ret = 0; 338 339 if(!priv->up) return -ENETDOWN; 340 341 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true) 342 return -EAGAIN; 343 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) 344 { 345 struct iw_scan_req *req = (struct iw_scan_req *)b; 346 if (req->essid_len) 347 { 348 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid); 349 ieee->current_network.ssid_len = req->essid_len; 350 memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 351 //printk("=====>network ssid:%s\n", ieee->current_network.ssid); 352 } 353 } 354 355 down(&priv->wx_sem); 356 if(priv->ieee80211->state != IEEE80211_LINKED){ 357 priv->ieee80211->scanning = 0; 358 ieee80211_softmac_scan_syncro(priv->ieee80211); 359 ret = 0; 360 } 361 else 362 ret = ieee80211_wx_set_scan(priv->ieee80211,a,wrqu,b); 363 up(&priv->wx_sem); 364 return ret; 365} 366 367 368static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 369 union iwreq_data *wrqu, char *b) 370{ 371 372 int ret; 373 struct r8192_priv *priv = ieee80211_priv(dev); 374 375 if(!priv->up) return -ENETDOWN; 376 377 down(&priv->wx_sem); 378 379 ret = ieee80211_wx_get_scan(priv->ieee80211,a,wrqu,b); 380 381 up(&priv->wx_sem); 382 383 return ret; 384} 385 386static int r8192_wx_set_essid(struct net_device *dev, 387 struct iw_request_info *a, 388 union iwreq_data *wrqu, char *b) 389{ 390 struct r8192_priv *priv = ieee80211_priv(dev); 391 int ret; 392 down(&priv->wx_sem); 393 394 ret = ieee80211_wx_set_essid(priv->ieee80211,a,wrqu,b); 395 396 up(&priv->wx_sem); 397 398 return ret; 399} 400 401 402 403 404static int r8192_wx_get_essid(struct net_device *dev, 405 struct iw_request_info *a, 406 union iwreq_data *wrqu, char *b) 407{ 408 int ret; 409 struct r8192_priv *priv = ieee80211_priv(dev); 410 411 down(&priv->wx_sem); 412 413 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); 414 415 up(&priv->wx_sem); 416 417 return ret; 418} 419 420 421static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, 422 union iwreq_data *wrqu, char *b) 423{ 424 int ret; 425 struct r8192_priv *priv = ieee80211_priv(dev); 426 427 down(&priv->wx_sem); 428 429 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); 430 431 up(&priv->wx_sem); 432 return ret; 433} 434 435static int r8192_wx_get_name(struct net_device *dev, 436 struct iw_request_info *info, 437 union iwreq_data *wrqu, char *extra) 438{ 439 struct r8192_priv *priv = ieee80211_priv(dev); 440 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); 441} 442 443 444static int r8192_wx_set_frag(struct net_device *dev, 445 struct iw_request_info *info, 446 union iwreq_data *wrqu, char *extra) 447{ 448 struct r8192_priv *priv = ieee80211_priv(dev); 449 450 if (wrqu->frag.disabled) 451 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; 452 else { 453 if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 454 wrqu->frag.value > MAX_FRAG_THRESHOLD) 455 return -EINVAL; 456 457 priv->ieee80211->fts = wrqu->frag.value & ~0x1; 458 } 459 460 return 0; 461} 462 463 464static int r8192_wx_get_frag(struct net_device *dev, 465 struct iw_request_info *info, 466 union iwreq_data *wrqu, char *extra) 467{ 468 struct r8192_priv *priv = ieee80211_priv(dev); 469 470 wrqu->frag.value = priv->ieee80211->fts; 471 wrqu->frag.fixed = 0; /* no auto select */ 472 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); 473 474 return 0; 475} 476 477 478static int r8192_wx_set_wap(struct net_device *dev, 479 struct iw_request_info *info, 480 union iwreq_data *awrq, 481 char *extra) 482{ 483 484 int ret; 485 struct r8192_priv *priv = ieee80211_priv(dev); 486// struct sockaddr *temp = (struct sockaddr *)awrq; 487 down(&priv->wx_sem); 488 489 ret = ieee80211_wx_set_wap(priv->ieee80211,info,awrq,extra); 490 491 up(&priv->wx_sem); 492 493 return ret; 494 495} 496 497 498static int r8192_wx_get_wap(struct net_device *dev, 499 struct iw_request_info *info, 500 union iwreq_data *wrqu, char *extra) 501{ 502 struct r8192_priv *priv = ieee80211_priv(dev); 503 504 return ieee80211_wx_get_wap(priv->ieee80211,info,wrqu,extra); 505} 506 507 508static int r8192_wx_get_enc(struct net_device *dev, 509 struct iw_request_info *info, 510 union iwreq_data *wrqu, char *key) 511{ 512 struct r8192_priv *priv = ieee80211_priv(dev); 513 514 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); 515} 516 517static int r8192_wx_set_enc(struct net_device *dev, 518 struct iw_request_info *info, 519 union iwreq_data *wrqu, char *key) 520{ 521 struct r8192_priv *priv = ieee80211_priv(dev); 522 struct ieee80211_device *ieee = priv->ieee80211; 523 int ret; 524 525 //u32 TargetContent; 526 u32 hwkey[4]={0,0,0,0}; 527 u8 mask=0xff; 528 u32 key_idx=0; 529 //u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff}; 530 u8 zero_addr[4][6] ={ {0x00,0x00,0x00,0x00,0x00,0x00}, 531 {0x00,0x00,0x00,0x00,0x00,0x01}, 532 {0x00,0x00,0x00,0x00,0x00,0x02}, 533 {0x00,0x00,0x00,0x00,0x00,0x03} }; 534 int i; 535 536 if(!priv->up) return -ENETDOWN; 537 538 down(&priv->wx_sem); 539 540 RT_TRACE(COMP_SEC, "Setting SW wep key"); 541 ret = ieee80211_wx_set_encode(priv->ieee80211,info,wrqu,key); 542 543 up(&priv->wx_sem); 544 545 546 547 //sometimes, the length is zero while we do not type key value 548 if(wrqu->encoding.length!=0){ 549 550 for(i=0 ; i<4 ; i++){ 551 hwkey[i] |= key[4*i+0]&mask; 552 if(i==1&&(4*i+1)==wrqu->encoding.length) mask=0x00; 553 if(i==3&&(4*i+1)==wrqu->encoding.length) mask=0x00; 554 hwkey[i] |= (key[4*i+1]&mask)<<8; 555 hwkey[i] |= (key[4*i+2]&mask)<<16; 556 hwkey[i] |= (key[4*i+3]&mask)<<24; 557 } 558 559 #define CONF_WEP40 0x4 560 #define CONF_WEP104 0x14 561 562 switch (wrqu->encoding.flags & IW_ENCODE_INDEX){ 563 case 0: key_idx = ieee->tx_keyidx; break; 564 case 1: key_idx = 0; break; 565 case 2: key_idx = 1; break; 566 case 3: key_idx = 2; break; 567 case 4: key_idx = 3; break; 568 default: break; 569 } 570 571 if(wrqu->encoding.length==0x5){ 572 ieee->pairwise_key_type = KEY_TYPE_WEP40; 573 EnableHWSecurityConfig8192(dev); 574 575 setKey( dev, 576 key_idx, //EntryNo 577 key_idx, //KeyIndex 578 KEY_TYPE_WEP40, //KeyType 579 zero_addr[key_idx], 580 0, //DefaultKey 581 hwkey); //KeyContent 582 583 } 584 585 else if(wrqu->encoding.length==0xd){ 586 ieee->pairwise_key_type = KEY_TYPE_WEP104; 587 EnableHWSecurityConfig8192(dev); 588 589 setKey( dev, 590 key_idx, //EntryNo 591 key_idx, //KeyIndex 592 KEY_TYPE_WEP104, //KeyType 593 zero_addr[key_idx], 594 0, //DefaultKey 595 hwkey); //KeyContent 596 597 } 598 else printk("wrong type in WEP, not WEP40 and WEP104\n"); 599 600 } 601 602 return ret; 603} 604 605 606static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, union 607 iwreq_data *wrqu, char *p){ 608 609 struct r8192_priv *priv = ieee80211_priv(dev); 610 int *parms=(int *)p; 611 int mode=parms[0]; 612 613 priv->ieee80211->active_scan = mode; 614 615 return 1; 616} 617 618 619 620static int r8192_wx_set_retry(struct net_device *dev, 621 struct iw_request_info *info, 622 union iwreq_data *wrqu, char *extra) 623{ 624 struct r8192_priv *priv = ieee80211_priv(dev); 625 int err = 0; 626 627 down(&priv->wx_sem); 628 629 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 630 wrqu->retry.disabled){ 631 err = -EINVAL; 632 goto exit; 633 } 634 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)){ 635 err = -EINVAL; 636 goto exit; 637 } 638 639 if(wrqu->retry.value > R8180_MAX_RETRY){ 640 err= -EINVAL; 641 goto exit; 642 } 643 if (wrqu->retry.flags & IW_RETRY_MAX) { 644 priv->retry_rts = wrqu->retry.value; 645 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 646 647 }else { 648 priv->retry_data = wrqu->retry.value; 649 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 650 } 651 652 /* FIXME ! 653 * We might try to write directly the TX config register 654 * or to restart just the (R)TX process. 655 * I'm unsure if whole reset is really needed 656 */ 657 658 rtl8192_commit(dev); 659 /* 660 if(priv->up){ 661 rtl8180_rtx_disable(dev); 662 rtl8180_rx_enable(dev); 663 rtl8180_tx_enable(dev); 664 665 } 666 */ 667exit: 668 up(&priv->wx_sem); 669 670 return err; 671} 672 673static int r8192_wx_get_retry(struct net_device *dev, 674 struct iw_request_info *info, 675 union iwreq_data *wrqu, char *extra) 676{ 677 struct r8192_priv *priv = ieee80211_priv(dev); 678 679 680 wrqu->retry.disabled = 0; /* can't be disabled */ 681 682 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 683 IW_RETRY_LIFETIME) 684 return -EINVAL; 685 686 if (wrqu->retry.flags & IW_RETRY_MAX) { 687 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 688 wrqu->retry.value = priv->retry_rts; 689 } else { 690 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; 691 wrqu->retry.value = priv->retry_data; 692 } 693 //printk("returning %d",wrqu->retry.value); 694 695 696 return 0; 697} 698 699static int r8192_wx_get_sens(struct net_device *dev, 700 struct iw_request_info *info, 701 union iwreq_data *wrqu, char *extra) 702{ 703 struct r8192_priv *priv = ieee80211_priv(dev); 704 if(priv->rf_set_sens == NULL) 705 return -1; /* we have not this support for this radio */ 706 wrqu->sens.value = priv->sens; 707 return 0; 708} 709 710 711static int r8192_wx_set_sens(struct net_device *dev, 712 struct iw_request_info *info, 713 union iwreq_data *wrqu, char *extra) 714{ 715 716 struct r8192_priv *priv = ieee80211_priv(dev); 717 718 short err = 0; 719 down(&priv->wx_sem); 720 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value); 721 if(priv->rf_set_sens == NULL) { 722 err= -1; /* we have not this support for this radio */ 723 goto exit; 724 } 725 if(priv->rf_set_sens(dev, wrqu->sens.value) == 0) 726 priv->sens = wrqu->sens.value; 727 else 728 err= -EINVAL; 729 730exit: 731 up(&priv->wx_sem); 732 733 return err; 734} 735 736#if (WIRELESS_EXT >= 18) 737//hw security need to reorganized. 738static int r8192_wx_set_enc_ext(struct net_device *dev, 739 struct iw_request_info *info, 740 union iwreq_data *wrqu, char *extra) 741{ 742 int ret=0; 743 struct r8192_priv *priv = ieee80211_priv(dev); 744 struct ieee80211_device *ieee = priv->ieee80211; 745 //printk("===>%s()\n", __FUNCTION__); 746 747 748 down(&priv->wx_sem); 749 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); 750 751 { 752 u8 broadcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff}; 753 u8 zero[6] = {0}; 754 u32 key[4] = {0}; 755 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 756 struct iw_point *encoding = &wrqu->encoding; 757 u8 idx = 0, alg = 0, group = 0; 758 if ((encoding->flags & IW_ENCODE_DISABLED) || 759 ext->alg == IW_ENCODE_ALG_NONE) //none is not allowed to use hwsec WB 2008.07.01 760 goto end_hw_sec; 761 762 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; 763 idx = encoding->flags & IW_ENCODE_INDEX; 764 if (idx) 765 idx --; 766 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 767 768 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) 769 { 770 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40) ) 771 alg = KEY_TYPE_WEP104; 772 ieee->pairwise_key_type = alg; 773 EnableHWSecurityConfig8192(dev); 774 } 775 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 776 777 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode !=2) ) 778 { 779 780 setKey( dev, 781 idx,//EntryNo 782 idx, //KeyIndex 783 alg, //KeyType 784 zero, //MacAddr 785 0, //DefaultKey 786 key); //KeyContent 787 } 788 else if (group) 789 { 790 ieee->group_key_type = alg; 791 setKey( dev, 792 idx,//EntryNo 793 idx, //KeyIndex 794 alg, //KeyType 795 broadcast_addr, //MacAddr 796 0, //DefaultKey 797 key); //KeyContent 798 } 799 else //pairwise key 800 { 801 setKey( dev, 802 4,//EntryNo 803 idx, //KeyIndex 804 alg, //KeyType 805 (u8 *)ieee->ap_mac_addr, //MacAddr 806 0, //DefaultKey 807 key); //KeyContent 808 } 809 810 811 } 812 813end_hw_sec: 814 815 up(&priv->wx_sem); 816 return ret; 817 818} 819static int r8192_wx_set_auth(struct net_device *dev, 820 struct iw_request_info *info, 821 union iwreq_data *data, char *extra) 822{ 823 int ret=0; 824 //printk("====>%s()\n", __FUNCTION__); 825 struct r8192_priv *priv = ieee80211_priv(dev); 826 down(&priv->wx_sem); 827 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 828 up(&priv->wx_sem); 829 return ret; 830} 831 832static int r8192_wx_set_mlme(struct net_device *dev, 833 struct iw_request_info *info, 834 union iwreq_data *wrqu, char *extra) 835{ 836 //printk("====>%s()\n", __FUNCTION__); 837 838 int ret=0; 839 struct r8192_priv *priv = ieee80211_priv(dev); 840 down(&priv->wx_sem); 841 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); 842 843 up(&priv->wx_sem); 844 return ret; 845} 846#endif 847static int r8192_wx_set_gen_ie(struct net_device *dev, 848 struct iw_request_info *info, 849 union iwreq_data *data, char *extra) 850{ 851 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length); 852 int ret=0; 853 struct r8192_priv *priv = ieee80211_priv(dev); 854 down(&priv->wx_sem); 855 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 856 up(&priv->wx_sem); 857 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret); 858 return ret; 859 860 861} 862 863static int dummy(struct net_device *dev, struct iw_request_info *a, 864 union iwreq_data *wrqu,char *b) 865{ 866 return -1; 867} 868 869 870static iw_handler r8192_wx_handlers[] = 871{ 872 NULL, /* SIOCSIWCOMMIT */ 873 r8192_wx_get_name, /* SIOCGIWNAME */ 874 dummy, /* SIOCSIWNWID */ 875 dummy, /* SIOCGIWNWID */ 876 r8192_wx_set_freq, /* SIOCSIWFREQ */ 877 r8192_wx_get_freq, /* SIOCGIWFREQ */ 878 r8192_wx_set_mode, /* SIOCSIWMODE */ 879 r8192_wx_get_mode, /* SIOCGIWMODE */ 880 r8192_wx_set_sens, /* SIOCSIWSENS */ 881 r8192_wx_get_sens, /* SIOCGIWSENS */ 882 NULL, /* SIOCSIWRANGE */ 883 rtl8180_wx_get_range, /* SIOCGIWRANGE */ 884 NULL, /* SIOCSIWPRIV */ 885 NULL, /* SIOCGIWPRIV */ 886 NULL, /* SIOCSIWSTATS */ 887 NULL, /* SIOCGIWSTATS */ 888 dummy, /* SIOCSIWSPY */ 889 dummy, /* SIOCGIWSPY */ 890 NULL, /* SIOCGIWTHRSPY */ 891 NULL, /* SIOCWIWTHRSPY */ 892 r8192_wx_set_wap, /* SIOCSIWAP */ 893 r8192_wx_get_wap, /* SIOCGIWAP */ 894#if (WIRELESS_EXT >= 18) 895 r8192_wx_set_mlme, /* MLME-- */ 896#else 897 NULL, 898#endif 899 dummy, /* SIOCGIWAPLIST -- deprecated */ 900 r8192_wx_set_scan, /* SIOCSIWSCAN */ 901 r8192_wx_get_scan, /* SIOCGIWSCAN */ 902 r8192_wx_set_essid, /* SIOCSIWESSID */ 903 r8192_wx_get_essid, /* SIOCGIWESSID */ 904 dummy, /* SIOCSIWNICKN */ 905 dummy, /* SIOCGIWNICKN */ 906 NULL, /* -- hole -- */ 907 NULL, /* -- hole -- */ 908 r8192_wx_set_rate, /* SIOCSIWRATE */ 909 r8192_wx_get_rate, /* SIOCGIWRATE */ 910 r8192_wx_set_rts, /* SIOCSIWRTS */ 911 r8192_wx_get_rts, /* SIOCGIWRTS */ 912 r8192_wx_set_frag, /* SIOCSIWFRAG */ 913 r8192_wx_get_frag, /* SIOCGIWFRAG */ 914 dummy, /* SIOCSIWTXPOW */ 915 dummy, /* SIOCGIWTXPOW */ 916 r8192_wx_set_retry, /* SIOCSIWRETRY */ 917 r8192_wx_get_retry, /* SIOCGIWRETRY */ 918 r8192_wx_set_enc, /* SIOCSIWENCODE */ 919 r8192_wx_get_enc, /* SIOCGIWENCODE */ 920 r8192_wx_set_power, /* SIOCSIWPOWER */ 921 r8192_wx_get_power, /* SIOCGIWPOWER */ 922 NULL, /*---hole---*/ 923 NULL, /*---hole---*/ 924 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ 925 NULL, /* SIOCSIWGENIE */ 926 927#if (WIRELESS_EXT >= 18) 928 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */ 929 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */ 930 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 931 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ 932#else 933 NULL, 934 NULL, 935 NULL, 936 NULL, 937#endif 938 NULL, /* SIOCSIWPMKSA */ 939 NULL, /*---hole---*/ 940 941}; 942 943 944static const struct iw_priv_args r8192_private_args[] = { 945 946 { 947 SIOCIWFIRSTPRIV + 0x0, 948 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" 949 }, 950 951 { 952 SIOCIWFIRSTPRIV + 0x1, 953 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" 954 955 }, 956 { 957 SIOCIWFIRSTPRIV + 0x2, 958 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 959 }, 960 { 961 SIOCIWFIRSTPRIV + 0x3, 962 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" 963 964 } 965 966}; 967 968 969static iw_handler r8192_private_handler[] = { 970// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */ 971 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ 972// r8192_wx_set_forceassociate, 973// r8192_wx_set_beaconinterval, 974// r8192_wx_set_monitor_type, 975 r8192_wx_set_scan_type, 976 r8192_wx_set_rawtx, 977 //r8192_wx_null, 978 r8192_wx_force_reset, 979}; 980 981//#if WIRELESS_EXT >= 17 982struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 983{ 984 struct r8192_priv *priv = ieee80211_priv(dev); 985 struct ieee80211_device *ieee = priv->ieee80211; 986 struct iw_statistics *wstats = &priv->wstats; 987 int tmp_level = 0; 988 int tmp_qual = 0; 989 int tmp_noise = 0; 990 if(ieee->state < IEEE80211_LINKED) 991 { 992 wstats->qual.qual = 0; 993 wstats->qual.level = 0; 994 wstats->qual.noise = 0; 995 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 996 return wstats; 997 } 998 999 tmp_level = (&ieee->current_network)->stats.rssi; 1000 tmp_qual = (&ieee->current_network)->stats.signal; 1001 tmp_noise = (&ieee->current_network)->stats.noise; 1002 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); 1003 1004 wstats->qual.level = tmp_level; 1005 wstats->qual.qual = tmp_qual; 1006 wstats->qual.noise = tmp_noise; 1007 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; 1008 return wstats; 1009} 1010//#endif 1011 1012 1013struct iw_handler_def r8192_wx_handlers_def={ 1014 .standard = r8192_wx_handlers, 1015 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 1016 .private = r8192_private_handler, 1017 .num_private = ARRAY_SIZE(r8192_private_handler), 1018 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 1019#if WIRELESS_EXT >= 17 1020 .get_wireless_stats = r8192_get_wireless_stats, 1021#endif 1022 .private_args = (struct iw_priv_args *)r8192_private_args, 1023}; 1024