1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
13 * released under the GPL
17 #include "ieee80211.h"
19 #include <linux/random.h>
20 #include <linux/delay.h>
21 #include <linux/version.h>
22 #include <asm/uaccess.h>
27 u8 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
36 short ieee80211_is_54g(struct ieee80211_network net)
38 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
41 short ieee80211_is_shortslot(struct ieee80211_network net)
43 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
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
50 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
52 unsigned int rate_len = 0;
54 if (ieee->modulation & IEEE80211_CCK_MODULATION)
55 rate_len = IEEE80211_CCK_RATE_LEN + 2;
57 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
59 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
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.
68 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
72 if (ieee->modulation & IEEE80211_CCK_MODULATION){
73 *tag++ = MFIE_TYPE_RATES;
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;
81 /* We may add an option for custom rates that specific HW might support */
85 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
89 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
91 *tag++ = MFIE_TYPE_RATES_EX;
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;
104 /* We may add an option for custom rates that specific HW might support */
109 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
112 *tag++ = MFIE_TYPE_GENERIC; //0
121 if(ieee->current_network.wmm_info & 0x80) {
122 *tag++ = 0x0f|MAX_SP_Len;
133 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
136 *tag++ = MFIE_TYPE_GENERIC; //0
147 printk(KERN_ALERT "This is enable turbo mode IE process\n");
151 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
154 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
157 * if the queue is full but we have newer frames then
158 * just overwrites the oldest.
160 * if (nh == ieee->mgmt_queue_tail)
163 ieee->mgmt_queue_head = nh;
164 ieee->mgmt_queue_ring[nh] = skb;
169 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
173 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
176 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
178 ieee->mgmt_queue_tail =
179 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
184 void init_mgmt_queue(struct ieee80211_device *ieee)
186 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
189 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
191 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
194 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
195 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
198 rate = ieee->basic_rate & 0x7f;
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))
211 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
212 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
214 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
224 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
226 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
229 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
230 struct ieee80211_hdr_3addr *header=
231 (struct ieee80211_hdr_3addr *) skb->data;
233 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
234 spin_lock_irqsave(&ieee->lock, flags);
236 /* called with 2nd param 0, no mgmt lock required */
237 ieee80211_sta_wakeup(ieee,0);
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;
246 if(ieee->queue_stop){
247 enqueue_mgmt(ieee,skb);
249 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
251 if (ieee->seq_ctrl[0] == 0xFFF)
252 ieee->seq_ctrl[0] = 0;
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
262 spin_unlock_irqrestore(&ieee->lock, flags);
264 spin_unlock_irqrestore(&ieee->lock, flags);
265 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
267 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
269 if (ieee->seq_ctrl[0] == 0xFFF)
270 ieee->seq_ctrl[0] = 0;
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.
282 //printk("%s():insert to waitqueue!\n",__FUNCTION__);
283 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
285 //printk("TX packet!\n");
286 ieee->softmac_hard_start_xmit(skb,ieee->dev);
287 //dev_kfree_skb_any(skb);//edit by thomas
289 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
293 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
296 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
297 struct ieee80211_hdr_3addr *header =
298 (struct ieee80211_hdr_3addr *) skb->data;
299 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
301 tcb_desc->queue_index = MGNT_QUEUE;
302 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
303 tcb_desc->RATRIndex = 7;
304 tcb_desc->bTxDisableRateFallBack = 1;
305 tcb_desc->bTxUseDriverAssingedRate = 1;
306 //printk("=============>%s()\n", __FUNCTION__);
309 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
311 if (ieee->seq_ctrl[0] == 0xFFF)
312 ieee->seq_ctrl[0] = 0;
316 /* avoid watchdog triggers */
317 // ieee->dev->trans_start = jiffies;
318 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
322 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
324 if (ieee->seq_ctrl[0] == 0xFFF)
325 ieee->seq_ctrl[0] = 0;
329 ieee->softmac_hard_start_xmit(skb,ieee->dev);
332 //dev_kfree_skb_any(skb);//edit by thomas
335 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
337 unsigned int len,rate_len;
340 struct ieee80211_probe_request *req;
342 len = ieee->current_network.ssid_len;
344 rate_len = ieee80211_MFIE_rate_len(ieee);
346 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
347 2 + len + rate_len + ieee->tx_headroom);
351 skb_reserve(skb, ieee->tx_headroom);
353 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
354 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
355 req->header.duration_id = 0; //FIXME: is this OK ?
357 memset(req->header.addr1, 0xff, ETH_ALEN);
358 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
359 memset(req->header.addr3, 0xff, ETH_ALEN);
361 tag = (u8 *) skb_put(skb,len+2+rate_len);
363 *tag++ = MFIE_TYPE_SSID;
365 memcpy(tag, ieee->current_network.ssid, len);
368 ieee80211_MFIE_Brate(ieee,&tag);
369 ieee80211_MFIE_Grate(ieee,&tag);
373 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
374 void ieee80211_send_beacon(struct ieee80211_device *ieee)
379 //unsigned long flags;
380 skb = ieee80211_get_beacon_(ieee);
383 softmac_mgmt_xmit(skb, ieee);
384 ieee->softmac_stats.tx_beacons++;
385 //dev_kfree_skb_any(skb);//edit by thomas
387 // ieee->beacon_timer.expires = jiffies +
388 // (MSECS( ieee->current_network.beacon_interval -5));
390 //spin_lock_irqsave(&ieee->beacon_lock,flags);
391 if(ieee->beacon_txing && ieee->ieee_up){
392 // if(!timer_pending(&ieee->beacon_timer))
393 // add_timer(&ieee->beacon_timer);
394 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
396 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
400 void ieee80211_send_beacon_cb(unsigned long _ieee)
402 struct ieee80211_device *ieee =
403 (struct ieee80211_device *) _ieee;
406 spin_lock_irqsave(&ieee->beacon_lock, flags);
407 ieee80211_send_beacon(ieee);
408 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
412 void ieee80211_send_probe(struct ieee80211_device *ieee)
416 skb = ieee80211_probe_req(ieee);
418 softmac_mgmt_xmit(skb, ieee);
419 ieee->softmac_stats.tx_probe_rq++;
420 //dev_kfree_skb_any(skb);//edit by thomas
424 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
426 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
427 ieee80211_send_probe(ieee);
428 ieee80211_send_probe(ieee);
432 /* this performs syncro scan blocking the caller until all channels
433 * in the allowed channel map has been checked.
435 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
439 u8 channel_map[MAX_CHANNEL_NUMBER+1];
440 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
442 down(&ieee->scan_sem);
449 if (ch > MAX_CHANNEL_NUMBER)
450 goto out; /* scan completed */
452 }while(!channel_map[ch]);
454 }while(!ieee->channel_map[ch]);
457 /* this fuction can be called in two situations
458 * 1- We have switched to ad-hoc mode and we are
459 * performing a complete syncro scan before conclude
460 * there are no interesting cell and to create a
461 * new one. In this case the link state is
462 * IEEE80211_NOLINK until we found an interesting cell.
463 * If so the ieee8021_new_net, called by the RX path
464 * will set the state to IEEE80211_LINKED, so we stop
466 * 2- We are linked and the root uses run iwlist scan.
467 * So we switch to IEEE80211_LINKED_SCANNING to remember
468 * that we are still logically linked (not interested in
469 * new network events, despite for updating the net list,
470 * but we are temporarly 'unlinked' as the driver shall
471 * not filter RX frames and the channel is changing.
472 * So the only situation in witch are interested is to check
473 * if the state become LINKED because of the #1 situation
476 if (ieee->state == IEEE80211_LINKED)
478 ieee->set_chan(ieee->dev, ch);
480 if(channel_map[ch] == 1)
482 ieee80211_send_probe_requests(ieee);
484 /* this prevent excessive time wait when we
485 * need to wait for a syncro scan to end..
487 if(ieee->state < IEEE80211_LINKED)
490 if (ieee->sync_scan_hurryup)
494 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
498 if(ieee->state < IEEE80211_LINKED){
499 ieee->actscanning = false;
503 ieee->sync_scan_hurryup = 0;
505 if(IS_DOT11D_ENABLE(ieee))
506 DOT11D_ScanComplete(ieee);
512 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
513 /* called both by wq with ieee->lock held */
514 void ieee80211_softmac_scan(struct ieee80211_device *ieee)
519 ieee->current_network.channel =
520 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
521 if (watchdog++ > MAX_CHANNEL_NUMBER)
522 return; /* no good chans */
524 }while(!ieee->channel_map[ieee->current_network.channel]);
527 schedule_task(&ieee->softmac_scan_wq);
531 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
532 void ieee80211_softmac_scan_wq(struct work_struct *work)
534 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
535 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
537 void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee)
540 static short watchdog = 0;
541 u8 last_channel = ieee->current_network.channel;
543 u8 channel_map[MAX_CHANNEL_NUMBER+1];
544 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
548 down(&ieee->scan_sem);
550 ieee->current_network.channel =
551 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
552 if (watchdog++ > MAX_CHANNEL_NUMBER)
554 //if current channel is not in channel map, set to default channel.
556 if (!channel_map[ieee->current_network.channel]);
558 if (!ieee->channel_map[ieee->current_network.channel]);
560 ieee->current_network.channel = 6;
561 goto out; /* no good chans */
564 }while(!channel_map[ieee->current_network.channel]);
566 }while(!ieee->channel_map[ieee->current_network.channel]);
568 if (ieee->scanning == 0 )
570 ieee->set_chan(ieee->dev, ieee->current_network.channel);
572 if(channel_map[ieee->current_network.channel] == 1)
574 ieee80211_send_probe_requests(ieee);
577 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
578 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
580 //ieee->scan_timer.expires = jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME);
581 if (ieee->scanning == 1)
582 mod_timer(&ieee->scan_timer,(jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME)));
589 if(IS_DOT11D_ENABLE(ieee))
590 DOT11D_ScanComplete(ieee);
592 ieee->current_network.channel = last_channel;
593 ieee->actscanning = false;
599 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
600 void ieee80211_softmac_scan_cb(unsigned long _dev)
603 struct ieee80211_device *ieee = (struct ieee80211_device *)_dev;
605 spin_lock_irqsave(&ieee->lock, flags);
606 ieee80211_softmac_scan(ieee);
607 spin_unlock_irqrestore(&ieee->lock, flags);
612 void ieee80211_beacons_start(struct ieee80211_device *ieee)
615 spin_lock_irqsave(&ieee->beacon_lock,flags);
617 ieee->beacon_txing = 1;
618 ieee80211_send_beacon(ieee);
620 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
623 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
627 spin_lock_irqsave(&ieee->beacon_lock,flags);
629 ieee->beacon_txing = 0;
630 del_timer_sync(&ieee->beacon_timer);
632 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
637 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
639 if(ieee->stop_send_beacons)
640 ieee->stop_send_beacons(ieee->dev);
641 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
642 ieee80211_beacons_stop(ieee);
646 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
648 if(ieee->start_send_beacons)
649 ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
650 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
651 ieee80211_beacons_start(ieee);
655 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
657 // unsigned long flags;
659 //ieee->sync_scan_hurryup = 1;
661 down(&ieee->scan_sem);
662 // spin_lock_irqsave(&ieee->lock, flags);
664 if (ieee->scanning == 1){
667 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
668 cancel_delayed_work(&ieee->softmac_scan_wq);
670 del_timer_sync(&ieee->scan_timer);
674 // spin_unlock_irqrestore(&ieee->lock, flags);
678 void ieee80211_stop_scan(struct ieee80211_device *ieee)
680 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
681 ieee80211_softmac_stop_scan(ieee);
683 ieee->stop_scan(ieee->dev);
686 /* called with ieee->lock held */
687 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
690 if(IS_DOT11D_ENABLE(ieee) )
692 if(IS_COUNTRY_IE_VALID(ieee))
694 RESET_CIE_WATCHDOG(ieee);
698 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
699 if (ieee->scanning == 0){
701 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
702 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
703 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
706 queue_work(ieee->wq, &ieee->softmac_scan_wq);
709 ieee80211_softmac_scan(ieee);
713 ieee->start_scan(ieee->dev);
717 /* called with wx_sem held */
718 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
721 if(IS_DOT11D_ENABLE(ieee) )
723 if(IS_COUNTRY_IE_VALID(ieee))
725 RESET_CIE_WATCHDOG(ieee);
729 ieee->sync_scan_hurryup = 0;
730 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
731 ieee80211_softmac_scan_syncro(ieee);
733 ieee->scan_syncro(ieee->dev);
737 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
738 struct ieee80211_device *ieee, int challengelen)
741 struct ieee80211_authentication *auth;
742 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
745 skb = dev_alloc_skb(len);
746 if (!skb) return NULL;
748 skb_reserve(skb, ieee->tx_headroom);
749 auth = (struct ieee80211_authentication *)
750 skb_put(skb, sizeof(struct ieee80211_authentication));
752 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
753 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
755 auth->header.duration_id = 0x013a; //FIXME
757 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
758 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
759 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
761 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
762 if(ieee->auth_mode == 0)
763 auth->algorithm = WLAN_AUTH_OPEN;
764 else if(ieee->auth_mode == 1)
765 auth->algorithm = WLAN_AUTH_SHARED_KEY;
766 else if(ieee->auth_mode == 2)
767 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
768 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
769 auth->transaction = cpu_to_le16(ieee->associate_seq);
770 ieee->associate_seq++;
772 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
779 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
783 struct ieee80211_probe_response *beacon_buf;
784 struct sk_buff *skb = NULL;
786 int atim_len,erp_len;
787 struct ieee80211_crypt_data* crypt;
789 char *ssid = ieee->current_network.ssid;
790 int ssid_len = ieee->current_network.ssid_len;
791 int rate_len = ieee->current_network.rates_len+2;
792 int rate_ex_len = ieee->current_network.rates_ex_len;
793 int wpa_ie_len = ieee->wpa_ie_len;
794 u8 erpinfo_content = 0;
799 u8 tmp_ht_info_len=0;
800 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
801 u8* tmp_generic_ie_buf=NULL;
802 u8 tmp_generic_ie_len=0;
804 if(rate_ex_len > 0) rate_ex_len+=2;
806 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
812 if(ieee80211_is_54g(ieee->current_network))
817 if((ieee->current_network.mode == IEEE_G)
818 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
821 if(ieee->current_network.buseprotection)
822 erpinfo_content |= ERP_UseProtection;
829 crypt = ieee->crypt[ieee->tx_keyidx];
832 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
833 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
836 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
837 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
838 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
839 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
840 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
841 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
844 if(pHTInfo->bRegRT2RTAggregation)
846 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
847 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
848 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
850 // 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);
852 beacon_size = sizeof(struct ieee80211_probe_response)+2+
862 // +tmp_generic_ie_len
865 skb = dev_alloc_skb(beacon_size);
868 skb_reserve(skb, ieee->tx_headroom);
869 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
870 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
871 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
872 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
874 beacon_buf->header.duration_id = 0; //FIXME
875 beacon_buf->beacon_interval =
876 cpu_to_le16(ieee->current_network.beacon_interval);
877 beacon_buf->capability =
878 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
879 beacon_buf->capability |=
880 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
882 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
883 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
885 crypt = ieee->crypt[ieee->tx_keyidx];
887 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
888 (0 == strcmp(crypt->ops->name, "WEP"));
891 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
894 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
895 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
896 beacon_buf->info_element[0].len = ssid_len;
898 tag = (u8*) beacon_buf->info_element[0].data;
900 memcpy(tag, ssid, ssid_len);
904 *(tag++) = MFIE_TYPE_RATES;
905 *(tag++) = rate_len-2;
906 memcpy(tag,ieee->current_network.rates,rate_len-2);
909 *(tag++) = MFIE_TYPE_DS_SET;
911 *(tag++) = ieee->current_network.channel;
915 *(tag++) = MFIE_TYPE_IBSS_SET;
917 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
918 val16 = cpu_to_le16(ieee->current_network.atim_window);
919 memcpy((u8 *)tag, (u8 *)&val16, 2);
924 *(tag++) = MFIE_TYPE_ERP;
926 *(tag++) = erpinfo_content;
929 //Include High Throuput capability
931 *(tag++) = MFIE_TYPE_HT_CAP;
932 *(tag++) = tmp_ht_cap_len - 2;
933 memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
934 tag += tmp_ht_cap_len - 2;
937 *(tag++) = MFIE_TYPE_RATES_EX;
938 *(tag++) = rate_ex_len-2;
939 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
944 //Include High Throuput info
946 *(tag++) = MFIE_TYPE_HT_INFO;
947 *(tag++) = tmp_ht_info_len - 2;
948 memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
949 tag += tmp_ht_info_len - 2;
953 if (ieee->iw_mode == IW_MODE_ADHOC)
954 {//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
955 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
957 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
963 // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
965 if(pHTInfo->bRegRT2RTAggregation)
968 (*tag++) = tmp_generic_ie_len - 2;
969 memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
970 tag += tmp_generic_ie_len -2;
975 if(ieee->qos_support)
979 memcpy(tag,QosOui,wmm_len);
983 //skb->dev = ieee->dev;
988 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
993 struct ieee80211_crypt_data* crypt;
994 struct ieee80211_assoc_response_frame *assoc;
997 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
998 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
1000 skb = dev_alloc_skb(len);
1005 skb_reserve(skb, ieee->tx_headroom);
1007 assoc = (struct ieee80211_assoc_response_frame *)
1008 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
1010 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
1011 memcpy(assoc->header.addr1, dest,ETH_ALEN);
1012 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1013 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1014 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
1015 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
1018 if(ieee->short_slot)
1019 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1021 if (ieee->host_encrypt)
1022 crypt = ieee->crypt[ieee->tx_keyidx];
1025 encrypt = ( crypt && crypt->ops);
1028 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1031 assoc->aid = cpu_to_le16(ieee->assoc_id);
1032 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
1033 else ieee->assoc_id++;
1035 tag = (u8*) skb_put(skb, rate_len);
1037 ieee80211_MFIE_Brate(ieee, &tag);
1038 ieee80211_MFIE_Grate(ieee, &tag);
1043 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
1045 struct sk_buff *skb;
1046 struct ieee80211_authentication *auth;
1047 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
1049 skb = dev_alloc_skb(len);
1054 skb->len = sizeof(struct ieee80211_authentication);
1056 auth = (struct ieee80211_authentication *)skb->data;
1058 auth->status = cpu_to_le16(status);
1059 auth->transaction = cpu_to_le16(2);
1060 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
1062 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1063 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1064 memcpy(auth->header.addr1, dest, ETH_ALEN);
1065 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
1071 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
1073 struct sk_buff *skb;
1074 struct ieee80211_hdr_3addr* hdr;
1076 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1081 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1083 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1084 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1085 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1087 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
1088 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1089 (pwr ? IEEE80211_FCTL_PM:0));
1097 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1099 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1102 softmac_mgmt_xmit(buf, ieee);
1106 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1108 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1111 softmac_mgmt_xmit(buf, ieee);
1115 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1119 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1121 softmac_mgmt_xmit(buf, ieee);
1125 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1127 struct sk_buff *skb;
1128 //unsigned long flags;
1130 struct ieee80211_assoc_request_frame *hdr;
1132 //short info_addr = 0;
1134 //u16 suite_count = 0;
1135 //u8 suit_select = 0;
1136 //unsigned int wpa_len = beacon->wpa_ie_len;
1138 u8* ht_cap_buf = NULL;
1140 u8* realtek_ie_buf=NULL;
1141 u8 realtek_ie_len=0;
1142 int wpa_ie_len= ieee->wpa_ie_len;
1143 unsigned int ckip_ie_len=0;
1144 unsigned int ccxrm_ie_len=0;
1145 unsigned int cxvernum_ie_len=0;
1146 struct ieee80211_crypt_data* crypt;
1149 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1150 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1152 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1157 crypt = ieee->crypt[ieee->tx_keyidx];
1158 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1160 //Include High Throuput capability && Realtek proprietary
1161 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1163 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1164 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1165 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1166 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1168 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1169 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1170 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1174 if(ieee->qos_support){
1175 wmm_info_len = beacon->qos_data.supported?9:0;
1179 if(beacon->bCkipSupported)
1183 if(beacon->bCcxRmEnable)
1187 if( beacon->BssCcxVerNumber >= 2 )
1189 cxvernum_ie_len = 5+2;
1192 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1193 + beacon->ssid_len//essid tagged val
1194 + rate_len//rates tagged val
1203 + ieee->tx_headroom;
1205 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1206 + beacon->ssid_len//essid tagged val
1207 + rate_len//rates tagged val
1215 + ieee->tx_headroom;
1218 skb = dev_alloc_skb(len);
1223 skb_reserve(skb, ieee->tx_headroom);
1225 hdr = (struct ieee80211_assoc_request_frame *)
1226 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1229 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1230 hdr->header.duration_id= 37; //FIXME
1231 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1232 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1233 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1235 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1237 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1238 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1239 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1241 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1242 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1244 if(ieee->short_slot)
1245 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1246 if (wmm_info_len) //QOS
1247 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1249 hdr->listen_interval = 0xa; //FIXME
1251 hdr->info_element[0].id = MFIE_TYPE_SSID;
1253 hdr->info_element[0].len = beacon->ssid_len;
1254 tag = skb_put(skb, beacon->ssid_len);
1255 memcpy(tag, beacon->ssid, beacon->ssid_len);
1257 tag = skb_put(skb, rate_len);
1259 ieee80211_MFIE_Brate(ieee, &tag);
1260 ieee80211_MFIE_Grate(ieee, &tag);
1261 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1262 if( beacon->bCkipSupported )
1264 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1265 u8 CcxAironetBuf[30];
1266 OCTET_STRING osCcxAironetIE;
1268 memset(CcxAironetBuf, 0,30);
1269 osCcxAironetIE.Octet = CcxAironetBuf;
1270 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1272 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1273 // We want to make the device type as "4500-client". 060926, by CCW.
1275 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1277 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1278 // "The CKIP negotiation is started with the associate request from the client to the access point,
1279 // containing an Aironet element with both the MIC and KP bits set."
1280 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1281 tag = skb_put(skb, ckip_ie_len);
1282 *tag++ = MFIE_TYPE_AIRONET;
1283 *tag++ = osCcxAironetIE.Length;
1284 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1285 tag += osCcxAironetIE.Length;
1288 if(beacon->bCcxRmEnable)
1290 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1291 OCTET_STRING osCcxRmCap;
1293 osCcxRmCap.Octet = CcxRmCapBuf;
1294 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1295 tag = skb_put(skb,ccxrm_ie_len);
1296 *tag++ = MFIE_TYPE_GENERIC;
1297 *tag++ = osCcxRmCap.Length;
1298 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1299 tag += osCcxRmCap.Length;
1302 if( beacon->BssCcxVerNumber >= 2 )
1304 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1305 OCTET_STRING osCcxVerNum;
1306 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1307 osCcxVerNum.Octet = CcxVerNumBuf;
1308 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1309 tag = skb_put(skb,cxvernum_ie_len);
1310 *tag++ = MFIE_TYPE_GENERIC;
1311 *tag++ = osCcxVerNum.Length;
1312 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1313 tag += osCcxVerNum.Length;
1316 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1317 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1319 tag = skb_put(skb, ht_cap_len);
1320 *tag++ = MFIE_TYPE_HT_CAP;
1321 *tag++ = ht_cap_len - 2;
1322 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1323 tag += ht_cap_len -2;
1328 //choose what wpa_supplicant gives to associate.
1329 tag = skb_put(skb, wpa_ie_len);
1331 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1334 tag = skb_put(skb,wmm_info_len);
1336 ieee80211_WMM_Info(ieee, &tag);
1339 tag = skb_put(skb,turbo_info_len);
1340 if(turbo_info_len) {
1341 ieee80211_TURBO_Info(ieee, &tag);
1345 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1346 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1348 tag = skb_put(skb, ht_cap_len);
1349 *tag++ = MFIE_TYPE_GENERIC;
1350 *tag++ = ht_cap_len - 2;
1351 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1352 tag += ht_cap_len -2;
1355 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1356 tag = skb_put(skb, realtek_ie_len);
1357 *tag++ = MFIE_TYPE_GENERIC;
1358 *tag++ = realtek_ie_len - 2;
1359 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1362 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1363 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1367 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1370 unsigned long flags;
1371 spin_lock_irqsave(&ieee->lock, flags);
1373 ieee->associate_seq++;
1375 /* don't scan, and avoid to have the RX path possibily
1376 * try again to associate. Even do not react to AUTH or
1377 * ASSOC response. Just wait for the retry wq to be scheduled.
1378 * Here we will check if there are good nets to associate
1379 * with, so we retry or just get back to NO_LINK and scanning
1381 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1382 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1383 ieee->softmac_stats.no_auth_rs++;
1385 IEEE80211_DEBUG_MGMT("Association failed\n");
1386 ieee->softmac_stats.no_ass_rs++;
1389 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1391 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1392 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1393 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1395 schedule_task(&ieee->associate_retry_wq);
1398 spin_unlock_irqrestore(&ieee->lock, flags);
1401 void ieee80211_associate_abort_cb(unsigned long dev)
1403 ieee80211_associate_abort((struct ieee80211_device *) dev);
1407 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1409 struct ieee80211_network *beacon = &ieee->current_network;
1410 struct sk_buff *skb;
1412 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1414 ieee->softmac_stats.tx_auth_rq++;
1415 skb=ieee80211_authentication_req(beacon, ieee, 0);
1418 ieee80211_associate_abort(ieee);
1420 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1421 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1422 //printk(KERN_WARNING "Sending authentication request\n");
1423 softmac_mgmt_xmit(skb, ieee);
1424 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1425 if(!timer_pending(&ieee->associate_timer)){
1426 ieee->associate_timer.expires = jiffies + (HZ / 2);
1427 add_timer(&ieee->associate_timer);
1429 //dev_kfree_skb_any(skb);//edit by thomas
1433 void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1436 struct sk_buff *skb;
1437 struct ieee80211_network *beacon = &ieee->current_network;
1438 // int hlen = sizeof(struct ieee80211_authentication);
1440 ieee->associate_seq++;
1441 ieee->softmac_stats.tx_auth_rq++;
1443 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1445 ieee80211_associate_abort(ieee);
1447 c = skb_put(skb, chlen+2);
1448 *(c++) = MFIE_TYPE_CHALLENGE;
1450 memcpy(c, challenge, chlen);
1452 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1454 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1456 softmac_mgmt_xmit(skb, ieee);
1457 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1459 ieee->associate_timer.expires = jiffies + (HZ / 2);
1460 add_timer(&ieee->associate_timer);
1462 //dev_kfree_skb_any(skb);//edit by thomas
1467 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1469 struct sk_buff* skb;
1470 struct ieee80211_network *beacon = &ieee->current_network;
1472 del_timer_sync(&ieee->associate_timer);
1474 IEEE80211_DEBUG_MGMT("Sending association request\n");
1476 ieee->softmac_stats.tx_ass_rq++;
1477 skb=ieee80211_association_req(beacon, ieee);
1479 ieee80211_associate_abort(ieee);
1481 softmac_mgmt_xmit(skb, ieee);
1482 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1484 ieee->associate_timer.expires = jiffies + (HZ / 2);
1485 add_timer(&ieee->associate_timer);
1487 //dev_kfree_skb_any(skb);//edit by thomas
1490 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1491 void ieee80211_associate_complete_wq(struct work_struct *work)
1493 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1495 void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1498 printk(KERN_INFO "Associated successfully\n");
1499 ieee->is_roaming = false;
1500 if(ieee80211_is_54g(ieee->current_network) &&
1501 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1504 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1507 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1509 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1511 printk("Successfully associated, ht enabled\n");
1516 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1517 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1518 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1520 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1521 // To prevent the immediately calling watch_dog after association.
1522 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1524 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1525 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1527 ieee->link_change(ieee->dev);
1528 if(ieee->is_silent_reset == 0){
1529 printk("============>normal associate\n");
1530 notify_wx_assoc_event(ieee);
1532 else if(ieee->is_silent_reset == 1)
1534 printk("==================>silent reset associate\n");
1535 ieee->is_silent_reset = 0;
1538 if (ieee->data_hard_resume)
1539 ieee->data_hard_resume(ieee->dev);
1540 netif_carrier_on(ieee->dev);
1543 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1546 // struct net_device* dev = ieee->dev;
1547 del_timer_sync(&ieee->associate_timer);
1550 for(i = 0; i < 6; i++) {
1551 ieee->seq_ctrl[i] = 0;
1554 ieee->state = IEEE80211_LINKED;
1556 if (ieee->pHTInfo->bCurrentHTSupport)
1558 printk("Successfully associated, ht enabled\n");
1559 queue_work(ieee->wq, &ieee->ht_onAssRsp);
1563 printk("Successfully associated, ht not enabled\n");
1564 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1565 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1568 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1569 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1570 queue_work(ieee->wq, &ieee->associate_complete_wq);
1572 schedule_task(&ieee->associate_complete_wq);
1576 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1577 void ieee80211_associate_procedure_wq(struct work_struct *work)
1579 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1581 void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1584 ieee->sync_scan_hurryup = 1;
1585 down(&ieee->wx_sem);
1587 if (ieee->data_hard_stop)
1588 ieee->data_hard_stop(ieee->dev);
1590 ieee80211_stop_scan(ieee);
1591 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1592 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1593 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1595 ieee->associate_seq = 1;
1596 ieee80211_associate_step1(ieee);
1601 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1603 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1604 int tmp_ssid_len = 0;
1606 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1608 /* we are interested in new new only if we are not associated
1609 * and we are not associating / authenticating
1611 if (ieee->state != IEEE80211_NOLINK)
1614 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1617 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1621 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1622 /* if the user specified the AP MAC, we need also the essid
1623 * This could be obtained by beacons or, if the network does not
1624 * broadcast it, it can be put manually.
1626 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1627 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1628 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1629 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1630 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1631 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1634 if ( /* if the user set the AP check if match.
1635 * if the network does not broadcast essid we check the user supplyed ANY essid
1636 * if the network does broadcast and the user does not set essid it is OK
1637 * if the network does broadcast and the user did set essid chech if essid match
1639 ( apset && apmatch &&
1640 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1641 /* if the ap is not set, check that the user set the bssid
1642 * and the network does bradcast and that those two bssid matches
1644 (!apset && ssidset && ssidbroad && ssidmatch)
1646 /* if the essid is hidden replace it with the
1647 * essid provided by the user.
1650 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1651 tmp_ssid_len = ieee->current_network.ssid_len;
1653 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1656 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1657 ieee->current_network.ssid_len = tmp_ssid_len;
1659 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);
1661 //ieee->pHTInfo->IOTAction = 0;
1662 HTResetIOTSetting(ieee->pHTInfo);
1663 if (ieee->iw_mode == IW_MODE_INFRA){
1664 /* Join the network for the first time */
1665 ieee->AsocRetryCount = 0;
1666 //for HT by amy 080514
1667 if((ieee->current_network.qos_data.supported == 1) &&
1668 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1669 ieee->current_network.bssht.bdSupportHT)
1670 /*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.*/
1672 // ieee->pHTInfo->bCurrentHTSupport = true;
1673 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1677 ieee->pHTInfo->bCurrentHTSupport = false;
1680 ieee->state = IEEE80211_ASSOCIATING;
1681 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1682 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1684 schedule_task(&ieee->associate_procedure_wq);
1687 if(ieee80211_is_54g(ieee->current_network) &&
1688 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1690 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1691 printk(KERN_INFO"Using G rates\n");
1694 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1695 printk(KERN_INFO"Using B rates\n");
1697 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1698 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1699 ieee->state = IEEE80211_LINKED;
1707 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1709 unsigned long flags;
1710 struct ieee80211_network *target;
1712 spin_lock_irqsave(&ieee->lock, flags);
1714 list_for_each_entry(target, &ieee->network_list, list) {
1716 /* if the state become different that NOLINK means
1717 * we had found what we are searching for
1720 if (ieee->state != IEEE80211_NOLINK)
1723 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1724 ieee80211_softmac_new_net(ieee, target);
1727 spin_unlock_irqrestore(&ieee->lock, flags);
1732 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1734 struct ieee80211_authentication *a;
1736 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1737 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1741 a = (struct ieee80211_authentication*) skb->data;
1742 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1743 t = skb->data + sizeof(struct ieee80211_authentication);
1745 if(*(t++) == MFIE_TYPE_CHALLENGE){
1747 *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1748 memcpy(*challenge, t, *chlen);
1752 return cpu_to_le16(a->status);
1757 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1759 struct ieee80211_authentication *a;
1761 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1762 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1765 a = (struct ieee80211_authentication*) skb->data;
1767 memcpy(dest,a->header.addr2, ETH_ALEN);
1769 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1770 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1772 return WLAN_STATUS_SUCCESS;
1775 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1782 struct ieee80211_hdr_3addr *header =
1783 (struct ieee80211_hdr_3addr *) skb->data;
1785 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1786 return -1; /* corrupted */
1788 memcpy(src,header->addr2, ETH_ALEN);
1790 skbend = (u8*)skb->data + skb->len;
1792 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1794 while (tag+1 < skbend){
1800 tag++; /* point to the len field */
1801 tag = tag + *(tag); /* point to the last data byte of the tag */
1802 tag++; /* point to the next tag */
1805 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1806 if (ssidlen == 0) return 1;
1808 if (!ssid) return 1; /* ssid not found in tagged param */
1809 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1813 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1815 struct ieee80211_assoc_request_frame *a;
1817 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1818 sizeof(struct ieee80211_info_element))) {
1820 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1824 a = (struct ieee80211_assoc_request_frame*) skb->data;
1826 memcpy(dest,a->header.addr2,ETH_ALEN);
1831 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1833 struct ieee80211_assoc_response_frame *response_head;
1836 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1837 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1841 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1842 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1844 status_code = le16_to_cpu(response_head->status);
1845 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1846 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1847 ((ieee->mode == IEEE_G) &&
1848 (ieee->current_network.mode == IEEE_N_24G) &&
1849 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1850 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1852 ieee->AsocRetryCount = 0;
1855 return le16_to_cpu(response_head->status);
1859 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1863 //IEEE80211DMESG("Rx probe");
1864 ieee->softmac_stats.rx_probe_rq++;
1865 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1866 if (probe_rq_parse(ieee, skb, dest)){
1867 //IEEE80211DMESG("Was for me!");
1868 ieee->softmac_stats.tx_probe_rs++;
1869 ieee80211_resp_to_probe(ieee, dest);
1874 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1878 //IEEE80211DMESG("Rx probe");
1879 ieee->softmac_stats.rx_auth_rq++;
1881 if ((status = auth_rq_parse(skb, dest))!= -1){
1882 ieee80211_resp_to_auth(ieee, status, dest);
1884 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1889 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1893 //unsigned long flags;
1895 ieee->softmac_stats.rx_ass_rq++;
1896 if (assoc_rq_parse(skb,dest) != -1){
1897 ieee80211_resp_to_assoc_rq(ieee, dest);
1900 printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
1903 spin_lock_irqsave(&ieee->lock,flags);
1904 add_associate(ieee,dest);
1905 spin_unlock_irqrestore(&ieee->lock,flags);
1911 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1914 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1917 softmac_ps_mgmt_xmit(buf, ieee);
1922 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1924 int timeout = ieee->ps_timeout;
1926 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1927 ieee->iw_mode != IW_MODE_INFRA ||
1928 ieee->state != IEEE80211_LINKED)
1932 dtim = ieee->current_network.dtim_data;
1934 if(!(dtim & IEEE80211_DTIM_VALID))
1936 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1937 //printk("VALID\n");
1938 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1940 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1943 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1946 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1949 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1950 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1954 *time_l = ieee->current_network.last_dtim_sta_time[0]
1955 + (ieee->current_network.beacon_interval);
1956 // * ieee->current_network.dtim_period) * 1000;
1960 *time_h = ieee->current_network.last_dtim_sta_time[1];
1961 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1970 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1976 unsigned long flags,flags2;
1978 spin_lock_irqsave(&ieee->lock, flags);
1980 if((ieee->ps == IEEE80211_PS_DISABLED ||
1981 ieee->iw_mode != IW_MODE_INFRA ||
1982 ieee->state != IEEE80211_LINKED)){
1984 // #warning CHECK_LOCK_HERE
1985 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1987 ieee80211_sta_wakeup(ieee, 1);
1989 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1992 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1993 /* 2 wake, 1 sleep, 0 do nothing */
1999 if(ieee->sta_sleep == 1)
2000 ieee->enter_sleep_state(ieee->dev,th,tl);
2002 else if(ieee->sta_sleep == 0){
2003 // printk("send null 1\n");
2004 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2006 if(ieee->ps_is_queue_empty(ieee->dev)){
2009 ieee->sta_sleep = 2;
2011 ieee->ack_tx_to_ieee = 1;
2013 ieee80211_sta_ps_send_null_frame(ieee,1);
2018 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2023 }else if(sleep == 2){
2024 //#warning CHECK_LOCK_HERE
2025 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2027 ieee80211_sta_wakeup(ieee,1);
2029 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2033 spin_unlock_irqrestore(&ieee->lock, flags);
2037 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2039 if(ieee->sta_sleep == 0){
2041 printk("Warning: driver is probably failing to report TX ps error\n");
2042 ieee->ack_tx_to_ieee = 1;
2043 ieee80211_sta_ps_send_null_frame(ieee, 0);
2049 if(ieee->sta_sleep == 1)
2050 ieee->sta_wake_up(ieee->dev);
2052 ieee->sta_sleep = 0;
2055 ieee->ack_tx_to_ieee = 1;
2056 ieee80211_sta_ps_send_null_frame(ieee, 0);
2060 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2062 unsigned long flags,flags2;
2064 spin_lock_irqsave(&ieee->lock, flags);
2066 if(ieee->sta_sleep == 2){
2067 /* Null frame with PS bit set */
2069 ieee->sta_sleep = 1;
2070 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2072 /* if the card report not success we can't be sure the AP
2073 * has not RXed so we can't assume the AP believe us awake
2076 /* 21112005 - tx again null without PS bit if lost */
2079 if((ieee->sta_sleep == 0) && !success){
2080 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2081 ieee80211_sta_ps_send_null_frame(ieee, 0);
2082 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2085 spin_unlock_irqrestore(&ieee->lock, flags);
2087 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2089 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2090 u8* act = ieee80211_get_payload(header);
2092 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2095 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2103 if (*act == ACT_ADDBAREQ)
2104 ieee80211_rx_ADDBAReq(ieee, skb);
2105 else if (*act == ACT_ADDBARSP)
2106 ieee80211_rx_ADDBARsp(ieee, skb);
2107 else if (*act == ACT_DELBA)
2108 ieee80211_rx_DELBA(ieee, skb);
2111 // if (net_ratelimit())
2112 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2119 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2120 struct ieee80211_rx_stats *rx_stats, u16 type,
2123 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2128 struct ieee80211_assoc_response_frame *assoc_resp;
2129 // struct ieee80211_info_element *info_element;
2130 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2132 if(!ieee->proto_started)
2135 printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2136 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2137 ieee->iw_mode == IW_MODE_INFRA &&
2138 ieee->state == IEEE80211_LINKED))
2140 tasklet_schedule(&ieee->ps_task);
2142 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2143 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2144 ieee->last_rx_ps_time = jiffies;
2147 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2149 case IEEE80211_STYPE_ASSOC_RESP:
2150 case IEEE80211_STYPE_REASSOC_RESP:
2152 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2153 WLAN_FC_GET_STYPE(header->frame_ctl));
2154 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2155 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2156 ieee->iw_mode == IW_MODE_INFRA){
2157 struct ieee80211_network network_resp;
2158 struct ieee80211_network *network = &network_resp;
2160 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2161 ieee->state=IEEE80211_LINKED;
2162 ieee->assoc_id = aid;
2163 ieee->softmac_stats.rx_ass_ok++;
2164 /* station support qos */
2165 /* Let the register setting defaultly with Legacy station */
2166 if(ieee->qos_support) {
2167 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2168 memset(network, 0, sizeof(*network));
2169 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2170 rx_stats->len - sizeof(*assoc_resp),\
2175 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2176 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2177 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2179 if (ieee->handle_assoc_response != NULL)
2180 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2182 ieee80211_associate_complete(ieee);
2184 /* aid could not been allocated */
2185 ieee->softmac_stats.rx_ass_err++;
2187 "Association response status code 0x%x\n",
2189 IEEE80211_DEBUG_MGMT(
2190 "Association response status code 0x%x\n",
2192 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2193 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2194 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2196 schedule_task(&ieee->associate_procedure_wq);
2199 ieee80211_associate_abort(ieee);
2205 case IEEE80211_STYPE_ASSOC_REQ:
2206 case IEEE80211_STYPE_REASSOC_REQ:
2208 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2209 ieee->iw_mode == IW_MODE_MASTER)
2211 ieee80211_rx_assoc_rq(ieee, skb);
2214 case IEEE80211_STYPE_AUTH:
2216 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2217 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2218 ieee->iw_mode == IW_MODE_INFRA){
2220 IEEE80211_DEBUG_MGMT("Received authentication response");
2222 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2223 if(ieee->open_wep || !challenge){
2224 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2225 ieee->softmac_stats.rx_auth_rs_ok++;
2226 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2228 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2230 // WEP or TKIP encryption
2231 if(IsHTHalfNmodeAPs(ieee))
2233 bSupportNmode = true;
2234 bHalfSupportNmode = true;
2238 bSupportNmode = false;
2239 bHalfSupportNmode = false;
2241 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2244 /* Dummy wirless mode setting to avoid encryption issue */
2247 ieee->SetWirelessMode(ieee->dev, \
2248 ieee->current_network.mode);
2252 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2255 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2257 printk("===============>entern half N mode\n");
2258 ieee->bHalfWirelessN24GMode = true;
2261 ieee->bHalfWirelessN24GMode = false;
2263 ieee80211_associate_step2(ieee);
2265 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2268 ieee->softmac_stats.rx_auth_rs_err++;
2269 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2271 printk("Authentication respose status code 0x%x",errcode);
2272 ieee80211_associate_abort(ieee);
2275 }else if (ieee->iw_mode == IW_MODE_MASTER){
2276 ieee80211_rx_auth_rq(ieee, skb);
2281 case IEEE80211_STYPE_PROBE_REQ:
2283 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2284 ((ieee->iw_mode == IW_MODE_ADHOC ||
2285 ieee->iw_mode == IW_MODE_MASTER) &&
2286 ieee->state == IEEE80211_LINKED)){
2287 ieee80211_rx_probe_rq(ieee, skb);
2291 case IEEE80211_STYPE_DISASSOC:
2292 case IEEE80211_STYPE_DEAUTH:
2293 /* FIXME for now repeat all the association procedure
2294 * both for disassociation and deauthentication
2296 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2297 ieee->state == IEEE80211_LINKED &&
2298 ieee->iw_mode == IW_MODE_INFRA){
2300 ieee->state = IEEE80211_ASSOCIATING;
2301 ieee->softmac_stats.reassoc++;
2302 ieee->is_roaming = true;
2303 ieee80211_disassociate(ieee);
2304 // notify_wx_assoc_event(ieee);
2305 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2306 RemovePeerTS(ieee, header->addr2);
2307 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2308 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2310 schedule_task(&ieee->associate_procedure_wq);
2314 case IEEE80211_STYPE_MANAGE_ACT:
2315 ieee80211_process_action(ieee,skb);
2322 //dev_kfree_skb_any(skb);
2326 /* following are for a simplier TX queue management.
2327 * Instead of using netif_[stop/wake]_queue the driver
2328 * will uses these two function (plus a reset one), that
2329 * will internally uses the kernel netif_* and takes
2330 * care of the ieee802.11 fragmentation.
2331 * So the driver receives a fragment per time and might
2332 * call the stop function when it want without take care
2333 * to have enough room to TX an entire packet.
2334 * This might be useful if each fragment need it's own
2335 * descriptor, thus just keep a total free memory > than
2336 * the max fragmentation threshold is not enough.. If the
2337 * ieee802.11 stack passed a TXB struct then you needed
2338 * to keep N free descriptors where
2339 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2340 * In this way you need just one and the 802.11 stack
2341 * will take care of buffering fragments and pass them to
2342 * to the driver later, when it wakes the queue.
2344 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2347 unsigned int queue_index = txb->queue_index;
2348 unsigned long flags;
2350 cb_desc *tcb_desc = NULL;
2352 spin_lock_irqsave(&ieee->lock,flags);
2354 /* called with 2nd parm 0, no tx mgmt lock required */
2355 ieee80211_sta_wakeup(ieee,0);
2357 /* update the tx status */
2358 // ieee->stats.tx_bytes += txb->payload_size;
2359 // ieee->stats.tx_packets++;
2360 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2361 if(tcb_desc->bMulticast) {
2362 ieee->stats.multicast++;
2365 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2366 for(i = 0; i < txb->nr_frags; i++) {
2367 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2368 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2370 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2372 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2373 (ieee->queue_stop)) {
2374 /* insert the skb packet to the wait queue */
2375 /* as for the completion function, it does not need
2376 * to check it any more.
2378 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2379 //ieee80211_rtl_stop_queue(ieee);
2380 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2381 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2383 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2386 ieee->softmac_data_hard_start_xmit(
2388 ieee->dev,ieee->rate);
2389 //ieee->stats.tx_packets++;
2390 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2391 //ieee->dev->trans_start = jiffies;
2395 ieee80211_txb_free(txb);
2398 spin_unlock_irqrestore(&ieee->lock,flags);
2402 /* called with ieee->lock acquired */
2403 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2406 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2408 if (ieee->queue_stop){
2409 ieee->tx_pending.frag = i;
2413 ieee->softmac_data_hard_start_xmit(
2414 ieee->tx_pending.txb->fragments[i],
2415 ieee->dev,ieee->rate);
2416 //(i+1)<ieee->tx_pending.txb->nr_frags);
2417 ieee->stats.tx_packets++;
2418 // ieee->dev->trans_start = jiffies;
2423 ieee80211_txb_free(ieee->tx_pending.txb);
2424 ieee->tx_pending.txb = NULL;
2428 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2430 unsigned long flags;
2432 spin_lock_irqsave(&ieee->lock,flags);
2433 init_mgmt_queue(ieee);
2434 if (ieee->tx_pending.txb){
2435 ieee80211_txb_free(ieee->tx_pending.txb);
2436 ieee->tx_pending.txb = NULL;
2438 ieee->queue_stop = 0;
2439 spin_unlock_irqrestore(&ieee->lock,flags);
2443 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2446 unsigned long flags;
2447 struct sk_buff *skb;
2448 struct ieee80211_hdr_3addr *header;
2450 spin_lock_irqsave(&ieee->lock,flags);
2451 if (! ieee->queue_stop) goto exit;
2453 ieee->queue_stop = 0;
2455 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2456 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2458 header = (struct ieee80211_hdr_3addr *) skb->data;
2460 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2462 if (ieee->seq_ctrl[0] == 0xFFF)
2463 ieee->seq_ctrl[0] = 0;
2465 ieee->seq_ctrl[0]++;
2467 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2468 //dev_kfree_skb_any(skb);//edit by thomas
2471 if (!ieee->queue_stop && ieee->tx_pending.txb)
2472 ieee80211_resume_tx(ieee);
2474 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2475 ieee->softmac_stats.swtxawake++;
2476 netif_wake_queue(ieee->dev);
2480 spin_unlock_irqrestore(&ieee->lock,flags);
2484 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2486 //unsigned long flags;
2487 //spin_lock_irqsave(&ieee->lock,flags);
2489 if (! netif_queue_stopped(ieee->dev)){
2490 netif_stop_queue(ieee->dev);
2491 ieee->softmac_stats.swtxstop++;
2493 ieee->queue_stop = 1;
2494 //spin_unlock_irqrestore(&ieee->lock,flags);
2499 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2502 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2504 /* an IBSS cell address must have the two less significant
2505 * bits of the first byte = 2
2507 ieee->current_network.bssid[0] &= ~0x01;
2508 ieee->current_network.bssid[0] |= 0x02;
2511 /* called in user context only */
2512 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2516 if (ieee->current_network.ssid_len == 0){
2517 strncpy(ieee->current_network.ssid,
2518 IEEE80211_DEFAULT_TX_ESSID,
2521 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2525 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2527 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2528 ieee->state = IEEE80211_LINKED;
2529 ieee->link_change(ieee->dev);
2530 notify_wx_assoc_event(ieee);
2532 if (ieee->data_hard_resume)
2533 ieee->data_hard_resume(ieee->dev);
2535 netif_carrier_on(ieee->dev);
2538 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2542 if (ieee->data_hard_resume)
2543 ieee->data_hard_resume(ieee->dev);
2545 netif_carrier_on(ieee->dev);
2548 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2549 void ieee80211_start_ibss_wq(struct work_struct *work)
2552 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2553 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2555 void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2558 /* iwconfig mode ad-hoc will schedule this and return
2559 * on the other hand this will block further iwconfig SET
2560 * operations because of the wx_sem hold.
2561 * Anyway some most set operations set a flag to speed-up
2562 * (abort) this wq (when syncro scanning) before sleeping
2565 if(!ieee->proto_started){
2566 printk("==========oh driver down return\n");
2569 down(&ieee->wx_sem);
2571 if (ieee->current_network.ssid_len == 0){
2572 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2573 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2577 /* check if we have this cell in our network list */
2578 ieee80211_softmac_check_all_nets(ieee);
2581 #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.
2582 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2583 if (ieee->state == IEEE80211_NOLINK)
2584 ieee->current_network.channel = 6;
2586 /* if not then the state is not linked. Maybe the user swithced to
2587 * ad-hoc mode just after being in monitor mode, or just after
2588 * being very few time in managed mode (so the card have had no
2589 * time to scan all the chans..) or we have just run up the iface
2590 * after setting ad-hoc mode. So we have to give another try..
2591 * Here, in ibss mode, should be safe to do this without extra care
2592 * (in bss mode we had to make sure no-one tryed to associate when
2593 * we had just checked the ieee->state and we was going to start the
2594 * scan) beacause in ibss mode the ieee80211_new_net function, when
2595 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2596 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2597 * scan, that will stop at the first round because it sees the state
2600 if (ieee->state == IEEE80211_NOLINK)
2601 ieee80211_start_scan_syncro(ieee);
2603 /* the network definitively is not here.. create a new cell */
2604 if (ieee->state == IEEE80211_NOLINK){
2605 printk("creating new IBSS cell\n");
2607 ieee80211_randomize_cell(ieee);
2609 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2611 ieee->current_network.rates_len = 4;
2613 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2614 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2615 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2616 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2619 ieee->current_network.rates_len = 0;
2621 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2622 ieee->current_network.rates_ex_len = 8;
2624 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2625 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2626 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2627 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2628 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2629 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2630 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2631 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2635 ieee->current_network.rates_ex_len = 0;
2639 // By default, WMM function will be disabled in IBSS mode
2640 ieee->current_network.QoS_Enable = 0;
2641 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2642 ieee->current_network.atim_window = 0;
2643 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2644 if(ieee->short_slot)
2645 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2649 ieee->state = IEEE80211_LINKED;
2651 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2652 ieee->link_change(ieee->dev);
2654 notify_wx_assoc_event(ieee);
2656 ieee80211_start_send_beacons(ieee);
2658 if (ieee->data_hard_resume)
2659 ieee->data_hard_resume(ieee->dev);
2660 netif_carrier_on(ieee->dev);
2665 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2667 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2668 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2670 schedule_task(&ieee->start_ibss_wq);
2674 /* this is called only in user context, with wx_sem held */
2675 void ieee80211_start_bss(struct ieee80211_device *ieee)
2677 unsigned long flags;
2678 #ifdef ENABLE_DOT11D
2680 // Ref: 802.11d 11.1.3.3
2681 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2683 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2685 if(! ieee->bGlobalDomain)
2691 /* check if we have already found the net we
2692 * are interested in (if any).
2693 * if not (we are disassociated and we are not
2694 * in associating / authenticating phase) start the background scanning.
2696 ieee80211_softmac_check_all_nets(ieee);
2698 /* ensure no-one start an associating process (thus setting
2699 * the ieee->state to ieee80211_ASSOCIATING) while we
2700 * have just cheked it and we are going to enable scan.
2701 * The ieee80211_new_net function is always called with
2702 * lock held (from both ieee80211_softmac_check_all_nets and
2703 * the rx path), so we cannot be in the middle of such function
2705 spin_lock_irqsave(&ieee->lock, flags);
2707 if (ieee->state == IEEE80211_NOLINK){
2708 ieee->actscanning = true;
2709 ieee80211_rtl_start_scan(ieee);
2711 spin_unlock_irqrestore(&ieee->lock, flags);
2714 /* called only in userspace context */
2715 void ieee80211_disassociate(struct ieee80211_device *ieee)
2719 netif_carrier_off(ieee->dev);
2720 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2721 ieee80211_reset_queue(ieee);
2723 if (ieee->data_hard_stop)
2724 ieee->data_hard_stop(ieee->dev);
2725 #ifdef ENABLE_DOT11D
2726 if(IS_DOT11D_ENABLE(ieee))
2729 ieee->state = IEEE80211_NOLINK;
2730 ieee->is_set_key = false;
2731 ieee->link_change(ieee->dev);
2732 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2733 notify_wx_assoc_event(ieee);
2736 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2737 void ieee80211_associate_retry_wq(struct work_struct *work)
2739 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2740 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2742 void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2745 unsigned long flags;
2747 down(&ieee->wx_sem);
2748 if(!ieee->proto_started)
2751 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2754 /* until we do not set the state to IEEE80211_NOLINK
2755 * there are no possibility to have someone else trying
2756 * to start an association procdure (we get here with
2757 * ieee->state = IEEE80211_ASSOCIATING).
2758 * When we set the state to IEEE80211_NOLINK it is possible
2759 * that the RX path run an attempt to associate, but
2760 * both ieee80211_softmac_check_all_nets and the
2761 * RX path works with ieee->lock held so there are no
2762 * problems. If we are still disassociated then start a scan.
2763 * the lock here is necessary to ensure no one try to start
2764 * an association procedure when we have just checked the
2765 * state and we are going to start the scan.
2767 ieee->beinretry = true;
2768 ieee->state = IEEE80211_NOLINK;
2770 ieee80211_softmac_check_all_nets(ieee);
2772 spin_lock_irqsave(&ieee->lock, flags);
2774 if(ieee->state == IEEE80211_NOLINK)
2776 ieee->is_roaming= false;
2777 ieee->actscanning = true;
2778 ieee80211_rtl_start_scan(ieee);
2780 spin_unlock_irqrestore(&ieee->lock, flags);
2782 ieee->beinretry = false;
2787 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2789 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2791 struct sk_buff *skb;
2792 struct ieee80211_probe_response *b;
2794 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2799 b = (struct ieee80211_probe_response *) skb->data;
2800 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2806 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2808 struct sk_buff *skb;
2809 struct ieee80211_probe_response *b;
2811 skb = ieee80211_get_beacon_(ieee);
2815 b = (struct ieee80211_probe_response *) skb->data;
2816 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2818 if (ieee->seq_ctrl[0] == 0xFFF)
2819 ieee->seq_ctrl[0] = 0;
2821 ieee->seq_ctrl[0]++;
2826 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2828 ieee->sync_scan_hurryup = 1;
2829 down(&ieee->wx_sem);
2830 ieee80211_stop_protocol(ieee);
2835 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2837 if (!ieee->proto_started)
2840 ieee->proto_started = 0;
2842 ieee80211_stop_send_beacons(ieee);
2843 del_timer_sync(&ieee->associate_timer);
2844 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2845 cancel_delayed_work(&ieee->associate_retry_wq);
2846 cancel_delayed_work(&ieee->start_ibss_wq);
2848 ieee80211_stop_scan(ieee);
2850 ieee80211_disassociate(ieee);
2851 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2854 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2856 ieee->sync_scan_hurryup = 0;
2857 down(&ieee->wx_sem);
2858 ieee80211_start_protocol(ieee);
2862 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2866 if (ieee->proto_started)
2869 ieee->proto_started = 1;
2871 if (ieee->current_network.channel == 0){
2874 if (ch > MAX_CHANNEL_NUMBER)
2875 return; /* no channel found */
2876 #ifdef ENABLE_DOT11D
2877 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2879 }while(!ieee->channel_map[ch]);
2881 ieee->current_network.channel = ch;
2884 if (ieee->current_network.beacon_interval == 0)
2885 ieee->current_network.beacon_interval = 100;
2886 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2887 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2889 for(i = 0; i < 17; i++) {
2890 ieee->last_rxseq_num[i] = -1;
2891 ieee->last_rxfrag_num[i] = -1;
2892 ieee->last_packet_time[i] = 0;
2895 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2898 /* if the user set the MAC of the ad-hoc cell and then
2899 * switch to managed mode, shall we make sure that association
2900 * attempts does not fail just because the user provide the essid
2901 * and the nic is still checking for the AP MAC ??
2903 if (ieee->iw_mode == IW_MODE_INFRA)
2904 ieee80211_start_bss(ieee);
2906 else if (ieee->iw_mode == IW_MODE_ADHOC)
2907 ieee80211_start_ibss(ieee);
2909 else if (ieee->iw_mode == IW_MODE_MASTER)
2910 ieee80211_start_master_bss(ieee);
2912 else if(ieee->iw_mode == IW_MODE_MONITOR)
2913 ieee80211_start_monitor_mode(ieee);
2917 #define DRV_NAME "Ieee80211"
2918 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2921 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2923 ieee->state = IEEE80211_NOLINK;
2924 ieee->sync_scan_hurryup = 0;
2925 for(i = 0; i < 5; i++) {
2926 ieee->seq_ctrl[i] = 0;
2928 #ifdef ENABLE_DOT11D
2929 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2930 if (!ieee->pDot11dInfo)
2931 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2932 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
2934 //added for AP roaming
2935 ieee->LinkDetectInfo.SlotNum = 2;
2936 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2937 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2940 ieee->queue_stop = 0;
2942 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2945 ieee->proto_started = 0;
2946 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2948 ieee->ps = IEEE80211_PS_DISABLED;
2949 ieee->sta_sleep = 0;
2950 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2951 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2952 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2954 ieee->actscanning = false;
2955 ieee->beinretry = false;
2956 ieee->is_set_key = false;
2957 init_mgmt_queue(ieee);
2959 ieee->sta_edca_param[0] = 0x0000A403;
2960 ieee->sta_edca_param[1] = 0x0000A427;
2961 ieee->sta_edca_param[2] = 0x005E4342;
2962 ieee->sta_edca_param[3] = 0x002F3262;
2963 ieee->aggregation = true;
2964 ieee->enable_rx_imm_BA = 1;
2965 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2966 init_timer(&ieee->scan_timer);
2967 ieee->scan_timer.data = (unsigned long)ieee;
2968 ieee->scan_timer.function = ieee80211_softmac_scan_cb;
2970 ieee->tx_pending.txb = NULL;
2972 init_timer(&ieee->associate_timer);
2973 ieee->associate_timer.data = (unsigned long)ieee;
2974 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2976 init_timer(&ieee->beacon_timer);
2977 ieee->beacon_timer.data = (unsigned long) ieee;
2978 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2980 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2981 #ifdef PF_SYNCTHREAD
2982 ieee->wq = create_workqueue(DRV_NAME,0);
2984 ieee->wq = create_workqueue(DRV_NAME);
2988 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2989 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
2990 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2991 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2992 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2993 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2994 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2995 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2998 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
2999 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3000 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3001 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3002 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3003 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3007 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3008 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3009 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3010 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3011 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3012 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3014 sema_init(&ieee->wx_sem, 1);
3015 sema_init(&ieee->scan_sem, 1);
3017 spin_lock_init(&ieee->mgmt_tx_lock);
3018 spin_lock_init(&ieee->beacon_lock);
3020 tasklet_init(&ieee->ps_task,
3021 (void(*)(unsigned long)) ieee80211_sta_ps,
3022 (unsigned long)ieee);
3026 void ieee80211_softmac_free(struct ieee80211_device *ieee)
3028 down(&ieee->wx_sem);
3029 #ifdef ENABLE_DOT11D
3030 if(NULL != ieee->pDot11dInfo)
3032 kfree(ieee->pDot11dInfo);
3033 ieee->pDot11dInfo = NULL;
3036 del_timer_sync(&ieee->associate_timer);
3038 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3039 cancel_delayed_work(&ieee->associate_retry_wq);
3040 destroy_workqueue(ieee->wq);
3046 /********************************************************
3047 * Start of WPA code. *
3048 * this is stolen from the ipw2200 driver *
3049 ********************************************************/
3052 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3054 /* This is called when wpa_supplicant loads and closes the driver
3056 printk("%s WPA\n",value ? "enabling" : "disabling");
3057 ieee->wpa_enabled = value;
3062 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3064 /* make sure WPA is enabled */
3065 ieee80211_wpa_enable(ieee, 1);
3067 ieee80211_disassociate(ieee);
3071 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3077 case IEEE_MLME_STA_DEAUTH:
3081 case IEEE_MLME_STA_DISASSOC:
3082 ieee80211_disassociate(ieee);
3086 printk("Unknown MLME request: %d\n", command);
3094 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3095 struct ieee_param *param, int plen)
3099 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3100 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3103 if (param->u.wpa_ie.len) {
3104 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
3108 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
3109 kfree(ieee->wpa_ie);
3111 ieee->wpa_ie_len = param->u.wpa_ie.len;
3113 kfree(ieee->wpa_ie);
3114 ieee->wpa_ie = NULL;
3115 ieee->wpa_ie_len = 0;
3118 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3122 #define AUTH_ALG_OPEN_SYSTEM 0x1
3123 #define AUTH_ALG_SHARED_KEY 0x2
3125 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3128 struct ieee80211_security sec = {
3129 .flags = SEC_AUTH_MODE,
3133 if (value & AUTH_ALG_SHARED_KEY) {
3134 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3136 ieee->auth_mode = 1;
3137 } else if (value & AUTH_ALG_OPEN_SYSTEM){
3138 sec.auth_mode = WLAN_AUTH_OPEN;
3140 ieee->auth_mode = 0;
3142 else if (value & IW_AUTH_ALG_LEAP){
3143 sec.auth_mode = WLAN_AUTH_LEAP;
3145 ieee->auth_mode = 2;
3149 if (ieee->set_security)
3150 ieee->set_security(ieee->dev, &sec);
3152 // ret = -EOPNOTSUPP;
3157 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3160 unsigned long flags;
3163 case IEEE_PARAM_WPA_ENABLED:
3164 ret = ieee80211_wpa_enable(ieee, value);
3167 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3168 ieee->tkip_countermeasures=value;
3171 case IEEE_PARAM_DROP_UNENCRYPTED: {
3174 * wpa_supplicant calls set_wpa_enabled when the driver
3175 * is loaded and unloaded, regardless of if WPA is being
3176 * used. No other calls are made which can be used to
3177 * determine if encryption will be used or not prior to
3178 * association being expected. If encryption is not being
3179 * used, drop_unencrypted is set to false, else true -- we
3180 * can use this to determine if the CAP_PRIVACY_ON bit should
3183 struct ieee80211_security sec = {
3184 .flags = SEC_ENABLED,
3187 ieee->drop_unencrypted = value;
3188 /* We only change SEC_LEVEL for open mode. Others
3189 * are set by ipw_wpa_set_encryption.
3192 sec.flags |= SEC_LEVEL;
3193 sec.level = SEC_LEVEL_0;
3196 sec.flags |= SEC_LEVEL;
3197 sec.level = SEC_LEVEL_1;
3199 if (ieee->set_security)
3200 ieee->set_security(ieee->dev, &sec);
3204 case IEEE_PARAM_PRIVACY_INVOKED:
3205 ieee->privacy_invoked=value;
3208 case IEEE_PARAM_AUTH_ALGS:
3209 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3212 case IEEE_PARAM_IEEE_802_1X:
3213 ieee->ieee802_1x=value;
3215 case IEEE_PARAM_WPAX_SELECT:
3216 // added for WPA2 mixed mode
3217 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3218 ieee->wpax_type_set = 1;
3219 ieee->wpax_type_notify = value;
3220 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3224 printk("Unknown WPA param: %d\n",name);
3231 /* implementation borrowed from hostap driver */
3233 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3234 struct ieee_param *param, int param_len)
3238 struct ieee80211_crypto_ops *ops;
3239 struct ieee80211_crypt_data **crypt;
3241 struct ieee80211_security sec = {
3245 param->u.crypt.err = 0;
3246 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3249 (int) ((char *) param->u.crypt.key - (char *) param) +
3250 param->u.crypt.key_len) {
3251 printk("Len mismatch %d, %d\n", param_len,
3252 param->u.crypt.key_len);
3255 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3256 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3257 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3258 if (param->u.crypt.idx >= WEP_KEYS)
3260 crypt = &ieee->crypt[param->u.crypt.idx];
3265 if (strcmp(param->u.crypt.alg, "none") == 0) {
3270 sec.level = SEC_LEVEL_0;
3271 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3272 ieee80211_crypt_delayed_deinit(ieee, crypt);
3279 sec.flags |= SEC_ENABLED;
3281 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3282 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3283 strcmp(param->u.crypt.alg, "TKIP"))
3284 goto skip_host_crypt;
3286 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3287 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3288 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3289 /* set WEP40 first, it will be modified according to WEP104 or
3290 * WEP40 at other place */
3291 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3292 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3293 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3294 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3296 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3297 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3302 if (*crypt == NULL || (*crypt)->ops != ops) {
3303 struct ieee80211_crypt_data *new_crypt;
3305 ieee80211_crypt_delayed_deinit(ieee, crypt);
3307 new_crypt = (struct ieee80211_crypt_data *)
3308 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3309 if (new_crypt == NULL) {
3313 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3314 new_crypt->ops = ops;
3317 new_crypt->ops->init(param->u.crypt.idx);
3319 if (new_crypt->priv == NULL) {
3321 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3329 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3330 (*crypt)->ops->set_key(param->u.crypt.key,
3331 param->u.crypt.key_len, param->u.crypt.seq,
3332 (*crypt)->priv) < 0) {
3333 printk("key setting failed\n");
3334 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3340 if (param->u.crypt.set_tx) {
3341 ieee->tx_keyidx = param->u.crypt.idx;
3342 sec.active_key = param->u.crypt.idx;
3343 sec.flags |= SEC_ACTIVE_KEY;
3345 sec.flags &= ~SEC_ACTIVE_KEY;
3347 if (param->u.crypt.alg != NULL) {
3348 memcpy(sec.keys[param->u.crypt.idx],
3350 param->u.crypt.key_len);
3351 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3352 sec.flags |= (1 << param->u.crypt.idx);
3354 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3355 sec.flags |= SEC_LEVEL;
3356 sec.level = SEC_LEVEL_1;
3357 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3358 sec.flags |= SEC_LEVEL;
3359 sec.level = SEC_LEVEL_2;
3360 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3361 sec.flags |= SEC_LEVEL;
3362 sec.level = SEC_LEVEL_3;
3366 if (ieee->set_security)
3367 ieee->set_security(ieee->dev, &sec);
3369 /* Do not reset port if card is in Managed mode since resetting will
3370 * generate new IEEE 802.11 authentication which may end up in looping
3371 * with IEEE 802.1X. If your hardware requires a reset after WEP
3372 * configuration (for example... Prism2), implement the reset_port in
3373 * the callbacks structures used to initialize the 802.11 stack. */
3374 if (ieee->reset_on_keychange &&
3375 ieee->iw_mode != IW_MODE_INFRA &&
3377 ieee->reset_port(ieee->dev)) {
3378 printk("reset_port failed\n");
3379 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3386 inline struct sk_buff *ieee80211_disassociate_skb(
3387 struct ieee80211_network *beacon,
3388 struct ieee80211_device *ieee,
3391 struct sk_buff *skb;
3392 struct ieee80211_disassoc *disass;
3394 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3398 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3399 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3400 disass->header.duration_id = 0;
3402 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3403 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3404 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3406 disass->reason = asRsn;
3413 struct ieee80211_device *ieee,
3418 struct ieee80211_network *beacon = &ieee->current_network;
3419 struct sk_buff *skb;
3420 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3422 softmac_mgmt_xmit(skb, ieee);
3423 //dev_kfree_skb_any(skb);//edit by thomas
3427 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3429 struct ieee_param *param;
3432 down(&ieee->wx_sem);
3433 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3435 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3440 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3445 if (copy_from_user(param, p->pointer, p->length)) {
3451 switch (param->cmd) {
3453 case IEEE_CMD_SET_WPA_PARAM:
3454 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3455 param->u.wpa_param.value);
3458 case IEEE_CMD_SET_WPA_IE:
3459 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3462 case IEEE_CMD_SET_ENCRYPTION:
3463 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3467 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3468 param->u.mlme.reason_code);
3472 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3477 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3487 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3489 union iwreq_data wrqu;
3490 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3491 if (ieee->state == IEEE80211_LINKED)
3492 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3494 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3495 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3498 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3499 //EXPORT_SYMBOL(ieee80211_get_beacon);
3500 //EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3501 //EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3502 //EXPORT_SYMBOL(ieee80211_reset_queue);
3503 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3504 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3505 //EXPORT_SYMBOL(ieee80211_is_shortslot);
3506 //EXPORT_SYMBOL(ieee80211_is_54g);
3507 //EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3508 //EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3509 //EXPORT_SYMBOL(ieee80211_softmac_xmit);
3510 //EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3511 //EXPORT_SYMBOL(notify_wx_assoc_event);
3512 //EXPORT_SYMBOL(SendDisassociation);
3513 //EXPORT_SYMBOL(ieee80211_disassociate);
3514 //EXPORT_SYMBOL(ieee80211_start_send_beacons);
3515 //EXPORT_SYMBOL(ieee80211_stop_scan);
3516 //EXPORT_SYMBOL(ieee80211_send_probe_requests);
3517 //EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3518 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3520 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3521 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3522 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3523 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3524 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3525 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3526 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3527 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3528 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3529 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3530 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3531 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3532 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3533 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3534 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3535 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3536 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3537 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3538 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3539 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3541 //EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);