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