1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
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 <asm/uaccess.h>
23 #include <linux/etherdevice.h>
27 short ieee80211_is_54g(const struct ieee80211_network *net)
29 return (net->rates_ex_len > 0) || (net->rates_len > 4);
31 EXPORT_SYMBOL(ieee80211_is_54g);
33 short ieee80211_is_shortslot(const struct ieee80211_network *net)
35 return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
37 EXPORT_SYMBOL(ieee80211_is_shortslot);
39 /* returns the total length needed for pleacing the RATE MFIE
40 * tag and the EXTENDED RATE MFIE tag if needed.
41 * It encludes two bytes per tag for the tag itself and its len
43 static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
45 unsigned int rate_len = 0;
47 if (ieee->modulation & IEEE80211_CCK_MODULATION)
48 rate_len = IEEE80211_CCK_RATE_LEN + 2;
50 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
52 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
57 /* pleace the MFIE rate, tag to the memory (double) poined.
58 * Then it updates the pointer so that
59 * it points after the new MFIE tag added.
61 static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
65 if (ieee->modulation & IEEE80211_CCK_MODULATION){
66 *tag++ = MFIE_TYPE_RATES;
68 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
69 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
70 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
71 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
74 /* We may add an option for custom rates that specific HW might support */
78 static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
82 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
84 *tag++ = MFIE_TYPE_RATES_EX;
86 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
87 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
88 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
89 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
90 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
91 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
97 /* We may add an option for custom rates that specific HW might support */
102 static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
106 *tag++ = MFIE_TYPE_GENERIC; //0
115 if(ieee->current_network.wmm_info & 0x80) {
116 *tag++ = 0x0f|MAX_SP_Len;
127 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
130 *tag++ = MFIE_TYPE_GENERIC; //0
141 printk(KERN_ALERT "This is enable turbo mode IE process\n");
145 static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
148 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
151 * if the queue is full but we have newer frames then
152 * just overwrites the oldest.
154 * if (nh == ieee->mgmt_queue_tail)
157 ieee->mgmt_queue_head = nh;
158 ieee->mgmt_queue_ring[nh] = skb;
163 static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
167 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
170 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
172 ieee->mgmt_queue_tail =
173 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
178 static void init_mgmt_queue(struct ieee80211_device *ieee)
180 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
183 static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
185 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
188 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
189 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
192 rate = ieee->basic_rate & 0x7f;
195 // 2005.01.26, by rcnjko.
196 if(ieee->mode == IEEE_A||
197 ieee->mode== IEEE_N_5G||
198 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
205 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
206 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
208 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
218 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
220 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
223 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
224 struct ieee80211_hdr_3addr *header=
225 (struct ieee80211_hdr_3addr *) skb->data;
227 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
228 spin_lock_irqsave(&ieee->lock, flags);
230 /* called with 2nd param 0, no mgmt lock required */
231 ieee80211_sta_wakeup(ieee,0);
233 tcb_desc->queue_index = MGNT_QUEUE;
234 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
235 tcb_desc->RATRIndex = 7;
236 tcb_desc->bTxDisableRateFallBack = 1;
237 tcb_desc->bTxUseDriverAssingedRate = 1;
240 if(ieee->queue_stop){
241 enqueue_mgmt(ieee,skb);
243 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
245 if (ieee->seq_ctrl[0] == 0xFFF)
246 ieee->seq_ctrl[0] = 0;
250 /* avoid watchdog triggers */
251 ieee->dev->trans_start = jiffies;
252 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
253 //dev_kfree_skb_any(skb);//edit by thomas
256 spin_unlock_irqrestore(&ieee->lock, flags);
258 spin_unlock_irqrestore(&ieee->lock, flags);
259 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
261 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
263 if (ieee->seq_ctrl[0] == 0xFFF)
264 ieee->seq_ctrl[0] = 0;
268 /* check whether the managed packet queued greater than 5 */
269 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
270 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
271 (ieee->queue_stop) ) {
272 /* insert the skb packet to the management queue */
273 /* as for the completion function, it does not need
274 * to check it any more.
276 printk("%s():insert to waitqueue!\n",__func__);
277 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
279 //printk("TX packet!\n");
280 ieee->softmac_hard_start_xmit(skb,ieee->dev);
281 //dev_kfree_skb_any(skb);//edit by thomas
283 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
287 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
290 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
291 struct ieee80211_hdr_3addr *header =
292 (struct ieee80211_hdr_3addr *) skb->data;
297 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
299 if (ieee->seq_ctrl[0] == 0xFFF)
300 ieee->seq_ctrl[0] = 0;
304 /* avoid watchdog triggers */
305 ieee->dev->trans_start = jiffies;
306 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
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 ieee->softmac_hard_start_xmit(skb,ieee->dev);
320 //dev_kfree_skb_any(skb);//edit by thomas
323 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
325 unsigned int len,rate_len;
328 struct ieee80211_probe_request *req;
330 len = ieee->current_network.ssid_len;
332 rate_len = ieee80211_MFIE_rate_len(ieee);
334 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
335 2 + len + rate_len + ieee->tx_headroom);
339 skb_reserve(skb, ieee->tx_headroom);
341 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
342 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
343 req->header.duration_id = 0; //FIXME: is this OK ?
345 memset(req->header.addr1, 0xff, ETH_ALEN);
346 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
347 memset(req->header.addr3, 0xff, ETH_ALEN);
349 tag = (u8 *) skb_put(skb,len+2+rate_len);
351 *tag++ = MFIE_TYPE_SSID;
353 memcpy(tag, ieee->current_network.ssid, len);
356 ieee80211_MFIE_Brate(ieee,&tag);
357 ieee80211_MFIE_Grate(ieee,&tag);
361 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
363 static void ieee80211_send_beacon(struct ieee80211_device *ieee)
368 //unsigned long flags;
369 skb = ieee80211_get_beacon_(ieee);
372 softmac_mgmt_xmit(skb, ieee);
373 ieee->softmac_stats.tx_beacons++;
374 //dev_kfree_skb_any(skb);//edit by thomas
376 // ieee->beacon_timer.expires = jiffies +
377 // (MSECS( ieee->current_network.beacon_interval -5));
379 //spin_lock_irqsave(&ieee->beacon_lock,flags);
380 if(ieee->beacon_txing && ieee->ieee_up){
381 // if(!timer_pending(&ieee->beacon_timer))
382 // add_timer(&ieee->beacon_timer);
383 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
385 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
389 static void ieee80211_send_beacon_cb(unsigned long _ieee)
391 struct ieee80211_device *ieee =
392 (struct ieee80211_device *) _ieee;
395 spin_lock_irqsave(&ieee->beacon_lock, flags);
396 ieee80211_send_beacon(ieee);
397 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
401 static void ieee80211_send_probe(struct ieee80211_device *ieee)
405 skb = ieee80211_probe_req(ieee);
407 softmac_mgmt_xmit(skb, ieee);
408 ieee->softmac_stats.tx_probe_rq++;
409 //dev_kfree_skb_any(skb);//edit by thomas
413 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
415 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
416 ieee80211_send_probe(ieee);
417 ieee80211_send_probe(ieee);
420 EXPORT_SYMBOL(ieee80211_send_probe_requests);
422 /* this performs syncro scan blocking the caller until all channels
423 * in the allowed channel map has been checked.
425 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
428 u8 channel_map[MAX_CHANNEL_NUMBER+1];
429 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
430 down(&ieee->scan_sem);
437 if (ch > MAX_CHANNEL_NUMBER)
438 goto out; /* scan completed */
439 }while(!channel_map[ch]);
441 /* this function can be called in two situations
442 * 1- We have switched to ad-hoc mode and we are
443 * performing a complete syncro scan before conclude
444 * there are no interesting cell and to create a
445 * new one. In this case the link state is
446 * IEEE80211_NOLINK until we found an interesting cell.
447 * If so the ieee8021_new_net, called by the RX path
448 * will set the state to IEEE80211_LINKED, so we stop
450 * 2- We are linked and the root uses run iwlist scan.
451 * So we switch to IEEE80211_LINKED_SCANNING to remember
452 * that we are still logically linked (not interested in
453 * new network events, despite for updating the net list,
454 * but we are temporarly 'unlinked' as the driver shall
455 * not filter RX frames and the channel is changing.
456 * So the only situation in witch are interested is to check
457 * if the state become LINKED because of the #1 situation
460 if (ieee->state == IEEE80211_LINKED)
462 ieee->set_chan(ieee->dev, ch);
463 if(channel_map[ch] == 1)
464 ieee80211_send_probe_requests(ieee);
466 /* this prevent excessive time wait when we
467 * need to wait for a syncro scan to end..
469 if(ieee->state < IEEE80211_LINKED)
472 if (ieee->sync_scan_hurryup)
476 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
480 if(ieee->state < IEEE80211_LINKED){
481 ieee->actscanning = false;
485 ieee->sync_scan_hurryup = 0;
486 if(IS_DOT11D_ENABLE(ieee))
487 DOT11D_ScanComplete(ieee);
491 EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
493 static void ieee80211_softmac_scan_wq(struct work_struct *work)
495 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
496 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
497 static short watchdog;
498 u8 channel_map[MAX_CHANNEL_NUMBER+1];
499 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
502 down(&ieee->scan_sem);
504 ieee->current_network.channel =
505 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
506 if (watchdog++ > MAX_CHANNEL_NUMBER)
508 //if current channel is not in channel map, set to default channel.
509 if (!channel_map[ieee->current_network.channel]) {
510 ieee->current_network.channel = 6;
511 goto out; /* no good chans */
514 }while(!channel_map[ieee->current_network.channel]);
515 if (ieee->scanning == 0 )
517 ieee->set_chan(ieee->dev, ieee->current_network.channel);
518 if(channel_map[ieee->current_network.channel] == 1)
519 ieee80211_send_probe_requests(ieee);
522 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
527 if(IS_DOT11D_ENABLE(ieee))
528 DOT11D_ScanComplete(ieee);
529 ieee->actscanning = false;
537 static void ieee80211_beacons_start(struct ieee80211_device *ieee)
540 spin_lock_irqsave(&ieee->beacon_lock,flags);
542 ieee->beacon_txing = 1;
543 ieee80211_send_beacon(ieee);
545 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
548 static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
552 spin_lock_irqsave(&ieee->beacon_lock,flags);
554 ieee->beacon_txing = 0;
555 del_timer_sync(&ieee->beacon_timer);
557 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
562 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
564 if(ieee->stop_send_beacons)
565 ieee->stop_send_beacons(ieee->dev);
566 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
567 ieee80211_beacons_stop(ieee);
569 EXPORT_SYMBOL(ieee80211_stop_send_beacons);
571 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
573 if(ieee->start_send_beacons)
574 ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
575 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
576 ieee80211_beacons_start(ieee);
578 EXPORT_SYMBOL(ieee80211_start_send_beacons);
580 static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
582 // unsigned long flags;
584 //ieee->sync_scan_hurryup = 1;
586 down(&ieee->scan_sem);
587 // spin_lock_irqsave(&ieee->lock, flags);
589 if (ieee->scanning == 1){
592 cancel_delayed_work(&ieee->softmac_scan_wq);
595 // spin_unlock_irqrestore(&ieee->lock, flags);
599 void ieee80211_stop_scan(struct ieee80211_device *ieee)
601 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
602 ieee80211_softmac_stop_scan(ieee);
604 ieee->stop_scan(ieee->dev);
606 EXPORT_SYMBOL(ieee80211_stop_scan);
608 /* called with ieee->lock held */
609 static void ieee80211_start_scan(struct ieee80211_device *ieee)
611 if(IS_DOT11D_ENABLE(ieee) )
613 if(IS_COUNTRY_IE_VALID(ieee))
615 RESET_CIE_WATCHDOG(ieee);
618 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
619 if (ieee->scanning == 0){
621 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
624 ieee->start_scan(ieee->dev);
628 /* called with wx_sem held */
629 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
631 if(IS_DOT11D_ENABLE(ieee) )
633 if(IS_COUNTRY_IE_VALID(ieee))
635 RESET_CIE_WATCHDOG(ieee);
638 ieee->sync_scan_hurryup = 0;
639 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
640 ieee80211_softmac_scan_syncro(ieee);
642 ieee->scan_syncro(ieee->dev);
645 EXPORT_SYMBOL(ieee80211_start_scan_syncro);
647 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
648 struct ieee80211_device *ieee, int challengelen)
651 struct ieee80211_authentication *auth;
652 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
655 skb = dev_alloc_skb(len);
656 if (!skb) return NULL;
658 skb_reserve(skb, ieee->tx_headroom);
659 auth = (struct ieee80211_authentication *)
660 skb_put(skb, sizeof(struct ieee80211_authentication));
662 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
663 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
665 auth->header.duration_id = 0x013a; //FIXME
667 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
668 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
669 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
671 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
672 if(ieee->auth_mode == 0)
673 auth->algorithm = WLAN_AUTH_OPEN;
674 else if(ieee->auth_mode == 1)
675 auth->algorithm = WLAN_AUTH_SHARED_KEY;
676 else if(ieee->auth_mode == 2)
677 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
678 printk("=================>%s():auth->algorithm is %d\n",__func__,auth->algorithm);
679 auth->transaction = cpu_to_le16(ieee->associate_seq);
680 ieee->associate_seq++;
682 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
689 static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
693 struct ieee80211_probe_response *beacon_buf;
694 struct sk_buff *skb = NULL;
696 int atim_len,erp_len;
697 struct ieee80211_crypt_data *crypt;
699 char *ssid = ieee->current_network.ssid;
700 int ssid_len = ieee->current_network.ssid_len;
701 int rate_len = ieee->current_network.rates_len+2;
702 int rate_ex_len = ieee->current_network.rates_ex_len;
703 int wpa_ie_len = ieee->wpa_ie_len;
704 u8 erpinfo_content = 0;
709 u8 tmp_ht_info_len=0;
710 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
711 u8 *tmp_generic_ie_buf=NULL;
712 u8 tmp_generic_ie_len=0;
714 if(rate_ex_len > 0) rate_ex_len+=2;
716 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
721 if(ieee80211_is_54g(&ieee->current_network))
727 crypt = ieee->crypt[ieee->tx_keyidx];
730 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
731 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
733 tmp_ht_cap_buf =(u8 *) &(ieee->pHTInfo->SelfHTCap);
734 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
735 tmp_ht_info_buf =(u8 *) &(ieee->pHTInfo->SelfHTInfo);
736 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
737 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
738 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
741 if(pHTInfo->bRegRT2RTAggregation)
743 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
744 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
745 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
747 // 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);
748 beacon_size = sizeof(struct ieee80211_probe_response)+2+
758 // +tmp_generic_ie_len
761 skb = dev_alloc_skb(beacon_size);
764 skb_reserve(skb, ieee->tx_headroom);
765 beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, (beacon_size - ieee->tx_headroom));
766 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
767 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
768 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
770 beacon_buf->header.duration_id = 0; //FIXME
771 beacon_buf->beacon_interval =
772 cpu_to_le16(ieee->current_network.beacon_interval);
773 beacon_buf->capability =
774 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
775 beacon_buf->capability |=
776 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
778 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
779 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
781 crypt = ieee->crypt[ieee->tx_keyidx];
783 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
786 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
787 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
788 beacon_buf->info_element[0].len = ssid_len;
790 tag = (u8 *) beacon_buf->info_element[0].data;
792 memcpy(tag, ssid, ssid_len);
796 *(tag++) = MFIE_TYPE_RATES;
797 *(tag++) = rate_len-2;
798 memcpy(tag,ieee->current_network.rates,rate_len-2);
801 *(tag++) = MFIE_TYPE_DS_SET;
803 *(tag++) = ieee->current_network.channel;
807 *(tag++) = MFIE_TYPE_IBSS_SET;
809 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
810 val16 = cpu_to_le16(ieee->current_network.atim_window);
811 memcpy((u8 *)tag, (u8 *)&val16, 2);
816 *(tag++) = MFIE_TYPE_ERP;
818 *(tag++) = erpinfo_content;
821 *(tag++) = MFIE_TYPE_RATES_EX;
822 *(tag++) = rate_ex_len-2;
823 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
829 if (ieee->iw_mode == IW_MODE_ADHOC)
830 {//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
831 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
833 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
837 //skb->dev = ieee->dev;
842 static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
848 struct ieee80211_crypt_data *crypt;
849 struct ieee80211_assoc_response_frame *assoc;
852 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
853 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
855 skb = dev_alloc_skb(len);
860 skb_reserve(skb, ieee->tx_headroom);
862 assoc = (struct ieee80211_assoc_response_frame *)
863 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
865 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
866 memcpy(assoc->header.addr1, dest,ETH_ALEN);
867 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
868 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
869 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
870 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
874 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
876 if (ieee->host_encrypt)
877 crypt = ieee->crypt[ieee->tx_keyidx];
880 encrypt = ( crypt && crypt->ops);
883 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
886 assoc->aid = cpu_to_le16(ieee->assoc_id);
887 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
888 else ieee->assoc_id++;
890 tag = (u8 *) skb_put(skb, rate_len);
892 ieee80211_MFIE_Brate(ieee, &tag);
893 ieee80211_MFIE_Grate(ieee, &tag);
898 static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
899 int status, u8 *dest)
902 struct ieee80211_authentication *auth;
903 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
905 skb = dev_alloc_skb(len);
910 skb->len = sizeof(struct ieee80211_authentication);
912 auth = (struct ieee80211_authentication *)skb->data;
914 auth->status = cpu_to_le16(status);
915 auth->transaction = cpu_to_le16(2);
916 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
918 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
919 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
920 memcpy(auth->header.addr1, dest, ETH_ALEN);
921 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
927 static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
931 struct ieee80211_hdr_3addr *hdr;
933 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
938 hdr = (struct ieee80211_hdr_3addr *)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
940 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
941 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
942 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
944 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
945 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
946 (pwr ? IEEE80211_FCTL_PM:0));
954 static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
956 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
959 softmac_mgmt_xmit(buf, ieee);
963 static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
966 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
969 softmac_mgmt_xmit(buf, ieee);
973 static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
977 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
979 softmac_mgmt_xmit(buf, ieee);
983 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
986 //unsigned long flags;
988 struct ieee80211_assoc_request_frame *hdr;
990 //short info_addr = 0;
992 //u16 suite_count = 0;
993 //u8 suit_select = 0;
994 //unsigned int wpa_len = beacon->wpa_ie_len;
996 u8 *ht_cap_buf = NULL;
998 u8 *realtek_ie_buf=NULL;
1000 int wpa_ie_len= ieee->wpa_ie_len;
1001 unsigned int ckip_ie_len=0;
1002 unsigned int ccxrm_ie_len=0;
1003 unsigned int cxvernum_ie_len=0;
1004 struct ieee80211_crypt_data *crypt;
1007 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1008 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1010 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1015 crypt = ieee->crypt[ieee->tx_keyidx];
1016 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1018 //Include High Throuput capability && Realtek proprietary
1019 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1021 ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
1022 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1023 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1024 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1026 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1027 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1028 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1032 if(ieee->qos_support){
1033 wmm_info_len = beacon->qos_data.supported?9:0;
1037 if(beacon->bCkipSupported)
1041 if(beacon->bCcxRmEnable)
1045 if( beacon->BssCcxVerNumber >= 2 )
1047 cxvernum_ie_len = 5+2;
1050 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1051 + beacon->ssid_len//essid tagged val
1052 + rate_len//rates tagged val
1061 + ieee->tx_headroom;
1063 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1064 + beacon->ssid_len//essid tagged val
1065 + rate_len//rates tagged val
1073 + ieee->tx_headroom;
1076 skb = dev_alloc_skb(len);
1081 skb_reserve(skb, ieee->tx_headroom);
1083 hdr = (struct ieee80211_assoc_request_frame *)
1084 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1087 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1088 hdr->header.duration_id= 37; //FIXME
1089 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1090 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1091 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1093 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1095 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1096 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1097 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1099 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1100 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1102 if(ieee->short_slot)
1103 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1104 if (wmm_info_len) //QOS
1105 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1107 hdr->listen_interval = 0xa; //FIXME
1109 hdr->info_element[0].id = MFIE_TYPE_SSID;
1111 hdr->info_element[0].len = beacon->ssid_len;
1112 tag = skb_put(skb, beacon->ssid_len);
1113 memcpy(tag, beacon->ssid, beacon->ssid_len);
1115 tag = skb_put(skb, rate_len);
1117 ieee80211_MFIE_Brate(ieee, &tag);
1118 ieee80211_MFIE_Grate(ieee, &tag);
1119 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1120 if( beacon->bCkipSupported )
1122 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1123 u8 CcxAironetBuf[30];
1124 OCTET_STRING osCcxAironetIE;
1126 memset(CcxAironetBuf, 0,30);
1127 osCcxAironetIE.Octet = CcxAironetBuf;
1128 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1130 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1131 // We want to make the device type as "4500-client". 060926, by CCW.
1133 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1135 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1136 // "The CKIP negotiation is started with the associate request from the client to the access point,
1137 // containing an Aironet element with both the MIC and KP bits set."
1138 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1139 tag = skb_put(skb, ckip_ie_len);
1140 *tag++ = MFIE_TYPE_AIRONET;
1141 *tag++ = osCcxAironetIE.Length;
1142 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1143 tag += osCcxAironetIE.Length;
1146 if(beacon->bCcxRmEnable)
1148 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1149 OCTET_STRING osCcxRmCap;
1151 osCcxRmCap.Octet = CcxRmCapBuf;
1152 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1153 tag = skb_put(skb,ccxrm_ie_len);
1154 *tag++ = MFIE_TYPE_GENERIC;
1155 *tag++ = osCcxRmCap.Length;
1156 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1157 tag += osCcxRmCap.Length;
1160 if( beacon->BssCcxVerNumber >= 2 )
1162 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1163 OCTET_STRING osCcxVerNum;
1164 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1165 osCcxVerNum.Octet = CcxVerNumBuf;
1166 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1167 tag = skb_put(skb,cxvernum_ie_len);
1168 *tag++ = MFIE_TYPE_GENERIC;
1169 *tag++ = osCcxVerNum.Length;
1170 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1171 tag += osCcxVerNum.Length;
1174 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1175 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1177 tag = skb_put(skb, ht_cap_len);
1178 *tag++ = MFIE_TYPE_HT_CAP;
1179 *tag++ = ht_cap_len - 2;
1180 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1181 tag += ht_cap_len -2;
1186 //choose what wpa_supplicant gives to associate.
1187 tag = skb_put(skb, wpa_ie_len);
1189 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1192 tag = skb_put(skb,wmm_info_len);
1194 ieee80211_WMM_Info(ieee, &tag);
1197 tag = skb_put(skb,turbo_info_len);
1198 if(turbo_info_len) {
1199 ieee80211_TURBO_Info(ieee, &tag);
1203 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1204 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1206 tag = skb_put(skb, ht_cap_len);
1207 *tag++ = MFIE_TYPE_GENERIC;
1208 *tag++ = ht_cap_len - 2;
1209 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1210 tag += ht_cap_len -2;
1213 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1214 tag = skb_put(skb, realtek_ie_len);
1215 *tag++ = MFIE_TYPE_GENERIC;
1216 *tag++ = realtek_ie_len - 2;
1217 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1220 // printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1221 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1225 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1228 unsigned long flags;
1229 spin_lock_irqsave(&ieee->lock, flags);
1231 ieee->associate_seq++;
1233 /* don't scan, and avoid to have the RX path possibily
1234 * try again to associate. Even do not react to AUTH or
1235 * ASSOC response. Just wait for the retry wq to be scheduled.
1236 * Here we will check if there are good nets to associate
1237 * with, so we retry or just get back to NO_LINK and scanning
1239 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1240 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1241 ieee->softmac_stats.no_auth_rs++;
1243 IEEE80211_DEBUG_MGMT("Association failed\n");
1244 ieee->softmac_stats.no_ass_rs++;
1247 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1249 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1250 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1252 spin_unlock_irqrestore(&ieee->lock, flags);
1255 static void ieee80211_associate_abort_cb(unsigned long dev)
1257 ieee80211_associate_abort((struct ieee80211_device *) dev);
1261 static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1263 struct ieee80211_network *beacon = &ieee->current_network;
1264 struct sk_buff *skb;
1266 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1268 ieee->softmac_stats.tx_auth_rq++;
1269 skb=ieee80211_authentication_req(beacon, ieee, 0);
1272 ieee80211_associate_abort(ieee);
1274 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1275 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1276 //printk(KERN_WARNING "Sending authentication request\n");
1277 softmac_mgmt_xmit(skb, ieee);
1278 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1279 if(!timer_pending(&ieee->associate_timer)){
1280 ieee->associate_timer.expires = jiffies + (HZ / 2);
1281 add_timer(&ieee->associate_timer);
1283 //dev_kfree_skb_any(skb);//edit by thomas
1287 static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1292 struct sk_buff *skb;
1293 struct ieee80211_network *beacon = &ieee->current_network;
1294 // int hlen = sizeof(struct ieee80211_authentication);
1296 ieee->associate_seq++;
1297 ieee->softmac_stats.tx_auth_rq++;
1299 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1301 ieee80211_associate_abort(ieee);
1303 c = skb_put(skb, chlen+2);
1304 *(c++) = MFIE_TYPE_CHALLENGE;
1306 memcpy(c, challenge, chlen);
1308 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1310 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1312 softmac_mgmt_xmit(skb, ieee);
1313 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1314 //dev_kfree_skb_any(skb);//edit by thomas
1319 static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1321 struct sk_buff *skb;
1322 struct ieee80211_network *beacon = &ieee->current_network;
1324 del_timer_sync(&ieee->associate_timer);
1326 IEEE80211_DEBUG_MGMT("Sending association request\n");
1328 ieee->softmac_stats.tx_ass_rq++;
1329 skb=ieee80211_association_req(beacon, ieee);
1331 ieee80211_associate_abort(ieee);
1333 softmac_mgmt_xmit(skb, ieee);
1334 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1335 //dev_kfree_skb_any(skb);//edit by thomas
1338 static void ieee80211_associate_complete_wq(struct work_struct *work)
1340 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1341 printk(KERN_INFO "Associated successfully\n");
1342 if(ieee80211_is_54g(&ieee->current_network) &&
1343 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1346 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1349 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1351 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1353 printk("Successfully associated, ht enabled\n");
1358 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1359 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1360 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1362 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1363 // To prevent the immediately calling watch_dog after association.
1364 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1366 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1367 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1369 ieee->link_change(ieee->dev);
1370 if(ieee->is_silent_reset == 0){
1371 printk("============>normal associate\n");
1372 notify_wx_assoc_event(ieee);
1374 else if(ieee->is_silent_reset == 1)
1376 printk("==================>silent reset associate\n");
1377 ieee->is_silent_reset = 0;
1380 if (ieee->data_hard_resume)
1381 ieee->data_hard_resume(ieee->dev);
1382 netif_carrier_on(ieee->dev);
1385 static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1388 // struct net_device* dev = ieee->dev;
1389 del_timer_sync(&ieee->associate_timer);
1391 ieee->state = IEEE80211_LINKED;
1392 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1393 queue_work(ieee->wq, &ieee->associate_complete_wq);
1396 static void ieee80211_associate_procedure_wq(struct work_struct *work)
1398 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1399 ieee->sync_scan_hurryup = 1;
1400 down(&ieee->wx_sem);
1402 if (ieee->data_hard_stop)
1403 ieee->data_hard_stop(ieee->dev);
1405 ieee80211_stop_scan(ieee);
1406 printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1407 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1408 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1410 ieee->associate_seq = 1;
1411 ieee80211_associate_step1(ieee);
1416 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1418 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1419 int tmp_ssid_len = 0;
1421 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1423 /* we are interested in new new only if we are not associated
1424 * and we are not associating / authenticating
1426 if (ieee->state != IEEE80211_NOLINK)
1429 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1432 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1436 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1437 /* if the user specified the AP MAC, we need also the essid
1438 * This could be obtained by beacons or, if the network does not
1439 * broadcast it, it can be put manually.
1441 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1442 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1443 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1444 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1445 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1446 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1449 if ( /* if the user set the AP check if match.
1450 * if the network does not broadcast essid we check the user supplyed ANY essid
1451 * if the network does broadcast and the user does not set essid it is OK
1452 * if the network does broadcast and the user did set essid chech if essid match
1454 ( apset && apmatch &&
1455 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1456 /* if the ap is not set, check that the user set the bssid
1457 * and the network does broadcast and that those two bssid matches
1459 (!apset && ssidset && ssidbroad && ssidmatch)
1461 /* if the essid is hidden replace it with the
1462 * essid provided by the user.
1465 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1466 tmp_ssid_len = ieee->current_network.ssid_len;
1468 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1471 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1472 ieee->current_network.ssid_len = tmp_ssid_len;
1474 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);
1476 //ieee->pHTInfo->IOTAction = 0;
1477 HTResetIOTSetting(ieee->pHTInfo);
1478 if (ieee->iw_mode == IW_MODE_INFRA){
1479 /* Join the network for the first time */
1480 ieee->AsocRetryCount = 0;
1481 //for HT by amy 080514
1482 if((ieee->current_network.qos_data.supported == 1) &&
1483 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1484 ieee->current_network.bssht.bdSupportHT)
1485 /*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.*/
1487 // ieee->pHTInfo->bCurrentHTSupport = true;
1488 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1492 ieee->pHTInfo->bCurrentHTSupport = false;
1495 ieee->state = IEEE80211_ASSOCIATING;
1496 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1498 if(ieee80211_is_54g(&ieee->current_network) &&
1499 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1501 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1502 printk(KERN_INFO"Using G rates\n");
1505 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1506 printk(KERN_INFO"Using B rates\n");
1508 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1509 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1510 ieee->state = IEEE80211_LINKED;
1518 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1520 unsigned long flags;
1521 struct ieee80211_network *target;
1523 spin_lock_irqsave(&ieee->lock, flags);
1525 list_for_each_entry(target, &ieee->network_list, list) {
1527 /* if the state become different that NOLINK means
1528 * we had found what we are searching for
1531 if (ieee->state != IEEE80211_NOLINK)
1534 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1535 ieee80211_softmac_new_net(ieee, target);
1538 spin_unlock_irqrestore(&ieee->lock, flags);
1543 static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1545 struct ieee80211_authentication *a;
1547 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1548 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1552 a = (struct ieee80211_authentication *) skb->data;
1553 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1554 t = skb->data + sizeof(struct ieee80211_authentication);
1556 if(*(t++) == MFIE_TYPE_CHALLENGE){
1558 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1564 return cpu_to_le16(a->status);
1569 static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1571 struct ieee80211_authentication *a;
1573 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1574 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1577 a = (struct ieee80211_authentication *) skb->data;
1579 memcpy(dest,a->header.addr2, ETH_ALEN);
1581 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1582 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1584 return WLAN_STATUS_SUCCESS;
1587 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1594 struct ieee80211_hdr_3addr *header =
1595 (struct ieee80211_hdr_3addr *) skb->data;
1597 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1598 return -1; /* corrupted */
1600 memcpy(src,header->addr2, ETH_ALEN);
1602 skbend = (u8 *)skb->data + skb->len;
1604 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1606 while (tag+1 < skbend){
1612 tag++; /* point to the len field */
1613 tag = tag + *(tag); /* point to the last data byte of the tag */
1614 tag++; /* point to the next tag */
1617 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1618 if (ssidlen == 0) return 1;
1620 if (!ssid) return 1; /* ssid not found in tagged param */
1621 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1625 static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1627 struct ieee80211_assoc_request_frame *a;
1629 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1630 sizeof(struct ieee80211_info_element))) {
1632 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1636 a = (struct ieee80211_assoc_request_frame *) skb->data;
1638 memcpy(dest,a->header.addr2,ETH_ALEN);
1643 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1645 struct ieee80211_assoc_response_frame *response_head;
1648 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1649 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1653 response_head = (struct ieee80211_assoc_response_frame *) skb->data;
1654 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1656 status_code = le16_to_cpu(response_head->status);
1657 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1658 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1659 ((ieee->mode == IEEE_G) &&
1660 (ieee->current_network.mode == IEEE_N_24G) &&
1661 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1662 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1664 ieee->AsocRetryCount = 0;
1667 return le16_to_cpu(response_head->status);
1671 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1675 //IEEE80211DMESG("Rx probe");
1676 ieee->softmac_stats.rx_probe_rq++;
1677 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1678 if (probe_rq_parse(ieee, skb, dest)){
1679 //IEEE80211DMESG("Was for me!");
1680 ieee->softmac_stats.tx_probe_rs++;
1681 ieee80211_resp_to_probe(ieee, dest);
1686 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1690 //IEEE80211DMESG("Rx probe");
1691 ieee->softmac_stats.rx_auth_rq++;
1693 status = auth_rq_parse(skb, dest);
1695 ieee80211_resp_to_auth(ieee, status, dest);
1697 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1702 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1706 //unsigned long flags;
1708 ieee->softmac_stats.rx_ass_rq++;
1709 if (assoc_rq_parse(skb,dest) != -1){
1710 ieee80211_resp_to_assoc_rq(ieee, dest);
1713 printk(KERN_INFO"New client associated: %pM\n", dest);
1717 static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1721 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1724 softmac_ps_mgmt_xmit(buf, ieee);
1727 /* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1729 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1732 int timeout = ieee->ps_timeout;
1734 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1735 ieee->iw_mode != IW_MODE_INFRA ||
1736 ieee->state != IEEE80211_LINKED)
1740 dtim = ieee->current_network.dtim_data;
1742 if(!(dtim & IEEE80211_DTIM_VALID))
1744 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1745 //printk("VALID\n");
1746 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1748 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1751 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1754 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1757 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1758 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1762 *time_l = ieee->current_network.last_dtim_sta_time[0]
1763 + (ieee->current_network.beacon_interval
1764 * ieee->current_network.dtim_period) * 1000;
1768 *time_h = ieee->current_network.last_dtim_sta_time[1];
1769 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1778 static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1784 unsigned long flags,flags2;
1786 spin_lock_irqsave(&ieee->lock, flags);
1788 if((ieee->ps == IEEE80211_PS_DISABLED ||
1789 ieee->iw_mode != IW_MODE_INFRA ||
1790 ieee->state != IEEE80211_LINKED)){
1792 // #warning CHECK_LOCK_HERE
1793 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1795 ieee80211_sta_wakeup(ieee, 1);
1797 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1800 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1801 /* 2 wake, 1 sleep, 0 do nothing */
1807 if(ieee->sta_sleep == 1)
1808 ieee->enter_sleep_state(ieee->dev,th,tl);
1810 else if(ieee->sta_sleep == 0){
1811 // printk("send null 1\n");
1812 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1814 if(ieee->ps_is_queue_empty(ieee->dev)){
1817 ieee->sta_sleep = 2;
1819 ieee->ps_request_tx_ack(ieee->dev);
1821 ieee80211_sta_ps_send_null_frame(ieee,1);
1826 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1831 }else if(sleep == 2){
1832 //#warning CHECK_LOCK_HERE
1833 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1835 ieee80211_sta_wakeup(ieee,1);
1837 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1841 spin_unlock_irqrestore(&ieee->lock, flags);
1845 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1847 if(ieee->sta_sleep == 0){
1849 printk("Warning: driver is probably failing to report TX ps error\n");
1850 ieee->ps_request_tx_ack(ieee->dev);
1851 ieee80211_sta_ps_send_null_frame(ieee, 0);
1857 if(ieee->sta_sleep == 1)
1858 ieee->sta_wake_up(ieee->dev);
1860 ieee->sta_sleep = 0;
1863 ieee->ps_request_tx_ack(ieee->dev);
1864 ieee80211_sta_ps_send_null_frame(ieee, 0);
1868 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1870 unsigned long flags,flags2;
1872 spin_lock_irqsave(&ieee->lock, flags);
1874 if(ieee->sta_sleep == 2){
1875 /* Null frame with PS bit set */
1877 ieee->sta_sleep = 1;
1878 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1880 /* if the card report not success we can't be sure the AP
1881 * has not RXed so we can't assume the AP believe us awake
1884 /* 21112005 - tx again null without PS bit if lost */
1887 if((ieee->sta_sleep == 0) && !success){
1888 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1889 ieee80211_sta_ps_send_null_frame(ieee, 0);
1890 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1893 spin_unlock_irqrestore(&ieee->lock, flags);
1895 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1897 static void ieee80211_process_action(struct ieee80211_device *ieee,
1898 struct sk_buff *skb)
1900 struct ieee80211_hdr *header = (struct ieee80211_hdr *)skb->data;
1901 u8 *act = ieee80211_get_payload(header);
1903 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1906 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1913 if (*act == ACT_ADDBAREQ)
1914 ieee80211_rx_ADDBAReq(ieee, skb);
1915 else if (*act == ACT_ADDBARSP)
1916 ieee80211_rx_ADDBARsp(ieee, skb);
1917 else if (*act == ACT_DELBA)
1918 ieee80211_rx_DELBA(ieee, skb);
1927 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1928 struct ieee80211_rx_stats *rx_stats, u16 type,
1931 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1936 struct ieee80211_assoc_response_frame *assoc_resp;
1937 // struct ieee80211_info_element *info_element;
1938 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1940 if(!ieee->proto_started)
1943 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1944 ieee->iw_mode == IW_MODE_INFRA &&
1945 ieee->state == IEEE80211_LINKED))
1947 tasklet_schedule(&ieee->ps_task);
1949 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1950 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1951 ieee->last_rx_ps_time = jiffies;
1953 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1955 case IEEE80211_STYPE_ASSOC_RESP:
1956 case IEEE80211_STYPE_REASSOC_RESP:
1958 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1959 WLAN_FC_GET_STYPE(header->frame_ctl));
1960 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1961 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1962 ieee->iw_mode == IW_MODE_INFRA){
1963 struct ieee80211_network network_resp;
1964 struct ieee80211_network *network = &network_resp;
1966 errcode = assoc_parse(ieee, skb, &aid);
1968 ieee->state=IEEE80211_LINKED;
1969 ieee->assoc_id = aid;
1970 ieee->softmac_stats.rx_ass_ok++;
1971 /* station support qos */
1972 /* Let the register setting defaultly with Legacy station */
1973 if(ieee->qos_support) {
1974 assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
1975 memset(network, 0, sizeof(*network));
1976 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1977 rx_stats->len - sizeof(*assoc_resp),\
1982 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
1983 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1984 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1986 if (ieee->handle_assoc_response != NULL)
1987 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
1989 ieee80211_associate_complete(ieee);
1991 /* aid could not been allocated */
1992 ieee->softmac_stats.rx_ass_err++;
1994 "Association response status code 0x%x\n",
1996 IEEE80211_DEBUG_MGMT(
1997 "Association response status code 0x%x\n",
1999 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2000 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2002 ieee80211_associate_abort(ieee);
2008 case IEEE80211_STYPE_ASSOC_REQ:
2009 case IEEE80211_STYPE_REASSOC_REQ:
2011 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2012 ieee->iw_mode == IW_MODE_MASTER)
2014 ieee80211_rx_assoc_rq(ieee, skb);
2017 case IEEE80211_STYPE_AUTH:
2019 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2020 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2021 ieee->iw_mode == IW_MODE_INFRA){
2023 IEEE80211_DEBUG_MGMT("Received authentication response");
2025 errcode = auth_parse(skb, &challenge, &chlen);
2027 if(ieee->open_wep || !challenge){
2028 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2029 ieee->softmac_stats.rx_auth_rs_ok++;
2030 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2032 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2034 // WEP or TKIP encryption
2035 if(IsHTHalfNmodeAPs(ieee))
2037 bSupportNmode = true;
2038 bHalfSupportNmode = true;
2042 bSupportNmode = false;
2043 bHalfSupportNmode = false;
2045 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2048 /* Dummy wirless mode setting to avoid encryption issue */
2051 ieee->SetWirelessMode(ieee->dev, \
2052 ieee->current_network.mode);
2056 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2059 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2061 printk("===============>entern half N mode\n");
2062 ieee->bHalfWirelessN24GMode = true;
2065 ieee->bHalfWirelessN24GMode = false;
2067 ieee80211_associate_step2(ieee);
2069 ieee80211_auth_challenge(ieee, challenge, chlen);
2072 ieee->softmac_stats.rx_auth_rs_err++;
2073 IEEE80211_DEBUG_MGMT("Authentication response status code 0x%x",errcode);
2074 ieee80211_associate_abort(ieee);
2077 }else if (ieee->iw_mode == IW_MODE_MASTER){
2078 ieee80211_rx_auth_rq(ieee, skb);
2083 case IEEE80211_STYPE_PROBE_REQ:
2085 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2086 ((ieee->iw_mode == IW_MODE_ADHOC ||
2087 ieee->iw_mode == IW_MODE_MASTER) &&
2088 ieee->state == IEEE80211_LINKED)){
2089 ieee80211_rx_probe_rq(ieee, skb);
2093 case IEEE80211_STYPE_DISASSOC:
2094 case IEEE80211_STYPE_DEAUTH:
2095 /* FIXME for now repeat all the association procedure
2096 * both for disassociation and deauthentication
2098 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2099 ieee->state == IEEE80211_LINKED &&
2100 ieee->iw_mode == IW_MODE_INFRA){
2102 ieee->state = IEEE80211_ASSOCIATING;
2103 ieee->softmac_stats.reassoc++;
2105 notify_wx_assoc_event(ieee);
2106 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2107 RemovePeerTS(ieee, header->addr2);
2108 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2111 case IEEE80211_STYPE_MANAGE_ACT:
2112 ieee80211_process_action(ieee,skb);
2119 //dev_kfree_skb_any(skb);
2123 /* following are for a simpler TX queue management.
2124 * Instead of using netif_[stop/wake]_queue the driver
2125 * will uses these two function (plus a reset one), that
2126 * will internally uses the kernel netif_* and takes
2127 * care of the ieee802.11 fragmentation.
2128 * So the driver receives a fragment per time and might
2129 * call the stop function when it want without take care
2130 * to have enought room to TX an entire packet.
2131 * This might be useful if each fragment need it's own
2132 * descriptor, thus just keep a total free memory > than
2133 * the max fragmentation treshold is not enought.. If the
2134 * ieee802.11 stack passed a TXB struct then you needed
2135 * to keep N free descriptors where
2136 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2137 * In this way you need just one and the 802.11 stack
2138 * will take care of buffering fragments and pass them to
2139 * to the driver later, when it wakes the queue.
2141 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2144 unsigned int queue_index = txb->queue_index;
2145 unsigned long flags;
2147 cb_desc *tcb_desc = NULL;
2149 spin_lock_irqsave(&ieee->lock,flags);
2151 /* called with 2nd parm 0, no tx mgmt lock required */
2152 ieee80211_sta_wakeup(ieee,0);
2154 /* update the tx status */
2155 ieee->stats.tx_bytes += txb->payload_size;
2156 ieee->stats.tx_packets++;
2157 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2158 if(tcb_desc->bMulticast) {
2159 ieee->stats.multicast++;
2161 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2162 for(i = 0; i < txb->nr_frags; i++) {
2163 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2164 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2166 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2168 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2169 (ieee->queue_stop)) {
2170 /* insert the skb packet to the wait queue */
2171 /* as for the completion function, it does not need
2172 * to check it any more.
2174 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2175 //ieee80211_stop_queue(ieee);
2176 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2177 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2179 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2182 ieee->softmac_data_hard_start_xmit(
2184 ieee->dev,ieee->rate);
2185 //ieee->stats.tx_packets++;
2186 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2187 //ieee->dev->trans_start = jiffies;
2190 ieee80211_txb_free(txb);
2193 spin_unlock_irqrestore(&ieee->lock,flags);
2196 EXPORT_SYMBOL(ieee80211_softmac_xmit);
2198 /* called with ieee->lock acquired */
2199 static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2202 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2204 if (ieee->queue_stop){
2205 ieee->tx_pending.frag = i;
2209 ieee->softmac_data_hard_start_xmit(
2210 ieee->tx_pending.txb->fragments[i],
2211 ieee->dev,ieee->rate);
2212 //(i+1)<ieee->tx_pending.txb->nr_frags);
2213 ieee->stats.tx_packets++;
2214 ieee->dev->trans_start = jiffies;
2219 ieee80211_txb_free(ieee->tx_pending.txb);
2220 ieee->tx_pending.txb = NULL;
2224 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2226 unsigned long flags;
2228 spin_lock_irqsave(&ieee->lock,flags);
2229 init_mgmt_queue(ieee);
2230 if (ieee->tx_pending.txb){
2231 ieee80211_txb_free(ieee->tx_pending.txb);
2232 ieee->tx_pending.txb = NULL;
2234 ieee->queue_stop = 0;
2235 spin_unlock_irqrestore(&ieee->lock,flags);
2238 EXPORT_SYMBOL(ieee80211_reset_queue);
2240 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2243 unsigned long flags;
2244 struct sk_buff *skb;
2245 struct ieee80211_hdr_3addr *header;
2247 spin_lock_irqsave(&ieee->lock,flags);
2248 if (! ieee->queue_stop) goto exit;
2250 ieee->queue_stop = 0;
2252 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2253 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2255 header = (struct ieee80211_hdr_3addr *) skb->data;
2257 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2259 if (ieee->seq_ctrl[0] == 0xFFF)
2260 ieee->seq_ctrl[0] = 0;
2262 ieee->seq_ctrl[0]++;
2264 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2265 //dev_kfree_skb_any(skb);//edit by thomas
2268 if (!ieee->queue_stop && ieee->tx_pending.txb)
2269 ieee80211_resume_tx(ieee);
2271 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2272 ieee->softmac_stats.swtxawake++;
2273 netif_wake_queue(ieee->dev);
2277 spin_unlock_irqrestore(&ieee->lock,flags);
2279 EXPORT_SYMBOL(ieee80211_wake_queue);
2281 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2283 //unsigned long flags;
2284 //spin_lock_irqsave(&ieee->lock,flags);
2286 if (! netif_queue_stopped(ieee->dev)){
2287 netif_stop_queue(ieee->dev);
2288 ieee->softmac_stats.swtxstop++;
2290 ieee->queue_stop = 1;
2291 //spin_unlock_irqrestore(&ieee->lock,flags);
2294 EXPORT_SYMBOL(ieee80211_stop_queue);
2296 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2299 random_ether_addr(ieee->current_network.bssid);
2302 /* called in user context only */
2303 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2307 if (ieee->current_network.ssid_len == 0){
2308 strncpy(ieee->current_network.ssid,
2309 IEEE80211_DEFAULT_TX_ESSID,
2312 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2316 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2318 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2319 ieee->state = IEEE80211_LINKED;
2320 ieee->link_change(ieee->dev);
2321 notify_wx_assoc_event(ieee);
2323 if (ieee->data_hard_resume)
2324 ieee->data_hard_resume(ieee->dev);
2326 netif_carrier_on(ieee->dev);
2329 static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2333 if (ieee->data_hard_resume)
2334 ieee->data_hard_resume(ieee->dev);
2336 netif_carrier_on(ieee->dev);
2339 static void ieee80211_start_ibss_wq(struct work_struct *work)
2342 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2343 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2344 /* iwconfig mode ad-hoc will schedule this and return
2345 * on the other hand this will block further iwconfig SET
2346 * operations because of the wx_sem hold.
2347 * Anyway some most set operations set a flag to speed-up
2348 * (abort) this wq (when syncro scanning) before sleeping
2351 if(!ieee->proto_started){
2352 printk("==========oh driver down return\n");
2355 down(&ieee->wx_sem);
2357 if (ieee->current_network.ssid_len == 0){
2358 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2359 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2363 /* check if we have this cell in our network list */
2364 ieee80211_softmac_check_all_nets(ieee);
2367 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2368 if (ieee->state == IEEE80211_NOLINK)
2369 ieee->current_network.channel = 6;
2370 /* if not then the state is not linked. Maybe the user swithced to
2371 * ad-hoc mode just after being in monitor mode, or just after
2372 * being very few time in managed mode (so the card have had no
2373 * time to scan all the chans..) or we have just run up the iface
2374 * after setting ad-hoc mode. So we have to give another try..
2375 * Here, in ibss mode, should be safe to do this without extra care
2376 * (in bss mode we had to make sure no-one tryed to associate when
2377 * we had just checked the ieee->state and we was going to start the
2378 * scan) beacause in ibss mode the ieee80211_new_net function, when
2379 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2380 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2381 * scan, that will stop at the first round because it sees the state
2384 if (ieee->state == IEEE80211_NOLINK)
2385 ieee80211_start_scan_syncro(ieee);
2387 /* the network definitively is not here.. create a new cell */
2388 if (ieee->state == IEEE80211_NOLINK){
2389 printk("creating new IBSS cell\n");
2391 ieee80211_randomize_cell(ieee);
2393 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2395 ieee->current_network.rates_len = 4;
2397 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2398 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2399 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2400 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2403 ieee->current_network.rates_len = 0;
2405 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2406 ieee->current_network.rates_ex_len = 8;
2408 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2409 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2410 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2411 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2412 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2413 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2414 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2415 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2419 ieee->current_network.rates_ex_len = 0;
2423 // By default, WMM function will be disabled in IBSS mode
2424 ieee->current_network.QoS_Enable = 0;
2425 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2426 ieee->current_network.atim_window = 0;
2427 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2428 if(ieee->short_slot)
2429 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2433 ieee->state = IEEE80211_LINKED;
2435 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2436 ieee->link_change(ieee->dev);
2438 notify_wx_assoc_event(ieee);
2440 ieee80211_start_send_beacons(ieee);
2442 if (ieee->data_hard_resume)
2443 ieee->data_hard_resume(ieee->dev);
2444 netif_carrier_on(ieee->dev);
2449 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2451 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2454 /* this is called only in user context, with wx_sem held */
2455 void ieee80211_start_bss(struct ieee80211_device *ieee)
2457 unsigned long flags;
2459 // Ref: 802.11d 11.1.3.3
2460 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2462 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2464 if(! ieee->bGlobalDomain)
2469 /* check if we have already found the net we
2470 * are interested in (if any).
2471 * if not (we are disassociated and we are not
2472 * in associating / authenticating phase) start the background scanning.
2474 ieee80211_softmac_check_all_nets(ieee);
2476 /* ensure no-one start an associating process (thus setting
2477 * the ieee->state to ieee80211_ASSOCIATING) while we
2478 * have just cheked it and we are going to enable scan.
2479 * The ieee80211_new_net function is always called with
2480 * lock held (from both ieee80211_softmac_check_all_nets and
2481 * the rx path), so we cannot be in the middle of such function
2483 spin_lock_irqsave(&ieee->lock, flags);
2485 if (ieee->state == IEEE80211_NOLINK){
2486 ieee->actscanning = true;
2487 ieee80211_start_scan(ieee);
2489 spin_unlock_irqrestore(&ieee->lock, flags);
2492 /* called only in userspace context */
2493 void ieee80211_disassociate(struct ieee80211_device *ieee)
2497 netif_carrier_off(ieee->dev);
2498 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2499 ieee80211_reset_queue(ieee);
2501 if (ieee->data_hard_stop)
2502 ieee->data_hard_stop(ieee->dev);
2503 if(IS_DOT11D_ENABLE(ieee))
2505 ieee->state = IEEE80211_NOLINK;
2506 ieee->is_set_key = false;
2507 ieee->link_change(ieee->dev);
2508 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2509 notify_wx_assoc_event(ieee);
2512 EXPORT_SYMBOL(ieee80211_disassociate);
2514 static void ieee80211_associate_retry_wq(struct work_struct *work)
2516 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2517 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2518 unsigned long flags;
2520 down(&ieee->wx_sem);
2521 if(!ieee->proto_started)
2524 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2527 /* until we do not set the state to IEEE80211_NOLINK
2528 * there are no possibility to have someone else trying
2529 * to start an association procedure (we get here with
2530 * ieee->state = IEEE80211_ASSOCIATING).
2531 * When we set the state to IEEE80211_NOLINK it is possible
2532 * that the RX path run an attempt to associate, but
2533 * both ieee80211_softmac_check_all_nets and the
2534 * RX path works with ieee->lock held so there are no
2535 * problems. If we are still disassociated then start a scan.
2536 * the lock here is necessary to ensure no one try to start
2537 * an association procedure when we have just checked the
2538 * state and we are going to start the scan.
2540 ieee->state = IEEE80211_NOLINK;
2542 ieee80211_softmac_check_all_nets(ieee);
2544 spin_lock_irqsave(&ieee->lock, flags);
2546 if(ieee->state == IEEE80211_NOLINK)
2547 ieee80211_start_scan(ieee);
2549 spin_unlock_irqrestore(&ieee->lock, flags);
2555 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2557 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2559 struct sk_buff *skb;
2560 struct ieee80211_probe_response *b;
2562 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2567 b = (struct ieee80211_probe_response *) skb->data;
2568 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2574 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2576 struct sk_buff *skb;
2577 struct ieee80211_probe_response *b;
2579 skb = ieee80211_get_beacon_(ieee);
2583 b = (struct ieee80211_probe_response *) skb->data;
2584 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2586 if (ieee->seq_ctrl[0] == 0xFFF)
2587 ieee->seq_ctrl[0] = 0;
2589 ieee->seq_ctrl[0]++;
2593 EXPORT_SYMBOL(ieee80211_get_beacon);
2595 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2597 ieee->sync_scan_hurryup = 1;
2598 down(&ieee->wx_sem);
2599 ieee80211_stop_protocol(ieee);
2602 EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2604 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2606 if (!ieee->proto_started)
2609 ieee->proto_started = 0;
2611 ieee80211_stop_send_beacons(ieee);
2612 del_timer_sync(&ieee->associate_timer);
2613 cancel_delayed_work(&ieee->associate_retry_wq);
2614 cancel_delayed_work(&ieee->start_ibss_wq);
2615 ieee80211_stop_scan(ieee);
2617 ieee80211_disassociate(ieee);
2618 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2621 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2623 ieee->sync_scan_hurryup = 0;
2624 down(&ieee->wx_sem);
2625 ieee80211_start_protocol(ieee);
2628 EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2630 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2634 if (ieee->proto_started)
2637 ieee->proto_started = 1;
2639 if (ieee->current_network.channel == 0){
2642 if (ch > MAX_CHANNEL_NUMBER)
2643 return; /* no channel found */
2644 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2645 ieee->current_network.channel = ch;
2648 if (ieee->current_network.beacon_interval == 0)
2649 ieee->current_network.beacon_interval = 100;
2650 // printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2651 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2653 for(i = 0; i < 17; i++) {
2654 ieee->last_rxseq_num[i] = -1;
2655 ieee->last_rxfrag_num[i] = -1;
2656 ieee->last_packet_time[i] = 0;
2659 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2662 /* if the user set the MAC of the ad-hoc cell and then
2663 * switch to managed mode, shall we make sure that association
2664 * attempts does not fail just because the user provide the essid
2665 * and the nic is still checking for the AP MAC ??
2667 if (ieee->iw_mode == IW_MODE_INFRA)
2668 ieee80211_start_bss(ieee);
2670 else if (ieee->iw_mode == IW_MODE_ADHOC)
2671 ieee80211_start_ibss(ieee);
2673 else if (ieee->iw_mode == IW_MODE_MASTER)
2674 ieee80211_start_master_bss(ieee);
2676 else if(ieee->iw_mode == IW_MODE_MONITOR)
2677 ieee80211_start_monitor_mode(ieee);
2681 #define DRV_NAME "Ieee80211"
2682 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2685 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2687 ieee->state = IEEE80211_NOLINK;
2688 ieee->sync_scan_hurryup = 0;
2689 for(i = 0; i < 5; i++) {
2690 ieee->seq_ctrl[i] = 0;
2692 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2693 if (!ieee->pDot11dInfo)
2694 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2695 //added for AP roaming
2696 ieee->LinkDetectInfo.SlotNum = 2;
2697 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2698 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2701 ieee->queue_stop = 0;
2703 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2706 ieee->proto_started = 0;
2707 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2709 ieee->ps = IEEE80211_PS_DISABLED;
2710 ieee->sta_sleep = 0;
2711 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2712 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2713 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2715 ieee->actscanning = false;
2716 ieee->beinretry = false;
2717 ieee->is_set_key = false;
2718 init_mgmt_queue(ieee);
2720 ieee->sta_edca_param[0] = 0x0000A403;
2721 ieee->sta_edca_param[1] = 0x0000A427;
2722 ieee->sta_edca_param[2] = 0x005E4342;
2723 ieee->sta_edca_param[3] = 0x002F3262;
2724 ieee->aggregation = true;
2725 ieee->enable_rx_imm_BA = 1;
2726 ieee->tx_pending.txb = NULL;
2728 init_timer(&ieee->associate_timer);
2729 ieee->associate_timer.data = (unsigned long)ieee;
2730 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2732 init_timer(&ieee->beacon_timer);
2733 ieee->beacon_timer.data = (unsigned long) ieee;
2734 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2736 ieee->wq = create_workqueue(DRV_NAME);
2738 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2739 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2740 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2741 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2742 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2743 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2746 sema_init(&ieee->wx_sem, 1);
2747 sema_init(&ieee->scan_sem, 1);
2749 spin_lock_init(&ieee->mgmt_tx_lock);
2750 spin_lock_init(&ieee->beacon_lock);
2752 tasklet_init(&ieee->ps_task,
2753 (void(*)(unsigned long)) ieee80211_sta_ps,
2754 (unsigned long)ieee);
2758 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2760 down(&ieee->wx_sem);
2761 kfree(ieee->pDot11dInfo);
2762 ieee->pDot11dInfo = NULL;
2763 del_timer_sync(&ieee->associate_timer);
2765 cancel_delayed_work(&ieee->associate_retry_wq);
2766 destroy_workqueue(ieee->wq);
2771 /********************************************************
2772 * Start of WPA code. *
2773 * this is stolen from the ipw2200 driver *
2774 ********************************************************/
2777 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2779 /* This is called when wpa_supplicant loads and closes the driver
2781 printk("%s WPA\n",value ? "enabling" : "disabling");
2782 ieee->wpa_enabled = value;
2787 static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2788 char *wpa_ie, int wpa_ie_len)
2790 /* make sure WPA is enabled */
2791 ieee80211_wpa_enable(ieee, 1);
2793 ieee80211_disassociate(ieee);
2797 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2803 case IEEE_MLME_STA_DEAUTH:
2807 case IEEE_MLME_STA_DISASSOC:
2808 ieee80211_disassociate(ieee);
2812 printk("Unknown MLME request: %d\n", command);
2820 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2821 struct ieee_param *param, int plen)
2825 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2826 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2829 if (param->u.wpa_ie.len) {
2830 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2835 kfree(ieee->wpa_ie);
2837 ieee->wpa_ie_len = param->u.wpa_ie.len;
2839 kfree(ieee->wpa_ie);
2840 ieee->wpa_ie = NULL;
2841 ieee->wpa_ie_len = 0;
2844 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2848 #define AUTH_ALG_OPEN_SYSTEM 0x1
2849 #define AUTH_ALG_SHARED_KEY 0x2
2851 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2854 struct ieee80211_security sec = {
2855 .flags = SEC_AUTH_MODE,
2858 if (value & AUTH_ALG_SHARED_KEY) {
2859 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2861 ieee->auth_mode = 1;
2862 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2863 sec.auth_mode = WLAN_AUTH_OPEN;
2865 ieee->auth_mode = 0;
2867 else if (value & IW_AUTH_ALG_LEAP){
2868 sec.auth_mode = WLAN_AUTH_LEAP;
2870 ieee->auth_mode = 2;
2874 if (ieee->set_security)
2875 ieee->set_security(ieee->dev, &sec);
2877 // ret = -EOPNOTSUPP;
2882 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2885 unsigned long flags;
2888 case IEEE_PARAM_WPA_ENABLED:
2889 ret = ieee80211_wpa_enable(ieee, value);
2892 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2893 ieee->tkip_countermeasures=value;
2896 case IEEE_PARAM_DROP_UNENCRYPTED: {
2899 * wpa_supplicant calls set_wpa_enabled when the driver
2900 * is loaded and unloaded, regardless of if WPA is being
2901 * used. No other calls are made which can be used to
2902 * determine if encryption will be used or not prior to
2903 * association being expected. If encryption is not being
2904 * used, drop_unencrypted is set to false, else true -- we
2905 * can use this to determine if the CAP_PRIVACY_ON bit should
2908 struct ieee80211_security sec = {
2909 .flags = SEC_ENABLED,
2912 ieee->drop_unencrypted = value;
2913 /* We only change SEC_LEVEL for open mode. Others
2914 * are set by ipw_wpa_set_encryption.
2917 sec.flags |= SEC_LEVEL;
2918 sec.level = SEC_LEVEL_0;
2921 sec.flags |= SEC_LEVEL;
2922 sec.level = SEC_LEVEL_1;
2924 if (ieee->set_security)
2925 ieee->set_security(ieee->dev, &sec);
2929 case IEEE_PARAM_PRIVACY_INVOKED:
2930 ieee->privacy_invoked=value;
2933 case IEEE_PARAM_AUTH_ALGS:
2934 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2937 case IEEE_PARAM_IEEE_802_1X:
2938 ieee->ieee802_1x=value;
2940 case IEEE_PARAM_WPAX_SELECT:
2941 // added for WPA2 mixed mode
2942 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2943 ieee->wpax_type_set = 1;
2944 ieee->wpax_type_notify = value;
2945 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
2949 printk("Unknown WPA param: %d\n",name);
2956 /* implementation borrowed from hostap driver */
2958 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2959 struct ieee_param *param, int param_len)
2963 struct ieee80211_crypto_ops *ops;
2964 struct ieee80211_crypt_data **crypt;
2966 struct ieee80211_security sec = {
2970 param->u.crypt.err = 0;
2971 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2974 (int) ((char *) param->u.crypt.key - (char *) param) +
2975 param->u.crypt.key_len) {
2976 printk("Len mismatch %d, %d\n", param_len,
2977 param->u.crypt.key_len);
2980 if (is_broadcast_ether_addr(param->sta_addr)) {
2981 if (param->u.crypt.idx >= WEP_KEYS)
2983 crypt = &ieee->crypt[param->u.crypt.idx];
2988 if (strcmp(param->u.crypt.alg, "none") == 0) {
2993 sec.level = SEC_LEVEL_0;
2994 sec.flags |= SEC_ENABLED | SEC_LEVEL;
2995 ieee80211_crypt_delayed_deinit(ieee, crypt);
3002 sec.flags |= SEC_ENABLED;
3004 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3005 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3006 strcmp(param->u.crypt.alg, "TKIP"))
3007 goto skip_host_crypt;
3009 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3010 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3011 request_module("ieee80211_crypt_wep");
3012 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3013 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3014 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3015 request_module("ieee80211_crypt_tkip");
3016 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3017 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3018 request_module("ieee80211_crypt_ccmp");
3019 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3022 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3023 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3028 if (*crypt == NULL || (*crypt)->ops != ops) {
3029 struct ieee80211_crypt_data *new_crypt;
3031 ieee80211_crypt_delayed_deinit(ieee, crypt);
3033 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3034 if (new_crypt == NULL) {
3038 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3039 new_crypt->ops = ops;
3040 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3042 new_crypt->ops->init(param->u.crypt.idx);
3044 if (new_crypt->priv == NULL) {
3046 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3054 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3055 (*crypt)->ops->set_key(param->u.crypt.key,
3056 param->u.crypt.key_len, param->u.crypt.seq,
3057 (*crypt)->priv) < 0) {
3058 printk("key setting failed\n");
3059 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3065 if (param->u.crypt.set_tx) {
3066 ieee->tx_keyidx = param->u.crypt.idx;
3067 sec.active_key = param->u.crypt.idx;
3068 sec.flags |= SEC_ACTIVE_KEY;
3070 sec.flags &= ~SEC_ACTIVE_KEY;
3072 if (param->u.crypt.alg != NULL) {
3073 memcpy(sec.keys[param->u.crypt.idx],
3075 param->u.crypt.key_len);
3076 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3077 sec.flags |= (1 << param->u.crypt.idx);
3079 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3080 sec.flags |= SEC_LEVEL;
3081 sec.level = SEC_LEVEL_1;
3082 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3083 sec.flags |= SEC_LEVEL;
3084 sec.level = SEC_LEVEL_2;
3085 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3086 sec.flags |= SEC_LEVEL;
3087 sec.level = SEC_LEVEL_3;
3091 if (ieee->set_security)
3092 ieee->set_security(ieee->dev, &sec);
3094 /* Do not reset port if card is in Managed mode since resetting will
3095 * generate new IEEE 802.11 authentication which may end up in looping
3096 * with IEEE 802.1X. If your hardware requires a reset after WEP
3097 * configuration (for example... Prism2), implement the reset_port in
3098 * the callbacks structures used to initialize the 802.11 stack. */
3099 if (ieee->reset_on_keychange &&
3100 ieee->iw_mode != IW_MODE_INFRA &&
3102 ieee->reset_port(ieee->dev)) {
3103 printk("reset_port failed\n");
3104 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3111 inline struct sk_buff *ieee80211_disassociate_skb(
3112 struct ieee80211_network *beacon,
3113 struct ieee80211_device *ieee,
3116 struct sk_buff *skb;
3117 struct ieee80211_disassoc *disass;
3119 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3123 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3124 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3125 disass->header.duration_id = 0;
3127 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3128 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3129 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3131 disass->reason = asRsn;
3138 struct ieee80211_device *ieee,
3143 struct ieee80211_network *beacon = &ieee->current_network;
3144 struct sk_buff *skb;
3145 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3147 softmac_mgmt_xmit(skb, ieee);
3148 //dev_kfree_skb_any(skb);//edit by thomas
3151 EXPORT_SYMBOL(SendDisassociation);
3153 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3155 struct ieee_param *param;
3158 down(&ieee->wx_sem);
3159 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3161 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3166 param = memdup_user(p->pointer, p->length);
3167 if (IS_ERR(param)) {
3168 ret = PTR_ERR(param);
3172 switch (param->cmd) {
3174 case IEEE_CMD_SET_WPA_PARAM:
3175 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3176 param->u.wpa_param.value);
3179 case IEEE_CMD_SET_WPA_IE:
3180 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3183 case IEEE_CMD_SET_ENCRYPTION:
3184 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3188 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3189 param->u.mlme.reason_code);
3193 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3198 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3207 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3209 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3211 union iwreq_data wrqu;
3212 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3213 if (ieee->state == IEEE80211_LINKED)
3214 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3216 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3217 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3219 EXPORT_SYMBOL(notify_wx_assoc_event);