ieee80211_softmac.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 * Few lines might be stolen from other part of the ieee80211 8 * stack. Copyright who own it's copyright 9 * 10 * WPA code stolen from the ipw2200 driver. 11 * Copyright who own it's copyright. 12 * 13 * released under the GPL 14 */ 15 16 17#include "ieee80211.h" 18 19#include <linux/random.h> 20#include <linux/delay.h> 21#include <linux/version.h> 22#include <asm/uaccess.h> 23#ifdef ENABLE_DOT11D 24#include "dot11d.h" 25#endif 26 27u8 rsn_authen_cipher_suite[16][4] = { 28 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved 29 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default 30 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default} 31 {0x00,0x0F,0xAC,0x03}, //WRAP-historical 32 {0x00,0x0F,0xAC,0x04}, //CCMP 33 {0x00,0x0F,0xAC,0x05}, //WEP-104 34}; 35 36short ieee80211_is_54g(struct ieee80211_network net) 37{ 38 return ((net.rates_ex_len > 0) || (net.rates_len > 4)); 39} 40 41short ieee80211_is_shortslot(struct ieee80211_network net) 42{ 43 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT); 44} 45 46/* returns the total length needed for pleacing the RATE MFIE 47 * tag and the EXTENDED RATE MFIE tag if needed. 48 * It encludes two bytes per tag for the tag itself and its len 49 */ 50unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee) 51{ 52 unsigned int rate_len = 0; 53 54 if (ieee->modulation & IEEE80211_CCK_MODULATION) 55 rate_len = IEEE80211_CCK_RATE_LEN + 2; 56 57 if (ieee->modulation & IEEE80211_OFDM_MODULATION) 58 59 rate_len += IEEE80211_OFDM_RATE_LEN + 2; 60 61 return rate_len; 62} 63 64/* pleace the MFIE rate, tag to the memory (double) poined. 65 * Then it updates the pointer so that 66 * it points after the new MFIE tag added. 67 */ 68void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p) 69{ 70 u8 *tag = *tag_p; 71 72 if (ieee->modulation & IEEE80211_CCK_MODULATION){ 73 *tag++ = MFIE_TYPE_RATES; 74 *tag++ = 4; 75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; 76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; 77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; 78 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; 79 } 80 81 /* We may add an option for custom rates that specific HW might support */ 82 *tag_p = tag; 83} 84 85void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p) 86{ 87 u8 *tag = *tag_p; 88 89 if (ieee->modulation & IEEE80211_OFDM_MODULATION){ 90 91 *tag++ = MFIE_TYPE_RATES_EX; 92 *tag++ = 8; 93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; 94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; 95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; 96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; 97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; 98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; 99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; 100 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; 101 102 } 103 104 /* We may add an option for custom rates that specific HW might support */ 105 *tag_p = tag; 106} 107 108 109void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) { 110 u8 *tag = *tag_p; 111 112 *tag++ = MFIE_TYPE_GENERIC; //0 113 *tag++ = 7; 114 *tag++ = 0x00; 115 *tag++ = 0x50; 116 *tag++ = 0xf2; 117 *tag++ = 0x02;//5 118 *tag++ = 0x00; 119 *tag++ = 0x01; 120#ifdef SUPPORT_USPD 121 if(ieee->current_network.wmm_info & 0x80) { 122 *tag++ = 0x0f|MAX_SP_Len; 123 } else { 124 *tag++ = MAX_SP_Len; 125 } 126#else 127 *tag++ = MAX_SP_Len; 128#endif 129 *tag_p = tag; 130} 131 132#ifdef THOMAS_TURBO 133void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) { 134 u8 *tag = *tag_p; 135 136 *tag++ = MFIE_TYPE_GENERIC; //0 137 *tag++ = 7; 138 *tag++ = 0x00; 139 *tag++ = 0xe0; 140 *tag++ = 0x4c; 141 *tag++ = 0x01;//5 142 *tag++ = 0x02; 143 *tag++ = 0x11; 144 *tag++ = 0x00; 145 146 *tag_p = tag; 147 printk(KERN_ALERT "This is enable turbo mode IE process\n"); 148} 149#endif 150 151void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb) 152{ 153 int nh; 154 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM; 155 156/* 157 * if the queue is full but we have newer frames then 158 * just overwrites the oldest. 159 * 160 * if (nh == ieee->mgmt_queue_tail) 161 * return -1; 162 */ 163 ieee->mgmt_queue_head = nh; 164 ieee->mgmt_queue_ring[nh] = skb; 165 166 //return 0; 167} 168 169struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee) 170{ 171 struct sk_buff *ret; 172 173 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head) 174 return NULL; 175 176 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail]; 177 178 ieee->mgmt_queue_tail = 179 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM; 180 181 return ret; 182} 183 184void init_mgmt_queue(struct ieee80211_device *ieee) 185{ 186 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0; 187} 188 189u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee) 190{ 191 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 192 u8 rate; 193 194 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. 195 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M) 196 rate = 0x0c; 197 else 198 rate = ieee->basic_rate & 0x7f; 199 200 if(rate == 0){ 201 // 2005.01.26, by rcnjko. 202 if(ieee->mode == IEEE_A|| 203 ieee->mode== IEEE_N_5G|| 204 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK)) 205 rate = 0x0c; 206 else 207 rate = 0x02; 208 } 209 210 /* 211 // Data rate of ProbeReq is already decided. Annie, 2005-03-31 212 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) ) 213 { 214 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A) 215 rate = 0x0c; 216 else 217 rate = 0x02; 218 } 219 */ 220 return rate; 221} 222 223 224void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl); 225 226inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) 227{ 228 unsigned long flags; 229 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; 230 struct ieee80211_hdr_3addr *header= 231 (struct ieee80211_hdr_3addr *) skb->data; 232 233 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8); 234 spin_lock_irqsave(&ieee->lock, flags); 235 236 /* called with 2nd param 0, no mgmt lock required */ 237 ieee80211_sta_wakeup(ieee,0); 238 239 tcb_desc->queue_index = MGNT_QUEUE; 240 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee); 241 tcb_desc->RATRIndex = 7; 242 tcb_desc->bTxDisableRateFallBack = 1; 243 tcb_desc->bTxUseDriverAssingedRate = 1; 244 245 if(single){ 246 if(ieee->queue_stop){ 247 enqueue_mgmt(ieee,skb); 248 }else{ 249 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4); 250 251 if (ieee->seq_ctrl[0] == 0xFFF) 252 ieee->seq_ctrl[0] = 0; 253 else 254 ieee->seq_ctrl[0]++; 255 256 /* avoid watchdog triggers */ 257 ieee->dev->trans_start = jiffies; 258 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); 259 //dev_kfree_skb_any(skb);//edit by thomas 260 } 261 262 spin_unlock_irqrestore(&ieee->lock, flags); 263 }else{ 264 spin_unlock_irqrestore(&ieee->lock, flags); 265 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags); 266 267 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); 268 269 if (ieee->seq_ctrl[0] == 0xFFF) 270 ieee->seq_ctrl[0] = 0; 271 else 272 ieee->seq_ctrl[0]++; 273 274 /* check wether the managed packet queued greater than 5 */ 275 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\ 276 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\ 277 (ieee->queue_stop) ) { 278 /* insert the skb packet to the management queue */ 279 /* as for the completion function, it does not need 280 * to check it any more. 281 * */ 282 printk("%s():insert to waitqueue!\n",__FUNCTION__); 283 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb); 284 } else { 285 //printk("TX packet!\n"); 286 ieee->softmac_hard_start_xmit(skb,ieee->dev); 287 //dev_kfree_skb_any(skb);//edit by thomas 288 } 289 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags); 290 } 291} 292 293inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee) 294{ 295 296 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE; 297 struct ieee80211_hdr_3addr *header = 298 (struct ieee80211_hdr_3addr *) skb->data; 299 300 301 if(single){ 302 303 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); 304 305 if (ieee->seq_ctrl[0] == 0xFFF) 306 ieee->seq_ctrl[0] = 0; 307 else 308 ieee->seq_ctrl[0]++; 309 310 /* avoid watchdog triggers */ 311 ieee->dev->trans_start = jiffies; 312 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); 313 314 }else{ 315 316 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); 317 318 if (ieee->seq_ctrl[0] == 0xFFF) 319 ieee->seq_ctrl[0] = 0; 320 else 321 ieee->seq_ctrl[0]++; 322 323 ieee->softmac_hard_start_xmit(skb,ieee->dev); 324 325 } 326 //dev_kfree_skb_any(skb);//edit by thomas 327} 328 329inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee) 330{ 331 unsigned int len,rate_len; 332 u8 *tag; 333 struct sk_buff *skb; 334 struct ieee80211_probe_request *req; 335 336 len = ieee->current_network.ssid_len; 337 338 rate_len = ieee80211_MFIE_rate_len(ieee); 339 340 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) + 341 2 + len + rate_len + ieee->tx_headroom); 342 if (!skb) 343 return NULL; 344 345 skb_reserve(skb, ieee->tx_headroom); 346 347 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request)); 348 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); 349 req->header.duration_id = 0; //FIXME: is this OK ? 350 351 memset(req->header.addr1, 0xff, ETH_ALEN); 352 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 353 memset(req->header.addr3, 0xff, ETH_ALEN); 354 355 tag = (u8 *) skb_put(skb,len+2+rate_len); 356 357 *tag++ = MFIE_TYPE_SSID; 358 *tag++ = len; 359 memcpy(tag, ieee->current_network.ssid, len); 360 tag += len; 361 362 ieee80211_MFIE_Brate(ieee,&tag); 363 ieee80211_MFIE_Grate(ieee,&tag); 364 return skb; 365} 366 367struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee); 368void ieee80211_send_beacon(struct ieee80211_device *ieee) 369{ 370 struct sk_buff *skb; 371 if(!ieee->ieee_up) 372 return; 373 //unsigned long flags; 374 skb = ieee80211_get_beacon_(ieee); 375 376 if (skb){ 377 softmac_mgmt_xmit(skb, ieee); 378 ieee->softmac_stats.tx_beacons++; 379 //dev_kfree_skb_any(skb);//edit by thomas 380 } 381// ieee->beacon_timer.expires = jiffies + 382// (MSECS( ieee->current_network.beacon_interval -5)); 383 384 //spin_lock_irqsave(&ieee->beacon_lock,flags); 385 if(ieee->beacon_txing && ieee->ieee_up){ 386// if(!timer_pending(&ieee->beacon_timer)) 387// add_timer(&ieee->beacon_timer); 388 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5))); 389 } 390 //spin_unlock_irqrestore(&ieee->beacon_lock,flags); 391} 392 393 394void ieee80211_send_beacon_cb(unsigned long _ieee) 395{ 396 struct ieee80211_device *ieee = 397 (struct ieee80211_device *) _ieee; 398 unsigned long flags; 399 400 spin_lock_irqsave(&ieee->beacon_lock, flags); 401 ieee80211_send_beacon(ieee); 402 spin_unlock_irqrestore(&ieee->beacon_lock, flags); 403} 404 405 406void ieee80211_send_probe(struct ieee80211_device *ieee) 407{ 408 struct sk_buff *skb; 409 410 skb = ieee80211_probe_req(ieee); 411 if (skb){ 412 softmac_mgmt_xmit(skb, ieee); 413 ieee->softmac_stats.tx_probe_rq++; 414 //dev_kfree_skb_any(skb);//edit by thomas 415 } 416} 417 418void ieee80211_send_probe_requests(struct ieee80211_device *ieee) 419{ 420 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){ 421 ieee80211_send_probe(ieee); 422 ieee80211_send_probe(ieee); 423 } 424} 425 426/* this performs syncro scan blocking the caller until all channels 427 * in the allowed channel map has been checked. 428 */ 429void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee) 430{ 431 short ch = 0; 432#ifdef ENABLE_DOT11D 433 u8 channel_map[MAX_CHANNEL_NUMBER+1]; 434 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); 435#endif 436 down(&ieee->scan_sem); 437 438 while(1) 439 { 440 441 do{ 442 ch++; 443 if (ch > MAX_CHANNEL_NUMBER) 444 goto out; /* scan completed */ 445#ifdef ENABLE_DOT11D 446 }while(!channel_map[ch]); 447#else 448 }while(!ieee->channel_map[ch]); 449#endif 450 451 /* this fuction can be called in two situations 452 * 1- We have switched to ad-hoc mode and we are 453 * performing a complete syncro scan before conclude 454 * there are no interesting cell and to create a 455 * new one. In this case the link state is 456 * IEEE80211_NOLINK until we found an interesting cell. 457 * If so the ieee8021_new_net, called by the RX path 458 * will set the state to IEEE80211_LINKED, so we stop 459 * scanning 460 * 2- We are linked and the root uses run iwlist scan. 461 * So we switch to IEEE80211_LINKED_SCANNING to remember 462 * that we are still logically linked (not interested in 463 * new network events, despite for updating the net list, 464 * but we are temporarly 'unlinked' as the driver shall 465 * not filter RX frames and the channel is changing. 466 * So the only situation in witch are interested is to check 467 * if the state become LINKED because of the #1 situation 468 */ 469 470 if (ieee->state == IEEE80211_LINKED) 471 goto out; 472 ieee->set_chan(ieee->dev, ch); 473#ifdef ENABLE_DOT11D 474 if(channel_map[ch] == 1) 475#endif 476 ieee80211_send_probe_requests(ieee); 477 478 /* this prevent excessive time wait when we 479 * need to wait for a syncro scan to end.. 480 */ 481 if(ieee->state < IEEE80211_LINKED) 482 ; 483 else 484 if (ieee->sync_scan_hurryup) 485 goto out; 486 487 488 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME); 489 490 } 491out: 492 if(ieee->state < IEEE80211_LINKED){ 493 ieee->actscanning = false; 494 up(&ieee->scan_sem); 495 } 496 else{ 497 ieee->sync_scan_hurryup = 0; 498#ifdef ENABLE_DOT11D 499 if(IS_DOT11D_ENABLE(ieee)) 500 DOT11D_ScanComplete(ieee); 501#endif 502 up(&ieee->scan_sem); 503} 504} 505 506#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 507/* called both by wq with ieee->lock held */ 508void ieee80211_softmac_scan(struct ieee80211_device *ieee) 509{ 510#if 0 511 short watchdog = 0; 512 do{ 513 ieee->current_network.channel = 514 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; 515 if (watchdog++ > MAX_CHANNEL_NUMBER) 516 return; /* no good chans */ 517 518 }while(!ieee->channel_map[ieee->current_network.channel]); 519#endif 520 521 schedule_task(&ieee->softmac_scan_wq); 522} 523#endif 524 525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) 526void ieee80211_softmac_scan_wq(struct work_struct *work) 527{ 528 struct delayed_work *dwork = container_of(work, struct delayed_work, work); 529 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq); 530#else 531void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee) 532{ 533#endif 534 static short watchdog = 0; 535#ifdef ENABLE_DOT11D 536 u8 channel_map[MAX_CHANNEL_NUMBER+1]; 537 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1); 538#endif 539 if(!ieee->ieee_up) 540 return; 541 down(&ieee->scan_sem); 542 do{ 543 ieee->current_network.channel = 544 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER; 545 if (watchdog++ > MAX_CHANNEL_NUMBER) 546 { 547 //if current channel is not in channel map, set to default channel. 548 #ifdef ENABLE_DOT11D 549 if (!channel_map[ieee->current_network.channel]); 550 #else 551 if (!ieee->channel_map[ieee->current_network.channel]); 552 #endif 553 ieee->current_network.channel = 6; 554 goto out; /* no good chans */ 555 } 556#ifdef ENABLE_DOT11D 557 }while(!channel_map[ieee->current_network.channel]); 558#else 559 }while(!ieee->channel_map[ieee->current_network.channel]); 560#endif 561 if (ieee->scanning == 0 ) 562 goto out; 563 ieee->set_chan(ieee->dev, ieee->current_network.channel); 564#ifdef ENABLE_DOT11D 565 if(channel_map[ieee->current_network.channel] == 1) 566#endif 567 ieee80211_send_probe_requests(ieee); 568 569 570#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 571 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME); 572#else 573 //ieee->scan_timer.expires = jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME); 574 if (ieee->scanning == 1) 575 mod_timer(&ieee->scan_timer,(jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME))); 576#endif 577 578 up(&ieee->scan_sem); 579 return; 580out: 581#ifdef ENABLE_DOT11D 582 if(IS_DOT11D_ENABLE(ieee)) 583 DOT11D_ScanComplete(ieee); 584#endif 585 ieee->actscanning = false; 586 watchdog = 0; 587 ieee->scanning = 0; 588 up(&ieee->scan_sem); 589} 590 591#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 592void ieee80211_softmac_scan_cb(unsigned long _dev) 593{ 594 unsigned long flags; 595 struct ieee80211_device *ieee = (struct ieee80211_device *)_dev; 596 597 spin_lock_irqsave(&ieee->lock, flags); 598 ieee80211_softmac_scan(ieee); 599 spin_unlock_irqrestore(&ieee->lock, flags); 600} 601#endif 602 603 604void ieee80211_beacons_start(struct ieee80211_device *ieee) 605{ 606 unsigned long flags; 607 spin_lock_irqsave(&ieee->beacon_lock,flags); 608 609 ieee->beacon_txing = 1; 610 ieee80211_send_beacon(ieee); 611 612 spin_unlock_irqrestore(&ieee->beacon_lock,flags); 613} 614 615void ieee80211_beacons_stop(struct ieee80211_device *ieee) 616{ 617 unsigned long flags; 618 619 spin_lock_irqsave(&ieee->beacon_lock,flags); 620 621 ieee->beacon_txing = 0; 622 del_timer_sync(&ieee->beacon_timer); 623 624 spin_unlock_irqrestore(&ieee->beacon_lock,flags); 625 626} 627 628 629void ieee80211_stop_send_beacons(struct ieee80211_device *ieee) 630{ 631 if(ieee->stop_send_beacons) 632 ieee->stop_send_beacons(ieee->dev); 633 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS) 634 ieee80211_beacons_stop(ieee); 635} 636 637 638void ieee80211_start_send_beacons(struct ieee80211_device *ieee) 639{ 640 if(ieee->start_send_beacons) 641 ieee->start_send_beacons(ieee->dev,ieee->basic_rate); 642 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS) 643 ieee80211_beacons_start(ieee); 644} 645 646 647void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee) 648{ 649// unsigned long flags; 650 651 //ieee->sync_scan_hurryup = 1; 652 653 down(&ieee->scan_sem); 654// spin_lock_irqsave(&ieee->lock, flags); 655 656 if (ieee->scanning == 1){ 657 ieee->scanning = 0; 658 659#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 660 cancel_delayed_work(&ieee->softmac_scan_wq); 661#else 662 del_timer_sync(&ieee->scan_timer); 663#endif 664 } 665 666// spin_unlock_irqrestore(&ieee->lock, flags); 667 up(&ieee->scan_sem); 668} 669 670void ieee80211_stop_scan(struct ieee80211_device *ieee) 671{ 672 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) 673 ieee80211_softmac_stop_scan(ieee); 674 else 675 ieee->stop_scan(ieee->dev); 676} 677 678/* called with ieee->lock held */ 679void ieee80211_start_scan(struct ieee80211_device *ieee) 680{ 681#ifdef ENABLE_DOT11D 682 if(IS_DOT11D_ENABLE(ieee) ) 683 { 684 if(IS_COUNTRY_IE_VALID(ieee)) 685 { 686 RESET_CIE_WATCHDOG(ieee); 687 } 688 } 689#endif 690 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){ 691 if (ieee->scanning == 0){ 692 ieee->scanning = 1; 693#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 694#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) 695 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0); 696#else 697 698 queue_work(ieee->wq, &ieee->softmac_scan_wq); 699#endif 700#else 701 ieee80211_softmac_scan(ieee); 702#endif 703 } 704 }else 705 ieee->start_scan(ieee->dev); 706 707} 708 709/* called with wx_sem held */ 710void ieee80211_start_scan_syncro(struct ieee80211_device *ieee) 711{ 712#ifdef ENABLE_DOT11D 713 if(IS_DOT11D_ENABLE(ieee) ) 714 { 715 if(IS_COUNTRY_IE_VALID(ieee)) 716 { 717 RESET_CIE_WATCHDOG(ieee); 718 } 719 } 720#endif 721 ieee->sync_scan_hurryup = 0; 722 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN) 723 ieee80211_softmac_scan_syncro(ieee); 724 else 725 ieee->scan_syncro(ieee->dev); 726 727} 728 729inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon, 730 struct ieee80211_device *ieee, int challengelen) 731{ 732 struct sk_buff *skb; 733 struct ieee80211_authentication *auth; 734 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom; 735 736 737 skb = dev_alloc_skb(len); 738 if (!skb) return NULL; 739 740 skb_reserve(skb, ieee->tx_headroom); 741 auth = (struct ieee80211_authentication *) 742 skb_put(skb, sizeof(struct ieee80211_authentication)); 743 744 auth->header.frame_ctl = IEEE80211_STYPE_AUTH; 745 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP; 746 747 auth->header.duration_id = 0x013a; //FIXME 748 749 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN); 750 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 751 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN); 752 753 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY; 754 if(ieee->auth_mode == 0) 755 auth->algorithm = WLAN_AUTH_OPEN; 756 else if(ieee->auth_mode == 1) 757 auth->algorithm = WLAN_AUTH_SHARED_KEY; 758 else if(ieee->auth_mode == 2) 759 auth->algorithm = WLAN_AUTH_OPEN;//0x80; 760 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm); 761 auth->transaction = cpu_to_le16(ieee->associate_seq); 762 ieee->associate_seq++; 763 764 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS); 765 766 return skb; 767 768} 769 770 771static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest) 772{ 773 u8 *tag; 774 int beacon_size; 775 struct ieee80211_probe_response *beacon_buf; 776 struct sk_buff *skb = NULL; 777 int encrypt; 778 int atim_len,erp_len; 779 struct ieee80211_crypt_data* crypt; 780 781 char *ssid = ieee->current_network.ssid; 782 int ssid_len = ieee->current_network.ssid_len; 783 int rate_len = ieee->current_network.rates_len+2; 784 int rate_ex_len = ieee->current_network.rates_ex_len; 785 int wpa_ie_len = ieee->wpa_ie_len; 786 u8 erpinfo_content = 0; 787 788 u8* tmp_ht_cap_buf; 789 u8 tmp_ht_cap_len=0; 790 u8* tmp_ht_info_buf; 791 u8 tmp_ht_info_len=0; 792 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo; 793 u8* tmp_generic_ie_buf=NULL; 794 u8 tmp_generic_ie_len=0; 795 796 if(rate_ex_len > 0) rate_ex_len+=2; 797 798 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS) 799 atim_len = 4; 800 else 801 atim_len = 0; 802 803#if 1 804 if(ieee80211_is_54g(ieee->current_network)) 805 erp_len = 3; 806 else 807 erp_len = 0; 808#else 809 if((ieee->current_network.mode == IEEE_G) 810 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) { 811 erp_len = 3; 812 erpinfo_content = 0; 813 if(ieee->current_network.buseprotection) 814 erpinfo_content |= ERP_UseProtection; 815 } 816 else 817 erp_len = 0; 818#endif 819 820 821 crypt = ieee->crypt[ieee->tx_keyidx]; 822 823 824 encrypt = ieee->host_encrypt && crypt && crypt->ops && 825 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len)); 826 //HT ralated element 827#if 1 828 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap); 829 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); 830 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo); 831 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo); 832 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt); 833 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt); 834 835 836 if(pHTInfo->bRegRT2RTAggregation) 837 { 838 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; 839 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer); 840 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len); 841 } 842// printk("===============>tmp_ht_cap_len is %d,tmp_ht_info_len is %d, tmp_generic_ie_len is %d\n",tmp_ht_cap_len,tmp_ht_info_len,tmp_generic_ie_len); 843#endif 844 beacon_size = sizeof(struct ieee80211_probe_response)+2+ 845 ssid_len 846 +3 //channel 847 +rate_len 848 +rate_ex_len 849 +atim_len 850 +erp_len 851 +wpa_ie_len 852 // +tmp_ht_cap_len 853 // +tmp_ht_info_len 854 // +tmp_generic_ie_len 855// +wmm_len+2 856 +ieee->tx_headroom; 857 skb = dev_alloc_skb(beacon_size); 858 if (!skb) 859 return NULL; 860 skb_reserve(skb, ieee->tx_headroom); 861 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom)); 862 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN); 863 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 864 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN); 865 866 beacon_buf->header.duration_id = 0; //FIXME 867 beacon_buf->beacon_interval = 868 cpu_to_le16(ieee->current_network.beacon_interval); 869 beacon_buf->capability = 870 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS); 871 beacon_buf->capability |= 872 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here 873 874 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT)) 875 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT)); 876 877 crypt = ieee->crypt[ieee->tx_keyidx]; 878#if 0 879 encrypt = ieee->host_encrypt && crypt && crypt->ops && 880 (0 == strcmp(crypt->ops->name, "WEP")); 881#endif 882 if (encrypt) 883 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); 884 885 886 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP); 887 beacon_buf->info_element[0].id = MFIE_TYPE_SSID; 888 beacon_buf->info_element[0].len = ssid_len; 889 890 tag = (u8*) beacon_buf->info_element[0].data; 891 892 memcpy(tag, ssid, ssid_len); 893 894 tag += ssid_len; 895 896 *(tag++) = MFIE_TYPE_RATES; 897 *(tag++) = rate_len-2; 898 memcpy(tag,ieee->current_network.rates,rate_len-2); 899 tag+=rate_len-2; 900 901 *(tag++) = MFIE_TYPE_DS_SET; 902 *(tag++) = 1; 903 *(tag++) = ieee->current_network.channel; 904 905 if(atim_len){ 906 u16 val16; 907 *(tag++) = MFIE_TYPE_IBSS_SET; 908 *(tag++) = 2; 909 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window); 910 val16 = cpu_to_le16(ieee->current_network.atim_window); 911 memcpy((u8 *)tag, (u8 *)&val16, 2); 912 tag+=2; 913 } 914 915 if(erp_len){ 916 *(tag++) = MFIE_TYPE_ERP; 917 *(tag++) = 1; 918 *(tag++) = erpinfo_content; 919 } 920#if 0 921 //Include High Throuput capability 922 923 *(tag++) = MFIE_TYPE_HT_CAP; 924 *(tag++) = tmp_ht_cap_len - 2; 925 memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2); 926 tag += tmp_ht_cap_len - 2; 927#endif 928 if(rate_ex_len){ 929 *(tag++) = MFIE_TYPE_RATES_EX; 930 *(tag++) = rate_ex_len-2; 931 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2); 932 tag+=rate_ex_len-2; 933 } 934 935#if 0 936 //Include High Throuput info 937 938 *(tag++) = MFIE_TYPE_HT_INFO; 939 *(tag++) = tmp_ht_info_len - 2; 940 memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2); 941 tag += tmp_ht_info_len - 2; 942#endif 943 if (wpa_ie_len) 944 { 945 if (ieee->iw_mode == IW_MODE_ADHOC) 946 {//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07 947 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4); 948 } 949 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); 950 tag += wpa_ie_len; 951 } 952 953#if 0 954 // 955 // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k) 956 // 957 if(pHTInfo->bRegRT2RTAggregation) 958 { 959 (*tag++) = 0xdd; 960 (*tag++) = tmp_generic_ie_len - 2; 961 memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2); 962 tag += tmp_generic_ie_len -2; 963 964 } 965#endif 966#if 0 967 if(ieee->qos_support) 968 { 969 (*tag++) = 0xdd; 970 (*tag++) = wmm_len; 971 memcpy(tag,QosOui,wmm_len); 972 tag += wmm_len; 973 } 974#endif 975 //skb->dev = ieee->dev; 976 return skb; 977} 978 979 980struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest) 981{ 982 struct sk_buff *skb; 983 u8* tag; 984 985 struct ieee80211_crypt_data* crypt; 986 struct ieee80211_assoc_response_frame *assoc; 987 short encrypt; 988 989 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); 990 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom; 991 992 skb = dev_alloc_skb(len); 993 994 if (!skb) 995 return NULL; 996 997 skb_reserve(skb, ieee->tx_headroom); 998 999 assoc = (struct ieee80211_assoc_response_frame *) 1000 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame)); 1001 1002 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP); 1003 memcpy(assoc->header.addr1, dest,ETH_ALEN); 1004 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN); 1005 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 1006 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ? 1007 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS); 1008 1009 1010 if(ieee->short_slot) 1011 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); 1012 1013 if (ieee->host_encrypt) 1014 crypt = ieee->crypt[ieee->tx_keyidx]; 1015 else crypt = NULL; 1016 1017 encrypt = ( crypt && crypt->ops); 1018 1019 if (encrypt) 1020 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); 1021 1022 assoc->status = 0; 1023 assoc->aid = cpu_to_le16(ieee->assoc_id); 1024 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0; 1025 else ieee->assoc_id++; 1026 1027 tag = (u8*) skb_put(skb, rate_len); 1028 1029 ieee80211_MFIE_Brate(ieee, &tag); 1030 ieee80211_MFIE_Grate(ieee, &tag); 1031 1032 return skb; 1033} 1034 1035struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest) 1036{ 1037 struct sk_buff *skb; 1038 struct ieee80211_authentication *auth; 1039 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1; 1040 1041 skb = dev_alloc_skb(len); 1042 1043 if (!skb) 1044 return NULL; 1045 1046 skb->len = sizeof(struct ieee80211_authentication); 1047 1048 auth = (struct ieee80211_authentication *)skb->data; 1049 1050 auth->status = cpu_to_le16(status); 1051 auth->transaction = cpu_to_le16(2); 1052 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN); 1053 1054 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN); 1055 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 1056 memcpy(auth->header.addr1, dest, ETH_ALEN); 1057 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH); 1058 return skb; 1059 1060 1061} 1062 1063struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr) 1064{ 1065 struct sk_buff *skb; 1066 struct ieee80211_hdr_3addr* hdr; 1067 1068 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr)); 1069 1070 if (!skb) 1071 return NULL; 1072 1073 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr)); 1074 1075 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN); 1076 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN); 1077 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN); 1078 1079 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | 1080 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS | 1081 (pwr ? IEEE80211_FCTL_PM:0)); 1082 1083 return skb; 1084 1085 1086} 1087 1088 1089void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest) 1090{ 1091 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest); 1092 1093 if (buf) 1094 softmac_mgmt_xmit(buf, ieee); 1095} 1096 1097 1098void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest) 1099{ 1100 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest); 1101 1102 if (buf) 1103 softmac_mgmt_xmit(buf, ieee); 1104} 1105 1106 1107void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest) 1108{ 1109 1110 1111 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest); 1112 if (buf) 1113 softmac_mgmt_xmit(buf, ieee); 1114} 1115 1116 1117inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee) 1118{ 1119 struct sk_buff *skb; 1120 //unsigned long flags; 1121 1122 struct ieee80211_assoc_request_frame *hdr; 1123 u8 *tag;//,*rsn_ie; 1124 //short info_addr = 0; 1125 //int i; 1126 //u16 suite_count = 0; 1127 //u8 suit_select = 0; 1128 //unsigned int wpa_len = beacon->wpa_ie_len; 1129 //for HT 1130 u8* ht_cap_buf = NULL; 1131 u8 ht_cap_len=0; 1132 u8* realtek_ie_buf=NULL; 1133 u8 realtek_ie_len=0; 1134 int wpa_ie_len= ieee->wpa_ie_len; 1135 unsigned int ckip_ie_len=0; 1136 unsigned int ccxrm_ie_len=0; 1137 unsigned int cxvernum_ie_len=0; 1138 struct ieee80211_crypt_data* crypt; 1139 int encrypt; 1140 1141 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee); 1142 unsigned int wmm_info_len = beacon->qos_data.supported?9:0; 1143#ifdef THOMAS_TURBO 1144 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0; 1145#endif 1146 1147 int len = 0; 1148 1149 crypt = ieee->crypt[ieee->tx_keyidx]; 1150 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len)); 1151 1152 //Include High Throuput capability && Realtek proprietary 1153 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) 1154 { 1155 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap); 1156 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap); 1157 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt); 1158 if(ieee->pHTInfo->bCurrentRT2RTAggregation) 1159 { 1160 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer; 1161 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer); 1162 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len); 1163 1164 } 1165 } 1166 if(ieee->qos_support){ 1167 wmm_info_len = beacon->qos_data.supported?9:0; 1168 } 1169 1170 1171 if(beacon->bCkipSupported) 1172 { 1173 ckip_ie_len = 30+2; 1174 } 1175 if(beacon->bCcxRmEnable) 1176 { 1177 ccxrm_ie_len = 6+2; 1178 } 1179 if( beacon->BssCcxVerNumber >= 2 ) 1180 { 1181 cxvernum_ie_len = 5+2; 1182 } 1183#ifdef THOMAS_TURBO 1184 len = sizeof(struct ieee80211_assoc_request_frame)+ 2 1185 + beacon->ssid_len//essid tagged val 1186 + rate_len//rates tagged val 1187 + wpa_ie_len 1188 + wmm_info_len 1189 + turbo_info_len 1190 + ht_cap_len 1191 + realtek_ie_len 1192 + ckip_ie_len 1193 + ccxrm_ie_len 1194 + cxvernum_ie_len 1195 + ieee->tx_headroom; 1196#else 1197 len = sizeof(struct ieee80211_assoc_request_frame)+ 2 1198 + beacon->ssid_len//essid tagged val 1199 + rate_len//rates tagged val 1200 + wpa_ie_len 1201 + wmm_info_len 1202 + ht_cap_len 1203 + realtek_ie_len 1204 + ckip_ie_len 1205 + ccxrm_ie_len 1206 + cxvernum_ie_len 1207 + ieee->tx_headroom; 1208#endif 1209 1210 skb = dev_alloc_skb(len); 1211 1212 if (!skb) 1213 return NULL; 1214 1215 skb_reserve(skb, ieee->tx_headroom); 1216 1217 hdr = (struct ieee80211_assoc_request_frame *) 1218 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2); 1219 1220 1221 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ; 1222 hdr->header.duration_id= 37; //FIXME 1223 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN); 1224 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 1225 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN); 1226 1227 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John 1228 1229 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS); 1230 if (beacon->capability & WLAN_CAPABILITY_PRIVACY ) 1231 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); 1232 1233 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) 1234 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here 1235 1236 if(ieee->short_slot) 1237 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT); 1238 if (wmm_info_len) //QOS 1239 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS); 1240 1241 hdr->listen_interval = 0xa; //FIXME 1242 1243 hdr->info_element[0].id = MFIE_TYPE_SSID; 1244 1245 hdr->info_element[0].len = beacon->ssid_len; 1246 tag = skb_put(skb, beacon->ssid_len); 1247 memcpy(tag, beacon->ssid, beacon->ssid_len); 1248 1249 tag = skb_put(skb, rate_len); 1250 1251 ieee80211_MFIE_Brate(ieee, &tag); 1252 ieee80211_MFIE_Grate(ieee, &tag); 1253 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14. 1254 if( beacon->bCkipSupported ) 1255 { 1256 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client" 1257 u8 CcxAironetBuf[30]; 1258 OCTET_STRING osCcxAironetIE; 1259 1260 memset(CcxAironetBuf, 0,30); 1261 osCcxAironetIE.Octet = CcxAironetBuf; 1262 osCcxAironetIE.Length = sizeof(CcxAironetBuf); 1263 // 1264 // Ref. CCX test plan v3.61, 3.2.3.1 step 13. 1265 // We want to make the device type as "4500-client". 060926, by CCW. 1266 // 1267 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui)); 1268 1269 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23): 1270 // "The CKIP negotiation is started with the associate request from the client to the access point, 1271 // containing an Aironet element with both the MIC and KP bits set." 1272 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ; 1273 tag = skb_put(skb, ckip_ie_len); 1274 *tag++ = MFIE_TYPE_AIRONET; 1275 *tag++ = osCcxAironetIE.Length; 1276 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length); 1277 tag += osCcxAironetIE.Length; 1278 } 1279 1280 if(beacon->bCcxRmEnable) 1281 { 1282 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00}; 1283 OCTET_STRING osCcxRmCap; 1284 1285 osCcxRmCap.Octet = CcxRmCapBuf; 1286 osCcxRmCap.Length = sizeof(CcxRmCapBuf); 1287 tag = skb_put(skb,ccxrm_ie_len); 1288 *tag++ = MFIE_TYPE_GENERIC; 1289 *tag++ = osCcxRmCap.Length; 1290 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length); 1291 tag += osCcxRmCap.Length; 1292 } 1293 1294 if( beacon->BssCcxVerNumber >= 2 ) 1295 { 1296 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00}; 1297 OCTET_STRING osCcxVerNum; 1298 CcxVerNumBuf[4] = beacon->BssCcxVerNumber; 1299 osCcxVerNum.Octet = CcxVerNumBuf; 1300 osCcxVerNum.Length = sizeof(CcxVerNumBuf); 1301 tag = skb_put(skb,cxvernum_ie_len); 1302 *tag++ = MFIE_TYPE_GENERIC; 1303 *tag++ = osCcxVerNum.Length; 1304 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length); 1305 tag += osCcxVerNum.Length; 1306 } 1307 //HT cap element 1308 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ 1309 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) 1310 { 1311 tag = skb_put(skb, ht_cap_len); 1312 *tag++ = MFIE_TYPE_HT_CAP; 1313 *tag++ = ht_cap_len - 2; 1314 memcpy(tag, ht_cap_buf,ht_cap_len -2); 1315 tag += ht_cap_len -2; 1316 } 1317 } 1318 1319 1320 //choose what wpa_supplicant gives to associate. 1321 tag = skb_put(skb, wpa_ie_len); 1322 if (wpa_ie_len){ 1323 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len); 1324 } 1325 1326 tag = skb_put(skb,wmm_info_len); 1327 if(wmm_info_len) { 1328 ieee80211_WMM_Info(ieee, &tag); 1329 } 1330#ifdef THOMAS_TURBO 1331 tag = skb_put(skb,turbo_info_len); 1332 if(turbo_info_len) { 1333 ieee80211_TURBO_Info(ieee, &tag); 1334 } 1335#endif 1336 1337 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){ 1338 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) 1339 { 1340 tag = skb_put(skb, ht_cap_len); 1341 *tag++ = MFIE_TYPE_GENERIC; 1342 *tag++ = ht_cap_len - 2; 1343 memcpy(tag, ht_cap_buf,ht_cap_len - 2); 1344 tag += ht_cap_len -2; 1345 } 1346 1347 if(ieee->pHTInfo->bCurrentRT2RTAggregation){ 1348 tag = skb_put(skb, realtek_ie_len); 1349 *tag++ = MFIE_TYPE_GENERIC; 1350 *tag++ = realtek_ie_len - 2; 1351 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 ); 1352 } 1353 } 1354// printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr); 1355// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len); 1356 return skb; 1357} 1358 1359void ieee80211_associate_abort(struct ieee80211_device *ieee) 1360{ 1361 1362 unsigned long flags; 1363 spin_lock_irqsave(&ieee->lock, flags); 1364 1365 ieee->associate_seq++; 1366 1367 /* don't scan, and avoid to have the RX path possibily 1368 * try again to associate. Even do not react to AUTH or 1369 * ASSOC response. Just wait for the retry wq to be scheduled. 1370 * Here we will check if there are good nets to associate 1371 * with, so we retry or just get back to NO_LINK and scanning 1372 */ 1373 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){ 1374 IEEE80211_DEBUG_MGMT("Authentication failed\n"); 1375 ieee->softmac_stats.no_auth_rs++; 1376 }else{ 1377 IEEE80211_DEBUG_MGMT("Association failed\n"); 1378 ieee->softmac_stats.no_ass_rs++; 1379 } 1380 1381 ieee->state = IEEE80211_ASSOCIATING_RETRY; 1382 1383#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1384 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \ 1385 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME); 1386#else 1387 schedule_task(&ieee->associate_retry_wq); 1388#endif 1389 1390 spin_unlock_irqrestore(&ieee->lock, flags); 1391} 1392 1393void ieee80211_associate_abort_cb(unsigned long dev) 1394{ 1395 ieee80211_associate_abort((struct ieee80211_device *) dev); 1396} 1397 1398 1399void ieee80211_associate_step1(struct ieee80211_device *ieee) 1400{ 1401 struct ieee80211_network *beacon = &ieee->current_network; 1402 struct sk_buff *skb; 1403 1404 IEEE80211_DEBUG_MGMT("Stopping scan\n"); 1405 1406 ieee->softmac_stats.tx_auth_rq++; 1407 skb=ieee80211_authentication_req(beacon, ieee, 0); 1408 1409 if (!skb) 1410 ieee80211_associate_abort(ieee); 1411 else{ 1412 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ; 1413 IEEE80211_DEBUG_MGMT("Sending authentication request\n"); 1414 //printk(KERN_WARNING "Sending authentication request\n"); 1415 softmac_mgmt_xmit(skb, ieee); 1416 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709 1417 if(!timer_pending(&ieee->associate_timer)){ 1418 ieee->associate_timer.expires = jiffies + (HZ / 2); 1419 add_timer(&ieee->associate_timer); 1420 } 1421 //dev_kfree_skb_any(skb);//edit by thomas 1422 } 1423} 1424 1425void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen) 1426{ 1427 u8 *c; 1428 struct sk_buff *skb; 1429 struct ieee80211_network *beacon = &ieee->current_network; 1430// int hlen = sizeof(struct ieee80211_authentication); 1431 1432 ieee->associate_seq++; 1433 ieee->softmac_stats.tx_auth_rq++; 1434 1435 skb = ieee80211_authentication_req(beacon, ieee, chlen+2); 1436 if (!skb) 1437 ieee80211_associate_abort(ieee); 1438 else{ 1439 c = skb_put(skb, chlen+2); 1440 *(c++) = MFIE_TYPE_CHALLENGE; 1441 *(c++) = chlen; 1442 memcpy(c, challenge, chlen); 1443 1444 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n"); 1445 1446 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr )); 1447 1448 softmac_mgmt_xmit(skb, ieee); 1449 mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); 1450#if 0 1451 ieee->associate_timer.expires = jiffies + (HZ / 2); 1452 add_timer(&ieee->associate_timer); 1453#endif 1454 //dev_kfree_skb_any(skb);//edit by thomas 1455 } 1456 kfree(challenge); 1457} 1458 1459void ieee80211_associate_step2(struct ieee80211_device *ieee) 1460{ 1461 struct sk_buff* skb; 1462 struct ieee80211_network *beacon = &ieee->current_network; 1463 1464 del_timer_sync(&ieee->associate_timer); 1465 1466 IEEE80211_DEBUG_MGMT("Sending association request\n"); 1467 1468 ieee->softmac_stats.tx_ass_rq++; 1469 skb=ieee80211_association_req(beacon, ieee); 1470 if (!skb) 1471 ieee80211_associate_abort(ieee); 1472 else{ 1473 softmac_mgmt_xmit(skb, ieee); 1474 mod_timer(&ieee->associate_timer, jiffies + (HZ/2)); 1475#if 0 1476 ieee->associate_timer.expires = jiffies + (HZ / 2); 1477 add_timer(&ieee->associate_timer); 1478#endif 1479 //dev_kfree_skb_any(skb);//edit by thomas 1480 } 1481} 1482#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) 1483void ieee80211_associate_complete_wq(struct work_struct *work) 1484{ 1485 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq); 1486#else 1487void ieee80211_associate_complete_wq(struct ieee80211_device *ieee) 1488{ 1489#endif 1490 printk(KERN_INFO "Associated successfully\n"); 1491 if(ieee80211_is_54g(ieee->current_network) && 1492 (ieee->modulation & IEEE80211_OFDM_MODULATION)){ 1493 1494 ieee->rate = 108; 1495 printk(KERN_INFO"Using G rates:%d\n", ieee->rate); 1496 }else{ 1497 ieee->rate = 22; 1498 printk(KERN_INFO"Using B rates:%d\n", ieee->rate); 1499 } 1500 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT) 1501 { 1502 printk("Successfully associated, ht enabled\n"); 1503 HTOnAssocRsp(ieee); 1504 } 1505 else 1506 { 1507 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT); 1508 memset(ieee->dot11HTOperationalRateSet, 0, 16); 1509 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 1510 } 1511 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500); 1512 // To prevent the immediately calling watch_dog after association. 1513 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 ) 1514 { 1515 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1; 1516 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1; 1517 } 1518 ieee->link_change(ieee->dev); 1519 if(ieee->is_silent_reset == 0){ 1520 printk("============>normal associate\n"); 1521 notify_wx_assoc_event(ieee); 1522 } 1523 else if(ieee->is_silent_reset == 1) 1524 { 1525 printk("==================>silent reset associate\n"); 1526 ieee->is_silent_reset = 0; 1527 } 1528 1529 if (ieee->data_hard_resume) 1530 ieee->data_hard_resume(ieee->dev); 1531 netif_carrier_on(ieee->dev); 1532} 1533 1534void ieee80211_associate_complete(struct ieee80211_device *ieee) 1535{ 1536// int i; 1537// struct net_device* dev = ieee->dev; 1538 del_timer_sync(&ieee->associate_timer); 1539 1540#if 0 1541 for(i = 0; i < 6; i++) { 1542 ieee->seq_ctrl[i] = 0; 1543 } 1544#endif 1545 ieee->state = IEEE80211_LINKED; 1546#if 0 1547 if (ieee->pHTInfo->bCurrentHTSupport) 1548 { 1549 printk("Successfully associated, ht enabled\n"); 1550 queue_work(ieee->wq, &ieee->ht_onAssRsp); 1551 } 1552 else 1553 { 1554 printk("Successfully associated, ht not enabled\n"); 1555 memset(ieee->dot11HTOperationalRateSet, 0, 16); 1556 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 1557 } 1558#endif 1559 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet); 1560#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1561 queue_work(ieee->wq, &ieee->associate_complete_wq); 1562#else 1563 schedule_task(&ieee->associate_complete_wq); 1564#endif 1565} 1566 1567#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) 1568void ieee80211_associate_procedure_wq(struct work_struct *work) 1569{ 1570 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq); 1571#else 1572void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee) 1573{ 1574#endif 1575 ieee->sync_scan_hurryup = 1; 1576 down(&ieee->wx_sem); 1577 1578 if (ieee->data_hard_stop) 1579 ieee->data_hard_stop(ieee->dev); 1580 1581 ieee80211_stop_scan(ieee); 1582 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel); 1583 //ieee->set_chan(ieee->dev, ieee->current_network.channel); 1584 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 1585 1586 ieee->associate_seq = 1; 1587 ieee80211_associate_step1(ieee); 1588 1589 up(&ieee->wx_sem); 1590} 1591 1592inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net) 1593{ 1594 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1]; 1595 int tmp_ssid_len = 0; 1596 1597 short apset,ssidset,ssidbroad,apmatch,ssidmatch; 1598 1599 /* we are interested in new new only if we are not associated 1600 * and we are not associating / authenticating 1601 */ 1602 if (ieee->state != IEEE80211_NOLINK) 1603 return; 1604 1605 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS)) 1606 return; 1607 1608 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS)) 1609 return; 1610 1611 1612 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){ 1613 /* if the user specified the AP MAC, we need also the essid 1614 * This could be obtained by beacons or, if the network does not 1615 * broadcast it, it can be put manually. 1616 */ 1617 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 ); 1618 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0'; 1619 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0'); 1620 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0); 1621 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\ 1622 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len)); 1623 1624 1625 if ( /* if the user set the AP check if match. 1626 * if the network does not broadcast essid we check the user supplyed ANY essid 1627 * if the network does broadcast and the user does not set essid it is OK 1628 * if the network does broadcast and the user did set essid chech if essid match 1629 */ 1630 ( apset && apmatch && 1631 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) || 1632 /* if the ap is not set, check that the user set the bssid 1633 * and the network does bradcast and that those two bssid matches 1634 */ 1635 (!apset && ssidset && ssidbroad && ssidmatch) 1636 ){ 1637 /* if the essid is hidden replace it with the 1638 * essid provided by the user. 1639 */ 1640 if (!ssidbroad){ 1641 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE); 1642 tmp_ssid_len = ieee->current_network.ssid_len; 1643 } 1644 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network)); 1645 1646 if (!ssidbroad){ 1647 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE); 1648 ieee->current_network.ssid_len = tmp_ssid_len; 1649 } 1650 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT); 1651 1652 //ieee->pHTInfo->IOTAction = 0; 1653 HTResetIOTSetting(ieee->pHTInfo); 1654 if (ieee->iw_mode == IW_MODE_INFRA){ 1655 /* Join the network for the first time */ 1656 ieee->AsocRetryCount = 0; 1657 //for HT by amy 080514 1658 if((ieee->current_network.qos_data.supported == 1) && 1659 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT)) 1660 ieee->current_network.bssht.bdSupportHT) 1661/*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/ 1662 { 1663 // ieee->pHTInfo->bCurrentHTSupport = true; 1664 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network)); 1665 } 1666 else 1667 { 1668 ieee->pHTInfo->bCurrentHTSupport = false; 1669 } 1670 1671 ieee->state = IEEE80211_ASSOCIATING; 1672#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 1673 queue_work(ieee->wq, &ieee->associate_procedure_wq); 1674#else 1675 schedule_task(&ieee->associate_procedure_wq); 1676#endif 1677 }else{ 1678 if(ieee80211_is_54g(ieee->current_network) && 1679 (ieee->modulation & IEEE80211_OFDM_MODULATION)){ 1680 ieee->rate = 108; 1681 ieee->SetWirelessMode(ieee->dev, IEEE_G); 1682 printk(KERN_INFO"Using G rates\n"); 1683 }else{ 1684 ieee->rate = 22; 1685 ieee->SetWirelessMode(ieee->dev, IEEE_B); 1686 printk(KERN_INFO"Using B rates\n"); 1687 } 1688 memset(ieee->dot11HTOperationalRateSet, 0, 16); 1689 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 1690 ieee->state = IEEE80211_LINKED; 1691 } 1692 1693 } 1694 } 1695 1696} 1697 1698void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee) 1699{ 1700 unsigned long flags; 1701 struct ieee80211_network *target; 1702 1703 spin_lock_irqsave(&ieee->lock, flags); 1704 1705 list_for_each_entry(target, &ieee->network_list, list) { 1706 1707 /* if the state become different that NOLINK means 1708 * we had found what we are searching for 1709 */ 1710 1711 if (ieee->state != IEEE80211_NOLINK) 1712 break; 1713 1714 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies)) 1715 ieee80211_softmac_new_net(ieee, target); 1716 } 1717 1718 spin_unlock_irqrestore(&ieee->lock, flags); 1719 1720} 1721 1722 1723static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen) 1724{ 1725 struct ieee80211_authentication *a; 1726 u8 *t; 1727 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ 1728 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len); 1729 return 0xcafe; 1730 } 1731 *challenge = NULL; 1732 a = (struct ieee80211_authentication*) skb->data; 1733 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){ 1734 t = skb->data + sizeof(struct ieee80211_authentication); 1735 1736 if(*(t++) == MFIE_TYPE_CHALLENGE){ 1737 *chlen = *(t++); 1738 *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC); 1739 memcpy(*challenge, t, *chlen); 1740 } 1741 } 1742 1743 return cpu_to_le16(a->status); 1744 1745} 1746 1747 1748int auth_rq_parse(struct sk_buff *skb,u8* dest) 1749{ 1750 struct ieee80211_authentication *a; 1751 1752 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){ 1753 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len); 1754 return -1; 1755 } 1756 a = (struct ieee80211_authentication*) skb->data; 1757 1758 memcpy(dest,a->header.addr2, ETH_ALEN); 1759 1760 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN) 1761 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; 1762 1763 return WLAN_STATUS_SUCCESS; 1764} 1765 1766static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src) 1767{ 1768 u8 *tag; 1769 u8 *skbend; 1770 u8 *ssid=NULL; 1771 u8 ssidlen = 0; 1772 1773 struct ieee80211_hdr_3addr *header = 1774 (struct ieee80211_hdr_3addr *) skb->data; 1775 1776 if (skb->len < sizeof (struct ieee80211_hdr_3addr )) 1777 return -1; /* corrupted */ 1778 1779 memcpy(src,header->addr2, ETH_ALEN); 1780 1781 skbend = (u8*)skb->data + skb->len; 1782 1783 tag = skb->data + sizeof (struct ieee80211_hdr_3addr ); 1784 1785 while (tag+1 < skbend){ 1786 if (*tag == 0){ 1787 ssid = tag+2; 1788 ssidlen = *(tag+1); 1789 break; 1790 } 1791 tag++; /* point to the len field */ 1792 tag = tag + *(tag); /* point to the last data byte of the tag */ 1793 tag++; /* point to the next tag */ 1794 } 1795 1796 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src)); 1797 if (ssidlen == 0) return 1; 1798 1799 if (!ssid) return 1; /* ssid not found in tagged param */ 1800 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen)); 1801 1802} 1803 1804int assoc_rq_parse(struct sk_buff *skb,u8* dest) 1805{ 1806 struct ieee80211_assoc_request_frame *a; 1807 1808 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) - 1809 sizeof(struct ieee80211_info_element))) { 1810 1811 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len); 1812 return -1; 1813 } 1814 1815 a = (struct ieee80211_assoc_request_frame*) skb->data; 1816 1817 memcpy(dest,a->header.addr2,ETH_ALEN); 1818 1819 return 0; 1820} 1821 1822static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid) 1823{ 1824 struct ieee80211_assoc_response_frame *response_head; 1825 u16 status_code; 1826 1827 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){ 1828 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len); 1829 return 0xcafe; 1830 } 1831 1832 response_head = (struct ieee80211_assoc_response_frame*) skb->data; 1833 *aid = le16_to_cpu(response_head->aid) & 0x3fff; 1834 1835 status_code = le16_to_cpu(response_head->status); 1836 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \ 1837 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&& 1838 ((ieee->mode == IEEE_G) && 1839 (ieee->current_network.mode == IEEE_N_24G) && 1840 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) { 1841 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE; 1842 }else { 1843 ieee->AsocRetryCount = 0; 1844 } 1845 1846 return le16_to_cpu(response_head->status); 1847} 1848 1849static inline void 1850ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb) 1851{ 1852 u8 dest[ETH_ALEN]; 1853 1854 //IEEE80211DMESG("Rx probe"); 1855 ieee->softmac_stats.rx_probe_rq++; 1856 //DMESG("Dest is "MACSTR, MAC2STR(dest)); 1857 if (probe_rq_parse(ieee, skb, dest)){ 1858 //IEEE80211DMESG("Was for me!"); 1859 ieee->softmac_stats.tx_probe_rs++; 1860 ieee80211_resp_to_probe(ieee, dest); 1861 } 1862} 1863 1864static inline void 1865ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb) 1866{ 1867 u8 dest[ETH_ALEN]; 1868 int status; 1869 //IEEE80211DMESG("Rx probe"); 1870 ieee->softmac_stats.rx_auth_rq++; 1871 1872 if ((status = auth_rq_parse(skb, dest))!= -1){ 1873 ieee80211_resp_to_auth(ieee, status, dest); 1874 } 1875 //DMESG("Dest is "MACSTR, MAC2STR(dest)); 1876 1877} 1878 1879static inline void 1880ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb) 1881{ 1882 1883 u8 dest[ETH_ALEN]; 1884 //unsigned long flags; 1885 1886 ieee->softmac_stats.rx_ass_rq++; 1887 if (assoc_rq_parse(skb,dest) != -1){ 1888 ieee80211_resp_to_assoc_rq(ieee, dest); 1889 } 1890 1891 printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest)); 1892 //FIXME 1893 #if 0 1894 spin_lock_irqsave(&ieee->lock,flags); 1895 add_associate(ieee,dest); 1896 spin_unlock_irqrestore(&ieee->lock,flags); 1897 #endif 1898} 1899 1900 1901 1902void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr) 1903{ 1904 1905 struct sk_buff *buf = ieee80211_null_func(ieee, pwr); 1906 1907 if (buf) 1908 softmac_ps_mgmt_xmit(buf, ieee); 1909 1910} 1911 1912 1913short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l) 1914{ 1915 int timeout = ieee->ps_timeout; 1916 u8 dtim; 1917 /*if(ieee->ps == IEEE80211_PS_DISABLED || 1918 ieee->iw_mode != IW_MODE_INFRA || 1919 ieee->state != IEEE80211_LINKED) 1920 1921 return 0; 1922 */ 1923 dtim = ieee->current_network.dtim_data; 1924 //printk("DTIM\n"); 1925 if(!(dtim & IEEE80211_DTIM_VALID)) 1926 return 0; 1927 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval 1928 //printk("VALID\n"); 1929 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID; 1930 1931 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps)) 1932 return 2; 1933 1934 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))) 1935 return 0; 1936 1937 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))) 1938 return 0; 1939 1940 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) && 1941 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head)) 1942 return 0; 1943 1944 if(time_l){ 1945 *time_l = ieee->current_network.last_dtim_sta_time[0] 1946 + (ieee->current_network.beacon_interval 1947 * ieee->current_network.dtim_period) * 1000; 1948 } 1949 1950 if(time_h){ 1951 *time_h = ieee->current_network.last_dtim_sta_time[1]; 1952 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0]) 1953 *time_h += 1; 1954 } 1955 1956 return 1; 1957 1958 1959} 1960 1961inline void ieee80211_sta_ps(struct ieee80211_device *ieee) 1962{ 1963 1964 u32 th,tl; 1965 short sleep; 1966 1967 unsigned long flags,flags2; 1968 1969 spin_lock_irqsave(&ieee->lock, flags); 1970 1971 if((ieee->ps == IEEE80211_PS_DISABLED || 1972 ieee->iw_mode != IW_MODE_INFRA || 1973 ieee->state != IEEE80211_LINKED)){ 1974 1975 // #warning CHECK_LOCK_HERE 1976 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); 1977 1978 ieee80211_sta_wakeup(ieee, 1); 1979 1980 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); 1981 } 1982 1983 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl); 1984 /* 2 wake, 1 sleep, 0 do nothing */ 1985 if(sleep == 0) 1986 goto out; 1987 1988 if(sleep == 1){ 1989 1990 if(ieee->sta_sleep == 1) 1991 ieee->enter_sleep_state(ieee->dev,th,tl); 1992 1993 else if(ieee->sta_sleep == 0){ 1994 // printk("send null 1\n"); 1995 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); 1996 1997 if(ieee->ps_is_queue_empty(ieee->dev)){ 1998 1999 2000 ieee->sta_sleep = 2; 2001 2002 ieee->ps_request_tx_ack(ieee->dev); 2003 2004 ieee80211_sta_ps_send_null_frame(ieee,1); 2005 2006 ieee->ps_th = th; 2007 ieee->ps_tl = tl; 2008 } 2009 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); 2010 2011 } 2012 2013 2014 }else if(sleep == 2){ 2015//#warning CHECK_LOCK_HERE 2016 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); 2017 2018 ieee80211_sta_wakeup(ieee,1); 2019 2020 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); 2021 } 2022 2023out: 2024 spin_unlock_irqrestore(&ieee->lock, flags); 2025 2026} 2027 2028void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl) 2029{ 2030 if(ieee->sta_sleep == 0){ 2031 if(nl){ 2032 printk("Warning: driver is probably failing to report TX ps error\n"); 2033 ieee->ps_request_tx_ack(ieee->dev); 2034 ieee80211_sta_ps_send_null_frame(ieee, 0); 2035 } 2036 return; 2037 2038 } 2039 2040 if(ieee->sta_sleep == 1) 2041 ieee->sta_wake_up(ieee->dev); 2042 2043 ieee->sta_sleep = 0; 2044 2045 if(nl){ 2046 ieee->ps_request_tx_ack(ieee->dev); 2047 ieee80211_sta_ps_send_null_frame(ieee, 0); 2048 } 2049} 2050 2051void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success) 2052{ 2053 unsigned long flags,flags2; 2054 2055 spin_lock_irqsave(&ieee->lock, flags); 2056 2057 if(ieee->sta_sleep == 2){ 2058 /* Null frame with PS bit set */ 2059 if(success){ 2060 ieee->sta_sleep = 1; 2061 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl); 2062 } 2063 /* if the card report not success we can't be sure the AP 2064 * has not RXed so we can't assume the AP believe us awake 2065 */ 2066 } 2067 /* 21112005 - tx again null without PS bit if lost */ 2068 else { 2069 2070 if((ieee->sta_sleep == 0) && !success){ 2071 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2); 2072 ieee80211_sta_ps_send_null_frame(ieee, 0); 2073 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2); 2074 } 2075 } 2076 spin_unlock_irqrestore(&ieee->lock, flags); 2077} 2078void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb) 2079{ 2080 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data; 2081 u8* act = ieee80211_get_payload(header); 2082 u8 tmp = 0; 2083// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len); 2084 if (act == NULL) 2085 { 2086 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n"); 2087 return; 2088 } 2089 tmp = *act; 2090 act ++; 2091 switch (tmp) 2092 { 2093 case ACT_CAT_BA: 2094 if (*act == ACT_ADDBAREQ) 2095 ieee80211_rx_ADDBAReq(ieee, skb); 2096 else if (*act == ACT_ADDBARSP) 2097 ieee80211_rx_ADDBARsp(ieee, skb); 2098 else if (*act == ACT_DELBA) 2099 ieee80211_rx_DELBA(ieee, skb); 2100 break; 2101 default: 2102// if (net_ratelimit()) 2103// IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp); 2104 break; 2105 } 2106 return; 2107 2108} 2109inline int 2110ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb, 2111 struct ieee80211_rx_stats *rx_stats, u16 type, 2112 u16 stype) 2113{ 2114 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data; 2115 u16 errcode; 2116 u8* challenge; 2117 int chlen=0; 2118 int aid; 2119 struct ieee80211_assoc_response_frame *assoc_resp; 2120// struct ieee80211_info_element *info_element; 2121 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode 2122 2123 if(!ieee->proto_started) 2124 return 0; 2125 2126 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED && 2127 ieee->iw_mode == IW_MODE_INFRA && 2128 ieee->state == IEEE80211_LINKED)) 2129 2130 tasklet_schedule(&ieee->ps_task); 2131 2132 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP && 2133 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON) 2134 ieee->last_rx_ps_time = jiffies; 2135 2136 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) { 2137 2138 case IEEE80211_STYPE_ASSOC_RESP: 2139 case IEEE80211_STYPE_REASSOC_RESP: 2140 2141 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n", 2142 WLAN_FC_GET_STYPE(header->frame_ctl)); 2143 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && 2144 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED && 2145 ieee->iw_mode == IW_MODE_INFRA){ 2146 struct ieee80211_network network_resp; 2147 struct ieee80211_network *network = &network_resp; 2148 2149 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){ 2150 ieee->state=IEEE80211_LINKED; 2151 ieee->assoc_id = aid; 2152 ieee->softmac_stats.rx_ass_ok++; 2153 /* station support qos */ 2154 /* Let the register setting defaultly with Legacy station */ 2155 if(ieee->qos_support) { 2156 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data; 2157 memset(network, 0, sizeof(*network)); 2158 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\ 2159 rx_stats->len - sizeof(*assoc_resp),\ 2160 network,rx_stats)){ 2161 return 1; 2162 } 2163 else 2164 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network. 2165 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen); 2166 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen); 2167 } 2168 if (ieee->handle_assoc_response != NULL) 2169 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network); 2170 } 2171 ieee80211_associate_complete(ieee); 2172 } else { 2173 /* aid could not been allocated */ 2174 ieee->softmac_stats.rx_ass_err++; 2175 printk( 2176 "Association response status code 0x%x\n", 2177 errcode); 2178 IEEE80211_DEBUG_MGMT( 2179 "Association response status code 0x%x\n", 2180 errcode); 2181 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) { 2182#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2183 queue_work(ieee->wq, &ieee->associate_procedure_wq); 2184#else 2185 schedule_task(&ieee->associate_procedure_wq); 2186#endif 2187 } else { 2188 ieee80211_associate_abort(ieee); 2189 } 2190 } 2191 } 2192 break; 2193 2194 case IEEE80211_STYPE_ASSOC_REQ: 2195 case IEEE80211_STYPE_REASSOC_REQ: 2196 2197 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && 2198 ieee->iw_mode == IW_MODE_MASTER) 2199 2200 ieee80211_rx_assoc_rq(ieee, skb); 2201 break; 2202 2203 case IEEE80211_STYPE_AUTH: 2204 2205 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){ 2206 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING && 2207 ieee->iw_mode == IW_MODE_INFRA){ 2208 2209 IEEE80211_DEBUG_MGMT("Received authentication response"); 2210 2211 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){ 2212 if(ieee->open_wep || !challenge){ 2213 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED; 2214 ieee->softmac_stats.rx_auth_rs_ok++; 2215 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE)) 2216 { 2217 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) 2218 { 2219 // WEP or TKIP encryption 2220 if(IsHTHalfNmodeAPs(ieee)) 2221 { 2222 bSupportNmode = true; 2223 bHalfSupportNmode = true; 2224 } 2225 else 2226 { 2227 bSupportNmode = false; 2228 bHalfSupportNmode = false; 2229 } 2230 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode); 2231 } 2232 } 2233 /* Dummy wirless mode setting to avoid encryption issue */ 2234 if(bSupportNmode) { 2235 //N mode setting 2236 ieee->SetWirelessMode(ieee->dev, \ 2237 ieee->current_network.mode); 2238 }else{ 2239 //b/g mode setting 2240 /*TODO*/ 2241 ieee->SetWirelessMode(ieee->dev, IEEE_G); 2242 } 2243 2244 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true) 2245 { 2246 printk("===============>entern half N mode\n"); 2247 ieee->bHalfWirelessN24GMode = true; 2248 } 2249 else 2250 ieee->bHalfWirelessN24GMode = false; 2251 2252 ieee80211_associate_step2(ieee); 2253 }else{ 2254 ieee80211_auth_challenge(ieee, challenge, chlen); 2255 } 2256 }else{ 2257 ieee->softmac_stats.rx_auth_rs_err++; 2258 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode); 2259 ieee80211_associate_abort(ieee); 2260 } 2261 2262 }else if (ieee->iw_mode == IW_MODE_MASTER){ 2263 ieee80211_rx_auth_rq(ieee, skb); 2264 } 2265 } 2266 break; 2267 2268 case IEEE80211_STYPE_PROBE_REQ: 2269 2270 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) && 2271 ((ieee->iw_mode == IW_MODE_ADHOC || 2272 ieee->iw_mode == IW_MODE_MASTER) && 2273 ieee->state == IEEE80211_LINKED)){ 2274 ieee80211_rx_probe_rq(ieee, skb); 2275 } 2276 break; 2277 2278 case IEEE80211_STYPE_DISASSOC: 2279 case IEEE80211_STYPE_DEAUTH: 2280 /* FIXME for now repeat all the association procedure 2281 * both for disassociation and deauthentication 2282 */ 2283 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) && 2284 ieee->state == IEEE80211_LINKED && 2285 ieee->iw_mode == IW_MODE_INFRA){ 2286 2287 ieee->state = IEEE80211_ASSOCIATING; 2288 ieee->softmac_stats.reassoc++; 2289 2290 notify_wx_assoc_event(ieee); 2291 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 2292 RemovePeerTS(ieee, header->addr2); 2293#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2294 queue_work(ieee->wq, &ieee->associate_procedure_wq); 2295#else 2296 schedule_task(&ieee->associate_procedure_wq); 2297#endif 2298 } 2299 break; 2300 case IEEE80211_STYPE_MANAGE_ACT: 2301 ieee80211_process_action(ieee,skb); 2302 break; 2303 default: 2304 return -1; 2305 break; 2306 } 2307 2308 //dev_kfree_skb_any(skb); 2309 return 0; 2310} 2311 2312/* following are for a simplier TX queue management. 2313 * Instead of using netif_[stop/wake]_queue the driver 2314 * will uses these two function (plus a reset one), that 2315 * will internally uses the kernel netif_* and takes 2316 * care of the ieee802.11 fragmentation. 2317 * So the driver receives a fragment per time and might 2318 * call the stop function when it want without take care 2319 * to have enought room to TX an entire packet. 2320 * This might be useful if each fragment need it's own 2321 * descriptor, thus just keep a total free memory > than 2322 * the max fragmentation treshold is not enought.. If the 2323 * ieee802.11 stack passed a TXB struct then you needed 2324 * to keep N free descriptors where 2325 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD 2326 * In this way you need just one and the 802.11 stack 2327 * will take care of buffering fragments and pass them to 2328 * to the driver later, when it wakes the queue. 2329 */ 2330void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee) 2331{ 2332 2333 unsigned int queue_index = txb->queue_index; 2334 unsigned long flags; 2335 int i; 2336 cb_desc *tcb_desc = NULL; 2337 2338 spin_lock_irqsave(&ieee->lock,flags); 2339 2340 /* called with 2nd parm 0, no tx mgmt lock required */ 2341 ieee80211_sta_wakeup(ieee,0); 2342 2343 /* update the tx status */ 2344 ieee->stats.tx_bytes += txb->payload_size; 2345 ieee->stats.tx_packets++; 2346 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE); 2347 if(tcb_desc->bMulticast) { 2348 ieee->stats.multicast++; 2349 } 2350#if 1 2351 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */ 2352 for(i = 0; i < txb->nr_frags; i++) { 2353#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE 2354 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) || 2355#else 2356 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) || 2357#endif 2358 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\ 2359 (ieee->queue_stop)) { 2360 /* insert the skb packet to the wait queue */ 2361 /* as for the completion function, it does not need 2362 * to check it any more. 2363 * */ 2364 //printk("error:no descriptor left@queue_index %d\n", queue_index); 2365 //ieee80211_stop_queue(ieee); 2366#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE 2367 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]); 2368#else 2369 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]); 2370#endif 2371 }else{ 2372 ieee->softmac_data_hard_start_xmit( 2373 txb->fragments[i], 2374 ieee->dev,ieee->rate); 2375 //ieee->stats.tx_packets++; 2376 //ieee->stats.tx_bytes += txb->fragments[i]->len; 2377 //ieee->dev->trans_start = jiffies; 2378 } 2379 } 2380#endif 2381 ieee80211_txb_free(txb); 2382 2383//exit: 2384 spin_unlock_irqrestore(&ieee->lock,flags); 2385 2386} 2387 2388/* called with ieee->lock acquired */ 2389void ieee80211_resume_tx(struct ieee80211_device *ieee) 2390{ 2391 int i; 2392 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) { 2393 2394 if (ieee->queue_stop){ 2395 ieee->tx_pending.frag = i; 2396 return; 2397 }else{ 2398 2399 ieee->softmac_data_hard_start_xmit( 2400 ieee->tx_pending.txb->fragments[i], 2401 ieee->dev,ieee->rate); 2402 //(i+1)<ieee->tx_pending.txb->nr_frags); 2403 ieee->stats.tx_packets++; 2404 ieee->dev->trans_start = jiffies; 2405 } 2406 } 2407 2408 2409 ieee80211_txb_free(ieee->tx_pending.txb); 2410 ieee->tx_pending.txb = NULL; 2411} 2412 2413 2414void ieee80211_reset_queue(struct ieee80211_device *ieee) 2415{ 2416 unsigned long flags; 2417 2418 spin_lock_irqsave(&ieee->lock,flags); 2419 init_mgmt_queue(ieee); 2420 if (ieee->tx_pending.txb){ 2421 ieee80211_txb_free(ieee->tx_pending.txb); 2422 ieee->tx_pending.txb = NULL; 2423 } 2424 ieee->queue_stop = 0; 2425 spin_unlock_irqrestore(&ieee->lock,flags); 2426 2427} 2428 2429void ieee80211_wake_queue(struct ieee80211_device *ieee) 2430{ 2431 2432 unsigned long flags; 2433 struct sk_buff *skb; 2434 struct ieee80211_hdr_3addr *header; 2435 2436 spin_lock_irqsave(&ieee->lock,flags); 2437 if (! ieee->queue_stop) goto exit; 2438 2439 ieee->queue_stop = 0; 2440 2441 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){ 2442 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){ 2443 2444 header = (struct ieee80211_hdr_3addr *) skb->data; 2445 2446 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); 2447 2448 if (ieee->seq_ctrl[0] == 0xFFF) 2449 ieee->seq_ctrl[0] = 0; 2450 else 2451 ieee->seq_ctrl[0]++; 2452 2453 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate); 2454 //dev_kfree_skb_any(skb);//edit by thomas 2455 } 2456 } 2457 if (!ieee->queue_stop && ieee->tx_pending.txb) 2458 ieee80211_resume_tx(ieee); 2459 2460 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){ 2461 ieee->softmac_stats.swtxawake++; 2462 netif_wake_queue(ieee->dev); 2463 } 2464 2465exit : 2466 spin_unlock_irqrestore(&ieee->lock,flags); 2467} 2468 2469 2470void ieee80211_stop_queue(struct ieee80211_device *ieee) 2471{ 2472 //unsigned long flags; 2473 //spin_lock_irqsave(&ieee->lock,flags); 2474 2475 if (! netif_queue_stopped(ieee->dev)){ 2476 netif_stop_queue(ieee->dev); 2477 ieee->softmac_stats.swtxstop++; 2478 } 2479 ieee->queue_stop = 1; 2480 //spin_unlock_irqrestore(&ieee->lock,flags); 2481 2482} 2483 2484 2485inline void ieee80211_randomize_cell(struct ieee80211_device *ieee) 2486{ 2487 2488 get_random_bytes(ieee->current_network.bssid, ETH_ALEN); 2489 2490 /* an IBSS cell address must have the two less significant 2491 * bits of the first byte = 2 2492 */ 2493 ieee->current_network.bssid[0] &= ~0x01; 2494 ieee->current_network.bssid[0] |= 0x02; 2495} 2496 2497/* called in user context only */ 2498void ieee80211_start_master_bss(struct ieee80211_device *ieee) 2499{ 2500 ieee->assoc_id = 1; 2501 2502 if (ieee->current_network.ssid_len == 0){ 2503 strncpy(ieee->current_network.ssid, 2504 IEEE80211_DEFAULT_TX_ESSID, 2505 IW_ESSID_MAX_SIZE); 2506 2507 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); 2508 ieee->ssid_set = 1; 2509 } 2510 2511 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN); 2512 2513 ieee->set_chan(ieee->dev, ieee->current_network.channel); 2514 ieee->state = IEEE80211_LINKED; 2515 ieee->link_change(ieee->dev); 2516 notify_wx_assoc_event(ieee); 2517 2518 if (ieee->data_hard_resume) 2519 ieee->data_hard_resume(ieee->dev); 2520 2521 netif_carrier_on(ieee->dev); 2522} 2523 2524void ieee80211_start_monitor_mode(struct ieee80211_device *ieee) 2525{ 2526 if(ieee->raw_tx){ 2527 2528 if (ieee->data_hard_resume) 2529 ieee->data_hard_resume(ieee->dev); 2530 2531 netif_carrier_on(ieee->dev); 2532 } 2533} 2534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) 2535void ieee80211_start_ibss_wq(struct work_struct *work) 2536{ 2537 2538 struct delayed_work *dwork = container_of(work, struct delayed_work, work); 2539 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq); 2540#else 2541void ieee80211_start_ibss_wq(struct ieee80211_device *ieee) 2542{ 2543#endif 2544 /* iwconfig mode ad-hoc will schedule this and return 2545 * on the other hand this will block further iwconfig SET 2546 * operations because of the wx_sem hold. 2547 * Anyway some most set operations set a flag to speed-up 2548 * (abort) this wq (when syncro scanning) before sleeping 2549 * on the semaphore 2550 */ 2551 if(!ieee->proto_started){ 2552 printk("==========oh driver down return\n"); 2553 return; 2554 } 2555 down(&ieee->wx_sem); 2556 2557 if (ieee->current_network.ssid_len == 0){ 2558 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID); 2559 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID); 2560 ieee->ssid_set = 1; 2561 } 2562 2563 /* check if we have this cell in our network list */ 2564 ieee80211_softmac_check_all_nets(ieee); 2565 2566 2567#ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d. 2568// if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK)) 2569 if (ieee->state == IEEE80211_NOLINK) 2570 ieee->current_network.channel = 6; 2571#endif 2572 /* if not then the state is not linked. Maybe the user swithced to 2573 * ad-hoc mode just after being in monitor mode, or just after 2574 * being very few time in managed mode (so the card have had no 2575 * time to scan all the chans..) or we have just run up the iface 2576 * after setting ad-hoc mode. So we have to give another try.. 2577 * Here, in ibss mode, should be safe to do this without extra care 2578 * (in bss mode we had to make sure no-one tryed to associate when 2579 * we had just checked the ieee->state and we was going to start the 2580 * scan) beacause in ibss mode the ieee80211_new_net function, when 2581 * finds a good net, just set the ieee->state to IEEE80211_LINKED, 2582 * so, at worst, we waste a bit of time to initiate an unneeded syncro 2583 * scan, that will stop at the first round because it sees the state 2584 * associated. 2585 */ 2586 if (ieee->state == IEEE80211_NOLINK) 2587 ieee80211_start_scan_syncro(ieee); 2588 2589 /* the network definitively is not here.. create a new cell */ 2590 if (ieee->state == IEEE80211_NOLINK){ 2591 printk("creating new IBSS cell\n"); 2592 if(!ieee->wap_set) 2593 ieee80211_randomize_cell(ieee); 2594 2595 if(ieee->modulation & IEEE80211_CCK_MODULATION){ 2596 2597 ieee->current_network.rates_len = 4; 2598 2599 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; 2600 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; 2601 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; 2602 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; 2603 2604 }else 2605 ieee->current_network.rates_len = 0; 2606 2607 if(ieee->modulation & IEEE80211_OFDM_MODULATION){ 2608 ieee->current_network.rates_ex_len = 8; 2609 2610 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB; 2611 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB; 2612 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB; 2613 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB; 2614 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB; 2615 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB; 2616 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB; 2617 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB; 2618 2619 ieee->rate = 108; 2620 }else{ 2621 ieee->current_network.rates_ex_len = 0; 2622 ieee->rate = 22; 2623 } 2624 2625 // By default, WMM function will be disabled in IBSS mode 2626 ieee->current_network.QoS_Enable = 0; 2627 ieee->SetWirelessMode(ieee->dev, IEEE_G); 2628 ieee->current_network.atim_window = 0; 2629 ieee->current_network.capability = WLAN_CAPABILITY_IBSS; 2630 if(ieee->short_slot) 2631 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT; 2632 2633 } 2634 2635 ieee->state = IEEE80211_LINKED; 2636 2637 ieee->set_chan(ieee->dev, ieee->current_network.channel); 2638 ieee->link_change(ieee->dev); 2639 2640 notify_wx_assoc_event(ieee); 2641 2642 ieee80211_start_send_beacons(ieee); 2643 2644 if (ieee->data_hard_resume) 2645 ieee->data_hard_resume(ieee->dev); 2646 netif_carrier_on(ieee->dev); 2647 2648 up(&ieee->wx_sem); 2649} 2650 2651inline void ieee80211_start_ibss(struct ieee80211_device *ieee) 2652{ 2653#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2654 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150); 2655#else 2656 schedule_task(&ieee->start_ibss_wq); 2657#endif 2658} 2659 2660/* this is called only in user context, with wx_sem held */ 2661void ieee80211_start_bss(struct ieee80211_device *ieee) 2662{ 2663 unsigned long flags; 2664#ifdef ENABLE_DOT11D 2665 // 2666 // Ref: 802.11d 11.1.3.3 2667 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE. 2668 // 2669 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) 2670 { 2671 if(! ieee->bGlobalDomain) 2672 { 2673 return; 2674 } 2675 } 2676#endif 2677 /* check if we have already found the net we 2678 * are interested in (if any). 2679 * if not (we are disassociated and we are not 2680 * in associating / authenticating phase) start the background scanning. 2681 */ 2682 ieee80211_softmac_check_all_nets(ieee); 2683 2684 /* ensure no-one start an associating process (thus setting 2685 * the ieee->state to ieee80211_ASSOCIATING) while we 2686 * have just cheked it and we are going to enable scan. 2687 * The ieee80211_new_net function is always called with 2688 * lock held (from both ieee80211_softmac_check_all_nets and 2689 * the rx path), so we cannot be in the middle of such function 2690 */ 2691 spin_lock_irqsave(&ieee->lock, flags); 2692 2693 if (ieee->state == IEEE80211_NOLINK){ 2694 ieee->actscanning = true; 2695 ieee80211_start_scan(ieee); 2696 } 2697 spin_unlock_irqrestore(&ieee->lock, flags); 2698} 2699 2700/* called only in userspace context */ 2701void ieee80211_disassociate(struct ieee80211_device *ieee) 2702{ 2703 2704 2705 netif_carrier_off(ieee->dev); 2706 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE) 2707 ieee80211_reset_queue(ieee); 2708 2709 if (ieee->data_hard_stop) 2710 ieee->data_hard_stop(ieee->dev); 2711#ifdef ENABLE_DOT11D 2712 if(IS_DOT11D_ENABLE(ieee)) 2713 Dot11d_Reset(ieee); 2714#endif 2715 ieee->state = IEEE80211_NOLINK; 2716 ieee->is_set_key = false; 2717 ieee->link_change(ieee->dev); 2718 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT); 2719 notify_wx_assoc_event(ieee); 2720 2721} 2722#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)) 2723void ieee80211_associate_retry_wq(struct work_struct *work) 2724{ 2725 struct delayed_work *dwork = container_of(work, struct delayed_work, work); 2726 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq); 2727#else 2728void ieee80211_associate_retry_wq(struct ieee80211_device *ieee) 2729{ 2730#endif 2731 unsigned long flags; 2732 2733 down(&ieee->wx_sem); 2734 if(!ieee->proto_started) 2735 goto exit; 2736 2737 if(ieee->state != IEEE80211_ASSOCIATING_RETRY) 2738 goto exit; 2739 2740 /* until we do not set the state to IEEE80211_NOLINK 2741 * there are no possibility to have someone else trying 2742 * to start an association procdure (we get here with 2743 * ieee->state = IEEE80211_ASSOCIATING). 2744 * When we set the state to IEEE80211_NOLINK it is possible 2745 * that the RX path run an attempt to associate, but 2746 * both ieee80211_softmac_check_all_nets and the 2747 * RX path works with ieee->lock held so there are no 2748 * problems. If we are still disassociated then start a scan. 2749 * the lock here is necessary to ensure no one try to start 2750 * an association procedure when we have just checked the 2751 * state and we are going to start the scan. 2752 */ 2753 ieee->state = IEEE80211_NOLINK; 2754 2755 ieee80211_softmac_check_all_nets(ieee); 2756 2757 spin_lock_irqsave(&ieee->lock, flags); 2758 2759 if(ieee->state == IEEE80211_NOLINK) 2760 ieee80211_start_scan(ieee); 2761 2762 spin_unlock_irqrestore(&ieee->lock, flags); 2763 2764exit: 2765 up(&ieee->wx_sem); 2766} 2767 2768struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee) 2769{ 2770 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff}; 2771 2772 struct sk_buff *skb; 2773 struct ieee80211_probe_response *b; 2774 2775 skb = ieee80211_probe_resp(ieee, broadcast_addr); 2776 2777 if (!skb) 2778 return NULL; 2779 2780 b = (struct ieee80211_probe_response *) skb->data; 2781 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON); 2782 2783 return skb; 2784 2785} 2786 2787struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee) 2788{ 2789 struct sk_buff *skb; 2790 struct ieee80211_probe_response *b; 2791 2792 skb = ieee80211_get_beacon_(ieee); 2793 if(!skb) 2794 return NULL; 2795 2796 b = (struct ieee80211_probe_response *) skb->data; 2797 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4); 2798 2799 if (ieee->seq_ctrl[0] == 0xFFF) 2800 ieee->seq_ctrl[0] = 0; 2801 else 2802 ieee->seq_ctrl[0]++; 2803 2804 return skb; 2805} 2806 2807void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee) 2808{ 2809 ieee->sync_scan_hurryup = 1; 2810 down(&ieee->wx_sem); 2811 ieee80211_stop_protocol(ieee); 2812 up(&ieee->wx_sem); 2813} 2814 2815 2816void ieee80211_stop_protocol(struct ieee80211_device *ieee) 2817{ 2818 if (!ieee->proto_started) 2819 return; 2820 2821 ieee->proto_started = 0; 2822 2823 ieee80211_stop_send_beacons(ieee); 2824 del_timer_sync(&ieee->associate_timer); 2825#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2826 cancel_delayed_work(&ieee->associate_retry_wq); 2827 cancel_delayed_work(&ieee->start_ibss_wq); 2828#endif 2829 ieee80211_stop_scan(ieee); 2830 2831 ieee80211_disassociate(ieee); 2832 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS 2833} 2834 2835void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee) 2836{ 2837 ieee->sync_scan_hurryup = 0; 2838 down(&ieee->wx_sem); 2839 ieee80211_start_protocol(ieee); 2840 up(&ieee->wx_sem); 2841} 2842 2843void ieee80211_start_protocol(struct ieee80211_device *ieee) 2844{ 2845 short ch = 0; 2846 int i = 0; 2847 if (ieee->proto_started) 2848 return; 2849 2850 ieee->proto_started = 1; 2851 2852 if (ieee->current_network.channel == 0){ 2853 do{ 2854 ch++; 2855 if (ch > MAX_CHANNEL_NUMBER) 2856 return; /* no channel found */ 2857#ifdef ENABLE_DOT11D 2858 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]); 2859#else 2860 }while(!ieee->channel_map[ch]); 2861#endif 2862 ieee->current_network.channel = ch; 2863 } 2864 2865 if (ieee->current_network.beacon_interval == 0) 2866 ieee->current_network.beacon_interval = 100; 2867// printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel); 2868// ieee->set_chan(ieee->dev,ieee->current_network.channel); 2869 2870 for(i = 0; i < 17; i++) { 2871 ieee->last_rxseq_num[i] = -1; 2872 ieee->last_rxfrag_num[i] = -1; 2873 ieee->last_packet_time[i] = 0; 2874 } 2875 2876 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers. 2877 2878 2879 /* if the user set the MAC of the ad-hoc cell and then 2880 * switch to managed mode, shall we make sure that association 2881 * attempts does not fail just because the user provide the essid 2882 * and the nic is still checking for the AP MAC ?? 2883 */ 2884 if (ieee->iw_mode == IW_MODE_INFRA) 2885 ieee80211_start_bss(ieee); 2886 2887 else if (ieee->iw_mode == IW_MODE_ADHOC) 2888 ieee80211_start_ibss(ieee); 2889 2890 else if (ieee->iw_mode == IW_MODE_MASTER) 2891 ieee80211_start_master_bss(ieee); 2892 2893 else if(ieee->iw_mode == IW_MODE_MONITOR) 2894 ieee80211_start_monitor_mode(ieee); 2895} 2896 2897 2898#define DRV_NAME "Ieee80211" 2899void ieee80211_softmac_init(struct ieee80211_device *ieee) 2900{ 2901 int i; 2902 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network)); 2903 2904 ieee->state = IEEE80211_NOLINK; 2905 ieee->sync_scan_hurryup = 0; 2906 for(i = 0; i < 5; i++) { 2907 ieee->seq_ctrl[i] = 0; 2908 } 2909#ifdef ENABLE_DOT11D 2910 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC); 2911 if (!ieee->pDot11dInfo) 2912 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n"); 2913 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO)); 2914#endif 2915 //added for AP roaming 2916 ieee->LinkDetectInfo.SlotNum = 2; 2917 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0; 2918 ieee->LinkDetectInfo.NumRecvDataInPeriod=0; 2919 2920 ieee->assoc_id = 0; 2921 ieee->queue_stop = 0; 2922 ieee->scanning = 0; 2923 ieee->softmac_features = 0; //so IEEE2100-like driver are happy 2924 ieee->wap_set = 0; 2925 ieee->ssid_set = 0; 2926 ieee->proto_started = 0; 2927 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE; 2928 ieee->rate = 22; 2929 ieee->ps = IEEE80211_PS_DISABLED; 2930 ieee->sta_sleep = 0; 2931 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7 2932 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15 2933 ieee->Regdot11HTOperationalRateSet[4]= 0x01; 2934 //added by amy 2935 ieee->actscanning = false; 2936 ieee->beinretry = false; 2937 ieee->is_set_key = false; 2938 init_mgmt_queue(ieee); 2939 2940 ieee->sta_edca_param[0] = 0x0000A403; 2941 ieee->sta_edca_param[1] = 0x0000A427; 2942 ieee->sta_edca_param[2] = 0x005E4342; 2943 ieee->sta_edca_param[3] = 0x002F3262; 2944 ieee->aggregation = true; 2945 ieee->enable_rx_imm_BA = 1; 2946#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) 2947 init_timer(&ieee->scan_timer); 2948 ieee->scan_timer.data = (unsigned long)ieee; 2949 ieee->scan_timer.function = ieee80211_softmac_scan_cb; 2950#endif 2951 ieee->tx_pending.txb = NULL; 2952 2953 init_timer(&ieee->associate_timer); 2954 ieee->associate_timer.data = (unsigned long)ieee; 2955 ieee->associate_timer.function = ieee80211_associate_abort_cb; 2956 2957 init_timer(&ieee->beacon_timer); 2958 ieee->beacon_timer.data = (unsigned long) ieee; 2959 ieee->beacon_timer.function = ieee80211_send_beacon_cb; 2960 2961#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2962#ifdef PF_SYNCTHREAD 2963 ieee->wq = create_workqueue(DRV_NAME,0); 2964#else 2965 ieee->wq = create_workqueue(DRV_NAME); 2966#endif 2967#endif 2968 2969#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 2970#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) 2971 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq); 2972 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq); 2973 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq); 2974 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq); 2975 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq); 2976 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq); 2977 2978#else 2979 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee); 2980 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee); 2981 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee); 2982 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee); 2983 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee); 2984 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee); 2985#endif 2986 2987#else 2988 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee); 2989 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee); 2990 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee); 2991 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee); 2992 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee); 2993 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee); 2994#endif 2995 sema_init(&ieee->wx_sem, 1); 2996 sema_init(&ieee->scan_sem, 1); 2997 2998 spin_lock_init(&ieee->mgmt_tx_lock); 2999 spin_lock_init(&ieee->beacon_lock); 3000 3001 tasklet_init(&ieee->ps_task, 3002 (void(*)(unsigned long)) ieee80211_sta_ps, 3003 (unsigned long)ieee); 3004 3005} 3006 3007void ieee80211_softmac_free(struct ieee80211_device *ieee) 3008{ 3009 down(&ieee->wx_sem); 3010#ifdef ENABLE_DOT11D 3011 if(NULL != ieee->pDot11dInfo) 3012 { 3013 kfree(ieee->pDot11dInfo); 3014 ieee->pDot11dInfo = NULL; 3015 } 3016#endif 3017 del_timer_sync(&ieee->associate_timer); 3018 3019#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0) 3020 cancel_delayed_work(&ieee->associate_retry_wq); 3021 destroy_workqueue(ieee->wq); 3022#endif 3023 3024 up(&ieee->wx_sem); 3025} 3026 3027/******************************************************** 3028 * Start of WPA code. * 3029 * this is stolen from the ipw2200 driver * 3030 ********************************************************/ 3031 3032 3033static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value) 3034{ 3035 /* This is called when wpa_supplicant loads and closes the driver 3036 * interface. */ 3037 printk("%s WPA\n",value ? "enabling" : "disabling"); 3038 ieee->wpa_enabled = value; 3039 return 0; 3040} 3041 3042 3043void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len) 3044{ 3045 /* make sure WPA is enabled */ 3046 ieee80211_wpa_enable(ieee, 1); 3047 3048 ieee80211_disassociate(ieee); 3049} 3050 3051 3052static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason) 3053{ 3054 3055 int ret = 0; 3056 3057 switch (command) { 3058 case IEEE_MLME_STA_DEAUTH: 3059 // silently ignore 3060 break; 3061 3062 case IEEE_MLME_STA_DISASSOC: 3063 ieee80211_disassociate(ieee); 3064 break; 3065 3066 default: 3067 printk("Unknown MLME request: %d\n", command); 3068 ret = -EOPNOTSUPP; 3069 } 3070 3071 return ret; 3072} 3073 3074 3075static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee, 3076 struct ieee_param *param, int plen) 3077{ 3078 u8 *buf; 3079 3080 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN || 3081 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL)) 3082 return -EINVAL; 3083 3084 if (param->u.wpa_ie.len) { 3085 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL); 3086 if (buf == NULL) 3087 return -ENOMEM; 3088 3089 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len); 3090 kfree(ieee->wpa_ie); 3091 ieee->wpa_ie = buf; 3092 ieee->wpa_ie_len = param->u.wpa_ie.len; 3093 } else { 3094 kfree(ieee->wpa_ie); 3095 ieee->wpa_ie = NULL; 3096 ieee->wpa_ie_len = 0; 3097 } 3098 3099 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len); 3100 return 0; 3101} 3102 3103#define AUTH_ALG_OPEN_SYSTEM 0x1 3104#define AUTH_ALG_SHARED_KEY 0x2 3105 3106static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value) 3107{ 3108 3109 struct ieee80211_security sec = { 3110 .flags = SEC_AUTH_MODE, 3111 }; 3112 int ret = 0; 3113 3114 if (value & AUTH_ALG_SHARED_KEY) { 3115 sec.auth_mode = WLAN_AUTH_SHARED_KEY; 3116 ieee->open_wep = 0; 3117 ieee->auth_mode = 1; 3118 } else if (value & AUTH_ALG_OPEN_SYSTEM){ 3119 sec.auth_mode = WLAN_AUTH_OPEN; 3120 ieee->open_wep = 1; 3121 ieee->auth_mode = 0; 3122 } 3123 else if (value & IW_AUTH_ALG_LEAP){ 3124 sec.auth_mode = WLAN_AUTH_LEAP; 3125 ieee->open_wep = 1; 3126 ieee->auth_mode = 2; 3127 } 3128 3129 3130 if (ieee->set_security) 3131 ieee->set_security(ieee->dev, &sec); 3132 //else 3133 // ret = -EOPNOTSUPP; 3134 3135 return ret; 3136} 3137 3138static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value) 3139{ 3140 int ret=0; 3141 unsigned long flags; 3142 3143 switch (name) { 3144 case IEEE_PARAM_WPA_ENABLED: 3145 ret = ieee80211_wpa_enable(ieee, value); 3146 break; 3147 3148 case IEEE_PARAM_TKIP_COUNTERMEASURES: 3149 ieee->tkip_countermeasures=value; 3150 break; 3151 3152 case IEEE_PARAM_DROP_UNENCRYPTED: { 3153 /* HACK: 3154 * 3155 * wpa_supplicant calls set_wpa_enabled when the driver 3156 * is loaded and unloaded, regardless of if WPA is being 3157 * used. No other calls are made which can be used to 3158 * determine if encryption will be used or not prior to 3159 * association being expected. If encryption is not being 3160 * used, drop_unencrypted is set to false, else true -- we 3161 * can use this to determine if the CAP_PRIVACY_ON bit should 3162 * be set. 3163 */ 3164 struct ieee80211_security sec = { 3165 .flags = SEC_ENABLED, 3166 .enabled = value, 3167 }; 3168 ieee->drop_unencrypted = value; 3169 /* We only change SEC_LEVEL for open mode. Others 3170 * are set by ipw_wpa_set_encryption. 3171 */ 3172 if (!value) { 3173 sec.flags |= SEC_LEVEL; 3174 sec.level = SEC_LEVEL_0; 3175 } 3176 else { 3177 sec.flags |= SEC_LEVEL; 3178 sec.level = SEC_LEVEL_1; 3179 } 3180 if (ieee->set_security) 3181 ieee->set_security(ieee->dev, &sec); 3182 break; 3183 } 3184 3185 case IEEE_PARAM_PRIVACY_INVOKED: 3186 ieee->privacy_invoked=value; 3187 break; 3188 3189 case IEEE_PARAM_AUTH_ALGS: 3190 ret = ieee80211_wpa_set_auth_algs(ieee, value); 3191 break; 3192 3193 case IEEE_PARAM_IEEE_802_1X: 3194 ieee->ieee802_1x=value; 3195 break; 3196 case IEEE_PARAM_WPAX_SELECT: 3197 // added for WPA2 mixed mode 3198 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags); 3199 ieee->wpax_type_set = 1; 3200 ieee->wpax_type_notify = value; 3201 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags); 3202 break; 3203 3204 default: 3205 printk("Unknown WPA param: %d\n",name); 3206 ret = -EOPNOTSUPP; 3207 } 3208 3209 return ret; 3210} 3211 3212/* implementation borrowed from hostap driver */ 3213 3214static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee, 3215 struct ieee_param *param, int param_len) 3216{ 3217 int ret = 0; 3218 3219 struct ieee80211_crypto_ops *ops; 3220 struct ieee80211_crypt_data **crypt; 3221 3222 struct ieee80211_security sec = { 3223 .flags = 0, 3224 }; 3225 3226 param->u.crypt.err = 0; 3227 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0'; 3228 3229 if (param_len != 3230 (int) ((char *) param->u.crypt.key - (char *) param) + 3231 param->u.crypt.key_len) { 3232 printk("Len mismatch %d, %d\n", param_len, 3233 param->u.crypt.key_len); 3234 return -EINVAL; 3235 } 3236 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && 3237 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && 3238 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { 3239 if (param->u.crypt.idx >= WEP_KEYS) 3240 return -EINVAL; 3241 crypt = &ieee->crypt[param->u.crypt.idx]; 3242 } else { 3243 return -EINVAL; 3244 } 3245 3246 if (strcmp(param->u.crypt.alg, "none") == 0) { 3247 if (crypt) { 3248 sec.enabled = 0; 3249 // FIXME FIXME 3250 //sec.encrypt = 0; 3251 sec.level = SEC_LEVEL_0; 3252 sec.flags |= SEC_ENABLED | SEC_LEVEL; 3253 ieee80211_crypt_delayed_deinit(ieee, crypt); 3254 } 3255 goto done; 3256 } 3257 sec.enabled = 1; 3258// FIXME FIXME 3259// sec.encrypt = 1; 3260 sec.flags |= SEC_ENABLED; 3261 3262 /* IPW HW cannot build TKIP MIC, host decryption still needed. */ 3263 if (!(ieee->host_encrypt || ieee->host_decrypt) && 3264 strcmp(param->u.crypt.alg, "TKIP")) 3265 goto skip_host_crypt; 3266 3267 ops = ieee80211_get_crypto_ops(param->u.crypt.alg); 3268 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { 3269 request_module("ieee80211_crypt_wep"); 3270 ops = ieee80211_get_crypto_ops(param->u.crypt.alg); 3271 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place 3272 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { 3273 request_module("ieee80211_crypt_tkip"); 3274 ops = ieee80211_get_crypto_ops(param->u.crypt.alg); 3275 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { 3276 request_module("ieee80211_crypt_ccmp"); 3277 ops = ieee80211_get_crypto_ops(param->u.crypt.alg); 3278 } 3279 if (ops == NULL) { 3280 printk("unknown crypto alg '%s'\n", param->u.crypt.alg); 3281 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG; 3282 ret = -EINVAL; 3283 goto done; 3284 } 3285 3286 if (*crypt == NULL || (*crypt)->ops != ops) { 3287 struct ieee80211_crypt_data *new_crypt; 3288 3289 ieee80211_crypt_delayed_deinit(ieee, crypt); 3290 3291 new_crypt = (struct ieee80211_crypt_data *) 3292 kmalloc(sizeof(*new_crypt), GFP_KERNEL); 3293 if (new_crypt == NULL) { 3294 ret = -ENOMEM; 3295 goto done; 3296 } 3297 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data)); 3298 new_crypt->ops = ops; 3299#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) 3300 if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) 3301#else 3302 if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner)) 3303#endif 3304 new_crypt->priv = 3305 new_crypt->ops->init(param->u.crypt.idx); 3306 3307 if (new_crypt->priv == NULL) { 3308 kfree(new_crypt); 3309 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED; 3310 ret = -EINVAL; 3311 goto done; 3312 } 3313 3314 *crypt = new_crypt; 3315 } 3316 3317 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key && 3318 (*crypt)->ops->set_key(param->u.crypt.key, 3319 param->u.crypt.key_len, param->u.crypt.seq, 3320 (*crypt)->priv) < 0) { 3321 printk("key setting failed\n"); 3322 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED; 3323 ret = -EINVAL; 3324 goto done; 3325 } 3326 3327 skip_host_crypt: 3328 if (param->u.crypt.set_tx) { 3329 ieee->tx_keyidx = param->u.crypt.idx; 3330 sec.active_key = param->u.crypt.idx; 3331 sec.flags |= SEC_ACTIVE_KEY; 3332 } else 3333 sec.flags &= ~SEC_ACTIVE_KEY; 3334 3335 if (param->u.crypt.alg != NULL) { 3336 memcpy(sec.keys[param->u.crypt.idx], 3337 param->u.crypt.key, 3338 param->u.crypt.key_len); 3339 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len; 3340 sec.flags |= (1 << param->u.crypt.idx); 3341 3342 if (strcmp(param->u.crypt.alg, "WEP") == 0) { 3343 sec.flags |= SEC_LEVEL; 3344 sec.level = SEC_LEVEL_1; 3345 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) { 3346 sec.flags |= SEC_LEVEL; 3347 sec.level = SEC_LEVEL_2; 3348 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) { 3349 sec.flags |= SEC_LEVEL; 3350 sec.level = SEC_LEVEL_3; 3351 } 3352 } 3353 done: 3354 if (ieee->set_security) 3355 ieee->set_security(ieee->dev, &sec); 3356 3357 /* Do not reset port if card is in Managed mode since resetting will 3358 * generate new IEEE 802.11 authentication which may end up in looping 3359 * with IEEE 802.1X. If your hardware requires a reset after WEP 3360 * configuration (for example... Prism2), implement the reset_port in 3361 * the callbacks structures used to initialize the 802.11 stack. */ 3362 if (ieee->reset_on_keychange && 3363 ieee->iw_mode != IW_MODE_INFRA && 3364 ieee->reset_port && 3365 ieee->reset_port(ieee->dev)) { 3366 printk("reset_port failed\n"); 3367 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED; 3368 return -EINVAL; 3369 } 3370 3371 return ret; 3372} 3373 3374inline struct sk_buff *ieee80211_disassociate_skb( 3375 struct ieee80211_network *beacon, 3376 struct ieee80211_device *ieee, 3377 u8 asRsn) 3378{ 3379 struct sk_buff *skb; 3380 struct ieee80211_disassoc *disass; 3381 3382 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc)); 3383 if (!skb) 3384 return NULL; 3385 3386 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc)); 3387 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC); 3388 disass->header.duration_id = 0; 3389 3390 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN); 3391 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN); 3392 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN); 3393 3394 disass->reason = asRsn; 3395 return skb; 3396} 3397 3398 3399void 3400SendDisassociation( 3401 struct ieee80211_device *ieee, 3402 u8* asSta, 3403 u8 asRsn 3404) 3405{ 3406 struct ieee80211_network *beacon = &ieee->current_network; 3407 struct sk_buff *skb; 3408 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn); 3409 if (skb){ 3410 softmac_mgmt_xmit(skb, ieee); 3411 //dev_kfree_skb_any(skb);//edit by thomas 3412 } 3413} 3414 3415int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p) 3416{ 3417 struct ieee_param *param; 3418 int ret=0; 3419 3420 down(&ieee->wx_sem); 3421 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length); 3422 3423 if (p->length < sizeof(struct ieee_param) || !p->pointer){ 3424 ret = -EINVAL; 3425 goto out; 3426 } 3427 3428 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL); 3429 if (param == NULL){ 3430 ret = -ENOMEM; 3431 goto out; 3432 } 3433 if (copy_from_user(param, p->pointer, p->length)) { 3434 kfree(param); 3435 ret = -EFAULT; 3436 goto out; 3437 } 3438 3439 switch (param->cmd) { 3440 3441 case IEEE_CMD_SET_WPA_PARAM: 3442 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name, 3443 param->u.wpa_param.value); 3444 break; 3445 3446 case IEEE_CMD_SET_WPA_IE: 3447 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length); 3448 break; 3449 3450 case IEEE_CMD_SET_ENCRYPTION: 3451 ret = ieee80211_wpa_set_encryption(ieee, param, p->length); 3452 break; 3453 3454 case IEEE_CMD_MLME: 3455 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command, 3456 param->u.mlme.reason_code); 3457 break; 3458 3459 default: 3460 printk("Unknown WPA supplicant request: %d\n",param->cmd); 3461 ret = -EOPNOTSUPP; 3462 break; 3463 } 3464 3465 if (ret == 0 && copy_to_user(p->pointer, param, p->length)) 3466 ret = -EFAULT; 3467 3468 kfree(param); 3469out: 3470 up(&ieee->wx_sem); 3471 3472 return ret; 3473} 3474 3475void notify_wx_assoc_event(struct ieee80211_device *ieee) 3476{ 3477 union iwreq_data wrqu; 3478 wrqu.ap_addr.sa_family = ARPHRD_ETHER; 3479 if (ieee->state == IEEE80211_LINKED) 3480 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN); 3481 else 3482 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); 3483 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL); 3484} 3485 3486#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)) 3487EXPORT_SYMBOL(ieee80211_get_beacon); 3488EXPORT_SYMBOL(ieee80211_wake_queue); 3489EXPORT_SYMBOL(ieee80211_stop_queue); 3490EXPORT_SYMBOL(ieee80211_reset_queue); 3491EXPORT_SYMBOL(ieee80211_softmac_stop_protocol); 3492EXPORT_SYMBOL(ieee80211_softmac_start_protocol); 3493EXPORT_SYMBOL(ieee80211_is_shortslot); 3494EXPORT_SYMBOL(ieee80211_is_54g); 3495EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl); 3496EXPORT_SYMBOL(ieee80211_ps_tx_ack); 3497EXPORT_SYMBOL(ieee80211_softmac_xmit); 3498EXPORT_SYMBOL(ieee80211_stop_send_beacons); 3499EXPORT_SYMBOL(notify_wx_assoc_event); 3500EXPORT_SYMBOL(SendDisassociation); 3501EXPORT_SYMBOL(ieee80211_disassociate); 3502EXPORT_SYMBOL(ieee80211_start_send_beacons); 3503EXPORT_SYMBOL(ieee80211_stop_scan); 3504EXPORT_SYMBOL(ieee80211_send_probe_requests); 3505EXPORT_SYMBOL(ieee80211_softmac_scan_syncro); 3506EXPORT_SYMBOL(ieee80211_start_scan_syncro); 3507#else 3508EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon); 3509EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue); 3510EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue); 3511EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue); 3512EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol); 3513EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol); 3514EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot); 3515EXPORT_SYMBOL_NOVERS(ieee80211_is_54g); 3516EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl); 3517EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack); 3518EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit); 3519EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons); 3520EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event); 3521EXPORT_SYMBOL_NOVERS(SendDisassociation); 3522EXPORT_SYMBOL_NOVERS(ieee80211_disassociate); 3523EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons); 3524EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan); 3525EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests); 3526EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro); 3527EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro); 3528#endif 3529//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); 3530