r8192U_wx.c revision e00b8fdca8c04eb39bd2ff8a68c7154135e4e179
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 //printk("==**&*&*&**===>scan set ssid:%s\n", req->essid); 345 ieee->current_network.ssid_len = req->essid_len; 346 memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 347 //printk("=====>network ssid:%s\n", ieee->current_network.ssid); 348 } 349 } 350 351 down(&priv->wx_sem); 352 if (priv->ieee80211->state != IEEE80211_LINKED) { 353 priv->ieee80211->scanning = 0; 354 ieee80211_softmac_scan_syncro(priv->ieee80211); 355 ret = 0; 356 } else { 357 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b); 358 } 359 up(&priv->wx_sem); 360 return ret; 361} 362 363 364static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 365 union iwreq_data *wrqu, char *b) 366{ 367 368 int ret; 369 struct r8192_priv *priv = ieee80211_priv(dev); 370 371 if (!priv->up) 372 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) 534 return -ENETDOWN; 535 536 down(&priv->wx_sem); 537 538 RT_TRACE(COMP_SEC, "Setting SW wep key"); 539 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); 540 541 up(&priv->wx_sem); 542 543 544 545 //sometimes, the length is zero while we do not type key value 546 if (wrqu->encoding.length != 0) { 547 548 for (i = 0; i < 4; i++) { 549 hwkey[i] |= key[4*i+0]&mask; 550 if (i == 1 && (4*i+1) == wrqu->encoding.length) 551 mask = 0x00; 552 if (i == 3 && (4*i+1) == wrqu->encoding.length) 553 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: 564 key_idx = ieee->tx_keyidx; 565 break; 566 case 1: 567 key_idx = 0; 568 break; 569 case 2: 570 key_idx = 1; 571 break; 572 case 3: 573 key_idx = 2; 574 break; 575 case 4: 576 key_idx = 3; 577 break; 578 default: 579 break; 580 } 581 582 if (wrqu->encoding.length == 0x5) { 583 ieee->pairwise_key_type = KEY_TYPE_WEP40; 584 EnableHWSecurityConfig8192(dev); 585 586 setKey(dev, 587 key_idx, //EntryNo 588 key_idx, //KeyIndex 589 KEY_TYPE_WEP40, //KeyType 590 zero_addr[key_idx], 591 0, //DefaultKey 592 hwkey); //KeyContent 593 594 } 595 596 else if (wrqu->encoding.length == 0xd) { 597 ieee->pairwise_key_type = KEY_TYPE_WEP104; 598 EnableHWSecurityConfig8192(dev); 599 600 setKey(dev, 601 key_idx, //EntryNo 602 key_idx, //KeyIndex 603 KEY_TYPE_WEP104, //KeyType 604 zero_addr[key_idx], 605 0, //DefaultKey 606 hwkey); //KeyContent 607 608 } else { 609 printk("wrong type in WEP, not WEP40 and WEP104\n"); 610 } 611 612 } 613 614 return ret; 615} 616 617 618static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, 619 union iwreq_data *wrqu, char *p) 620{ 621 622 struct r8192_priv *priv = ieee80211_priv(dev); 623 int *parms = (int *)p; 624 int mode = parms[0]; 625 626 priv->ieee80211->active_scan = mode; 627 628 return 1; 629} 630 631 632 633static int r8192_wx_set_retry(struct net_device *dev, 634 struct iw_request_info *info, 635 union iwreq_data *wrqu, char *extra) 636{ 637 struct r8192_priv *priv = ieee80211_priv(dev); 638 int err = 0; 639 640 down(&priv->wx_sem); 641 642 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 643 wrqu->retry.disabled){ 644 err = -EINVAL; 645 goto exit; 646 } 647 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { 648 err = -EINVAL; 649 goto exit; 650 } 651 652 if (wrqu->retry.value > R8180_MAX_RETRY) { 653 err = -EINVAL; 654 goto exit; 655 } 656 if (wrqu->retry.flags & IW_RETRY_MAX) { 657 priv->retry_rts = wrqu->retry.value; 658 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 659 660 } else { 661 priv->retry_data = wrqu->retry.value; 662 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 663 } 664 665 /* FIXME ! 666 * We might try to write directly the TX config register 667 * or to restart just the (R)TX process. 668 * I'm unsure if whole reset is really needed 669 */ 670 671 rtl8192_commit(dev); 672 /* 673 if(priv->up){ 674 rtl8180_rtx_disable(dev); 675 rtl8180_rx_enable(dev); 676 rtl8180_tx_enable(dev); 677 678 } 679 */ 680exit: 681 up(&priv->wx_sem); 682 683 return err; 684} 685 686static int r8192_wx_get_retry(struct net_device *dev, 687 struct iw_request_info *info, 688 union iwreq_data *wrqu, char *extra) 689{ 690 struct r8192_priv *priv = ieee80211_priv(dev); 691 692 693 wrqu->retry.disabled = 0; /* can't be disabled */ 694 695 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 696 IW_RETRY_LIFETIME) 697 return -EINVAL; 698 699 if (wrqu->retry.flags & IW_RETRY_MAX) { 700 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 701 wrqu->retry.value = priv->retry_rts; 702 } else { 703 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; 704 wrqu->retry.value = priv->retry_data; 705 } 706 //printk("returning %d",wrqu->retry.value); 707 708 709 return 0; 710} 711 712static int r8192_wx_get_sens(struct net_device *dev, 713 struct iw_request_info *info, 714 union iwreq_data *wrqu, char *extra) 715{ 716 struct r8192_priv *priv = ieee80211_priv(dev); 717 if (priv->rf_set_sens == NULL) 718 return -1; /* we have not this support for this radio */ 719 wrqu->sens.value = priv->sens; 720 return 0; 721} 722 723 724static int r8192_wx_set_sens(struct net_device *dev, 725 struct iw_request_info *info, 726 union iwreq_data *wrqu, char *extra) 727{ 728 729 struct r8192_priv *priv = ieee80211_priv(dev); 730 731 short err = 0; 732 down(&priv->wx_sem); 733 //DMESG("attempt to set sensivity to %ddb",wrqu->sens.value); 734 if (priv->rf_set_sens == NULL) { 735 err = -1; /* we have not this support for this radio */ 736 goto exit; 737 } 738 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) 739 priv->sens = wrqu->sens.value; 740 else 741 err = -EINVAL; 742 743exit: 744 up(&priv->wx_sem); 745 746 return err; 747} 748 749//hw security need to reorganized. 750static int r8192_wx_set_enc_ext(struct net_device *dev, 751 struct iw_request_info *info, 752 union iwreq_data *wrqu, char *extra) 753{ 754 int ret = 0; 755 struct r8192_priv *priv = ieee80211_priv(dev); 756 struct ieee80211_device *ieee = priv->ieee80211; 757 //printk("===>%s()\n", __func__); 758 759 760 down(&priv->wx_sem); 761 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); 762 763 { 764 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 765 u8 zero[6] = {0}; 766 u32 key[4] = {0}; 767 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 768 struct iw_point *encoding = &wrqu->encoding; 769 u8 idx = 0, alg = 0, group = 0; 770 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE) 771 //none is not allowed to use hwsec WB 2008.07.01 772 goto end_hw_sec; 773 774 // as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; 775 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 776 idx = encoding->flags & IW_ENCODE_INDEX; 777 if (idx) 778 idx--; 779 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 780 781 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) { 782 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) 783 alg = KEY_TYPE_WEP104; 784 ieee->pairwise_key_type = alg; 785 EnableHWSecurityConfig8192(dev); 786 } 787 memcpy((u8 *)key, ext->key, 16); //we only get 16 bytes key.why? WB 2008.7.1 788 789 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { 790 791 setKey(dev, 792 idx,//EntryNo 793 idx, //KeyIndex 794 alg, //KeyType 795 zero, //MacAddr 796 0, //DefaultKey 797 key); //KeyContent 798 } else if (group) { 799 ieee->group_key_type = alg; 800 setKey(dev, 801 idx,//EntryNo 802 idx, //KeyIndex 803 alg, //KeyType 804 broadcast_addr, //MacAddr 805 0, //DefaultKey 806 key); //KeyContent 807 } else {//pairwise key 808 setKey(dev, 809 4,//EntryNo 810 idx, //KeyIndex 811 alg, //KeyType 812 (u8 *)ieee->ap_mac_addr, //MacAddr 813 0, //DefaultKey 814 key); //KeyContent 815 } 816 817 818 } 819 820end_hw_sec: 821 822 up(&priv->wx_sem); 823 return ret; 824 825} 826static int r8192_wx_set_auth(struct net_device *dev, 827 struct iw_request_info *info, 828 union iwreq_data *data, char *extra) 829{ 830 int ret = 0; 831 //printk("====>%s()\n", __func__); 832 struct r8192_priv *priv = ieee80211_priv(dev); 833 down(&priv->wx_sem); 834 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 835 up(&priv->wx_sem); 836 return ret; 837} 838 839static int r8192_wx_set_mlme(struct net_device *dev, 840 struct iw_request_info *info, 841 union iwreq_data *wrqu, char *extra) 842{ 843 //printk("====>%s()\n", __func__); 844 845 int ret = 0; 846 struct r8192_priv *priv = ieee80211_priv(dev); 847 down(&priv->wx_sem); 848 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); 849 850 up(&priv->wx_sem); 851 return ret; 852} 853 854static int r8192_wx_set_gen_ie(struct net_device *dev, 855 struct iw_request_info *info, 856 union iwreq_data *data, char *extra) 857{ 858 //printk("====>%s(), len:%d\n", __func__, data->length); 859 int ret = 0; 860 struct r8192_priv *priv = ieee80211_priv(dev); 861 down(&priv->wx_sem); 862 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 863 up(&priv->wx_sem); 864 //printk("<======%s(), ret:%d\n", __func__, ret); 865 return ret; 866 867 868} 869 870static int dummy(struct net_device *dev, struct iw_request_info *a, 871 union iwreq_data *wrqu, char *b) 872{ 873 return -1; 874} 875 876 877static iw_handler r8192_wx_handlers[] = { 878 NULL, /* SIOCSIWCOMMIT */ 879 r8192_wx_get_name, /* SIOCGIWNAME */ 880 dummy, /* SIOCSIWNWID */ 881 dummy, /* SIOCGIWNWID */ 882 r8192_wx_set_freq, /* SIOCSIWFREQ */ 883 r8192_wx_get_freq, /* SIOCGIWFREQ */ 884 r8192_wx_set_mode, /* SIOCSIWMODE */ 885 r8192_wx_get_mode, /* SIOCGIWMODE */ 886 r8192_wx_set_sens, /* SIOCSIWSENS */ 887 r8192_wx_get_sens, /* SIOCGIWSENS */ 888 NULL, /* SIOCSIWRANGE */ 889 rtl8180_wx_get_range, /* SIOCGIWRANGE */ 890 NULL, /* SIOCSIWPRIV */ 891 NULL, /* SIOCGIWPRIV */ 892 NULL, /* SIOCSIWSTATS */ 893 NULL, /* SIOCGIWSTATS */ 894 dummy, /* SIOCSIWSPY */ 895 dummy, /* SIOCGIWSPY */ 896 NULL, /* SIOCGIWTHRSPY */ 897 NULL, /* SIOCWIWTHRSPY */ 898 r8192_wx_set_wap, /* SIOCSIWAP */ 899 r8192_wx_get_wap, /* SIOCGIWAP */ 900 r8192_wx_set_mlme, /* MLME-- */ 901 dummy, /* SIOCGIWAPLIST -- deprecated */ 902 r8192_wx_set_scan, /* SIOCSIWSCAN */ 903 r8192_wx_get_scan, /* SIOCGIWSCAN */ 904 r8192_wx_set_essid, /* SIOCSIWESSID */ 905 r8192_wx_get_essid, /* SIOCGIWESSID */ 906 dummy, /* SIOCSIWNICKN */ 907 dummy, /* SIOCGIWNICKN */ 908 NULL, /* -- hole -- */ 909 NULL, /* -- hole -- */ 910 r8192_wx_set_rate, /* SIOCSIWRATE */ 911 r8192_wx_get_rate, /* SIOCGIWRATE */ 912 r8192_wx_set_rts, /* SIOCSIWRTS */ 913 r8192_wx_get_rts, /* SIOCGIWRTS */ 914 r8192_wx_set_frag, /* SIOCSIWFRAG */ 915 r8192_wx_get_frag, /* SIOCGIWFRAG */ 916 dummy, /* SIOCSIWTXPOW */ 917 dummy, /* SIOCGIWTXPOW */ 918 r8192_wx_set_retry, /* SIOCSIWRETRY */ 919 r8192_wx_get_retry, /* SIOCGIWRETRY */ 920 r8192_wx_set_enc, /* SIOCSIWENCODE */ 921 r8192_wx_get_enc, /* SIOCGIWENCODE */ 922 r8192_wx_set_power, /* SIOCSIWPOWER */ 923 r8192_wx_get_power, /* SIOCGIWPOWER */ 924 NULL, /*---hole---*/ 925 NULL, /*---hole---*/ 926 r8192_wx_set_gen_ie,//NULL, /* SIOCSIWGENIE */ 927 NULL, /* SIOCSIWGENIE */ 928 929 r8192_wx_set_auth,//NULL, /* SIOCSIWAUTH */ 930 NULL,//r8192_wx_get_auth,//NULL, /* SIOCSIWAUTH */ 931 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 932 NULL,//r8192_wx_get_enc_ext,//NULL, /* SIOCSIWENCODEEXT */ 933 NULL, /* SIOCSIWPMKSA */ 934 NULL, /*---hole---*/ 935 936}; 937 938 939static const struct iw_priv_args r8192_private_args[] = { 940 941 { 942 SIOCIWFIRSTPRIV + 0x0, 943 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" 944 }, 945 946 { 947 SIOCIWFIRSTPRIV + 0x1, 948 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" 949 950 }, 951 { 952 SIOCIWFIRSTPRIV + 0x2, 953 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 954 }, 955 { 956 SIOCIWFIRSTPRIV + 0x3, 957 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" 958 959 } 960 961}; 962 963 964static iw_handler r8192_private_handler[] = { 965// r8192_wx_set_monitor, /* SIOCIWFIRSTPRIV */ 966 r8192_wx_set_crcmon, /*SIOCIWSECONDPRIV*/ 967// r8192_wx_set_forceassociate, 968// r8192_wx_set_beaconinterval, 969// r8192_wx_set_monitor_type, 970 r8192_wx_set_scan_type, 971 r8192_wx_set_rawtx, 972 //r8192_wx_null, 973 r8192_wx_force_reset, 974}; 975 976struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 977{ 978 struct r8192_priv *priv = ieee80211_priv(dev); 979 struct ieee80211_device *ieee = priv->ieee80211; 980 struct iw_statistics *wstats = &priv->wstats; 981 int tmp_level = 0; 982 int tmp_qual = 0; 983 int tmp_noise = 0; 984 if (ieee->state < IEEE80211_LINKED) { 985 wstats->qual.qual = 0; 986 wstats->qual.level = 0; 987 wstats->qual.noise = 0; 988 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 989 return wstats; 990 } 991 992 tmp_level = (&ieee->current_network)->stats.rssi; 993 tmp_qual = (&ieee->current_network)->stats.signal; 994 tmp_noise = (&ieee->current_network)->stats.noise; 995 //printk("level:%d, qual:%d, noise:%d\n", tmp_level, tmp_qual, tmp_noise); 996 997 wstats->qual.level = tmp_level; 998 wstats->qual.qual = tmp_qual; 999 wstats->qual.noise = tmp_noise; 1000 wstats->qual.updated = IW_QUAL_ALL_UPDATED| IW_QUAL_DBM; 1001 return wstats; 1002} 1003 1004 1005struct iw_handler_def r8192_wx_handlers_def = { 1006 .standard = r8192_wx_handlers, 1007 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 1008 .private = r8192_private_handler, 1009 .num_private = ARRAY_SIZE(r8192_private_handler), 1010 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 1011 .get_wireless_stats = r8192_get_wireless_stats, 1012 .private_args = (struct iw_priv_args *)r8192_private_args, 1013}; 1014