r8192U_wx.c revision 2808a02332b8249324a78565421abf1059b4be9d
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", __func__, *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) 337 return -ENETDOWN; 338 339 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true) 340 return -EAGAIN; 341 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 342 struct iw_scan_req *req = (struct iw_scan_req *)b; 343 if (req->essid_len) { 344 ieee->current_network.ssid_len = req->essid_len; 345 memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 346 } 347 } 348 349 down(&priv->wx_sem); 350 if (priv->ieee80211->state != IEEE80211_LINKED) { 351 priv->ieee80211->scanning = 0; 352 ieee80211_softmac_scan_syncro(priv->ieee80211); 353 ret = 0; 354 } else { 355 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b); 356 } 357 up(&priv->wx_sem); 358 return ret; 359} 360 361 362static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 363 union iwreq_data *wrqu, char *b) 364{ 365 366 int ret; 367 struct r8192_priv *priv = ieee80211_priv(dev); 368 369 if (!priv->up) 370 return -ENETDOWN; 371 372 down(&priv->wx_sem); 373 374 ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b); 375 376 up(&priv->wx_sem); 377 378 return ret; 379} 380 381static int r8192_wx_set_essid(struct net_device *dev, 382 struct iw_request_info *a, 383 union iwreq_data *wrqu, char *b) 384{ 385 struct r8192_priv *priv = ieee80211_priv(dev); 386 int ret; 387 down(&priv->wx_sem); 388 389 ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b); 390 391 up(&priv->wx_sem); 392 393 return ret; 394} 395 396 397 398 399static int r8192_wx_get_essid(struct net_device *dev, 400 struct iw_request_info *a, 401 union iwreq_data *wrqu, char *b) 402{ 403 int ret; 404 struct r8192_priv *priv = ieee80211_priv(dev); 405 406 down(&priv->wx_sem); 407 408 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); 409 410 up(&priv->wx_sem); 411 412 return ret; 413} 414 415 416static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, 417 union iwreq_data *wrqu, char *b) 418{ 419 int ret; 420 struct r8192_priv *priv = ieee80211_priv(dev); 421 422 down(&priv->wx_sem); 423 424 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); 425 426 up(&priv->wx_sem); 427 return ret; 428} 429 430static int r8192_wx_get_name(struct net_device *dev, 431 struct iw_request_info *info, 432 union iwreq_data *wrqu, char *extra) 433{ 434 struct r8192_priv *priv = ieee80211_priv(dev); 435 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); 436} 437 438 439static int r8192_wx_set_frag(struct net_device *dev, 440 struct iw_request_info *info, 441 union iwreq_data *wrqu, char *extra) 442{ 443 struct r8192_priv *priv = ieee80211_priv(dev); 444 445 if (wrqu->frag.disabled) 446 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; 447 else { 448 if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 449 wrqu->frag.value > MAX_FRAG_THRESHOLD) 450 return -EINVAL; 451 452 priv->ieee80211->fts = wrqu->frag.value & ~0x1; 453 } 454 455 return 0; 456} 457 458 459static int r8192_wx_get_frag(struct net_device *dev, 460 struct iw_request_info *info, 461 union iwreq_data *wrqu, char *extra) 462{ 463 struct r8192_priv *priv = ieee80211_priv(dev); 464 465 wrqu->frag.value = priv->ieee80211->fts; 466 wrqu->frag.fixed = 0; /* no auto select */ 467 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); 468 469 return 0; 470} 471 472 473static int r8192_wx_set_wap(struct net_device *dev, 474 struct iw_request_info *info, 475 union iwreq_data *awrq, 476 char *extra) 477{ 478 479 int ret; 480 struct r8192_priv *priv = ieee80211_priv(dev); 481// struct sockaddr *temp = (struct sockaddr *)awrq; 482 down(&priv->wx_sem); 483 484 ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra); 485 486 up(&priv->wx_sem); 487 488 return ret; 489 490} 491 492 493static int r8192_wx_get_wap(struct net_device *dev, 494 struct iw_request_info *info, 495 union iwreq_data *wrqu, char *extra) 496{ 497 struct r8192_priv *priv = ieee80211_priv(dev); 498 499 return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra); 500} 501 502 503static int r8192_wx_get_enc(struct net_device *dev, 504 struct iw_request_info *info, 505 union iwreq_data *wrqu, char *key) 506{ 507 struct r8192_priv *priv = ieee80211_priv(dev); 508 509 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); 510} 511 512static int r8192_wx_set_enc(struct net_device *dev, 513 struct iw_request_info *info, 514 union iwreq_data *wrqu, char *key) 515{ 516 struct r8192_priv *priv = ieee80211_priv(dev); 517 struct ieee80211_device *ieee = priv->ieee80211; 518 int ret; 519 520 //u32 TargetContent; 521 u32 hwkey[4] = {0, 0, 0, 0}; 522 u8 mask = 0xff; 523 u32 key_idx = 0; 524 //u8 broadcast_addr[6] ={ 0xff,0xff,0xff,0xff,0xff,0xff}; 525 u8 zero_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 526 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 527 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 528 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; 529 int i; 530 531 if (!priv->up) 532 return -ENETDOWN; 533 534 down(&priv->wx_sem); 535 536 RT_TRACE(COMP_SEC, "Setting SW wep key"); 537 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); 538 539 up(&priv->wx_sem); 540 541 542 543 //sometimes, the length is zero while we do not type key value 544 if (wrqu->encoding.length != 0) { 545 546 for (i = 0; i < 4; i++) { 547 hwkey[i] |= key[4*i+0]&mask; 548 if (i == 1 && (4*i+1) == wrqu->encoding.length) 549 mask = 0x00; 550 if (i == 3 && (4*i+1) == wrqu->encoding.length) 551 mask = 0x00; 552 hwkey[i] |= (key[4*i+1]&mask)<<8; 553 hwkey[i] |= (key[4*i+2]&mask)<<16; 554 hwkey[i] |= (key[4*i+3]&mask)<<24; 555 } 556 557 #define CONF_WEP40 0x4 558 #define CONF_WEP104 0x14 559 560 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) { 561 case 0: 562 key_idx = ieee->tx_keyidx; 563 break; 564 case 1: 565 key_idx = 0; 566 break; 567 case 2: 568 key_idx = 1; 569 break; 570 case 3: 571 key_idx = 2; 572 break; 573 case 4: 574 key_idx = 3; 575 break; 576 default: 577 break; 578 } 579 580 if (wrqu->encoding.length == 0x5) { 581 ieee->pairwise_key_type = KEY_TYPE_WEP40; 582 EnableHWSecurityConfig8192(dev); 583 584 setKey(dev, 585 key_idx, //EntryNo 586 key_idx, //KeyIndex 587 KEY_TYPE_WEP40, //KeyType 588 zero_addr[key_idx], 589 0, //DefaultKey 590 hwkey); //KeyContent 591 592 } 593 594 else if (wrqu->encoding.length == 0xd) { 595 ieee->pairwise_key_type = KEY_TYPE_WEP104; 596 EnableHWSecurityConfig8192(dev); 597 598 setKey(dev, 599 key_idx, //EntryNo 600 key_idx, //KeyIndex 601 KEY_TYPE_WEP104, //KeyType 602 zero_addr[key_idx], 603 0, //DefaultKey 604 hwkey); //KeyContent 605 606 } else { 607 printk("wrong type in WEP, not WEP40 and WEP104\n"); 608 } 609 610 } 611 612 return ret; 613} 614 615 616static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, 617 union iwreq_data *wrqu, char *p) 618{ 619 620 struct r8192_priv *priv = ieee80211_priv(dev); 621 int *parms = (int *)p; 622 int mode = parms[0]; 623 624 priv->ieee80211->active_scan = mode; 625 626 return 1; 627} 628 629 630 631static int r8192_wx_set_retry(struct net_device *dev, 632 struct iw_request_info *info, 633 union iwreq_data *wrqu, char *extra) 634{ 635 struct r8192_priv *priv = ieee80211_priv(dev); 636 int err = 0; 637 638 down(&priv->wx_sem); 639 640 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 641 wrqu->retry.disabled){ 642 err = -EINVAL; 643 goto exit; 644 } 645 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { 646 err = -EINVAL; 647 goto exit; 648 } 649 650 if (wrqu->retry.value > R8180_MAX_RETRY) { 651 err = -EINVAL; 652 goto exit; 653 } 654 if (wrqu->retry.flags & IW_RETRY_MAX) { 655 priv->retry_rts = wrqu->retry.value; 656 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 657 658 } else { 659 priv->retry_data = wrqu->retry.value; 660 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 661 } 662 663 /* FIXME ! 664 * We might try to write directly the TX config register 665 * or to restart just the (R)TX process. 666 * I'm unsure if whole reset is really needed 667 */ 668 669 rtl8192_commit(dev); 670 /* 671 if(priv->up){ 672 rtl8180_rtx_disable(dev); 673 rtl8180_rx_enable(dev); 674 rtl8180_tx_enable(dev); 675 676 } 677 */ 678exit: 679 up(&priv->wx_sem); 680 681 return err; 682} 683 684static int r8192_wx_get_retry(struct net_device *dev, 685 struct iw_request_info *info, 686 union iwreq_data *wrqu, char *extra) 687{ 688 struct r8192_priv *priv = ieee80211_priv(dev); 689 690 691 wrqu->retry.disabled = 0; /* can't be disabled */ 692 693 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 694 IW_RETRY_LIFETIME) 695 return -EINVAL; 696 697 if (wrqu->retry.flags & IW_RETRY_MAX) { 698 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 699 wrqu->retry.value = priv->retry_rts; 700 } else { 701 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; 702 wrqu->retry.value = priv->retry_data; 703 } 704 705 706 return 0; 707} 708 709static int r8192_wx_get_sens(struct net_device *dev, 710 struct iw_request_info *info, 711 union iwreq_data *wrqu, char *extra) 712{ 713 struct r8192_priv *priv = ieee80211_priv(dev); 714 if (priv->rf_set_sens == NULL) 715 return -1; /* we have not this support for this radio */ 716 wrqu->sens.value = priv->sens; 717 return 0; 718} 719 720 721static int r8192_wx_set_sens(struct net_device *dev, 722 struct iw_request_info *info, 723 union iwreq_data *wrqu, char *extra) 724{ 725 726 struct r8192_priv *priv = ieee80211_priv(dev); 727 728 short err = 0; 729 down(&priv->wx_sem); 730 if (priv->rf_set_sens == NULL) { 731 err = -1; /* we have not this support for this radio */ 732 goto exit; 733 } 734 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) 735 priv->sens = wrqu->sens.value; 736 else 737 err = -EINVAL; 738 739exit: 740 up(&priv->wx_sem); 741 742 return err; 743} 744 745//hw security need to reorganized. 746static int r8192_wx_set_enc_ext(struct net_device *dev, 747 struct iw_request_info *info, 748 union iwreq_data *wrqu, char *extra) 749{ 750 int ret = 0; 751 struct r8192_priv *priv = ieee80211_priv(dev); 752 struct ieee80211_device *ieee = priv->ieee80211; 753 754 755 down(&priv->wx_sem); 756 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); 757 758 { 759 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 760 u8 zero[6] = {0}; 761 u32 key[4] = {0}; 762 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 763 struct iw_point *encoding = &wrqu->encoding; 764 u8 idx = 0, alg = 0, group = 0; 765 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE) 766 //none is not allowed to use hwsec WB 2008.07.01 767 goto end_hw_sec; 768 769 // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; 770 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 771 idx = encoding->flags & IW_ENCODE_INDEX; 772 if (idx) 773 idx--; 774 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 775 776 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) { 777 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) 778 alg = KEY_TYPE_WEP104; 779 ieee->pairwise_key_type = alg; 780 EnableHWSecurityConfig8192(dev); 781 } 782 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 783 784 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { 785 786 setKey(dev, 787 idx,//EntryNo 788 idx, //KeyIndex 789 alg, //KeyType 790 zero, //MacAddr 791 0, //DefaultKey 792 key); //KeyContent 793 } else if (group) { 794 ieee->group_key_type = alg; 795 setKey(dev, 796 idx,//EntryNo 797 idx, //KeyIndex 798 alg, //KeyType 799 broadcast_addr, //MacAddr 800 0, //DefaultKey 801 key); //KeyContent 802 } else {//pairwise key 803 setKey(dev, 804 4,//EntryNo 805 idx, //KeyIndex 806 alg, //KeyType 807 (u8 *)ieee->ap_mac_addr, //MacAddr 808 0, //DefaultKey 809 key); //KeyContent 810 } 811 812 813 } 814 815end_hw_sec: 816 817 up(&priv->wx_sem); 818 return ret; 819 820} 821static int r8192_wx_set_auth(struct net_device *dev, 822 struct iw_request_info *info, 823 union iwreq_data *data, char *extra) 824{ 825 int ret = 0; 826 struct r8192_priv *priv = ieee80211_priv(dev); 827 down(&priv->wx_sem); 828 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 829 up(&priv->wx_sem); 830 return ret; 831} 832 833static int r8192_wx_set_mlme(struct net_device *dev, 834 struct iw_request_info *info, 835 union iwreq_data *wrqu, char *extra) 836{ 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 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 int ret = 0; 852 struct r8192_priv *priv = ieee80211_priv(dev); 853 down(&priv->wx_sem); 854 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 855 up(&priv->wx_sem); 856 return ret; 857 858 859} 860 861static int dummy(struct net_device *dev, struct iw_request_info *a, 862 union iwreq_data *wrqu, char *b) 863{ 864 return -1; 865} 866 867 868static iw_handler r8192_wx_handlers[] = { 869 NULL, /* SIOCSIWCOMMIT */ 870 r8192_wx_get_name, /* SIOCGIWNAME */ 871 dummy, /* SIOCSIWNWID */ 872 dummy, /* SIOCGIWNWID */ 873 r8192_wx_set_freq, /* SIOCSIWFREQ */ 874 r8192_wx_get_freq, /* SIOCGIWFREQ */ 875 r8192_wx_set_mode, /* SIOCSIWMODE */ 876 r8192_wx_get_mode, /* SIOCGIWMODE */ 877 r8192_wx_set_sens, /* SIOCSIWSENS */ 878 r8192_wx_get_sens, /* SIOCGIWSENS */ 879 NULL, /* SIOCSIWRANGE */ 880 rtl8180_wx_get_range, /* SIOCGIWRANGE */ 881 NULL, /* SIOCSIWPRIV */ 882 NULL, /* SIOCGIWPRIV */ 883 NULL, /* SIOCSIWSTATS */ 884 NULL, /* SIOCGIWSTATS */ 885 dummy, /* SIOCSIWSPY */ 886 dummy, /* SIOCGIWSPY */ 887 NULL, /* SIOCGIWTHRSPY */ 888 NULL, /* SIOCWIWTHRSPY */ 889 r8192_wx_set_wap, /* SIOCSIWAP */ 890 r8192_wx_get_wap, /* SIOCGIWAP */ 891 r8192_wx_set_mlme, /* MLME-- */ 892 dummy, /* SIOCGIWAPLIST -- deprecated */ 893 r8192_wx_set_scan, /* SIOCSIWSCAN */ 894 r8192_wx_get_scan, /* SIOCGIWSCAN */ 895 r8192_wx_set_essid, /* SIOCSIWESSID */ 896 r8192_wx_get_essid, /* SIOCGIWESSID */ 897 dummy, /* SIOCSIWNICKN */ 898 dummy, /* SIOCGIWNICKN */ 899 NULL, /* -- hole -- */ 900 NULL, /* -- hole -- */ 901 r8192_wx_set_rate, /* SIOCSIWRATE */ 902 r8192_wx_get_rate, /* SIOCGIWRATE */ 903 r8192_wx_set_rts, /* SIOCSIWRTS */ 904 r8192_wx_get_rts, /* SIOCGIWRTS */ 905 r8192_wx_set_frag, /* SIOCSIWFRAG */ 906 r8192_wx_get_frag, /* SIOCGIWFRAG */ 907 dummy, /* SIOCSIWTXPOW */ 908 dummy, /* SIOCGIWTXPOW */ 909 r8192_wx_set_retry, /* SIOCSIWRETRY */ 910 r8192_wx_get_retry, /* SIOCGIWRETRY */ 911 r8192_wx_set_enc, /* SIOCSIWENCODE */ 912 r8192_wx_get_enc, /* SIOCGIWENCODE */ 913 r8192_wx_set_power, /* SIOCSIWPOWER */ 914 r8192_wx_get_power, /* SIOCGIWPOWER */ 915 NULL, /*---hole---*/ 916 NULL, /*---hole---*/ 917 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ 918 NULL, /* SIOCSIWGENIE */ 919 920 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */ 921 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */ 922 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 923 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ 924 NULL, /* SIOCSIWPMKSA */ 925 NULL, /*---hole---*/ 926 927}; 928 929 930static const struct iw_priv_args r8192_private_args[] = { 931 932 { 933 SIOCIWFIRSTPRIV + 0x0, 934 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" 935 }, 936 937 { 938 SIOCIWFIRSTPRIV + 0x1, 939 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" 940 941 }, 942 { 943 SIOCIWFIRSTPRIV + 0x2, 944 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 945 }, 946 { 947 SIOCIWFIRSTPRIV + 0x3, 948 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" 949 950 } 951 952}; 953 954 955static iw_handler r8192_private_handler[] = { 956// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */ 957 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ 958// r8192_wx_set_forceassociate, 959// r8192_wx_set_beaconinterval, 960// r8192_wx_set_monitor_type, 961 r8192_wx_set_scan_type, 962 r8192_wx_set_rawtx, 963 //r8192_wx_null, 964 r8192_wx_force_reset, 965}; 966 967struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 968{ 969 struct r8192_priv *priv = ieee80211_priv(dev); 970 struct ieee80211_device *ieee = priv->ieee80211; 971 struct iw_statistics *wstats = &priv->wstats; 972 int tmp_level = 0; 973 int tmp_qual = 0; 974 int tmp_noise = 0; 975 if (ieee->state < IEEE80211_LINKED) { 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 987 wstats->qual.level = tmp_level; 988 wstats->qual.qual = tmp_qual; 989 wstats->qual.noise = tmp_noise; 990 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; 991 return wstats; 992} 993 994 995struct iw_handler_def r8192_wx_handlers_def = { 996 .standard = r8192_wx_handlers, 997 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 998 .private = r8192_private_handler, 999 .num_private = ARRAY_SIZE(r8192_private_handler), 1000 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 1001 .get_wireless_stats = r8192_get_wireless_stats, 1002 .private_args = (struct iw_priv_args *)r8192_private_args, 1003}; 1004