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 = (u8*)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 if ((status = auth_rq_parse(skb, dest))!= -1){
1938 ieee80211_resp_to_auth(ieee, status, dest);
1940 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1945 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1949 //unsigned long flags;
1951 ieee->softmac_stats.rx_ass_rq++;
1952 if (assoc_rq_parse(skb,dest) != -1){
1953 ieee80211_resp_to_assoc_rq(ieee, dest);
1956 printk(KERN_INFO"New client associated: %pM\n", dest);
1959 spin_lock_irqsave(&ieee->lock,flags);
1960 add_associate(ieee,dest);
1961 spin_unlock_irqrestore(&ieee->lock,flags);
1967 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1970 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1973 softmac_ps_mgmt_xmit(buf, ieee);
1977 void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1980 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1983 softmac_ps_mgmt_xmit(buf, ieee);
1987 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1989 int timeout = ieee->ps_timeout;
1991 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
1993 if(ieee->LPSDelayCnt)
1995 //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
1996 ieee->LPSDelayCnt --;
2000 dtim = ieee->current_network.dtim_data;
2001 // printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
2002 if(!(dtim & IEEE80211_DTIM_VALID))
2004 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
2005 //printk("VALID\n");
2006 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
2007 /* there's no need to nofity AP that I find you buffered with broadcast packet */
2008 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
2011 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
2012 // printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2015 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
2016 // printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2019 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
2020 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
2024 if(ieee->bAwakePktSent == true) {
2025 pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
2029 if(pPSC->LPSAwakeIntvl == 0)
2030 pPSC->LPSAwakeIntvl = 1;
2031 //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
2032 if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
2033 MaxPeriod = 1; // 1 Beacon interval
2034 else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
2035 MaxPeriod = ieee->current_network.dtim_period;
2037 MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
2038 pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
2041 u8 LPSAwakeIntvl_tmp = 0;
2042 u8 period = ieee->current_network.dtim_period;
2043 u8 count = ieee->current_network.tim.tim_count;
2045 if(pPSC->LPSAwakeIntvl > period)
2046 LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
2048 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
2051 if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
2052 LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
2054 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
2056 //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);
2058 *time_l = ieee->current_network.last_dtim_sta_time[0]
2059 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
2060 // * ieee->current_network.dtim_period) * 1000;
2065 *time_h = ieee->current_network.last_dtim_sta_time[1];
2066 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
2075 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
2081 unsigned long flags,flags2;
2083 spin_lock_irqsave(&ieee->lock, flags);
2085 if((ieee->ps == IEEE80211_PS_DISABLED ||
2086 ieee->iw_mode != IW_MODE_INFRA ||
2087 ieee->state != IEEE80211_LINKED)){
2089 // #warning CHECK_LOCK_HERE
2090 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
2091 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
2092 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2094 ieee80211_sta_wakeup(ieee, 1);
2096 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2099 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
2100 /* 2 wake, 1 sleep, 0 do nothing */
2101 if(sleep == 0)//it is not time out or dtim is not valid
2103 //printk("===========>sleep is 0,do nothing\n");
2107 //printk("===========>sleep is 1,to sleep\n");
2108 if(ieee->sta_sleep == 1){
2109 //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
2110 ieee->enter_sleep_state(ieee->dev,th,tl);
2113 else if(ieee->sta_sleep == 0){
2114 // printk("send null 1\n");
2115 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2117 if(ieee->ps_is_queue_empty(ieee->dev)){
2118 ieee->sta_sleep = 2;
2119 ieee->ack_tx_to_ieee = 1;
2120 //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
2121 ieee80211_sta_ps_send_null_frame(ieee,1);
2125 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2129 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
2131 }else if(sleep == 2){
2132 //printk("==========>sleep is 2,to wakeup\n");
2133 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2135 //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
2136 ieee80211_sta_wakeup(ieee,1);
2138 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2142 spin_unlock_irqrestore(&ieee->lock, flags);
2146 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2148 if(ieee->sta_sleep == 0){
2150 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2152 //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2153 //printk("Warning: driver is probably failing to report TX ps error\n");
2154 ieee->ack_tx_to_ieee = 1;
2155 ieee80211_sta_ps_send_null_frame(ieee, 0);
2159 ieee->ack_tx_to_ieee = 1;
2160 //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2161 ieee80211_sta_ps_send_pspoll_frame(ieee);
2168 if(ieee->sta_sleep == 1)
2169 ieee->sta_wake_up(ieee->dev);
2172 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2174 //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2175 //printk("Warning: driver is probably failing to report TX ps error\n");
2176 ieee->ack_tx_to_ieee = 1;
2177 ieee80211_sta_ps_send_null_frame(ieee, 0);
2181 ieee->ack_tx_to_ieee = 1;
2182 ieee->polling = true;
2183 //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2184 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2185 ieee80211_sta_ps_send_pspoll_frame(ieee);
2189 ieee->sta_sleep = 0;
2190 ieee->polling = false;
2194 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2196 unsigned long flags,flags2;
2198 spin_lock_irqsave(&ieee->lock, flags);
2200 if(ieee->sta_sleep == 2){
2201 /* Null frame with PS bit set */
2203 ieee->sta_sleep = 1;
2204 //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
2205 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2207 } else {/* 21112005 - tx again null without PS bit if lost */
2209 if((ieee->sta_sleep == 0) && !success){
2210 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2211 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2212 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2214 //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
2215 ieee80211_sta_ps_send_null_frame(ieee, 0);
2219 //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
2220 ieee80211_sta_ps_send_pspoll_frame(ieee);
2222 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2225 spin_unlock_irqrestore(&ieee->lock, flags);
2228 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2230 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2231 u8* act = ieee80211_get_payload(header);
2233 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2236 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2244 if (*act == ACT_ADDBAREQ)
2245 ieee80211_rx_ADDBAReq(ieee, skb);
2246 else if (*act == ACT_ADDBARSP)
2247 ieee80211_rx_ADDBARsp(ieee, skb);
2248 else if (*act == ACT_DELBA)
2249 ieee80211_rx_DELBA(ieee, skb);
2252 // if (net_ratelimit())
2253 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2260 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2261 struct ieee80211_rx_stats *rx_stats, u16 type,
2264 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2269 struct ieee80211_assoc_response_frame *assoc_resp;
2270 // struct ieee80211_info_element *info_element;
2271 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2273 if(!ieee->proto_started)
2276 printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2277 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2278 ieee->iw_mode == IW_MODE_INFRA &&
2279 ieee->state == IEEE80211_LINKED))
2281 tasklet_schedule(&ieee->ps_task);
2283 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2284 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2285 ieee->last_rx_ps_time = jiffies;
2288 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2290 case IEEE80211_STYPE_ASSOC_RESP:
2291 case IEEE80211_STYPE_REASSOC_RESP:
2293 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2294 WLAN_FC_GET_STYPE(header->frame_ctl));
2295 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2296 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2297 ieee->iw_mode == IW_MODE_INFRA){
2298 struct ieee80211_network network_resp;
2299 struct ieee80211_network *network = &network_resp;
2301 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2302 ieee->state=IEEE80211_LINKED;
2303 ieee->assoc_id = aid;
2304 ieee->softmac_stats.rx_ass_ok++;
2305 /* station support qos */
2306 /* Let the register setting defaultly with Legacy station */
2307 if(ieee->qos_support) {
2308 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2309 memset(network, 0, sizeof(*network));
2310 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2311 rx_stats->len - sizeof(*assoc_resp),\
2316 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2317 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2318 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2320 if (ieee->handle_assoc_response != NULL)
2321 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2323 ieee80211_associate_complete(ieee);
2325 /* aid could not been allocated */
2326 ieee->softmac_stats.rx_ass_err++;
2328 "Association response status code 0x%x\n",
2330 IEEE80211_DEBUG_MGMT(
2331 "Association response status code 0x%x\n",
2333 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2334 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2335 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2337 schedule_task(&ieee->associate_procedure_wq);
2340 ieee80211_associate_abort(ieee);
2346 case IEEE80211_STYPE_ASSOC_REQ:
2347 case IEEE80211_STYPE_REASSOC_REQ:
2349 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2350 ieee->iw_mode == IW_MODE_MASTER)
2352 ieee80211_rx_assoc_rq(ieee, skb);
2355 case IEEE80211_STYPE_AUTH:
2357 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2358 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2359 ieee->iw_mode == IW_MODE_INFRA){
2361 IEEE80211_DEBUG_MGMT("Received authentication response");
2363 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2364 if(ieee->open_wep || !challenge){
2365 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2366 ieee->softmac_stats.rx_auth_rs_ok++;
2367 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2369 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2371 // WEP or TKIP encryption
2372 if(IsHTHalfNmodeAPs(ieee))
2374 bSupportNmode = true;
2375 bHalfSupportNmode = true;
2379 bSupportNmode = false;
2380 bHalfSupportNmode = false;
2382 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2385 /* Dummy wirless mode setting to avoid encryption issue */
2388 ieee->SetWirelessMode(ieee->dev, \
2389 ieee->current_network.mode);
2393 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2396 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2398 printk("===============>entern half N mode\n");
2399 ieee->bHalfWirelessN24GMode = true;
2402 ieee->bHalfWirelessN24GMode = false;
2404 ieee80211_associate_step2(ieee);
2406 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2409 ieee->softmac_stats.rx_auth_rs_err++;
2410 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2412 printk("Authentication respose status code 0x%x",errcode);
2413 ieee80211_associate_abort(ieee);
2416 }else if (ieee->iw_mode == IW_MODE_MASTER){
2417 ieee80211_rx_auth_rq(ieee, skb);
2422 case IEEE80211_STYPE_PROBE_REQ:
2424 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2425 ((ieee->iw_mode == IW_MODE_ADHOC ||
2426 ieee->iw_mode == IW_MODE_MASTER) &&
2427 ieee->state == IEEE80211_LINKED)){
2428 ieee80211_rx_probe_rq(ieee, skb);
2432 case IEEE80211_STYPE_DISASSOC:
2433 case IEEE80211_STYPE_DEAUTH:
2434 /* FIXME for now repeat all the association procedure
2435 * both for disassociation and deauthentication
2437 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2438 ieee->state == IEEE80211_LINKED &&
2439 ieee->iw_mode == IW_MODE_INFRA){
2441 ieee->state = IEEE80211_ASSOCIATING;
2442 ieee->softmac_stats.reassoc++;
2443 ieee->is_roaming = true;
2444 ieee80211_disassociate(ieee);
2445 // notify_wx_assoc_event(ieee);
2446 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2447 RemovePeerTS(ieee, header->addr2);
2448 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2449 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2451 schedule_task(&ieee->associate_procedure_wq);
2455 case IEEE80211_STYPE_MANAGE_ACT:
2456 ieee80211_process_action(ieee,skb);
2463 //dev_kfree_skb_any(skb);
2467 /* following are for a simplier TX queue management.
2468 * Instead of using netif_[stop/wake]_queue the driver
2469 * will uses these two function (plus a reset one), that
2470 * will internally uses the kernel netif_* and takes
2471 * care of the ieee802.11 fragmentation.
2472 * So the driver receives a fragment per time and might
2473 * call the stop function when it want without take care
2474 * to have enough room to TX an entire packet.
2475 * This might be useful if each fragment need it's own
2476 * descriptor, thus just keep a total free memory > than
2477 * the max fragmentation threshold is not enough.. If the
2478 * ieee802.11 stack passed a TXB struct then you needed
2479 * to keep N free descriptors where
2480 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2481 * In this way you need just one and the 802.11 stack
2482 * will take care of buffering fragments and pass them to
2483 * to the driver later, when it wakes the queue.
2485 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2488 unsigned int queue_index = txb->queue_index;
2489 unsigned long flags;
2491 cb_desc *tcb_desc = NULL;
2493 spin_lock_irqsave(&ieee->lock,flags);
2495 /* called with 2nd parm 0, no tx mgmt lock required */
2496 ieee80211_sta_wakeup(ieee,0);
2498 /* update the tx status */
2499 // ieee->stats.tx_bytes += txb->payload_size;
2500 // ieee->stats.tx_packets++;
2501 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2502 if(tcb_desc->bMulticast) {
2503 ieee->stats.multicast++;
2506 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2507 for(i = 0; i < txb->nr_frags; i++) {
2508 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2509 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2511 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2513 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2514 (ieee->queue_stop)) {
2515 /* insert the skb packet to the wait queue */
2516 /* as for the completion function, it does not need
2517 * to check it any more.
2519 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2520 //ieee80211_rtl_stop_queue(ieee);
2521 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2522 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2524 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2527 ieee->softmac_data_hard_start_xmit(
2529 ieee->dev,ieee->rate);
2530 //ieee->stats.tx_packets++;
2531 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2532 //ieee->dev->trans_start = jiffies;
2536 ieee80211_txb_free(txb);
2539 spin_unlock_irqrestore(&ieee->lock,flags);
2543 /* called with ieee->lock acquired */
2544 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2547 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2549 if (ieee->queue_stop){
2550 ieee->tx_pending.frag = i;
2554 ieee->softmac_data_hard_start_xmit(
2555 ieee->tx_pending.txb->fragments[i],
2556 ieee->dev,ieee->rate);
2557 //(i+1)<ieee->tx_pending.txb->nr_frags);
2558 ieee->stats.tx_packets++;
2559 // ieee->dev->trans_start = jiffies;
2564 ieee80211_txb_free(ieee->tx_pending.txb);
2565 ieee->tx_pending.txb = NULL;
2569 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2571 unsigned long flags;
2573 spin_lock_irqsave(&ieee->lock,flags);
2574 init_mgmt_queue(ieee);
2575 if (ieee->tx_pending.txb){
2576 ieee80211_txb_free(ieee->tx_pending.txb);
2577 ieee->tx_pending.txb = NULL;
2579 ieee->queue_stop = 0;
2580 spin_unlock_irqrestore(&ieee->lock,flags);
2584 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2587 unsigned long flags;
2588 struct sk_buff *skb;
2589 struct ieee80211_hdr_3addr *header;
2591 spin_lock_irqsave(&ieee->lock,flags);
2592 if (! ieee->queue_stop) goto exit;
2594 ieee->queue_stop = 0;
2596 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2597 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2599 header = (struct ieee80211_hdr_3addr *) skb->data;
2601 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2603 if (ieee->seq_ctrl[0] == 0xFFF)
2604 ieee->seq_ctrl[0] = 0;
2606 ieee->seq_ctrl[0]++;
2608 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2609 //dev_kfree_skb_any(skb);//edit by thomas
2612 if (!ieee->queue_stop && ieee->tx_pending.txb)
2613 ieee80211_resume_tx(ieee);
2615 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2616 ieee->softmac_stats.swtxawake++;
2617 netif_wake_queue(ieee->dev);
2621 spin_unlock_irqrestore(&ieee->lock,flags);
2625 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2627 //unsigned long flags;
2628 //spin_lock_irqsave(&ieee->lock,flags);
2630 if (! netif_queue_stopped(ieee->dev)){
2631 netif_stop_queue(ieee->dev);
2632 ieee->softmac_stats.swtxstop++;
2634 ieee->queue_stop = 1;
2635 //spin_unlock_irqrestore(&ieee->lock,flags);
2640 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2643 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2645 /* an IBSS cell address must have the two less significant
2646 * bits of the first byte = 2
2648 ieee->current_network.bssid[0] &= ~0x01;
2649 ieee->current_network.bssid[0] |= 0x02;
2652 /* called in user context only */
2653 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2657 if (ieee->current_network.ssid_len == 0){
2658 strncpy(ieee->current_network.ssid,
2659 IEEE80211_DEFAULT_TX_ESSID,
2662 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2666 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2668 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2669 ieee->state = IEEE80211_LINKED;
2670 ieee->link_change(ieee->dev);
2671 notify_wx_assoc_event(ieee);
2673 if (ieee->data_hard_resume)
2674 ieee->data_hard_resume(ieee->dev);
2676 netif_carrier_on(ieee->dev);
2679 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2683 if (ieee->data_hard_resume)
2684 ieee->data_hard_resume(ieee->dev);
2686 netif_carrier_on(ieee->dev);
2689 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2690 void ieee80211_start_ibss_wq(struct work_struct *work)
2693 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2694 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2696 void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2699 /* iwconfig mode ad-hoc will schedule this and return
2700 * on the other hand this will block further iwconfig SET
2701 * operations because of the wx_sem hold.
2702 * Anyway some most set operations set a flag to speed-up
2703 * (abort) this wq (when syncro scanning) before sleeping
2706 if(!ieee->proto_started){
2707 printk("==========oh driver down return\n");
2710 down(&ieee->wx_sem);
2712 if (ieee->current_network.ssid_len == 0){
2713 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2714 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2718 ieee->state = IEEE80211_NOLINK;
2719 /* check if we have this cell in our network list */
2720 ieee80211_softmac_check_all_nets(ieee);
2723 #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.
2724 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2725 if (ieee->state == IEEE80211_NOLINK)
2726 ieee->current_network.channel = 6;
2728 /* if not then the state is not linked. Maybe the user swithced to
2729 * ad-hoc mode just after being in monitor mode, or just after
2730 * being very few time in managed mode (so the card have had no
2731 * time to scan all the chans..) or we have just run up the iface
2732 * after setting ad-hoc mode. So we have to give another try..
2733 * Here, in ibss mode, should be safe to do this without extra care
2734 * (in bss mode we had to make sure no-one tryed to associate when
2735 * we had just checked the ieee->state and we was going to start the
2736 * scan) beacause in ibss mode the ieee80211_new_net function, when
2737 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2738 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2739 * scan, that will stop at the first round because it sees the state
2742 if (ieee->state == IEEE80211_NOLINK)
2743 ieee80211_start_scan_syncro(ieee);
2745 /* the network definitively is not here.. create a new cell */
2746 if (ieee->state == IEEE80211_NOLINK){
2747 printk("creating new IBSS cell\n");
2749 ieee80211_randomize_cell(ieee);
2751 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2753 ieee->current_network.rates_len = 4;
2755 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2756 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2757 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2758 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2761 ieee->current_network.rates_len = 0;
2763 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2764 ieee->current_network.rates_ex_len = 8;
2766 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2767 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2768 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2769 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2770 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2771 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2772 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2773 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2777 ieee->current_network.rates_ex_len = 0;
2781 // By default, WMM function will be disabled in IBSS mode
2782 ieee->current_network.QoS_Enable = 0;
2783 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2784 ieee->current_network.atim_window = 0;
2785 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2786 if(ieee->short_slot)
2787 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2791 ieee->state = IEEE80211_LINKED;
2793 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2794 ieee->link_change(ieee->dev);
2796 notify_wx_assoc_event(ieee);
2798 ieee80211_start_send_beacons(ieee);
2800 if (ieee->data_hard_resume)
2801 ieee->data_hard_resume(ieee->dev);
2802 netif_carrier_on(ieee->dev);
2807 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2809 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2810 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2812 schedule_task(&ieee->start_ibss_wq);
2816 /* this is called only in user context, with wx_sem held */
2817 void ieee80211_start_bss(struct ieee80211_device *ieee)
2819 unsigned long flags;
2820 #ifdef ENABLE_DOT11D
2822 // Ref: 802.11d 11.1.3.3
2823 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2825 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2827 if(! ieee->bGlobalDomain)
2833 /* check if we have already found the net we
2834 * are interested in (if any).
2835 * if not (we are disassociated and we are not
2836 * in associating / authenticating phase) start the background scanning.
2838 ieee80211_softmac_check_all_nets(ieee);
2840 /* ensure no-one start an associating process (thus setting
2841 * the ieee->state to ieee80211_ASSOCIATING) while we
2842 * have just cheked it and we are going to enable scan.
2843 * The ieee80211_new_net function is always called with
2844 * lock held (from both ieee80211_softmac_check_all_nets and
2845 * the rx path), so we cannot be in the middle of such function
2847 spin_lock_irqsave(&ieee->lock, flags);
2849 if (ieee->state == IEEE80211_NOLINK){
2851 if(ieee->ieee80211_ips_leave_wq != NULL)
2852 ieee->ieee80211_ips_leave_wq(ieee->dev);
2854 ieee->actscanning = true;
2855 ieee80211_rtl_start_scan(ieee);
2857 spin_unlock_irqrestore(&ieee->lock, flags);
2860 /* called only in userspace context */
2861 void ieee80211_disassociate(struct ieee80211_device *ieee)
2865 netif_carrier_off(ieee->dev);
2866 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2867 ieee80211_reset_queue(ieee);
2869 if (ieee->data_hard_stop)
2870 ieee->data_hard_stop(ieee->dev);
2871 #ifdef ENABLE_DOT11D
2872 if(IS_DOT11D_ENABLE(ieee))
2875 ieee->state = IEEE80211_NOLINK;
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 notify_wx_assoc_event(ieee);
2882 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2883 void ieee80211_associate_retry_wq(struct work_struct *work)
2885 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2886 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2888 void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2891 unsigned long flags;
2893 down(&ieee->wx_sem);
2894 if(!ieee->proto_started)
2897 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2900 /* until we do not set the state to IEEE80211_NOLINK
2901 * there are no possibility to have someone else trying
2902 * to start an association procdure (we get here with
2903 * ieee->state = IEEE80211_ASSOCIATING).
2904 * When we set the state to IEEE80211_NOLINK it is possible
2905 * that the RX path run an attempt to associate, but
2906 * both ieee80211_softmac_check_all_nets and the
2907 * RX path works with ieee->lock held so there are no
2908 * problems. If we are still disassociated then start a scan.
2909 * the lock here is necessary to ensure no one try to start
2910 * an association procedure when we have just checked the
2911 * state and we are going to start the scan.
2913 ieee->beinretry = true;
2914 ieee->state = IEEE80211_NOLINK;
2916 ieee80211_softmac_check_all_nets(ieee);
2918 spin_lock_irqsave(&ieee->lock, flags);
2920 if(ieee->state == IEEE80211_NOLINK)
2922 ieee->is_roaming= false;
2923 ieee->actscanning = true;
2924 ieee80211_rtl_start_scan(ieee);
2926 spin_unlock_irqrestore(&ieee->lock, flags);
2928 ieee->beinretry = false;
2933 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2935 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2937 struct sk_buff *skb;
2938 struct ieee80211_probe_response *b;
2940 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2945 b = (struct ieee80211_probe_response *) skb->data;
2946 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2952 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2954 struct sk_buff *skb;
2955 struct ieee80211_probe_response *b;
2957 skb = ieee80211_get_beacon_(ieee);
2961 b = (struct ieee80211_probe_response *) skb->data;
2962 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2964 if (ieee->seq_ctrl[0] == 0xFFF)
2965 ieee->seq_ctrl[0] = 0;
2967 ieee->seq_ctrl[0]++;
2972 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2974 ieee->sync_scan_hurryup = 1;
2975 down(&ieee->wx_sem);
2976 ieee80211_stop_protocol(ieee, shutdown);
2981 void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2983 if (!ieee->proto_started)
2987 ieee->proto_started = 0;
2988 ieee->proto_stoppping = 1;
2990 ieee80211_stop_send_beacons(ieee);
2991 del_timer_sync(&ieee->associate_timer);
2992 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2993 cancel_delayed_work(&ieee->associate_retry_wq);
2994 cancel_delayed_work(&ieee->start_ibss_wq);
2996 ieee80211_stop_scan(ieee);
2998 ieee80211_disassociate(ieee);
2999 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
3001 ieee->proto_stoppping = 0;
3004 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
3006 ieee->sync_scan_hurryup = 0;
3007 down(&ieee->wx_sem);
3008 ieee80211_start_protocol(ieee);
3012 void ieee80211_start_protocol(struct ieee80211_device *ieee)
3016 if (ieee->proto_started)
3019 ieee->proto_started = 1;
3021 if (ieee->current_network.channel == 0){
3024 if (ch > MAX_CHANNEL_NUMBER)
3025 return; /* no channel found */
3026 #ifdef ENABLE_DOT11D
3027 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
3029 }while(!ieee->channel_map[ch]);
3031 ieee->current_network.channel = ch;
3034 if (ieee->current_network.beacon_interval == 0)
3035 ieee->current_network.beacon_interval = 100;
3036 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
3037 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
3039 for(i = 0; i < 17; i++) {
3040 ieee->last_rxseq_num[i] = -1;
3041 ieee->last_rxfrag_num[i] = -1;
3042 ieee->last_packet_time[i] = 0;
3045 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
3047 ieee->state = IEEE80211_NOLINK;
3050 /* if the user set the MAC of the ad-hoc cell and then
3051 * switch to managed mode, shall we make sure that association
3052 * attempts does not fail just because the user provide the essid
3053 * and the nic is still checking for the AP MAC ??
3055 if (ieee->iw_mode == IW_MODE_INFRA)
3056 ieee80211_start_bss(ieee);
3058 else if (ieee->iw_mode == IW_MODE_ADHOC)
3059 ieee80211_start_ibss(ieee);
3061 else if (ieee->iw_mode == IW_MODE_MASTER)
3062 ieee80211_start_master_bss(ieee);
3064 else if(ieee->iw_mode == IW_MODE_MONITOR)
3065 ieee80211_start_monitor_mode(ieee);
3069 #define DRV_NAME "Ieee80211"
3070 void ieee80211_softmac_init(struct ieee80211_device *ieee)
3073 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
3075 ieee->state = IEEE80211_NOLINK;
3076 ieee->sync_scan_hurryup = 0;
3077 for(i = 0; i < 5; i++) {
3078 ieee->seq_ctrl[i] = 0;
3080 #ifdef ENABLE_DOT11D
3081 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
3082 if (!ieee->pDot11dInfo)
3083 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
3084 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
3086 //added for AP roaming
3087 ieee->LinkDetectInfo.SlotNum = 2;
3088 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3089 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3092 ieee->queue_stop = 0;
3094 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
3097 ieee->proto_started = 0;
3098 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
3100 ieee->ps = IEEE80211_PS_DISABLED;
3101 ieee->sta_sleep = 0;
3102 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
3103 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
3104 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
3106 ieee->actscanning = false;
3107 ieee->beinretry = false;
3108 ieee->is_set_key = false;
3109 init_mgmt_queue(ieee);
3111 ieee->sta_edca_param[0] = 0x0000A403;
3112 ieee->sta_edca_param[1] = 0x0000A427;
3113 ieee->sta_edca_param[2] = 0x005E4342;
3114 ieee->sta_edca_param[3] = 0x002F3262;
3115 ieee->aggregation = true;
3116 ieee->enable_rx_imm_BA = 1;
3117 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3118 init_timer(&ieee->scan_timer);
3119 ieee->scan_timer.data = (unsigned long)ieee;
3120 ieee->scan_timer.function = ieee80211_softmac_scan_cb;
3122 ieee->tx_pending.txb = NULL;
3124 init_timer(&ieee->associate_timer);
3125 ieee->associate_timer.data = (unsigned long)ieee;
3126 ieee->associate_timer.function = ieee80211_associate_abort_cb;
3128 init_timer(&ieee->beacon_timer);
3129 ieee->beacon_timer.data = (unsigned long) ieee;
3130 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
3132 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3133 #ifdef PF_SYNCTHREAD
3134 ieee->wq = create_workqueue(DRV_NAME,0);
3136 ieee->wq = create_workqueue(DRV_NAME);
3140 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3141 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3142 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
3143 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
3144 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
3145 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
3146 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
3147 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
3150 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3151 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3152 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3153 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3154 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3155 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3159 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3160 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3161 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3162 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3163 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3164 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3166 sema_init(&ieee->wx_sem, 1);
3167 sema_init(&ieee->scan_sem, 1);
3169 sema_init(&ieee->ips_sem,1);
3171 spin_lock_init(&ieee->mgmt_tx_lock);
3172 spin_lock_init(&ieee->beacon_lock);
3174 tasklet_init(&ieee->ps_task,
3175 (void(*)(unsigned long)) ieee80211_sta_ps,
3176 (unsigned long)ieee);
3180 void ieee80211_softmac_free(struct ieee80211_device *ieee)
3182 down(&ieee->wx_sem);
3183 #ifdef ENABLE_DOT11D
3184 if(NULL != ieee->pDot11dInfo)
3186 kfree(ieee->pDot11dInfo);
3187 ieee->pDot11dInfo = NULL;
3190 del_timer_sync(&ieee->associate_timer);
3192 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3193 cancel_delayed_work(&ieee->associate_retry_wq);
3194 destroy_workqueue(ieee->wq);
3200 /********************************************************
3201 * Start of WPA code. *
3202 * this is stolen from the ipw2200 driver *
3203 ********************************************************/
3206 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3208 /* This is called when wpa_supplicant loads and closes the driver
3210 printk("%s WPA\n",value ? "enabling" : "disabling");
3211 ieee->wpa_enabled = value;
3216 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3218 /* make sure WPA is enabled */
3219 ieee80211_wpa_enable(ieee, 1);
3221 ieee80211_disassociate(ieee);
3225 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3231 case IEEE_MLME_STA_DEAUTH:
3235 case IEEE_MLME_STA_DISASSOC:
3236 ieee80211_disassociate(ieee);
3240 printk("Unknown MLME request: %d\n", command);
3248 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3249 struct ieee_param *param, int plen)
3253 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3254 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3257 if (param->u.wpa_ie.len) {
3258 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
3262 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
3263 kfree(ieee->wpa_ie);
3265 ieee->wpa_ie_len = param->u.wpa_ie.len;
3267 kfree(ieee->wpa_ie);
3268 ieee->wpa_ie = NULL;
3269 ieee->wpa_ie_len = 0;
3272 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3276 #define AUTH_ALG_OPEN_SYSTEM 0x1
3277 #define AUTH_ALG_SHARED_KEY 0x2
3279 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3282 struct ieee80211_security sec = {
3283 .flags = SEC_AUTH_MODE,
3287 if (value & AUTH_ALG_SHARED_KEY) {
3288 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3290 ieee->auth_mode = 1;
3291 } else if (value & AUTH_ALG_OPEN_SYSTEM){
3292 sec.auth_mode = WLAN_AUTH_OPEN;
3294 ieee->auth_mode = 0;
3296 else if (value & IW_AUTH_ALG_LEAP){
3297 sec.auth_mode = WLAN_AUTH_LEAP;
3299 ieee->auth_mode = 2;
3303 if (ieee->set_security)
3304 ieee->set_security(ieee->dev, &sec);
3306 // ret = -EOPNOTSUPP;
3311 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3314 unsigned long flags;
3317 case IEEE_PARAM_WPA_ENABLED:
3318 ret = ieee80211_wpa_enable(ieee, value);
3321 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3322 ieee->tkip_countermeasures=value;
3325 case IEEE_PARAM_DROP_UNENCRYPTED: {
3328 * wpa_supplicant calls set_wpa_enabled when the driver
3329 * is loaded and unloaded, regardless of if WPA is being
3330 * used. No other calls are made which can be used to
3331 * determine if encryption will be used or not prior to
3332 * association being expected. If encryption is not being
3333 * used, drop_unencrypted is set to false, else true -- we
3334 * can use this to determine if the CAP_PRIVACY_ON bit should
3337 struct ieee80211_security sec = {
3338 .flags = SEC_ENABLED,
3341 ieee->drop_unencrypted = value;
3342 /* We only change SEC_LEVEL for open mode. Others
3343 * are set by ipw_wpa_set_encryption.
3346 sec.flags |= SEC_LEVEL;
3347 sec.level = SEC_LEVEL_0;
3350 sec.flags |= SEC_LEVEL;
3351 sec.level = SEC_LEVEL_1;
3353 if (ieee->set_security)
3354 ieee->set_security(ieee->dev, &sec);
3358 case IEEE_PARAM_PRIVACY_INVOKED:
3359 ieee->privacy_invoked=value;
3362 case IEEE_PARAM_AUTH_ALGS:
3363 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3366 case IEEE_PARAM_IEEE_802_1X:
3367 ieee->ieee802_1x=value;
3369 case IEEE_PARAM_WPAX_SELECT:
3370 // added for WPA2 mixed mode
3371 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3372 ieee->wpax_type_set = 1;
3373 ieee->wpax_type_notify = value;
3374 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3378 printk("Unknown WPA param: %d\n",name);
3385 /* implementation borrowed from hostap driver */
3387 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3388 struct ieee_param *param, int param_len)
3392 struct ieee80211_crypto_ops *ops;
3393 struct ieee80211_crypt_data **crypt;
3395 struct ieee80211_security sec = {
3399 param->u.crypt.err = 0;
3400 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3403 (int) ((char *) param->u.crypt.key - (char *) param) +
3404 param->u.crypt.key_len) {
3405 printk("Len mismatch %d, %d\n", param_len,
3406 param->u.crypt.key_len);
3409 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3410 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3411 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3412 if (param->u.crypt.idx >= WEP_KEYS)
3414 crypt = &ieee->crypt[param->u.crypt.idx];
3419 if (strcmp(param->u.crypt.alg, "none") == 0) {
3424 sec.level = SEC_LEVEL_0;
3425 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3426 ieee80211_crypt_delayed_deinit(ieee, crypt);
3433 sec.flags |= SEC_ENABLED;
3435 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3436 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3437 strcmp(param->u.crypt.alg, "TKIP"))
3438 goto skip_host_crypt;
3440 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3441 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3442 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3443 /* set WEP40 first, it will be modified according to WEP104 or
3444 * WEP40 at other place */
3445 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3446 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3447 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3448 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3450 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3451 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3456 if (*crypt == NULL || (*crypt)->ops != ops) {
3457 struct ieee80211_crypt_data *new_crypt;
3459 ieee80211_crypt_delayed_deinit(ieee, crypt);
3461 new_crypt = (struct ieee80211_crypt_data *)
3462 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3463 if (new_crypt == NULL) {
3467 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3468 new_crypt->ops = ops;
3471 new_crypt->ops->init(param->u.crypt.idx);
3473 if (new_crypt->priv == NULL) {
3475 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3483 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3484 (*crypt)->ops->set_key(param->u.crypt.key,
3485 param->u.crypt.key_len, param->u.crypt.seq,
3486 (*crypt)->priv) < 0) {
3487 printk("key setting failed\n");
3488 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3494 if (param->u.crypt.set_tx) {
3495 ieee->tx_keyidx = param->u.crypt.idx;
3496 sec.active_key = param->u.crypt.idx;
3497 sec.flags |= SEC_ACTIVE_KEY;
3499 sec.flags &= ~SEC_ACTIVE_KEY;
3501 if (param->u.crypt.alg != NULL) {
3502 memcpy(sec.keys[param->u.crypt.idx],
3504 param->u.crypt.key_len);
3505 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3506 sec.flags |= (1 << param->u.crypt.idx);
3508 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3509 sec.flags |= SEC_LEVEL;
3510 sec.level = SEC_LEVEL_1;
3511 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3512 sec.flags |= SEC_LEVEL;
3513 sec.level = SEC_LEVEL_2;
3514 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3515 sec.flags |= SEC_LEVEL;
3516 sec.level = SEC_LEVEL_3;
3520 if (ieee->set_security)
3521 ieee->set_security(ieee->dev, &sec);
3523 /* Do not reset port if card is in Managed mode since resetting will
3524 * generate new IEEE 802.11 authentication which may end up in looping
3525 * with IEEE 802.1X. If your hardware requires a reset after WEP
3526 * configuration (for example... Prism2), implement the reset_port in
3527 * the callbacks structures used to initialize the 802.11 stack. */
3528 if (ieee->reset_on_keychange &&
3529 ieee->iw_mode != IW_MODE_INFRA &&
3531 ieee->reset_port(ieee->dev)) {
3532 printk("reset_port failed\n");
3533 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3540 inline struct sk_buff *ieee80211_disassociate_skb(
3541 struct ieee80211_network *beacon,
3542 struct ieee80211_device *ieee,
3545 struct sk_buff *skb;
3546 struct ieee80211_disassoc *disass;
3548 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3552 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3553 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3554 disass->header.duration_id = 0;
3556 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3557 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3558 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3560 disass->reason = asRsn;
3567 struct ieee80211_device *ieee,
3572 struct ieee80211_network *beacon = &ieee->current_network;
3573 struct sk_buff *skb;
3574 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3576 softmac_mgmt_xmit(skb, ieee);
3577 //dev_kfree_skb_any(skb);//edit by thomas
3581 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3583 struct ieee_param *param;
3586 down(&ieee->wx_sem);
3587 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3589 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3594 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3599 if (copy_from_user(param, p->pointer, p->length)) {
3605 switch (param->cmd) {
3607 case IEEE_CMD_SET_WPA_PARAM:
3608 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3609 param->u.wpa_param.value);
3612 case IEEE_CMD_SET_WPA_IE:
3613 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3616 case IEEE_CMD_SET_ENCRYPTION:
3617 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3621 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3622 param->u.mlme.reason_code);
3626 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3631 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3641 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3643 union iwreq_data wrqu;
3644 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3645 if (ieee->state == IEEE80211_LINKED)
3646 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3648 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3649 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3652 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3653 //EXPORT_SYMBOL(ieee80211_get_beacon);
3654 //EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3655 //EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3656 //EXPORT_SYMBOL(ieee80211_reset_queue);
3657 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3658 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3659 //EXPORT_SYMBOL(ieee80211_is_shortslot);
3660 //EXPORT_SYMBOL(ieee80211_is_54g);
3661 //EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3662 //EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3663 //EXPORT_SYMBOL(ieee80211_softmac_xmit);
3664 //EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3665 //EXPORT_SYMBOL(notify_wx_assoc_event);
3666 //EXPORT_SYMBOL(SendDisassociation);
3667 //EXPORT_SYMBOL(ieee80211_disassociate);
3668 //EXPORT_SYMBOL(ieee80211_start_send_beacons);
3669 //EXPORT_SYMBOL(ieee80211_stop_scan);
3670 //EXPORT_SYMBOL(ieee80211_send_probe_requests);
3671 //EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3672 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3674 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3675 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3676 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3677 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3678 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3679 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3680 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3681 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3682 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3683 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3684 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3685 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3686 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3687 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3688 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3689 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3690 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3691 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3692 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3693 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3694 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
3695 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);