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>
25 u8 rsn_authen_cipher_suite[16][4] = {
26 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
27 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
28 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
29 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
30 {0x00,0x0F,0xAC,0x04}, //CCMP
31 {0x00,0x0F,0xAC,0x05}, //WEP-104
34 short ieee80211_is_54g(struct ieee80211_network net)
36 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39 short ieee80211_is_shortslot(struct ieee80211_network net)
41 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
44 /* returns the total length needed for pleacing the RATE MFIE
45 * tag and the EXTENDED RATE MFIE tag if needed.
46 * It encludes two bytes per tag for the tag itself and its len
48 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
50 unsigned int rate_len = 0;
52 if (ieee->modulation & IEEE80211_CCK_MODULATION)
53 rate_len = IEEE80211_CCK_RATE_LEN + 2;
55 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
57 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
62 /* pleace the MFIE rate, tag to the memory (double) poined.
63 * Then it updates the pointer so that
64 * it points after the new MFIE tag added.
66 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
70 if (ieee->modulation & IEEE80211_CCK_MODULATION){
71 *tag++ = MFIE_TYPE_RATES;
73 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
74 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
79 /* We may add an option for custom rates that specific HW might support */
83 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
87 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
89 *tag++ = MFIE_TYPE_RATES_EX;
91 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
102 /* We may add an option for custom rates that specific HW might support */
107 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
110 *tag++ = MFIE_TYPE_GENERIC; //0
119 if(ieee->current_network.wmm_info & 0x80) {
120 *tag++ = 0x0f|MAX_SP_Len;
130 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
133 *tag++ = MFIE_TYPE_GENERIC; //0
144 printk(KERN_ALERT "This is enable turbo mode IE process\n");
147 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
150 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
153 * if the queue is full but we have newer frames then
154 * just overwrites the oldest.
156 * if (nh == ieee->mgmt_queue_tail)
159 ieee->mgmt_queue_head = nh;
160 ieee->mgmt_queue_ring[nh] = skb;
165 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
169 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
172 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
174 ieee->mgmt_queue_tail =
175 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
180 void init_mgmt_queue(struct ieee80211_device *ieee)
182 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
185 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
187 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
190 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
191 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
194 rate = ieee->basic_rate & 0x7f;
197 // 2005.01.26, by rcnjko.
198 if(ieee->mode == IEEE_A||
199 ieee->mode== IEEE_N_5G||
200 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
207 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
208 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
210 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
220 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
222 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
225 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
226 struct ieee80211_hdr_3addr *header=
227 (struct ieee80211_hdr_3addr *) skb->data;
229 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
230 spin_lock_irqsave(&ieee->lock, flags);
232 /* called with 2nd param 0, no mgmt lock required */
233 ieee80211_sta_wakeup(ieee,0);
235 tcb_desc->queue_index = MGNT_QUEUE;
236 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
237 tcb_desc->RATRIndex = 7;
238 tcb_desc->bTxDisableRateFallBack = 1;
239 tcb_desc->bTxUseDriverAssingedRate = 1;
242 if(ieee->queue_stop){
243 enqueue_mgmt(ieee,skb);
245 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
247 if (ieee->seq_ctrl[0] == 0xFFF)
248 ieee->seq_ctrl[0] = 0;
252 /* avoid watchdog triggers */
253 // ieee->dev->trans_start = jiffies;
254 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
255 //dev_kfree_skb_any(skb);//edit by thomas
258 spin_unlock_irqrestore(&ieee->lock, flags);
260 spin_unlock_irqrestore(&ieee->lock, flags);
261 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
263 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
265 if (ieee->seq_ctrl[0] == 0xFFF)
266 ieee->seq_ctrl[0] = 0;
270 /* check wether the managed packet queued greater than 5 */
271 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
272 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
273 (ieee->queue_stop) ) {
274 /* insert the skb packet to the management queue */
275 /* as for the completion function, it does not need
276 * to check it any more.
278 printk("%s():insert to waitqueue!\n",__FUNCTION__);
279 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
281 //printk("TX packet!\n");
282 ieee->softmac_hard_start_xmit(skb,ieee->dev);
283 //dev_kfree_skb_any(skb);//edit by thomas
285 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
289 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
292 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
293 struct ieee80211_hdr_3addr *header =
294 (struct ieee80211_hdr_3addr *) skb->data;
295 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
297 tcb_desc->queue_index = MGNT_QUEUE;
298 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
299 tcb_desc->RATRIndex = 7;
300 tcb_desc->bTxDisableRateFallBack = 1;
301 tcb_desc->bTxUseDriverAssingedRate = 1;
302 //printk("=============>%s()\n", __FUNCTION__);
305 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
307 if (ieee->seq_ctrl[0] == 0xFFF)
308 ieee->seq_ctrl[0] = 0;
312 /* avoid watchdog triggers */
313 // ieee->dev->trans_start = jiffies;
314 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
318 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
320 if (ieee->seq_ctrl[0] == 0xFFF)
321 ieee->seq_ctrl[0] = 0;
325 ieee->softmac_hard_start_xmit(skb,ieee->dev);
328 //dev_kfree_skb_any(skb);//edit by thomas
331 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
333 unsigned int len,rate_len;
336 struct ieee80211_probe_request *req;
338 len = ieee->current_network.ssid_len;
340 rate_len = ieee80211_MFIE_rate_len(ieee);
342 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
343 2 + len + rate_len + ieee->tx_headroom);
347 skb_reserve(skb, ieee->tx_headroom);
349 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
350 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
351 req->header.duration_id = 0; //FIXME: is this OK ?
353 memset(req->header.addr1, 0xff, ETH_ALEN);
354 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
355 memset(req->header.addr3, 0xff, ETH_ALEN);
357 tag = (u8 *) skb_put(skb,len+2+rate_len);
359 *tag++ = MFIE_TYPE_SSID;
361 memcpy(tag, ieee->current_network.ssid, len);
364 ieee80211_MFIE_Brate(ieee,&tag);
365 ieee80211_MFIE_Grate(ieee,&tag);
369 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
370 void ieee80211_send_beacon(struct ieee80211_device *ieee)
375 //unsigned long flags;
376 skb = ieee80211_get_beacon_(ieee);
379 softmac_mgmt_xmit(skb, ieee);
380 ieee->softmac_stats.tx_beacons++;
381 //dev_kfree_skb_any(skb);//edit by thomas
383 // ieee->beacon_timer.expires = jiffies +
384 // (MSECS( ieee->current_network.beacon_interval -5));
386 //spin_lock_irqsave(&ieee->beacon_lock,flags);
387 if(ieee->beacon_txing && ieee->ieee_up){
388 // if(!timer_pending(&ieee->beacon_timer))
389 // add_timer(&ieee->beacon_timer);
390 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
392 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
396 void ieee80211_send_beacon_cb(unsigned long _ieee)
398 struct ieee80211_device *ieee =
399 (struct ieee80211_device *) _ieee;
402 spin_lock_irqsave(&ieee->beacon_lock, flags);
403 ieee80211_send_beacon(ieee);
404 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
408 void ieee80211_send_probe(struct ieee80211_device *ieee)
412 skb = ieee80211_probe_req(ieee);
414 softmac_mgmt_xmit(skb, ieee);
415 ieee->softmac_stats.tx_probe_rq++;
416 //dev_kfree_skb_any(skb);//edit by thomas
420 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
422 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
423 ieee80211_send_probe(ieee);
424 ieee80211_send_probe(ieee);
428 /* this performs syncro scan blocking the caller until all channels
429 * in the allowed channel map has been checked.
431 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
434 u8 channel_map[MAX_CHANNEL_NUMBER+1];
435 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
436 ieee->be_scan_inprogress = true;
437 down(&ieee->scan_sem);
444 if (ch > MAX_CHANNEL_NUMBER)
445 goto out; /* scan completed */
446 }while(!channel_map[ch]);
448 /* this fuction can be called in two situations
449 * 1- We have switched to ad-hoc mode and we are
450 * performing a complete syncro scan before conclude
451 * there are no interesting cell and to create a
452 * new one. In this case the link state is
453 * IEEE80211_NOLINK until we found an interesting cell.
454 * If so the ieee8021_new_net, called by the RX path
455 * will set the state to IEEE80211_LINKED, so we stop
457 * 2- We are linked and the root uses run iwlist scan.
458 * So we switch to IEEE80211_LINKED_SCANNING to remember
459 * that we are still logically linked (not interested in
460 * new network events, despite for updating the net list,
461 * but we are temporarly 'unlinked' as the driver shall
462 * not filter RX frames and the channel is changing.
463 * So the only situation in witch are interested is to check
464 * if the state become LINKED because of the #1 situation
467 if (ieee->state == IEEE80211_LINKED)
469 ieee->set_chan(ieee->dev, ch);
470 if(channel_map[ch] == 1)
471 ieee80211_send_probe_requests(ieee);
473 /* this prevent excessive time wait when we
474 * need to wait for a syncro scan to end..
476 if(ieee->state < IEEE80211_LINKED)
479 if (ieee->sync_scan_hurryup)
483 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
487 if(ieee->state < IEEE80211_LINKED){
488 ieee->actscanning = false;
490 ieee->be_scan_inprogress = false;
493 ieee->sync_scan_hurryup = 0;
494 if(IS_DOT11D_ENABLE(ieee))
495 DOT11D_ScanComplete(ieee);
497 ieee->be_scan_inprogress = false;
501 void ieee80211_softmac_scan_wq(struct work_struct *work)
503 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
504 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
505 u8 last_channel = ieee->current_network.channel; //recored init channel inorder not change current channel when comming out the scan unexpectedly. WB.
506 u8 channel_map[MAX_CHANNEL_NUMBER+1];
507 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
510 down(&ieee->scan_sem);
512 ieee->current_network.channel =
513 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
514 if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER)
516 //if current channel is not in channel map, set to default channel.
517 if (!channel_map[ieee->current_network.channel]);
518 ieee->current_network.channel = 6;
519 goto out; /* no good chans */
521 }while(!channel_map[ieee->current_network.channel]);
522 if (ieee->scanning == 0 )
524 ieee->set_chan(ieee->dev, ieee->current_network.channel);
525 if(channel_map[ieee->current_network.channel] == 1)
526 ieee80211_send_probe_requests(ieee);
528 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
533 if(IS_DOT11D_ENABLE(ieee))
534 DOT11D_ScanComplete(ieee);
535 ieee->current_network.channel = last_channel;
536 ieee->actscanning = false;
537 ieee->scan_watch_dog = 0;
542 void ieee80211_beacons_start(struct ieee80211_device *ieee)
545 spin_lock_irqsave(&ieee->beacon_lock,flags);
547 ieee->beacon_txing = 1;
548 ieee80211_send_beacon(ieee);
550 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
553 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
557 spin_lock_irqsave(&ieee->beacon_lock,flags);
559 ieee->beacon_txing = 0;
560 del_timer_sync(&ieee->beacon_timer);
562 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
567 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
569 if(ieee->stop_send_beacons)
570 ieee->stop_send_beacons(ieee->dev);
571 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
572 ieee80211_beacons_stop(ieee);
576 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
578 if(ieee->start_send_beacons)
579 ieee->start_send_beacons(ieee->dev);
580 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
581 ieee80211_beacons_start(ieee);
585 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
587 // unsigned long flags;
589 //ieee->sync_scan_hurryup = 1;
591 down(&ieee->scan_sem);
592 // spin_lock_irqsave(&ieee->lock, flags);
593 ieee->scan_watch_dog = 0;
594 if (ieee->scanning == 1){
597 cancel_delayed_work(&ieee->softmac_scan_wq);
600 // spin_unlock_irqrestore(&ieee->lock, flags);
604 void ieee80211_stop_scan(struct ieee80211_device *ieee)
606 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
607 ieee80211_softmac_stop_scan(ieee);
609 ieee->stop_scan(ieee->dev);
612 /* called with ieee->lock held */
613 void ieee80211_start_scan(struct ieee80211_device *ieee)
615 if(IS_DOT11D_ENABLE(ieee) )
617 if(IS_COUNTRY_IE_VALID(ieee))
619 RESET_CIE_WATCHDOG(ieee);
622 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
623 if (ieee->scanning == 0){
625 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
628 ieee->start_scan(ieee->dev);
632 /* called with wx_sem held */
633 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
635 if(IS_DOT11D_ENABLE(ieee) )
637 if(IS_COUNTRY_IE_VALID(ieee))
639 RESET_CIE_WATCHDOG(ieee);
642 ieee->sync_scan_hurryup = 0;
643 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
644 ieee80211_softmac_scan_syncro(ieee);
646 ieee->scan_syncro(ieee->dev);
650 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
651 struct ieee80211_device *ieee, int challengelen)
654 struct ieee80211_authentication *auth;
655 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
658 skb = dev_alloc_skb(len);
659 if (!skb) return NULL;
661 skb_reserve(skb, ieee->tx_headroom);
662 auth = (struct ieee80211_authentication *)
663 skb_put(skb, sizeof(struct ieee80211_authentication));
665 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
666 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
668 auth->header.duration_id = 0x013a; //FIXME
670 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
671 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
672 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
674 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
675 if(ieee->auth_mode == 0)
676 auth->algorithm = WLAN_AUTH_OPEN;
677 else if(ieee->auth_mode == 1)
678 auth->algorithm = WLAN_AUTH_SHARED_KEY;
679 else if(ieee->auth_mode == 2)
680 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
681 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
682 auth->transaction = cpu_to_le16(ieee->associate_seq);
683 ieee->associate_seq++;
685 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
692 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
696 struct ieee80211_probe_response *beacon_buf;
697 struct sk_buff *skb = NULL;
699 int atim_len,erp_len;
700 struct ieee80211_crypt_data* crypt;
702 char *ssid = ieee->current_network.ssid;
703 int ssid_len = ieee->current_network.ssid_len;
704 int rate_len = ieee->current_network.rates_len+2;
705 int rate_ex_len = ieee->current_network.rates_ex_len;
706 int wpa_ie_len = ieee->wpa_ie_len;
707 u8 erpinfo_content = 0;
712 u8 tmp_ht_info_len=0;
713 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
714 u8* tmp_generic_ie_buf=NULL;
715 u8 tmp_generic_ie_len=0;
717 if(rate_ex_len > 0) rate_ex_len+=2;
719 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
725 if(ieee80211_is_54g(ieee->current_network))
730 if((ieee->current_network.mode == IEEE_G)
731 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
734 if(ieee->current_network.buseprotection)
735 erpinfo_content |= ERP_UseProtection;
742 crypt = ieee->crypt[ieee->tx_keyidx];
745 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
746 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
749 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
750 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
751 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
752 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
753 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
754 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
757 if(pHTInfo->bRegRT2RTAggregation)
759 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
760 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
761 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
763 // 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);
765 beacon_size = sizeof(struct ieee80211_probe_response)+2+
775 // +tmp_generic_ie_len
778 skb = dev_alloc_skb(beacon_size);
781 skb_reserve(skb, ieee->tx_headroom);
782 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
783 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
784 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
785 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
787 beacon_buf->header.duration_id = 0; //FIXME
788 beacon_buf->beacon_interval =
789 cpu_to_le16(ieee->current_network.beacon_interval);
790 beacon_buf->capability =
791 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
792 beacon_buf->capability |=
793 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
795 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
796 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
798 crypt = ieee->crypt[ieee->tx_keyidx];
801 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
804 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
805 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
806 beacon_buf->info_element[0].len = ssid_len;
808 tag = (u8*) beacon_buf->info_element[0].data;
810 memcpy(tag, ssid, ssid_len);
814 *(tag++) = MFIE_TYPE_RATES;
815 *(tag++) = rate_len-2;
816 memcpy(tag,ieee->current_network.rates,rate_len-2);
819 *(tag++) = MFIE_TYPE_DS_SET;
821 *(tag++) = ieee->current_network.channel;
825 *(tag++) = MFIE_TYPE_IBSS_SET;
827 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
828 val16 = cpu_to_le16(ieee->current_network.atim_window);
829 memcpy((u8 *)tag, (u8 *)&val16, 2);
834 *(tag++) = MFIE_TYPE_ERP;
836 *(tag++) = erpinfo_content;
840 *(tag++) = MFIE_TYPE_RATES_EX;
841 *(tag++) = rate_ex_len-2;
842 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
848 if (ieee->iw_mode == IW_MODE_ADHOC)
849 {//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
850 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
852 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
856 //skb->dev = ieee->dev;
861 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
866 struct ieee80211_crypt_data* crypt;
867 struct ieee80211_assoc_response_frame *assoc;
870 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
871 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
873 skb = dev_alloc_skb(len);
878 skb_reserve(skb, ieee->tx_headroom);
880 assoc = (struct ieee80211_assoc_response_frame *)
881 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
883 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
884 memcpy(assoc->header.addr1, dest,ETH_ALEN);
885 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
886 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
887 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
888 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
892 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
894 if (ieee->host_encrypt)
895 crypt = ieee->crypt[ieee->tx_keyidx];
898 encrypt = ( crypt && crypt->ops);
901 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
904 assoc->aid = cpu_to_le16(ieee->assoc_id);
905 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
906 else ieee->assoc_id++;
908 tag = (u8*) skb_put(skb, rate_len);
910 ieee80211_MFIE_Brate(ieee, &tag);
911 ieee80211_MFIE_Grate(ieee, &tag);
916 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
919 struct ieee80211_authentication *auth;
920 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
922 skb = dev_alloc_skb(len);
927 skb->len = sizeof(struct ieee80211_authentication);
929 auth = (struct ieee80211_authentication *)skb->data;
931 auth->status = cpu_to_le16(status);
932 auth->transaction = cpu_to_le16(2);
933 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
935 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
936 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
937 memcpy(auth->header.addr1, dest, ETH_ALEN);
938 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
944 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
947 struct ieee80211_hdr_3addr* hdr;
949 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
954 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
956 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
957 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
958 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
960 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
961 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
962 (pwr ? IEEE80211_FCTL_PM:0));
970 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
972 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
975 softmac_mgmt_xmit(buf, ieee);
979 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
981 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
984 softmac_mgmt_xmit(buf, ieee);
988 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
992 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
994 softmac_mgmt_xmit(buf, ieee);
998 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1000 struct sk_buff *skb;
1001 //unsigned long flags;
1003 struct ieee80211_assoc_request_frame *hdr;
1005 //short info_addr = 0;
1007 //u16 suite_count = 0;
1008 //u8 suit_select = 0;
1009 //unsigned int wpa_len = beacon->wpa_ie_len;
1011 u8* ht_cap_buf = NULL;
1013 u8* realtek_ie_buf=NULL;
1014 u8 realtek_ie_len=0;
1015 int wpa_ie_len= ieee->wpa_ie_len;
1016 unsigned int ckip_ie_len=0;
1017 unsigned int ccxrm_ie_len=0;
1018 unsigned int cxvernum_ie_len=0;
1019 struct ieee80211_crypt_data* crypt;
1022 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1023 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1024 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1028 crypt = ieee->crypt[ieee->tx_keyidx];
1029 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1031 //Include High Throuput capability && Realtek proprietary
1032 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1034 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1035 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1036 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1037 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1039 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1040 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1041 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1045 if(ieee->qos_support){
1046 wmm_info_len = beacon->qos_data.supported?9:0;
1050 if(beacon->bCkipSupported)
1054 if(beacon->bCcxRmEnable)
1058 if( beacon->BssCcxVerNumber >= 2 )
1060 cxvernum_ie_len = 5+2;
1062 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1063 + beacon->ssid_len//essid tagged val
1064 + rate_len//rates tagged val
1073 + ieee->tx_headroom;
1075 skb = dev_alloc_skb(len);
1080 skb_reserve(skb, ieee->tx_headroom);
1082 hdr = (struct ieee80211_assoc_request_frame *)
1083 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1086 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1087 hdr->header.duration_id= 37; //FIXME
1088 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1089 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1090 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1092 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1094 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1095 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1096 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1098 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1099 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1101 if(ieee->short_slot)
1102 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1103 if (wmm_info_len) //QOS
1104 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1106 hdr->listen_interval = 0xa; //FIXME
1108 hdr->info_element[0].id = MFIE_TYPE_SSID;
1110 hdr->info_element[0].len = beacon->ssid_len;
1111 tag = skb_put(skb, beacon->ssid_len);
1112 memcpy(tag, beacon->ssid, beacon->ssid_len);
1114 tag = skb_put(skb, rate_len);
1116 ieee80211_MFIE_Brate(ieee, &tag);
1117 ieee80211_MFIE_Grate(ieee, &tag);
1118 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1119 if( beacon->bCkipSupported )
1121 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1122 u8 CcxAironetBuf[30];
1123 OCTET_STRING osCcxAironetIE;
1125 memset(CcxAironetBuf, 0,30);
1126 osCcxAironetIE.Octet = CcxAironetBuf;
1127 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1129 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1130 // We want to make the device type as "4500-client". 060926, by CCW.
1132 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1134 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1135 // "The CKIP negotiation is started with the associate request from the client to the access point,
1136 // containing an Aironet element with both the MIC and KP bits set."
1137 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1138 tag = skb_put(skb, ckip_ie_len);
1139 *tag++ = MFIE_TYPE_AIRONET;
1140 *tag++ = osCcxAironetIE.Length;
1141 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1142 tag += osCcxAironetIE.Length;
1145 if(beacon->bCcxRmEnable)
1147 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1148 OCTET_STRING osCcxRmCap;
1150 osCcxRmCap.Octet = CcxRmCapBuf;
1151 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1152 tag = skb_put(skb,ccxrm_ie_len);
1153 *tag++ = MFIE_TYPE_GENERIC;
1154 *tag++ = osCcxRmCap.Length;
1155 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1156 tag += osCcxRmCap.Length;
1159 if( beacon->BssCcxVerNumber >= 2 )
1161 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1162 OCTET_STRING osCcxVerNum;
1163 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1164 osCcxVerNum.Octet = CcxVerNumBuf;
1165 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1166 tag = skb_put(skb,cxvernum_ie_len);
1167 *tag++ = MFIE_TYPE_GENERIC;
1168 *tag++ = osCcxVerNum.Length;
1169 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1170 tag += osCcxVerNum.Length;
1173 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1174 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1176 tag = skb_put(skb, ht_cap_len);
1177 *tag++ = MFIE_TYPE_HT_CAP;
1178 *tag++ = ht_cap_len - 2;
1179 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1180 tag += ht_cap_len -2;
1185 //choose what wpa_supplicant gives to associate.
1186 tag = skb_put(skb, wpa_ie_len);
1188 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1191 tag = skb_put(skb,wmm_info_len);
1193 ieee80211_WMM_Info(ieee, &tag);
1195 tag = skb_put(skb,turbo_info_len);
1196 if(turbo_info_len) {
1197 ieee80211_TURBO_Info(ieee, &tag);
1200 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1201 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1203 tag = skb_put(skb, ht_cap_len);
1204 *tag++ = MFIE_TYPE_GENERIC;
1205 *tag++ = ht_cap_len - 2;
1206 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1207 tag += ht_cap_len -2;
1210 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1211 tag = skb_put(skb, realtek_ie_len);
1212 *tag++ = MFIE_TYPE_GENERIC;
1213 *tag++ = realtek_ie_len - 2;
1214 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1217 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1218 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1222 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1225 unsigned long flags;
1226 spin_lock_irqsave(&ieee->lock, flags);
1228 ieee->associate_seq++;
1230 /* don't scan, and avoid to have the RX path possibily
1231 * try again to associate. Even do not react to AUTH or
1232 * ASSOC response. Just wait for the retry wq to be scheduled.
1233 * Here we will check if there are good nets to associate
1234 * with, so we retry or just get back to NO_LINK and scanning
1236 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1237 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1238 ieee->softmac_stats.no_auth_rs++;
1240 IEEE80211_DEBUG_MGMT("Association failed\n");
1241 ieee->softmac_stats.no_ass_rs++;
1244 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1246 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1247 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1249 spin_unlock_irqrestore(&ieee->lock, flags);
1252 void ieee80211_associate_abort_cb(unsigned long dev)
1254 ieee80211_associate_abort((struct ieee80211_device *) dev);
1258 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1260 struct ieee80211_network *beacon = &ieee->current_network;
1261 struct sk_buff *skb;
1263 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1265 ieee->softmac_stats.tx_auth_rq++;
1266 skb=ieee80211_authentication_req(beacon, ieee, 0);
1269 ieee80211_associate_abort(ieee);
1271 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1272 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1273 //printk(KERN_WARNING "Sending authentication request\n");
1274 softmac_mgmt_xmit(skb, ieee);
1275 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1276 if(!timer_pending(&ieee->associate_timer)){
1277 ieee->associate_timer.expires = jiffies + (HZ / 2);
1278 add_timer(&ieee->associate_timer);
1280 //dev_kfree_skb_any(skb);//edit by thomas
1284 void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1287 struct sk_buff *skb;
1288 struct ieee80211_network *beacon = &ieee->current_network;
1289 // int hlen = sizeof(struct ieee80211_authentication);
1291 ieee->associate_seq++;
1292 ieee->softmac_stats.tx_auth_rq++;
1294 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1296 ieee80211_associate_abort(ieee);
1298 c = skb_put(skb, chlen+2);
1299 *(c++) = MFIE_TYPE_CHALLENGE;
1301 memcpy(c, challenge, chlen);
1303 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1305 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1307 softmac_mgmt_xmit(skb, ieee);
1308 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1309 //dev_kfree_skb_any(skb);//edit by thomas
1314 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1316 struct sk_buff* skb;
1317 struct ieee80211_network *beacon = &ieee->current_network;
1319 del_timer_sync(&ieee->associate_timer);
1321 IEEE80211_DEBUG_MGMT("Sending association request\n");
1323 ieee->softmac_stats.tx_ass_rq++;
1324 skb=ieee80211_association_req(beacon, ieee);
1326 ieee80211_associate_abort(ieee);
1328 softmac_mgmt_xmit(skb, ieee);
1329 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1330 //dev_kfree_skb_any(skb);//edit by thomas
1334 void ieee80211_associate_complete_wq(struct work_struct *work)
1336 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1338 printk(KERN_INFO "Associated successfully\n");
1339 ieee->is_roaming = false;
1340 if(ieee80211_is_54g(ieee->current_network) &&
1341 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1344 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1347 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1349 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1351 printk("Successfully associated, ht enabled\n");
1356 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1357 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1358 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1360 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1361 // To prevent the immediately calling watch_dog after association.
1362 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1364 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1365 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1367 ieee->link_change(ieee->dev);
1368 if(ieee->is_silent_reset == 0){
1369 printk("============>normal associate\n");
1370 notify_wx_assoc_event(ieee);
1372 else if(ieee->is_silent_reset == 1)
1374 printk("==================>silent reset associate\n");
1375 ieee->is_silent_reset = 0;
1378 if (ieee->data_hard_resume)
1379 ieee->data_hard_resume(ieee->dev);
1380 netif_carrier_on(ieee->dev);
1383 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1386 // struct net_device* dev = ieee->dev;
1387 del_timer_sync(&ieee->associate_timer);
1389 ieee->state = IEEE80211_LINKED;
1390 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1391 queue_work(ieee->wq, &ieee->associate_complete_wq);
1394 void ieee80211_associate_procedure_wq(struct work_struct *work)
1396 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1398 ieee->sync_scan_hurryup = 1;
1399 down(&ieee->wx_sem);
1401 if (ieee->data_hard_stop)
1402 ieee->data_hard_stop(ieee->dev);
1404 ieee80211_stop_scan(ieee);
1405 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1406 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1407 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1409 ieee->associate_seq = 1;
1410 ieee80211_associate_step1(ieee);
1415 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1417 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1418 int tmp_ssid_len = 0;
1420 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1422 /* we are interested in new new only if we are not associated
1423 * and we are not associating / authenticating
1425 if (ieee->state != IEEE80211_NOLINK)
1428 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1431 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1435 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1436 /* if the user specified the AP MAC, we need also the essid
1437 * This could be obtained by beacons or, if the network does not
1438 * broadcast it, it can be put manually.
1440 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1441 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1442 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1443 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1444 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1445 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1448 if ( /* if the user set the AP check if match.
1449 * if the network does not broadcast essid we check the user supplyed ANY essid
1450 * if the network does broadcast and the user does not set essid it is OK
1451 * if the network does broadcast and the user did set essid chech if essid match
1453 ( apset && apmatch &&
1454 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1455 /* if the ap is not set, check that the user set the bssid
1456 * and the network does bradcast and that those two bssid matches
1458 (!apset && ssidset && ssidbroad && ssidmatch)
1460 /* if the essid is hidden replace it with the
1461 * essid provided by the user.
1464 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1465 tmp_ssid_len = ieee->current_network.ssid_len;
1467 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1470 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1471 ieee->current_network.ssid_len = tmp_ssid_len;
1473 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT, ieee->current_network.mode);
1475 //ieee->pHTInfo->IOTAction = 0;
1476 HTResetIOTSetting(ieee->pHTInfo);
1477 if (ieee->iw_mode == IW_MODE_INFRA){
1478 /* Join the network for the first time */
1479 ieee->AsocRetryCount = 0;
1480 //for HT by amy 080514
1481 if((ieee->current_network.qos_data.supported == 1) &&
1482 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1483 ieee->current_network.bssht.bdSupportHT)
1484 /*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.*/
1486 // ieee->pHTInfo->bCurrentHTSupport = true;
1487 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1491 ieee->pHTInfo->bCurrentHTSupport = false;
1494 ieee->state = IEEE80211_ASSOCIATING;
1495 if(ieee->LedControlHandler != NULL)
1496 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK);
1497 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1499 if(ieee80211_is_54g(ieee->current_network) &&
1500 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1502 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1503 printk(KERN_INFO"Using G rates\n");
1506 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1507 printk(KERN_INFO"Using B rates\n");
1509 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1510 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1511 ieee->state = IEEE80211_LINKED;
1519 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1521 unsigned long flags;
1522 struct ieee80211_network *target;
1524 spin_lock_irqsave(&ieee->lock, flags);
1526 list_for_each_entry(target, &ieee->network_list, list) {
1528 /* if the state become different that NOLINK means
1529 * we had found what we are searching for
1532 if (ieee->state != IEEE80211_NOLINK)
1535 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1536 ieee80211_softmac_new_net(ieee, target);
1539 spin_unlock_irqrestore(&ieee->lock, flags);
1544 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1546 struct ieee80211_authentication *a;
1548 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1549 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1553 a = (struct ieee80211_authentication*) skb->data;
1554 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1555 t = skb->data + sizeof(struct ieee80211_authentication);
1557 if(*(t++) == MFIE_TYPE_CHALLENGE){
1559 *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1560 memcpy(*challenge, t, *chlen);
1564 return cpu_to_le16(a->status);
1569 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1571 struct ieee80211_authentication *a;
1573 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1574 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1577 a = (struct ieee80211_authentication*) skb->data;
1579 memcpy(dest,a->header.addr2, ETH_ALEN);
1581 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1582 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1584 return WLAN_STATUS_SUCCESS;
1587 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1594 struct ieee80211_hdr_3addr *header =
1595 (struct ieee80211_hdr_3addr *) skb->data;
1597 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1598 return -1; /* corrupted */
1600 memcpy(src,header->addr2, ETH_ALEN);
1602 skbend = (u8*)skb->data + skb->len;
1604 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1606 while (tag+1 < skbend){
1612 tag++; /* point to the len field */
1613 tag = tag + *(tag); /* point to the last data byte of the tag */
1614 tag++; /* point to the next tag */
1617 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1618 if (ssidlen == 0) return 1;
1620 if (!ssid) return 1; /* ssid not found in tagged param */
1621 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1625 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1627 struct ieee80211_assoc_request_frame *a;
1629 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1630 sizeof(struct ieee80211_info_element))) {
1632 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1636 a = (struct ieee80211_assoc_request_frame*) skb->data;
1638 memcpy(dest,a->header.addr2,ETH_ALEN);
1643 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1645 struct ieee80211_assoc_response_frame *response_head;
1648 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1649 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1653 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1654 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1656 status_code = le16_to_cpu(response_head->status);
1657 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1658 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1659 ((ieee->mode == IEEE_G) &&
1660 (ieee->current_network.mode == IEEE_N_24G) &&
1661 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1662 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1664 ieee->AsocRetryCount = 0;
1667 return le16_to_cpu(response_head->status);
1671 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1675 //IEEE80211DMESG("Rx probe");
1676 ieee->softmac_stats.rx_probe_rq++;
1677 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1678 if (probe_rq_parse(ieee, skb, dest)){
1679 //IEEE80211DMESG("Was for me!");
1680 ieee->softmac_stats.tx_probe_rs++;
1681 ieee80211_resp_to_probe(ieee, dest);
1686 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1690 //IEEE80211DMESG("Rx probe");
1691 ieee->softmac_stats.rx_auth_rq++;
1693 if ((status = auth_rq_parse(skb, dest))!= -1){
1694 ieee80211_resp_to_auth(ieee, status, dest);
1696 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1701 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1705 //unsigned long flags;
1707 ieee->softmac_stats.rx_ass_rq++;
1708 if (assoc_rq_parse(skb,dest) != -1){
1709 ieee80211_resp_to_assoc_rq(ieee, dest);
1712 printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
1718 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1721 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1724 softmac_ps_mgmt_xmit(buf, ieee);
1729 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1731 int timeout = ieee->ps_timeout;
1733 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1734 ieee->iw_mode != IW_MODE_INFRA ||
1735 ieee->state != IEEE80211_LINKED)
1739 dtim = ieee->current_network.dtim_data;
1741 if(!(dtim & IEEE80211_DTIM_VALID))
1743 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1744 //printk("VALID\n");
1745 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1747 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1750 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1753 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1756 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1757 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1761 *time_l = ieee->current_network.last_dtim_sta_time[0]
1762 + (ieee->current_network.beacon_interval);
1763 // * ieee->current_network.dtim_period) * 1000;
1767 *time_h = ieee->current_network.last_dtim_sta_time[1];
1768 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1777 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1783 unsigned long flags,flags2;
1785 spin_lock_irqsave(&ieee->lock, flags);
1787 if((ieee->ps == IEEE80211_PS_DISABLED ||
1788 ieee->iw_mode != IW_MODE_INFRA ||
1789 ieee->state != IEEE80211_LINKED)){
1791 // #warning CHECK_LOCK_HERE
1792 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1794 ieee80211_sta_wakeup(ieee, 1);
1796 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1799 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1800 /* 2 wake, 1 sleep, 0 do nothing */
1806 if(ieee->sta_sleep == 1)
1807 ieee->enter_sleep_state(ieee->dev,th,tl);
1809 else if(ieee->sta_sleep == 0){
1810 // printk("send null 1\n");
1811 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1813 if(ieee->ps_is_queue_empty(ieee->dev)){
1816 ieee->sta_sleep = 2;
1818 ieee->ack_tx_to_ieee = 1;
1820 ieee80211_sta_ps_send_null_frame(ieee,1);
1825 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1830 }else if(sleep == 2){
1831 //#warning CHECK_LOCK_HERE
1832 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1834 ieee80211_sta_wakeup(ieee,1);
1836 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1840 spin_unlock_irqrestore(&ieee->lock, flags);
1844 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1846 if(ieee->sta_sleep == 0){
1848 printk("Warning: driver is probably failing to report TX ps error\n");
1849 ieee->ack_tx_to_ieee = 1;
1850 ieee80211_sta_ps_send_null_frame(ieee, 0);
1856 if(ieee->sta_sleep == 1)
1857 ieee->sta_wake_up(ieee->dev);
1859 ieee->sta_sleep = 0;
1862 ieee->ack_tx_to_ieee = 1;
1863 ieee80211_sta_ps_send_null_frame(ieee, 0);
1867 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1869 unsigned long flags,flags2;
1871 spin_lock_irqsave(&ieee->lock, flags);
1873 if(ieee->sta_sleep == 2){
1874 /* Null frame with PS bit set */
1876 ieee->sta_sleep = 1;
1877 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1879 /* if the card report not success we can't be sure the AP
1880 * has not RXed so we can't assume the AP believe us awake
1883 /* 21112005 - tx again null without PS bit if lost */
1886 if((ieee->sta_sleep == 0) && !success){
1887 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1888 ieee80211_sta_ps_send_null_frame(ieee, 0);
1889 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1892 spin_unlock_irqrestore(&ieee->lock, flags);
1894 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1896 struct rtl_ieee80211_hdr *header =
1897 (struct rtl_ieee80211_hdr *)skb->data;
1898 u8* act = ieee80211_get_payload(header);
1900 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1903 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1911 if (*act == ACT_ADDBAREQ)
1912 ieee80211_rx_ADDBAReq(ieee, skb);
1913 else if (*act == ACT_ADDBARSP)
1914 ieee80211_rx_ADDBARsp(ieee, skb);
1915 else if (*act == ACT_DELBA)
1916 ieee80211_rx_DELBA(ieee, skb);
1919 // if (net_ratelimit())
1920 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
1927 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1928 struct ieee80211_rx_stats *rx_stats, u16 type,
1931 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1936 struct ieee80211_assoc_response_frame *assoc_resp;
1937 // struct ieee80211_info_element *info_element;
1938 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1940 if(!ieee->proto_started)
1943 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1945 case IEEE80211_STYPE_ASSOC_RESP:
1946 case IEEE80211_STYPE_REASSOC_RESP:
1948 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1949 WLAN_FC_GET_STYPE(header->frame_ctl));
1950 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1951 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1952 ieee->iw_mode == IW_MODE_INFRA){
1953 struct ieee80211_network network_resp;
1954 struct ieee80211_network *network = &network_resp;
1956 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
1957 ieee->state=IEEE80211_LINKED;
1958 ieee->assoc_id = aid;
1959 ieee->softmac_stats.rx_ass_ok++;
1960 /* station support qos */
1961 /* Let the register setting defaultly with Legacy station */
1962 if(ieee->qos_support) {
1963 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
1964 memset(network, 0, sizeof(*network));
1965 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1966 rx_stats->len - sizeof(*assoc_resp),\
1971 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
1972 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1973 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1975 if (ieee->handle_assoc_response != NULL)
1976 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
1978 ieee80211_associate_complete(ieee);
1980 /* aid could not been allocated */
1981 ieee->softmac_stats.rx_ass_err++;
1983 "Association response status code 0x%x\n",
1985 IEEE80211_DEBUG_MGMT(
1986 "Association response status code 0x%x\n",
1988 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
1989 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1991 ieee80211_associate_abort(ieee);
1997 case IEEE80211_STYPE_ASSOC_REQ:
1998 case IEEE80211_STYPE_REASSOC_REQ:
2000 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2001 ieee->iw_mode == IW_MODE_MASTER)
2003 ieee80211_rx_assoc_rq(ieee, skb);
2006 case IEEE80211_STYPE_AUTH:
2008 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2009 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2010 ieee->iw_mode == IW_MODE_INFRA){
2012 IEEE80211_DEBUG_MGMT("Received authentication response");
2014 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2015 if(ieee->open_wep || !challenge){
2016 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2017 ieee->softmac_stats.rx_auth_rs_ok++;
2018 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2020 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2022 // WEP or TKIP encryption
2023 if(IsHTHalfNmodeAPs(ieee))
2025 bSupportNmode = true;
2026 bHalfSupportNmode = true;
2030 bSupportNmode = false;
2031 bHalfSupportNmode = false;
2033 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2036 /* Dummy wirless mode setting to avoid encryption issue */
2039 ieee->SetWirelessMode(ieee->dev, \
2040 ieee->current_network.mode);
2044 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2047 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2049 printk("===============>entern half N mode\n");
2050 ieee->bHalfWirelessN24GMode = true;
2053 ieee->bHalfWirelessN24GMode = false;
2055 ieee80211_associate_step2(ieee);
2057 ieee80211_auth_challenge(ieee, challenge, chlen);
2060 ieee->softmac_stats.rx_auth_rs_err++;
2061 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2063 printk("Authentication respose status code 0x%x",errcode);
2064 ieee80211_associate_abort(ieee);
2067 }else if (ieee->iw_mode == IW_MODE_MASTER){
2068 ieee80211_rx_auth_rq(ieee, skb);
2073 case IEEE80211_STYPE_PROBE_REQ:
2075 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2076 ((ieee->iw_mode == IW_MODE_ADHOC ||
2077 ieee->iw_mode == IW_MODE_MASTER) &&
2078 ieee->state == IEEE80211_LINKED)){
2079 ieee80211_rx_probe_rq(ieee, skb);
2083 case IEEE80211_STYPE_DISASSOC:
2084 case IEEE80211_STYPE_DEAUTH:
2085 /* FIXME for now repeat all the association procedure
2086 * both for disassociation and deauthentication
2088 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2089 ieee->state == IEEE80211_LINKED &&
2090 ieee->iw_mode == IW_MODE_INFRA){
2091 printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason);
2092 ieee->state = IEEE80211_ASSOCIATING;
2093 ieee->softmac_stats.reassoc++;
2094 ieee->is_roaming = true;
2095 ieee80211_disassociate(ieee);
2096 // notify_wx_assoc_event(ieee);
2097 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2098 RemovePeerTS(ieee, header->addr2);
2099 if(ieee->LedControlHandler != NULL)
2100 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); //added by amy for LED 090318
2101 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2104 case IEEE80211_STYPE_MANAGE_ACT:
2105 ieee80211_process_action(ieee,skb);
2112 //dev_kfree_skb_any(skb);
2116 /* following are for a simplier TX queue management.
2117 * Instead of using netif_[stop/wake]_queue the driver
2118 * will uses these two function (plus a reset one), that
2119 * will internally uses the kernel netif_* and takes
2120 * care of the ieee802.11 fragmentation.
2121 * So the driver receives a fragment per time and might
2122 * call the stop function when it want without take care
2123 * to have enough room to TX an entire packet.
2124 * This might be useful if each fragment need it's own
2125 * descriptor, thus just keep a total free memory > than
2126 * the max fragmentation threshold is not enough.. If the
2127 * ieee802.11 stack passed a TXB struct then you needed
2128 * to keep N free descriptors where
2129 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2130 * In this way you need just one and the 802.11 stack
2131 * will take care of buffering fragments and pass them to
2132 * to the driver later, when it wakes the queue.
2134 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2137 unsigned int queue_index = txb->queue_index;
2138 unsigned long flags;
2140 cb_desc *tcb_desc = NULL;
2142 spin_lock_irqsave(&ieee->lock,flags);
2144 /* called with 2nd parm 0, no tx mgmt lock required */
2145 ieee80211_sta_wakeup(ieee,0);
2147 /* update the tx status */
2148 // ieee->stats.tx_bytes += txb->payload_size;
2149 // ieee->stats.tx_packets++;
2150 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2151 if(tcb_desc->bMulticast) {
2152 ieee->stats.multicast++;
2155 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2156 for(i = 0; i < txb->nr_frags; i++) {
2157 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2158 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2159 (ieee->queue_stop)) {
2160 /* insert the skb packet to the wait queue */
2161 /* as for the completion function, it does not need
2162 * to check it any more.
2164 //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index));
2165 //ieee80211_stop_queue(ieee);
2166 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2168 ieee->softmac_data_hard_start_xmit(
2170 ieee->dev,ieee->rate);
2171 //ieee->stats.tx_packets++;
2172 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2173 //ieee->dev->trans_start = jiffies;
2177 ieee80211_txb_free(txb);
2180 spin_unlock_irqrestore(&ieee->lock,flags);
2184 /* called with ieee->lock acquired */
2185 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2188 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2190 if (ieee->queue_stop){
2191 ieee->tx_pending.frag = i;
2195 ieee->softmac_data_hard_start_xmit(
2196 ieee->tx_pending.txb->fragments[i],
2197 ieee->dev,ieee->rate);
2198 //(i+1)<ieee->tx_pending.txb->nr_frags);
2199 ieee->stats.tx_packets++;
2200 // ieee->dev->trans_start = jiffies;
2205 ieee80211_txb_free(ieee->tx_pending.txb);
2206 ieee->tx_pending.txb = NULL;
2210 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2212 unsigned long flags;
2214 spin_lock_irqsave(&ieee->lock,flags);
2215 init_mgmt_queue(ieee);
2216 if (ieee->tx_pending.txb){
2217 ieee80211_txb_free(ieee->tx_pending.txb);
2218 ieee->tx_pending.txb = NULL;
2220 ieee->queue_stop = 0;
2221 spin_unlock_irqrestore(&ieee->lock,flags);
2225 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2228 unsigned long flags;
2229 struct sk_buff *skb;
2230 struct ieee80211_hdr_3addr *header;
2232 spin_lock_irqsave(&ieee->lock,flags);
2233 if (! ieee->queue_stop) goto exit;
2235 ieee->queue_stop = 0;
2237 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2238 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2240 header = (struct ieee80211_hdr_3addr *) skb->data;
2242 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2244 if (ieee->seq_ctrl[0] == 0xFFF)
2245 ieee->seq_ctrl[0] = 0;
2247 ieee->seq_ctrl[0]++;
2249 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2250 //dev_kfree_skb_any(skb);//edit by thomas
2253 if (!ieee->queue_stop && ieee->tx_pending.txb)
2254 ieee80211_resume_tx(ieee);
2256 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2257 ieee->softmac_stats.swtxawake++;
2258 netif_wake_queue(ieee->dev);
2262 spin_unlock_irqrestore(&ieee->lock,flags);
2266 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2268 //unsigned long flags;
2269 //spin_lock_irqsave(&ieee->lock,flags);
2271 if (! netif_queue_stopped(ieee->dev)){
2272 netif_stop_queue(ieee->dev);
2273 ieee->softmac_stats.swtxstop++;
2275 ieee->queue_stop = 1;
2276 //spin_unlock_irqrestore(&ieee->lock,flags);
2281 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2284 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2286 /* an IBSS cell address must have the two less significant
2287 * bits of the first byte = 2
2289 ieee->current_network.bssid[0] &= ~0x01;
2290 ieee->current_network.bssid[0] |= 0x02;
2293 /* called in user context only */
2294 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2298 if (ieee->current_network.ssid_len == 0){
2299 strncpy(ieee->current_network.ssid,
2300 IEEE80211_DEFAULT_TX_ESSID,
2303 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2307 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2309 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2310 ieee->state = IEEE80211_LINKED;
2311 ieee->link_change(ieee->dev);
2312 notify_wx_assoc_event(ieee);
2314 if (ieee->data_hard_resume)
2315 ieee->data_hard_resume(ieee->dev);
2317 netif_carrier_on(ieee->dev);
2320 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2324 if (ieee->data_hard_resume)
2325 ieee->data_hard_resume(ieee->dev);
2327 netif_carrier_on(ieee->dev);
2331 void ieee80211_start_ibss_wq(struct work_struct *work)
2334 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2335 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2336 /* iwconfig mode ad-hoc will schedule this and return
2337 * on the other hand this will block further iwconfig SET
2338 * operations because of the wx_sem hold.
2339 * Anyway some most set operations set a flag to speed-up
2340 * (abort) this wq (when syncro scanning) before sleeping
2343 if(!ieee->proto_started){
2344 printk("==========oh driver down return\n");
2347 down(&ieee->wx_sem);
2348 //FIXME:set back to 20M whenever HT for ibss is not ready. Otherwise,after being connected to 40M AP, it will still stay in 40M when set to ibss mode. WB 2009.02.04
2349 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2351 if (ieee->current_network.ssid_len == 0){
2352 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2353 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2357 /* check if we have this cell in our network list */
2358 ieee80211_softmac_check_all_nets(ieee);
2361 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2362 if (ieee->state == IEEE80211_NOLINK)
2363 ieee->current_network.channel = 6;
2364 /* if not then the state is not linked. Maybe the user swithced to
2365 * ad-hoc mode just after being in monitor mode, or just after
2366 * being very few time in managed mode (so the card have had no
2367 * time to scan all the chans..) or we have just run up the iface
2368 * after setting ad-hoc mode. So we have to give another try..
2369 * Here, in ibss mode, should be safe to do this without extra care
2370 * (in bss mode we had to make sure no-one tryed to associate when
2371 * we had just checked the ieee->state and we was going to start the
2372 * scan) beacause in ibss mode the ieee80211_new_net function, when
2373 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2374 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2375 * scan, that will stop at the first round because it sees the state
2378 if (ieee->state == IEEE80211_NOLINK)
2379 ieee80211_start_scan_syncro(ieee);
2381 /* the network definitively is not here.. create a new cell */
2382 if (ieee->state == IEEE80211_NOLINK){
2383 printk("creating new IBSS cell\n");
2385 ieee80211_randomize_cell(ieee);
2387 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2389 ieee->current_network.rates_len = 4;
2391 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2392 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2393 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2394 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2397 ieee->current_network.rates_len = 0;
2399 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2400 ieee->current_network.rates_ex_len = 8;
2402 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2403 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2404 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2405 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2406 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2407 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2408 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2409 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2413 ieee->current_network.rates_ex_len = 0;
2417 // By default, WMM function will be disabled in IBSS mode
2418 ieee->current_network.QoS_Enable = 0;
2419 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2420 ieee->current_network.atim_window = 0;
2421 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2422 if(ieee->short_slot)
2423 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2427 ieee->state = IEEE80211_LINKED;
2429 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2430 ieee->link_change(ieee->dev);
2431 if(ieee->LedControlHandler != NULL)
2432 ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
2433 notify_wx_assoc_event(ieee);
2435 ieee80211_start_send_beacons(ieee);
2437 if (ieee->data_hard_resume)
2438 ieee->data_hard_resume(ieee->dev);
2439 netif_carrier_on(ieee->dev);
2444 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2446 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2449 /* this is called only in user context, with wx_sem held */
2450 void ieee80211_start_bss(struct ieee80211_device *ieee)
2452 unsigned long flags;
2454 // Ref: 802.11d 11.1.3.3
2455 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2457 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2459 if(! ieee->bGlobalDomain)
2464 /* check if we have already found the net we
2465 * are interested in (if any).
2466 * if not (we are disassociated and we are not
2467 * in associating / authenticating phase) start the background scanning.
2469 ieee80211_softmac_check_all_nets(ieee);
2471 /* ensure no-one start an associating process (thus setting
2472 * the ieee->state to ieee80211_ASSOCIATING) while we
2473 * have just cheked it and we are going to enable scan.
2474 * The ieee80211_new_net function is always called with
2475 * lock held (from both ieee80211_softmac_check_all_nets and
2476 * the rx path), so we cannot be in the middle of such function
2478 spin_lock_irqsave(&ieee->lock, flags);
2480 if (ieee->state == IEEE80211_NOLINK){
2481 ieee->actscanning = true;
2482 ieee80211_start_scan(ieee);
2484 spin_unlock_irqrestore(&ieee->lock, flags);
2487 void ieee80211_link_change_wq(struct work_struct *work)
2489 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2490 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, link_change_wq);
2492 ieee->link_change(ieee->dev);
2494 /* called only in userspace context */
2495 void ieee80211_disassociate(struct ieee80211_device *ieee)
2499 netif_carrier_off(ieee->dev);
2500 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2501 ieee80211_reset_queue(ieee);
2503 if (ieee->data_hard_stop)
2504 ieee->data_hard_stop(ieee->dev);
2505 if(IS_DOT11D_ENABLE(ieee))
2507 ieee->state = IEEE80211_NOLINK;
2508 ieee->is_set_key = false;
2510 //LZM for usb dev crash.
2511 //ieee->link_change(ieee->dev);
2512 queue_delayed_work(ieee->wq, &ieee->link_change_wq, 0);
2514 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2515 notify_wx_assoc_event(ieee);
2519 void ieee80211_associate_retry_wq(struct work_struct *work)
2521 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2522 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2523 unsigned long flags;
2525 down(&ieee->wx_sem);
2526 if(!ieee->proto_started)
2529 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2532 /* until we do not set the state to IEEE80211_NOLINK
2533 * there are no possibility to have someone else trying
2534 * to start an association procdure (we get here with
2535 * ieee->state = IEEE80211_ASSOCIATING).
2536 * When we set the state to IEEE80211_NOLINK it is possible
2537 * that the RX path run an attempt to associate, but
2538 * both ieee80211_softmac_check_all_nets and the
2539 * RX path works with ieee->lock held so there are no
2540 * problems. If we are still disassociated then start a scan.
2541 * the lock here is necessary to ensure no one try to start
2542 * an association procedure when we have just checked the
2543 * state and we are going to start the scan.
2545 ieee->beinretry = true;
2546 ieee->state = IEEE80211_NOLINK;
2548 ieee80211_softmac_check_all_nets(ieee);
2550 spin_lock_irqsave(&ieee->lock, flags);
2552 if(ieee->state == IEEE80211_NOLINK)
2554 ieee->actscanning = true;
2555 ieee80211_start_scan(ieee);
2557 spin_unlock_irqrestore(&ieee->lock, flags);
2559 ieee->beinretry = false;
2564 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2566 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2568 struct sk_buff *skb;
2569 struct ieee80211_probe_response *b;
2571 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2576 b = (struct ieee80211_probe_response *) skb->data;
2577 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2583 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2585 struct sk_buff *skb;
2586 struct ieee80211_probe_response *b;
2588 skb = ieee80211_get_beacon_(ieee);
2592 b = (struct ieee80211_probe_response *) skb->data;
2593 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2595 if (ieee->seq_ctrl[0] == 0xFFF)
2596 ieee->seq_ctrl[0] = 0;
2598 ieee->seq_ctrl[0]++;
2603 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2605 ieee->sync_scan_hurryup = 1;
2606 down(&ieee->wx_sem);
2607 ieee80211_stop_protocol(ieee);
2612 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2614 if (!ieee->proto_started)
2617 ieee->proto_started = 0;
2619 ieee80211_stop_send_beacons(ieee);
2620 del_timer_sync(&ieee->associate_timer);
2621 cancel_delayed_work(&ieee->associate_retry_wq);
2622 cancel_delayed_work(&ieee->start_ibss_wq);
2623 cancel_delayed_work(&ieee->link_change_wq);
2624 ieee80211_stop_scan(ieee);
2626 ieee80211_disassociate(ieee);
2627 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2630 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2632 ieee->sync_scan_hurryup = 0;
2633 down(&ieee->wx_sem);
2634 ieee80211_start_protocol(ieee);
2638 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2642 if (ieee->proto_started)
2645 ieee->proto_started = 1;
2647 if (ieee->current_network.channel == 0){
2650 if (ch > MAX_CHANNEL_NUMBER)
2651 return; /* no channel found */
2652 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2653 ieee->current_network.channel = ch;
2656 if (ieee->current_network.beacon_interval == 0)
2657 ieee->current_network.beacon_interval = 100;
2658 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2659 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2661 for(i = 0; i < 17; i++) {
2662 ieee->last_rxseq_num[i] = -1;
2663 ieee->last_rxfrag_num[i] = -1;
2664 ieee->last_packet_time[i] = 0;
2667 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2670 /* if the user set the MAC of the ad-hoc cell and then
2671 * switch to managed mode, shall we make sure that association
2672 * attempts does not fail just because the user provide the essid
2673 * and the nic is still checking for the AP MAC ??
2675 if (ieee->iw_mode == IW_MODE_INFRA)
2676 ieee80211_start_bss(ieee);
2678 else if (ieee->iw_mode == IW_MODE_ADHOC)
2679 ieee80211_start_ibss(ieee);
2681 else if (ieee->iw_mode == IW_MODE_MASTER)
2682 ieee80211_start_master_bss(ieee);
2684 else if(ieee->iw_mode == IW_MODE_MONITOR)
2685 ieee80211_start_monitor_mode(ieee);
2689 #define DRV_NAME "Ieee80211"
2690 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2693 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2695 ieee->state = IEEE80211_NOLINK;
2696 ieee->sync_scan_hurryup = 0;
2697 for(i = 0; i < 5; i++) {
2698 ieee->seq_ctrl[i] = 0;
2700 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2701 if (!ieee->pDot11dInfo)
2702 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2703 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
2704 //added for AP roaming
2705 ieee->LinkDetectInfo.SlotNum = 2;
2706 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2707 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2710 ieee->queue_stop = 0;
2712 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2715 ieee->proto_started = 0;
2716 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2718 ieee->ps = IEEE80211_PS_DISABLED;
2719 ieee->sta_sleep = 0;
2720 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2721 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2722 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2724 ieee->actscanning = false;
2725 ieee->beinretry = false;
2726 ieee->is_set_key = false;
2727 init_mgmt_queue(ieee);
2729 ieee->sta_edca_param[0] = 0x0000A403;
2730 ieee->sta_edca_param[1] = 0x0000A427;
2731 ieee->sta_edca_param[2] = 0x005E4342;
2732 ieee->sta_edca_param[3] = 0x002F3262;
2733 ieee->aggregation = true;
2734 ieee->enable_rx_imm_BA = 1;
2735 ieee->tx_pending.txb = NULL;
2737 init_timer(&ieee->associate_timer);
2738 ieee->associate_timer.data = (unsigned long)ieee;
2739 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2741 init_timer(&ieee->beacon_timer);
2742 ieee->beacon_timer.data = (unsigned long) ieee;
2743 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2745 #ifdef PF_SYNCTHREAD
2746 ieee->wq = create_workqueue(DRV_NAME,0);
2748 ieee->wq = create_workqueue(DRV_NAME);
2751 INIT_DELAYED_WORK(&ieee->link_change_wq,ieee80211_link_change_wq);
2752 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2753 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2754 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2755 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2756 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2757 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2759 sema_init(&ieee->wx_sem, 1);
2760 sema_init(&ieee->scan_sem, 1);
2762 spin_lock_init(&ieee->mgmt_tx_lock);
2763 spin_lock_init(&ieee->beacon_lock);
2765 tasklet_init(&ieee->ps_task,
2766 (void(*)(unsigned long)) ieee80211_sta_ps,
2767 (unsigned long)ieee);
2771 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2773 down(&ieee->wx_sem);
2774 if(NULL != ieee->pDot11dInfo)
2776 kfree(ieee->pDot11dInfo);
2777 ieee->pDot11dInfo = NULL;
2779 del_timer_sync(&ieee->associate_timer);
2781 cancel_delayed_work(&ieee->associate_retry_wq);
2782 destroy_workqueue(ieee->wq);
2787 /********************************************************
2788 * Start of WPA code. *
2789 * this is stolen from the ipw2200 driver *
2790 ********************************************************/
2793 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2795 /* This is called when wpa_supplicant loads and closes the driver
2797 printk("%s WPA\n",value ? "enabling" : "disabling");
2798 ieee->wpa_enabled = value;
2799 memset(ieee->ap_mac_addr, 0, 6); //reset ap_mac_addr everytime it starts wpa.
2804 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2806 /* make sure WPA is enabled */
2807 ieee80211_wpa_enable(ieee, 1);
2809 ieee80211_disassociate(ieee);
2813 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2819 case IEEE_MLME_STA_DEAUTH:
2823 case IEEE_MLME_STA_DISASSOC:
2824 ieee80211_disassociate(ieee);
2828 printk("Unknown MLME request: %d\n", command);
2836 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2837 struct ieee_param *param, int plen)
2841 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2842 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2845 if (param->u.wpa_ie.len) {
2846 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
2850 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
2851 kfree(ieee->wpa_ie);
2853 ieee->wpa_ie_len = param->u.wpa_ie.len;
2855 kfree(ieee->wpa_ie);
2856 ieee->wpa_ie = NULL;
2857 ieee->wpa_ie_len = 0;
2860 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2864 #define AUTH_ALG_OPEN_SYSTEM 0x1
2865 #define AUTH_ALG_SHARED_KEY 0x2
2866 #define AUTH_ALG_LEAP 0x4
2867 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2870 struct ieee80211_security sec = {
2871 .flags = SEC_AUTH_MODE,
2875 if (value & AUTH_ALG_SHARED_KEY) {
2876 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2878 ieee->auth_mode = 1;
2879 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2880 sec.auth_mode = WLAN_AUTH_OPEN;
2882 ieee->auth_mode = 0;
2884 else if (value & AUTH_ALG_LEAP){
2885 sec.auth_mode = RTL_WLAN_AUTH_LEAP;
2887 ieee->auth_mode = 2;
2891 if (ieee->set_security)
2892 ieee->set_security(ieee->dev, &sec);
2894 // ret = -EOPNOTSUPP;
2899 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2902 unsigned long flags;
2905 case IEEE_PARAM_WPA_ENABLED:
2906 ret = ieee80211_wpa_enable(ieee, value);
2909 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2910 ieee->tkip_countermeasures=value;
2913 case IEEE_PARAM_DROP_UNENCRYPTED: {
2916 * wpa_supplicant calls set_wpa_enabled when the driver
2917 * is loaded and unloaded, regardless of if WPA is being
2918 * used. No other calls are made which can be used to
2919 * determine if encryption will be used or not prior to
2920 * association being expected. If encryption is not being
2921 * used, drop_unencrypted is set to false, else true -- we
2922 * can use this to determine if the CAP_PRIVACY_ON bit should
2925 struct ieee80211_security sec = {
2926 .flags = SEC_ENABLED,
2929 ieee->drop_unencrypted = value;
2930 /* We only change SEC_LEVEL for open mode. Others
2931 * are set by ipw_wpa_set_encryption.
2934 sec.flags |= SEC_LEVEL;
2935 sec.level = SEC_LEVEL_0;
2938 sec.flags |= SEC_LEVEL;
2939 sec.level = SEC_LEVEL_1;
2941 if (ieee->set_security)
2942 ieee->set_security(ieee->dev, &sec);
2946 case IEEE_PARAM_PRIVACY_INVOKED:
2947 ieee->privacy_invoked=value;
2950 case IEEE_PARAM_AUTH_ALGS:
2951 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2954 case IEEE_PARAM_IEEE_802_1X:
2955 ieee->ieee802_1x=value;
2957 case IEEE_PARAM_WPAX_SELECT:
2958 // added for WPA2 mixed mode
2959 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2960 ieee->wpax_type_set = 1;
2961 ieee->wpax_type_notify = value;
2962 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
2966 printk("Unknown WPA param: %d\n",name);
2973 /* implementation borrowed from hostap driver */
2975 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2976 struct ieee_param *param, int param_len)
2980 struct ieee80211_crypto_ops *ops;
2981 struct ieee80211_crypt_data **crypt;
2983 struct ieee80211_security sec = {
2987 param->u.crypt.err = 0;
2988 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2991 (int) ((char *) param->u.crypt.key - (char *) param) +
2992 param->u.crypt.key_len) {
2993 printk("Len mismatch %d, %d\n", param_len,
2994 param->u.crypt.key_len);
2997 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2998 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2999 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3000 if (param->u.crypt.idx >= WEP_KEYS)
3002 crypt = &ieee->crypt[param->u.crypt.idx];
3007 if (strcmp(param->u.crypt.alg, "none") == 0) {
3012 sec.level = SEC_LEVEL_0;
3013 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3014 ieee80211_crypt_delayed_deinit(ieee, crypt);
3021 sec.flags |= SEC_ENABLED;
3023 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3024 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3025 strcmp(param->u.crypt.alg, "TKIP"))
3026 goto skip_host_crypt;
3028 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3029 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3030 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3031 /* set WEP40 first, it will be modified according to WEP104 or
3032 * WEP40 at other place */
3033 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3034 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3035 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3036 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3038 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3039 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3044 if (*crypt == NULL || (*crypt)->ops != ops) {
3045 struct ieee80211_crypt_data *new_crypt;
3047 ieee80211_crypt_delayed_deinit(ieee, crypt);
3049 new_crypt = (struct ieee80211_crypt_data *)
3050 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3051 if (new_crypt == NULL) {
3055 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3056 new_crypt->ops = ops;
3060 new_crypt->ops->init(param->u.crypt.idx);
3062 if (new_crypt->priv == NULL) {
3064 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3072 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3073 (*crypt)->ops->set_key(param->u.crypt.key,
3074 param->u.crypt.key_len, param->u.crypt.seq,
3075 (*crypt)->priv) < 0) {
3076 printk("key setting failed\n");
3077 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3083 if (param->u.crypt.set_tx) {
3084 ieee->tx_keyidx = param->u.crypt.idx;
3085 sec.active_key = param->u.crypt.idx;
3086 sec.flags |= SEC_ACTIVE_KEY;
3088 sec.flags &= ~SEC_ACTIVE_KEY;
3090 if (param->u.crypt.alg != NULL) {
3091 memcpy(sec.keys[param->u.crypt.idx],
3093 param->u.crypt.key_len);
3094 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3095 sec.flags |= (1 << param->u.crypt.idx);
3097 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3098 sec.flags |= SEC_LEVEL;
3099 sec.level = SEC_LEVEL_1;
3100 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3101 sec.flags |= SEC_LEVEL;
3102 sec.level = SEC_LEVEL_2;
3103 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3104 sec.flags |= SEC_LEVEL;
3105 sec.level = SEC_LEVEL_3;
3109 if (ieee->set_security)
3110 ieee->set_security(ieee->dev, &sec);
3112 /* Do not reset port if card is in Managed mode since resetting will
3113 * generate new IEEE 802.11 authentication which may end up in looping
3114 * with IEEE 802.1X. If your hardware requires a reset after WEP
3115 * configuration (for example... Prism2), implement the reset_port in
3116 * the callbacks structures used to initialize the 802.11 stack. */
3117 if (ieee->reset_on_keychange &&
3118 ieee->iw_mode != IW_MODE_INFRA &&
3120 ieee->reset_port(ieee->dev)) {
3121 printk("reset_port failed\n");
3122 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3129 inline struct sk_buff *ieee80211_disassociate_skb(
3130 struct ieee80211_network *beacon,
3131 struct ieee80211_device *ieee,
3134 struct sk_buff *skb;
3135 struct ieee80211_disassoc *disass;
3137 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3141 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3142 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3143 disass->header.duration_id = 0;
3145 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3146 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3147 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3149 disass->reason = asRsn;
3156 struct ieee80211_device *ieee,
3161 struct ieee80211_network *beacon = &ieee->current_network;
3162 struct sk_buff *skb;
3163 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3165 softmac_mgmt_xmit(skb, ieee);
3166 //dev_kfree_skb_any(skb);//edit by thomas
3170 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3172 struct ieee_param *param;
3175 down(&ieee->wx_sem);
3176 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3178 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3183 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3188 if (copy_from_user(param, p->pointer, p->length)) {
3194 switch (param->cmd) {
3196 case IEEE_CMD_SET_WPA_PARAM:
3197 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3198 param->u.wpa_param.value);
3201 case IEEE_CMD_SET_WPA_IE:
3202 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3205 case IEEE_CMD_SET_ENCRYPTION:
3206 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3210 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3211 param->u.mlme.reason_code);
3215 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3220 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3230 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3232 union iwreq_data wrqu;
3233 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3234 if (ieee->state == IEEE80211_LINKED)
3235 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3237 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3238 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);