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 netdev_dbg(dev, "%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 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 up(&priv->wx_sem); 186 187 return 0; 188} 189 190static int r8192_wx_set_mode(struct net_device *dev, struct iw_request_info *a, 191 union iwreq_data *wrqu, char *b) 192{ 193 struct r8192_priv *priv = ieee80211_priv(dev); 194 int ret; 195 196 down(&priv->wx_sem); 197 198 ret = ieee80211_wx_set_mode(priv->ieee80211, a, wrqu, b); 199 200 rtl8192_set_rxconf(dev); 201 202 up(&priv->wx_sem); 203 return ret; 204} 205 206struct iw_range_with_scan_capa { 207 /* Informative stuff (to choose between different interface) */ 208 __u32 throughput; /* To give an idea... */ 209 /* In theory this value should be the maximum benchmarked 210 * TCP/IP throughput, because with most of these devices the 211 * bit rate is meaningless (overhead an co) to estimate how 212 * fast the connection will go and pick the fastest one. 213 * I suggest people to play with Netperf or any benchmark... 214 */ 215 216 /* NWID (or domain id) */ 217 __u32 min_nwid; /* Minimal NWID we are able to set */ 218 __u32 max_nwid; /* Maximal NWID we are able to set */ 219 220 /* Old Frequency (backward compat - moved lower ) */ 221 __u16 old_num_channels; 222 __u8 old_num_frequency; 223 224 /* Scan capabilities */ 225 __u8 scan_capa; 226}; 227static int rtl8180_wx_get_range(struct net_device *dev, 228 struct iw_request_info *info, 229 union iwreq_data *wrqu, char *extra) 230{ 231 struct iw_range *range = (struct iw_range *)extra; 232 struct iw_range_with_scan_capa *tmp = (struct iw_range_with_scan_capa *)range; 233 struct r8192_priv *priv = ieee80211_priv(dev); 234 u16 val; 235 int i; 236 237 wrqu->data.length = sizeof(*range); 238 memset(range, 0, sizeof(*range)); 239 240 /* Let's try to keep this struct in the same order as in 241 * linux/include/wireless.h 242 */ 243 244 /* TODO: See what values we can set, and remove the ones we can't 245 * set, or fill them with some default data. 246 */ 247 248 /* ~5 Mb/s real (802.11b) */ 249 range->throughput = 5 * 1000 * 1000; 250 251 /* TODO: Not used in 802.11b? */ 252 /* range->min_nwid; */ /* Minimal NWID we are able to set */ 253 /* TODO: Not used in 802.11b? */ 254 /* range->max_nwid; */ /* Maximal NWID we are able to set */ 255 256 /* Old Frequency (backward compat - moved lower ) */ 257 /* range->old_num_channels; */ 258 /* range->old_num_frequency; */ 259 /* range->old_freq[6]; */ /* Filler to keep "version" at the same offset */ 260 if (priv->rf_set_sens != NULL) 261 range->sensitivity = priv->max_sens; /* signal level threshold range */ 262 263 range->max_qual.qual = 100; 264 /* TODO: Find real max RSSI and stick here */ 265 range->max_qual.level = 0; 266 range->max_qual.noise = -98; 267 range->max_qual.updated = 7; /* Updated all three */ 268 269 range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */ 270 /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ 271 range->avg_qual.level = 20 + -98; 272 range->avg_qual.noise = 0; 273 range->avg_qual.updated = 7; /* Updated all three */ 274 275 range->num_bitrates = RATE_COUNT; 276 277 for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) 278 range->bitrate[i] = rtl8180_rates[i]; 279 280 range->min_frag = MIN_FRAG_THRESHOLD; 281 range->max_frag = MAX_FRAG_THRESHOLD; 282 283 range->min_pmp = 0; 284 range->max_pmp = 5000000; 285 range->min_pmt = 0; 286 range->max_pmt = 65535*1000; 287 range->pmp_flags = IW_POWER_PERIOD; 288 range->pmt_flags = IW_POWER_TIMEOUT; 289 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; 290 291 range->we_version_compiled = WIRELESS_EXT; 292 range->we_version_source = 16; 293 294 /* range->retry_capa; */ /* What retry options are supported */ 295 /* range->retry_flags; */ /* How to decode max/min retry limit */ 296 /* range->r_time_flags; */ /* How to decode max/min retry life */ 297 /* range->min_retry; */ /* Minimal number of retries */ 298 /* range->max_retry; */ /* Maximal number of retries */ 299 /* range->min_r_time; */ /* Minimal retry lifetime */ 300 /* range->max_r_time; */ /* Maximal retry lifetime */ 301 302 303 for (i = 0, val = 0; i < 14; i++) { 304 305 /* Include only legal frequencies for some countries */ 306 if ((GET_DOT11D_INFO(priv->ieee80211)->channel_map)[i+1]) { 307 range->freq[val].i = i + 1; 308 range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000; 309 range->freq[val].e = 1; 310 val++; 311 } else { 312 /* FIXME: do we need to set anything for channels */ 313 /* we don't use ? */ 314 } 315 316 if (val == IW_MAX_FREQUENCIES) 317 break; 318 } 319 range->num_frequency = val; 320 range->num_channels = val; 321 range->enc_capa = IW_ENC_CAPA_WPA|IW_ENC_CAPA_WPA2| 322 IW_ENC_CAPA_CIPHER_TKIP|IW_ENC_CAPA_CIPHER_CCMP; 323 tmp->scan_capa = 0x01; 324 return 0; 325} 326 327 328static int r8192_wx_set_scan(struct net_device *dev, struct iw_request_info *a, 329 union iwreq_data *wrqu, char *b) 330{ 331 struct r8192_priv *priv = ieee80211_priv(dev); 332 struct ieee80211_device *ieee = priv->ieee80211; 333 int ret = 0; 334 335 if (!priv->up) 336 return -ENETDOWN; 337 338 if (priv->ieee80211->LinkDetectInfo.bBusyTraffic) 339 return -EAGAIN; 340 if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { 341 struct iw_scan_req *req = (struct iw_scan_req *)b; 342 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 388 down(&priv->wx_sem); 389 390 ret = ieee80211_wx_set_essid(priv->ieee80211, a, wrqu, b); 391 392 up(&priv->wx_sem); 393 394 return ret; 395} 396 397 398 399 400static int r8192_wx_get_essid(struct net_device *dev, 401 struct iw_request_info *a, 402 union iwreq_data *wrqu, char *b) 403{ 404 int ret; 405 struct r8192_priv *priv = ieee80211_priv(dev); 406 407 down(&priv->wx_sem); 408 409 ret = ieee80211_wx_get_essid(priv->ieee80211, a, wrqu, b); 410 411 up(&priv->wx_sem); 412 413 return ret; 414} 415 416 417static int r8192_wx_set_freq(struct net_device *dev, struct iw_request_info *a, 418 union iwreq_data *wrqu, char *b) 419{ 420 int ret; 421 struct r8192_priv *priv = ieee80211_priv(dev); 422 423 down(&priv->wx_sem); 424 425 ret = ieee80211_wx_set_freq(priv->ieee80211, a, wrqu, b); 426 427 up(&priv->wx_sem); 428 return ret; 429} 430 431static int r8192_wx_get_name(struct net_device *dev, 432 struct iw_request_info *info, 433 union iwreq_data *wrqu, char *extra) 434{ 435 struct r8192_priv *priv = ieee80211_priv(dev); 436 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 u32 hwkey[4] = {0, 0, 0, 0}; 522 u8 mask = 0xff; 523 u32 key_idx = 0; 524 u8 zero_addr[4][6] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 525 {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}, 526 {0x00, 0x00, 0x00, 0x00, 0x00, 0x02}, 527 {0x00, 0x00, 0x00, 0x00, 0x00, 0x03} }; 528 int i; 529 530 if (!priv->up) 531 return -ENETDOWN; 532 533 down(&priv->wx_sem); 534 535 RT_TRACE(COMP_SEC, "Setting SW wep key"); 536 ret = ieee80211_wx_set_encode(priv->ieee80211, info, wrqu, key); 537 538 up(&priv->wx_sem); 539 540 541 542 /* sometimes, the length is zero while we do not type key value */ 543 if (wrqu->encoding.length != 0) { 544 545 for (i = 0; i < 4; i++) { 546 hwkey[i] |= key[4*i+0]&mask; 547 if (i == 1 && (4*i+1) == wrqu->encoding.length) 548 mask = 0x00; 549 if (i == 3 && (4*i+1) == wrqu->encoding.length) 550 mask = 0x00; 551 hwkey[i] |= (key[4*i+1]&mask)<<8; 552 hwkey[i] |= (key[4*i+2]&mask)<<16; 553 hwkey[i] |= (key[4*i+3]&mask)<<24; 554 } 555 556 #define CONF_WEP40 0x4 557 #define CONF_WEP104 0x14 558 559 switch (wrqu->encoding.flags & IW_ENCODE_INDEX) { 560 case 0: 561 key_idx = ieee->tx_keyidx; 562 break; 563 case 1: 564 key_idx = 0; 565 break; 566 case 2: 567 key_idx = 1; 568 break; 569 case 3: 570 key_idx = 2; 571 break; 572 case 4: 573 key_idx = 3; 574 break; 575 default: 576 break; 577 } 578 579 if (wrqu->encoding.length == 0x5) { 580 ieee->pairwise_key_type = KEY_TYPE_WEP40; 581 EnableHWSecurityConfig8192(dev); 582 583 setKey(dev, 584 key_idx, /* EntryNo */ 585 key_idx, /* KeyIndex */ 586 KEY_TYPE_WEP40, /* KeyType */ 587 zero_addr[key_idx], 588 0, /* DefaultKey */ 589 hwkey); /* KeyContent */ 590 591 } 592 593 else if (wrqu->encoding.length == 0xd) { 594 ieee->pairwise_key_type = KEY_TYPE_WEP104; 595 EnableHWSecurityConfig8192(dev); 596 597 setKey(dev, 598 key_idx, /* EntryNo */ 599 key_idx, /* KeyIndex */ 600 KEY_TYPE_WEP104, /* KeyType */ 601 zero_addr[key_idx], 602 0, /* DefaultKey */ 603 hwkey); /* KeyContent */ 604 605 } else { 606 printk("wrong type in WEP, not WEP40 and WEP104\n"); 607 } 608 609 } 610 611 return ret; 612} 613 614 615static int r8192_wx_set_scan_type(struct net_device *dev, struct iw_request_info *aa, 616 union iwreq_data *wrqu, char *p) 617{ 618 619 struct r8192_priv *priv = ieee80211_priv(dev); 620 int *parms = (int *)p; 621 int mode = parms[0]; 622 623 priv->ieee80211->active_scan = mode; 624 625 return 1; 626} 627 628 629 630static int r8192_wx_set_retry(struct net_device *dev, 631 struct iw_request_info *info, 632 union iwreq_data *wrqu, char *extra) 633{ 634 struct r8192_priv *priv = ieee80211_priv(dev); 635 int err = 0; 636 637 down(&priv->wx_sem); 638 639 if (wrqu->retry.flags & IW_RETRY_LIFETIME || 640 wrqu->retry.disabled){ 641 err = -EINVAL; 642 goto exit; 643 } 644 if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) { 645 err = -EINVAL; 646 goto exit; 647 } 648 649 if (wrqu->retry.value > R8180_MAX_RETRY) { 650 err = -EINVAL; 651 goto exit; 652 } 653 if (wrqu->retry.flags & IW_RETRY_MAX) { 654 priv->retry_rts = wrqu->retry.value; 655 DMESG("Setting retry for RTS/CTS data to %d", wrqu->retry.value); 656 657 } else { 658 priv->retry_data = wrqu->retry.value; 659 DMESG("Setting retry for non RTS/CTS data to %d", wrqu->retry.value); 660 } 661 662 /* FIXME ! 663 * We might try to write directly the TX config register 664 * or to restart just the (R)TX process. 665 * I'm unsure if whole reset is really needed 666 */ 667 668 rtl8192_commit(dev); 669exit: 670 up(&priv->wx_sem); 671 672 return err; 673} 674 675static int r8192_wx_get_retry(struct net_device *dev, 676 struct iw_request_info *info, 677 union iwreq_data *wrqu, char *extra) 678{ 679 struct r8192_priv *priv = ieee80211_priv(dev); 680 681 682 wrqu->retry.disabled = 0; /* can't be disabled */ 683 684 if ((wrqu->retry.flags & IW_RETRY_TYPE) == 685 IW_RETRY_LIFETIME) 686 return -EINVAL; 687 688 if (wrqu->retry.flags & IW_RETRY_MAX) { 689 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MAX; 690 wrqu->retry.value = priv->retry_rts; 691 } else { 692 wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_MIN; 693 wrqu->retry.value = priv->retry_data; 694 } 695 696 697 return 0; 698} 699 700static int r8192_wx_get_sens(struct net_device *dev, 701 struct iw_request_info *info, 702 union iwreq_data *wrqu, char *extra) 703{ 704 struct r8192_priv *priv = ieee80211_priv(dev); 705 706 if (priv->rf_set_sens == NULL) 707 return -1; /* we have not this support for this radio */ 708 wrqu->sens.value = priv->sens; 709 return 0; 710} 711 712 713static int r8192_wx_set_sens(struct net_device *dev, 714 struct iw_request_info *info, 715 union iwreq_data *wrqu, char *extra) 716{ 717 718 struct r8192_priv *priv = ieee80211_priv(dev); 719 short err = 0; 720 721 down(&priv->wx_sem); 722 if (priv->rf_set_sens == NULL) { 723 err = -1; /* we have not this support for this radio */ 724 goto exit; 725 } 726 if (priv->rf_set_sens(dev, wrqu->sens.value) == 0) 727 priv->sens = wrqu->sens.value; 728 else 729 err = -EINVAL; 730 731exit: 732 up(&priv->wx_sem); 733 734 return err; 735} 736 737/* hw security need to reorganized. */ 738static int r8192_wx_set_enc_ext(struct net_device *dev, 739 struct iw_request_info *info, 740 union iwreq_data *wrqu, char *extra) 741{ 742 int ret = 0; 743 struct r8192_priv *priv = ieee80211_priv(dev); 744 struct ieee80211_device *ieee = priv->ieee80211; 745 746 747 down(&priv->wx_sem); 748 ret = ieee80211_wx_set_encode_ext(priv->ieee80211, info, wrqu, extra); 749 750 { 751 u8 broadcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; 752 u8 zero[6] = {0}; 753 u32 key[4] = {0}; 754 struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; 755 struct iw_point *encoding = &wrqu->encoding; 756 u8 idx = 0, alg = 0, group = 0; 757 758 if ((encoding->flags & IW_ENCODE_DISABLED) || ext->alg == IW_ENCODE_ALG_NONE) 759 /* none is not allowed to use hwsec WB 2008.07.01 */ 760 goto end_hw_sec; 761 762 /* as IW_ENCODE_ALG_CCMP is defined to be 3 and KEY_TYPE_CCMP is defined to 4; */ 763 alg = (ext->alg == IW_ENCODE_ALG_CCMP)?KEY_TYPE_CCMP:ext->alg; 764 idx = encoding->flags & IW_ENCODE_INDEX; 765 if (idx) 766 idx--; 767 group = ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY; 768 769 if ((!group) || (IW_MODE_ADHOC == ieee->iw_mode) || (alg == KEY_TYPE_WEP40)) { 770 if ((ext->key_len == 13) && (alg == KEY_TYPE_WEP40)) 771 alg = KEY_TYPE_WEP104; 772 ieee->pairwise_key_type = alg; 773 EnableHWSecurityConfig8192(dev); 774 } 775 memcpy((u8 *)key, ext->key, 16); /* we only get 16 bytes key.why? WB 2008.7.1 */ 776 777 if ((alg & KEY_TYPE_WEP40) && (ieee->auth_mode != 2)) { 778 779 setKey(dev, 780 idx, /* EntryNao */ 781 idx, /* KeyIndex */ 782 alg, /* KeyType */ 783 zero, /* MacAddr */ 784 0, /* DefaultKey */ 785 key); /* KeyContent */ 786 } else if (group) { 787 ieee->group_key_type = alg; 788 setKey(dev, 789 idx, /* EntryNo */ 790 idx, /* KeyIndex */ 791 alg, /* KeyType */ 792 broadcast_addr, /* MacAddr */ 793 0, /* DefaultKey */ 794 key); /* KeyContent */ 795 } else { /* pairwise key */ 796 setKey(dev, 797 4, /* EntryNo */ 798 idx, /* KeyIndex */ 799 alg, /* KeyType */ 800 (u8 *)ieee->ap_mac_addr,/* MacAddr */ 801 0, /* DefaultKey */ 802 key); /* KeyContent */ 803 } 804 805 806 } 807 808end_hw_sec: 809 810 up(&priv->wx_sem); 811 return ret; 812 813} 814static int r8192_wx_set_auth(struct net_device *dev, 815 struct iw_request_info *info, 816 union iwreq_data *data, char *extra) 817{ 818 int ret = 0; 819 struct r8192_priv *priv = ieee80211_priv(dev); 820 821 down(&priv->wx_sem); 822 ret = ieee80211_wx_set_auth(priv->ieee80211, info, &(data->param), extra); 823 up(&priv->wx_sem); 824 return ret; 825} 826 827static int r8192_wx_set_mlme(struct net_device *dev, 828 struct iw_request_info *info, 829 union iwreq_data *wrqu, char *extra) 830{ 831 832 int ret = 0; 833 struct r8192_priv *priv = ieee80211_priv(dev); 834 835 down(&priv->wx_sem); 836 ret = ieee80211_wx_set_mlme(priv->ieee80211, info, wrqu, extra); 837 838 up(&priv->wx_sem); 839 return ret; 840} 841 842static int r8192_wx_set_gen_ie(struct net_device *dev, 843 struct iw_request_info *info, 844 union iwreq_data *data, char *extra) 845{ 846 int ret = 0; 847 struct r8192_priv *priv = ieee80211_priv(dev); 848 849 down(&priv->wx_sem); 850 ret = ieee80211_wx_set_gen_ie(priv->ieee80211, extra, data->data.length); 851 up(&priv->wx_sem); 852 return ret; 853 854 855} 856 857static int dummy(struct net_device *dev, struct iw_request_info *a, 858 union iwreq_data *wrqu, char *b) 859{ 860 return -1; 861} 862 863 864static iw_handler r8192_wx_handlers[] = { 865 NULL, /* SIOCSIWCOMMIT */ 866 r8192_wx_get_name, /* SIOCGIWNAME */ 867 dummy, /* SIOCSIWNWID */ 868 dummy, /* SIOCGIWNWID */ 869 r8192_wx_set_freq, /* SIOCSIWFREQ */ 870 r8192_wx_get_freq, /* SIOCGIWFREQ */ 871 r8192_wx_set_mode, /* SIOCSIWMODE */ 872 r8192_wx_get_mode, /* SIOCGIWMODE */ 873 r8192_wx_set_sens, /* SIOCSIWSENS */ 874 r8192_wx_get_sens, /* SIOCGIWSENS */ 875 NULL, /* SIOCSIWRANGE */ 876 rtl8180_wx_get_range, /* SIOCGIWRANGE */ 877 NULL, /* SIOCSIWPRIV */ 878 NULL, /* SIOCGIWPRIV */ 879 NULL, /* SIOCSIWSTATS */ 880 NULL, /* SIOCGIWSTATS */ 881 dummy, /* SIOCSIWSPY */ 882 dummy, /* SIOCGIWSPY */ 883 NULL, /* SIOCGIWTHRSPY */ 884 NULL, /* SIOCWIWTHRSPY */ 885 r8192_wx_set_wap, /* SIOCSIWAP */ 886 r8192_wx_get_wap, /* SIOCGIWAP */ 887 r8192_wx_set_mlme, /* MLME-- */ 888 dummy, /* SIOCGIWAPLIST -- deprecated */ 889 r8192_wx_set_scan, /* SIOCSIWSCAN */ 890 r8192_wx_get_scan, /* SIOCGIWSCAN */ 891 r8192_wx_set_essid, /* SIOCSIWESSID */ 892 r8192_wx_get_essid, /* SIOCGIWESSID */ 893 dummy, /* SIOCSIWNICKN */ 894 dummy, /* SIOCGIWNICKN */ 895 NULL, /* -- hole -- */ 896 NULL, /* -- hole -- */ 897 r8192_wx_set_rate, /* SIOCSIWRATE */ 898 r8192_wx_get_rate, /* SIOCGIWRATE */ 899 r8192_wx_set_rts, /* SIOCSIWRTS */ 900 r8192_wx_get_rts, /* SIOCGIWRTS */ 901 r8192_wx_set_frag, /* SIOCSIWFRAG */ 902 r8192_wx_get_frag, /* SIOCGIWFRAG */ 903 dummy, /* SIOCSIWTXPOW */ 904 dummy, /* SIOCGIWTXPOW */ 905 r8192_wx_set_retry, /* SIOCSIWRETRY */ 906 r8192_wx_get_retry, /* SIOCGIWRETRY */ 907 r8192_wx_set_enc, /* SIOCSIWENCODE */ 908 r8192_wx_get_enc, /* SIOCGIWENCODE */ 909 r8192_wx_set_power, /* SIOCSIWPOWER */ 910 r8192_wx_get_power, /* SIOCGIWPOWER */ 911 NULL, /*---hole---*/ 912 NULL, /*---hole---*/ 913 r8192_wx_set_gen_ie, /* NULL, */ /* SIOCSIWGENIE */ 914 NULL, /* SIOCSIWGENIE */ 915 916 r8192_wx_set_auth,/* NULL, */ /* SIOCSIWAUTH */ 917 NULL,/* r8192_wx_get_auth, */ /* NULL, */ /* SIOCSIWAUTH */ 918 r8192_wx_set_enc_ext, /* SIOCSIWENCODEEXT */ 919 NULL,/* r8192_wx_get_enc_ext, *//* NULL, */ /* SIOCSIWENCODEEXT */ 920 NULL, /* SIOCSIWPMKSA */ 921 NULL, /*---hole---*/ 922 923}; 924 925 926static const struct iw_priv_args r8192_private_args[] = { 927 928 { 929 SIOCIWFIRSTPRIV + 0x0, 930 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "badcrc" 931 }, 932 933 { 934 SIOCIWFIRSTPRIV + 0x1, 935 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "activescan" 936 937 }, 938 { 939 SIOCIWFIRSTPRIV + 0x2, 940 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "rawtx" 941 }, 942 { 943 SIOCIWFIRSTPRIV + 0x3, 944 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "forcereset" 945 946 } 947 948}; 949 950 951static iw_handler r8192_private_handler[] = { 952 r8192_wx_set_crcmon, 953 r8192_wx_set_scan_type, 954 r8192_wx_set_rawtx, 955 r8192_wx_force_reset, 956}; 957 958struct iw_statistics *r8192_get_wireless_stats(struct net_device *dev) 959{ 960 struct r8192_priv *priv = ieee80211_priv(dev); 961 struct ieee80211_device *ieee = priv->ieee80211; 962 struct iw_statistics *wstats = &priv->wstats; 963 int tmp_level = 0; 964 int tmp_qual = 0; 965 int tmp_noise = 0; 966 967 if (ieee->state < IEEE80211_LINKED) { 968 wstats->qual.qual = 0; 969 wstats->qual.level = 0; 970 wstats->qual.noise = 0; 971 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 972 return wstats; 973 } 974 975 tmp_level = (&ieee->current_network)->stats.rssi; 976 tmp_qual = (&ieee->current_network)->stats.signal; 977 tmp_noise = (&ieee->current_network)->stats.noise; 978 979 wstats->qual.level = tmp_level; 980 wstats->qual.qual = tmp_qual; 981 wstats->qual.noise = tmp_noise; 982 wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; 983 return wstats; 984} 985 986 987struct iw_handler_def r8192_wx_handlers_def = { 988 .standard = r8192_wx_handlers, 989 .num_standard = ARRAY_SIZE(r8192_wx_handlers), 990 .private = r8192_private_handler, 991 .num_private = ARRAY_SIZE(r8192_private_handler), 992 .num_private_args = sizeof(r8192_private_args) / sizeof(struct iw_priv_args), 993 .get_wireless_stats = r8192_get_wireless_stats, 994 .private_args = (struct iw_priv_args *)r8192_private_args, 995}; 996