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