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/slab.h>
22 #include <linux/version.h>
23 #include <asm/uaccess.h>
26 u8 rsn_authen_cipher_suite[16][4] = {
27 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
28 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
29 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
30 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
31 {0x00,0x0F,0xAC,0x04}, //CCMP
32 {0x00,0x0F,0xAC,0x05}, //WEP-104
35 short ieee80211_is_54g(struct ieee80211_network net)
37 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
40 short ieee80211_is_shortslot(struct ieee80211_network net)
42 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
45 /* returns the total length needed for pleacing the RATE MFIE
46 * tag and the EXTENDED RATE MFIE tag if needed.
47 * It encludes two bytes per tag for the tag itself and its len
49 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
51 unsigned int rate_len = 0;
53 if (ieee->modulation & IEEE80211_CCK_MODULATION)
54 rate_len = IEEE80211_CCK_RATE_LEN + 2;
56 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
58 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
63 /* pleace the MFIE rate, tag to the memory (double) poined.
64 * Then it updates the pointer so that
65 * it points after the new MFIE tag added.
67 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
71 if (ieee->modulation & IEEE80211_CCK_MODULATION){
72 *tag++ = MFIE_TYPE_RATES;
74 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
80 /* We may add an option for custom rates that specific HW might support */
84 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
88 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
90 *tag++ = MFIE_TYPE_RATES_EX;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
103 /* We may add an option for custom rates that specific HW might support */
108 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
111 *tag++ = MFIE_TYPE_GENERIC; //0
120 if(ieee->current_network.wmm_info & 0x80) {
121 *tag++ = 0x0f|MAX_SP_Len;
131 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
134 *tag++ = MFIE_TYPE_GENERIC; //0
145 printk(KERN_ALERT "This is enable turbo mode IE process\n");
148 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
151 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
154 * if the queue is full but we have newer frames then
155 * just overwrites the oldest.
157 * if (nh == ieee->mgmt_queue_tail)
160 ieee->mgmt_queue_head = nh;
161 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;
186 MgntQuery_TxRateExcludeCCKRates(struct ieee80211_device *ieee)
193 for( i = 0; i < ieee->current_network.rates_len; i++)
195 BasicRate = ieee->current_network.rates[i]&0x7F;
196 if(!ieee80211_is_cck_rate(BasicRate))
200 QueryRate = BasicRate;
204 if(BasicRate < QueryRate)
206 QueryRate = BasicRate;
215 printk("No BasicRate found!!\n");
219 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
221 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
224 if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
226 rate = MgntQuery_TxRateExcludeCCKRates(ieee);
229 rate = ieee->basic_rate & 0x7f;
232 if(ieee->mode == IEEE_A||
233 ieee->mode== IEEE_N_5G||
234 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
243 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
245 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
248 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
249 struct ieee80211_hdr_3addr *header=
250 (struct ieee80211_hdr_3addr *) skb->data;
252 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
253 spin_lock_irqsave(&ieee->lock, flags);
255 /* called with 2nd param 0, no mgmt lock required */
256 ieee80211_sta_wakeup(ieee,0);
258 tcb_desc->queue_index = MGNT_QUEUE;
259 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
260 tcb_desc->RATRIndex = 7;
261 tcb_desc->bTxDisableRateFallBack = 1;
262 tcb_desc->bTxUseDriverAssingedRate = 1;
265 if(ieee->queue_stop){
266 enqueue_mgmt(ieee,skb);
268 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
270 if (ieee->seq_ctrl[0] == 0xFFF)
271 ieee->seq_ctrl[0] = 0;
275 /* avoid watchdog triggers */
276 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
279 spin_unlock_irqrestore(&ieee->lock, flags);
281 spin_unlock_irqrestore(&ieee->lock, flags);
282 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
284 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
286 if (ieee->seq_ctrl[0] == 0xFFF)
287 ieee->seq_ctrl[0] = 0;
291 /* check wether the managed packet queued greater than 5 */
292 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
293 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
294 (ieee->queue_stop) ) {
295 /* insert the skb packet to the management queue */
296 /* as for the completion function, it does not need
297 * to check it any more.
299 printk("%s():insert to waitqueue!\n",__FUNCTION__);
300 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
302 ieee->softmac_hard_start_xmit(skb,ieee->dev);
304 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
308 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
311 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
312 struct ieee80211_hdr_3addr *header =
313 (struct ieee80211_hdr_3addr *) skb->data;
315 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
317 fc = header->frame_control;
318 type = WLAN_FC_GET_TYPE(fc);
319 stype = WLAN_FC_GET_STYPE(fc);
322 if(stype != IEEE80211_STYPE_PSPOLL)
323 tcb_desc->queue_index = MGNT_QUEUE;
325 tcb_desc->queue_index = HIGH_QUEUE;
326 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
327 tcb_desc->RATRIndex = 7;
328 tcb_desc->bTxDisableRateFallBack = 1;
329 tcb_desc->bTxUseDriverAssingedRate = 1;
331 if(!(type == IEEE80211_FTYPE_CTL)) {
332 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
334 if (ieee->seq_ctrl[0] == 0xFFF)
335 ieee->seq_ctrl[0] = 0;
340 /* avoid watchdog triggers */
341 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
344 if(!(type == IEEE80211_FTYPE_CTL)) {
345 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
347 if (ieee->seq_ctrl[0] == 0xFFF)
348 ieee->seq_ctrl[0] = 0;
353 ieee->softmac_hard_start_xmit(skb,ieee->dev);
358 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
360 unsigned int len,rate_len;
363 struct ieee80211_probe_request *req;
365 len = ieee->current_network.ssid_len;
367 rate_len = ieee80211_MFIE_rate_len(ieee);
369 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
370 2 + len + rate_len + ieee->tx_headroom);
374 skb_reserve(skb, ieee->tx_headroom);
376 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
377 req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
378 req->header.duration_id = 0; //FIXME: is this OK ?
380 memset(req->header.addr1, 0xff, ETH_ALEN);
381 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
382 memset(req->header.addr3, 0xff, ETH_ALEN);
384 tag = (u8 *) skb_put(skb,len+2+rate_len);
386 *tag++ = MFIE_TYPE_SSID;
388 memcpy(tag, ieee->current_network.ssid, len);
391 ieee80211_MFIE_Brate(ieee,&tag);
392 ieee80211_MFIE_Grate(ieee,&tag);
396 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
397 void ieee80211_send_beacon(struct ieee80211_device *ieee)
402 skb = ieee80211_get_beacon_(ieee);
405 softmac_mgmt_xmit(skb, ieee);
406 ieee->softmac_stats.tx_beacons++;
409 if(ieee->beacon_txing && ieee->ieee_up){
410 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
415 void ieee80211_send_beacon_cb(unsigned long _ieee)
417 struct ieee80211_device *ieee =
418 (struct ieee80211_device *) _ieee;
421 spin_lock_irqsave(&ieee->beacon_lock, flags);
422 ieee80211_send_beacon(ieee);
423 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
427 void ieee80211_send_probe(struct ieee80211_device *ieee)
431 skb = ieee80211_probe_req(ieee);
433 softmac_mgmt_xmit(skb, ieee);
434 ieee->softmac_stats.tx_probe_rq++;
438 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
440 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
441 ieee80211_send_probe(ieee);
442 ieee80211_send_probe(ieee);
446 /* this performs syncro scan blocking the caller until all channels
447 * in the allowed channel map has been checked.
449 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
452 u8 channel_map[MAX_CHANNEL_NUMBER+1];
453 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
454 ieee->be_scan_inprogress = true;
455 down(&ieee->scan_sem);
462 if (ch > MAX_CHANNEL_NUMBER)
463 goto out; /* scan completed */
464 }while(!channel_map[ch]);
466 /* this fuction can be called in two situations
467 * 1- We have switched to ad-hoc mode and we are
468 * performing a complete syncro scan before conclude
469 * there are no interesting cell and to create a
470 * new one. In this case the link state is
471 * IEEE80211_NOLINK until we found an interesting cell.
472 * If so the ieee8021_new_net, called by the RX path
473 * will set the state to IEEE80211_LINKED, so we stop
475 * 2- We are linked and the root uses run iwlist scan.
476 * So we switch to IEEE80211_LINKED_SCANNING to remember
477 * that we are still logically linked (not interested in
478 * new network events, despite for updating the net list,
479 * but we are temporarly 'unlinked' as the driver shall
480 * not filter RX frames and the channel is changing.
481 * So the only situation in witch are interested is to check
482 * if the state become LINKED because of the #1 situation
485 if (ieee->state == IEEE80211_LINKED)
487 ieee->set_chan(ieee->dev, ch);
488 if(channel_map[ch] == 1)
489 ieee80211_send_probe_requests(ieee);
491 /* this prevent excessive time wait when we
492 * need to wait for a syncro scan to end..
494 if(ieee->state < IEEE80211_LINKED)
497 if (ieee->sync_scan_hurryup)
501 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
505 if(ieee->state < IEEE80211_LINKED){
506 ieee->actscanning = false;
508 ieee->be_scan_inprogress = false;
511 ieee->sync_scan_hurryup = 0;
512 if(IS_DOT11D_ENABLE(ieee))
513 DOT11D_ScanComplete(ieee);
515 ieee->be_scan_inprogress = false;
519 void ieee80211_softmac_scan_wq(struct work_struct *work)
521 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
522 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
523 u8 last_channel = ieee->current_network.channel; //recored init channel inorder not change current channel when comming out the scan unexpectedly. WB.
524 u8 channel_map[MAX_CHANNEL_NUMBER+1];
525 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
528 down(&ieee->scan_sem);
530 ieee->current_network.channel =
531 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
532 if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER)
534 //if current channel is not in channel map, set to default channel.
535 if (!channel_map[ieee->current_network.channel]);
536 ieee->current_network.channel = 6;
537 goto out; /* no good chans */
539 }while(!channel_map[ieee->current_network.channel]);
540 if (ieee->scanning == 0 )
542 ieee->set_chan(ieee->dev, ieee->current_network.channel);
543 if(channel_map[ieee->current_network.channel] == 1)
544 ieee80211_send_probe_requests(ieee);
546 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
551 if(IS_DOT11D_ENABLE(ieee))
552 DOT11D_ScanComplete(ieee);
553 ieee->current_network.channel = last_channel;
554 ieee->actscanning = false;
555 ieee->scan_watch_dog = 0;
560 void ieee80211_beacons_start(struct ieee80211_device *ieee)
563 spin_lock_irqsave(&ieee->beacon_lock,flags);
565 ieee->beacon_txing = 1;
566 ieee80211_send_beacon(ieee);
568 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
571 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
575 spin_lock_irqsave(&ieee->beacon_lock,flags);
577 ieee->beacon_txing = 0;
578 del_timer_sync(&ieee->beacon_timer);
580 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
585 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
587 if(ieee->stop_send_beacons)
588 ieee->stop_send_beacons(ieee->dev);
589 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
590 ieee80211_beacons_stop(ieee);
594 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
596 if(ieee->start_send_beacons)
597 ieee->start_send_beacons(ieee->dev);
598 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
599 ieee80211_beacons_start(ieee);
603 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
606 down(&ieee->scan_sem);
607 ieee->scan_watch_dog = 0;
608 if (ieee->scanning == 1){
611 cancel_delayed_work(&ieee->softmac_scan_wq);
617 void ieee80211_stop_scan(struct ieee80211_device *ieee)
619 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
620 ieee80211_softmac_stop_scan(ieee);
622 ieee->stop_scan(ieee->dev);
625 /* called with ieee->lock held */
626 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
628 if(IS_DOT11D_ENABLE(ieee) )
630 if(IS_COUNTRY_IE_VALID(ieee))
632 RESET_CIE_WATCHDOG(ieee);
635 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
636 if (ieee->scanning == 0){
638 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
641 ieee->start_scan(ieee->dev);
645 /* called with wx_sem held */
646 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
648 if(IS_DOT11D_ENABLE(ieee) )
650 if(IS_COUNTRY_IE_VALID(ieee))
652 RESET_CIE_WATCHDOG(ieee);
655 ieee->sync_scan_hurryup = 0;
656 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
657 ieee80211_softmac_scan_syncro(ieee);
659 ieee->scan_syncro(ieee->dev);
663 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
664 struct ieee80211_device *ieee, int challengelen)
667 struct ieee80211_authentication *auth;
668 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
671 skb = dev_alloc_skb(len);
672 if (!skb) return NULL;
674 skb_reserve(skb, ieee->tx_headroom);
675 auth = (struct ieee80211_authentication *)
676 skb_put(skb, sizeof(struct ieee80211_authentication));
678 auth->header.frame_control = IEEE80211_STYPE_AUTH;
679 if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP;
681 auth->header.duration_id = 0x013a; //FIXME
683 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
684 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
685 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
687 if(ieee->auth_mode == 0)
688 auth->algorithm = WLAN_AUTH_OPEN;
689 else if(ieee->auth_mode == 1)
690 auth->algorithm = WLAN_AUTH_SHARED_KEY;
691 else if(ieee->auth_mode == 2)
692 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
693 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
694 auth->transaction = cpu_to_le16(ieee->associate_seq);
695 ieee->associate_seq++;
697 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
703 void constructWMMIE(u8* wmmie, u8* wmm_len,u8 oui_subtype)
705 u8 szQoSOUI[] ={221, 0, 0x00, 0x50, 0xf2, 0x02, 0, 1};
707 if (oui_subtype == OUI_SUBTYPE_QOS_CAPABI)
710 szQoSOUI[1] = *wmm_len;
711 memcpy(wmmie,szQoSOUI,3);
716 szQoSOUI[1] = *wmm_len + 6;
717 szQoSOUI[6] = oui_subtype;
718 memcpy(wmmie, szQoSOUI, 8);
724 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
728 struct ieee80211_probe_response *beacon_buf;
729 struct sk_buff *skb = NULL;
731 int atim_len,erp_len;
732 struct ieee80211_crypt_data* crypt;
734 char *ssid = ieee->current_network.ssid;
735 int ssid_len = ieee->current_network.ssid_len;
736 int rate_len = ieee->current_network.rates_len+2;
737 int rate_ex_len = ieee->current_network.rates_ex_len;
738 int wpa_ie_len = ieee->wpa_ie_len;
739 u8 erpinfo_content = 0;
741 u8* tmp_ht_cap_buf=NULL;
743 u8* tmp_ht_info_buf=NULL;
744 u8 tmp_ht_info_len=0;
745 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
746 u8* tmp_generic_ie_buf=NULL;
747 u8 tmp_generic_ie_len=0;
753 if(rate_ex_len > 0) rate_ex_len+=2;
755 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
761 if(ieee80211_is_54g(ieee->current_network))
766 if((ieee->current_network.mode == IEEE_G)
767 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
770 if(ieee->current_network.buseprotection)
771 erpinfo_content |= ERP_UseProtection;
778 crypt = ieee->crypt[ieee->tx_keyidx];
781 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
782 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
785 if(ieee->pHTInfo->bCurrentHTSupport){
786 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
787 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
788 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
789 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
791 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
793 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
796 if(pHTInfo->bRegRT2RTAggregation)
798 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
799 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
800 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
805 if(ieee->qos_support){
807 if(ieee->iw_mode == IW_MODE_ADHOC)
810 constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO);
814 beacon_size = sizeof(struct ieee80211_probe_response)+2+
824 // +tmp_generic_ie_len
827 skb = dev_alloc_skb(beacon_size);
830 skb_reserve(skb, ieee->tx_headroom);
831 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
832 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
833 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
834 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
836 beacon_buf->header.duration_id = 0; //FIXME
837 beacon_buf->beacon_interval =
838 cpu_to_le16(ieee->current_network.beacon_interval);
839 beacon_buf->capability =
840 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
841 beacon_buf->capability |=
842 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
844 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
845 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
847 crypt = ieee->crypt[ieee->tx_keyidx];
850 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
853 beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
854 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
855 beacon_buf->info_element[0].len = ssid_len;
857 tag = (u8*) beacon_buf->info_element[0].data;
859 memcpy(tag, ssid, ssid_len);
863 *(tag++) = MFIE_TYPE_RATES;
864 *(tag++) = rate_len-2;
865 memcpy(tag,ieee->current_network.rates,rate_len-2);
868 *(tag++) = MFIE_TYPE_DS_SET;
870 *(tag++) = ieee->current_network.channel;
874 *(tag++) = MFIE_TYPE_IBSS_SET;
876 val16 = cpu_to_le16(ieee->current_network.atim_window);
877 memcpy((u8 *)tag, (u8 *)&val16, 2);
882 *(tag++) = MFIE_TYPE_ERP;
884 *(tag++) = erpinfo_content;
888 *(tag++) = MFIE_TYPE_RATES_EX;
889 *(tag++) = rate_ex_len-2;
890 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
896 if (ieee->iw_mode == IW_MODE_ADHOC)
897 {//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
898 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
900 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
908 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
913 struct ieee80211_crypt_data* crypt;
914 struct ieee80211_assoc_response_frame *assoc;
917 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
918 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
920 skb = dev_alloc_skb(len);
925 skb_reserve(skb, ieee->tx_headroom);
927 assoc = (struct ieee80211_assoc_response_frame *)
928 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
930 assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
931 memcpy(assoc->header.addr1, dest,ETH_ALEN);
932 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
933 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
934 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
935 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
939 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
941 if (ieee->host_encrypt)
942 crypt = ieee->crypt[ieee->tx_keyidx];
945 encrypt = ( crypt && crypt->ops);
948 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
951 assoc->aid = cpu_to_le16(ieee->assoc_id);
952 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
953 else ieee->assoc_id++;
955 tag = (u8*) skb_put(skb, rate_len);
957 ieee80211_MFIE_Brate(ieee, &tag);
958 ieee80211_MFIE_Grate(ieee, &tag);
963 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
966 struct ieee80211_authentication *auth;
967 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
969 skb = dev_alloc_skb(len);
974 skb->len = sizeof(struct ieee80211_authentication);
976 auth = (struct ieee80211_authentication *)skb->data;
978 auth->status = cpu_to_le16(status);
979 auth->transaction = cpu_to_le16(2);
980 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
982 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
983 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
984 memcpy(auth->header.addr1, dest, ETH_ALEN);
985 auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
991 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
994 struct ieee80211_hdr_3addr* hdr;
996 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1001 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1003 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1004 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1005 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1007 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
1008 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1009 (pwr ? IEEE80211_FCTL_PM:0));
1017 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1019 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1022 softmac_mgmt_xmit(buf, ieee);
1026 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1028 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1031 softmac_mgmt_xmit(buf, ieee);
1035 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1039 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1041 softmac_mgmt_xmit(buf, ieee);
1045 inline int SecIsInPMKIDList(struct ieee80211_device *ieee, u8 *bssid)
1051 if ((ieee->PMKIDList[i].bUsed) && (memcmp(ieee->PMKIDList[i].Bssid, bssid, ETH_ALEN) == 0))
1059 } while (i < NUM_PMKID_CACHE);
1061 if (i == NUM_PMKID_CACHE)
1072 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1074 struct sk_buff *skb;
1076 struct ieee80211_assoc_request_frame *hdr;
1078 u8* ht_cap_buf = NULL;
1080 u8* realtek_ie_buf=NULL;
1081 u8 realtek_ie_len=0;
1082 int wpa_ie_len= ieee->wpa_ie_len;
1083 unsigned int ckip_ie_len=0;
1084 unsigned int ccxrm_ie_len=0;
1085 unsigned int cxvernum_ie_len=0;
1086 struct ieee80211_crypt_data* crypt;
1090 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1091 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1092 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1096 crypt = ieee->crypt[ieee->tx_keyidx];
1097 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1099 //Include High Throuput capability && Realtek proprietary
1100 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1102 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1103 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1104 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1105 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1107 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1108 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1109 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1113 if(ieee->qos_support){
1114 wmm_info_len = beacon->qos_data.supported?9:0;
1118 if(beacon->bCkipSupported)
1122 if(beacon->bCcxRmEnable)
1126 if( beacon->BssCcxVerNumber >= 2 )
1128 cxvernum_ie_len = 5+2;
1131 PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
1132 if (PMKCacheIdx >= 0)
1135 printk("[PMK cache]: WPA2 IE length: %x\n", wpa_ie_len);
1138 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1139 + beacon->ssid_len//essid tagged val
1140 + rate_len//rates tagged val
1149 + ieee->tx_headroom;
1151 skb = dev_alloc_skb(len);
1156 skb_reserve(skb, ieee->tx_headroom);
1158 hdr = (struct ieee80211_assoc_request_frame *)
1159 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1162 hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
1163 hdr->header.duration_id= 37; //FIXME
1164 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1165 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1166 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1168 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1170 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1171 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1172 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1174 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1175 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1177 if(ieee->short_slot)
1178 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1179 if (wmm_info_len) //QOS
1180 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1182 hdr->listen_interval = 0xa; //FIXME
1184 hdr->info_element[0].id = MFIE_TYPE_SSID;
1186 hdr->info_element[0].len = beacon->ssid_len;
1187 tag = skb_put(skb, beacon->ssid_len);
1188 memcpy(tag, beacon->ssid, beacon->ssid_len);
1190 tag = skb_put(skb, rate_len);
1192 ieee80211_MFIE_Brate(ieee, &tag);
1193 ieee80211_MFIE_Grate(ieee, &tag);
1194 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1195 if( beacon->bCkipSupported )
1197 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1198 u8 CcxAironetBuf[30];
1199 OCTET_STRING osCcxAironetIE;
1201 memset(CcxAironetBuf, 0,30);
1202 osCcxAironetIE.Octet = CcxAironetBuf;
1203 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1205 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1206 // We want to make the device type as "4500-client". 060926, by CCW.
1208 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1210 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1211 // "The CKIP negotiation is started with the associate request from the client to the access point,
1212 // containing an Aironet element with both the MIC and KP bits set."
1213 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1214 tag = skb_put(skb, ckip_ie_len);
1215 *tag++ = MFIE_TYPE_AIRONET;
1216 *tag++ = osCcxAironetIE.Length;
1217 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1218 tag += osCcxAironetIE.Length;
1221 if(beacon->bCcxRmEnable)
1223 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1224 OCTET_STRING osCcxRmCap;
1226 osCcxRmCap.Octet = CcxRmCapBuf;
1227 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1228 tag = skb_put(skb,ccxrm_ie_len);
1229 *tag++ = MFIE_TYPE_GENERIC;
1230 *tag++ = osCcxRmCap.Length;
1231 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1232 tag += osCcxRmCap.Length;
1235 if( beacon->BssCcxVerNumber >= 2 )
1237 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1238 OCTET_STRING osCcxVerNum;
1239 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1240 osCcxVerNum.Octet = CcxVerNumBuf;
1241 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1242 tag = skb_put(skb,cxvernum_ie_len);
1243 *tag++ = MFIE_TYPE_GENERIC;
1244 *tag++ = osCcxVerNum.Length;
1245 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1246 tag += osCcxVerNum.Length;
1249 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1250 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1252 tag = skb_put(skb, ht_cap_len);
1253 *tag++ = MFIE_TYPE_HT_CAP;
1254 *tag++ = ht_cap_len - 2;
1255 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1256 tag += ht_cap_len -2;
1261 //choose what wpa_supplicant gives to associate.
1262 tag = skb_put(skb, wpa_ie_len);
1264 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1265 if (PMKCacheIdx >= 0)
1267 tag = skb_put(skb, 18);
1270 memcpy((tag + 2), &ieee->PMKIDList[PMKCacheIdx].PMKID, 16);
1274 tag = skb_put(skb,wmm_info_len);
1276 ieee80211_WMM_Info(ieee, &tag);
1278 tag = skb_put(skb,turbo_info_len);
1279 if(turbo_info_len) {
1280 ieee80211_TURBO_Info(ieee, &tag);
1283 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1284 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1286 tag = skb_put(skb, ht_cap_len);
1287 *tag++ = MFIE_TYPE_GENERIC;
1288 *tag++ = ht_cap_len - 2;
1289 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1290 tag += ht_cap_len -2;
1293 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1294 tag = skb_put(skb, realtek_ie_len);
1295 *tag++ = MFIE_TYPE_GENERIC;
1296 *tag++ = realtek_ie_len - 2;
1297 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1303 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1306 unsigned long flags;
1307 spin_lock_irqsave(&ieee->lock, flags);
1309 ieee->associate_seq++;
1311 /* don't scan, and avoid to have the RX path possibily
1312 * try again to associate. Even do not react to AUTH or
1313 * ASSOC response. Just wait for the retry wq to be scheduled.
1314 * Here we will check if there are good nets to associate
1315 * with, so we retry or just get back to NO_LINK and scanning
1317 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1318 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1319 ieee->softmac_stats.no_auth_rs++;
1321 IEEE80211_DEBUG_MGMT("Association failed\n");
1322 ieee->softmac_stats.no_ass_rs++;
1325 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1327 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1328 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1330 spin_unlock_irqrestore(&ieee->lock, flags);
1333 void ieee80211_associate_abort_cb(unsigned long dev)
1335 ieee80211_associate_abort((struct ieee80211_device *) dev);
1339 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1341 struct ieee80211_network *beacon = &ieee->current_network;
1342 struct sk_buff *skb;
1344 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1346 ieee->softmac_stats.tx_auth_rq++;
1347 skb=ieee80211_authentication_req(beacon, ieee, 0);
1350 ieee80211_associate_abort(ieee);
1352 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1353 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1354 softmac_mgmt_xmit(skb, ieee);
1355 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1356 if(!timer_pending(&ieee->associate_timer)){
1357 ieee->associate_timer.expires = jiffies + (HZ / 2);
1358 add_timer(&ieee->associate_timer);
1360 //dev_kfree_skb_any(skb);//edit by thomas
1364 void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1367 struct sk_buff *skb;
1368 struct ieee80211_network *beacon = &ieee->current_network;
1370 ieee->associate_seq++;
1371 ieee->softmac_stats.tx_auth_rq++;
1373 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1375 ieee80211_associate_abort(ieee);
1377 c = skb_put(skb, chlen+2);
1378 *(c++) = MFIE_TYPE_CHALLENGE;
1380 memcpy(c, challenge, chlen);
1382 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1384 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1386 softmac_mgmt_xmit(skb, ieee);
1387 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1392 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1394 struct sk_buff* skb;
1395 struct ieee80211_network *beacon = &ieee->current_network;
1397 del_timer_sync(&ieee->associate_timer);
1399 IEEE80211_DEBUG_MGMT("Sending association request\n");
1401 ieee->softmac_stats.tx_ass_rq++;
1402 skb=ieee80211_association_req(beacon, ieee);
1404 ieee80211_associate_abort(ieee);
1406 softmac_mgmt_xmit(skb, ieee);
1407 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1411 void ieee80211_associate_complete_wq(struct work_struct *work)
1413 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1415 printk(KERN_INFO "Associated successfully\n");
1416 ieee->is_roaming = false;
1417 if(ieee80211_is_54g(ieee->current_network) &&
1418 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1421 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1424 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1426 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1428 printk("Successfully associated, ht enabled\n");
1433 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1434 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1436 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1437 // To prevent the immediately calling watch_dog after association.
1438 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1440 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1441 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1443 ieee->link_change(ieee->dev);
1444 if(ieee->is_silent_reset == 0){
1445 printk("============>normal associate\n");
1446 notify_wx_assoc_event(ieee);
1448 else if(ieee->is_silent_reset == 1)
1450 printk("==================>silent reset associate\n");
1451 ieee->is_silent_reset = 0;
1454 if (ieee->data_hard_resume)
1455 ieee->data_hard_resume(ieee->dev);
1456 netif_carrier_on(ieee->dev);
1459 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1462 // struct net_device* dev = ieee->dev;
1463 del_timer_sync(&ieee->associate_timer);
1465 ieee->state = IEEE80211_LINKED;
1466 queue_work(ieee->wq, &ieee->associate_complete_wq);
1469 void ieee80211_associate_procedure_wq(struct work_struct *work)
1471 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1473 ieee->sync_scan_hurryup = 1;
1474 down(&ieee->wx_sem);
1476 if (ieee->data_hard_stop)
1477 ieee->data_hard_stop(ieee->dev);
1479 ieee80211_stop_scan(ieee);
1480 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1481 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1483 if(ieee->eRFPowerState == eRfOff)
1485 printk("=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",__FUNCTION__);
1489 ieee->associate_seq = 1;
1490 ieee80211_associate_step1(ieee);
1495 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1497 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1498 int tmp_ssid_len = 0;
1500 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1502 /* we are interested in new new only if we are not associated
1503 * and we are not associating / authenticating
1505 if (ieee->state != IEEE80211_NOLINK)
1508 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1511 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1514 if ((ieee->iw_mode == IW_MODE_ADHOC) && (net->channel > ieee->ibss_maxjoin_chal))
1517 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1518 /* if the user specified the AP MAC, we need also the essid
1519 * This could be obtained by beacons or, if the network does not
1520 * broadcast it, it can be put manually.
1522 apset = ieee->wap_set;
1523 ssidset = ieee->ssid_set;
1524 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1525 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1526 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1527 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1530 if ( /* if the user set the AP check if match.
1531 * if the network does not broadcast essid we check the user supplyed ANY essid
1532 * if the network does broadcast and the user does not set essid it is OK
1533 * if the network does broadcast and the user did set essid chech if essid match
1535 ( apset && apmatch &&
1536 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1537 /* if the ap is not set, check that the user set the bssid
1538 * and the network does bradcast and that those two bssid matches
1540 (!apset && ssidset && ssidbroad && ssidmatch)
1542 /* if the essid is hidden replace it with the
1543 * essid provided by the user.
1546 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1547 tmp_ssid_len = ieee->current_network.ssid_len;
1549 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1552 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1553 ieee->current_network.ssid_len = tmp_ssid_len;
1555 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);
1557 //ieee->pHTInfo->IOTAction = 0;
1558 HTResetIOTSetting(ieee->pHTInfo);
1559 if (ieee->iw_mode == IW_MODE_INFRA){
1560 /* Join the network for the first time */
1561 ieee->AsocRetryCount = 0;
1562 //for HT by amy 080514
1563 if((ieee->current_network.qos_data.supported == 1) &&
1564 ieee->current_network.bssht.bdSupportHT)
1565 /*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.*/
1567 // ieee->pHTInfo->bCurrentHTSupport = true;
1568 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1572 ieee->pHTInfo->bCurrentHTSupport = false;
1575 ieee->state = IEEE80211_ASSOCIATING;
1576 if(ieee->LedControlHandler != NULL)
1577 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK);
1578 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1580 if(ieee80211_is_54g(ieee->current_network) &&
1581 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1583 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1584 printk(KERN_INFO"Using G rates\n");
1587 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1588 printk(KERN_INFO"Using B rates\n");
1590 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1591 ieee->state = IEEE80211_LINKED;
1599 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1601 unsigned long flags;
1602 struct ieee80211_network *target;
1604 spin_lock_irqsave(&ieee->lock, flags);
1606 list_for_each_entry(target, &ieee->network_list, list) {
1608 /* if the state become different that NOLINK means
1609 * we had found what we are searching for
1612 if (ieee->state != IEEE80211_NOLINK)
1615 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1616 ieee80211_softmac_new_net(ieee, target);
1619 spin_unlock_irqrestore(&ieee->lock, flags);
1624 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1626 struct ieee80211_authentication *a;
1628 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1629 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1633 a = (struct ieee80211_authentication*) skb->data;
1634 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1635 t = skb->data + sizeof(struct ieee80211_authentication);
1637 if(*(t++) == MFIE_TYPE_CHALLENGE){
1639 *challenge = kmalloc(*chlen, GFP_ATOMIC);
1640 memcpy(*challenge, t, *chlen);
1644 return cpu_to_le16(a->status);
1649 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1651 struct ieee80211_authentication *a;
1653 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1654 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1657 a = (struct ieee80211_authentication*) skb->data;
1659 memcpy(dest,a->header.addr2, ETH_ALEN);
1661 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1662 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1664 return WLAN_STATUS_SUCCESS;
1667 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1674 struct ieee80211_hdr_3addr *header =
1675 (struct ieee80211_hdr_3addr *) skb->data;
1677 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1678 return -1; /* corrupted */
1680 if((memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) != 0)&&
1681 (memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) != 0)) {
1685 if(memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) == 0) {
1688 if(memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) == 0) {
1690 memcpy(src,header->addr2, ETH_ALEN);
1692 skbend = (u8*)skb->data + skb->len;
1694 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1696 while (tag+1 < skbend){
1702 tag++; /* point to the len field */
1703 tag = tag + *(tag); /* point to the last data byte of the tag */
1704 tag++; /* point to the next tag */
1707 if (ssidlen == 0) return 1;
1709 if (!ssid) return 1; /* ssid not found in tagged param */
1710 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1714 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1716 struct ieee80211_assoc_request_frame *a;
1718 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1719 sizeof(struct ieee80211_info_element))) {
1721 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1725 a = (struct ieee80211_assoc_request_frame*) skb->data;
1727 memcpy(dest,a->header.addr2,ETH_ALEN);
1732 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1734 struct ieee80211_assoc_response_frame *response_head;
1737 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1738 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1742 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1743 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1745 status_code = le16_to_cpu(response_head->status);
1746 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1747 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1748 ((ieee->mode == IEEE_G) &&
1749 (ieee->current_network.mode == IEEE_N_24G) &&
1750 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1751 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1753 ieee->AsocRetryCount = 0;
1756 return le16_to_cpu(response_head->status);
1760 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1764 ieee->softmac_stats.rx_probe_rq++;
1765 if (probe_rq_parse(ieee, skb, dest)){
1766 ieee->softmac_stats.tx_probe_rs++;
1767 ieee80211_resp_to_probe(ieee, dest);
1772 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1776 ieee->softmac_stats.rx_auth_rq++;
1778 status = auth_rq_parse(skb, dest);
1780 ieee80211_resp_to_auth(ieee, status, dest);
1786 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1791 ieee->softmac_stats.rx_ass_rq++;
1792 if (assoc_rq_parse(skb,dest) != -1){
1793 ieee80211_resp_to_assoc_rq(ieee, dest);
1796 printk(KERN_INFO"New client associated: %pM\n", dest);
1802 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1805 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1808 softmac_ps_mgmt_xmit(buf, ieee);
1813 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1815 int timeout = ieee->ps_timeout;
1817 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1818 ieee->iw_mode != IW_MODE_INFRA ||
1819 ieee->state != IEEE80211_LINKED)
1823 dtim = ieee->current_network.dtim_data;
1824 if(!(dtim & IEEE80211_DTIM_VALID))
1826 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1827 //printk("VALID\n");
1828 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1830 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1833 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1836 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1839 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1840 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1844 *time_l = ieee->current_network.last_dtim_sta_time[0]
1845 + (ieee->current_network.beacon_interval);
1849 *time_h = ieee->current_network.last_dtim_sta_time[1];
1850 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1859 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1865 unsigned long flags,flags2;
1867 spin_lock_irqsave(&ieee->lock, flags);
1869 if((ieee->ps == IEEE80211_PS_DISABLED ||
1870 ieee->iw_mode != IW_MODE_INFRA ||
1871 ieee->state != IEEE80211_LINKED)){
1873 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1875 ieee80211_sta_wakeup(ieee, 1);
1877 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1880 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1881 /* 2 wake, 1 sleep, 0 do nothing */
1887 if(ieee->sta_sleep == 1)
1888 ieee->enter_sleep_state(ieee->dev,th,tl);
1890 else if(ieee->sta_sleep == 0){
1891 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1893 if(ieee->ps_is_queue_empty(ieee->dev)){
1896 ieee->sta_sleep = 2;
1898 ieee->ack_tx_to_ieee = 1;
1900 ieee80211_sta_ps_send_null_frame(ieee,1);
1905 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1910 }else if(sleep == 2){
1911 //#warning CHECK_LOCK_HERE
1912 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1914 ieee80211_sta_wakeup(ieee,1);
1916 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1920 spin_unlock_irqrestore(&ieee->lock, flags);
1924 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1926 if(ieee->sta_sleep == 0){
1928 printk("Warning: driver is probably failing to report TX ps error\n");
1929 ieee->ack_tx_to_ieee = 1;
1930 ieee80211_sta_ps_send_null_frame(ieee, 0);
1936 if(ieee->sta_sleep == 1)
1937 ieee->sta_wake_up(ieee->dev);
1939 ieee->sta_sleep = 0;
1942 ieee->ack_tx_to_ieee = 1;
1943 ieee80211_sta_ps_send_null_frame(ieee, 0);
1947 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1949 unsigned long flags,flags2;
1951 spin_lock_irqsave(&ieee->lock, flags);
1953 if(ieee->sta_sleep == 2){
1954 /* Null frame with PS bit set */
1956 ieee->sta_sleep = 1;
1957 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1959 /* if the card report not success we can't be sure the AP
1960 * has not RXed so we can't assume the AP believe us awake
1963 /* 21112005 - tx again null without PS bit if lost */
1966 if((ieee->sta_sleep == 0) && !success){
1967 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1968 ieee80211_sta_ps_send_null_frame(ieee, 0);
1969 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1972 spin_unlock_irqrestore(&ieee->lock, flags);
1974 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1976 struct rtl_ieee80211_hdr *header =
1977 (struct rtl_ieee80211_hdr *)skb->data;
1978 u8* act = ieee80211_get_payload(header);
1980 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1983 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1991 if (*act == ACT_ADDBAREQ)
1992 ieee80211_rx_ADDBAReq(ieee, skb);
1993 else if (*act == ACT_ADDBARSP)
1994 ieee80211_rx_ADDBARsp(ieee, skb);
1995 else if (*act == ACT_DELBA)
1996 ieee80211_rx_DELBA(ieee, skb);
2005 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2006 struct ieee80211_rx_stats *rx_stats, u16 type,
2009 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2014 struct ieee80211_assoc_response_frame *assoc_resp;
2015 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2017 if(!ieee->proto_started)
2020 switch (WLAN_FC_GET_STYPE(header->frame_control)) {
2022 case IEEE80211_STYPE_ASSOC_RESP:
2023 case IEEE80211_STYPE_REASSOC_RESP:
2025 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2026 WLAN_FC_GET_STYPE(header->frame_control));
2027 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2028 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2029 ieee->iw_mode == IW_MODE_INFRA){
2030 struct ieee80211_network network_resp;
2031 struct ieee80211_network *network = &network_resp;
2033 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2034 ieee->state=IEEE80211_LINKED;
2035 ieee->assoc_id = aid;
2036 ieee->softmac_stats.rx_ass_ok++;
2037 /* station support qos */
2038 /* Let the register setting defaultly with Legacy station */
2039 if(ieee->qos_support) {
2040 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2041 memset(network, 0, sizeof(*network));
2042 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2043 rx_stats->len - sizeof(*assoc_resp),\
2048 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2049 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2050 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2052 if (ieee->handle_assoc_response != NULL)
2053 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2055 ieee80211_associate_complete(ieee);
2057 /* aid could not been allocated */
2058 ieee->softmac_stats.rx_ass_err++;
2060 "Association response status code 0x%x\n",
2062 IEEE80211_DEBUG_MGMT(
2063 "Association response status code 0x%x\n",
2065 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2066 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2068 ieee80211_associate_abort(ieee);
2074 case IEEE80211_STYPE_ASSOC_REQ:
2075 case IEEE80211_STYPE_REASSOC_REQ:
2077 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2078 ieee->iw_mode == IW_MODE_MASTER)
2080 ieee80211_rx_assoc_rq(ieee, skb);
2083 case IEEE80211_STYPE_AUTH:
2085 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2086 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2087 ieee->iw_mode == IW_MODE_INFRA){
2089 IEEE80211_DEBUG_MGMT("Received authentication response");
2091 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2092 if(ieee->open_wep || !challenge){
2093 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2094 ieee->softmac_stats.rx_auth_rs_ok++;
2095 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2097 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2099 // WEP or TKIP encryption
2100 if(IsHTHalfNmodeAPs(ieee))
2102 bSupportNmode = true;
2103 bHalfSupportNmode = true;
2107 bSupportNmode = false;
2108 bHalfSupportNmode = false;
2110 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2113 /* Dummy wirless mode setting to avoid encryption issue */
2116 ieee->SetWirelessMode(ieee->dev, \
2117 ieee->current_network.mode);
2121 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2124 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2126 printk("===============>entern half N mode\n");
2127 ieee->bHalfWirelessN24GMode = true;
2130 ieee->bHalfWirelessN24GMode = false;
2132 ieee80211_associate_step2(ieee);
2134 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2137 ieee->softmac_stats.rx_auth_rs_err++;
2138 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2140 printk("Authentication respose status code 0x%x",errcode);
2141 ieee80211_associate_abort(ieee);
2144 }else if (ieee->iw_mode == IW_MODE_MASTER){
2145 ieee80211_rx_auth_rq(ieee, skb);
2150 case IEEE80211_STYPE_PROBE_REQ:
2152 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2153 ((ieee->iw_mode == IW_MODE_ADHOC ||
2154 ieee->iw_mode == IW_MODE_MASTER) &&
2155 ieee->state == IEEE80211_LINKED)){
2156 ieee80211_rx_probe_rq(ieee, skb);
2160 case IEEE80211_STYPE_DISASSOC:
2161 case IEEE80211_STYPE_DEAUTH:
2162 /* FIXME for now repeat all the association procedure
2163 * both for disassociation and deauthentication
2165 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2166 ieee->state == IEEE80211_LINKED &&
2167 ieee->iw_mode == IW_MODE_INFRA){
2168 printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason);
2169 ieee->state = IEEE80211_ASSOCIATING;
2170 ieee->softmac_stats.reassoc++;
2171 ieee->is_roaming = true;
2172 ieee80211_disassociate(ieee);
2173 RemovePeerTS(ieee, header->addr2);
2174 if(ieee->LedControlHandler != NULL)
2175 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); //added by amy for LED 090318
2176 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2179 case IEEE80211_STYPE_MANAGE_ACT:
2180 ieee80211_process_action(ieee,skb);
2190 /* following are for a simplier TX queue management.
2191 * Instead of using netif_[stop/wake]_queue the driver
2192 * will uses these two function (plus a reset one), that
2193 * will internally uses the kernel netif_* and takes
2194 * care of the ieee802.11 fragmentation.
2195 * So the driver receives a fragment per time and might
2196 * call the stop function when it want without take care
2197 * to have enough room to TX an entire packet.
2198 * This might be useful if each fragment need it's own
2199 * descriptor, thus just keep a total free memory > than
2200 * the max fragmentation threshold is not enough.. If the
2201 * ieee802.11 stack passed a TXB struct then you needed
2202 * to keep N free descriptors where
2203 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2204 * In this way you need just one and the 802.11 stack
2205 * will take care of buffering fragments and pass them to
2206 * to the driver later, when it wakes the queue.
2208 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2211 unsigned int queue_index = txb->queue_index;
2212 unsigned long flags;
2214 cb_desc *tcb_desc = NULL;
2216 spin_lock_irqsave(&ieee->lock,flags);
2218 /* called with 2nd parm 0, no tx mgmt lock required */
2219 ieee80211_sta_wakeup(ieee,0);
2221 /* update the tx status */
2222 ieee->stats.tx_bytes += txb->payload_size;
2223 ieee->stats.tx_packets++;
2224 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2225 if(tcb_desc->bMulticast) {
2226 ieee->stats.multicast++;
2229 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2230 for(i = 0; i < txb->nr_frags; i++) {
2231 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2232 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2233 (ieee->queue_stop)) {
2234 /* insert the skb packet to the wait queue */
2235 /* as for the completion function, it does not need
2236 * to check it any more.
2238 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2240 ieee->softmac_data_hard_start_xmit(
2242 ieee->dev,ieee->rate);
2246 ieee80211_txb_free(txb);
2248 spin_unlock_irqrestore(&ieee->lock,flags);
2252 /* called with ieee->lock acquired */
2253 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2256 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2258 if (ieee->queue_stop){
2259 ieee->tx_pending.frag = i;
2263 ieee->softmac_data_hard_start_xmit(
2264 ieee->tx_pending.txb->fragments[i],
2265 ieee->dev,ieee->rate);
2266 ieee->stats.tx_packets++;
2271 ieee80211_txb_free(ieee->tx_pending.txb);
2272 ieee->tx_pending.txb = NULL;
2276 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2278 unsigned long flags;
2280 spin_lock_irqsave(&ieee->lock,flags);
2281 init_mgmt_queue(ieee);
2282 if (ieee->tx_pending.txb){
2283 ieee80211_txb_free(ieee->tx_pending.txb);
2284 ieee->tx_pending.txb = NULL;
2286 ieee->queue_stop = 0;
2287 spin_unlock_irqrestore(&ieee->lock,flags);
2291 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2294 unsigned long flags;
2295 struct sk_buff *skb;
2296 struct ieee80211_hdr_3addr *header;
2298 spin_lock_irqsave(&ieee->lock,flags);
2299 if (! ieee->queue_stop) goto exit;
2301 ieee->queue_stop = 0;
2303 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2304 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2306 header = (struct ieee80211_hdr_3addr *) skb->data;
2308 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2310 if (ieee->seq_ctrl[0] == 0xFFF)
2311 ieee->seq_ctrl[0] = 0;
2313 ieee->seq_ctrl[0]++;
2315 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2318 if (!ieee->queue_stop && ieee->tx_pending.txb)
2319 ieee80211_resume_tx(ieee);
2321 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2322 ieee->softmac_stats.swtxawake++;
2323 netif_wake_queue(ieee->dev);
2327 spin_unlock_irqrestore(&ieee->lock,flags);
2331 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2334 if (! netif_queue_stopped(ieee->dev)){
2335 netif_stop_queue(ieee->dev);
2336 ieee->softmac_stats.swtxstop++;
2338 ieee->queue_stop = 1;
2343 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2346 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2348 /* an IBSS cell address must have the two less significant
2349 * bits of the first byte = 2
2351 ieee->current_network.bssid[0] &= ~0x01;
2352 ieee->current_network.bssid[0] |= 0x02;
2355 /* called in user context only */
2356 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2360 if (ieee->current_network.ssid_len == 0){
2361 strncpy(ieee->current_network.ssid,
2362 IEEE80211_DEFAULT_TX_ESSID,
2365 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2369 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2371 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2372 ieee->state = IEEE80211_LINKED;
2373 ieee->link_change(ieee->dev);
2374 notify_wx_assoc_event(ieee);
2376 if (ieee->data_hard_resume)
2377 ieee->data_hard_resume(ieee->dev);
2379 netif_carrier_on(ieee->dev);
2382 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2386 if (ieee->data_hard_resume)
2387 ieee->data_hard_resume(ieee->dev);
2389 netif_carrier_on(ieee->dev);
2393 void ieee80211_start_ibss_wq(struct work_struct *work)
2396 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2397 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2398 /* iwconfig mode ad-hoc will schedule this and return
2399 * on the other hand this will block further iwconfig SET
2400 * operations because of the wx_sem hold.
2401 * Anyway some most set operations set a flag to speed-up
2402 * (abort) this wq (when syncro scanning) before sleeping
2405 if(!ieee->proto_started){
2406 printk("==========oh driver down return\n");
2409 down(&ieee->wx_sem);
2410 //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
2411 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2413 if (ieee->current_network.ssid_len == 0){
2414 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2415 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2419 /* check if we have this cell in our network list */
2420 ieee80211_softmac_check_all_nets(ieee);
2423 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2424 if (ieee->state == IEEE80211_NOLINK)
2425 ieee->current_network.channel = ieee->IbssStartChnl;
2426 /* if not then the state is not linked. Maybe the user swithced to
2427 * ad-hoc mode just after being in monitor mode, or just after
2428 * being very few time in managed mode (so the card have had no
2429 * time to scan all the chans..) or we have just run up the iface
2430 * after setting ad-hoc mode. So we have to give another try..
2431 * Here, in ibss mode, should be safe to do this without extra care
2432 * (in bss mode we had to make sure no-one tryed to associate when
2433 * we had just checked the ieee->state and we was going to start the
2434 * scan) beacause in ibss mode the ieee80211_new_net function, when
2435 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2436 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2437 * scan, that will stop at the first round because it sees the state
2440 if (ieee->state == IEEE80211_NOLINK)
2441 ieee80211_start_scan_syncro(ieee);
2443 /* the network definitively is not here.. create a new cell */
2444 if (ieee->state == IEEE80211_NOLINK){
2445 printk("creating new IBSS cell\n");
2447 ieee80211_randomize_cell(ieee);
2449 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2451 ieee->current_network.rates_len = 4;
2453 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2454 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2455 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2456 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2459 ieee->current_network.rates_len = 0;
2461 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2462 ieee->current_network.rates_ex_len = 8;
2464 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2465 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2466 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2467 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2468 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2469 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2470 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2471 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2475 ieee->current_network.rates_ex_len = 0;
2479 // By default, WMM function will be disabled in IBSS mode
2480 ieee->current_network.QoS_Enable = 0;
2481 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2482 ieee->current_network.atim_window = 0;
2483 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2484 if(ieee->short_slot)
2485 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2489 ieee->state = IEEE80211_LINKED;
2491 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2492 ieee->link_change(ieee->dev);
2493 if(ieee->LedControlHandler != NULL)
2494 ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
2495 notify_wx_assoc_event(ieee);
2497 ieee80211_start_send_beacons(ieee);
2499 if (ieee->data_hard_resume)
2500 ieee->data_hard_resume(ieee->dev);
2501 netif_carrier_on(ieee->dev);
2506 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2508 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2511 /* this is called only in user context, with wx_sem held */
2512 void ieee80211_start_bss(struct ieee80211_device *ieee)
2514 unsigned long flags;
2516 // Ref: 802.11d 11.1.3.3
2517 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2519 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2521 if(! ieee->bGlobalDomain)
2526 /* check if we have already found the net we
2527 * are interested in (if any).
2528 * if not (we are disassociated and we are not
2529 * in associating / authenticating phase) start the background scanning.
2531 ieee80211_softmac_check_all_nets(ieee);
2533 /* ensure no-one start an associating process (thus setting
2534 * the ieee->state to ieee80211_ASSOCIATING) while we
2535 * have just cheked it and we are going to enable scan.
2536 * The ieee80211_new_net function is always called with
2537 * lock held (from both ieee80211_softmac_check_all_nets and
2538 * the rx path), so we cannot be in the middle of such function
2540 spin_lock_irqsave(&ieee->lock, flags);
2542 if (ieee->state == IEEE80211_NOLINK){
2543 ieee->actscanning = true;
2544 ieee80211_rtl_start_scan(ieee);
2546 spin_unlock_irqrestore(&ieee->lock, flags);
2549 void ieee80211_link_change_wq(struct work_struct *work)
2551 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2552 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, link_change_wq);
2554 ieee->link_change(ieee->dev);
2556 /* called only in userspace context */
2557 void ieee80211_disassociate(struct ieee80211_device *ieee)
2561 netif_carrier_off(ieee->dev);
2562 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2563 ieee80211_reset_queue(ieee);
2565 if (ieee->data_hard_stop)
2566 ieee->data_hard_stop(ieee->dev);
2567 if(IS_DOT11D_ENABLE(ieee))
2569 ieee->state = IEEE80211_NOLINK;
2570 ieee->is_set_key = false;
2572 queue_delayed_work(ieee->wq, &ieee->link_change_wq, 0);
2575 notify_wx_assoc_event(ieee);
2579 void ieee80211_associate_retry_wq(struct work_struct *work)
2581 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2582 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2583 unsigned long flags;
2585 down(&ieee->wx_sem);
2586 if(!ieee->proto_started)
2589 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2592 /* until we do not set the state to IEEE80211_NOLINK
2593 * there are no possibility to have someone else trying
2594 * to start an association procdure (we get here with
2595 * ieee->state = IEEE80211_ASSOCIATING).
2596 * When we set the state to IEEE80211_NOLINK it is possible
2597 * that the RX path run an attempt to associate, but
2598 * both ieee80211_softmac_check_all_nets and the
2599 * RX path works with ieee->lock held so there are no
2600 * problems. If we are still disassociated then start a scan.
2601 * the lock here is necessary to ensure no one try to start
2602 * an association procedure when we have just checked the
2603 * state and we are going to start the scan.
2605 ieee->beinretry = true;
2606 ieee->state = IEEE80211_NOLINK;
2608 ieee80211_softmac_check_all_nets(ieee);
2610 spin_lock_irqsave(&ieee->lock, flags);
2612 if(ieee->state == IEEE80211_NOLINK)
2614 ieee->actscanning = true;
2615 ieee80211_rtl_start_scan(ieee);
2617 spin_unlock_irqrestore(&ieee->lock, flags);
2619 ieee->beinretry = false;
2624 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2626 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2628 struct sk_buff *skb;
2629 struct ieee80211_probe_response *b;
2631 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2636 b = (struct ieee80211_probe_response *) skb->data;
2637 b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON);
2643 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2645 struct sk_buff *skb;
2646 struct ieee80211_probe_response *b;
2648 skb = ieee80211_get_beacon_(ieee);
2652 b = (struct ieee80211_probe_response *) skb->data;
2653 b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2655 if (ieee->seq_ctrl[0] == 0xFFF)
2656 ieee->seq_ctrl[0] = 0;
2658 ieee->seq_ctrl[0]++;
2663 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2665 ieee->sync_scan_hurryup = 1;
2666 down(&ieee->wx_sem);
2667 ieee80211_stop_protocol(ieee);
2672 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2674 if (!ieee->proto_started)
2677 ieee->proto_started = 0;
2679 ieee80211_stop_send_beacons(ieee);
2680 del_timer_sync(&ieee->associate_timer);
2681 cancel_delayed_work(&ieee->associate_retry_wq);
2682 cancel_delayed_work(&ieee->start_ibss_wq);
2683 cancel_delayed_work(&ieee->link_change_wq);
2684 ieee80211_stop_scan(ieee);
2686 ieee80211_disassociate(ieee);
2687 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2690 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2692 ieee->sync_scan_hurryup = 0;
2693 down(&ieee->wx_sem);
2694 ieee80211_start_protocol(ieee);
2698 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2702 if (ieee->proto_started)
2705 ieee->proto_started = 1;
2707 if (ieee->current_network.channel == 0){
2710 if (ch > MAX_CHANNEL_NUMBER)
2711 return; /* no channel found */
2712 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2713 ieee->current_network.channel = ch;
2716 if (ieee->current_network.beacon_interval == 0)
2717 ieee->current_network.beacon_interval = 100;
2719 for(i = 0; i < 17; i++) {
2720 ieee->last_rxseq_num[i] = -1;
2721 ieee->last_rxfrag_num[i] = -1;
2722 ieee->last_packet_time[i] = 0;
2725 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2728 /* if the user set the MAC of the ad-hoc cell and then
2729 * switch to managed mode, shall we make sure that association
2730 * attempts does not fail just because the user provide the essid
2731 * and the nic is still checking for the AP MAC ??
2733 if (ieee->iw_mode == IW_MODE_INFRA)
2734 ieee80211_start_bss(ieee);
2736 else if (ieee->iw_mode == IW_MODE_ADHOC)
2737 ieee80211_start_ibss(ieee);
2739 else if (ieee->iw_mode == IW_MODE_MASTER)
2740 ieee80211_start_master_bss(ieee);
2742 else if(ieee->iw_mode == IW_MODE_MONITOR)
2743 ieee80211_start_monitor_mode(ieee);
2747 #define DRV_NAME "Ieee80211"
2748 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2751 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2753 ieee->state = IEEE80211_NOLINK;
2754 ieee->sync_scan_hurryup = 0;
2755 for(i = 0; i < 5; i++) {
2756 ieee->seq_ctrl[i] = 0;
2758 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2759 if (!ieee->pDot11dInfo)
2760 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2761 //added for AP roaming
2762 ieee->LinkDetectInfo.SlotNum = 2;
2763 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2764 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2767 ieee->queue_stop = 0;
2769 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2772 ieee->proto_started = 0;
2773 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2775 ieee->ps = IEEE80211_PS_DISABLED;
2776 ieee->sta_sleep = 0;
2777 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2778 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2779 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2780 ieee->actscanning = false;
2781 ieee->beinretry = false;
2782 ieee->is_set_key = false;
2783 init_mgmt_queue(ieee);
2785 ieee->sta_edca_param[0] = 0x0000A403;
2786 ieee->sta_edca_param[1] = 0x0000A427;
2787 ieee->sta_edca_param[2] = 0x005E4342;
2788 ieee->sta_edca_param[3] = 0x002F3262;
2789 ieee->aggregation = true;
2790 ieee->enable_rx_imm_BA = 1;
2791 ieee->tx_pending.txb = NULL;
2793 init_timer(&ieee->associate_timer);
2794 ieee->associate_timer.data = (unsigned long)ieee;
2795 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2797 init_timer(&ieee->beacon_timer);
2798 ieee->beacon_timer.data = (unsigned long) ieee;
2799 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2801 #ifdef PF_SYNCTHREAD
2802 ieee->wq = create_workqueue(DRV_NAME,0);
2804 ieee->wq = create_workqueue(DRV_NAME);
2807 INIT_DELAYED_WORK(&ieee->link_change_wq,ieee80211_link_change_wq);
2808 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2809 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2810 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2811 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2812 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2813 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2815 sema_init(&ieee->wx_sem, 1);
2816 sema_init(&ieee->scan_sem, 1);
2818 spin_lock_init(&ieee->mgmt_tx_lock);
2819 spin_lock_init(&ieee->beacon_lock);
2821 tasklet_init(&ieee->ps_task,
2822 (void(*)(unsigned long)) ieee80211_sta_ps,
2823 (unsigned long)ieee);
2827 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2829 down(&ieee->wx_sem);
2830 if(NULL != ieee->pDot11dInfo)
2832 kfree(ieee->pDot11dInfo);
2833 ieee->pDot11dInfo = NULL;
2835 del_timer_sync(&ieee->associate_timer);
2837 cancel_delayed_work(&ieee->associate_retry_wq);
2838 destroy_workqueue(ieee->wq);
2843 /********************************************************
2844 * Start of WPA code. *
2845 * this is stolen from the ipw2200 driver *
2846 ********************************************************/
2849 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2851 /* This is called when wpa_supplicant loads and closes the driver
2853 printk("%s WPA\n",value ? "enabling" : "disabling");
2854 ieee->wpa_enabled = value;
2855 memset(ieee->ap_mac_addr, 0, 6); //reset ap_mac_addr everytime it starts wpa.
2860 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2862 /* make sure WPA is enabled */
2863 ieee80211_wpa_enable(ieee, 1);
2865 ieee80211_disassociate(ieee);
2869 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2875 case IEEE_MLME_STA_DEAUTH:
2879 case IEEE_MLME_STA_DISASSOC:
2880 ieee80211_disassociate(ieee);
2884 printk("Unknown MLME request: %d\n", command);
2892 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2893 struct ieee_param *param, int plen)
2897 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2898 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2901 if (param->u.wpa_ie.len) {
2902 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2907 kfree(ieee->wpa_ie);
2909 ieee->wpa_ie_len = param->u.wpa_ie.len;
2911 kfree(ieee->wpa_ie);
2912 ieee->wpa_ie = NULL;
2913 ieee->wpa_ie_len = 0;
2916 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2920 #define AUTH_ALG_OPEN_SYSTEM 0x1
2921 #define AUTH_ALG_SHARED_KEY 0x2
2922 #define AUTH_ALG_LEAP 0x4
2923 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2926 struct ieee80211_security sec = {
2927 .flags = SEC_AUTH_MODE,
2931 if (value & AUTH_ALG_SHARED_KEY) {
2932 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2934 ieee->auth_mode = 1;
2935 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2936 sec.auth_mode = WLAN_AUTH_OPEN;
2938 ieee->auth_mode = 0;
2940 else if (value & AUTH_ALG_LEAP){
2941 sec.auth_mode = RTL_WLAN_AUTH_LEAP;
2943 ieee->auth_mode = 2;
2947 if (ieee->set_security)
2948 ieee->set_security(ieee->dev, &sec);
2953 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2956 unsigned long flags;
2959 case IEEE_PARAM_WPA_ENABLED:
2960 ret = ieee80211_wpa_enable(ieee, value);
2963 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2964 ieee->tkip_countermeasures=value;
2967 case IEEE_PARAM_DROP_UNENCRYPTED: {
2970 * wpa_supplicant calls set_wpa_enabled when the driver
2971 * is loaded and unloaded, regardless of if WPA is being
2972 * used. No other calls are made which can be used to
2973 * determine if encryption will be used or not prior to
2974 * association being expected. If encryption is not being
2975 * used, drop_unencrypted is set to false, else true -- we
2976 * can use this to determine if the CAP_PRIVACY_ON bit should
2979 struct ieee80211_security sec = {
2980 .flags = SEC_ENABLED,
2983 ieee->drop_unencrypted = value;
2984 /* We only change SEC_LEVEL for open mode. Others
2985 * are set by ipw_wpa_set_encryption.
2988 sec.flags |= SEC_LEVEL;
2989 sec.level = SEC_LEVEL_0;
2992 sec.flags |= SEC_LEVEL;
2993 sec.level = SEC_LEVEL_1;
2995 if (ieee->set_security)
2996 ieee->set_security(ieee->dev, &sec);
3000 case IEEE_PARAM_PRIVACY_INVOKED:
3001 ieee->privacy_invoked=value;
3004 case IEEE_PARAM_AUTH_ALGS:
3005 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3008 case IEEE_PARAM_IEEE_802_1X:
3009 ieee->ieee802_1x=value;
3011 case IEEE_PARAM_WPAX_SELECT:
3012 // added for WPA2 mixed mode
3013 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3014 ieee->wpax_type_set = 1;
3015 ieee->wpax_type_notify = value;
3016 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3020 printk("Unknown WPA param: %d\n",name);
3027 /* implementation borrowed from hostap driver */
3029 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3030 struct ieee_param *param, int param_len)
3034 struct ieee80211_crypto_ops *ops;
3035 struct ieee80211_crypt_data **crypt;
3037 struct ieee80211_security sec = {
3041 param->u.crypt.err = 0;
3042 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3045 (int) ((char *) param->u.crypt.key - (char *) param) +
3046 param->u.crypt.key_len) {
3047 printk("Len mismatch %d, %d\n", param_len,
3048 param->u.crypt.key_len);
3051 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3052 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3053 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3054 if (param->u.crypt.idx >= WEP_KEYS)
3056 crypt = &ieee->crypt[param->u.crypt.idx];
3061 if (strcmp(param->u.crypt.alg, "none") == 0) {
3066 sec.level = SEC_LEVEL_0;
3067 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3068 ieee80211_crypt_delayed_deinit(ieee, crypt);
3075 sec.flags |= SEC_ENABLED;
3077 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3078 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3079 strcmp(param->u.crypt.alg, "TKIP"))
3080 goto skip_host_crypt;
3082 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3083 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3084 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3085 /* set WEP40 first, it will be modified according to WEP104 or
3086 * WEP40 at other place */
3087 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3088 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3089 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3090 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3092 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3093 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3098 if (*crypt == NULL || (*crypt)->ops != ops) {
3099 struct ieee80211_crypt_data *new_crypt;
3101 ieee80211_crypt_delayed_deinit(ieee, crypt);
3103 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3104 if (new_crypt == NULL) {
3108 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3109 new_crypt->ops = ops;
3113 new_crypt->ops->init(param->u.crypt.idx);
3115 if (new_crypt->priv == NULL) {
3117 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3125 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3126 (*crypt)->ops->set_key(param->u.crypt.key,
3127 param->u.crypt.key_len, param->u.crypt.seq,
3128 (*crypt)->priv) < 0) {
3129 printk("key setting failed\n");
3130 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3136 if (param->u.crypt.set_tx) {
3137 ieee->tx_keyidx = param->u.crypt.idx;
3138 sec.active_key = param->u.crypt.idx;
3139 sec.flags |= SEC_ACTIVE_KEY;
3141 sec.flags &= ~SEC_ACTIVE_KEY;
3143 if (param->u.crypt.alg != NULL) {
3144 memcpy(sec.keys[param->u.crypt.idx],
3146 param->u.crypt.key_len);
3147 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3148 sec.flags |= (1 << param->u.crypt.idx);
3150 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3151 sec.flags |= SEC_LEVEL;
3152 sec.level = SEC_LEVEL_1;
3153 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3154 sec.flags |= SEC_LEVEL;
3155 sec.level = SEC_LEVEL_2;
3156 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3157 sec.flags |= SEC_LEVEL;
3158 sec.level = SEC_LEVEL_3;
3162 if (ieee->set_security)
3163 ieee->set_security(ieee->dev, &sec);
3165 /* Do not reset port if card is in Managed mode since resetting will
3166 * generate new IEEE 802.11 authentication which may end up in looping
3167 * with IEEE 802.1X. If your hardware requires a reset after WEP
3168 * configuration (for example... Prism2), implement the reset_port in
3169 * the callbacks structures used to initialize the 802.11 stack. */
3170 if (ieee->reset_on_keychange &&
3171 ieee->iw_mode != IW_MODE_INFRA &&
3173 ieee->reset_port(ieee->dev)) {
3174 printk("reset_port failed\n");
3175 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3182 inline struct sk_buff *ieee80211_disassociate_skb(
3183 struct ieee80211_network *beacon,
3184 struct ieee80211_device *ieee,
3187 struct sk_buff *skb;
3188 struct ieee80211_disassoc *disass;
3190 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3194 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3195 disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3196 disass->header.duration_id = 0;
3198 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3199 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3200 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3202 disass->reason = asRsn;
3209 struct ieee80211_device *ieee,
3214 struct ieee80211_network *beacon = &ieee->current_network;
3215 struct sk_buff *skb;
3216 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3218 softmac_mgmt_xmit(skb, ieee);
3219 //dev_kfree_skb_any(skb);//edit by thomas
3223 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3225 struct ieee_param *param;
3228 down(&ieee->wx_sem);
3230 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3235 param = kmalloc(p->length, GFP_KERNEL);
3240 if (copy_from_user(param, p->pointer, p->length)) {
3246 switch (param->cmd) {
3248 case IEEE_CMD_SET_WPA_PARAM:
3249 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3250 param->u.wpa_param.value);
3253 case IEEE_CMD_SET_WPA_IE:
3254 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3257 case IEEE_CMD_SET_ENCRYPTION:
3258 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3262 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3263 param->u.mlme.reason_code);
3267 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3272 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3282 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3284 union iwreq_data wrqu;
3285 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3286 if (ieee->state == IEEE80211_LINKED)
3287 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3289 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3290 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);