r8192U_wx.c revision e6c1ef6ce9dadadd1961578487f9c76fa134b020
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 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 307 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { 308 range->freq[val].i = i + 1; 309 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; 321 range->num_channels = val; 322 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 323 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 324 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); 333 struct ieee80211_device *ieee = priv->ieee80211; 334 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 { 342 struct iw_scan_req *req = (struct iw_scan_req *)b; 343 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){ 354 priv->ieee80211->scanning = 0; 355 ieee80211_softmac_scan_syncro(priv->ieee80211); 356 ret = 0; 357 } 358 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 559 switch (wrqu->encoding.flags & IW_ENCODE_INDEX){ 560 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; 566 } 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 606 struct r8192_priv *priv = ieee80211_priv(dev); 607 int *parms=(int *)p; 608 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 655 rtl8192_commit(dev); 656 /* 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 733//hw security need to reorganized. 734static int r8192_wx_set_enc_ext(struct net_device *dev, 735 struct iw_request_info *info, 736 union iwreq_data *wrqu, char *extra) 737{ 738 int ret=0; 739 struct r8192_priv *priv = ieee80211_priv(dev); 740 struct ieee80211_device *ieee = priv->ieee80211; 741 //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; 753 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 } 771 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 772 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 801 (u8 *)ieee->ap_mac_addr, //MacAddr 802 0, //DefaultKey 803 key); //KeyContent 804 } 805 806 807 } 808 809end_hw_sec: 810 811 up(&priv->wx_sem); 812 return ret; 813 814} 815static int r8192_wx_set_auth(struct net_device *dev, 816 struct iw_request_info *info, 817 union iwreq_data *data, char *extra) 818{ 819 int ret=0; 820 //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); 825 return ret; 826} 827 828static int r8192_wx_set_mlme(struct net_device *dev, 829 struct iw_request_info *info, 830 union iwreq_data *wrqu, char *extra) 831{ 832 //printk("====>%s()\n", __FUNCTION__); 833 834 int ret=0; 835 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); 840 return ret; 841} 842 843static int r8192_wx_set_gen_ie(struct net_device *dev, 844 struct iw_request_info *info, 845 union iwreq_data *data, char *extra) 846{ 847 //printk("====>%s(), len:%d\n", __FUNCTION__, data->length); 848 int ret=0; 849 struct r8192_priv *priv = ieee80211_priv(dev); 850 down(&priv->wx_sem); 851 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 852 up(&priv->wx_sem); 853 //printk("<======%s(), ret:%d\n", __FUNCTION__, ret); 854 return ret; 855 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{ 868 NULL, /* SIOCSIWCOMMIT */ 869 r8192_wx_get_name, /* SIOCGIWNAME */ 870 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 */ 888 r8192_wx_set_wap, /* SIOCSIWAP */ 889 r8192_wx_get_wap, /* SIOCGIWAP */ 890 r8192_wx_set_mlme, /* MLME-- */ 891 dummy, /* SIOCGIWAPLIST -- deprecated */ 892 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 */ 914 NULL, /*---hole---*/ 915 NULL, /*---hole---*/ 916 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ 917 NULL, /* SIOCSIWGENIE */ 918 919 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 */ 923 NULL, /* SIOCSIWPMKSA */ 924 NULL, /*---hole---*/ 925 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" 944 }, 945 { 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, 962 //r8192_wx_null, 963 r8192_wx_force_reset, 964}; 965 966struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 967{ 968 struct r8192_priv *priv = ieee80211_priv(dev); 969 struct ieee80211_device *ieee = priv->ieee80211; 970 struct iw_statistics *wstats = &priv->wstats; 971 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; 979 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 980 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; 991 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; 992 return wstats; 993} 994 995 996struct iw_handler_def r8192_wx_handlers_def={ 997 .standard = r8192_wx_handlers, 998 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 999 .private = r8192_private_handler, 1000 .num_private = ARRAY_SIZE(r8192_private_handler), 1001 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 1002 .get_wireless_stats = r8192_get_wireless_stats, 1003 .private_args = (struct iw_priv_args *)r8192_private_args, 1004}; 1005