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>
28 u8 rsn_authen_cipher_suite[16][4] = {
29 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
30 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
31 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
32 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
33 {0x00,0x0F,0xAC,0x04}, //CCMP
34 {0x00,0x0F,0xAC,0x05}, //WEP-104
37 short ieee80211_is_54g(struct ieee80211_network net)
39 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
42 short ieee80211_is_shortslot(struct ieee80211_network net)
44 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
47 /* returns the total length needed for pleacing the RATE MFIE
48 * tag and the EXTENDED RATE MFIE tag if needed.
49 * It encludes two bytes per tag for the tag itself and its len
51 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
53 unsigned int rate_len = 0;
55 if (ieee->modulation & IEEE80211_CCK_MODULATION)
56 rate_len = IEEE80211_CCK_RATE_LEN + 2;
58 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
60 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
65 /* pleace the MFIE rate, tag to the memory (double) poined.
66 * Then it updates the pointer so that
67 * it points after the new MFIE tag added.
69 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
73 if (ieee->modulation & IEEE80211_CCK_MODULATION){
74 *tag++ = MFIE_TYPE_RATES;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
78 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
79 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
82 /* We may add an option for custom rates that specific HW might support */
86 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
90 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
92 *tag++ = MFIE_TYPE_RATES_EX;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
100 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
101 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
105 /* We may add an option for custom rates that specific HW might support */
110 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
113 *tag++ = MFIE_TYPE_GENERIC; //0
122 if(ieee->current_network.wmm_info & 0x80) {
123 *tag++ = 0x0f|MAX_SP_Len;
134 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
137 *tag++ = MFIE_TYPE_GENERIC; //0
148 printk(KERN_ALERT "This is enable turbo mode IE process\n");
152 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
155 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
158 * if the queue is full but we have newer frames then
159 * just overwrites the oldest.
161 * if (nh == ieee->mgmt_queue_tail)
164 ieee->mgmt_queue_head = nh;
165 ieee->mgmt_queue_ring[nh] = skb;
170 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
174 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
177 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
179 ieee->mgmt_queue_tail =
180 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
185 void init_mgmt_queue(struct ieee80211_device *ieee)
187 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
190 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
192 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
195 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
196 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
199 rate = ieee->basic_rate & 0x7f;
202 // 2005.01.26, by rcnjko.
203 if(ieee->mode == IEEE_A||
204 ieee->mode== IEEE_N_5G||
205 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
212 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
213 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
215 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
225 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
227 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
230 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
231 struct ieee80211_hdr_3addr *header=
232 (struct ieee80211_hdr_3addr *) skb->data;
234 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
235 spin_lock_irqsave(&ieee->lock, flags);
237 /* called with 2nd param 0, no mgmt lock required */
238 ieee80211_sta_wakeup(ieee,0);
240 tcb_desc->queue_index = MGNT_QUEUE;
241 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
242 tcb_desc->RATRIndex = 7;
243 tcb_desc->bTxDisableRateFallBack = 1;
244 tcb_desc->bTxUseDriverAssingedRate = 1;
247 if(ieee->queue_stop){
248 enqueue_mgmt(ieee,skb);
250 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
252 if (ieee->seq_ctrl[0] == 0xFFF)
253 ieee->seq_ctrl[0] = 0;
257 /* avoid watchdog triggers */
258 // ieee->dev->trans_start = jiffies;
259 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
260 //dev_kfree_skb_any(skb);//edit by thomas
263 spin_unlock_irqrestore(&ieee->lock, flags);
265 spin_unlock_irqrestore(&ieee->lock, flags);
266 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
268 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
270 if (ieee->seq_ctrl[0] == 0xFFF)
271 ieee->seq_ctrl[0] = 0;
275 /* check wether the managed packet queued greater than 5 */
276 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
277 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
278 (ieee->queue_stop) ) {
279 /* insert the skb packet to the management queue */
280 /* as for the completion function, it does not need
281 * to check it any more.
283 //printk("%s():insert to waitqueue!\n",__FUNCTION__);
284 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
286 //printk("TX packet!\n");
287 ieee->softmac_hard_start_xmit(skb,ieee->dev);
288 //dev_kfree_skb_any(skb);//edit by thomas
290 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
294 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
297 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
298 struct ieee80211_hdr_3addr *header =
299 (struct ieee80211_hdr_3addr *) skb->data;
300 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
302 tcb_desc->queue_index = MGNT_QUEUE;
303 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
304 tcb_desc->RATRIndex = 7;
305 tcb_desc->bTxDisableRateFallBack = 1;
306 tcb_desc->bTxUseDriverAssingedRate = 1;
307 //printk("=============>%s()\n", __FUNCTION__);
310 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
312 if (ieee->seq_ctrl[0] == 0xFFF)
313 ieee->seq_ctrl[0] = 0;
317 /* avoid watchdog triggers */
318 // ieee->dev->trans_start = jiffies;
319 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
323 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
325 if (ieee->seq_ctrl[0] == 0xFFF)
326 ieee->seq_ctrl[0] = 0;
330 ieee->softmac_hard_start_xmit(skb,ieee->dev);
333 //dev_kfree_skb_any(skb);//edit by thomas
336 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
338 unsigned int len,rate_len;
341 struct ieee80211_probe_request *req;
343 len = ieee->current_network.ssid_len;
345 rate_len = ieee80211_MFIE_rate_len(ieee);
347 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
348 2 + len + rate_len + ieee->tx_headroom);
352 skb_reserve(skb, ieee->tx_headroom);
354 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
355 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
356 req->header.duration_id = 0; //FIXME: is this OK ?
358 memset(req->header.addr1, 0xff, ETH_ALEN);
359 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
360 memset(req->header.addr3, 0xff, ETH_ALEN);
362 tag = (u8 *) skb_put(skb,len+2+rate_len);
364 *tag++ = MFIE_TYPE_SSID;
366 memcpy(tag, ieee->current_network.ssid, len);
369 ieee80211_MFIE_Brate(ieee,&tag);
370 ieee80211_MFIE_Grate(ieee,&tag);
374 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
375 void ieee80211_send_beacon(struct ieee80211_device *ieee)
380 //unsigned long flags;
381 skb = ieee80211_get_beacon_(ieee);
384 softmac_mgmt_xmit(skb, ieee);
385 ieee->softmac_stats.tx_beacons++;
386 //dev_kfree_skb_any(skb);//edit by thomas
388 // ieee->beacon_timer.expires = jiffies +
389 // (MSECS( ieee->current_network.beacon_interval -5));
391 //spin_lock_irqsave(&ieee->beacon_lock,flags);
392 if(ieee->beacon_txing && ieee->ieee_up){
393 // if(!timer_pending(&ieee->beacon_timer))
394 // add_timer(&ieee->beacon_timer);
395 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
397 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
401 void ieee80211_send_beacon_cb(unsigned long _ieee)
403 struct ieee80211_device *ieee =
404 (struct ieee80211_device *) _ieee;
407 spin_lock_irqsave(&ieee->beacon_lock, flags);
408 ieee80211_send_beacon(ieee);
409 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
413 void ieee80211_send_probe(struct ieee80211_device *ieee)
417 skb = ieee80211_probe_req(ieee);
419 softmac_mgmt_xmit(skb, ieee);
420 ieee->softmac_stats.tx_probe_rq++;
421 //dev_kfree_skb_any(skb);//edit by thomas
425 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
427 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
428 ieee80211_send_probe(ieee);
429 ieee80211_send_probe(ieee);
433 /* this performs syncro scan blocking the caller until all channels
434 * in the allowed channel map has been checked.
436 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
440 u8 channel_map[MAX_CHANNEL_NUMBER+1];
441 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
443 down(&ieee->scan_sem);
450 if (ch > MAX_CHANNEL_NUMBER)
451 goto out; /* scan completed */
453 }while(!channel_map[ch]);
455 }while(!ieee->channel_map[ch]);
458 /* this fuction can be called in two situations
459 * 1- We have switched to ad-hoc mode and we are
460 * performing a complete syncro scan before conclude
461 * there are no interesting cell and to create a
462 * new one. In this case the link state is
463 * IEEE80211_NOLINK until we found an interesting cell.
464 * If so the ieee8021_new_net, called by the RX path
465 * will set the state to IEEE80211_LINKED, so we stop
467 * 2- We are linked and the root uses run iwlist scan.
468 * So we switch to IEEE80211_LINKED_SCANNING to remember
469 * that we are still logically linked (not interested in
470 * new network events, despite for updating the net list,
471 * but we are temporarly 'unlinked' as the driver shall
472 * not filter RX frames and the channel is changing.
473 * So the only situation in witch are interested is to check
474 * if the state become LINKED because of the #1 situation
477 if (ieee->state == IEEE80211_LINKED)
479 ieee->set_chan(ieee->dev, ch);
481 if(channel_map[ch] == 1)
483 ieee80211_send_probe_requests(ieee);
485 /* this prevent excessive time wait when we
486 * need to wait for a syncro scan to end..
488 if(ieee->state < IEEE80211_LINKED)
491 if (ieee->sync_scan_hurryup)
495 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
499 if(ieee->state < IEEE80211_LINKED){
500 ieee->actscanning = false;
504 ieee->sync_scan_hurryup = 0;
506 if(IS_DOT11D_ENABLE(ieee))
507 DOT11D_ScanComplete(ieee);
513 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
514 /* called both by wq with ieee->lock held */
515 void ieee80211_softmac_scan(struct ieee80211_device *ieee)
520 ieee->current_network.channel =
521 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
522 if (watchdog++ > MAX_CHANNEL_NUMBER)
523 return; /* no good chans */
525 }while(!ieee->channel_map[ieee->current_network.channel]);
528 schedule_task(&ieee->softmac_scan_wq);
532 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
533 void ieee80211_softmac_scan_wq(struct work_struct *work)
535 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
536 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
538 void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee)
541 static short watchdog = 0;
542 u8 last_channel = ieee->current_network.channel;
544 u8 channel_map[MAX_CHANNEL_NUMBER+1];
545 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
549 down(&ieee->scan_sem);
551 ieee->current_network.channel =
552 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
553 if (watchdog++ > MAX_CHANNEL_NUMBER)
555 //if current channel is not in channel map, set to default channel.
557 if (!channel_map[ieee->current_network.channel]);
559 if (!ieee->channel_map[ieee->current_network.channel]);
561 ieee->current_network.channel = 6;
562 goto out; /* no good chans */
565 }while(!channel_map[ieee->current_network.channel]);
567 }while(!ieee->channel_map[ieee->current_network.channel]);
569 if (ieee->scanning == 0 )
571 ieee->set_chan(ieee->dev, ieee->current_network.channel);
573 if(channel_map[ieee->current_network.channel] == 1)
575 ieee80211_send_probe_requests(ieee);
578 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
579 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
581 //ieee->scan_timer.expires = jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME);
582 if (ieee->scanning == 1)
583 mod_timer(&ieee->scan_timer,(jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME)));
590 if(IS_DOT11D_ENABLE(ieee))
591 DOT11D_ScanComplete(ieee);
593 ieee->current_network.channel = last_channel;
594 ieee->actscanning = false;
600 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
601 void ieee80211_softmac_scan_cb(unsigned long _dev)
604 struct ieee80211_device *ieee = (struct ieee80211_device *)_dev;
606 spin_lock_irqsave(&ieee->lock, flags);
607 ieee80211_softmac_scan(ieee);
608 spin_unlock_irqrestore(&ieee->lock, flags);
613 void ieee80211_beacons_start(struct ieee80211_device *ieee)
616 spin_lock_irqsave(&ieee->beacon_lock,flags);
618 ieee->beacon_txing = 1;
619 ieee80211_send_beacon(ieee);
621 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
624 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
628 spin_lock_irqsave(&ieee->beacon_lock,flags);
630 ieee->beacon_txing = 0;
631 del_timer_sync(&ieee->beacon_timer);
633 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
638 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
640 if(ieee->stop_send_beacons)
641 ieee->stop_send_beacons(ieee->dev);
642 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
643 ieee80211_beacons_stop(ieee);
647 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
649 if(ieee->start_send_beacons)
650 ieee->start_send_beacons(ieee->dev);
651 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
652 ieee80211_beacons_start(ieee);
656 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
658 // unsigned long flags;
660 //ieee->sync_scan_hurryup = 1;
662 down(&ieee->scan_sem);
663 // spin_lock_irqsave(&ieee->lock, flags);
665 if (ieee->scanning == 1){
668 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
669 cancel_delayed_work(&ieee->softmac_scan_wq);
671 del_timer_sync(&ieee->scan_timer);
675 // spin_unlock_irqrestore(&ieee->lock, flags);
679 void ieee80211_stop_scan(struct ieee80211_device *ieee)
681 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
682 ieee80211_softmac_stop_scan(ieee);
684 ieee->stop_scan(ieee->dev);
687 /* called with ieee->lock held */
688 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
691 if(ieee->ieee80211_ips_leave_wq != NULL)
692 ieee->ieee80211_ips_leave_wq(ieee->dev);
696 if(IS_DOT11D_ENABLE(ieee) )
698 if(IS_COUNTRY_IE_VALID(ieee))
700 RESET_CIE_WATCHDOG(ieee);
704 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
705 if (ieee->scanning == 0){
707 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
708 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
709 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
712 queue_work(ieee->wq, &ieee->softmac_scan_wq);
715 ieee80211_softmac_scan(ieee);
719 ieee->start_scan(ieee->dev);
723 /* called with wx_sem held */
724 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
727 if(IS_DOT11D_ENABLE(ieee) )
729 if(IS_COUNTRY_IE_VALID(ieee))
731 RESET_CIE_WATCHDOG(ieee);
735 ieee->sync_scan_hurryup = 0;
736 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
737 ieee80211_softmac_scan_syncro(ieee);
739 ieee->scan_syncro(ieee->dev);
743 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
744 struct ieee80211_device *ieee, int challengelen)
747 struct ieee80211_authentication *auth;
748 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
751 skb = dev_alloc_skb(len);
752 if (!skb) return NULL;
754 skb_reserve(skb, ieee->tx_headroom);
755 auth = (struct ieee80211_authentication *)
756 skb_put(skb, sizeof(struct ieee80211_authentication));
758 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
759 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
761 auth->header.duration_id = 0x013a; //FIXME
763 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
764 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
765 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
767 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
768 if(ieee->auth_mode == 0)
769 auth->algorithm = WLAN_AUTH_OPEN;
770 else if(ieee->auth_mode == 1)
771 auth->algorithm = WLAN_AUTH_SHARED_KEY;
772 else if(ieee->auth_mode == 2)
773 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
774 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
775 auth->transaction = cpu_to_le16(ieee->associate_seq);
776 ieee->associate_seq++;
778 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
785 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
789 struct ieee80211_probe_response *beacon_buf;
790 struct sk_buff *skb = NULL;
792 int atim_len,erp_len;
793 struct ieee80211_crypt_data* crypt;
795 char *ssid = ieee->current_network.ssid;
796 int ssid_len = ieee->current_network.ssid_len;
797 int rate_len = ieee->current_network.rates_len+2;
798 int rate_ex_len = ieee->current_network.rates_ex_len;
799 int wpa_ie_len = ieee->wpa_ie_len;
800 u8 erpinfo_content = 0;
805 u8 tmp_ht_info_len=0;
806 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
807 u8* tmp_generic_ie_buf=NULL;
808 u8 tmp_generic_ie_len=0;
810 if(rate_ex_len > 0) rate_ex_len+=2;
812 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
818 if(ieee80211_is_54g(ieee->current_network))
823 if((ieee->current_network.mode == IEEE_G)
824 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
827 if(ieee->current_network.buseprotection)
828 erpinfo_content |= ERP_UseProtection;
835 crypt = ieee->crypt[ieee->tx_keyidx];
838 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
839 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
842 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
843 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
844 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
845 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
846 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
847 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
850 if(pHTInfo->bRegRT2RTAggregation)
852 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
853 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
854 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
856 // 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);
858 beacon_size = sizeof(struct ieee80211_probe_response)+2+
868 // +tmp_generic_ie_len
871 skb = dev_alloc_skb(beacon_size);
874 skb_reserve(skb, ieee->tx_headroom);
875 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
876 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
877 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
878 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
880 beacon_buf->header.duration_id = 0; //FIXME
881 beacon_buf->beacon_interval =
882 cpu_to_le16(ieee->current_network.beacon_interval);
883 beacon_buf->capability =
884 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
885 beacon_buf->capability |=
886 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
888 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
889 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
891 crypt = ieee->crypt[ieee->tx_keyidx];
893 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
894 (0 == strcmp(crypt->ops->name, "WEP"));
897 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
900 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
901 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
902 beacon_buf->info_element[0].len = ssid_len;
904 tag = (u8*) beacon_buf->info_element[0].data;
906 memcpy(tag, ssid, ssid_len);
910 *(tag++) = MFIE_TYPE_RATES;
911 *(tag++) = rate_len-2;
912 memcpy(tag,ieee->current_network.rates,rate_len-2);
915 *(tag++) = MFIE_TYPE_DS_SET;
917 *(tag++) = ieee->current_network.channel;
921 *(tag++) = MFIE_TYPE_IBSS_SET;
923 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
924 val16 = cpu_to_le16(ieee->current_network.atim_window);
925 memcpy((u8 *)tag, (u8 *)&val16, 2);
930 *(tag++) = MFIE_TYPE_ERP;
932 *(tag++) = erpinfo_content;
935 //Include High Throuput capability
937 *(tag++) = MFIE_TYPE_HT_CAP;
938 *(tag++) = tmp_ht_cap_len - 2;
939 memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
940 tag += tmp_ht_cap_len - 2;
943 *(tag++) = MFIE_TYPE_RATES_EX;
944 *(tag++) = rate_ex_len-2;
945 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
950 //Include High Throuput info
952 *(tag++) = MFIE_TYPE_HT_INFO;
953 *(tag++) = tmp_ht_info_len - 2;
954 memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
955 tag += tmp_ht_info_len - 2;
959 if (ieee->iw_mode == IW_MODE_ADHOC)
960 {//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
961 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
963 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
969 // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
971 if(pHTInfo->bRegRT2RTAggregation)
974 (*tag++) = tmp_generic_ie_len - 2;
975 memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
976 tag += tmp_generic_ie_len -2;
981 if(ieee->qos_support)
985 memcpy(tag,QosOui,wmm_len);
989 //skb->dev = ieee->dev;
994 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
999 struct ieee80211_crypt_data* crypt;
1000 struct ieee80211_assoc_response_frame *assoc;
1003 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1004 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
1006 skb = dev_alloc_skb(len);
1011 skb_reserve(skb, ieee->tx_headroom);
1013 assoc = (struct ieee80211_assoc_response_frame *)
1014 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
1016 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
1017 memcpy(assoc->header.addr1, dest,ETH_ALEN);
1018 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1019 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1020 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
1021 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
1024 if(ieee->short_slot)
1025 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1027 if (ieee->host_encrypt)
1028 crypt = ieee->crypt[ieee->tx_keyidx];
1031 encrypt = ( crypt && crypt->ops);
1034 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1037 assoc->aid = cpu_to_le16(ieee->assoc_id);
1038 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
1039 else ieee->assoc_id++;
1041 tag = (u8*) skb_put(skb, rate_len);
1043 ieee80211_MFIE_Brate(ieee, &tag);
1044 ieee80211_MFIE_Grate(ieee, &tag);
1049 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
1051 struct sk_buff *skb;
1052 struct ieee80211_authentication *auth;
1053 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
1055 skb = dev_alloc_skb(len);
1060 skb->len = sizeof(struct ieee80211_authentication);
1062 auth = (struct ieee80211_authentication *)skb->data;
1064 auth->status = cpu_to_le16(status);
1065 auth->transaction = cpu_to_le16(2);
1066 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
1068 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1069 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1070 memcpy(auth->header.addr1, dest, ETH_ALEN);
1071 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
1077 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
1079 struct sk_buff *skb;
1080 struct ieee80211_hdr_3addr* hdr;
1082 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1087 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1089 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1090 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1091 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1093 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
1094 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1095 (pwr ? IEEE80211_FCTL_PM:0));
1102 struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
1104 struct sk_buff *skb;
1105 struct ieee80211_pspoll_hdr* hdr;
1107 #ifdef USB_USE_ALIGNMENT
1110 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
1112 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
1117 #ifdef USB_USE_ALIGNMENT
1118 Tmpaddr = (u32)skb->data;
1119 alignment = Tmpaddr & 0x1ff;
1120 skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
1122 skb_reserve(skb, ieee->tx_headroom);
1124 hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
1126 memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
1127 memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
1129 hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
1130 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
1137 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1139 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1142 softmac_mgmt_xmit(buf, ieee);
1146 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1148 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1151 softmac_mgmt_xmit(buf, ieee);
1155 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1159 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1161 softmac_mgmt_xmit(buf, ieee);
1165 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1167 struct sk_buff *skb;
1168 //unsigned long flags;
1170 struct ieee80211_assoc_request_frame *hdr;
1172 //short info_addr = 0;
1174 //u16 suite_count = 0;
1175 //u8 suit_select = 0;
1176 //unsigned int wpa_len = beacon->wpa_ie_len;
1178 u8* ht_cap_buf = NULL;
1180 u8* realtek_ie_buf=NULL;
1181 u8 realtek_ie_len=0;
1182 int wpa_ie_len= ieee->wpa_ie_len;
1183 unsigned int ckip_ie_len=0;
1184 unsigned int ccxrm_ie_len=0;
1185 unsigned int cxvernum_ie_len=0;
1186 struct ieee80211_crypt_data* crypt;
1189 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1190 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1192 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1197 crypt = ieee->crypt[ieee->tx_keyidx];
1198 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1200 //Include High Throuput capability && Realtek proprietary
1201 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1203 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1204 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1205 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1206 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1208 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1209 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1210 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1214 if(ieee->qos_support){
1215 wmm_info_len = beacon->qos_data.supported?9:0;
1219 if(beacon->bCkipSupported)
1223 if(beacon->bCcxRmEnable)
1227 if( beacon->BssCcxVerNumber >= 2 )
1229 cxvernum_ie_len = 5+2;
1232 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1233 + beacon->ssid_len//essid tagged val
1234 + rate_len//rates tagged val
1243 + ieee->tx_headroom;
1245 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1246 + beacon->ssid_len//essid tagged val
1247 + rate_len//rates tagged val
1255 + ieee->tx_headroom;
1258 skb = dev_alloc_skb(len);
1263 skb_reserve(skb, ieee->tx_headroom);
1265 hdr = (struct ieee80211_assoc_request_frame *)
1266 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1269 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1270 hdr->header.duration_id= 37; //FIXME
1271 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1272 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1273 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1275 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1277 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1278 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1279 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1281 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1282 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1284 if(ieee->short_slot)
1285 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1286 if (wmm_info_len) //QOS
1287 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1289 hdr->listen_interval = 0xa; //FIXME
1291 hdr->info_element[0].id = MFIE_TYPE_SSID;
1293 hdr->info_element[0].len = beacon->ssid_len;
1294 tag = skb_put(skb, beacon->ssid_len);
1295 memcpy(tag, beacon->ssid, beacon->ssid_len);
1297 tag = skb_put(skb, rate_len);
1299 ieee80211_MFIE_Brate(ieee, &tag);
1300 ieee80211_MFIE_Grate(ieee, &tag);
1301 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1302 if( beacon->bCkipSupported )
1304 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1305 u8 CcxAironetBuf[30];
1306 OCTET_STRING osCcxAironetIE;
1308 memset(CcxAironetBuf, 0,30);
1309 osCcxAironetIE.Octet = CcxAironetBuf;
1310 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1312 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1313 // We want to make the device type as "4500-client". 060926, by CCW.
1315 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1317 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1318 // "The CKIP negotiation is started with the associate request from the client to the access point,
1319 // containing an Aironet element with both the MIC and KP bits set."
1320 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1321 tag = skb_put(skb, ckip_ie_len);
1322 *tag++ = MFIE_TYPE_AIRONET;
1323 *tag++ = osCcxAironetIE.Length;
1324 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1325 tag += osCcxAironetIE.Length;
1328 if(beacon->bCcxRmEnable)
1330 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1331 OCTET_STRING osCcxRmCap;
1333 osCcxRmCap.Octet = CcxRmCapBuf;
1334 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1335 tag = skb_put(skb,ccxrm_ie_len);
1336 *tag++ = MFIE_TYPE_GENERIC;
1337 *tag++ = osCcxRmCap.Length;
1338 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1339 tag += osCcxRmCap.Length;
1342 if( beacon->BssCcxVerNumber >= 2 )
1344 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1345 OCTET_STRING osCcxVerNum;
1346 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1347 osCcxVerNum.Octet = CcxVerNumBuf;
1348 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1349 tag = skb_put(skb,cxvernum_ie_len);
1350 *tag++ = MFIE_TYPE_GENERIC;
1351 *tag++ = osCcxVerNum.Length;
1352 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1353 tag += osCcxVerNum.Length;
1356 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1357 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1359 tag = skb_put(skb, ht_cap_len);
1360 *tag++ = MFIE_TYPE_HT_CAP;
1361 *tag++ = ht_cap_len - 2;
1362 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1363 tag += ht_cap_len -2;
1368 //choose what wpa_supplicant gives to associate.
1369 tag = skb_put(skb, wpa_ie_len);
1371 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1374 tag = skb_put(skb,wmm_info_len);
1376 ieee80211_WMM_Info(ieee, &tag);
1379 tag = skb_put(skb,turbo_info_len);
1380 if(turbo_info_len) {
1381 ieee80211_TURBO_Info(ieee, &tag);
1385 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1386 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1388 tag = skb_put(skb, ht_cap_len);
1389 *tag++ = MFIE_TYPE_GENERIC;
1390 *tag++ = ht_cap_len - 2;
1391 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1392 tag += ht_cap_len -2;
1395 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1396 tag = skb_put(skb, realtek_ie_len);
1397 *tag++ = MFIE_TYPE_GENERIC;
1398 *tag++ = realtek_ie_len - 2;
1399 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1402 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1403 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1407 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1410 unsigned long flags;
1411 spin_lock_irqsave(&ieee->lock, flags);
1413 ieee->associate_seq++;
1415 /* don't scan, and avoid to have the RX path possibily
1416 * try again to associate. Even do not react to AUTH or
1417 * ASSOC response. Just wait for the retry wq to be scheduled.
1418 * Here we will check if there are good nets to associate
1419 * with, so we retry or just get back to NO_LINK and scanning
1421 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1422 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1423 ieee->softmac_stats.no_auth_rs++;
1425 IEEE80211_DEBUG_MGMT("Association failed\n");
1426 ieee->softmac_stats.no_ass_rs++;
1429 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1431 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1432 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1433 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1435 schedule_task(&ieee->associate_retry_wq);
1438 spin_unlock_irqrestore(&ieee->lock, flags);
1441 void ieee80211_associate_abort_cb(unsigned long dev)
1443 ieee80211_associate_abort((struct ieee80211_device *) dev);
1447 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1449 struct ieee80211_network *beacon = &ieee->current_network;
1450 struct sk_buff *skb;
1452 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1454 ieee->softmac_stats.tx_auth_rq++;
1455 skb=ieee80211_authentication_req(beacon, ieee, 0);
1458 ieee80211_associate_abort(ieee);
1460 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1461 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1462 //printk(KERN_WARNING "Sending authentication request\n");
1463 softmac_mgmt_xmit(skb, ieee);
1464 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1465 if(!timer_pending(&ieee->associate_timer)){
1466 ieee->associate_timer.expires = jiffies + (HZ / 2);
1467 add_timer(&ieee->associate_timer);
1469 //dev_kfree_skb_any(skb);//edit by thomas
1473 void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1476 struct sk_buff *skb;
1477 struct ieee80211_network *beacon = &ieee->current_network;
1478 // int hlen = sizeof(struct ieee80211_authentication);
1480 ieee->associate_seq++;
1481 ieee->softmac_stats.tx_auth_rq++;
1483 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1485 ieee80211_associate_abort(ieee);
1487 c = skb_put(skb, chlen+2);
1488 *(c++) = MFIE_TYPE_CHALLENGE;
1490 memcpy(c, challenge, chlen);
1492 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1494 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1496 softmac_mgmt_xmit(skb, ieee);
1497 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1499 ieee->associate_timer.expires = jiffies + (HZ / 2);
1500 add_timer(&ieee->associate_timer);
1502 //dev_kfree_skb_any(skb);//edit by thomas
1507 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1509 struct sk_buff* skb;
1510 struct ieee80211_network *beacon = &ieee->current_network;
1512 del_timer_sync(&ieee->associate_timer);
1514 IEEE80211_DEBUG_MGMT("Sending association request\n");
1516 ieee->softmac_stats.tx_ass_rq++;
1517 skb=ieee80211_association_req(beacon, ieee);
1519 ieee80211_associate_abort(ieee);
1521 softmac_mgmt_xmit(skb, ieee);
1522 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1524 ieee->associate_timer.expires = jiffies + (HZ / 2);
1525 add_timer(&ieee->associate_timer);
1527 //dev_kfree_skb_any(skb);//edit by thomas
1530 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1531 void ieee80211_associate_complete_wq(struct work_struct *work)
1533 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1535 void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1538 printk(KERN_INFO "Associated successfully\n");
1539 ieee->is_roaming = false;
1540 if(ieee80211_is_54g(ieee->current_network) &&
1541 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1544 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1547 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1549 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1551 printk("Successfully associated, ht enabled\n");
1556 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1557 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1558 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1560 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1561 // To prevent the immediately calling watch_dog after association.
1562 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1564 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1565 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1567 ieee->link_change(ieee->dev);
1568 if(ieee->is_silent_reset == 0){
1569 printk("============>normal associate\n");
1570 notify_wx_assoc_event(ieee);
1572 else if(ieee->is_silent_reset == 1)
1574 printk("==================>silent reset associate\n");
1575 ieee->is_silent_reset = 0;
1578 if (ieee->data_hard_resume)
1579 ieee->data_hard_resume(ieee->dev);
1580 netif_carrier_on(ieee->dev);
1583 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1586 // struct net_device* dev = ieee->dev;
1587 del_timer_sync(&ieee->associate_timer);
1590 for(i = 0; i < 6; i++) {
1591 ieee->seq_ctrl[i] = 0;
1594 ieee->state = IEEE80211_LINKED;
1596 if (ieee->pHTInfo->bCurrentHTSupport)
1598 printk("Successfully associated, ht enabled\n");
1599 queue_work(ieee->wq, &ieee->ht_onAssRsp);
1603 printk("Successfully associated, ht not enabled\n");
1604 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1605 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1608 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1609 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1610 queue_work(ieee->wq, &ieee->associate_complete_wq);
1612 schedule_task(&ieee->associate_complete_wq);
1616 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1617 void ieee80211_associate_procedure_wq(struct work_struct *work)
1619 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1621 void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1624 ieee->sync_scan_hurryup = 1;
1626 if(ieee->ieee80211_ips_leave != NULL)
1627 ieee->ieee80211_ips_leave(ieee->dev);
1630 down(&ieee->wx_sem);
1632 if (ieee->data_hard_stop)
1633 ieee->data_hard_stop(ieee->dev);
1635 ieee80211_stop_scan(ieee);
1636 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1637 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1638 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1641 if(ieee->eRFPowerState == eRfOff)
1643 if(ieee->ieee80211_ips_leave_wq != NULL)
1644 ieee->ieee80211_ips_leave_wq(ieee->dev);
1651 ieee->associate_seq = 1;
1652 ieee80211_associate_step1(ieee);
1657 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1659 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1660 int tmp_ssid_len = 0;
1662 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1664 /* we are interested in new new only if we are not associated
1665 * and we are not associating / authenticating
1667 if (ieee->state != IEEE80211_NOLINK)
1670 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1673 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1677 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1678 /* if the user specified the AP MAC, we need also the essid
1679 * This could be obtained by beacons or, if the network does not
1680 * broadcast it, it can be put manually.
1682 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1683 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1684 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1685 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1686 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1687 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1690 if ( /* if the user set the AP check if match.
1691 * if the network does not broadcast essid we check the user supplyed ANY essid
1692 * if the network does broadcast and the user does not set essid it is OK
1693 * if the network does broadcast and the user did set essid chech if essid match
1695 ( apset && apmatch &&
1696 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1697 /* if the ap is not set, check that the user set the bssid
1698 * and the network does bradcast and that those two bssid matches
1700 (!apset && ssidset && ssidbroad && ssidmatch)
1702 /* if the essid is hidden replace it with the
1703 * essid provided by the user.
1706 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1707 tmp_ssid_len = ieee->current_network.ssid_len;
1709 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1712 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1713 ieee->current_network.ssid_len = tmp_ssid_len;
1715 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1717 //ieee->pHTInfo->IOTAction = 0;
1718 HTResetIOTSetting(ieee->pHTInfo);
1719 if (ieee->iw_mode == IW_MODE_INFRA){
1720 /* Join the network for the first time */
1721 ieee->AsocRetryCount = 0;
1722 //for HT by amy 080514
1723 if((ieee->current_network.qos_data.supported == 1) &&
1724 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1725 ieee->current_network.bssht.bdSupportHT)
1726 /*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.*/
1728 // ieee->pHTInfo->bCurrentHTSupport = true;
1729 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1733 ieee->pHTInfo->bCurrentHTSupport = false;
1736 ieee->state = IEEE80211_ASSOCIATING;
1737 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1738 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1740 schedule_task(&ieee->associate_procedure_wq);
1743 if(ieee80211_is_54g(ieee->current_network) &&
1744 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1746 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1747 printk(KERN_INFO"Using G rates\n");
1750 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1751 printk(KERN_INFO"Using B rates\n");
1753 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1754 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1755 ieee->state = IEEE80211_LINKED;
1763 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1765 unsigned long flags;
1766 struct ieee80211_network *target;
1768 spin_lock_irqsave(&ieee->lock, flags);
1770 list_for_each_entry(target, &ieee->network_list, list) {
1772 /* if the state become different that NOLINK means
1773 * we had found what we are searching for
1776 if (ieee->state != IEEE80211_NOLINK)
1779 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1780 ieee80211_softmac_new_net(ieee, target);
1783 spin_unlock_irqrestore(&ieee->lock, flags);
1788 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1790 struct ieee80211_authentication *a;
1792 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1793 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1797 a = (struct ieee80211_authentication*) skb->data;
1798 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1799 t = skb->data + sizeof(struct ieee80211_authentication);
1801 if(*(t++) == MFIE_TYPE_CHALLENGE){
1803 *challenge = kmalloc(*chlen, GFP_ATOMIC);
1804 memcpy(*challenge, t, *chlen);
1808 return cpu_to_le16(a->status);
1813 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1815 struct ieee80211_authentication *a;
1817 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1818 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1821 a = (struct ieee80211_authentication*) skb->data;
1823 memcpy(dest,a->header.addr2, ETH_ALEN);
1825 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1826 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1828 return WLAN_STATUS_SUCCESS;
1831 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1838 struct ieee80211_hdr_3addr *header =
1839 (struct ieee80211_hdr_3addr *) skb->data;
1841 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1842 return -1; /* corrupted */
1844 memcpy(src,header->addr2, ETH_ALEN);
1846 skbend = (u8*)skb->data + skb->len;
1848 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1850 while (tag+1 < skbend){
1856 tag++; /* point to the len field */
1857 tag = tag + *(tag); /* point to the last data byte of the tag */
1858 tag++; /* point to the next tag */
1861 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1862 if (ssidlen == 0) return 1;
1864 if (!ssid) return 1; /* ssid not found in tagged param */
1865 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1869 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1871 struct ieee80211_assoc_request_frame *a;
1873 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1874 sizeof(struct ieee80211_info_element))) {
1876 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1880 a = (struct ieee80211_assoc_request_frame*) skb->data;
1882 memcpy(dest,a->header.addr2,ETH_ALEN);
1887 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1889 struct ieee80211_assoc_response_frame *response_head;
1892 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1893 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1897 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1898 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1900 status_code = le16_to_cpu(response_head->status);
1901 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1902 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1903 ((ieee->mode == IEEE_G) &&
1904 (ieee->current_network.mode == IEEE_N_24G) &&
1905 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1906 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1908 ieee->AsocRetryCount = 0;
1911 return le16_to_cpu(response_head->status);
1915 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1919 //IEEE80211DMESG("Rx probe");
1920 ieee->softmac_stats.rx_probe_rq++;
1921 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1922 if (probe_rq_parse(ieee, skb, dest)){
1923 //IEEE80211DMESG("Was for me!");
1924 ieee->softmac_stats.tx_probe_rs++;
1925 ieee80211_resp_to_probe(ieee, dest);
1930 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1934 //IEEE80211DMESG("Rx probe");
1935 ieee->softmac_stats.rx_auth_rq++;
1937 status = auth_rq_parse(skb, dest);
1939 ieee80211_resp_to_auth(ieee, status, dest);
1941 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1946 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1950 //unsigned long flags;
1952 ieee->softmac_stats.rx_ass_rq++;
1953 if (assoc_rq_parse(skb,dest) != -1){
1954 ieee80211_resp_to_assoc_rq(ieee, dest);
1957 printk(KERN_INFO"New client associated: %pM\n", dest);
1960 spin_lock_irqsave(&ieee->lock,flags);
1961 add_associate(ieee,dest);
1962 spin_unlock_irqrestore(&ieee->lock,flags);
1968 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1971 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1974 softmac_ps_mgmt_xmit(buf, ieee);
1978 void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1981 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1984 softmac_ps_mgmt_xmit(buf, ieee);
1988 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1990 int timeout = ieee->ps_timeout;
1992 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
1994 if(ieee->LPSDelayCnt)
1996 //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
1997 ieee->LPSDelayCnt --;
2001 dtim = ieee->current_network.dtim_data;
2002 // printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
2003 if(!(dtim & IEEE80211_DTIM_VALID))
2005 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
2006 //printk("VALID\n");
2007 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
2008 /* there's no need to nofity AP that I find you buffered with broadcast packet */
2009 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
2012 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
2013 // printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2016 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
2017 // printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2020 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
2021 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
2025 if(ieee->bAwakePktSent == true) {
2026 pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
2030 if(pPSC->LPSAwakeIntvl == 0)
2031 pPSC->LPSAwakeIntvl = 1;
2032 //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
2033 if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
2034 MaxPeriod = 1; // 1 Beacon interval
2035 else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
2036 MaxPeriod = ieee->current_network.dtim_period;
2038 MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
2039 pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
2042 u8 LPSAwakeIntvl_tmp = 0;
2043 u8 period = ieee->current_network.dtim_period;
2044 u8 count = ieee->current_network.tim.tim_count;
2046 if(pPSC->LPSAwakeIntvl > period)
2047 LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
2049 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
2052 if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
2053 LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
2055 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
2057 //printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
2059 *time_l = ieee->current_network.last_dtim_sta_time[0]
2060 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
2061 // * ieee->current_network.dtim_period) * 1000;
2066 *time_h = ieee->current_network.last_dtim_sta_time[1];
2067 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
2076 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
2082 unsigned long flags,flags2;
2084 spin_lock_irqsave(&ieee->lock, flags);
2086 if((ieee->ps == IEEE80211_PS_DISABLED ||
2087 ieee->iw_mode != IW_MODE_INFRA ||
2088 ieee->state != IEEE80211_LINKED)){
2090 // #warning CHECK_LOCK_HERE
2091 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
2092 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
2093 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2095 ieee80211_sta_wakeup(ieee, 1);
2097 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2100 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
2101 /* 2 wake, 1 sleep, 0 do nothing */
2102 if(sleep == 0)//it is not time out or dtim is not valid
2104 //printk("===========>sleep is 0,do nothing\n");
2108 //printk("===========>sleep is 1,to sleep\n");
2109 if(ieee->sta_sleep == 1){
2110 //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
2111 ieee->enter_sleep_state(ieee->dev,th,tl);
2114 else if(ieee->sta_sleep == 0){
2115 // printk("send null 1\n");
2116 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2118 if(ieee->ps_is_queue_empty(ieee->dev)){
2119 ieee->sta_sleep = 2;
2120 ieee->ack_tx_to_ieee = 1;
2121 //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
2122 ieee80211_sta_ps_send_null_frame(ieee,1);
2126 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2130 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
2132 }else if(sleep == 2){
2133 //printk("==========>sleep is 2,to wakeup\n");
2134 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2136 //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
2137 ieee80211_sta_wakeup(ieee,1);
2139 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2143 spin_unlock_irqrestore(&ieee->lock, flags);
2147 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2149 if(ieee->sta_sleep == 0){
2151 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2153 //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2154 //printk("Warning: driver is probably failing to report TX ps error\n");
2155 ieee->ack_tx_to_ieee = 1;
2156 ieee80211_sta_ps_send_null_frame(ieee, 0);
2160 ieee->ack_tx_to_ieee = 1;
2161 //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2162 ieee80211_sta_ps_send_pspoll_frame(ieee);
2169 if(ieee->sta_sleep == 1)
2170 ieee->sta_wake_up(ieee->dev);
2173 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2175 //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2176 //printk("Warning: driver is probably failing to report TX ps error\n");
2177 ieee->ack_tx_to_ieee = 1;
2178 ieee80211_sta_ps_send_null_frame(ieee, 0);
2182 ieee->ack_tx_to_ieee = 1;
2183 ieee->polling = true;
2184 //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2185 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2186 ieee80211_sta_ps_send_pspoll_frame(ieee);
2190 ieee->sta_sleep = 0;
2191 ieee->polling = false;
2195 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2197 unsigned long flags,flags2;
2199 spin_lock_irqsave(&ieee->lock, flags);
2201 if(ieee->sta_sleep == 2){
2202 /* Null frame with PS bit set */
2204 ieee->sta_sleep = 1;
2205 //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
2206 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2208 } else {/* 21112005 - tx again null without PS bit if lost */
2210 if((ieee->sta_sleep == 0) && !success){
2211 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2212 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2213 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2215 //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
2216 ieee80211_sta_ps_send_null_frame(ieee, 0);
2220 //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
2221 ieee80211_sta_ps_send_pspoll_frame(ieee);
2223 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2226 spin_unlock_irqrestore(&ieee->lock, flags);
2229 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2231 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2232 u8* act = ieee80211_get_payload(header);
2234 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2237 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2245 if (*act == ACT_ADDBAREQ)
2246 ieee80211_rx_ADDBAReq(ieee, skb);
2247 else if (*act == ACT_ADDBARSP)
2248 ieee80211_rx_ADDBARsp(ieee, skb);
2249 else if (*act == ACT_DELBA)
2250 ieee80211_rx_DELBA(ieee, skb);
2253 // if (net_ratelimit())
2254 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2261 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2262 struct ieee80211_rx_stats *rx_stats, u16 type,
2265 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2270 struct ieee80211_assoc_response_frame *assoc_resp;
2271 // struct ieee80211_info_element *info_element;
2272 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2274 if(!ieee->proto_started)
2277 printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2278 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2279 ieee->iw_mode == IW_MODE_INFRA &&
2280 ieee->state == IEEE80211_LINKED))
2282 tasklet_schedule(&ieee->ps_task);
2284 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2285 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2286 ieee->last_rx_ps_time = jiffies;
2289 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2291 case IEEE80211_STYPE_ASSOC_RESP:
2292 case IEEE80211_STYPE_REASSOC_RESP:
2294 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2295 WLAN_FC_GET_STYPE(header->frame_ctl));
2296 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2297 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2298 ieee->iw_mode == IW_MODE_INFRA){
2299 struct ieee80211_network network_resp;
2300 struct ieee80211_network *network = &network_resp;
2302 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2303 ieee->state=IEEE80211_LINKED;
2304 ieee->assoc_id = aid;
2305 ieee->softmac_stats.rx_ass_ok++;
2306 /* station support qos */
2307 /* Let the register setting defaultly with Legacy station */
2308 if(ieee->qos_support) {
2309 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2310 memset(network, 0, sizeof(*network));
2311 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2312 rx_stats->len - sizeof(*assoc_resp),\
2317 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2318 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2319 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2321 if (ieee->handle_assoc_response != NULL)
2322 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2324 ieee80211_associate_complete(ieee);
2326 /* aid could not been allocated */
2327 ieee->softmac_stats.rx_ass_err++;
2329 "Association response status code 0x%x\n",
2331 IEEE80211_DEBUG_MGMT(
2332 "Association response status code 0x%x\n",
2334 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2335 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2336 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2338 schedule_task(&ieee->associate_procedure_wq);
2341 ieee80211_associate_abort(ieee);
2347 case IEEE80211_STYPE_ASSOC_REQ:
2348 case IEEE80211_STYPE_REASSOC_REQ:
2350 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2351 ieee->iw_mode == IW_MODE_MASTER)
2353 ieee80211_rx_assoc_rq(ieee, skb);
2356 case IEEE80211_STYPE_AUTH:
2358 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2359 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2360 ieee->iw_mode == IW_MODE_INFRA){
2362 IEEE80211_DEBUG_MGMT("Received authentication response");
2364 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2365 if(ieee->open_wep || !challenge){
2366 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2367 ieee->softmac_stats.rx_auth_rs_ok++;
2368 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2370 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2372 // WEP or TKIP encryption
2373 if(IsHTHalfNmodeAPs(ieee))
2375 bSupportNmode = true;
2376 bHalfSupportNmode = true;
2380 bSupportNmode = false;
2381 bHalfSupportNmode = false;
2383 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2386 /* Dummy wirless mode setting to avoid encryption issue */
2389 ieee->SetWirelessMode(ieee->dev, \
2390 ieee->current_network.mode);
2394 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2397 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2399 printk("===============>entern half N mode\n");
2400 ieee->bHalfWirelessN24GMode = true;
2403 ieee->bHalfWirelessN24GMode = false;
2405 ieee80211_associate_step2(ieee);
2407 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2410 ieee->softmac_stats.rx_auth_rs_err++;
2411 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2413 printk("Authentication respose status code 0x%x",errcode);
2414 ieee80211_associate_abort(ieee);
2417 }else if (ieee->iw_mode == IW_MODE_MASTER){
2418 ieee80211_rx_auth_rq(ieee, skb);
2423 case IEEE80211_STYPE_PROBE_REQ:
2425 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2426 ((ieee->iw_mode == IW_MODE_ADHOC ||
2427 ieee->iw_mode == IW_MODE_MASTER) &&
2428 ieee->state == IEEE80211_LINKED)){
2429 ieee80211_rx_probe_rq(ieee, skb);
2433 case IEEE80211_STYPE_DISASSOC:
2434 case IEEE80211_STYPE_DEAUTH:
2435 /* FIXME for now repeat all the association procedure
2436 * both for disassociation and deauthentication
2438 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2439 ieee->state == IEEE80211_LINKED &&
2440 ieee->iw_mode == IW_MODE_INFRA){
2442 ieee->state = IEEE80211_ASSOCIATING;
2443 ieee->softmac_stats.reassoc++;
2444 ieee->is_roaming = true;
2445 ieee80211_disassociate(ieee);
2446 // notify_wx_assoc_event(ieee);
2447 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2448 RemovePeerTS(ieee, header->addr2);
2449 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2450 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2452 schedule_task(&ieee->associate_procedure_wq);
2456 case IEEE80211_STYPE_MANAGE_ACT:
2457 ieee80211_process_action(ieee,skb);
2464 //dev_kfree_skb_any(skb);
2468 /* following are for a simplier TX queue management.
2469 * Instead of using netif_[stop/wake]_queue the driver
2470 * will uses these two function (plus a reset one), that
2471 * will internally uses the kernel netif_* and takes
2472 * care of the ieee802.11 fragmentation.
2473 * So the driver receives a fragment per time and might
2474 * call the stop function when it want without take care
2475 * to have enough room to TX an entire packet.
2476 * This might be useful if each fragment need it's own
2477 * descriptor, thus just keep a total free memory > than
2478 * the max fragmentation threshold is not enough.. If the
2479 * ieee802.11 stack passed a TXB struct then you needed
2480 * to keep N free descriptors where
2481 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2482 * In this way you need just one and the 802.11 stack
2483 * will take care of buffering fragments and pass them to
2484 * to the driver later, when it wakes the queue.
2486 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2489 unsigned int queue_index = txb->queue_index;
2490 unsigned long flags;
2492 cb_desc *tcb_desc = NULL;
2494 spin_lock_irqsave(&ieee->lock,flags);
2496 /* called with 2nd parm 0, no tx mgmt lock required */
2497 ieee80211_sta_wakeup(ieee,0);
2499 /* update the tx status */
2500 // ieee->stats.tx_bytes += txb->payload_size;
2501 // ieee->stats.tx_packets++;
2502 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2503 if(tcb_desc->bMulticast) {
2504 ieee->stats.multicast++;
2507 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2508 for(i = 0; i < txb->nr_frags; i++) {
2509 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2510 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2512 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2514 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2515 (ieee->queue_stop)) {
2516 /* insert the skb packet to the wait queue */
2517 /* as for the completion function, it does not need
2518 * to check it any more.
2520 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2521 //ieee80211_rtl_stop_queue(ieee);
2522 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2523 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2525 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2528 ieee->softmac_data_hard_start_xmit(
2530 ieee->dev,ieee->rate);
2531 //ieee->stats.tx_packets++;
2532 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2533 //ieee->dev->trans_start = jiffies;
2537 ieee80211_txb_free(txb);
2540 spin_unlock_irqrestore(&ieee->lock,flags);
2544 /* called with ieee->lock acquired */
2545 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2548 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2550 if (ieee->queue_stop){
2551 ieee->tx_pending.frag = i;
2555 ieee->softmac_data_hard_start_xmit(
2556 ieee->tx_pending.txb->fragments[i],
2557 ieee->dev,ieee->rate);
2558 //(i+1)<ieee->tx_pending.txb->nr_frags);
2559 ieee->stats.tx_packets++;
2560 // ieee->dev->trans_start = jiffies;
2565 ieee80211_txb_free(ieee->tx_pending.txb);
2566 ieee->tx_pending.txb = NULL;
2570 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2572 unsigned long flags;
2574 spin_lock_irqsave(&ieee->lock,flags);
2575 init_mgmt_queue(ieee);
2576 if (ieee->tx_pending.txb){
2577 ieee80211_txb_free(ieee->tx_pending.txb);
2578 ieee->tx_pending.txb = NULL;
2580 ieee->queue_stop = 0;
2581 spin_unlock_irqrestore(&ieee->lock,flags);
2585 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2588 unsigned long flags;
2589 struct sk_buff *skb;
2590 struct ieee80211_hdr_3addr *header;
2592 spin_lock_irqsave(&ieee->lock,flags);
2593 if (! ieee->queue_stop) goto exit;
2595 ieee->queue_stop = 0;
2597 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2598 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2600 header = (struct ieee80211_hdr_3addr *) skb->data;
2602 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2604 if (ieee->seq_ctrl[0] == 0xFFF)
2605 ieee->seq_ctrl[0] = 0;
2607 ieee->seq_ctrl[0]++;
2609 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2610 //dev_kfree_skb_any(skb);//edit by thomas
2613 if (!ieee->queue_stop && ieee->tx_pending.txb)
2614 ieee80211_resume_tx(ieee);
2616 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2617 ieee->softmac_stats.swtxawake++;
2618 netif_wake_queue(ieee->dev);
2622 spin_unlock_irqrestore(&ieee->lock,flags);
2626 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2628 //unsigned long flags;
2629 //spin_lock_irqsave(&ieee->lock,flags);
2631 if (! netif_queue_stopped(ieee->dev)){
2632 netif_stop_queue(ieee->dev);
2633 ieee->softmac_stats.swtxstop++;
2635 ieee->queue_stop = 1;
2636 //spin_unlock_irqrestore(&ieee->lock,flags);
2641 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2644 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2646 /* an IBSS cell address must have the two less significant
2647 * bits of the first byte = 2
2649 ieee->current_network.bssid[0] &= ~0x01;
2650 ieee->current_network.bssid[0] |= 0x02;
2653 /* called in user context only */
2654 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2658 if (ieee->current_network.ssid_len == 0){
2659 strncpy(ieee->current_network.ssid,
2660 IEEE80211_DEFAULT_TX_ESSID,
2663 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2667 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2669 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2670 ieee->state = IEEE80211_LINKED;
2671 ieee->link_change(ieee->dev);
2672 notify_wx_assoc_event(ieee);
2674 if (ieee->data_hard_resume)
2675 ieee->data_hard_resume(ieee->dev);
2677 netif_carrier_on(ieee->dev);
2680 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2684 if (ieee->data_hard_resume)
2685 ieee->data_hard_resume(ieee->dev);
2687 netif_carrier_on(ieee->dev);
2690 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2691 void ieee80211_start_ibss_wq(struct work_struct *work)
2694 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2695 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2697 void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2700 /* iwconfig mode ad-hoc will schedule this and return
2701 * on the other hand this will block further iwconfig SET
2702 * operations because of the wx_sem hold.
2703 * Anyway some most set operations set a flag to speed-up
2704 * (abort) this wq (when syncro scanning) before sleeping
2707 if(!ieee->proto_started){
2708 printk("==========oh driver down return\n");
2711 down(&ieee->wx_sem);
2713 if (ieee->current_network.ssid_len == 0){
2714 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2715 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2719 ieee->state = IEEE80211_NOLINK;
2720 /* check if we have this cell in our network list */
2721 ieee80211_softmac_check_all_nets(ieee);
2724 #ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
2725 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2726 if (ieee->state == IEEE80211_NOLINK)
2727 ieee->current_network.channel = 6;
2729 /* if not then the state is not linked. Maybe the user swithced to
2730 * ad-hoc mode just after being in monitor mode, or just after
2731 * being very few time in managed mode (so the card have had no
2732 * time to scan all the chans..) or we have just run up the iface
2733 * after setting ad-hoc mode. So we have to give another try..
2734 * Here, in ibss mode, should be safe to do this without extra care
2735 * (in bss mode we had to make sure no-one tryed to associate when
2736 * we had just checked the ieee->state and we was going to start the
2737 * scan) beacause in ibss mode the ieee80211_new_net function, when
2738 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2739 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2740 * scan, that will stop at the first round because it sees the state
2743 if (ieee->state == IEEE80211_NOLINK)
2744 ieee80211_start_scan_syncro(ieee);
2746 /* the network definitively is not here.. create a new cell */
2747 if (ieee->state == IEEE80211_NOLINK){
2748 printk("creating new IBSS cell\n");
2750 ieee80211_randomize_cell(ieee);
2752 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2754 ieee->current_network.rates_len = 4;
2756 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2757 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2758 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2759 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2762 ieee->current_network.rates_len = 0;
2764 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2765 ieee->current_network.rates_ex_len = 8;
2767 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2768 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2769 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2770 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2771 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2772 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2773 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2774 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2778 ieee->current_network.rates_ex_len = 0;
2782 // By default, WMM function will be disabled in IBSS mode
2783 ieee->current_network.QoS_Enable = 0;
2784 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2785 ieee->current_network.atim_window = 0;
2786 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2787 if(ieee->short_slot)
2788 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2792 ieee->state = IEEE80211_LINKED;
2794 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2795 ieee->link_change(ieee->dev);
2797 notify_wx_assoc_event(ieee);
2799 ieee80211_start_send_beacons(ieee);
2801 if (ieee->data_hard_resume)
2802 ieee->data_hard_resume(ieee->dev);
2803 netif_carrier_on(ieee->dev);
2808 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2810 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2811 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2813 schedule_task(&ieee->start_ibss_wq);
2817 /* this is called only in user context, with wx_sem held */
2818 void ieee80211_start_bss(struct ieee80211_device *ieee)
2820 unsigned long flags;
2821 #ifdef ENABLE_DOT11D
2823 // Ref: 802.11d 11.1.3.3
2824 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2826 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2828 if(! ieee->bGlobalDomain)
2834 /* check if we have already found the net we
2835 * are interested in (if any).
2836 * if not (we are disassociated and we are not
2837 * in associating / authenticating phase) start the background scanning.
2839 ieee80211_softmac_check_all_nets(ieee);
2841 /* ensure no-one start an associating process (thus setting
2842 * the ieee->state to ieee80211_ASSOCIATING) while we
2843 * have just cheked it and we are going to enable scan.
2844 * The ieee80211_new_net function is always called with
2845 * lock held (from both ieee80211_softmac_check_all_nets and
2846 * the rx path), so we cannot be in the middle of such function
2848 spin_lock_irqsave(&ieee->lock, flags);
2850 if (ieee->state == IEEE80211_NOLINK){
2852 if(ieee->ieee80211_ips_leave_wq != NULL)
2853 ieee->ieee80211_ips_leave_wq(ieee->dev);
2855 ieee->actscanning = true;
2856 ieee80211_rtl_start_scan(ieee);
2858 spin_unlock_irqrestore(&ieee->lock, flags);
2861 /* called only in userspace context */
2862 void ieee80211_disassociate(struct ieee80211_device *ieee)
2866 netif_carrier_off(ieee->dev);
2867 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2868 ieee80211_reset_queue(ieee);
2870 if (ieee->data_hard_stop)
2871 ieee->data_hard_stop(ieee->dev);
2872 #ifdef ENABLE_DOT11D
2873 if(IS_DOT11D_ENABLE(ieee))
2876 ieee->is_set_key = false;
2877 ieee->link_change(ieee->dev);
2878 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2879 if (ieee->state == IEEE80211_LINKED ||
2880 ieee->state == IEEE80211_ASSOCIATING) {
2881 ieee->state = IEEE80211_NOLINK;
2882 notify_wx_assoc_event(ieee);
2885 ieee->state = IEEE80211_NOLINK;
2888 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2889 void ieee80211_associate_retry_wq(struct work_struct *work)
2891 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2892 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2894 void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2897 unsigned long flags;
2899 down(&ieee->wx_sem);
2900 if(!ieee->proto_started)
2903 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2906 /* until we do not set the state to IEEE80211_NOLINK
2907 * there are no possibility to have someone else trying
2908 * to start an association procdure (we get here with
2909 * ieee->state = IEEE80211_ASSOCIATING).
2910 * When we set the state to IEEE80211_NOLINK it is possible
2911 * that the RX path run an attempt to associate, but
2912 * both ieee80211_softmac_check_all_nets and the
2913 * RX path works with ieee->lock held so there are no
2914 * problems. If we are still disassociated then start a scan.
2915 * the lock here is necessary to ensure no one try to start
2916 * an association procedure when we have just checked the
2917 * state and we are going to start the scan.
2919 ieee->beinretry = true;
2920 ieee->state = IEEE80211_NOLINK;
2922 ieee80211_softmac_check_all_nets(ieee);
2924 spin_lock_irqsave(&ieee->lock, flags);
2926 if(ieee->state == IEEE80211_NOLINK)
2928 ieee->is_roaming= false;
2929 ieee->actscanning = true;
2930 ieee80211_rtl_start_scan(ieee);
2932 spin_unlock_irqrestore(&ieee->lock, flags);
2934 ieee->beinretry = false;
2939 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2941 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2943 struct sk_buff *skb;
2944 struct ieee80211_probe_response *b;
2946 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2951 b = (struct ieee80211_probe_response *) skb->data;
2952 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2958 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2960 struct sk_buff *skb;
2961 struct ieee80211_probe_response *b;
2963 skb = ieee80211_get_beacon_(ieee);
2967 b = (struct ieee80211_probe_response *) skb->data;
2968 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2970 if (ieee->seq_ctrl[0] == 0xFFF)
2971 ieee->seq_ctrl[0] = 0;
2973 ieee->seq_ctrl[0]++;
2978 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2980 ieee->sync_scan_hurryup = 1;
2981 down(&ieee->wx_sem);
2982 ieee80211_stop_protocol(ieee, shutdown);
2987 void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2989 if (!ieee->proto_started)
2993 ieee->proto_started = 0;
2994 ieee->proto_stoppping = 1;
2996 ieee80211_stop_send_beacons(ieee);
2997 del_timer_sync(&ieee->associate_timer);
2998 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2999 cancel_delayed_work(&ieee->associate_retry_wq);
3000 cancel_delayed_work(&ieee->start_ibss_wq);
3002 ieee80211_stop_scan(ieee);
3004 ieee80211_disassociate(ieee);
3005 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
3007 ieee->proto_stoppping = 0;
3010 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
3012 ieee->sync_scan_hurryup = 0;
3013 down(&ieee->wx_sem);
3014 ieee80211_start_protocol(ieee);
3018 void ieee80211_start_protocol(struct ieee80211_device *ieee)
3022 if (ieee->proto_started)
3025 ieee->proto_started = 1;
3027 if (ieee->current_network.channel == 0){
3030 if (ch > MAX_CHANNEL_NUMBER)
3031 return; /* no channel found */
3032 #ifdef ENABLE_DOT11D
3033 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
3035 }while(!ieee->channel_map[ch]);
3037 ieee->current_network.channel = ch;
3040 if (ieee->current_network.beacon_interval == 0)
3041 ieee->current_network.beacon_interval = 100;
3042 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
3043 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
3045 for(i = 0; i < 17; i++) {
3046 ieee->last_rxseq_num[i] = -1;
3047 ieee->last_rxfrag_num[i] = -1;
3048 ieee->last_packet_time[i] = 0;
3051 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
3053 ieee->state = IEEE80211_NOLINK;
3056 /* if the user set the MAC of the ad-hoc cell and then
3057 * switch to managed mode, shall we make sure that association
3058 * attempts does not fail just because the user provide the essid
3059 * and the nic is still checking for the AP MAC ??
3061 if (ieee->iw_mode == IW_MODE_INFRA)
3062 ieee80211_start_bss(ieee);
3064 else if (ieee->iw_mode == IW_MODE_ADHOC)
3065 ieee80211_start_ibss(ieee);
3067 else if (ieee->iw_mode == IW_MODE_MASTER)
3068 ieee80211_start_master_bss(ieee);
3070 else if(ieee->iw_mode == IW_MODE_MONITOR)
3071 ieee80211_start_monitor_mode(ieee);
3075 #define DRV_NAME "Ieee80211"
3076 void ieee80211_softmac_init(struct ieee80211_device *ieee)
3079 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
3081 ieee->state = IEEE80211_NOLINK;
3082 ieee->sync_scan_hurryup = 0;
3083 for(i = 0; i < 5; i++) {
3084 ieee->seq_ctrl[i] = 0;
3086 #ifdef ENABLE_DOT11D
3087 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
3088 if (!ieee->pDot11dInfo)
3089 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
3091 //added for AP roaming
3092 ieee->LinkDetectInfo.SlotNum = 2;
3093 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3094 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3097 ieee->queue_stop = 0;
3099 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
3102 ieee->proto_started = 0;
3103 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
3105 ieee->ps = IEEE80211_PS_DISABLED;
3106 ieee->sta_sleep = 0;
3107 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
3108 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
3109 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
3111 ieee->actscanning = false;
3112 ieee->beinretry = false;
3113 ieee->is_set_key = false;
3114 init_mgmt_queue(ieee);
3116 ieee->sta_edca_param[0] = 0x0000A403;
3117 ieee->sta_edca_param[1] = 0x0000A427;
3118 ieee->sta_edca_param[2] = 0x005E4342;
3119 ieee->sta_edca_param[3] = 0x002F3262;
3120 ieee->aggregation = true;
3121 ieee->enable_rx_imm_BA = 1;
3122 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3123 init_timer(&ieee->scan_timer);
3124 ieee->scan_timer.data = (unsigned long)ieee;
3125 ieee->scan_timer.function = ieee80211_softmac_scan_cb;
3127 ieee->tx_pending.txb = NULL;
3129 init_timer(&ieee->associate_timer);
3130 ieee->associate_timer.data = (unsigned long)ieee;
3131 ieee->associate_timer.function = ieee80211_associate_abort_cb;
3133 init_timer(&ieee->beacon_timer);
3134 ieee->beacon_timer.data = (unsigned long) ieee;
3135 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
3137 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3138 #ifdef PF_SYNCTHREAD
3139 ieee->wq = create_workqueue(DRV_NAME,0);
3141 ieee->wq = create_workqueue(DRV_NAME);
3145 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3146 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3147 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
3148 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
3149 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
3150 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
3151 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
3152 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
3155 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3156 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3157 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3158 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3159 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3160 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3164 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3165 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3166 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3167 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3168 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3169 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3171 sema_init(&ieee->wx_sem, 1);
3172 sema_init(&ieee->scan_sem, 1);
3174 sema_init(&ieee->ips_sem,1);
3176 spin_lock_init(&ieee->mgmt_tx_lock);
3177 spin_lock_init(&ieee->beacon_lock);
3179 tasklet_init(&ieee->ps_task,
3180 (void(*)(unsigned long)) ieee80211_sta_ps,
3181 (unsigned long)ieee);
3185 void ieee80211_softmac_free(struct ieee80211_device *ieee)
3187 down(&ieee->wx_sem);
3188 #ifdef ENABLE_DOT11D
3189 if(NULL != ieee->pDot11dInfo)
3191 kfree(ieee->pDot11dInfo);
3192 ieee->pDot11dInfo = NULL;
3195 del_timer_sync(&ieee->associate_timer);
3197 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3198 cancel_delayed_work(&ieee->associate_retry_wq);
3199 destroy_workqueue(ieee->wq);
3205 /********************************************************
3206 * Start of WPA code. *
3207 * this is stolen from the ipw2200 driver *
3208 ********************************************************/
3211 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3213 /* This is called when wpa_supplicant loads and closes the driver
3215 printk("%s WPA\n",value ? "enabling" : "disabling");
3216 ieee->wpa_enabled = value;
3221 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3223 /* make sure WPA is enabled */
3224 ieee80211_wpa_enable(ieee, 1);
3226 ieee80211_disassociate(ieee);
3230 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3236 case IEEE_MLME_STA_DEAUTH:
3240 case IEEE_MLME_STA_DISASSOC:
3241 ieee80211_disassociate(ieee);
3245 printk("Unknown MLME request: %d\n", command);
3253 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3254 struct ieee_param *param, int plen)
3258 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3259 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3262 if (param->u.wpa_ie.len) {
3263 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
3268 kfree(ieee->wpa_ie);
3270 ieee->wpa_ie_len = param->u.wpa_ie.len;
3272 kfree(ieee->wpa_ie);
3273 ieee->wpa_ie = NULL;
3274 ieee->wpa_ie_len = 0;
3277 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3281 #define AUTH_ALG_OPEN_SYSTEM 0x1
3282 #define AUTH_ALG_SHARED_KEY 0x2
3284 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3287 struct ieee80211_security sec = {
3288 .flags = SEC_AUTH_MODE,
3292 if (value & AUTH_ALG_SHARED_KEY) {
3293 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3295 ieee->auth_mode = 1;
3296 } else if (value & AUTH_ALG_OPEN_SYSTEM){
3297 sec.auth_mode = WLAN_AUTH_OPEN;
3299 ieee->auth_mode = 0;
3301 else if (value & IW_AUTH_ALG_LEAP){
3302 sec.auth_mode = WLAN_AUTH_LEAP;
3304 ieee->auth_mode = 2;
3308 if (ieee->set_security)
3309 ieee->set_security(ieee->dev, &sec);
3311 // ret = -EOPNOTSUPP;
3316 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3319 unsigned long flags;
3322 case IEEE_PARAM_WPA_ENABLED:
3323 ret = ieee80211_wpa_enable(ieee, value);
3326 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3327 ieee->tkip_countermeasures=value;
3330 case IEEE_PARAM_DROP_UNENCRYPTED: {
3333 * wpa_supplicant calls set_wpa_enabled when the driver
3334 * is loaded and unloaded, regardless of if WPA is being
3335 * used. No other calls are made which can be used to
3336 * determine if encryption will be used or not prior to
3337 * association being expected. If encryption is not being
3338 * used, drop_unencrypted is set to false, else true -- we
3339 * can use this to determine if the CAP_PRIVACY_ON bit should
3342 struct ieee80211_security sec = {
3343 .flags = SEC_ENABLED,
3346 ieee->drop_unencrypted = value;
3347 /* We only change SEC_LEVEL for open mode. Others
3348 * are set by ipw_wpa_set_encryption.
3351 sec.flags |= SEC_LEVEL;
3352 sec.level = SEC_LEVEL_0;
3355 sec.flags |= SEC_LEVEL;
3356 sec.level = SEC_LEVEL_1;
3358 if (ieee->set_security)
3359 ieee->set_security(ieee->dev, &sec);
3363 case IEEE_PARAM_PRIVACY_INVOKED:
3364 ieee->privacy_invoked=value;
3367 case IEEE_PARAM_AUTH_ALGS:
3368 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3371 case IEEE_PARAM_IEEE_802_1X:
3372 ieee->ieee802_1x=value;
3374 case IEEE_PARAM_WPAX_SELECT:
3375 // added for WPA2 mixed mode
3376 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3377 ieee->wpax_type_set = 1;
3378 ieee->wpax_type_notify = value;
3379 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3383 printk("Unknown WPA param: %d\n",name);
3390 /* implementation borrowed from hostap driver */
3392 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3393 struct ieee_param *param, int param_len)
3397 struct ieee80211_crypto_ops *ops;
3398 struct ieee80211_crypt_data **crypt;
3400 struct ieee80211_security sec = {
3404 param->u.crypt.err = 0;
3405 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3408 (int) ((char *) param->u.crypt.key - (char *) param) +
3409 param->u.crypt.key_len) {
3410 printk("Len mismatch %d, %d\n", param_len,
3411 param->u.crypt.key_len);
3414 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3415 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3416 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3417 if (param->u.crypt.idx >= WEP_KEYS)
3419 crypt = &ieee->crypt[param->u.crypt.idx];
3424 if (strcmp(param->u.crypt.alg, "none") == 0) {
3429 sec.level = SEC_LEVEL_0;
3430 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3431 ieee80211_crypt_delayed_deinit(ieee, crypt);
3438 sec.flags |= SEC_ENABLED;
3440 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3441 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3442 strcmp(param->u.crypt.alg, "TKIP"))
3443 goto skip_host_crypt;
3445 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3446 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3447 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3448 /* set WEP40 first, it will be modified according to WEP104 or
3449 * WEP40 at other place */
3450 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3451 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3452 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3453 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3455 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3456 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3461 if (*crypt == NULL || (*crypt)->ops != ops) {
3462 struct ieee80211_crypt_data *new_crypt;
3464 ieee80211_crypt_delayed_deinit(ieee, crypt);
3466 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3467 if (new_crypt == NULL) {
3471 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3472 new_crypt->ops = ops;
3475 new_crypt->ops->init(param->u.crypt.idx);
3477 if (new_crypt->priv == NULL) {
3479 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3487 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3488 (*crypt)->ops->set_key(param->u.crypt.key,
3489 param->u.crypt.key_len, param->u.crypt.seq,
3490 (*crypt)->priv) < 0) {
3491 printk("key setting failed\n");
3492 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3498 if (param->u.crypt.set_tx) {
3499 ieee->tx_keyidx = param->u.crypt.idx;
3500 sec.active_key = param->u.crypt.idx;
3501 sec.flags |= SEC_ACTIVE_KEY;
3503 sec.flags &= ~SEC_ACTIVE_KEY;
3505 if (param->u.crypt.alg != NULL) {
3506 memcpy(sec.keys[param->u.crypt.idx],
3508 param->u.crypt.key_len);
3509 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3510 sec.flags |= (1 << param->u.crypt.idx);
3512 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3513 sec.flags |= SEC_LEVEL;
3514 sec.level = SEC_LEVEL_1;
3515 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3516 sec.flags |= SEC_LEVEL;
3517 sec.level = SEC_LEVEL_2;
3518 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3519 sec.flags |= SEC_LEVEL;
3520 sec.level = SEC_LEVEL_3;
3524 if (ieee->set_security)
3525 ieee->set_security(ieee->dev, &sec);
3527 /* Do not reset port if card is in Managed mode since resetting will
3528 * generate new IEEE 802.11 authentication which may end up in looping
3529 * with IEEE 802.1X. If your hardware requires a reset after WEP
3530 * configuration (for example... Prism2), implement the reset_port in
3531 * the callbacks structures used to initialize the 802.11 stack. */
3532 if (ieee->reset_on_keychange &&
3533 ieee->iw_mode != IW_MODE_INFRA &&
3535 ieee->reset_port(ieee->dev)) {
3536 printk("reset_port failed\n");
3537 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3544 inline struct sk_buff *ieee80211_disassociate_skb(
3545 struct ieee80211_network *beacon,
3546 struct ieee80211_device *ieee,
3549 struct sk_buff *skb;
3550 struct ieee80211_disassoc *disass;
3552 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3556 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3557 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3558 disass->header.duration_id = 0;
3560 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3561 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3562 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3564 disass->reason = asRsn;
3571 struct ieee80211_device *ieee,
3576 struct ieee80211_network *beacon = &ieee->current_network;
3577 struct sk_buff *skb;
3578 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3580 softmac_mgmt_xmit(skb, ieee);
3581 //dev_kfree_skb_any(skb);//edit by thomas
3585 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3587 struct ieee_param *param;
3590 down(&ieee->wx_sem);
3591 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3593 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3598 param = kmalloc(p->length, GFP_KERNEL);
3603 if (copy_from_user(param, p->pointer, p->length)) {
3609 switch (param->cmd) {
3611 case IEEE_CMD_SET_WPA_PARAM:
3612 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3613 param->u.wpa_param.value);
3616 case IEEE_CMD_SET_WPA_IE:
3617 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3620 case IEEE_CMD_SET_ENCRYPTION:
3621 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3625 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3626 param->u.mlme.reason_code);
3630 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3635 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3645 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3647 union iwreq_data wrqu;
3648 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3649 if (ieee->state == IEEE80211_LINKED)
3650 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3652 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3653 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3656 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3657 //EXPORT_SYMBOL(ieee80211_get_beacon);
3658 //EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3659 //EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3660 //EXPORT_SYMBOL(ieee80211_reset_queue);
3661 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3662 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3663 //EXPORT_SYMBOL(ieee80211_is_shortslot);
3664 //EXPORT_SYMBOL(ieee80211_is_54g);
3665 //EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3666 //EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3667 //EXPORT_SYMBOL(ieee80211_softmac_xmit);
3668 //EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3669 //EXPORT_SYMBOL(notify_wx_assoc_event);
3670 //EXPORT_SYMBOL(SendDisassociation);
3671 //EXPORT_SYMBOL(ieee80211_disassociate);
3672 //EXPORT_SYMBOL(ieee80211_start_send_beacons);
3673 //EXPORT_SYMBOL(ieee80211_stop_scan);
3674 //EXPORT_SYMBOL(ieee80211_send_probe_requests);
3675 //EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3676 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3678 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3679 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3680 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3681 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3682 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3683 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3684 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3685 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3686 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3687 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3688 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3689 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3690 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3691 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3692 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3693 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3694 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3695 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3696 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3697 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3698 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
3699 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);