Staging: rtl8192e: Do not send NULL BSSID events when not associated
[linux-2.6/libata-dev.git] / drivers / staging / rtl8192e / ieee80211 / ieee80211_softmac.c
blobd2a243a718243e3d82dda940f248b6fd089f53ee
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>
24 #ifdef ENABLE_DOT11D
25 #include "dot11d.h"
26 #endif
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;
62 return rate_len;
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)
71 u8 *tag = *tag_p;
73 if (ieee->modulation & IEEE80211_CCK_MODULATION){
74 *tag++ = MFIE_TYPE_RATES;
75 *tag++ = 4;
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 */
83 *tag_p = tag;
86 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
88 u8 *tag = *tag_p;
90 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
92 *tag++ = MFIE_TYPE_RATES_EX;
93 *tag++ = 8;
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 */
106 *tag_p = tag;
110 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
111 u8 *tag = *tag_p;
113 *tag++ = MFIE_TYPE_GENERIC; //0
114 *tag++ = 7;
115 *tag++ = 0x00;
116 *tag++ = 0x50;
117 *tag++ = 0xf2;
118 *tag++ = 0x02;//5
119 *tag++ = 0x00;
120 *tag++ = 0x01;
121 #ifdef SUPPORT_USPD
122 if(ieee->current_network.wmm_info & 0x80) {
123 *tag++ = 0x0f|MAX_SP_Len;
124 } else {
125 *tag++ = MAX_SP_Len;
127 #else
128 *tag++ = MAX_SP_Len;
129 #endif
130 *tag_p = tag;
133 #ifdef THOMAS_TURBO
134 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
135 u8 *tag = *tag_p;
137 *tag++ = MFIE_TYPE_GENERIC; //0
138 *tag++ = 7;
139 *tag++ = 0x00;
140 *tag++ = 0xe0;
141 *tag++ = 0x4c;
142 *tag++ = 0x01;//5
143 *tag++ = 0x02;
144 *tag++ = 0x11;
145 *tag++ = 0x00;
147 *tag_p = tag;
148 printk(KERN_ALERT "This is enable turbo mode IE process\n");
150 #endif
152 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
154 int nh;
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)
162 * return -1;
164 ieee->mgmt_queue_head = nh;
165 ieee->mgmt_queue_ring[nh] = skb;
167 //return 0;
170 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
172 struct sk_buff *ret;
174 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
175 return NULL;
177 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
179 ieee->mgmt_queue_tail =
180 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
182 return ret;
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;
193 u8 rate;
195 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
196 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
197 rate = 0x0c;
198 else
199 rate = ieee->basic_rate & 0x7f;
201 if(rate == 0){
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))
206 rate = 0x0c;
207 else
208 rate = 0x02;
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)
216 rate = 0x0c;
217 else
218 rate = 0x02;
221 return rate;
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)
229 unsigned long flags;
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;
246 if(single){
247 if(ieee->queue_stop){
248 enqueue_mgmt(ieee,skb);
249 }else{
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;
254 else
255 ieee->seq_ctrl[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);
264 }else{
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;
272 else
273 ieee->seq_ctrl[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.
282 * */
283 //printk("%s():insert to waitqueue!\n",__FUNCTION__);
284 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
285 } else {
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__);
308 if(single){
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;
314 else
315 ieee->seq_ctrl[0]++;
317 /* avoid watchdog triggers */
318 // ieee->dev->trans_start = jiffies;
319 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
321 }else{
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;
327 else
328 ieee->seq_ctrl[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;
339 u8 *tag;
340 struct sk_buff *skb;
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);
349 if (!skb)
350 return NULL;
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;
365 *tag++ = len;
366 memcpy(tag, ieee->current_network.ssid, len);
367 tag += len;
369 ieee80211_MFIE_Brate(ieee,&tag);
370 ieee80211_MFIE_Grate(ieee,&tag);
371 return skb;
374 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
375 void ieee80211_send_beacon(struct ieee80211_device *ieee)
377 struct sk_buff *skb;
378 if(!ieee->ieee_up)
379 return;
380 //unsigned long flags;
381 skb = ieee80211_get_beacon_(ieee);
383 if (skb){
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;
405 unsigned long flags;
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)
415 struct sk_buff *skb;
417 skb = ieee80211_probe_req(ieee);
418 if (skb){
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)
438 short ch = 0;
439 #ifdef ENABLE_DOT11D
440 u8 channel_map[MAX_CHANNEL_NUMBER+1];
441 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
442 #endif
443 down(&ieee->scan_sem);
445 while(1)
449 ch++;
450 if (ch > MAX_CHANNEL_NUMBER)
451 goto out; /* scan completed */
452 #ifdef ENABLE_DOT11D
453 }while(!channel_map[ch]);
454 #else
455 }while(!ieee->channel_map[ch]);
456 #endif
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
466 * scanning
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)
478 goto out;
479 ieee->set_chan(ieee->dev, ch);
480 #ifdef ENABLE_DOT11D
481 if(channel_map[ch] == 1)
482 #endif
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)
490 else
491 if (ieee->sync_scan_hurryup)
492 goto out;
495 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
498 out:
499 if(ieee->state < IEEE80211_LINKED){
500 ieee->actscanning = false;
501 up(&ieee->scan_sem);
503 else{
504 ieee->sync_scan_hurryup = 0;
505 #ifdef ENABLE_DOT11D
506 if(IS_DOT11D_ENABLE(ieee))
507 DOT11D_ScanComplete(ieee);
508 #endif
509 up(&ieee->scan_sem);
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)
517 #if 0
518 short watchdog = 0;
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]);
526 #endif
528 schedule_task(&ieee->softmac_scan_wq);
530 #endif
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);
537 #else
538 void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee)
540 #endif
541 static short watchdog = 0;
542 u8 last_channel = ieee->current_network.channel;
543 #ifdef ENABLE_DOT11D
544 u8 channel_map[MAX_CHANNEL_NUMBER+1];
545 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
546 #endif
547 if(!ieee->ieee_up)
548 return;
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.
556 #ifdef ENABLE_DOT11D
557 if (!channel_map[ieee->current_network.channel]);
558 #else
559 if (!ieee->channel_map[ieee->current_network.channel]);
560 #endif
561 ieee->current_network.channel = 6;
562 goto out; /* no good chans */
564 #ifdef ENABLE_DOT11D
565 }while(!channel_map[ieee->current_network.channel]);
566 #else
567 }while(!ieee->channel_map[ieee->current_network.channel]);
568 #endif
569 if (ieee->scanning == 0 )
570 goto out;
571 ieee->set_chan(ieee->dev, ieee->current_network.channel);
572 #ifdef ENABLE_DOT11D
573 if(channel_map[ieee->current_network.channel] == 1)
574 #endif
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);
580 #else
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)));
584 #endif
586 up(&ieee->scan_sem);
587 return;
588 out:
589 #ifdef ENABLE_DOT11D
590 if(IS_DOT11D_ENABLE(ieee))
591 DOT11D_ScanComplete(ieee);
592 #endif
593 ieee->current_network.channel = last_channel;
594 ieee->actscanning = false;
595 watchdog = 0;
596 ieee->scanning = 0;
597 up(&ieee->scan_sem);
600 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
601 void ieee80211_softmac_scan_cb(unsigned long _dev)
603 unsigned long flags;
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);
610 #endif
613 void ieee80211_beacons_start(struct ieee80211_device *ieee)
615 unsigned long flags;
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)
626 unsigned long flags;
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){
666 ieee->scanning = 0;
668 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
669 cancel_delayed_work(&ieee->softmac_scan_wq);
670 #else
671 del_timer_sync(&ieee->scan_timer);
672 #endif
675 // spin_unlock_irqrestore(&ieee->lock, flags);
676 up(&ieee->scan_sem);
679 void ieee80211_stop_scan(struct ieee80211_device *ieee)
681 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
682 ieee80211_softmac_stop_scan(ieee);
683 else
684 ieee->stop_scan(ieee->dev);
687 /* called with ieee->lock held */
688 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
690 #ifdef ENABLE_IPS
691 if(ieee->ieee80211_ips_leave_wq != NULL)
692 ieee->ieee80211_ips_leave_wq(ieee->dev);
693 #endif
695 #ifdef ENABLE_DOT11D
696 if(IS_DOT11D_ENABLE(ieee) )
698 if(IS_COUNTRY_IE_VALID(ieee))
700 RESET_CIE_WATCHDOG(ieee);
703 #endif
704 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
705 if (ieee->scanning == 0){
706 ieee->scanning = 1;
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);
710 #else
712 queue_work(ieee->wq, &ieee->softmac_scan_wq);
713 #endif
714 #else
715 ieee80211_softmac_scan(ieee);
716 #endif
718 }else
719 ieee->start_scan(ieee->dev);
723 /* called with wx_sem held */
724 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
726 #ifdef ENABLE_DOT11D
727 if(IS_DOT11D_ENABLE(ieee) )
729 if(IS_COUNTRY_IE_VALID(ieee))
731 RESET_CIE_WATCHDOG(ieee);
734 #endif
735 ieee->sync_scan_hurryup = 0;
736 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
737 ieee80211_softmac_scan_syncro(ieee);
738 else
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)
746 struct sk_buff *skb;
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);
780 return skb;
785 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
787 u8 *tag;
788 int beacon_size;
789 struct ieee80211_probe_response *beacon_buf;
790 struct sk_buff *skb = NULL;
791 int encrypt;
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;
802 u8* tmp_ht_cap_buf;
803 u8 tmp_ht_cap_len=0;
804 u8* tmp_ht_info_buf;
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)
813 atim_len = 4;
814 else
815 atim_len = 0;
817 #if 1
818 if(ieee80211_is_54g(ieee->current_network))
819 erp_len = 3;
820 else
821 erp_len = 0;
822 #else
823 if((ieee->current_network.mode == IEEE_G)
824 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
825 erp_len = 3;
826 erpinfo_content = 0;
827 if(ieee->current_network.buseprotection)
828 erpinfo_content |= ERP_UseProtection;
830 else
831 erp_len = 0;
832 #endif
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));
840 //HT ralated element
841 #if 1
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);
857 #endif
858 beacon_size = sizeof(struct ieee80211_probe_response)+2+
859 ssid_len
860 +3 //channel
861 +rate_len
862 +rate_ex_len
863 +atim_len
864 +erp_len
865 +wpa_ie_len
866 // +tmp_ht_cap_len
867 // +tmp_ht_info_len
868 // +tmp_generic_ie_len
869 // +wmm_len+2
870 +ieee->tx_headroom;
871 skb = dev_alloc_skb(beacon_size);
872 if (!skb)
873 return NULL;
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];
892 #if 0
893 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
894 (0 == strcmp(crypt->ops->name, "WEP"));
895 #endif
896 if (encrypt)
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);
908 tag += ssid_len;
910 *(tag++) = MFIE_TYPE_RATES;
911 *(tag++) = rate_len-2;
912 memcpy(tag,ieee->current_network.rates,rate_len-2);
913 tag+=rate_len-2;
915 *(tag++) = MFIE_TYPE_DS_SET;
916 *(tag++) = 1;
917 *(tag++) = ieee->current_network.channel;
919 if(atim_len){
920 u16 val16;
921 *(tag++) = MFIE_TYPE_IBSS_SET;
922 *(tag++) = 2;
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);
926 tag+=2;
929 if(erp_len){
930 *(tag++) = MFIE_TYPE_ERP;
931 *(tag++) = 1;
932 *(tag++) = erpinfo_content;
934 #if 0
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;
941 #endif
942 if(rate_ex_len){
943 *(tag++) = MFIE_TYPE_RATES_EX;
944 *(tag++) = rate_ex_len-2;
945 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
946 tag+=rate_ex_len-2;
949 #if 0
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;
956 #endif
957 if (wpa_ie_len)
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);
964 tag += wpa_ie_len;
967 #if 0
969 // Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
971 if(pHTInfo->bRegRT2RTAggregation)
973 (*tag++) = 0xdd;
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;
979 #endif
980 #if 0
981 if(ieee->qos_support)
983 (*tag++) = 0xdd;
984 (*tag++) = wmm_len;
985 memcpy(tag,QosOui,wmm_len);
986 tag += wmm_len;
988 #endif
989 //skb->dev = ieee->dev;
990 return skb;
994 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
996 struct sk_buff *skb;
997 u8* tag;
999 struct ieee80211_crypt_data* crypt;
1000 struct ieee80211_assoc_response_frame *assoc;
1001 short encrypt;
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);
1008 if (!skb)
1009 return NULL;
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];
1029 else crypt = NULL;
1031 encrypt = ( crypt && crypt->ops);
1033 if (encrypt)
1034 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1036 assoc->status = 0;
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);
1046 return skb;
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);
1057 if (!skb)
1058 return NULL;
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);
1072 return skb;
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));
1084 if (!skb)
1085 return NULL;
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));
1097 return skb;
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
1108 u32 Tmpaddr=0;
1109 int alignment=0;
1110 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
1111 #else
1112 skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
1113 #endif
1114 if (!skb)
1115 return NULL;
1117 #ifdef USB_USE_ALIGNMENT
1118 Tmpaddr = (u32)skb->data;
1119 alignment = Tmpaddr & 0x1ff;
1120 skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
1121 #endif
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);
1132 return skb;
1137 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1139 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1141 if (buf)
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);
1150 if (buf)
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);
1160 if (buf)
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;
1171 u8 *tag;//,*rsn_ie;
1172 //short info_addr = 0;
1173 //int i;
1174 //u16 suite_count = 0;
1175 //u8 suit_select = 0;
1176 //unsigned int wpa_len = beacon->wpa_ie_len;
1177 //for HT
1178 u8* ht_cap_buf = NULL;
1179 u8 ht_cap_len=0;
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;
1187 int encrypt;
1189 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1190 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1191 #ifdef THOMAS_TURBO
1192 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1193 #endif
1195 int len = 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)
1221 ckip_ie_len = 30+2;
1223 if(beacon->bCcxRmEnable)
1225 ccxrm_ie_len = 6+2;
1227 if( beacon->BssCcxVerNumber >= 2 )
1229 cxvernum_ie_len = 5+2;
1231 #ifdef THOMAS_TURBO
1232 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1233 + beacon->ssid_len//essid tagged val
1234 + rate_len//rates tagged val
1235 + wpa_ie_len
1236 + wmm_info_len
1237 + turbo_info_len
1238 + ht_cap_len
1239 + realtek_ie_len
1240 + ckip_ie_len
1241 + ccxrm_ie_len
1242 + cxvernum_ie_len
1243 + ieee->tx_headroom;
1244 #else
1245 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1246 + beacon->ssid_len//essid tagged val
1247 + rate_len//rates tagged val
1248 + wpa_ie_len
1249 + wmm_info_len
1250 + ht_cap_len
1251 + realtek_ie_len
1252 + ckip_ie_len
1253 + ccxrm_ie_len
1254 + cxvernum_ie_len
1255 + ieee->tx_headroom;
1256 #endif
1258 skb = dev_alloc_skb(len);
1260 if (!skb)
1261 return NULL;
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;
1355 //HT cap element
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);
1370 if (wpa_ie_len){
1371 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1374 tag = skb_put(skb,wmm_info_len);
1375 if(wmm_info_len) {
1376 ieee80211_WMM_Info(ieee, &tag);
1378 #ifdef THOMAS_TURBO
1379 tag = skb_put(skb,turbo_info_len);
1380 if(turbo_info_len) {
1381 ieee80211_TURBO_Info(ieee, &tag);
1383 #endif
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);
1404 return skb;
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++;
1424 }else{
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);
1434 #else
1435 schedule_task(&ieee->associate_retry_wq);
1436 #endif
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);
1457 if (!skb)
1458 ieee80211_associate_abort(ieee);
1459 else{
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)
1475 u8 *c;
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);
1484 if (!skb)
1485 ieee80211_associate_abort(ieee);
1486 else{
1487 c = skb_put(skb, chlen+2);
1488 *(c++) = MFIE_TYPE_CHALLENGE;
1489 *(c++) = chlen;
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));
1498 #if 0
1499 ieee->associate_timer.expires = jiffies + (HZ / 2);
1500 add_timer(&ieee->associate_timer);
1501 #endif
1502 //dev_kfree_skb_any(skb);//edit by thomas
1504 kfree(challenge);
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);
1518 if (!skb)
1519 ieee80211_associate_abort(ieee);
1520 else{
1521 softmac_mgmt_xmit(skb, ieee);
1522 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1523 #if 0
1524 ieee->associate_timer.expires = jiffies + (HZ / 2);
1525 add_timer(&ieee->associate_timer);
1526 #endif
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);
1534 #else
1535 void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1537 #endif
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)){
1543 ieee->rate = 108;
1544 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1545 }else{
1546 ieee->rate = 22;
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");
1552 HTOnAssocRsp(ieee);
1554 else
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)
1585 // int i;
1586 // struct net_device* dev = ieee->dev;
1587 del_timer_sync(&ieee->associate_timer);
1589 #if 0
1590 for(i = 0; i < 6; i++) {
1591 ieee->seq_ctrl[i] = 0;
1593 #endif
1594 ieee->state = IEEE80211_LINKED;
1595 #if 0
1596 if (ieee->pHTInfo->bCurrentHTSupport)
1598 printk("Successfully associated, ht enabled\n");
1599 queue_work(ieee->wq, &ieee->ht_onAssRsp);
1601 else
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);
1607 #endif
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);
1611 #else
1612 schedule_task(&ieee->associate_complete_wq);
1613 #endif
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);
1620 #else
1621 void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1623 #endif
1624 ieee->sync_scan_hurryup = 1;
1625 #ifdef ENABLE_IPS
1626 if(ieee->ieee80211_ips_leave != NULL)
1627 ieee->ieee80211_ips_leave(ieee->dev);
1628 #endif
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);
1640 #ifdef ENABLE_IPS
1641 if(ieee->eRFPowerState == eRfOff)
1643 if(ieee->ieee80211_ips_leave_wq != NULL)
1644 ieee->ieee80211_ips_leave_wq(ieee->dev);
1646 up(&ieee->wx_sem);
1647 return;
1649 #endif
1651 ieee->associate_seq = 1;
1652 ieee80211_associate_step1(ieee);
1654 up(&ieee->wx_sem);
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)
1668 return;
1670 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1671 return;
1673 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1674 return;
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.
1705 if (!ssidbroad){
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));
1711 if (!ssidbroad){
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));
1731 else
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);
1739 #else
1740 schedule_task(&ieee->associate_procedure_wq);
1741 #endif
1742 }else{
1743 if(ieee80211_is_54g(ieee->current_network) &&
1744 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1745 ieee->rate = 108;
1746 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1747 printk(KERN_INFO"Using G rates\n");
1748 }else{
1749 ieee->rate = 22;
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)
1777 break;
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;
1791 u8 *t;
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);
1794 return 0xcafe;
1796 *challenge = NULL;
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){
1802 *chlen = *(t++);
1803 *challenge = kmalloc(*chlen, GFP_ATOMIC);
1804 memcpy(*challenge, t, *chlen);
1808 return cpu_to_le16(a->status);
1813 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1815 struct ieee80211_authentication *a;
1817 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1818 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1819 return -1;
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)
1833 u8 *tag;
1834 u8 *skbend;
1835 u8 *ssid=NULL;
1836 u8 ssidlen = 0;
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){
1851 if (*tag == 0){
1852 ssid = tag+2;
1853 ssidlen = *(tag+1);
1854 break;
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);
1877 return -1;
1880 a = (struct ieee80211_assoc_request_frame*) skb->data;
1882 memcpy(dest,a->header.addr2,ETH_ALEN);
1884 return 0;
1887 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1889 struct ieee80211_assoc_response_frame *response_head;
1890 u16 status_code;
1892 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1893 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1894 return 0xcafe;
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;
1907 }else {
1908 ieee->AsocRetryCount = 0;
1911 return le16_to_cpu(response_head->status);
1914 static inline void
1915 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1917 u8 dest[ETH_ALEN];
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);
1929 static inline void
1930 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1932 u8 dest[ETH_ALEN];
1933 int status;
1934 //IEEE80211DMESG("Rx probe");
1935 ieee->softmac_stats.rx_auth_rq++;
1937 status = auth_rq_parse(skb, dest);
1938 if (status != -1) {
1939 ieee80211_resp_to_auth(ieee, status, dest);
1941 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1945 static inline void
1946 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1949 u8 dest[ETH_ALEN];
1950 //unsigned long flags;
1952 ieee->softmac_stats.rx_ass_rq++;
1953 if (assoc_rq_parse(skb,dest) != -1){
1954 ieee80211_resp_to_assoc_rq(ieee, dest);
1957 printk(KERN_INFO"New client associated: %pM\n", dest);
1958 //FIXME
1959 #if 0
1960 spin_lock_irqsave(&ieee->lock,flags);
1961 add_associate(ieee,dest);
1962 spin_unlock_irqrestore(&ieee->lock,flags);
1963 #endif
1968 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1971 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1973 if (buf)
1974 softmac_ps_mgmt_xmit(buf, ieee);
1978 void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1981 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1983 if (buf)
1984 softmac_ps_mgmt_xmit(buf, ieee);
1988 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1990 int timeout = ieee->ps_timeout;
1991 u8 dtim;
1992 PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
1994 if(ieee->LPSDelayCnt)
1996 //printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
1997 ieee->LPSDelayCnt --;
1998 return 0;
2001 dtim = ieee->current_network.dtim_data;
2002 // printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
2003 if(!(dtim & IEEE80211_DTIM_VALID))
2004 return 0;
2005 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
2006 //printk("VALID\n");
2007 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
2008 /* there's no need to nofity AP that I find you buffered with broadcast packet */
2009 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
2010 return 2;
2012 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
2013 // printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2014 return 0;
2016 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
2017 // printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2018 return 0;
2020 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
2021 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
2022 return 0;
2024 if(time_l){
2025 if(ieee->bAwakePktSent == true) {
2026 pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
2027 } else {
2028 u8 MaxPeriod = 1;
2030 if(pPSC->LPSAwakeIntvl == 0)
2031 pPSC->LPSAwakeIntvl = 1;
2032 //pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
2033 if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
2034 MaxPeriod = 1; // 1 Beacon interval
2035 else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
2036 MaxPeriod = ieee->current_network.dtim_period;
2037 else
2038 MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
2039 pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
2042 u8 LPSAwakeIntvl_tmp = 0;
2043 u8 period = ieee->current_network.dtim_period;
2044 u8 count = ieee->current_network.tim.tim_count;
2045 if(count == 0 ) {
2046 if(pPSC->LPSAwakeIntvl > period)
2047 LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
2048 else
2049 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
2051 } else {
2052 if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
2053 LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
2054 else
2055 LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
2057 //printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
2059 *time_l = ieee->current_network.last_dtim_sta_time[0]
2060 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
2061 // * ieee->current_network.dtim_period) * 1000;
2065 if(time_h){
2066 *time_h = ieee->current_network.last_dtim_sta_time[1];
2067 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
2068 *time_h += 1;
2071 return 1;
2076 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
2079 u32 th,tl;
2080 short sleep;
2082 unsigned long flags,flags2;
2084 spin_lock_irqsave(&ieee->lock, flags);
2086 if((ieee->ps == IEEE80211_PS_DISABLED ||
2087 ieee->iw_mode != IW_MODE_INFRA ||
2088 ieee->state != IEEE80211_LINKED)){
2090 // #warning CHECK_LOCK_HERE
2091 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
2092 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
2093 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2095 ieee80211_sta_wakeup(ieee, 1);
2097 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2100 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
2101 /* 2 wake, 1 sleep, 0 do nothing */
2102 if(sleep == 0)//it is not time out or dtim is not valid
2104 //printk("===========>sleep is 0,do nothing\n");
2105 goto out;
2107 if(sleep == 1){
2108 //printk("===========>sleep is 1,to sleep\n");
2109 if(ieee->sta_sleep == 1){
2110 //printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
2111 ieee->enter_sleep_state(ieee->dev,th,tl);
2114 else if(ieee->sta_sleep == 0){
2115 // printk("send null 1\n");
2116 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2118 if(ieee->ps_is_queue_empty(ieee->dev)){
2119 ieee->sta_sleep = 2;
2120 ieee->ack_tx_to_ieee = 1;
2121 //printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
2122 ieee80211_sta_ps_send_null_frame(ieee,1);
2123 ieee->ps_th = th;
2124 ieee->ps_tl = tl;
2126 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2130 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
2132 }else if(sleep == 2){
2133 //printk("==========>sleep is 2,to wakeup\n");
2134 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2136 //printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
2137 ieee80211_sta_wakeup(ieee,1);
2139 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2142 out:
2143 spin_unlock_irqrestore(&ieee->lock, flags);
2147 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2149 if(ieee->sta_sleep == 0){
2150 if(nl){
2151 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2153 //printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2154 //printk("Warning: driver is probably failing to report TX ps error\n");
2155 ieee->ack_tx_to_ieee = 1;
2156 ieee80211_sta_ps_send_null_frame(ieee, 0);
2158 else
2160 ieee->ack_tx_to_ieee = 1;
2161 //printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2162 ieee80211_sta_ps_send_pspoll_frame(ieee);
2165 return;
2169 if(ieee->sta_sleep == 1)
2170 ieee->sta_wake_up(ieee->dev);
2171 if(nl){
2173 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2175 //printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2176 //printk("Warning: driver is probably failing to report TX ps error\n");
2177 ieee->ack_tx_to_ieee = 1;
2178 ieee80211_sta_ps_send_null_frame(ieee, 0);
2180 else
2182 ieee->ack_tx_to_ieee = 1;
2183 ieee->polling = true;
2184 //printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2185 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2186 ieee80211_sta_ps_send_pspoll_frame(ieee);
2189 } else {
2190 ieee->sta_sleep = 0;
2191 ieee->polling = false;
2195 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2197 unsigned long flags,flags2;
2199 spin_lock_irqsave(&ieee->lock, flags);
2201 if(ieee->sta_sleep == 2){
2202 /* Null frame with PS bit set */
2203 if(success){
2204 ieee->sta_sleep = 1;
2205 //printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
2206 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2208 } else {/* 21112005 - tx again null without PS bit if lost */
2210 if((ieee->sta_sleep == 0) && !success){
2211 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2212 //ieee80211_sta_ps_send_null_frame(ieee, 0);
2213 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2215 //printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
2216 ieee80211_sta_ps_send_null_frame(ieee, 0);
2218 else
2220 //printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
2221 ieee80211_sta_ps_send_pspoll_frame(ieee);
2223 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2226 spin_unlock_irqrestore(&ieee->lock, flags);
2229 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2231 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2232 u8* act = ieee80211_get_payload(header);
2233 u8 tmp = 0;
2234 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2235 if (act == NULL)
2237 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2238 return;
2240 tmp = *act;
2241 act ++;
2242 switch (tmp)
2244 case ACT_CAT_BA:
2245 if (*act == ACT_ADDBAREQ)
2246 ieee80211_rx_ADDBAReq(ieee, skb);
2247 else if (*act == ACT_ADDBARSP)
2248 ieee80211_rx_ADDBARsp(ieee, skb);
2249 else if (*act == ACT_DELBA)
2250 ieee80211_rx_DELBA(ieee, skb);
2251 break;
2252 default:
2253 // if (net_ratelimit())
2254 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2255 break;
2257 return;
2260 inline int
2261 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2262 struct ieee80211_rx_stats *rx_stats, u16 type,
2263 u16 stype)
2265 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2266 u16 errcode;
2267 u8* challenge;
2268 int chlen=0;
2269 int aid;
2270 struct ieee80211_assoc_response_frame *assoc_resp;
2271 // struct ieee80211_info_element *info_element;
2272 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2274 if(!ieee->proto_started)
2275 return 0;
2276 #if 0
2277 printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2278 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2279 ieee->iw_mode == IW_MODE_INFRA &&
2280 ieee->state == IEEE80211_LINKED))
2282 tasklet_schedule(&ieee->ps_task);
2284 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2285 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2286 ieee->last_rx_ps_time = jiffies;
2287 #endif
2289 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2291 case IEEE80211_STYPE_ASSOC_RESP:
2292 case IEEE80211_STYPE_REASSOC_RESP:
2294 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2295 WLAN_FC_GET_STYPE(header->frame_ctl));
2296 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2297 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2298 ieee->iw_mode == IW_MODE_INFRA){
2299 struct ieee80211_network network_resp;
2300 struct ieee80211_network *network = &network_resp;
2302 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2303 ieee->state=IEEE80211_LINKED;
2304 ieee->assoc_id = aid;
2305 ieee->softmac_stats.rx_ass_ok++;
2306 /* station support qos */
2307 /* Let the register setting defaultly with Legacy station */
2308 if(ieee->qos_support) {
2309 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2310 memset(network, 0, sizeof(*network));
2311 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2312 rx_stats->len - sizeof(*assoc_resp),\
2313 network,rx_stats)){
2314 return 1;
2316 else
2317 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2318 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2319 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2321 if (ieee->handle_assoc_response != NULL)
2322 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2324 ieee80211_associate_complete(ieee);
2325 } else {
2326 /* aid could not been allocated */
2327 ieee->softmac_stats.rx_ass_err++;
2328 printk(
2329 "Association response status code 0x%x\n",
2330 errcode);
2331 IEEE80211_DEBUG_MGMT(
2332 "Association response status code 0x%x\n",
2333 errcode);
2334 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2335 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2336 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2337 #else
2338 schedule_task(&ieee->associate_procedure_wq);
2339 #endif
2340 } else {
2341 ieee80211_associate_abort(ieee);
2345 break;
2347 case IEEE80211_STYPE_ASSOC_REQ:
2348 case IEEE80211_STYPE_REASSOC_REQ:
2350 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2351 ieee->iw_mode == IW_MODE_MASTER)
2353 ieee80211_rx_assoc_rq(ieee, skb);
2354 break;
2356 case IEEE80211_STYPE_AUTH:
2358 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2359 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2360 ieee->iw_mode == IW_MODE_INFRA){
2362 IEEE80211_DEBUG_MGMT("Received authentication response");
2364 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2365 if(ieee->open_wep || !challenge){
2366 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2367 ieee->softmac_stats.rx_auth_rs_ok++;
2368 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2370 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2372 // WEP or TKIP encryption
2373 if(IsHTHalfNmodeAPs(ieee))
2375 bSupportNmode = true;
2376 bHalfSupportNmode = true;
2378 else
2380 bSupportNmode = false;
2381 bHalfSupportNmode = false;
2383 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2386 /* Dummy wirless mode setting to avoid encryption issue */
2387 if(bSupportNmode) {
2388 //N mode setting
2389 ieee->SetWirelessMode(ieee->dev, \
2390 ieee->current_network.mode);
2391 }else{
2392 //b/g mode setting
2393 /*TODO*/
2394 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2397 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2399 printk("===============>entern half N mode\n");
2400 ieee->bHalfWirelessN24GMode = true;
2402 else
2403 ieee->bHalfWirelessN24GMode = false;
2405 ieee80211_associate_step2(ieee);
2406 }else{
2407 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2409 }else{
2410 ieee->softmac_stats.rx_auth_rs_err++;
2411 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2413 printk("Authentication respose status code 0x%x",errcode);
2414 ieee80211_associate_abort(ieee);
2417 }else if (ieee->iw_mode == IW_MODE_MASTER){
2418 ieee80211_rx_auth_rq(ieee, skb);
2421 break;
2423 case IEEE80211_STYPE_PROBE_REQ:
2425 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2426 ((ieee->iw_mode == IW_MODE_ADHOC ||
2427 ieee->iw_mode == IW_MODE_MASTER) &&
2428 ieee->state == IEEE80211_LINKED)){
2429 ieee80211_rx_probe_rq(ieee, skb);
2431 break;
2433 case IEEE80211_STYPE_DISASSOC:
2434 case IEEE80211_STYPE_DEAUTH:
2435 /* FIXME for now repeat all the association procedure
2436 * both for disassociation and deauthentication
2438 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2439 ieee->state == IEEE80211_LINKED &&
2440 ieee->iw_mode == IW_MODE_INFRA){
2442 ieee->state = IEEE80211_ASSOCIATING;
2443 ieee->softmac_stats.reassoc++;
2444 ieee->is_roaming = true;
2445 ieee80211_disassociate(ieee);
2446 // notify_wx_assoc_event(ieee);
2447 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2448 RemovePeerTS(ieee, header->addr2);
2449 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2450 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2451 #else
2452 schedule_task(&ieee->associate_procedure_wq);
2453 #endif
2455 break;
2456 case IEEE80211_STYPE_MANAGE_ACT:
2457 ieee80211_process_action(ieee,skb);
2458 break;
2459 default:
2460 return -1;
2461 break;
2464 //dev_kfree_skb_any(skb);
2465 return 0;
2468 /* following are for a simplier TX queue management.
2469 * Instead of using netif_[stop/wake]_queue the driver
2470 * will uses these two function (plus a reset one), that
2471 * will internally uses the kernel netif_* and takes
2472 * care of the ieee802.11 fragmentation.
2473 * So the driver receives a fragment per time and might
2474 * call the stop function when it want without take care
2475 * to have enough room to TX an entire packet.
2476 * This might be useful if each fragment need it's own
2477 * descriptor, thus just keep a total free memory > than
2478 * the max fragmentation threshold is not enough.. If the
2479 * ieee802.11 stack passed a TXB struct then you needed
2480 * to keep N free descriptors where
2481 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2482 * In this way you need just one and the 802.11 stack
2483 * will take care of buffering fragments and pass them to
2484 * to the driver later, when it wakes the queue.
2486 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2489 unsigned int queue_index = txb->queue_index;
2490 unsigned long flags;
2491 int i;
2492 cb_desc *tcb_desc = NULL;
2494 spin_lock_irqsave(&ieee->lock,flags);
2496 /* called with 2nd parm 0, no tx mgmt lock required */
2497 ieee80211_sta_wakeup(ieee,0);
2499 /* update the tx status */
2500 // ieee->stats.tx_bytes += txb->payload_size;
2501 // ieee->stats.tx_packets++;
2502 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2503 if(tcb_desc->bMulticast) {
2504 ieee->stats.multicast++;
2506 #if 1
2507 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2508 for(i = 0; i < txb->nr_frags; i++) {
2509 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2510 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2511 #else
2512 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2513 #endif
2514 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2515 (ieee->queue_stop)) {
2516 /* insert the skb packet to the wait queue */
2517 /* as for the completion function, it does not need
2518 * to check it any more.
2519 * */
2520 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2521 //ieee80211_rtl_stop_queue(ieee);
2522 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2523 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2524 #else
2525 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2526 #endif
2527 }else{
2528 ieee->softmac_data_hard_start_xmit(
2529 txb->fragments[i],
2530 ieee->dev,ieee->rate);
2531 //ieee->stats.tx_packets++;
2532 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2533 //ieee->dev->trans_start = jiffies;
2536 #endif
2537 ieee80211_txb_free(txb);
2539 //exit:
2540 spin_unlock_irqrestore(&ieee->lock,flags);
2544 /* called with ieee->lock acquired */
2545 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2547 int i;
2548 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2550 if (ieee->queue_stop){
2551 ieee->tx_pending.frag = i;
2552 return;
2553 }else{
2555 ieee->softmac_data_hard_start_xmit(
2556 ieee->tx_pending.txb->fragments[i],
2557 ieee->dev,ieee->rate);
2558 //(i+1)<ieee->tx_pending.txb->nr_frags);
2559 ieee->stats.tx_packets++;
2560 // ieee->dev->trans_start = jiffies;
2565 ieee80211_txb_free(ieee->tx_pending.txb);
2566 ieee->tx_pending.txb = NULL;
2570 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2572 unsigned long flags;
2574 spin_lock_irqsave(&ieee->lock,flags);
2575 init_mgmt_queue(ieee);
2576 if (ieee->tx_pending.txb){
2577 ieee80211_txb_free(ieee->tx_pending.txb);
2578 ieee->tx_pending.txb = NULL;
2580 ieee->queue_stop = 0;
2581 spin_unlock_irqrestore(&ieee->lock,flags);
2585 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2588 unsigned long flags;
2589 struct sk_buff *skb;
2590 struct ieee80211_hdr_3addr *header;
2592 spin_lock_irqsave(&ieee->lock,flags);
2593 if (! ieee->queue_stop) goto exit;
2595 ieee->queue_stop = 0;
2597 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2598 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2600 header = (struct ieee80211_hdr_3addr *) skb->data;
2602 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2604 if (ieee->seq_ctrl[0] == 0xFFF)
2605 ieee->seq_ctrl[0] = 0;
2606 else
2607 ieee->seq_ctrl[0]++;
2609 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2610 //dev_kfree_skb_any(skb);//edit by thomas
2613 if (!ieee->queue_stop && ieee->tx_pending.txb)
2614 ieee80211_resume_tx(ieee);
2616 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2617 ieee->softmac_stats.swtxawake++;
2618 netif_wake_queue(ieee->dev);
2621 exit :
2622 spin_unlock_irqrestore(&ieee->lock,flags);
2626 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2628 //unsigned long flags;
2629 //spin_lock_irqsave(&ieee->lock,flags);
2631 if (! netif_queue_stopped(ieee->dev)){
2632 netif_stop_queue(ieee->dev);
2633 ieee->softmac_stats.swtxstop++;
2635 ieee->queue_stop = 1;
2636 //spin_unlock_irqrestore(&ieee->lock,flags);
2641 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2644 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2646 /* an IBSS cell address must have the two less significant
2647 * bits of the first byte = 2
2649 ieee->current_network.bssid[0] &= ~0x01;
2650 ieee->current_network.bssid[0] |= 0x02;
2653 /* called in user context only */
2654 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2656 ieee->assoc_id = 1;
2658 if (ieee->current_network.ssid_len == 0){
2659 strncpy(ieee->current_network.ssid,
2660 IEEE80211_DEFAULT_TX_ESSID,
2661 IW_ESSID_MAX_SIZE);
2663 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2664 ieee->ssid_set = 1;
2667 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2669 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2670 ieee->state = IEEE80211_LINKED;
2671 ieee->link_change(ieee->dev);
2672 notify_wx_assoc_event(ieee);
2674 if (ieee->data_hard_resume)
2675 ieee->data_hard_resume(ieee->dev);
2677 netif_carrier_on(ieee->dev);
2680 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2682 if(ieee->raw_tx){
2684 if (ieee->data_hard_resume)
2685 ieee->data_hard_resume(ieee->dev);
2687 netif_carrier_on(ieee->dev);
2690 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2691 void ieee80211_start_ibss_wq(struct work_struct *work)
2694 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2695 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2696 #else
2697 void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2699 #endif
2700 /* iwconfig mode ad-hoc will schedule this and return
2701 * on the other hand this will block further iwconfig SET
2702 * operations because of the wx_sem hold.
2703 * Anyway some most set operations set a flag to speed-up
2704 * (abort) this wq (when syncro scanning) before sleeping
2705 * on the semaphore
2707 if(!ieee->proto_started){
2708 printk("==========oh driver down return\n");
2709 return;
2711 down(&ieee->wx_sem);
2713 if (ieee->current_network.ssid_len == 0){
2714 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2715 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2716 ieee->ssid_set = 1;
2719 ieee->state = IEEE80211_NOLINK;
2720 /* check if we have this cell in our network list */
2721 ieee80211_softmac_check_all_nets(ieee);
2724 #ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
2725 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2726 if (ieee->state == IEEE80211_NOLINK)
2727 ieee->current_network.channel = 6;
2728 #endif
2729 /* if not then the state is not linked. Maybe the user swithced to
2730 * ad-hoc mode just after being in monitor mode, or just after
2731 * being very few time in managed mode (so the card have had no
2732 * time to scan all the chans..) or we have just run up the iface
2733 * after setting ad-hoc mode. So we have to give another try..
2734 * Here, in ibss mode, should be safe to do this without extra care
2735 * (in bss mode we had to make sure no-one tryed to associate when
2736 * we had just checked the ieee->state and we was going to start the
2737 * scan) beacause in ibss mode the ieee80211_new_net function, when
2738 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2739 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2740 * scan, that will stop at the first round because it sees the state
2741 * associated.
2743 if (ieee->state == IEEE80211_NOLINK)
2744 ieee80211_start_scan_syncro(ieee);
2746 /* the network definitively is not here.. create a new cell */
2747 if (ieee->state == IEEE80211_NOLINK){
2748 printk("creating new IBSS cell\n");
2749 if(!ieee->wap_set)
2750 ieee80211_randomize_cell(ieee);
2752 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2754 ieee->current_network.rates_len = 4;
2756 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2757 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2758 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2759 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2761 }else
2762 ieee->current_network.rates_len = 0;
2764 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2765 ieee->current_network.rates_ex_len = 8;
2767 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2768 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2769 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2770 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2771 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2772 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2773 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2774 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2776 ieee->rate = 108;
2777 }else{
2778 ieee->current_network.rates_ex_len = 0;
2779 ieee->rate = 22;
2782 // By default, WMM function will be disabled in IBSS mode
2783 ieee->current_network.QoS_Enable = 0;
2784 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2785 ieee->current_network.atim_window = 0;
2786 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2787 if(ieee->short_slot)
2788 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2792 ieee->state = IEEE80211_LINKED;
2794 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2795 ieee->link_change(ieee->dev);
2797 notify_wx_assoc_event(ieee);
2799 ieee80211_start_send_beacons(ieee);
2801 if (ieee->data_hard_resume)
2802 ieee->data_hard_resume(ieee->dev);
2803 netif_carrier_on(ieee->dev);
2805 up(&ieee->wx_sem);
2808 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2810 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2811 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2812 #else
2813 schedule_task(&ieee->start_ibss_wq);
2814 #endif
2817 /* this is called only in user context, with wx_sem held */
2818 void ieee80211_start_bss(struct ieee80211_device *ieee)
2820 unsigned long flags;
2821 #ifdef ENABLE_DOT11D
2823 // Ref: 802.11d 11.1.3.3
2824 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2826 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2828 if(! ieee->bGlobalDomain)
2830 return;
2833 #endif
2834 /* check if we have already found the net we
2835 * are interested in (if any).
2836 * if not (we are disassociated and we are not
2837 * in associating / authenticating phase) start the background scanning.
2839 ieee80211_softmac_check_all_nets(ieee);
2841 /* ensure no-one start an associating process (thus setting
2842 * the ieee->state to ieee80211_ASSOCIATING) while we
2843 * have just cheked it and we are going to enable scan.
2844 * The ieee80211_new_net function is always called with
2845 * lock held (from both ieee80211_softmac_check_all_nets and
2846 * the rx path), so we cannot be in the middle of such function
2848 spin_lock_irqsave(&ieee->lock, flags);
2850 if (ieee->state == IEEE80211_NOLINK){
2851 #ifdef ENABLE_IPS
2852 if(ieee->ieee80211_ips_leave_wq != NULL)
2853 ieee->ieee80211_ips_leave_wq(ieee->dev);
2854 #endif
2855 ieee->actscanning = true;
2856 ieee80211_rtl_start_scan(ieee);
2858 spin_unlock_irqrestore(&ieee->lock, flags);
2861 /* called only in userspace context */
2862 void ieee80211_disassociate(struct ieee80211_device *ieee)
2866 netif_carrier_off(ieee->dev);
2867 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2868 ieee80211_reset_queue(ieee);
2870 if (ieee->data_hard_stop)
2871 ieee->data_hard_stop(ieee->dev);
2872 #ifdef ENABLE_DOT11D
2873 if(IS_DOT11D_ENABLE(ieee))
2874 Dot11d_Reset(ieee);
2875 #endif
2876 ieee->is_set_key = false;
2877 ieee->link_change(ieee->dev);
2878 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2879 if (ieee->state == IEEE80211_LINKED ||
2880 ieee->state == IEEE80211_ASSOCIATING) {
2881 ieee->state = IEEE80211_NOLINK;
2882 notify_wx_assoc_event(ieee);
2885 ieee->state = IEEE80211_NOLINK;
2888 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2889 void ieee80211_associate_retry_wq(struct work_struct *work)
2891 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2892 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2893 #else
2894 void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2896 #endif
2897 unsigned long flags;
2899 down(&ieee->wx_sem);
2900 if(!ieee->proto_started)
2901 goto exit;
2903 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2904 goto exit;
2906 /* until we do not set the state to IEEE80211_NOLINK
2907 * there are no possibility to have someone else trying
2908 * to start an association procdure (we get here with
2909 * ieee->state = IEEE80211_ASSOCIATING).
2910 * When we set the state to IEEE80211_NOLINK it is possible
2911 * that the RX path run an attempt to associate, but
2912 * both ieee80211_softmac_check_all_nets and the
2913 * RX path works with ieee->lock held so there are no
2914 * problems. If we are still disassociated then start a scan.
2915 * the lock here is necessary to ensure no one try to start
2916 * an association procedure when we have just checked the
2917 * state and we are going to start the scan.
2919 ieee->beinretry = true;
2920 ieee->state = IEEE80211_NOLINK;
2922 ieee80211_softmac_check_all_nets(ieee);
2924 spin_lock_irqsave(&ieee->lock, flags);
2926 if(ieee->state == IEEE80211_NOLINK)
2928 ieee->is_roaming= false;
2929 ieee->actscanning = true;
2930 ieee80211_rtl_start_scan(ieee);
2932 spin_unlock_irqrestore(&ieee->lock, flags);
2934 ieee->beinretry = false;
2935 exit:
2936 up(&ieee->wx_sem);
2939 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2941 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2943 struct sk_buff *skb;
2944 struct ieee80211_probe_response *b;
2946 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2948 if (!skb)
2949 return NULL;
2951 b = (struct ieee80211_probe_response *) skb->data;
2952 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2954 return skb;
2958 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2960 struct sk_buff *skb;
2961 struct ieee80211_probe_response *b;
2963 skb = ieee80211_get_beacon_(ieee);
2964 if(!skb)
2965 return NULL;
2967 b = (struct ieee80211_probe_response *) skb->data;
2968 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2970 if (ieee->seq_ctrl[0] == 0xFFF)
2971 ieee->seq_ctrl[0] = 0;
2972 else
2973 ieee->seq_ctrl[0]++;
2975 return skb;
2978 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2980 ieee->sync_scan_hurryup = 1;
2981 down(&ieee->wx_sem);
2982 ieee80211_stop_protocol(ieee, shutdown);
2983 up(&ieee->wx_sem);
2987 void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2989 if (!ieee->proto_started)
2990 return;
2992 if(shutdown)
2993 ieee->proto_started = 0;
2994 ieee->proto_stoppping = 1;
2996 ieee80211_stop_send_beacons(ieee);
2997 del_timer_sync(&ieee->associate_timer);
2998 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2999 cancel_delayed_work(&ieee->associate_retry_wq);
3000 cancel_delayed_work(&ieee->start_ibss_wq);
3001 #endif
3002 ieee80211_stop_scan(ieee);
3004 ieee80211_disassociate(ieee);
3005 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
3007 ieee->proto_stoppping = 0;
3010 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
3012 ieee->sync_scan_hurryup = 0;
3013 down(&ieee->wx_sem);
3014 ieee80211_start_protocol(ieee);
3015 up(&ieee->wx_sem);
3018 void ieee80211_start_protocol(struct ieee80211_device *ieee)
3020 short ch = 0;
3021 int i = 0;
3022 if (ieee->proto_started)
3023 return;
3025 ieee->proto_started = 1;
3027 if (ieee->current_network.channel == 0){
3029 ch++;
3030 if (ch > MAX_CHANNEL_NUMBER)
3031 return; /* no channel found */
3032 #ifdef ENABLE_DOT11D
3033 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
3034 #else
3035 }while(!ieee->channel_map[ch]);
3036 #endif
3037 ieee->current_network.channel = ch;
3040 if (ieee->current_network.beacon_interval == 0)
3041 ieee->current_network.beacon_interval = 100;
3042 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
3043 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
3045 for(i = 0; i < 17; i++) {
3046 ieee->last_rxseq_num[i] = -1;
3047 ieee->last_rxfrag_num[i] = -1;
3048 ieee->last_packet_time[i] = 0;
3051 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
3053 ieee->state = IEEE80211_NOLINK;
3056 /* if the user set the MAC of the ad-hoc cell and then
3057 * switch to managed mode, shall we make sure that association
3058 * attempts does not fail just because the user provide the essid
3059 * and the nic is still checking for the AP MAC ??
3061 if (ieee->iw_mode == IW_MODE_INFRA)
3062 ieee80211_start_bss(ieee);
3064 else if (ieee->iw_mode == IW_MODE_ADHOC)
3065 ieee80211_start_ibss(ieee);
3067 else if (ieee->iw_mode == IW_MODE_MASTER)
3068 ieee80211_start_master_bss(ieee);
3070 else if(ieee->iw_mode == IW_MODE_MONITOR)
3071 ieee80211_start_monitor_mode(ieee);
3075 #define DRV_NAME "Ieee80211"
3076 void ieee80211_softmac_init(struct ieee80211_device *ieee)
3078 int i;
3079 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
3081 ieee->state = IEEE80211_NOLINK;
3082 ieee->sync_scan_hurryup = 0;
3083 for(i = 0; i < 5; i++) {
3084 ieee->seq_ctrl[i] = 0;
3086 #ifdef ENABLE_DOT11D
3087 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
3088 if (!ieee->pDot11dInfo)
3089 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
3090 #endif
3091 //added for AP roaming
3092 ieee->LinkDetectInfo.SlotNum = 2;
3093 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3094 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3096 ieee->assoc_id = 0;
3097 ieee->queue_stop = 0;
3098 ieee->scanning = 0;
3099 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
3100 ieee->wap_set = 0;
3101 ieee->ssid_set = 0;
3102 ieee->proto_started = 0;
3103 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
3104 ieee->rate = 22;
3105 ieee->ps = IEEE80211_PS_DISABLED;
3106 ieee->sta_sleep = 0;
3107 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
3108 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
3109 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
3110 //added by amy
3111 ieee->actscanning = false;
3112 ieee->beinretry = false;
3113 ieee->is_set_key = false;
3114 init_mgmt_queue(ieee);
3116 ieee->sta_edca_param[0] = 0x0000A403;
3117 ieee->sta_edca_param[1] = 0x0000A427;
3118 ieee->sta_edca_param[2] = 0x005E4342;
3119 ieee->sta_edca_param[3] = 0x002F3262;
3120 ieee->aggregation = true;
3121 ieee->enable_rx_imm_BA = 1;
3122 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3123 init_timer(&ieee->scan_timer);
3124 ieee->scan_timer.data = (unsigned long)ieee;
3125 ieee->scan_timer.function = ieee80211_softmac_scan_cb;
3126 #endif
3127 ieee->tx_pending.txb = NULL;
3129 init_timer(&ieee->associate_timer);
3130 ieee->associate_timer.data = (unsigned long)ieee;
3131 ieee->associate_timer.function = ieee80211_associate_abort_cb;
3133 init_timer(&ieee->beacon_timer);
3134 ieee->beacon_timer.data = (unsigned long) ieee;
3135 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
3137 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3138 #ifdef PF_SYNCTHREAD
3139 ieee->wq = create_workqueue(DRV_NAME,0);
3140 #else
3141 ieee->wq = create_workqueue(DRV_NAME);
3142 #endif
3143 #endif
3145 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3146 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3147 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
3148 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
3149 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
3150 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
3151 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
3152 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
3154 #else
3155 INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3156 INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3157 INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3158 INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3159 INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3160 INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3161 #endif
3163 #else
3164 tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3165 tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3166 tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3167 tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3168 tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3169 tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3170 #endif
3171 sema_init(&ieee->wx_sem, 1);
3172 sema_init(&ieee->scan_sem, 1);
3173 #ifdef ENABLE_IPS
3174 sema_init(&ieee->ips_sem,1);
3175 #endif
3176 spin_lock_init(&ieee->mgmt_tx_lock);
3177 spin_lock_init(&ieee->beacon_lock);
3179 tasklet_init(&ieee->ps_task,
3180 (void(*)(unsigned long)) ieee80211_sta_ps,
3181 (unsigned long)ieee);
3185 void ieee80211_softmac_free(struct ieee80211_device *ieee)
3187 down(&ieee->wx_sem);
3188 #ifdef ENABLE_DOT11D
3189 if(NULL != ieee->pDot11dInfo)
3191 kfree(ieee->pDot11dInfo);
3192 ieee->pDot11dInfo = NULL;
3194 #endif
3195 del_timer_sync(&ieee->associate_timer);
3197 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3198 cancel_delayed_work(&ieee->associate_retry_wq);
3199 destroy_workqueue(ieee->wq);
3200 #endif
3202 up(&ieee->wx_sem);
3205 /********************************************************
3206 * Start of WPA code. *
3207 * this is stolen from the ipw2200 driver *
3208 ********************************************************/
3211 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3213 /* This is called when wpa_supplicant loads and closes the driver
3214 * interface. */
3215 printk("%s WPA\n",value ? "enabling" : "disabling");
3216 ieee->wpa_enabled = value;
3217 return 0;
3221 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3223 /* make sure WPA is enabled */
3224 ieee80211_wpa_enable(ieee, 1);
3226 ieee80211_disassociate(ieee);
3230 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3233 int ret = 0;
3235 switch (command) {
3236 case IEEE_MLME_STA_DEAUTH:
3237 // silently ignore
3238 break;
3240 case IEEE_MLME_STA_DISASSOC:
3241 ieee80211_disassociate(ieee);
3242 break;
3244 default:
3245 printk("Unknown MLME request: %d\n", command);
3246 ret = -EOPNOTSUPP;
3249 return ret;
3253 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3254 struct ieee_param *param, int plen)
3256 u8 *buf;
3258 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3259 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3260 return -EINVAL;
3262 if (param->u.wpa_ie.len) {
3263 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
3264 GFP_KERNEL);
3265 if (buf == NULL)
3266 return -ENOMEM;
3268 kfree(ieee->wpa_ie);
3269 ieee->wpa_ie = buf;
3270 ieee->wpa_ie_len = param->u.wpa_ie.len;
3271 } else {
3272 kfree(ieee->wpa_ie);
3273 ieee->wpa_ie = NULL;
3274 ieee->wpa_ie_len = 0;
3277 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3278 return 0;
3281 #define AUTH_ALG_OPEN_SYSTEM 0x1
3282 #define AUTH_ALG_SHARED_KEY 0x2
3284 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3287 struct ieee80211_security sec = {
3288 .flags = SEC_AUTH_MODE,
3290 int ret = 0;
3292 if (value & AUTH_ALG_SHARED_KEY) {
3293 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3294 ieee->open_wep = 0;
3295 ieee->auth_mode = 1;
3296 } else if (value & AUTH_ALG_OPEN_SYSTEM){
3297 sec.auth_mode = WLAN_AUTH_OPEN;
3298 ieee->open_wep = 1;
3299 ieee->auth_mode = 0;
3301 else if (value & IW_AUTH_ALG_LEAP){
3302 sec.auth_mode = WLAN_AUTH_LEAP;
3303 ieee->open_wep = 1;
3304 ieee->auth_mode = 2;
3308 if (ieee->set_security)
3309 ieee->set_security(ieee->dev, &sec);
3310 //else
3311 // ret = -EOPNOTSUPP;
3313 return ret;
3316 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3318 int ret=0;
3319 unsigned long flags;
3321 switch (name) {
3322 case IEEE_PARAM_WPA_ENABLED:
3323 ret = ieee80211_wpa_enable(ieee, value);
3324 break;
3326 case IEEE_PARAM_TKIP_COUNTERMEASURES:
3327 ieee->tkip_countermeasures=value;
3328 break;
3330 case IEEE_PARAM_DROP_UNENCRYPTED: {
3331 /* HACK:
3333 * wpa_supplicant calls set_wpa_enabled when the driver
3334 * is loaded and unloaded, regardless of if WPA is being
3335 * used. No other calls are made which can be used to
3336 * determine if encryption will be used or not prior to
3337 * association being expected. If encryption is not being
3338 * used, drop_unencrypted is set to false, else true -- we
3339 * can use this to determine if the CAP_PRIVACY_ON bit should
3340 * be set.
3342 struct ieee80211_security sec = {
3343 .flags = SEC_ENABLED,
3344 .enabled = value,
3346 ieee->drop_unencrypted = value;
3347 /* We only change SEC_LEVEL for open mode. Others
3348 * are set by ipw_wpa_set_encryption.
3350 if (!value) {
3351 sec.flags |= SEC_LEVEL;
3352 sec.level = SEC_LEVEL_0;
3354 else {
3355 sec.flags |= SEC_LEVEL;
3356 sec.level = SEC_LEVEL_1;
3358 if (ieee->set_security)
3359 ieee->set_security(ieee->dev, &sec);
3360 break;
3363 case IEEE_PARAM_PRIVACY_INVOKED:
3364 ieee->privacy_invoked=value;
3365 break;
3367 case IEEE_PARAM_AUTH_ALGS:
3368 ret = ieee80211_wpa_set_auth_algs(ieee, value);
3369 break;
3371 case IEEE_PARAM_IEEE_802_1X:
3372 ieee->ieee802_1x=value;
3373 break;
3374 case IEEE_PARAM_WPAX_SELECT:
3375 // added for WPA2 mixed mode
3376 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3377 ieee->wpax_type_set = 1;
3378 ieee->wpax_type_notify = value;
3379 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3380 break;
3382 default:
3383 printk("Unknown WPA param: %d\n",name);
3384 ret = -EOPNOTSUPP;
3387 return ret;
3390 /* implementation borrowed from hostap driver */
3392 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3393 struct ieee_param *param, int param_len)
3395 int ret = 0;
3397 struct ieee80211_crypto_ops *ops;
3398 struct ieee80211_crypt_data **crypt;
3400 struct ieee80211_security sec = {
3401 .flags = 0,
3404 param->u.crypt.err = 0;
3405 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3407 if (param_len !=
3408 (int) ((char *) param->u.crypt.key - (char *) param) +
3409 param->u.crypt.key_len) {
3410 printk("Len mismatch %d, %d\n", param_len,
3411 param->u.crypt.key_len);
3412 return -EINVAL;
3414 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3415 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3416 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3417 if (param->u.crypt.idx >= WEP_KEYS)
3418 return -EINVAL;
3419 crypt = &ieee->crypt[param->u.crypt.idx];
3420 } else {
3421 return -EINVAL;
3424 if (strcmp(param->u.crypt.alg, "none") == 0) {
3425 if (crypt) {
3426 sec.enabled = 0;
3427 // FIXME FIXME
3428 //sec.encrypt = 0;
3429 sec.level = SEC_LEVEL_0;
3430 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3431 ieee80211_crypt_delayed_deinit(ieee, crypt);
3433 goto done;
3435 sec.enabled = 1;
3436 // FIXME FIXME
3437 // sec.encrypt = 1;
3438 sec.flags |= SEC_ENABLED;
3440 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3441 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3442 strcmp(param->u.crypt.alg, "TKIP"))
3443 goto skip_host_crypt;
3445 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3446 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3447 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3448 /* set WEP40 first, it will be modified according to WEP104 or
3449 * WEP40 at other place */
3450 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3451 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3452 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3453 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3454 if (ops == NULL) {
3455 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3456 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3457 ret = -EINVAL;
3458 goto done;
3461 if (*crypt == NULL || (*crypt)->ops != ops) {
3462 struct ieee80211_crypt_data *new_crypt;
3464 ieee80211_crypt_delayed_deinit(ieee, crypt);
3466 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3467 if (new_crypt == NULL) {
3468 ret = -ENOMEM;
3469 goto done;
3471 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3472 new_crypt->ops = ops;
3473 if (new_crypt->ops)
3474 new_crypt->priv =
3475 new_crypt->ops->init(param->u.crypt.idx);
3477 if (new_crypt->priv == NULL) {
3478 kfree(new_crypt);
3479 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3480 ret = -EINVAL;
3481 goto done;
3484 *crypt = new_crypt;
3487 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3488 (*crypt)->ops->set_key(param->u.crypt.key,
3489 param->u.crypt.key_len, param->u.crypt.seq,
3490 (*crypt)->priv) < 0) {
3491 printk("key setting failed\n");
3492 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3493 ret = -EINVAL;
3494 goto done;
3497 skip_host_crypt:
3498 if (param->u.crypt.set_tx) {
3499 ieee->tx_keyidx = param->u.crypt.idx;
3500 sec.active_key = param->u.crypt.idx;
3501 sec.flags |= SEC_ACTIVE_KEY;
3502 } else
3503 sec.flags &= ~SEC_ACTIVE_KEY;
3505 if (param->u.crypt.alg != NULL) {
3506 memcpy(sec.keys[param->u.crypt.idx],
3507 param->u.crypt.key,
3508 param->u.crypt.key_len);
3509 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3510 sec.flags |= (1 << param->u.crypt.idx);
3512 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3513 sec.flags |= SEC_LEVEL;
3514 sec.level = SEC_LEVEL_1;
3515 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3516 sec.flags |= SEC_LEVEL;
3517 sec.level = SEC_LEVEL_2;
3518 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3519 sec.flags |= SEC_LEVEL;
3520 sec.level = SEC_LEVEL_3;
3523 done:
3524 if (ieee->set_security)
3525 ieee->set_security(ieee->dev, &sec);
3527 /* Do not reset port if card is in Managed mode since resetting will
3528 * generate new IEEE 802.11 authentication which may end up in looping
3529 * with IEEE 802.1X. If your hardware requires a reset after WEP
3530 * configuration (for example... Prism2), implement the reset_port in
3531 * the callbacks structures used to initialize the 802.11 stack. */
3532 if (ieee->reset_on_keychange &&
3533 ieee->iw_mode != IW_MODE_INFRA &&
3534 ieee->reset_port &&
3535 ieee->reset_port(ieee->dev)) {
3536 printk("reset_port failed\n");
3537 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3538 return -EINVAL;
3541 return ret;
3544 inline struct sk_buff *ieee80211_disassociate_skb(
3545 struct ieee80211_network *beacon,
3546 struct ieee80211_device *ieee,
3547 u8 asRsn)
3549 struct sk_buff *skb;
3550 struct ieee80211_disassoc *disass;
3552 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3553 if (!skb)
3554 return NULL;
3556 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3557 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3558 disass->header.duration_id = 0;
3560 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3561 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3562 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3564 disass->reason = asRsn;
3565 return skb;
3569 void
3570 SendDisassociation(
3571 struct ieee80211_device *ieee,
3572 u8* asSta,
3573 u8 asRsn
3576 struct ieee80211_network *beacon = &ieee->current_network;
3577 struct sk_buff *skb;
3578 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3579 if (skb){
3580 softmac_mgmt_xmit(skb, ieee);
3581 //dev_kfree_skb_any(skb);//edit by thomas
3585 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3587 struct ieee_param *param;
3588 int ret=0;
3590 down(&ieee->wx_sem);
3591 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3593 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3594 ret = -EINVAL;
3595 goto out;
3598 param = kmalloc(p->length, GFP_KERNEL);
3599 if (param == NULL){
3600 ret = -ENOMEM;
3601 goto out;
3603 if (copy_from_user(param, p->pointer, p->length)) {
3604 kfree(param);
3605 ret = -EFAULT;
3606 goto out;
3609 switch (param->cmd) {
3611 case IEEE_CMD_SET_WPA_PARAM:
3612 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3613 param->u.wpa_param.value);
3614 break;
3616 case IEEE_CMD_SET_WPA_IE:
3617 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3618 break;
3620 case IEEE_CMD_SET_ENCRYPTION:
3621 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3622 break;
3624 case IEEE_CMD_MLME:
3625 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3626 param->u.mlme.reason_code);
3627 break;
3629 default:
3630 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3631 ret = -EOPNOTSUPP;
3632 break;
3635 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3636 ret = -EFAULT;
3638 kfree(param);
3639 out:
3640 up(&ieee->wx_sem);
3642 return ret;
3645 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3647 union iwreq_data wrqu;
3648 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3649 if (ieee->state == IEEE80211_LINKED)
3650 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3651 else
3652 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3653 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3656 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3657 //EXPORT_SYMBOL(ieee80211_get_beacon);
3658 //EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3659 //EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3660 //EXPORT_SYMBOL(ieee80211_reset_queue);
3661 //EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3662 //EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3663 //EXPORT_SYMBOL(ieee80211_is_shortslot);
3664 //EXPORT_SYMBOL(ieee80211_is_54g);
3665 //EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3666 //EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3667 //EXPORT_SYMBOL(ieee80211_softmac_xmit);
3668 //EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3669 //EXPORT_SYMBOL(notify_wx_assoc_event);
3670 //EXPORT_SYMBOL(SendDisassociation);
3671 //EXPORT_SYMBOL(ieee80211_disassociate);
3672 //EXPORT_SYMBOL(ieee80211_start_send_beacons);
3673 //EXPORT_SYMBOL(ieee80211_stop_scan);
3674 //EXPORT_SYMBOL(ieee80211_send_probe_requests);
3675 //EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3676 //EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3677 #else
3678 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3679 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3680 EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3681 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3682 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3683 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3684 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3685 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3686 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3687 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3688 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3689 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3690 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3691 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3692 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3693 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3694 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3695 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3696 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3697 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3698 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
3699 EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);
3700 #endif