ieee80211_softmac_wx.c revision 8fc8598e61f6f384f3eaf1d9b09500c12af47b37
1/* IEEE 802.11 SoftMAC layer 2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it> 3 * 4 * Mostly extracted from the rtl8180-sa2400 driver for the 5 * in-kernel generic ieee802.11 stack. 6 * 7 * Some pieces of code might be stolen from ipw2100 driver 8 * copyright of who own it's copyright ;-) 9 * 10 * PS wx handler mostly stolen from hostap, copyright who 11 * own it's copyright ;-) 12 * 13 * released under the GPL 14 */ 15 16 17#include "ieee80211.h" 18#ifdef ENABLE_DOT11D 19#include "dot11d.h" 20#endif 21/* FIXME: add A freqs */ 22 23const long ieee80211_wlan_frequencies[] = { 24 2412, 2417, 2422, 2427, 25 2432, 2437, 2442, 2447, 26 2452, 2457, 2462, 2467, 27 2472, 2484 28}; 29 30 31int ieee80211_wx_set_freq(struct ieee80211_device *ieee, struct iw_request_info *a, 32 union iwreq_data *wrqu, char *b) 33{ 34 int ret; 35 struct iw_freq *fwrq = & wrqu->freq; 36 37 down(&ieee->wx_sem); 38 39 if(ieee->iw_mode == IW_MODE_INFRA){ 40 ret = -EOPNOTSUPP; 41 goto out; 42 } 43 44 /* if setting by freq convert to channel */ 45 if (fwrq->e == 1) { 46 if ((fwrq->m >= (int) 2.412e8 && 47 fwrq->m <= (int) 2.487e8)) { 48 int f = fwrq->m / 100000; 49 int c = 0; 50 51 while ((c < 14) && (f != ieee80211_wlan_frequencies[c])) 52 c++; 53 54 /* hack to fall through */ 55 fwrq->e = 0; 56 fwrq->m = c + 1; 57 } 58 } 59 60 if (fwrq->e > 0 || fwrq->m > 14 || fwrq->m < 1 ){ 61 ret = -EOPNOTSUPP; 62 goto out; 63 64 }else { /* Set the channel */ 65 66#ifdef ENABLE_DOT11D 67 if (!(GET_DOT11D_INFO(ieee)->channel_map)[fwrq->m]) { 68 ret = -EINVAL; 69 goto out; 70 } 71#endif 72 ieee->current_network.channel = fwrq->m; 73 ieee->set_chan(ieee->dev, ieee->current_network.channel); 74 75 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) 76 if(ieee->state == IEEE80211_LINKED){ 77 78 ieee80211_stop_send_beacons(ieee); 79 ieee80211_start_send_beacons(ieee); 80 } 81 } 82 83 ret = 0; 84out: 85 up(&ieee->wx_sem); 86 return ret; 87} 88 89 90int ieee80211_wx_get_freq(struct ieee80211_device *ieee, 91 struct iw_request_info *a, 92 union iwreq_data *wrqu, char *b) 93{ 94 struct iw_freq *fwrq = & wrqu->freq; 95 96 if (ieee->current_network.channel == 0) 97 return -1; 98 //NM 0.7.0 will not accept channel any more. 99 fwrq->m = ieee80211_wlan_frequencies[ieee->current_network.channel-1] * 100000; 100 fwrq->e = 1; 101// fwrq->m = ieee->current_network.channel; 102// fwrq->e = 0; 103 104 return 0; 105} 106 107int ieee80211_wx_get_wap(struct ieee80211_device *ieee, 108 struct iw_request_info *info, 109 union iwreq_data *wrqu, char *extra) 110{ 111 unsigned long flags; 112 113 wrqu->ap_addr.sa_family = ARPHRD_ETHER; 114 115 if (ieee->iw_mode == IW_MODE_MONITOR) 116 return -1; 117 118 /* We want avoid to give to the user inconsistent infos*/ 119 spin_lock_irqsave(&ieee->lock, flags); 120 121 if (ieee->state != IEEE80211_LINKED && 122 ieee->state != IEEE80211_LINKED_SCANNING && 123 ieee->wap_set == 0) 124 125 memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); 126 else 127 memcpy(wrqu->ap_addr.sa_data, 128 ieee->current_network.bssid, ETH_ALEN); 129 130 spin_unlock_irqrestore(&ieee->lock, flags); 131 132 return 0; 133} 134 135 136int ieee80211_wx_set_wap(struct ieee80211_device *ieee, 137 struct iw_request_info *info, 138 union iwreq_data *awrq, 139 char *extra) 140{ 141 142 int ret = 0; 143 u8 zero[] = {0,0,0,0,0,0}; 144 unsigned long flags; 145 146 short ifup = ieee->proto_started;//dev->flags & IFF_UP; 147 struct sockaddr *temp = (struct sockaddr *)awrq; 148 149 ieee->sync_scan_hurryup = 1; 150 151 down(&ieee->wx_sem); 152 /* use ifconfig hw ether */ 153 if (ieee->iw_mode == IW_MODE_MASTER){ 154 ret = -1; 155 goto out; 156 } 157 158 if (temp->sa_family != ARPHRD_ETHER){ 159 ret = -EINVAL; 160 goto out; 161 } 162 163 if (ifup) 164 ieee80211_stop_protocol(ieee); 165 166 /* just to avoid to give inconsistent infos in the 167 * get wx method. not really needed otherwise 168 */ 169 spin_lock_irqsave(&ieee->lock, flags); 170 171 memcpy(ieee->current_network.bssid, temp->sa_data, ETH_ALEN); 172 ieee->wap_set = memcmp(temp->sa_data, zero,ETH_ALEN)!=0; 173 174 spin_unlock_irqrestore(&ieee->lock, flags); 175 176 if (ifup) 177 ieee80211_start_protocol(ieee); 178out: 179 up(&ieee->wx_sem); 180 return ret; 181} 182 183 int ieee80211_wx_get_essid(struct ieee80211_device *ieee, struct iw_request_info *a,union iwreq_data *wrqu,char *b) 184{ 185 int len,ret = 0; 186 unsigned long flags; 187 188 if (ieee->iw_mode == IW_MODE_MONITOR) 189 return -1; 190 191 /* We want avoid to give to the user inconsistent infos*/ 192 spin_lock_irqsave(&ieee->lock, flags); 193 194 if (ieee->current_network.ssid[0] == '\0' || 195 ieee->current_network.ssid_len == 0){ 196 ret = -1; 197 goto out; 198 } 199 200 if (ieee->state != IEEE80211_LINKED && 201 ieee->state != IEEE80211_LINKED_SCANNING && 202 ieee->ssid_set == 0){ 203 ret = -1; 204 goto out; 205 } 206 len = ieee->current_network.ssid_len; 207 wrqu->essid.length = len; 208 strncpy(b,ieee->current_network.ssid,len); 209 wrqu->essid.flags = 1; 210 211out: 212 spin_unlock_irqrestore(&ieee->lock, flags); 213 214 return ret; 215 216} 217 218int ieee80211_wx_set_rate(struct ieee80211_device *ieee, 219 struct iw_request_info *info, 220 union iwreq_data *wrqu, char *extra) 221{ 222 223 u32 target_rate = wrqu->bitrate.value; 224 225 ieee->rate = target_rate/100000; 226 //FIXME: we might want to limit rate also in management protocols. 227 return 0; 228} 229 230 231 232int ieee80211_wx_get_rate(struct ieee80211_device *ieee, 233 struct iw_request_info *info, 234 union iwreq_data *wrqu, char *extra) 235{ 236 u32 tmp_rate; 237#if 0 238 printk("===>mode:%d, halfNmode:%d\n", ieee->mode, ieee->bHalfWirelessN24GMode); 239 if (ieee->mode & (IEEE_A | IEEE_B | IEEE_G)) 240 tmp_rate = ieee->rate; 241 else if (ieee->mode & IEEE_N_5G) 242 tmp_rate = 580; 243 else if (ieee->mode & IEEE_N_24G) 244 { 245 if (ieee->GetHalfNmodeSupportByAPsHandler(ieee->dev)) 246 tmp_rate = HTHalfMcsToDataRate(ieee, 15); 247 else 248 tmp_rate = HTMcsToDataRate(ieee, 15); 249 } 250#else 251 tmp_rate = TxCountToDataRate(ieee, ieee->softmac_stats.CurrentShowTxate); 252 253#endif 254 wrqu->bitrate.value = tmp_rate * 500000; 255 256 return 0; 257} 258 259 260int ieee80211_wx_set_rts(struct ieee80211_device *ieee, 261 struct iw_request_info *info, 262 union iwreq_data *wrqu, char *extra) 263{ 264 if (wrqu->rts.disabled || !wrqu->rts.fixed) 265 ieee->rts = DEFAULT_RTS_THRESHOLD; 266 else 267 { 268 if (wrqu->rts.value < MIN_RTS_THRESHOLD || 269 wrqu->rts.value > MAX_RTS_THRESHOLD) 270 return -EINVAL; 271 ieee->rts = wrqu->rts.value; 272 } 273 return 0; 274} 275 276int ieee80211_wx_get_rts(struct ieee80211_device *ieee, 277 struct iw_request_info *info, 278 union iwreq_data *wrqu, char *extra) 279{ 280 wrqu->rts.value = ieee->rts; 281 wrqu->rts.fixed = 0; /* no auto select */ 282 wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); 283 return 0; 284} 285int ieee80211_wx_set_mode(struct ieee80211_device *ieee, struct iw_request_info *a, 286 union iwreq_data *wrqu, char *b) 287{ 288 289 ieee->sync_scan_hurryup = 1; 290 291 down(&ieee->wx_sem); 292 293 if (wrqu->mode == ieee->iw_mode) 294 goto out; 295 296 if (wrqu->mode == IW_MODE_MONITOR){ 297 298 ieee->dev->type = ARPHRD_IEEE80211; 299 }else{ 300 ieee->dev->type = ARPHRD_ETHER; 301 } 302 303 if (!ieee->proto_started){ 304 ieee->iw_mode = wrqu->mode; 305 }else{ 306 ieee80211_stop_protocol(ieee); 307 ieee->iw_mode = wrqu->mode; 308 ieee80211_start_protocol(ieee); 309 } 310 311out: 312 up(&ieee->wx_sem); 313 return 0; 314} 315 316#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) 317void ieee80211_wx_sync_scan_wq(struct work_struct *work) 318{ 319 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, wx_sync_scan_wq); 320#else 321void ieee80211_wx_sync_scan_wq(struct ieee80211_device *ieee) 322{ 323#endif 324 short chan; 325 HT_EXTCHNL_OFFSET chan_offset=0; 326 HT_CHANNEL_WIDTH bandwidth=0; 327 int b40M = 0; 328 static int count = 0; 329 chan = ieee->current_network.channel; 330 netif_carrier_off(ieee->dev); 331 332 if (ieee->data_hard_stop) 333 ieee->data_hard_stop(ieee->dev); 334 335 ieee80211_stop_send_beacons(ieee); 336 337 ieee->state = IEEE80211_LINKED_SCANNING; 338 ieee->link_change(ieee->dev); 339 ieee->InitialGainHandler(ieee->dev,IG_Backup); 340 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT && ieee->pHTInfo->bCurBW40MHz) { 341 b40M = 1; 342 chan_offset = ieee->pHTInfo->CurSTAExtChnlOffset; 343 bandwidth = (HT_CHANNEL_WIDTH)ieee->pHTInfo->bCurBW40MHz; 344 printk("Scan in 40M, force to 20M first:%d, %d\n", chan_offset, bandwidth); 345 ieee->SetBWModeHandler(ieee->dev, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 346 } 347 ieee80211_start_scan_syncro(ieee); 348 if (b40M) { 349 printk("Scan in 20M, back to 40M\n"); 350 if (chan_offset == HT_EXTCHNL_OFFSET_UPPER) 351 ieee->set_chan(ieee->dev, chan + 2); 352 else if (chan_offset == HT_EXTCHNL_OFFSET_LOWER) 353 ieee->set_chan(ieee->dev, chan - 2); 354 else 355 ieee->set_chan(ieee->dev, chan); 356 ieee->SetBWModeHandler(ieee->dev, bandwidth, chan_offset); 357 } else { 358 ieee->set_chan(ieee->dev, chan); 359 } 360 361 ieee->InitialGainHandler(ieee->dev,IG_Restore); 362 ieee->state = IEEE80211_LINKED; 363 ieee->link_change(ieee->dev); 364 // To prevent the immediately calling watch_dog after scan. 365 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 ) 366 { 367 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; 368 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; 369 } 370 if (ieee->data_hard_resume) 371 ieee->data_hard_resume(ieee->dev); 372 373 if(ieee->iw_mode == IW_MODE_ADHOC || ieee->iw_mode == IW_MODE_MASTER) 374 ieee80211_start_send_beacons(ieee); 375 376 netif_carrier_on(ieee->dev); 377 count = 0; 378 up(&ieee->wx_sem); 379 380} 381 382int ieee80211_wx_set_scan(struct ieee80211_device *ieee, struct iw_request_info *a, 383 union iwreq_data *wrqu, char *b) 384{ 385 int ret = 0; 386 387 down(&ieee->wx_sem); 388 389 if (ieee->iw_mode == IW_MODE_MONITOR || !(ieee->proto_started)){ 390 ret = -1; 391 goto out; 392 } 393 394 if ( ieee->state == IEEE80211_LINKED){ 395#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 396 queue_work(ieee->wq, &ieee->wx_sync_scan_wq); 397#else 398 schedule_task(&ieee->wx_sync_scan_wq); 399#endif 400 /* intentionally forget to up sem */ 401 return 0; 402 } 403 404out: 405 up(&ieee->wx_sem); 406 return ret; 407} 408 409int ieee80211_wx_set_essid(struct ieee80211_device *ieee, 410 struct iw_request_info *a, 411 union iwreq_data *wrqu, char *extra) 412{ 413 414 int ret=0,len; 415 short proto_started; 416 unsigned long flags; 417 418 ieee->sync_scan_hurryup = 1; 419 down(&ieee->wx_sem); 420 421 proto_started = ieee->proto_started; 422 423 if (wrqu->essid.length > IW_ESSID_MAX_SIZE){ 424 ret= -E2BIG; 425 goto out; 426 } 427 428 if (ieee->iw_mode == IW_MODE_MONITOR){ 429 ret= -1; 430 goto out; 431 } 432 433 if(proto_started) 434 ieee80211_stop_protocol(ieee); 435 436 437 /* this is just to be sure that the GET wx callback 438 * has consisten infos. not needed otherwise 439 */ 440 spin_lock_irqsave(&ieee->lock, flags); 441 442 if (wrqu->essid.flags && wrqu->essid.length) { 443 //first flush current network.ssid 444 len = ((wrqu->essid.length-1) < IW_ESSID_MAX_SIZE) ? (wrqu->essid.length-1) : IW_ESSID_MAX_SIZE; 445#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) 446 strncpy(ieee->current_network.ssid, extra, len); 447 ieee->current_network.ssid_len = len; 448#if 0 449 { 450 int i; 451 for (i=0; i<len; i++) 452 printk("%c ", extra[i]); 453 printk("\n"); 454 } 455#endif 456#else 457 strncpy(ieee->current_network.ssid, extra, len+1); 458 ieee->current_network.ssid_len = len+1; 459#if 0 460 { 461 int i; 462 for (i=0; i<len + 1; i++) 463 printk("%c ", extra[i]); 464 printk("\n"); 465 } 466#endif 467#endif 468 ieee->ssid_set = 1; 469 } 470 else{ 471 ieee->ssid_set = 0; 472 ieee->current_network.ssid[0] = '\0'; 473 ieee->current_network.ssid_len = 0; 474 } 475 spin_unlock_irqrestore(&ieee->lock, flags); 476 477 if (proto_started) 478 ieee80211_start_protocol(ieee); 479out: 480 up(&ieee->wx_sem); 481 return ret; 482} 483 484 int ieee80211_wx_get_mode(struct ieee80211_device *ieee, struct iw_request_info *a, 485 union iwreq_data *wrqu, char *b) 486{ 487 488 wrqu->mode = ieee->iw_mode; 489 return 0; 490} 491 492 int ieee80211_wx_set_rawtx(struct ieee80211_device *ieee, 493 struct iw_request_info *info, 494 union iwreq_data *wrqu, char *extra) 495{ 496 497 int *parms = (int *)extra; 498 int enable = (parms[0] > 0); 499 short prev = ieee->raw_tx; 500 501 down(&ieee->wx_sem); 502 503 if(enable) 504 ieee->raw_tx = 1; 505 else 506 ieee->raw_tx = 0; 507 508 printk(KERN_INFO"raw TX is %s\n", 509 ieee->raw_tx ? "enabled" : "disabled"); 510 511 if(ieee->iw_mode == IW_MODE_MONITOR) 512 { 513 if(prev == 0 && ieee->raw_tx){ 514 if (ieee->data_hard_resume) 515 ieee->data_hard_resume(ieee->dev); 516 517 netif_carrier_on(ieee->dev); 518 } 519 520 if(prev && ieee->raw_tx == 1) 521 netif_carrier_off(ieee->dev); 522 } 523 524 up(&ieee->wx_sem); 525 526 return 0; 527} 528 529int ieee80211_wx_get_name(struct ieee80211_device *ieee, 530 struct iw_request_info *info, 531 union iwreq_data *wrqu, char *extra) 532{ 533 strcpy(wrqu->name, "802.11"); 534 if(ieee->modulation & IEEE80211_CCK_MODULATION){ 535 strcat(wrqu->name, "b"); 536 if(ieee->modulation & IEEE80211_OFDM_MODULATION) 537 strcat(wrqu->name, "/g"); 538 }else if(ieee->modulation & IEEE80211_OFDM_MODULATION) 539 strcat(wrqu->name, "g"); 540 if (ieee->mode & (IEEE_N_24G | IEEE_N_5G)) 541 strcat(wrqu->name, "/n"); 542 543 if((ieee->state == IEEE80211_LINKED) || 544 (ieee->state == IEEE80211_LINKED_SCANNING)) 545 strcat(wrqu->name," linked"); 546 else if(ieee->state != IEEE80211_NOLINK) 547 strcat(wrqu->name," link.."); 548 549 550 return 0; 551} 552 553 554/* this is mostly stolen from hostap */ 555int ieee80211_wx_set_power(struct ieee80211_device *ieee, 556 struct iw_request_info *info, 557 union iwreq_data *wrqu, char *extra) 558{ 559 int ret = 0; 560#if 0 561 if( 562 (!ieee->sta_wake_up) || 563 (!ieee->ps_request_tx_ack) || 564 (!ieee->enter_sleep_state) || 565 (!ieee->ps_is_queue_empty)){ 566 567 // printk("ERROR. PS mode is tryied to be use but driver missed a callback\n\n"); 568 569 return -1; 570 } 571#endif 572 down(&ieee->wx_sem); 573 574 if (wrqu->power.disabled){ 575 ieee->ps = IEEE80211_PS_DISABLED; 576 goto exit; 577 } 578 if (wrqu->power.flags & IW_POWER_TIMEOUT) { 579 //ieee->ps_period = wrqu->power.value / 1000; 580 ieee->ps_timeout = wrqu->power.value / 1000; 581 } 582 583 if (wrqu->power.flags & IW_POWER_PERIOD) { 584 585 //ieee->ps_timeout = wrqu->power.value / 1000; 586 ieee->ps_period = wrqu->power.value / 1000; 587 //wrq->value / 1024; 588 589 } 590 switch (wrqu->power.flags & IW_POWER_MODE) { 591 case IW_POWER_UNICAST_R: 592 ieee->ps = IEEE80211_PS_UNICAST; 593 break; 594 case IW_POWER_MULTICAST_R: 595 ieee->ps = IEEE80211_PS_MBCAST; 596 break; 597 case IW_POWER_ALL_R: 598 ieee->ps = IEEE80211_PS_UNICAST | IEEE80211_PS_MBCAST; 599 break; 600 601 case IW_POWER_ON: 602 // ieee->ps = IEEE80211_PS_DISABLED; 603 break; 604 605 default: 606 ret = -EINVAL; 607 goto exit; 608 609 } 610exit: 611 up(&ieee->wx_sem); 612 return ret; 613 614} 615 616/* this is stolen from hostap */ 617int ieee80211_wx_get_power(struct ieee80211_device *ieee, 618 struct iw_request_info *info, 619 union iwreq_data *wrqu, char *extra) 620{ 621 int ret =0; 622 623 down(&ieee->wx_sem); 624 625 if(ieee->ps == IEEE80211_PS_DISABLED){ 626 wrqu->power.disabled = 1; 627 goto exit; 628 } 629 630 wrqu->power.disabled = 0; 631 632 if ((wrqu->power.flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { 633 wrqu->power.flags = IW_POWER_TIMEOUT; 634 wrqu->power.value = ieee->ps_timeout * 1000; 635 } else { 636// ret = -EOPNOTSUPP; 637// goto exit; 638 wrqu->power.flags = IW_POWER_PERIOD; 639 wrqu->power.value = ieee->ps_period * 1000; 640//ieee->current_network.dtim_period * ieee->current_network.beacon_interval * 1024; 641 } 642 643 if ((ieee->ps & (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) == (IEEE80211_PS_MBCAST | IEEE80211_PS_UNICAST)) 644 wrqu->power.flags |= IW_POWER_ALL_R; 645 else if (ieee->ps & IEEE80211_PS_MBCAST) 646 wrqu->power.flags |= IW_POWER_MULTICAST_R; 647 else 648 wrqu->power.flags |= IW_POWER_UNICAST_R; 649 650exit: 651 up(&ieee->wx_sem); 652 return ret; 653 654} 655#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 656EXPORT_SYMBOL(ieee80211_wx_get_essid); 657EXPORT_SYMBOL(ieee80211_wx_set_essid); 658EXPORT_SYMBOL(ieee80211_wx_set_rate); 659EXPORT_SYMBOL(ieee80211_wx_get_rate); 660EXPORT_SYMBOL(ieee80211_wx_set_wap); 661EXPORT_SYMBOL(ieee80211_wx_get_wap); 662EXPORT_SYMBOL(ieee80211_wx_set_mode); 663EXPORT_SYMBOL(ieee80211_wx_get_mode); 664EXPORT_SYMBOL(ieee80211_wx_set_scan); 665EXPORT_SYMBOL(ieee80211_wx_get_freq); 666EXPORT_SYMBOL(ieee80211_wx_set_freq); 667EXPORT_SYMBOL(ieee80211_wx_set_rawtx); 668EXPORT_SYMBOL(ieee80211_wx_get_name); 669EXPORT_SYMBOL(ieee80211_wx_set_power); 670EXPORT_SYMBOL(ieee80211_wx_get_power); 671EXPORT_SYMBOL(ieee80211_wlan_frequencies); 672EXPORT_SYMBOL(ieee80211_wx_set_rts); 673EXPORT_SYMBOL(ieee80211_wx_get_rts); 674#else 675EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_essid); 676EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_essid); 677EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rate); 678EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_rate); 679EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_wap); 680EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_wap); 681EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_mode); 682EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_mode); 683EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_scan); 684EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_freq); 685EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_freq); 686EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rawtx); 687EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_name); 688EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_power); 689EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_power); 690EXPORT_SYMBOL_NOVERS(ieee80211_wlan_frequencies); 691EXPORT_SYMBOL_NOVERS(ieee80211_wx_set_rts); 692EXPORT_SYMBOL_NOVERS(ieee80211_wx_get_rts); 693#endif 694