r8192U_wx.c revision 0b5b4e223a4de2a006bf58fc5303cfa75484374e
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 61 return ieee80211_wx_get_rate(priv->ieee80211, info, wrqu, extra); 62} 63 64 65 66static int r8192_wx_set_rate(struct net_device *dev, 67 struct iw_request_info *info, 68 union iwreq_data *wrqu, char *extra) 69{ 70 int ret; 71 struct r8192_priv *priv = ieee80211_priv(dev); 72 73 down(&priv->wx_sem); 74 75 ret = ieee80211_wx_set_rate(priv->ieee80211, info, wrqu, extra); 76 77 up(&priv->wx_sem); 78 79 return ret; 80} 81 82 83static int r8192_wx_set_rts(struct net_device *dev, 84 struct iw_request_info *info, 85 union iwreq_data *wrqu, char *extra) 86{ 87 int ret; 88 struct r8192_priv *priv = ieee80211_priv(dev); 89 90 down(&priv->wx_sem); 91 92 ret = ieee80211_wx_set_rts(priv->ieee80211, info, wrqu, extra); 93 94 up(&priv->wx_sem); 95 96 return ret; 97} 98 99static int r8192_wx_get_rts(struct net_device *dev, 100 struct iw_request_info *info, 101 union iwreq_data *wrqu, char *extra) 102{ 103 struct r8192_priv *priv = ieee80211_priv(dev); 104 105 return ieee80211_wx_get_rts(priv->ieee80211, info, wrqu, extra); 106} 107 108static int r8192_wx_set_power(struct net_device *dev, 109 struct iw_request_info *info, 110 union iwreq_data *wrqu, char *extra) 111{ 112 int ret; 113 struct r8192_priv *priv = ieee80211_priv(dev); 114 115 down(&priv->wx_sem); 116 117 ret = ieee80211_wx_set_power(priv->ieee80211, info, wrqu, extra); 118 119 up(&priv->wx_sem); 120 121 return ret; 122} 123 124static int r8192_wx_get_power(struct net_device *dev, 125 struct iw_request_info *info, 126 union iwreq_data *wrqu, char *extra) 127{ 128 struct r8192_priv *priv = ieee80211_priv(dev); 129 130 return ieee80211_wx_get_power(priv->ieee80211, info, wrqu, extra); 131} 132 133static int r8192_wx_force_reset(struct net_device *dev, 134 struct iw_request_info *info, 135 union iwreq_data *wrqu, char *extra) 136{ 137 struct r8192_priv *priv = ieee80211_priv(dev); 138 139 down(&priv->wx_sem); 140 141 printk("%s(): force reset ! extra is %d\n", __func__, *extra); 142 priv->force_reset = *extra; 143 up(&priv->wx_sem); 144 return 0; 145 146} 147 148 149static int r8192_wx_set_rawtx(struct net_device *dev, 150 struct iw_request_info *info, 151 union iwreq_data *wrqu, char *extra) 152{ 153 struct r8192_priv *priv = ieee80211_priv(dev); 154 int ret; 155 156 down(&priv->wx_sem); 157 158 ret = ieee80211_wx_set_rawtx(priv->ieee80211, info, wrqu, extra); 159 160 up(&priv->wx_sem); 161 162 return ret; 163 164} 165 166static int r8192_wx_set_crcmon(struct net_device *dev, 167 struct iw_request_info *info, 168 union iwreq_data *wrqu, char *extra) 169{ 170 struct r8192_priv *priv = ieee80211_priv(dev); 171 int *parms = (int *)extra; 172 int enable = (parms[0] > 0); 173 short prev = priv->crcmon; 174 175 down(&priv->wx_sem); 176 177 if (enable) 178 priv->crcmon = 1; 179 else 180 priv->crcmon = 0; 181 182 DMESG("bad CRC in monitor mode are %s", 183 priv->crcmon ? "accepted" : "rejected"); 184 185 if (prev != priv->crcmon && priv->up) { 186 /* rtl8180_down(dev); */ 187 /* rtl8180_up(dev); */ 188 } 189 190 up(&priv->wx_sem); 191 192 return 0; 193} 194 195static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a, 196 union iwreq_data *wrqu, char *b) 197{ 198 struct r8192_priv *priv = ieee80211_priv(dev); 199 int ret; 200 201 down(&priv->wx_sem); 202 203 ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b); 204 205 rtl8192_set_rxconf(dev); 206 207 up(&priv->wx_sem); 208 return ret; 209} 210 211struct iw_range_with_scan_capa { 212 /* Informative stuff (to choose between different interface) */ 213 __u32 throughput; /* To give an idea... */ 214 /* In theory this value should be the maximum benchmarked 215 * TCP/IP throughput, because with most of these devices the 216 * bit rate is meaningless (overhead an co) to estimate how 217 * fast the connection will go and pick the fastest one. 218 * I suggest people to play with Netperf or any benchmark... 219 */ 220 221 /* NWID (or domain id) */ 222 __u32 min_nwid; /* Minimal NWID we are able to set */ 223 __u32 max_nwid; /* Maximal NWID we are able to set */ 224 225 /* Old Frequency (backward compat - moved lower ) */ 226 __u16 old_num_channels; 227 __u8 old_num_frequency; 228 229 /* Scan capabilities */ 230 __u8 scan_capa; 231}; 232static int rtl8180_wx_get_range(struct net_device *dev, 233 struct iw_request_info *info, 234 union iwreq_data *wrqu, char *extra) 235{ 236 struct iw_range *range = (struct iw_range *)extra; 237 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range; 238 struct r8192_priv *priv = ieee80211_priv(dev); 239 u16 val; 240 int i; 241 242 wrqu->data.length = sizeof(*range); 243 memset(range, 0, sizeof(*range)); 244 245 /* Let's try to keep this struct in the same order as in 246 * linux/include/wireless.h 247 */ 248 249 /* TODO: See what values we can set, and remove the ones we can't 250 * set, or fill them with some default data. 251 */ 252 253 /* ~5 Mb/s real (802.11b) */ 254 range->throughput = 5 * 1000 * 1000; 255 256 /* TODO: Not used in 802.11b? */ 257 /* range->min_nwid; */ /* Minimal NWID we are able to set */ 258 /* TODO: Not used in 802.11b? */ 259 /* range->max_nwid; */ /* Maximal NWID we are able to set */ 260 261 /* Old Frequency (backward compat - moved lower ) */ 262 /* range->old_num_channels; */ 263 /* range->old_num_frequency; */ 264 /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */ 265 if (priv->rf_set_sens != NULL) 266 range->sensitivity = priv->max_sens; /* signal level threshold range */ 267 268 range->max_qual.qual = 100; 269 /* TODO: Find real max RSSI and stick here */ 270 range->max_qual.level = 0; 271 range->max_qual.noise = -98; 272 range->max_qual.updated = 7; /* Updated all three */ 273 274 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ 275 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ 276 range->avg_qual.level = 20 + -98; 277 range->avg_qual.noise = 0; 278 range->avg_qual.updated = 7; /* Updated all three */ 279 280 range->num_bitrates = RATE_COUNT; 281 282 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) 283 range->bitrate[i] = rtl8180_rates[i]; 284 285 range->min_frag = MIN_FRAG_THRESHOLD; 286 range->max_frag = MAX_FRAG_THRESHOLD; 287 288 range->min_pmp = 0; 289 range->max_pmp = 5000000; 290 range->min_pmt = 0; 291 range->max_pmt = 65535*1000; 292 range->pmp_flags = IW_POWER_PERIOD; 293 range->pmt_flags = IW_POWER_TIMEOUT; 294 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; 295 296 range->we_version_compiled = WIRELESS_EXT; 297 range->we_version_source = 16; 298 299 /* range->retry_capa; */ /* What retry options are supported */ 300 /* range->retry_flags; */ /* How to decode max/min retry limit */ 301 /* range->r_time_flags; */ /* How to decode max/min retry life */ 302 /* range->min_retry; */ /* Minimal number of retries */ 303 /* range->max_retry; */ /* Maximal number of retries */ 304 /* range->min_r_time; */ /* Minimal retry lifetime */ 305 /* range->max_r_time; */ /* Maximal retry lifetime */ 306 307 308 for (i = 0, val = 0; i < 14; i++) { 309 310 /* Include only legal frequencies for some countries */ 311 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { 312 range->freq[val].i = i + 1; 313 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; 314 range->freq[val].e = 1; 315 val++; 316 } else { 317 /* FIXME: do we need to set anything for channels */ 318 /* we don't use ? */ 319 } 320 321 if (val == IW_MAX_FREQUENCIES) 322 break; 323 } 324 range->num_frequency = val; 325 range->num_channels = val; 326 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 327 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 328 tmp->scan_capa = 0x01; 329 return 0; 330} 331 332 333static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 334 union iwreq_data *wrqu, char *b) 335{ 336 struct r8192_priv *priv = ieee80211_priv(dev); 337 struct ieee80211_device *ieee = priv->ieee80211; 338 int ret = 0; 339 340 if (!priv->up) 341 return -ENETDOWN; 342 343 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic == true) 344 return -EAGAIN; 345 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 346 struct iw_scan_req *req = (struct iw_scan_req *)b; 347 if (req->essid_len) { 348 ieee->current_network.ssid_len = req->essid_len; 349 memcpy(ieee->current_network.ssid, req->essid, req->essid_len); 350 } 351 } 352 353 down(&priv->wx_sem); 354 if (priv->ieee80211->state != IEEE80211_LINKED) { 355 priv->ieee80211->scanning = 0; 356 ieee80211_softmac_scan_syncro(priv->ieee80211); 357 ret = 0; 358 } else { 359 ret = ieee80211_wx_set_scan(priv->ieee80211, a, wrqu, b); 360 } 361 up(&priv->wx_sem); 362 return ret; 363} 364 365 366static int r8192_wx_get_scan(struct net_device *dev, struct iw_request_info *a, 367 union iwreq_data *wrqu, char *b) 368{ 369 370 int ret; 371 struct r8192_priv *priv = ieee80211_priv(dev); 372 373 if (!priv->up) 374 return -ENETDOWN; 375 376 down(&priv->wx_sem); 377 378 ret = ieee80211_wx_get_scan(priv->ieee80211, a, wrqu, b); 379 380 up(&priv->wx_sem); 381 382 return ret; 383} 384 385static int r8192_wx_set_essid(struct net_device *dev, 386 struct iw_request_info *a, 387 union iwreq_data *wrqu, char *b) 388{ 389 struct r8192_priv *priv = ieee80211_priv(dev); 390 int ret; 391 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 441 return ieee80211_wx_get_name(priv->ieee80211, info, wrqu, extra); 442} 443 444 445static int r8192_wx_set_frag(struct net_device *dev, 446 struct iw_request_info *info, 447 union iwreq_data *wrqu, char *extra) 448{ 449 struct r8192_priv *priv = ieee80211_priv(dev); 450 451 if (wrqu->frag.disabled) 452 priv->ieee80211->fts = DEFAULT_FRAG_THRESHOLD; 453 else { 454 if (wrqu->frag.value < MIN_FRAG_THRESHOLD || 455 wrqu->frag.value > MAX_FRAG_THRESHOLD) 456 return -EINVAL; 457 458 priv->ieee80211->fts = wrqu->frag.value & ~0x1; 459 } 460 461 return 0; 462} 463 464 465static int r8192_wx_get_frag(struct net_device *dev, 466 struct iw_request_info *info, 467 union iwreq_data *wrqu, char *extra) 468{ 469 struct r8192_priv *priv = ieee80211_priv(dev); 470 471 wrqu->frag.value = priv->ieee80211->fts; 472 wrqu->frag.fixed = 0; /* no auto select */ 473 wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FRAG_THRESHOLD); 474 475 return 0; 476} 477 478 479static int r8192_wx_set_wap(struct net_device *dev, 480 struct iw_request_info *info, 481 union iwreq_data *awrq, 482 char *extra) 483{ 484 485 int ret; 486 struct r8192_priv *priv = ieee80211_priv(dev); 487 /* struct sockaddr *temp = (struct sockaddr *)awrq; */ 488 down(&priv->wx_sem); 489 490 ret = ieee80211_wx_set_wap(priv->ieee80211, info, awrq, extra); 491 492 up(&priv->wx_sem); 493 494 return ret; 495 496} 497 498 499static int r8192_wx_get_wap(struct net_device *dev, 500 struct iw_request_info *info, 501 union iwreq_data *wrqu, char *extra) 502{ 503 struct r8192_priv *priv = ieee80211_priv(dev); 504 505 return ieee80211_wx_get_wap(priv->ieee80211, info, wrqu, extra); 506} 507 508 509static int r8192_wx_get_enc(struct net_device *dev, 510 struct iw_request_info *info, 511 union iwreq_data *wrqu, char *key) 512{ 513 struct r8192_priv *priv = ieee80211_priv(dev); 514 515 return ieee80211_wx_get_encode(priv->ieee80211, info, wrqu, key); 516} 517 518static int r8192_wx_set_enc(struct net_device *dev, 519 struct iw_request_info *info, 520 union iwreq_data *wrqu, char *key) 521{ 522 struct r8192_priv *priv = ieee80211_priv(dev); 523 struct ieee80211_device *ieee = priv->ieee80211; 524 int ret; 525 u32 hwkey[4] = {0, 0, 0, 0}; 526 u8 mask = 0xff; 527 u32 key_idx = 0; 528 u8 zero_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 529 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 530 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 531 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; 532 int i; 533 534 if (!priv->up) 535 return -ENETDOWN; 536 537 down(&priv->wx_sem); 538 539 RT_TRACE(COMP_SEC, "Setting SW wep key"); 540 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); 541 542 up(&priv->wx_sem); 543 544 545 546 /* sometimes, the length is zero while we do not type key value */ 547 if (wrqu->encoding.length != 0) { 548 549 for (i = 0; i < 4; i++) { 550 hwkey[i] |= key[4*i+0]&mask; 551 if (i == 1 && (4*i+1) == wrqu->encoding.length) 552 mask = 0x00; 553 if (i == 3 && (4*i+1) == wrqu->encoding.length) 554 mask = 0x00; 555 hwkey[i] |= (key[4*i+1]&mask)<<8; 556 hwkey[i] |= (key[4*i+2]&mask)<<16; 557 hwkey[i] |= (key[4*i+3]&mask)<<24; 558 } 559 560 #define CONF_WEP40 0x4 561 #define CONF_WEP104 0x14 562 563 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) { 564 case 0: 565 key_idx = ieee->tx_keyidx; 566 break; 567 case 1: 568 key_idx = 0; 569 break; 570 case 2: 571 key_idx = 1; 572 break; 573 case 3: 574 key_idx = 2; 575 break; 576 case 4: 577 key_idx = 3; 578 break; 579 default: 580 break; 581 } 582 583 if (wrqu->encoding.length == 0x5) { 584 ieee->pairwise_key_type = KEY_TYPE_WEP40; 585 EnableHWSecurityConfig8192(dev); 586 587 setKey(dev, 588 key_idx, /* EntryNo */ 589 key_idx, /* KeyIndex */ 590 KEY_TYPE_WEP40, /* KeyType */ 591 zero_addr[key_idx], 592 0, /* DefaultKey */ 593 hwkey); /* KeyContent */ 594 595 } 596 597 else if (wrqu->encoding.length == 0xd) { 598 ieee->pairwise_key_type = KEY_TYPE_WEP104; 599 EnableHWSecurityConfig8192(dev); 600 601 setKey(dev, 602 key_idx, /* EntryNo */ 603 key_idx, /* KeyIndex */ 604 KEY_TYPE_WEP104, /* KeyType */ 605 zero_addr[key_idx], 606 0, /* DefaultKey */ 607 hwkey); /* KeyContent */ 608 609 } else { 610 printk("wrong type in WEP, not WEP40 and WEP104\n"); 611 } 612 613 } 614 615 return ret; 616} 617 618 619static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, 620 union iwreq_data *wrqu, char *p) 621{ 622 623 struct r8192_priv *priv = ieee80211_priv(dev); 624 int *parms = (int *)p; 625 int mode = parms[0]; 626 627 priv->ieee80211->active_scan = mode; 628 629 return 1; 630} 631 632 633 634static int r8192_wx_set_retry(struct net_device *dev, 635 struct iw_request_info *info, 636 union iwreq_data *wrqu, char *extra) 637{ 638 struct r8192_priv *priv = ieee80211_priv(dev); 639 int err = 0; 640 641 down(&priv->wx_sem); 642 643 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 644 wrqu->retry.disabled){ 645 err = -EINVAL; 646 goto exit; 647 } 648 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { 649 err = -EINVAL; 650 goto exit; 651 } 652 653 if (wrqu->retry.value > R8180_MAX_RETRY) { 654 err = -EINVAL; 655 goto exit; 656 } 657 if (wrqu->retry.flags & IW_RETRY_MAX) { 658 priv->retry_rts = wrqu->retry.value; 659 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 660 661 } else { 662 priv->retry_data = wrqu->retry.value; 663 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 664 } 665 666 /* FIXME ! 667 * We might try to write directly the TX config register 668 * or to restart just the (R)TX process. 669 * I'm unsure if whole reset is really needed 670 */ 671 672 rtl8192_commit(dev); 673exit: 674 up(&priv->wx_sem); 675 676 return err; 677} 678 679static int r8192_wx_get_retry(struct net_device *dev, 680 struct iw_request_info *info, 681 union iwreq_data *wrqu, char *extra) 682{ 683 struct r8192_priv *priv = ieee80211_priv(dev); 684 685 686 wrqu->retry.disabled = 0; /* can't be disabled */ 687 688 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 689 IW_RETRY_LIFETIME) 690 return -EINVAL; 691 692 if (wrqu->retry.flags & IW_RETRY_MAX) { 693 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 694 wrqu->retry.value = priv->retry_rts; 695 } else { 696 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; 697 wrqu->retry.value = priv->retry_data; 698 } 699 700 701 return 0; 702} 703 704static int r8192_wx_get_sens(struct net_device *dev, 705 struct iw_request_info *info, 706 union iwreq_data *wrqu, char *extra) 707{ 708 struct r8192_priv *priv = ieee80211_priv(dev); 709 710 if (priv->rf_set_sens == NULL) 711 return -1; /* we have not this support for this radio */ 712 wrqu->sens.value = priv->sens; 713 return 0; 714} 715 716 717static int r8192_wx_set_sens(struct net_device *dev, 718 struct iw_request_info *info, 719 union iwreq_data *wrqu, char *extra) 720{ 721 722 struct r8192_priv *priv = ieee80211_priv(dev); 723 short err = 0; 724 725 down(&priv->wx_sem); 726 if (priv->rf_set_sens == NULL) { 727 err = -1; /* we have not this support for this radio */ 728 goto exit; 729 } 730 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) 731 priv->sens = wrqu->sens.value; 732 else 733 err = -EINVAL; 734 735exit: 736 up(&priv->wx_sem); 737 738 return err; 739} 740 741/* hw security need to reorganized. */ 742static int r8192_wx_set_enc_ext(struct net_device *dev, 743 struct iw_request_info *info, 744 union iwreq_data *wrqu, char *extra) 745{ 746 int ret = 0; 747 struct r8192_priv *priv = ieee80211_priv(dev); 748 struct ieee80211_device *ieee = priv->ieee80211; 749 750 751 down(&priv->wx_sem); 752 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); 753 754 { 755 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 756 u8 zero[6] = {0}; 757 u32 key[4] = {0}; 758 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 759 struct iw_point *encoding = &wrqu->encoding; 760 u8 idx = 0, alg = 0, group = 0; 761 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE) 762 /* none is not allowed to use hwsec WB 2008.07.01 */ 763 goto end_hw_sec; 764 765 /* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */ 766 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 767 idx = encoding->flags & IW_ENCODE_INDEX; 768 if (idx) 769 idx--; 770 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 771 772 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) { 773 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) 774 alg = KEY_TYPE_WEP104; 775 ieee->pairwise_key_type = alg; 776 EnableHWSecurityConfig8192(dev); 777 } 778 memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */ 779 780 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { 781 782 setKey(dev, 783 idx, /* EntryNao */ 784 idx, /* KeyIndex */ 785 alg, /* KeyType */ 786 zero, /* MacAddr */ 787 0, /* DefaultKey */ 788 key); /* KeyContent */ 789 } else if (group) { 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 } else { /* pairwise key */ 799 setKey(dev, 800 4, /* EntryNo */ 801 idx, /* KeyIndex */ 802 alg, /* KeyType */ 803 (u8 *)ieee->ap_mac_addr,/* MacAddr */ 804 0, /* DefaultKey */ 805 key); /* KeyContent */ 806 } 807 808 809 } 810 811end_hw_sec: 812 813 up(&priv->wx_sem); 814 return ret; 815 816} 817static int r8192_wx_set_auth(struct net_device *dev, 818 struct iw_request_info *info, 819 union iwreq_data *data, char *extra) 820{ 821 int ret = 0; 822 struct r8192_priv *priv = ieee80211_priv(dev); 823 824 down(&priv->wx_sem); 825 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 826 up(&priv->wx_sem); 827 return ret; 828} 829 830static int r8192_wx_set_mlme(struct net_device *dev, 831 struct iw_request_info *info, 832 union iwreq_data *wrqu, char *extra) 833{ 834 835 int ret = 0; 836 struct r8192_priv *priv = ieee80211_priv(dev); 837 838 down(&priv->wx_sem); 839 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); 840 841 up(&priv->wx_sem); 842 return ret; 843} 844 845static int r8192_wx_set_gen_ie(struct net_device *dev, 846 struct iw_request_info *info, 847 union iwreq_data *data, char *extra) 848{ 849 int ret = 0; 850 struct r8192_priv *priv = ieee80211_priv(dev); 851 852 down(&priv->wx_sem); 853 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 854 up(&priv->wx_sem); 855 return ret; 856 857 858} 859 860static int dummy(struct net_device *dev, struct iw_request_info *a, 861 union iwreq_data *wrqu, char *b) 862{ 863 return -1; 864} 865 866 867static iw_handler r8192_wx_handlers[] = { 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_crcmon, 956 r8192_wx_set_scan_type, 957 r8192_wx_set_rawtx, 958 r8192_wx_force_reset, 959}; 960 961struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 962{ 963 struct r8192_priv *priv = ieee80211_priv(dev); 964 struct ieee80211_device *ieee = priv->ieee80211; 965 struct iw_statistics *wstats = &priv->wstats; 966 int tmp_level = 0; 967 int tmp_qual = 0; 968 int tmp_noise = 0; 969 970 if (ieee->state < IEEE80211_LINKED) { 971 wstats->qual.qual = 0; 972 wstats->qual.level = 0; 973 wstats->qual.noise = 0; 974 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 975 return wstats; 976 } 977 978 tmp_level = (&ieee->current_network)->stats.rssi; 979 tmp_qual = (&ieee->current_network)->stats.signal; 980 tmp_noise = (&ieee->current_network)->stats.noise; 981 982 wstats->qual.level = tmp_level; 983 wstats->qual.qual = tmp_qual; 984 wstats->qual.noise = tmp_noise; 985 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 986 return wstats; 987} 988 989 990struct iw_handler_def r8192_wx_handlers_def = { 991 .standard = r8192_wx_handlers, 992 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 993 .private = r8192_private_handler, 994 .num_private = ARRAY_SIZE(r8192_private_handler), 995 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 996 .get_wireless_stats = r8192_get_wireless_stats, 997 .private_args = (struct iw_priv_args *)r8192_private_args, 998}; 999