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);
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(ieee->ieee80211_ips_leave_wq != NULL)
691 ieee->ieee80211_ips_leave_wq(ieee->dev);
695 if(IS_DOT11D_ENABLE(ieee) )
697 if(IS_COUNTRY_IE_VALID(ieee))
699 RESET_CIE_WATCHDOG(ieee);
703 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
704 if (ieee->scanning == 0){
706 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
707 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
708 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
711 queue_work(ieee->wq, &ieee->softmac_scan_wq);
714 ieee80211_softmac_scan(ieee);
718 ieee->start_scan(ieee->dev);
722 /* called with wx_sem held */
723 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
726 if(IS_DOT11D_ENABLE(ieee) )
728 if(IS_COUNTRY_IE_VALID(ieee))
730 RESET_CIE_WATCHDOG(ieee);
734 ieee->sync_scan_hurryup = 0;
735 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
736 ieee80211_softmac_scan_syncro(ieee);
738 ieee->scan_syncro(ieee->dev);
742 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
743 struct ieee80211_device *ieee, int challengelen)
746 struct ieee80211_authentication *auth;
747 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
750 skb = dev_alloc_skb(len);
751 if (!skb) return NULL;
753 skb_reserve(skb, ieee->tx_headroom);
754 auth = (struct ieee80211_authentication *)
755 skb_put(skb, sizeof(struct ieee80211_authentication));
757 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
758 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
760 auth->header.duration_id = 0x013a; //FIXME
762 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
763 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
764 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
766 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
767 if(ieee->auth_mode == 0)
768 auth->algorithm = WLAN_AUTH_OPEN;
769 else if(ieee->auth_mode == 1)
770 auth->algorithm = WLAN_AUTH_SHARED_KEY;
771 else if(ieee->auth_mode == 2)
772 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
773 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
774 auth->transaction = cpu_to_le16(ieee->associate_seq);
775 ieee->associate_seq++;
777 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
784 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
788 struct ieee80211_probe_response *beacon_buf;
789 struct sk_buff *skb = NULL;
791 int atim_len,erp_len;
792 struct ieee80211_crypt_data* crypt;
794 char *ssid = ieee->current_network.ssid;
795 int ssid_len = ieee->current_network.ssid_len;
796 int rate_len = ieee->current_network.rates_len+2;
797 int rate_ex_len = ieee->current_network.rates_ex_len;
798 int wpa_ie_len = ieee->wpa_ie_len;
799 u8 erpinfo_content = 0;
804 u8 tmp_ht_info_len=0;
805 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
806 u8* tmp_generic_ie_buf=NULL;
807 u8 tmp_generic_ie_len=0;
809 if(rate_ex_len > 0) rate_ex_len+=2;
811 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
817 if(ieee80211_is_54g(ieee->current_network))
822 if((ieee->current_network.mode == IEEE_G)
823 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
826 if(ieee->current_network.buseprotection)
827 erpinfo_content |= ERP_UseProtection;
834 crypt = ieee->crypt[ieee->tx_keyidx];
837 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
838 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
841 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
842 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
843 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
844 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
845 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
846 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
849 if(pHTInfo->bRegRT2RTAggregation)
851 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
852 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
853 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
855 // 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);
857 beacon_size = sizeof(struct ieee80211_probe_response)+2+
867 // +tmp_generic_ie_len
870 skb = dev_alloc_skb(beacon_size);
873 skb_reserve(skb, ieee->tx_headroom);
874 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
875 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
876 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
877 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
879 beacon_buf->header.duration_id = 0; //FIXME
880 beacon_buf->beacon_interval =
881 cpu_to_le16(ieee->current_network.beacon_interval);
882 beacon_buf->capability =
883 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
884 beacon_buf->capability |=
885 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
887 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
888 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
890 crypt = ieee->crypt[ieee->tx_keyidx];
892 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
893 (0 == strcmp(crypt->ops->name, "WEP"));
896 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
899 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
900 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
901 beacon_buf->info_element[0].len = ssid_len;
903 tag = (u8*) beacon_buf->info_element[0].data;
905 memcpy(tag, ssid, ssid_len);
909 *(tag++) = MFIE_TYPE_RATES;
910 *(tag++) = rate_len-2;
911 memcpy(tag,ieee->current_network.rates,rate_len-2);
914 *(tag++) = MFIE_TYPE_DS_SET;
916 *(tag++) = ieee->current_network.channel;
920 *(tag++) = MFIE_TYPE_IBSS_SET;
922 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
923 val16 = cpu_to_le16(ieee->current_network.atim_window);
924 memcpy((u8 *)tag, (u8 *)&val16, 2);
929 *(tag++) = MFIE_TYPE_ERP;
931 *(tag++) = erpinfo_content;
934 //Include High Throuput capability
936 *(tag++) = MFIE_TYPE_HT_CAP;
937 *(tag++) = tmp_ht_cap_len - 2;
938 memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
939 tag += tmp_ht_cap_len - 2;
942 *(tag++) = MFIE_TYPE_RATES_EX;
943 *(tag++) = rate_ex_len-2;
944 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
949 //Include High Throuput info
951 *(tag++) = MFIE_TYPE_HT_INFO;
952 *(tag++) = tmp_ht_info_len - 2;
953 memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
954 tag += tmp_ht_info_len - 2;
958 if (ieee->iw_mode == IW_MODE_ADHOC)
959 {//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
960 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
962 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
968 // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
970 if(pHTInfo->bRegRT2RTAggregation)
973 (*tag++) = tmp_generic_ie_len - 2;
974 memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
975 tag += tmp_generic_ie_len -2;
980 if(ieee->qos_support)
984 memcpy(tag,QosOui,wmm_len);
988 //skb->dev = ieee->dev;
993 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
998 struct ieee80211_crypt_data* crypt;
999 struct ieee80211_assoc_response_frame *assoc;
1002 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1003 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
1005 skb = dev_alloc_skb(len);
1010 skb_reserve(skb, ieee->tx_headroom);
1012 assoc = (struct ieee80211_assoc_response_frame *)
1013 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
1015 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
1016 memcpy(assoc->header.addr1, dest,ETH_ALEN);
1017 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1018 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1019 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
1020 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
1023 if(ieee->short_slot)
1024 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1026 if (ieee->host_encrypt)
1027 crypt = ieee->crypt[ieee->tx_keyidx];
1030 encrypt = ( crypt && crypt->ops);
1033 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1036 assoc->aid = cpu_to_le16(ieee->assoc_id);
1037 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
1038 else ieee->assoc_id++;
1040 tag = (u8*) skb_put(skb, rate_len);
1042 ieee80211_MFIE_Brate(ieee, &tag);
1043 ieee80211_MFIE_Grate(ieee, &tag);
1048 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
1050 struct sk_buff *skb;
1051 struct ieee80211_authentication *auth;
1052 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
1054 skb = dev_alloc_skb(len);
1059 skb->len = sizeof(struct ieee80211_authentication);
1061 auth = (struct ieee80211_authentication *)skb->data;
1063 auth->status = cpu_to_le16(status);
1064 auth->transaction = cpu_to_le16(2);
1065 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
1067 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1068 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1069 memcpy(auth->header.addr1, dest, ETH_ALEN);
1070 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
1076 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
1078 struct sk_buff *skb;
1079 struct ieee80211_hdr_3addr* hdr;
1081 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1086 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1088 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1089 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1090 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1092 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
1093 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1094 (pwr ? IEEE80211_FCTL_PM:0));
1101 struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
1103 struct sk_buff *skb;
1104 struct ieee80211_pspoll_hdr* hdr;
1106 #ifdef USB_USE_ALIGNMENT
1109 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
1111 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
1116 #ifdef USB_USE_ALIGNMENT
1117 Tmpaddr = (u32)skb->data;
1118 alignment = Tmpaddr & 0x1ff;
1119 skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
1121 skb_reserve(skb, ieee->tx_headroom);
1123 hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
1125 memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
1126 memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
1128 hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
1129 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
1136 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1138 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1141 softmac_mgmt_xmit(buf, ieee);
1145 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1147 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1150 softmac_mgmt_xmit(buf, ieee);
1154 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1158 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1160 softmac_mgmt_xmit(buf, ieee);
1164 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1166 struct sk_buff *skb;
1167 //unsigned long flags;
1169 struct ieee80211_assoc_request_frame *hdr;
1171 //short info_addr = 0;
1173 //u16 suite_count = 0;
1174 //u8 suit_select = 0;
1175 //unsigned int wpa_len = beacon->wpa_ie_len;
1177 u8* ht_cap_buf = NULL;
1179 u8* realtek_ie_buf=NULL;
1180 u8 realtek_ie_len=0;
1181 int wpa_ie_len= ieee->wpa_ie_len;
1182 unsigned int ckip_ie_len=0;
1183 unsigned int ccxrm_ie_len=0;
1184 unsigned int cxvernum_ie_len=0;
1185 struct ieee80211_crypt_data* crypt;
1188 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1189 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1191 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1196 crypt = ieee->crypt[ieee->tx_keyidx];
1197 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1199 //Include High Throuput capability && Realtek proprietary
1200 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1202 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1203 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1204 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1205 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1207 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1208 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1209 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1213 if(ieee->qos_support){
1214 wmm_info_len = beacon->qos_data.supported?9:0;
1218 if(beacon->bCkipSupported)
1222 if(beacon->bCcxRmEnable)
1226 if( beacon->BssCcxVerNumber >= 2 )
1228 cxvernum_ie_len = 5+2;
1231 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1232 + beacon->ssid_len//essid tagged val
1233 + rate_len//rates tagged val
1242 + ieee->tx_headroom;
1244 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1245 + beacon->ssid_len//essid tagged val
1246 + rate_len//rates tagged val
1254 + ieee->tx_headroom;
1257 skb = dev_alloc_skb(len);
1262 skb_reserve(skb, ieee->tx_headroom);
1264 hdr = (struct ieee80211_assoc_request_frame *)
1265 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1268 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1269 hdr->header.duration_id= 37; //FIXME
1270 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1271 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1272 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1274 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1276 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1277 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1278 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1280 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1281 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1283 if(ieee->short_slot)
1284 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1285 if (wmm_info_len) //QOS
1286 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1288 hdr->listen_interval = 0xa; //FIXME
1290 hdr->info_element[0].id = MFIE_TYPE_SSID;
1292 hdr->info_element[0].len = beacon->ssid_len;
1293 tag = skb_put(skb, beacon->ssid_len);
1294 memcpy(tag, beacon->ssid, beacon->ssid_len);
1296 tag = skb_put(skb, rate_len);
1298 ieee80211_MFIE_Brate(ieee, &tag);
1299 ieee80211_MFIE_Grate(ieee, &tag);
1300 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1301 if( beacon->bCkipSupported )
1303 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1304 u8 CcxAironetBuf[30];
1305 OCTET_STRING osCcxAironetIE;
1307 memset(CcxAironetBuf, 0,30);
1308 osCcxAironetIE.Octet = CcxAironetBuf;
1309 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1311 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1312 // We want to make the device type as "4500-client". 060926, by CCW.
1314 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1316 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1317 // "The CKIP negotiation is started with the associate request from the client to the access point,
1318 // containing an Aironet element with both the MIC and KP bits set."
1319 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1320 tag = skb_put(skb, ckip_ie_len);
1321 *tag++ = MFIE_TYPE_AIRONET;
1322 *tag++ = osCcxAironetIE.Length;
1323 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1324 tag += osCcxAironetIE.Length;
1327 if(beacon->bCcxRmEnable)
1329 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1330 OCTET_STRING osCcxRmCap;
1332 osCcxRmCap.Octet = CcxRmCapBuf;
1333 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1334 tag = skb_put(skb,ccxrm_ie_len);
1335 *tag++ = MFIE_TYPE_GENERIC;
1336 *tag++ = osCcxRmCap.Length;
1337 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1338 tag += osCcxRmCap.Length;
1341 if( beacon->BssCcxVerNumber >= 2 )
1343 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1344 OCTET_STRING osCcxVerNum;
1345 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1346 osCcxVerNum.Octet = CcxVerNumBuf;
1347 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1348 tag = skb_put(skb,cxvernum_ie_len);
1349 *tag++ = MFIE_TYPE_GENERIC;
1350 *tag++ = osCcxVerNum.Length;
1351 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1352 tag += osCcxVerNum.Length;
1355 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1356 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1358 tag = skb_put(skb, ht_cap_len);
1359 *tag++ = MFIE_TYPE_HT_CAP;
1360 *tag++ = ht_cap_len - 2;
1361 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1362 tag += ht_cap_len -2;
1367 //choose what wpa_supplicant gives to associate.
1368 tag = skb_put(skb, wpa_ie_len);
1370 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1373 tag = skb_put(skb,wmm_info_len);
1375 ieee80211_WMM_Info(ieee, &tag);
1378 tag = skb_put(skb,turbo_info_len);
1379 if(turbo_info_len) {
1380 ieee80211_TURBO_Info(ieee, &tag);
1384 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1385 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1387 tag = skb_put(skb, ht_cap_len);
1388 *tag++ = MFIE_TYPE_GENERIC;
1389 *tag++ = ht_cap_len - 2;
1390 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1391 tag += ht_cap_len -2;
1394 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1395 tag = skb_put(skb, realtek_ie_len);
1396 *tag++ = MFIE_TYPE_GENERIC;
1397 *tag++ = realtek_ie_len - 2;
1398 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1401 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1402 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1406 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1409 unsigned long flags;
1410 spin_lock_irqsave(&ieee->lock, flags);
1412 ieee->associate_seq++;
1414 /* don't scan, and avoid to have the RX path possibily
1415 * try again to associate. Even do not react to AUTH or
1416 * ASSOC response. Just wait for the retry wq to be scheduled.
1417 * Here we will check if there are good nets to associate
1418 * with, so we retry or just get back to NO_LINK and scanning
1420 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1421 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1422 ieee->softmac_stats.no_auth_rs++;
1424 IEEE80211_DEBUG_MGMT("Association failed\n");
1425 ieee->softmac_stats.no_ass_rs++;
1428 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1430 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1431 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1432 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1434 schedule_task(&ieee->associate_retry_wq);
1437 spin_unlock_irqrestore(&ieee->lock, flags);
1440 void ieee80211_associate_abort_cb(unsigned long dev)
1442 ieee80211_associate_abort((struct ieee80211_device *) dev);
1446 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1448 struct ieee80211_network *beacon = &ieee->current_network;
1449 struct sk_buff *skb;
1451 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1453 ieee->softmac_stats.tx_auth_rq++;
1454 skb=ieee80211_authentication_req(beacon, ieee, 0);
1457 ieee80211_associate_abort(ieee);
1459 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1460 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1461 //printk(KERN_WARNING "Sending authentication request\n");
1462 softmac_mgmt_xmit(skb, ieee);
1463 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1464 if(!timer_pending(&ieee->associate_timer)){
1465 ieee->associate_timer.expires = jiffies + (HZ / 2);
1466 add_timer(&ieee->associate_timer);
1468 //dev_kfree_skb_any(skb);//edit by thomas
1472 void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1475 struct sk_buff *skb;
1476 struct ieee80211_network *beacon = &ieee->current_network;
1477 // int hlen = sizeof(struct ieee80211_authentication);
1479 ieee->associate_seq++;
1480 ieee->softmac_stats.tx_auth_rq++;
1482 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1484 ieee80211_associate_abort(ieee);
1486 c = skb_put(skb, chlen+2);
1487 *(c++) = MFIE_TYPE_CHALLENGE;
1489 memcpy(c, challenge, chlen);
1491 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1493 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1495 softmac_mgmt_xmit(skb, ieee);
1496 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1498 ieee->associate_timer.expires = jiffies + (HZ / 2);
1499 add_timer(&ieee->associate_timer);
1501 //dev_kfree_skb_any(skb);//edit by thomas
1506 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1508 struct sk_buff* skb;
1509 struct ieee80211_network *beacon = &ieee->current_network;
1511 del_timer_sync(&ieee->associate_timer);
1513 IEEE80211_DEBUG_MGMT("Sending association request\n");
1515 ieee->softmac_stats.tx_ass_rq++;
1516 skb=ieee80211_association_req(beacon, ieee);
1518 ieee80211_associate_abort(ieee);
1520 softmac_mgmt_xmit(skb, ieee);
1521 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1523 ieee->associate_timer.expires = jiffies + (HZ / 2);
1524 add_timer(&ieee->associate_timer);
1526 //dev_kfree_skb_any(skb);//edit by thomas
1529 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1530 void ieee80211_associate_complete_wq(struct work_struct *work)
1532 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1534 void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1537 printk(KERN_INFO "Associated successfully\n");
1538 ieee->is_roaming = false;
1539 if(ieee80211_is_54g(ieee->current_network) &&
1540 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1543 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1546 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1548 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1550 printk("Successfully associated, ht enabled\n");
1555 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1556 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1557 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1559 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1560 // To prevent the immediately calling watch_dog after association.
1561 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1563 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1564 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1566 ieee->link_change(ieee->dev);
1567 if(ieee->is_silent_reset == 0){
1568 printk("============>normal associate\n");
1569 notify_wx_assoc_event(ieee);
1571 else if(ieee->is_silent_reset == 1)
1573 printk("==================>silent reset associate\n");
1574 ieee->is_silent_reset = 0;
1577 if (ieee->data_hard_resume)
1578 ieee->data_hard_resume(ieee->dev);
1579 netif_carrier_on(ieee->dev);
1582 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1585 // struct net_device* dev = ieee->dev;
1586 del_timer_sync(&ieee->associate_timer);
1589 for(i = 0; i < 6; i++) {
1590 ieee->seq_ctrl[i] = 0;
1593 ieee->state = IEEE80211_LINKED;
1595 if (ieee->pHTInfo->bCurrentHTSupport)
1597 printk("Successfully associated, ht enabled\n");
1598 queue_work(ieee->wq, &ieee->ht_onAssRsp);
1602 printk("Successfully associated, ht not enabled\n");
1603 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1604 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1607 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1608 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1609 queue_work(ieee->wq, &ieee->associate_complete_wq);
1611 schedule_task(&ieee->associate_complete_wq);
1615 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1616 void ieee80211_associate_procedure_wq(struct work_struct *work)
1618 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1620 void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1623 ieee->sync_scan_hurryup = 1;
1625 if(ieee->ieee80211_ips_leave != NULL)
1626 ieee->ieee80211_ips_leave(ieee->dev);
1629 down(&ieee->wx_sem);
1631 if (ieee->data_hard_stop)
1632 ieee->data_hard_stop(ieee->dev);
1634 ieee80211_stop_scan(ieee);
1635 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1636 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1637 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1640 if(ieee->eRFPowerState == eRfOff)
1642 if(ieee->ieee80211_ips_leave_wq != NULL)
1643 ieee->ieee80211_ips_leave_wq(ieee->dev);
1650 ieee->associate_seq = 1;
1651 ieee80211_associate_step1(ieee);
1656 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1658 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1659 int tmp_ssid_len = 0;
1661 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1663 /* we are interested in new new only if we are not associated
1664 * and we are not associating / authenticating
1666 if (ieee->state != IEEE80211_NOLINK)
1669 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1672 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1676 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1677 /* if the user specified the AP MAC, we need also the essid
1678 * This could be obtained by beacons or, if the network does not
1679 * broadcast it, it can be put manually.
1681 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1682 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1683 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1684 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1685 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1686 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1689 if ( /* if the user set the AP check if match.
1690 * if the network does not broadcast essid we check the user supplyed ANY essid
1691 * if the network does broadcast and the user does not set essid it is OK
1692 * if the network does broadcast and the user did set essid chech if essid match
1694 ( apset && apmatch &&
1695 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1696 /* if the ap is not set, check that the user set the bssid
1697 * and the network does bradcast and that those two bssid matches
1699 (!apset && ssidset && ssidbroad && ssidmatch)
1701 /* if the essid is hidden replace it with the
1702 * essid provided by the user.
1705 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1706 tmp_ssid_len = ieee->current_network.ssid_len;
1708 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1711 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1712 ieee->current_network.ssid_len = tmp_ssid_len;
1714 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);
1716 //ieee->pHTInfo->IOTAction = 0;
1717 HTResetIOTSetting(ieee->pHTInfo);
1718 if (ieee->iw_mode == IW_MODE_INFRA){
1719 /* Join the network for the first time */
1720 ieee->AsocRetryCount = 0;
1721 //for HT by amy 080514
1722 if((ieee->current_network.qos_data.supported == 1) &&
1723 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1724 ieee->current_network.bssht.bdSupportHT)
1725 /*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.*/
1727 // ieee->pHTInfo->bCurrentHTSupport = true;
1728 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1732 ieee->pHTInfo->bCurrentHTSupport = false;
1735 ieee->state = IEEE80211_ASSOCIATING;
1736 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1737 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1739 schedule_task(&ieee->associate_procedure_wq);
1742 if(ieee80211_is_54g(ieee->current_network) &&
1743 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1745 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1746 printk(KERN_INFO"Using G rates\n");
1749 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1750 printk(KERN_INFO"Using B rates\n");
1752 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1753 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1754 ieee->state = IEEE80211_LINKED;
1762 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1764 unsigned long flags;
1765 struct ieee80211_network *target;
1767 spin_lock_irqsave(&ieee->lock, flags);
1769 list_for_each_entry(target, &ieee->network_list, list) {
1771 /* if the state become different that NOLINK means
1772 * we had found what we are searching for
1775 if (ieee->state != IEEE80211_NOLINK)
1778 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1779 ieee80211_softmac_new_net(ieee, target);
1782 spin_unlock_irqrestore(&ieee->lock, flags);
1787 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1789 struct ieee80211_authentication *a;
1791 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1792 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1796 a = (struct ieee80211_authentication*) skb->data;
1797 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1798 t = skb->data + sizeof(struct ieee80211_authentication);
1800 if(*(t++) == MFIE_TYPE_CHALLENGE){
1802 *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1803 memcpy(*challenge, t, *chlen);
1807 return cpu_to_le16(a->status);
1812 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1814 struct ieee80211_authentication *a;
1816 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1817 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1820 a = (struct ieee80211_authentication*) skb->data;
1822 memcpy(dest,a->header.addr2, ETH_ALEN);
1824 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1825 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1827 return WLAN_STATUS_SUCCESS;
1830 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1837 struct ieee80211_hdr_3addr *header =
1838 (struct ieee80211_hdr_3addr *) skb->data;
1840 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1841 return -1; /* corrupted */
1843 memcpy(src,header->addr2, ETH_ALEN);
1845 skbend = (u8*)skb->data + skb->len;
1847 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1849 while (tag+1 < skbend){
1855 tag++; /* point to the len field */
1856 tag = tag + *(tag); /* point to the last data byte of the tag */
1857 tag++; /* point to the next tag */
1860 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1861 if (ssidlen == 0) return 1;
1863 if (!ssid) return 1; /* ssid not found in tagged param */
1864 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1868 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1870 struct ieee80211_assoc_request_frame *a;
1872 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1873 sizeof(struct ieee80211_info_element))) {
1875 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1879 a = (struct ieee80211_assoc_request_frame*) skb->data;
1881 memcpy(dest,a->header.addr2,ETH_ALEN);
1886 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1888 struct ieee80211_assoc_response_frame *response_head;
1891 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1892 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1896 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1897 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1899 status_code = le16_to_cpu(response_head->status);
1900 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1901 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1902 ((ieee->mode == IEEE_G) &&
1903 (ieee->current_network.mode == IEEE_N_24G) &&
1904 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1905 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1907 ieee->AsocRetryCount = 0;
1910 return le16_to_cpu(response_head->status);
1914 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1918 //IEEE80211DMESG("Rx probe");
1919 ieee->softmac_stats.rx_probe_rq++;
1920 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1921 if (probe_rq_parse(ieee, skb, dest)){
1922 //IEEE80211DMESG("Was for me!");
1923 ieee->softmac_stats.tx_probe_rs++;
1924 ieee80211_resp_to_probe(ieee, dest);
1929 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1933 //IEEE80211DMESG("Rx probe");
1934 ieee->softmac_stats.rx_auth_rq++;
1936 if ((status = auth_rq_parse(skb, dest))!= -1){
1937 ieee80211_resp_to_auth(ieee, status, dest);
1939 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1944 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1948 //unsigned long flags;
1950 ieee->softmac_stats.rx_ass_rq++;
1951 if (assoc_rq_parse(skb,dest) != -1){
1952 ieee80211_resp_to_assoc_rq(ieee, dest);
1955 printk(KERN_INFO"New client associated: %pM\n", dest);
1958 spin_lock_irqsave(&ieee->lock,flags);
1959 add_associate(ieee,dest);
1960 spin_unlock_irqrestore(&ieee->lock,flags);
1966 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1969 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1972 softmac_ps_mgmt_xmit(buf, ieee);
1976 void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1979 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1982 softmac_ps_mgmt_xmit(buf, ieee);
1986 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1988 int timeout = ieee->ps_timeout;
1990 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
1992 if(ieee->LPSDelayCnt)
1994 //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
1995 ieee->LPSDelayCnt --;
1999 dtim = ieee->current_network.dtim_data;
2000 // printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
2001 if(!(dtim & IEEE80211_DTIM_VALID))
2003 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
2004 //printk("VALID\n");
2005 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
2006 /* there's no need to nofity AP that I find you buffered with broadcast packet */
2007 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
2010 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
2011 // printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2014 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
2015 // printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2018 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
2019 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
2023 if(ieee->bAwakePktSent == true) {
2024 pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
2028 if(pPSC->LPSAwakeIntvl == 0)
2029 pPSC->LPSAwakeIntvl = 1;
2030 //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
2031 if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
2032 MaxPeriod = 1; // 1 Beacon interval
2033 else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
2034 MaxPeriod = ieee->current_network.dtim_period;
2036 MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
2037 pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
2040 u8 LPSAwakeIntvl_tmp = 0;
2041 u8 period = ieee->current_network.dtim_period;
2042 u8 count = ieee->current_network.tim.tim_count;
2044 if(pPSC->LPSAwakeIntvl > period)
2045 LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
2047 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
2050 if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
2051 LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
2053 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
2055 //printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
2057 *time_l = ieee->current_network.last_dtim_sta_time[0]
2058 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
2059 // * ieee->current_network.dtim_period) * 1000;
2064 *time_h = ieee->current_network.last_dtim_sta_time[1];
2065 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
2074 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
2080 unsigned long flags,flags2;
2082 spin_lock_irqsave(&ieee->lock, flags);
2084 if((ieee->ps == IEEE80211_PS_DISABLED ||
2085 ieee->iw_mode != IW_MODE_INFRA ||
2086 ieee->state != IEEE80211_LINKED)){
2088 // #warning CHECK_LOCK_HERE
2089 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
2090 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
2091 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2093 ieee80211_sta_wakeup(ieee, 1);
2095 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2098 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
2099 /* 2 wake, 1 sleep, 0 do nothing */
2100 if(sleep == 0)//it is not time out or dtim is not valid
2102 //printk("===========>sleep is 0,do nothing\n");
2106 //printk("===========>sleep is 1,to sleep\n");
2107 if(ieee->sta_sleep == 1){
2108 //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
2109 ieee->enter_sleep_state(ieee->dev,th,tl);
2112 else if(ieee->sta_sleep == 0){
2113 // printk("send null 1\n");
2114 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2116 if(ieee->ps_is_queue_empty(ieee->dev)){
2117 ieee->sta_sleep = 2;
2118 ieee->ack_tx_to_ieee = 1;
2119 //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
2120 ieee80211_sta_ps_send_null_frame(ieee,1);
2124 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2128 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
2130 }else if(sleep == 2){
2131 //printk("==========>sleep is 2,to wakeup\n");
2132 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2134 //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
2135 ieee80211_sta_wakeup(ieee,1);
2137 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2141 spin_unlock_irqrestore(&ieee->lock, flags);
2145 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2147 if(ieee->sta_sleep == 0){
2149 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2151 //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2152 //printk("Warning: driver is probably failing to report TX ps error\n");
2153 ieee->ack_tx_to_ieee = 1;
2154 ieee80211_sta_ps_send_null_frame(ieee, 0);
2158 ieee->ack_tx_to_ieee = 1;
2159 //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2160 ieee80211_sta_ps_send_pspoll_frame(ieee);
2167 if(ieee->sta_sleep == 1)
2168 ieee->sta_wake_up(ieee->dev);
2171 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2173 //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2174 //printk("Warning: driver is probably failing to report TX ps error\n");
2175 ieee->ack_tx_to_ieee = 1;
2176 ieee80211_sta_ps_send_null_frame(ieee, 0);
2180 ieee->ack_tx_to_ieee = 1;
2181 ieee->polling = true;
2182 //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2183 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2184 ieee80211_sta_ps_send_pspoll_frame(ieee);
2188 ieee->sta_sleep = 0;
2189 ieee->polling = false;
2193 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2195 unsigned long flags,flags2;
2197 spin_lock_irqsave(&ieee->lock, flags);
2199 if(ieee->sta_sleep == 2){
2200 /* Null frame with PS bit set */
2202 ieee->sta_sleep = 1;
2203 //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
2204 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2206 } else {/* 21112005 - tx again null without PS bit if lost */
2208 if((ieee->sta_sleep == 0) && !success){
2209 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2210 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2211 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2213 //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
2214 ieee80211_sta_ps_send_null_frame(ieee, 0);
2218 //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
2219 ieee80211_sta_ps_send_pspoll_frame(ieee);
2221 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2224 spin_unlock_irqrestore(&ieee->lock, flags);
2227 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2229 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2230 u8* act = ieee80211_get_payload(header);
2232 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2235 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2243 if (*act == ACT_ADDBAREQ)
2244 ieee80211_rx_ADDBAReq(ieee, skb);
2245 else if (*act == ACT_ADDBARSP)
2246 ieee80211_rx_ADDBARsp(ieee, skb);
2247 else if (*act == ACT_DELBA)
2248 ieee80211_rx_DELBA(ieee, skb);
2251 // if (net_ratelimit())
2252 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2259 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2260 struct ieee80211_rx_stats *rx_stats, u16 type,
2263 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2268 struct ieee80211_assoc_response_frame *assoc_resp;
2269 // struct ieee80211_info_element *info_element;
2270 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2272 if(!ieee->proto_started)
2275 printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2276 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2277 ieee->iw_mode == IW_MODE_INFRA &&
2278 ieee->state == IEEE80211_LINKED))
2280 tasklet_schedule(&ieee->ps_task);
2282 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2283 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2284 ieee->last_rx_ps_time = jiffies;
2287 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2289 case IEEE80211_STYPE_ASSOC_RESP:
2290 case IEEE80211_STYPE_REASSOC_RESP:
2292 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2293 WLAN_FC_GET_STYPE(header->frame_ctl));
2294 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2295 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2296 ieee->iw_mode == IW_MODE_INFRA){
2297 struct ieee80211_network network_resp;
2298 struct ieee80211_network *network = &network_resp;
2300 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2301 ieee->state=IEEE80211_LINKED;
2302 ieee->assoc_id = aid;
2303 ieee->softmac_stats.rx_ass_ok++;
2304 /* station support qos */
2305 /* Let the register setting defaultly with Legacy station */
2306 if(ieee->qos_support) {
2307 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2308 memset(network, 0, sizeof(*network));
2309 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2310 rx_stats->len - sizeof(*assoc_resp),\
2315 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2316 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2317 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2319 if (ieee->handle_assoc_response != NULL)
2320 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2322 ieee80211_associate_complete(ieee);
2324 /* aid could not been allocated */
2325 ieee->softmac_stats.rx_ass_err++;
2327 "Association response status code 0x%x\n",
2329 IEEE80211_DEBUG_MGMT(
2330 "Association response status code 0x%x\n",
2332 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2333 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2334 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2336 schedule_task(&ieee->associate_procedure_wq);
2339 ieee80211_associate_abort(ieee);
2345 case IEEE80211_STYPE_ASSOC_REQ:
2346 case IEEE80211_STYPE_REASSOC_REQ:
2348 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2349 ieee->iw_mode == IW_MODE_MASTER)
2351 ieee80211_rx_assoc_rq(ieee, skb);
2354 case IEEE80211_STYPE_AUTH:
2356 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2357 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2358 ieee->iw_mode == IW_MODE_INFRA){
2360 IEEE80211_DEBUG_MGMT("Received authentication response");
2362 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2363 if(ieee->open_wep || !challenge){
2364 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2365 ieee->softmac_stats.rx_auth_rs_ok++;
2366 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2368 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2370 // WEP or TKIP encryption
2371 if(IsHTHalfNmodeAPs(ieee))
2373 bSupportNmode = true;
2374 bHalfSupportNmode = true;
2378 bSupportNmode = false;
2379 bHalfSupportNmode = false;
2381 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2384 /* Dummy wirless mode setting to avoid encryption issue */
2387 ieee->SetWirelessMode(ieee->dev, \
2388 ieee->current_network.mode);
2392 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2395 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2397 printk("===============>entern half N mode\n");
2398 ieee->bHalfWirelessN24GMode = true;
2401 ieee->bHalfWirelessN24GMode = false;
2403 ieee80211_associate_step2(ieee);
2405 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2408 ieee->softmac_stats.rx_auth_rs_err++;
2409 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2411 printk("Authentication respose status code 0x%x",errcode);
2412 ieee80211_associate_abort(ieee);
2415 }else if (ieee->iw_mode == IW_MODE_MASTER){
2416 ieee80211_rx_auth_rq(ieee, skb);
2421 case IEEE80211_STYPE_PROBE_REQ:
2423 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2424 ((ieee->iw_mode == IW_MODE_ADHOC ||
2425 ieee->iw_mode == IW_MODE_MASTER) &&
2426 ieee->state == IEEE80211_LINKED)){
2427 ieee80211_rx_probe_rq(ieee, skb);
2431 case IEEE80211_STYPE_DISASSOC:
2432 case IEEE80211_STYPE_DEAUTH:
2433 /* FIXME for now repeat all the association procedure
2434 * both for disassociation and deauthentication
2436 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2437 ieee->state == IEEE80211_LINKED &&
2438 ieee->iw_mode == IW_MODE_INFRA){
2440 ieee->state = IEEE80211_ASSOCIATING;
2441 ieee->softmac_stats.reassoc++;
2442 ieee->is_roaming = true;
2443 ieee80211_disassociate(ieee);
2444 // notify_wx_assoc_event(ieee);
2445 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2446 RemovePeerTS(ieee, header->addr2);
2447 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2448 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2450 schedule_task(&ieee->associate_procedure_wq);
2454 case IEEE80211_STYPE_MANAGE_ACT:
2455 ieee80211_process_action(ieee,skb);
2462 //dev_kfree_skb_any(skb);
2466 /* following are for a simplier TX queue management.
2467 * Instead of using netif_[stop/wake]_queue the driver
2468 * will uses these two function (plus a reset one), that
2469 * will internally uses the kernel netif_* and takes
2470 * care of the ieee802.11 fragmentation.
2471 * So the driver receives a fragment per time and might
2472 * call the stop function when it want without take care
2473 * to have enough room to TX an entire packet.
2474 * This might be useful if each fragment need it's own
2475 * descriptor, thus just keep a total free memory > than
2476 * the max fragmentation threshold is not enough.. If the
2477 * ieee802.11 stack passed a TXB struct then you needed
2478 * to keep N free descriptors where
2479 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2480 * In this way you need just one and the 802.11 stack
2481 * will take care of buffering fragments and pass them to
2482 * to the driver later, when it wakes the queue.
2484 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2487 unsigned int queue_index = txb->queue_index;
2488 unsigned long flags;
2490 cb_desc *tcb_desc = NULL;
2492 spin_lock_irqsave(&ieee->lock,flags);
2494 /* called with 2nd parm 0, no tx mgmt lock required */
2495 ieee80211_sta_wakeup(ieee,0);
2497 /* update the tx status */
2498 // ieee->stats.tx_bytes += txb->payload_size;
2499 // ieee->stats.tx_packets++;
2500 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2501 if(tcb_desc->bMulticast) {
2502 ieee->stats.multicast++;
2505 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2506 for(i = 0; i < txb->nr_frags; i++) {
2507 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2508 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2510 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2512 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2513 (ieee->queue_stop)) {
2514 /* insert the skb packet to the wait queue */
2515 /* as for the completion function, it does not need
2516 * to check it any more.
2518 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2519 //ieee80211_rtl_stop_queue(ieee);
2520 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2521 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2523 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2526 ieee->softmac_data_hard_start_xmit(
2528 ieee->dev,ieee->rate);
2529 //ieee->stats.tx_packets++;
2530 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2531 //ieee->dev->trans_start = jiffies;
2535 ieee80211_txb_free(txb);
2538 spin_unlock_irqrestore(&ieee->lock,flags);
2542 /* called with ieee->lock acquired */
2543 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2546 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2548 if (ieee->queue_stop){
2549 ieee->tx_pending.frag = i;
2553 ieee->softmac_data_hard_start_xmit(
2554 ieee->tx_pending.txb->fragments[i],
2555 ieee->dev,ieee->rate);
2556 //(i+1)<ieee->tx_pending.txb->nr_frags);
2557 ieee->stats.tx_packets++;
2558 // ieee->dev->trans_start = jiffies;
2563 ieee80211_txb_free(ieee->tx_pending.txb);
2564 ieee->tx_pending.txb = NULL;
2568 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2570 unsigned long flags;
2572 spin_lock_irqsave(&ieee->lock,flags);
2573 init_mgmt_queue(ieee);
2574 if (ieee->tx_pending.txb){
2575 ieee80211_txb_free(ieee->tx_pending.txb);
2576 ieee->tx_pending.txb = NULL;
2578 ieee->queue_stop = 0;
2579 spin_unlock_irqrestore(&ieee->lock,flags);
2583 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2586 unsigned long flags;
2587 struct sk_buff *skb;
2588 struct ieee80211_hdr_3addr *header;
2590 spin_lock_irqsave(&ieee->lock,flags);
2591 if (! ieee->queue_stop) goto exit;
2593 ieee->queue_stop = 0;
2595 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2596 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2598 header = (struct ieee80211_hdr_3addr *) skb->data;
2600 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2602 if (ieee->seq_ctrl[0] == 0xFFF)
2603 ieee->seq_ctrl[0] = 0;
2605 ieee->seq_ctrl[0]++;
2607 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2608 //dev_kfree_skb_any(skb);//edit by thomas
2611 if (!ieee->queue_stop && ieee->tx_pending.txb)
2612 ieee80211_resume_tx(ieee);
2614 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2615 ieee->softmac_stats.swtxawake++;
2616 netif_wake_queue(ieee->dev);
2620 spin_unlock_irqrestore(&ieee->lock,flags);
2624 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2626 //unsigned long flags;
2627 //spin_lock_irqsave(&ieee->lock,flags);
2629 if (! netif_queue_stopped(ieee->dev)){
2630 netif_stop_queue(ieee->dev);
2631 ieee->softmac_stats.swtxstop++;
2633 ieee->queue_stop = 1;
2634 //spin_unlock_irqrestore(&ieee->lock,flags);
2639 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2642 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2644 /* an IBSS cell address must have the two less significant
2645 * bits of the first byte = 2
2647 ieee->current_network.bssid[0] &= ~0x01;
2648 ieee->current_network.bssid[0] |= 0x02;
2651 /* called in user context only */
2652 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2656 if (ieee->current_network.ssid_len == 0){
2657 strncpy(ieee->current_network.ssid,
2658 IEEE80211_DEFAULT_TX_ESSID,
2661 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2665 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2667 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2668 ieee->state = IEEE80211_LINKED;
2669 ieee->link_change(ieee->dev);
2670 notify_wx_assoc_event(ieee);
2672 if (ieee->data_hard_resume)
2673 ieee->data_hard_resume(ieee->dev);
2675 netif_carrier_on(ieee->dev);
2678 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2682 if (ieee->data_hard_resume)
2683 ieee->data_hard_resume(ieee->dev);
2685 netif_carrier_on(ieee->dev);
2688 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2689 void ieee80211_start_ibss_wq(struct work_struct *work)
2692 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2693 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2695 void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2698 /* iwconfig mode ad-hoc will schedule this and return
2699 * on the other hand this will block further iwconfig SET
2700 * operations because of the wx_sem hold.
2701 * Anyway some most set operations set a flag to speed-up
2702 * (abort) this wq (when syncro scanning) before sleeping
2705 if(!ieee->proto_started){
2706 printk("==========oh driver down return\n");
2709 down(&ieee->wx_sem);
2711 if (ieee->current_network.ssid_len == 0){
2712 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2713 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2717 ieee->state = IEEE80211_NOLINK;
2718 /* check if we have this cell in our network list */
2719 ieee80211_softmac_check_all_nets(ieee);
2722 #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.
2723 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2724 if (ieee->state == IEEE80211_NOLINK)
2725 ieee->current_network.channel = 6;
2727 /* if not then the state is not linked. Maybe the user swithced to
2728 * ad-hoc mode just after being in monitor mode, or just after
2729 * being very few time in managed mode (so the card have had no
2730 * time to scan all the chans..) or we have just run up the iface
2731 * after setting ad-hoc mode. So we have to give another try..
2732 * Here, in ibss mode, should be safe to do this without extra care
2733 * (in bss mode we had to make sure no-one tryed to associate when
2734 * we had just checked the ieee->state and we was going to start the
2735 * scan) beacause in ibss mode the ieee80211_new_net function, when
2736 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2737 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2738 * scan, that will stop at the first round because it sees the state
2741 if (ieee->state == IEEE80211_NOLINK)
2742 ieee80211_start_scan_syncro(ieee);
2744 /* the network definitively is not here.. create a new cell */
2745 if (ieee->state == IEEE80211_NOLINK){
2746 printk("creating new IBSS cell\n");
2748 ieee80211_randomize_cell(ieee);
2750 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2752 ieee->current_network.rates_len = 4;
2754 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2755 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2756 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2757 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2760 ieee->current_network.rates_len = 0;
2762 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2763 ieee->current_network.rates_ex_len = 8;
2765 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2766 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2767 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2768 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2769 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2770 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2771 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2772 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2776 ieee->current_network.rates_ex_len = 0;
2780 // By default, WMM function will be disabled in IBSS mode
2781 ieee->current_network.QoS_Enable = 0;
2782 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2783 ieee->current_network.atim_window = 0;
2784 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2785 if(ieee->short_slot)
2786 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2790 ieee->state = IEEE80211_LINKED;
2792 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2793 ieee->link_change(ieee->dev);
2795 notify_wx_assoc_event(ieee);
2797 ieee80211_start_send_beacons(ieee);
2799 if (ieee->data_hard_resume)
2800 ieee->data_hard_resume(ieee->dev);
2801 netif_carrier_on(ieee->dev);
2806 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2808 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2809 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2811 schedule_task(&ieee->start_ibss_wq);
2815 /* this is called only in user context, with wx_sem held */
2816 void ieee80211_start_bss(struct ieee80211_device *ieee)
2818 unsigned long flags;
2819 #ifdef ENABLE_DOT11D
2821 // Ref: 802.11d 11.1.3.3
2822 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2824 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2826 if(! ieee->bGlobalDomain)
2832 /* check if we have already found the net we
2833 * are interested in (if any).
2834 * if not (we are disassociated and we are not
2835 * in associating / authenticating phase) start the background scanning.
2837 ieee80211_softmac_check_all_nets(ieee);
2839 /* ensure no-one start an associating process (thus setting
2840 * the ieee->state to ieee80211_ASSOCIATING) while we
2841 * have just cheked it and we are going to enable scan.
2842 * The ieee80211_new_net function is always called with
2843 * lock held (from both ieee80211_softmac_check_all_nets and
2844 * the rx path), so we cannot be in the middle of such function
2846 spin_lock_irqsave(&ieee->lock, flags);
2848 if (ieee->state == IEEE80211_NOLINK){
2850 if(ieee->ieee80211_ips_leave_wq != NULL)
2851 ieee->ieee80211_ips_leave_wq(ieee->dev);
2853 ieee->actscanning = true;
2854 ieee80211_rtl_start_scan(ieee);
2856 spin_unlock_irqrestore(&ieee->lock, flags);
2859 /* called only in userspace context */
2860 void ieee80211_disassociate(struct ieee80211_device *ieee)
2864 netif_carrier_off(ieee->dev);
2865 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2866 ieee80211_reset_queue(ieee);
2868 if (ieee->data_hard_stop)
2869 ieee->data_hard_stop(ieee->dev);
2870 #ifdef ENABLE_DOT11D
2871 if(IS_DOT11D_ENABLE(ieee))
2874 ieee->state = IEEE80211_NOLINK;
2875 ieee->is_set_key = false;
2876 ieee->link_change(ieee->dev);
2877 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2878 notify_wx_assoc_event(ieee);
2881 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2882 void ieee80211_associate_retry_wq(struct work_struct *work)
2884 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2885 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2887 void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2890 unsigned long flags;
2892 down(&ieee->wx_sem);
2893 if(!ieee->proto_started)
2896 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2899 /* until we do not set the state to IEEE80211_NOLINK
2900 * there are no possibility to have someone else trying
2901 * to start an association procdure (we get here with
2902 * ieee->state = IEEE80211_ASSOCIATING).
2903 * When we set the state to IEEE80211_NOLINK it is possible
2904 * that the RX path run an attempt to associate, but
2905 * both ieee80211_softmac_check_all_nets and the
2906 * RX path works with ieee->lock held so there are no
2907 * problems. If we are still disassociated then start a scan.
2908 * the lock here is necessary to ensure no one try to start
2909 * an association procedure when we have just checked the
2910 * state and we are going to start the scan.
2912 ieee->beinretry = true;
2913 ieee->state = IEEE80211_NOLINK;
2915 ieee80211_softmac_check_all_nets(ieee);
2917 spin_lock_irqsave(&ieee->lock, flags);
2919 if(ieee->state == IEEE80211_NOLINK)
2921 ieee->is_roaming= false;
2922 ieee->actscanning = true;
2923 ieee80211_rtl_start_scan(ieee);
2925 spin_unlock_irqrestore(&ieee->lock, flags);
2927 ieee->beinretry = false;
2932 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2934 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2936 struct sk_buff *skb;
2937 struct ieee80211_probe_response *b;
2939 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2944 b = (struct ieee80211_probe_response *) skb->data;
2945 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2951 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2953 struct sk_buff *skb;
2954 struct ieee80211_probe_response *b;
2956 skb = ieee80211_get_beacon_(ieee);
2960 b = (struct ieee80211_probe_response *) skb->data;
2961 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2963 if (ieee->seq_ctrl[0] == 0xFFF)
2964 ieee->seq_ctrl[0] = 0;
2966 ieee->seq_ctrl[0]++;
2971 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2973 ieee->sync_scan_hurryup = 1;
2974 down(&ieee->wx_sem);
2975 ieee80211_stop_protocol(ieee, shutdown);
2980 void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2982 if (!ieee->proto_started)
2986 ieee->proto_started = 0;
2987 ieee->proto_stoppping = 1;
2989 ieee80211_stop_send_beacons(ieee);
2990 del_timer_sync(&ieee->associate_timer);
2991 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2992 cancel_delayed_work(&ieee->associate_retry_wq);
2993 cancel_delayed_work(&ieee->start_ibss_wq);
2995 ieee80211_stop_scan(ieee);
2997 ieee80211_disassociate(ieee);
2998 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
3000 ieee->proto_stoppping = 0;
3003 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
3005 ieee->sync_scan_hurryup = 0;
3006 down(&ieee->wx_sem);
3007 ieee80211_start_protocol(ieee);
3011 void ieee80211_start_protocol(struct ieee80211_device *ieee)
3015 if (ieee->proto_started)
3018 ieee->proto_started = 1;
3020 if (ieee->current_network.channel == 0){
3023 if (ch > MAX_CHANNEL_NUMBER)
3024 return; /* no channel found */
3025 #ifdef ENABLE_DOT11D
3026 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
3028 }while(!ieee->channel_map[ch]);
3030 ieee->current_network.channel = ch;
3033 if (ieee->current_network.beacon_interval == 0)
3034 ieee->current_network.beacon_interval = 100;
3035 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
3036 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
3038 for(i = 0; i < 17; i++) {
3039 ieee->last_rxseq_num[i] = -1;
3040 ieee->last_rxfrag_num[i] = -1;
3041 ieee->last_packet_time[i] = 0;
3044 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
3046 ieee->state = IEEE80211_NOLINK;
3049 /* if the user set the MAC of the ad-hoc cell and then
3050 * switch to managed mode, shall we make sure that association
3051 * attempts does not fail just because the user provide the essid
3052 * and the nic is still checking for the AP MAC ??
3054 if (ieee->iw_mode == IW_MODE_INFRA)
3055 ieee80211_start_bss(ieee);
3057 else if (ieee->iw_mode == IW_MODE_ADHOC)
3058 ieee80211_start_ibss(ieee);
3060 else if (ieee->iw_mode == IW_MODE_MASTER)
3061 ieee80211_start_master_bss(ieee);
3063 else if(ieee->iw_mode == IW_MODE_MONITOR)
3064 ieee80211_start_monitor_mode(ieee);
3068 #define DRV_NAME "Ieee80211"
3069 void ieee80211_softmac_init(struct ieee80211_device *ieee)
3072 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
3074 ieee->state = IEEE80211_NOLINK;
3075 ieee->sync_scan_hurryup = 0;
3076 for(i = 0; i < 5; i++) {
3077 ieee->seq_ctrl[i] = 0;
3079 #ifdef ENABLE_DOT11D
3080 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
3081 if (!ieee->pDot11dInfo)
3082 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
3083 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
3085 //added for AP roaming
3086 ieee->LinkDetectInfo.SlotNum = 2;
3087 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3088 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3091 ieee->queue_stop = 0;
3093 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
3096 ieee->proto_started = 0;
3097 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
3099 ieee->ps = IEEE80211_PS_DISABLED;
3100 ieee->sta_sleep = 0;
3101 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
3102 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
3103 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
3105 ieee->actscanning = false;
3106 ieee->beinretry = false;
3107 ieee->is_set_key = false;
3108 init_mgmt_queue(ieee);
3110 ieee->sta_edca_param[0] = 0x0000A403;
3111 ieee->sta_edca_param[1] = 0x0000A427;
3112 ieee->sta_edca_param[2] = 0x005E4342;
3113 ieee->sta_edca_param[3] = 0x002F3262;
3114 ieee->aggregation = true;
3115 ieee->enable_rx_imm_BA = 1;
3116 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3117 init_timer(&ieee->scan_timer);
3118 ieee->scan_timer.data = (unsigned long)ieee;
3119 ieee->scan_timer.function = ieee80211_softmac_scan_cb;
3121 ieee->tx_pending.txb = NULL;
3123 init_timer(&ieee->associate_timer);
3124 ieee->associate_timer.data = (unsigned long)ieee;
3125 ieee->associate_timer.function = ieee80211_associate_abort_cb;
3127 init_timer(&ieee->beacon_timer);
3128 ieee->beacon_timer.data = (unsigned long) ieee;
3129 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
3131 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3132 #ifdef PF_SYNCTHREAD
3133 ieee->wq = create_workqueue(DRV_NAME,0);
3135 ieee->wq = create_workqueue(DRV_NAME);
3139 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3140 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3141 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
3142 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
3143 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
3144 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
3145 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
3146 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
3149 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3150 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3151 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3152 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3153 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3154 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3158 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3159 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3160 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3161 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3162 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3163 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3165 sema_init(&ieee->wx_sem, 1);
3166 sema_init(&ieee->scan_sem, 1);
3168 sema_init(&ieee->ips_sem,1);
3170 spin_lock_init(&ieee->mgmt_tx_lock);
3171 spin_lock_init(&ieee->beacon_lock);
3173 tasklet_init(&ieee->ps_task,
3174 (void(*)(unsigned long)) ieee80211_sta_ps,
3175 (unsigned long)ieee);
3179 void ieee80211_softmac_free(struct ieee80211_device *ieee)
3181 down(&ieee->wx_sem);
3182 #ifdef ENABLE_DOT11D
3183 if(NULL != ieee->pDot11dInfo)
3185 kfree(ieee->pDot11dInfo);
3186 ieee->pDot11dInfo = NULL;
3189 del_timer_sync(&ieee->associate_timer);
3191 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3192 cancel_delayed_work(&ieee->associate_retry_wq);
3193 destroy_workqueue(ieee->wq);
3199 /********************************************************
3200 * Start of WPA code. *
3201 * this is stolen from the ipw2200 driver *
3202 ********************************************************/
3205 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3207 /* This is called when wpa_supplicant loads and closes the driver
3209 printk("%s WPA\n",value ? "enabling" : "disabling");
3210 ieee->wpa_enabled = value;
3215 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3217 /* make sure WPA is enabled */
3218 ieee80211_wpa_enable(ieee, 1);
3220 ieee80211_disassociate(ieee);
3224 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3230 case IEEE_MLME_STA_DEAUTH:
3234 case IEEE_MLME_STA_DISASSOC:
3235 ieee80211_disassociate(ieee);
3239 printk("Unknown MLME request: %d\n", command);
3247 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3248 struct ieee_param *param, int plen)
3252 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3253 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3256 if (param->u.wpa_ie.len) {
3257 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
3261 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
3262 kfree(ieee->wpa_ie);
3264 ieee->wpa_ie_len = param->u.wpa_ie.len;
3266 kfree(ieee->wpa_ie);
3267 ieee->wpa_ie = NULL;
3268 ieee->wpa_ie_len = 0;
3271 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3275 #define AUTH_ALG_OPEN_SYSTEM 0x1
3276 #define AUTH_ALG_SHARED_KEY 0x2
3278 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3281 struct ieee80211_security sec = {
3282 .flags = SEC_AUTH_MODE,
3286 if (value & AUTH_ALG_SHARED_KEY) {
3287 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3289 ieee->auth_mode = 1;
3290 } else if (value & AUTH_ALG_OPEN_SYSTEM){
3291 sec.auth_mode = WLAN_AUTH_OPEN;
3293 ieee->auth_mode = 0;
3295 else if (value & IW_AUTH_ALG_LEAP){
3296 sec.auth_mode = WLAN_AUTH_LEAP;
3298 ieee->auth_mode = 2;
3302 if (ieee->set_security)
3303 ieee->set_security(ieee->dev, &sec);
3305 // ret = -EOPNOTSUPP;
3310 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3313 unsigned long flags;
3316 case IEEE_PARAM_WPA_ENABLED:
3317 ret = ieee80211_wpa_enable(ieee, value);
3320 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3321 ieee->tkip_countermeasures=value;
3324 case IEEE_PARAM_DROP_UNENCRYPTED: {
3327 * wpa_supplicant calls set_wpa_enabled when the driver
3328 * is loaded and unloaded, regardless of if WPA is being
3329 * used. No other calls are made which can be used to
3330 * determine if encryption will be used or not prior to
3331 * association being expected. If encryption is not being
3332 * used, drop_unencrypted is set to false, else true -- we
3333 * can use this to determine if the CAP_PRIVACY_ON bit should
3336 struct ieee80211_security sec = {
3337 .flags = SEC_ENABLED,
3340 ieee->drop_unencrypted = value;
3341 /* We only change SEC_LEVEL for open mode. Others
3342 * are set by ipw_wpa_set_encryption.
3345 sec.flags |= SEC_LEVEL;
3346 sec.level = SEC_LEVEL_0;
3349 sec.flags |= SEC_LEVEL;
3350 sec.level = SEC_LEVEL_1;
3352 if (ieee->set_security)
3353 ieee->set_security(ieee->dev, &sec);
3357 case IEEE_PARAM_PRIVACY_INVOKED:
3358 ieee->privacy_invoked=value;
3361 case IEEE_PARAM_AUTH_ALGS:
3362 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3365 case IEEE_PARAM_IEEE_802_1X:
3366 ieee->ieee802_1x=value;
3368 case IEEE_PARAM_WPAX_SELECT:
3369 // added for WPA2 mixed mode
3370 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3371 ieee->wpax_type_set = 1;
3372 ieee->wpax_type_notify = value;
3373 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3377 printk("Unknown WPA param: %d\n",name);
3384 /* implementation borrowed from hostap driver */
3386 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3387 struct ieee_param *param, int param_len)
3391 struct ieee80211_crypto_ops *ops;
3392 struct ieee80211_crypt_data **crypt;
3394 struct ieee80211_security sec = {
3398 param->u.crypt.err = 0;
3399 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3402 (int) ((char *) param->u.crypt.key - (char *) param) +
3403 param->u.crypt.key_len) {
3404 printk("Len mismatch %d, %d\n", param_len,
3405 param->u.crypt.key_len);
3408 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3409 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3410 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3411 if (param->u.crypt.idx >= WEP_KEYS)
3413 crypt = &ieee->crypt[param->u.crypt.idx];
3418 if (strcmp(param->u.crypt.alg, "none") == 0) {
3423 sec.level = SEC_LEVEL_0;
3424 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3425 ieee80211_crypt_delayed_deinit(ieee, crypt);
3432 sec.flags |= SEC_ENABLED;
3434 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3435 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3436 strcmp(param->u.crypt.alg, "TKIP"))
3437 goto skip_host_crypt;
3439 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3440 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3441 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3442 /* set WEP40 first, it will be modified according to WEP104 or
3443 * WEP40 at other place */
3444 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3445 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3446 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3447 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3449 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3450 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3455 if (*crypt == NULL || (*crypt)->ops != ops) {
3456 struct ieee80211_crypt_data *new_crypt;
3458 ieee80211_crypt_delayed_deinit(ieee, crypt);
3460 new_crypt = (struct ieee80211_crypt_data *)
3461 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3462 if (new_crypt == NULL) {
3466 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3467 new_crypt->ops = ops;
3470 new_crypt->ops->init(param->u.crypt.idx);
3472 if (new_crypt->priv == NULL) {
3474 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3482 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3483 (*crypt)->ops->set_key(param->u.crypt.key,
3484 param->u.crypt.key_len, param->u.crypt.seq,
3485 (*crypt)->priv) < 0) {
3486 printk("key setting failed\n");
3487 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3493 if (param->u.crypt.set_tx) {
3494 ieee->tx_keyidx = param->u.crypt.idx;
3495 sec.active_key = param->u.crypt.idx;
3496 sec.flags |= SEC_ACTIVE_KEY;
3498 sec.flags &= ~SEC_ACTIVE_KEY;
3500 if (param->u.crypt.alg != NULL) {
3501 memcpy(sec.keys[param->u.crypt.idx],
3503 param->u.crypt.key_len);
3504 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3505 sec.flags |= (1 << param->u.crypt.idx);
3507 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3508 sec.flags |= SEC_LEVEL;
3509 sec.level = SEC_LEVEL_1;
3510 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3511 sec.flags |= SEC_LEVEL;
3512 sec.level = SEC_LEVEL_2;
3513 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3514 sec.flags |= SEC_LEVEL;
3515 sec.level = SEC_LEVEL_3;
3519 if (ieee->set_security)
3520 ieee->set_security(ieee->dev, &sec);
3522 /* Do not reset port if card is in Managed mode since resetting will
3523 * generate new IEEE 802.11 authentication which may end up in looping
3524 * with IEEE 802.1X. If your hardware requires a reset after WEP
3525 * configuration (for example... Prism2), implement the reset_port in
3526 * the callbacks structures used to initialize the 802.11 stack. */
3527 if (ieee->reset_on_keychange &&
3528 ieee->iw_mode != IW_MODE_INFRA &&
3530 ieee->reset_port(ieee->dev)) {
3531 printk("reset_port failed\n");
3532 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3539 inline struct sk_buff *ieee80211_disassociate_skb(
3540 struct ieee80211_network *beacon,
3541 struct ieee80211_device *ieee,
3544 struct sk_buff *skb;
3545 struct ieee80211_disassoc *disass;
3547 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3551 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3552 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3553 disass->header.duration_id = 0;
3555 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3556 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3557 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3559 disass->reason = asRsn;
3566 struct ieee80211_device *ieee,
3571 struct ieee80211_network *beacon = &ieee->current_network;
3572 struct sk_buff *skb;
3573 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3575 softmac_mgmt_xmit(skb, ieee);
3576 //dev_kfree_skb_any(skb);//edit by thomas
3580 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3582 struct ieee_param *param;
3585 down(&ieee->wx_sem);
3586 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3588 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3593 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3598 if (copy_from_user(param, p->pointer, p->length)) {
3604 switch (param->cmd) {
3606 case IEEE_CMD_SET_WPA_PARAM:
3607 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3608 param->u.wpa_param.value);
3611 case IEEE_CMD_SET_WPA_IE:
3612 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3615 case IEEE_CMD_SET_ENCRYPTION:
3616 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3620 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3621 param->u.mlme.reason_code);
3625 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3630 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3640 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3642 union iwreq_data wrqu;
3643 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3644 if (ieee->state == IEEE80211_LINKED)
3645 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3647 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3648 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3651 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3652 //EXPORT_SYMBOL(ieee80211_get_beacon);
3653 //EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3654 //EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3655 //EXPORT_SYMBOL(ieee80211_reset_queue);
3656 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3657 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3658 //EXPORT_SYMBOL(ieee80211_is_shortslot);
3659 //EXPORT_SYMBOL(ieee80211_is_54g);
3660 //EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3661 //EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3662 //EXPORT_SYMBOL(ieee80211_softmac_xmit);
3663 //EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3664 //EXPORT_SYMBOL(notify_wx_assoc_event);
3665 //EXPORT_SYMBOL(SendDisassociation);
3666 //EXPORT_SYMBOL(ieee80211_disassociate);
3667 //EXPORT_SYMBOL(ieee80211_start_send_beacons);
3668 //EXPORT_SYMBOL(ieee80211_stop_scan);
3669 //EXPORT_SYMBOL(ieee80211_send_probe_requests);
3670 //EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3671 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3673 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3674 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3675 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3676 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3677 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3678 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3679 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3680 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3681 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3682 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3683 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3684 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3685 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3686 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3687 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3688 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3689 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3690 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3691 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3692 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3693 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
3694 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);