ieee80211_softmac.c revision 8fc8598e61f6f384f3eaf1d9b09500c12af47b37
1/* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
9 *
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18
19#include <linux/random.h>
20#include <linux/delay.h>
21#include <linux/version.h>
22#include <asm/uaccess.h>
23#ifdef ENABLE_DOT11D
24#include "dot11d.h"
25#endif
26
27u8 rsn_authen_cipher_suite[16][4] = {
28	{0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
29	{0x00,0x0F,0xAC,0x01}, //WEP-40         //RSNA default
30	{0x00,0x0F,0xAC,0x02}, //TKIP           //NONE		//{used just as default}
31	{0x00,0x0F,0xAC,0x03}, //WRAP-historical
32	{0x00,0x0F,0xAC,0x04}, //CCMP
33	{0x00,0x0F,0xAC,0x05}, //WEP-104
34};
35
36short ieee80211_is_54g(struct ieee80211_network net)
37{
38	return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39}
40
41short ieee80211_is_shortslot(struct ieee80211_network net)
42{
43	return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
44}
45
46/* returns the total length needed for pleacing the RATE MFIE
47 * tag and the EXTENDED RATE MFIE tag if needed.
48 * It encludes two bytes per tag for the tag itself and its len
49 */
50unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
51{
52	unsigned int rate_len = 0;
53
54	if (ieee->modulation & IEEE80211_CCK_MODULATION)
55		rate_len = IEEE80211_CCK_RATE_LEN + 2;
56
57	if (ieee->modulation & IEEE80211_OFDM_MODULATION)
58
59		rate_len += IEEE80211_OFDM_RATE_LEN + 2;
60
61	return rate_len;
62}
63
64/* pleace the MFIE rate, tag to the memory (double) poined.
65 * Then it updates the pointer so that
66 * it points after the new MFIE tag added.
67 */
68void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
69{
70	u8 *tag = *tag_p;
71
72	if (ieee->modulation & IEEE80211_CCK_MODULATION){
73		*tag++ = MFIE_TYPE_RATES;
74		*tag++ = 4;
75		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
76		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
77		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
78		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
79	}
80
81	/* We may add an option for custom rates that specific HW might support */
82	*tag_p = tag;
83}
84
85void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
86{
87	u8 *tag = *tag_p;
88
89		if (ieee->modulation & IEEE80211_OFDM_MODULATION){
90
91		*tag++ = MFIE_TYPE_RATES_EX;
92		*tag++ = 8;
93		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
94		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
95		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
96		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
97		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
98		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
99		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
100		*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
101
102	}
103
104	/* We may add an option for custom rates that specific HW might support */
105	*tag_p = tag;
106}
107
108
109void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
110	u8 *tag = *tag_p;
111
112	*tag++ = MFIE_TYPE_GENERIC; //0
113	*tag++ = 7;
114	*tag++ = 0x00;
115	*tag++ = 0x50;
116	*tag++ = 0xf2;
117	*tag++ = 0x02;//5
118	*tag++ = 0x00;
119	*tag++ = 0x01;
120#ifdef SUPPORT_USPD
121	if(ieee->current_network.wmm_info & 0x80) {
122		*tag++ = 0x0f|MAX_SP_Len;
123	} else {
124		*tag++ = MAX_SP_Len;
125	}
126#else
127	*tag++ = MAX_SP_Len;
128#endif
129	*tag_p = tag;
130}
131
132#ifdef THOMAS_TURBO
133void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
134	u8 *tag = *tag_p;
135
136        *tag++ = MFIE_TYPE_GENERIC; //0
137        *tag++ = 7;
138        *tag++ = 0x00;
139        *tag++ = 0xe0;
140        *tag++ = 0x4c;
141        *tag++ = 0x01;//5
142        *tag++ = 0x02;
143        *tag++ = 0x11;
144	*tag++ = 0x00;
145
146	*tag_p = tag;
147	printk(KERN_ALERT "This is enable turbo mode IE process\n");
148}
149#endif
150
151void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
152{
153	int nh;
154	nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
155
156/*
157 * if the queue is full but we have newer frames then
158 * just overwrites the oldest.
159 *
160 * if (nh == ieee->mgmt_queue_tail)
161 *		return -1;
162 */
163	ieee->mgmt_queue_head = nh;
164	ieee->mgmt_queue_ring[nh] = skb;
165
166	//return 0;
167}
168
169struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
170{
171	struct sk_buff *ret;
172
173	if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
174		return NULL;
175
176	ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
177
178	ieee->mgmt_queue_tail =
179		(ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
180
181	return ret;
182}
183
184void init_mgmt_queue(struct ieee80211_device *ieee)
185{
186	ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
187}
188
189u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
190{
191	PRT_HIGH_THROUGHPUT      pHTInfo = ieee->pHTInfo;
192	u8 rate;
193
194	// 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
195	if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
196		rate = 0x0c;
197	else
198		rate = ieee->basic_rate & 0x7f;
199
200	if(rate == 0){
201		// 2005.01.26, by rcnjko.
202		if(ieee->mode == IEEE_A||
203		   ieee->mode== IEEE_N_5G||
204		   (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
205			rate = 0x0c;
206		else
207			rate = 0x02;
208	}
209
210	/*
211	// Data rate of ProbeReq is already decided. Annie, 2005-03-31
212	if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
213	{
214	if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
215	rate = 0x0c;
216	else
217	rate = 0x02;
218	}
219	 */
220	return rate;
221}
222
223
224void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
225
226inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
227{
228	unsigned long flags;
229	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
230	struct ieee80211_hdr_3addr  *header=
231		(struct ieee80211_hdr_3addr  *) skb->data;
232
233	cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
234	spin_lock_irqsave(&ieee->lock, flags);
235
236	/* called with 2nd param 0, no mgmt lock required */
237	ieee80211_sta_wakeup(ieee,0);
238
239	tcb_desc->queue_index = MGNT_QUEUE;
240	tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
241        tcb_desc->RATRIndex = 7;
242        tcb_desc->bTxDisableRateFallBack = 1;
243        tcb_desc->bTxUseDriverAssingedRate = 1;
244
245	if(single){
246		if(ieee->queue_stop){
247			enqueue_mgmt(ieee,skb);
248		}else{
249			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
250
251			if (ieee->seq_ctrl[0] == 0xFFF)
252				ieee->seq_ctrl[0] = 0;
253			else
254				ieee->seq_ctrl[0]++;
255
256			/* avoid watchdog triggers */
257			ieee->dev->trans_start = jiffies;
258			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
259			//dev_kfree_skb_any(skb);//edit by thomas
260		}
261
262		spin_unlock_irqrestore(&ieee->lock, flags);
263	}else{
264		spin_unlock_irqrestore(&ieee->lock, flags);
265		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
266
267		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
268
269		if (ieee->seq_ctrl[0] == 0xFFF)
270			ieee->seq_ctrl[0] = 0;
271		else
272			ieee->seq_ctrl[0]++;
273
274		/* check wether the managed packet queued greater than 5 */
275		if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
276				(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
277				(ieee->queue_stop) ) {
278			/* insert the skb packet to the management queue */
279			/* as for the completion function, it does not need
280			 * to check it any more.
281			 * */
282			printk("%s():insert to waitqueue!\n",__FUNCTION__);
283			skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
284		} else {
285			//printk("TX packet!\n");
286			ieee->softmac_hard_start_xmit(skb,ieee->dev);
287			//dev_kfree_skb_any(skb);//edit by thomas
288		}
289		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
290	}
291}
292
293inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
294{
295
296	short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
297	struct ieee80211_hdr_3addr  *header =
298		(struct ieee80211_hdr_3addr  *) skb->data;
299
300
301	if(single){
302
303		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
304
305		if (ieee->seq_ctrl[0] == 0xFFF)
306			ieee->seq_ctrl[0] = 0;
307		else
308			ieee->seq_ctrl[0]++;
309
310		/* avoid watchdog triggers */
311		ieee->dev->trans_start = jiffies;
312		ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
313
314	}else{
315
316		header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
317
318		if (ieee->seq_ctrl[0] == 0xFFF)
319			ieee->seq_ctrl[0] = 0;
320		else
321			ieee->seq_ctrl[0]++;
322
323		ieee->softmac_hard_start_xmit(skb,ieee->dev);
324
325	}
326	//dev_kfree_skb_any(skb);//edit by thomas
327}
328
329inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
330{
331	unsigned int len,rate_len;
332	u8 *tag;
333	struct sk_buff *skb;
334	struct ieee80211_probe_request *req;
335
336	len = ieee->current_network.ssid_len;
337
338	rate_len = ieee80211_MFIE_rate_len(ieee);
339
340	skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
341			    2 + len + rate_len + ieee->tx_headroom);
342	if (!skb)
343		return NULL;
344
345	skb_reserve(skb, ieee->tx_headroom);
346
347	req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
348	req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
349	req->header.duration_id = 0; //FIXME: is this OK ?
350
351	memset(req->header.addr1, 0xff, ETH_ALEN);
352	memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
353	memset(req->header.addr3, 0xff, ETH_ALEN);
354
355	tag = (u8 *) skb_put(skb,len+2+rate_len);
356
357	*tag++ = MFIE_TYPE_SSID;
358	*tag++ = len;
359	memcpy(tag, ieee->current_network.ssid, len);
360	tag += len;
361
362	ieee80211_MFIE_Brate(ieee,&tag);
363	ieee80211_MFIE_Grate(ieee,&tag);
364	return skb;
365}
366
367struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
368void ieee80211_send_beacon(struct ieee80211_device *ieee)
369{
370	struct sk_buff *skb;
371	if(!ieee->ieee_up)
372		return;
373	//unsigned long flags;
374	skb = ieee80211_get_beacon_(ieee);
375
376	if (skb){
377		softmac_mgmt_xmit(skb, ieee);
378		ieee->softmac_stats.tx_beacons++;
379		//dev_kfree_skb_any(skb);//edit by thomas
380	}
381//	ieee->beacon_timer.expires = jiffies +
382//		(MSECS( ieee->current_network.beacon_interval -5));
383
384	//spin_lock_irqsave(&ieee->beacon_lock,flags);
385	if(ieee->beacon_txing && ieee->ieee_up){
386//		if(!timer_pending(&ieee->beacon_timer))
387//			add_timer(&ieee->beacon_timer);
388		mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
389	}
390	//spin_unlock_irqrestore(&ieee->beacon_lock,flags);
391}
392
393
394void ieee80211_send_beacon_cb(unsigned long _ieee)
395{
396	struct ieee80211_device *ieee =
397		(struct ieee80211_device *) _ieee;
398	unsigned long flags;
399
400	spin_lock_irqsave(&ieee->beacon_lock, flags);
401	ieee80211_send_beacon(ieee);
402	spin_unlock_irqrestore(&ieee->beacon_lock, flags);
403}
404
405
406void ieee80211_send_probe(struct ieee80211_device *ieee)
407{
408	struct sk_buff *skb;
409
410	skb = ieee80211_probe_req(ieee);
411	if (skb){
412		softmac_mgmt_xmit(skb, ieee);
413		ieee->softmac_stats.tx_probe_rq++;
414		//dev_kfree_skb_any(skb);//edit by thomas
415	}
416}
417
418void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
419{
420	if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
421		ieee80211_send_probe(ieee);
422		ieee80211_send_probe(ieee);
423	}
424}
425
426/* this performs syncro scan blocking the caller until all channels
427 * in the allowed channel map has been checked.
428 */
429void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
430{
431	short ch = 0;
432#ifdef ENABLE_DOT11D
433	u8 channel_map[MAX_CHANNEL_NUMBER+1];
434	memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
435#endif
436	down(&ieee->scan_sem);
437
438	while(1)
439	{
440
441		do{
442			ch++;
443			if (ch > MAX_CHANNEL_NUMBER)
444				goto out; /* scan completed */
445#ifdef ENABLE_DOT11D
446		}while(!channel_map[ch]);
447#else
448		}while(!ieee->channel_map[ch]);
449#endif
450
451		/* this fuction can be called in two situations
452		 * 1- We have switched to ad-hoc mode and we are
453		 *    performing a complete syncro scan before conclude
454		 *    there are no interesting cell and to create a
455		 *    new one. In this case the link state is
456		 *    IEEE80211_NOLINK until we found an interesting cell.
457		 *    If so the ieee8021_new_net, called by the RX path
458		 *    will set the state to IEEE80211_LINKED, so we stop
459		 *    scanning
460		 * 2- We are linked and the root uses run iwlist scan.
461		 *    So we switch to IEEE80211_LINKED_SCANNING to remember
462		 *    that we are still logically linked (not interested in
463		 *    new network events, despite for updating the net list,
464		 *    but we are temporarly 'unlinked' as the driver shall
465		 *    not filter RX frames and the channel is changing.
466		 * So the only situation in witch are interested is to check
467		 * if the state become LINKED because of the #1 situation
468		 */
469
470		if (ieee->state == IEEE80211_LINKED)
471			goto out;
472		ieee->set_chan(ieee->dev, ch);
473#ifdef ENABLE_DOT11D
474		if(channel_map[ch] == 1)
475#endif
476		ieee80211_send_probe_requests(ieee);
477
478		/* this prevent excessive time wait when we
479		 * need to wait for a syncro scan to end..
480		 */
481		if(ieee->state < IEEE80211_LINKED)
482			;
483		else
484		if (ieee->sync_scan_hurryup)
485			goto out;
486
487
488		msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
489
490	}
491out:
492	if(ieee->state < IEEE80211_LINKED){
493		ieee->actscanning = false;
494		up(&ieee->scan_sem);
495	}
496	else{
497	ieee->sync_scan_hurryup = 0;
498#ifdef ENABLE_DOT11D
499	if(IS_DOT11D_ENABLE(ieee))
500		DOT11D_ScanComplete(ieee);
501#endif
502	up(&ieee->scan_sem);
503}
504}
505
506#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
507/* called both by wq with ieee->lock held */
508void ieee80211_softmac_scan(struct ieee80211_device *ieee)
509{
510#if 0
511	short watchdog = 0;
512	do{
513		ieee->current_network.channel =
514			(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
515		if (watchdog++ > MAX_CHANNEL_NUMBER)
516				return; /* no good chans */
517
518	}while(!ieee->channel_map[ieee->current_network.channel]);
519#endif
520
521	schedule_task(&ieee->softmac_scan_wq);
522}
523#endif
524
525#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
526void ieee80211_softmac_scan_wq(struct work_struct *work)
527{
528        struct delayed_work *dwork = container_of(work, struct delayed_work, work);
529        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
530#else
531void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee)
532{
533#endif
534	static short watchdog = 0;
535#ifdef ENABLE_DOT11D
536	u8 channel_map[MAX_CHANNEL_NUMBER+1];
537	memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
538#endif
539	if(!ieee->ieee_up)
540		return;
541	down(&ieee->scan_sem);
542	do{
543		ieee->current_network.channel =
544			(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
545		if (watchdog++ > MAX_CHANNEL_NUMBER)
546		{
547		//if current channel is not in channel map, set to default channel.
548		#ifdef ENABLE_DOT11D
549      			if (!channel_map[ieee->current_network.channel]);
550		#else
551			if (!ieee->channel_map[ieee->current_network.channel]);
552		#endif
553				ieee->current_network.channel = 6;
554				goto out; /* no good chans */
555		}
556#ifdef ENABLE_DOT11D
557        }while(!channel_map[ieee->current_network.channel]);
558#else
559	}while(!ieee->channel_map[ieee->current_network.channel]);
560#endif
561	if (ieee->scanning == 0 )
562		goto out;
563	ieee->set_chan(ieee->dev, ieee->current_network.channel);
564#ifdef ENABLE_DOT11D
565	if(channel_map[ieee->current_network.channel] == 1)
566#endif
567	ieee80211_send_probe_requests(ieee);
568
569
570#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
571	queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
572#else
573	//ieee->scan_timer.expires = jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME);
574	if (ieee->scanning == 1)
575		mod_timer(&ieee->scan_timer,(jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME)));
576#endif
577
578	up(&ieee->scan_sem);
579	return;
580out:
581#ifdef ENABLE_DOT11D
582	if(IS_DOT11D_ENABLE(ieee))
583		DOT11D_ScanComplete(ieee);
584#endif
585        ieee->actscanning = false;
586	watchdog = 0;
587	ieee->scanning = 0;
588	up(&ieee->scan_sem);
589}
590
591#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
592void ieee80211_softmac_scan_cb(unsigned long _dev)
593{
594	unsigned long flags;
595	struct ieee80211_device *ieee = (struct ieee80211_device *)_dev;
596
597	spin_lock_irqsave(&ieee->lock, flags);
598	ieee80211_softmac_scan(ieee);
599	spin_unlock_irqrestore(&ieee->lock, flags);
600}
601#endif
602
603
604void ieee80211_beacons_start(struct ieee80211_device *ieee)
605{
606	unsigned long flags;
607	spin_lock_irqsave(&ieee->beacon_lock,flags);
608
609	ieee->beacon_txing = 1;
610	ieee80211_send_beacon(ieee);
611
612	spin_unlock_irqrestore(&ieee->beacon_lock,flags);
613}
614
615void ieee80211_beacons_stop(struct ieee80211_device *ieee)
616{
617	unsigned long flags;
618
619	spin_lock_irqsave(&ieee->beacon_lock,flags);
620
621	ieee->beacon_txing = 0;
622 	del_timer_sync(&ieee->beacon_timer);
623
624	spin_unlock_irqrestore(&ieee->beacon_lock,flags);
625
626}
627
628
629void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
630{
631	if(ieee->stop_send_beacons)
632		ieee->stop_send_beacons(ieee->dev);
633	if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
634		ieee80211_beacons_stop(ieee);
635}
636
637
638void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
639{
640	if(ieee->start_send_beacons)
641		ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
642	if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
643		ieee80211_beacons_start(ieee);
644}
645
646
647void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
648{
649//	unsigned long flags;
650
651	//ieee->sync_scan_hurryup = 1;
652
653	down(&ieee->scan_sem);
654//	spin_lock_irqsave(&ieee->lock, flags);
655
656	if (ieee->scanning == 1){
657		ieee->scanning = 0;
658
659#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
660		cancel_delayed_work(&ieee->softmac_scan_wq);
661#else
662		del_timer_sync(&ieee->scan_timer);
663#endif
664	}
665
666//	spin_unlock_irqrestore(&ieee->lock, flags);
667	up(&ieee->scan_sem);
668}
669
670void ieee80211_stop_scan(struct ieee80211_device *ieee)
671{
672	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
673		ieee80211_softmac_stop_scan(ieee);
674	else
675		ieee->stop_scan(ieee->dev);
676}
677
678/* called with ieee->lock held */
679void ieee80211_start_scan(struct ieee80211_device *ieee)
680{
681#ifdef ENABLE_DOT11D
682	if(IS_DOT11D_ENABLE(ieee) )
683	{
684		if(IS_COUNTRY_IE_VALID(ieee))
685		{
686			RESET_CIE_WATCHDOG(ieee);
687		}
688	}
689#endif
690	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
691		if (ieee->scanning == 0){
692			ieee->scanning = 1;
693#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
694#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
695			queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
696#else
697
698			queue_work(ieee->wq, &ieee->softmac_scan_wq);
699#endif
700#else
701			ieee80211_softmac_scan(ieee);
702#endif
703		}
704	}else
705		ieee->start_scan(ieee->dev);
706
707}
708
709/* called with wx_sem held */
710void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
711{
712#ifdef ENABLE_DOT11D
713	if(IS_DOT11D_ENABLE(ieee) )
714	{
715		if(IS_COUNTRY_IE_VALID(ieee))
716		{
717			RESET_CIE_WATCHDOG(ieee);
718		}
719	}
720#endif
721	ieee->sync_scan_hurryup = 0;
722	if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
723		ieee80211_softmac_scan_syncro(ieee);
724	else
725		ieee->scan_syncro(ieee->dev);
726
727}
728
729inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
730	struct ieee80211_device *ieee, int challengelen)
731{
732	struct sk_buff *skb;
733	struct ieee80211_authentication *auth;
734	int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
735
736
737	skb = dev_alloc_skb(len);
738	if (!skb) return NULL;
739
740	skb_reserve(skb, ieee->tx_headroom);
741	auth = (struct ieee80211_authentication *)
742		skb_put(skb, sizeof(struct ieee80211_authentication));
743
744	auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
745	if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
746
747	auth->header.duration_id = 0x013a; //FIXME
748
749	memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
750	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
751	memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
752
753	//auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
754	if(ieee->auth_mode == 0)
755		auth->algorithm = WLAN_AUTH_OPEN;
756	else if(ieee->auth_mode == 1)
757		auth->algorithm = WLAN_AUTH_SHARED_KEY;
758	else if(ieee->auth_mode == 2)
759		auth->algorithm = WLAN_AUTH_OPEN;//0x80;
760	printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
761	auth->transaction = cpu_to_le16(ieee->associate_seq);
762	ieee->associate_seq++;
763
764	auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
765
766	return skb;
767
768}
769
770
771static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
772{
773	u8 *tag;
774	int beacon_size;
775	struct ieee80211_probe_response *beacon_buf;
776	struct sk_buff *skb = NULL;
777	int encrypt;
778	int atim_len,erp_len;
779	struct ieee80211_crypt_data* crypt;
780
781	char *ssid = ieee->current_network.ssid;
782	int ssid_len = ieee->current_network.ssid_len;
783	int rate_len = ieee->current_network.rates_len+2;
784	int rate_ex_len = ieee->current_network.rates_ex_len;
785	int wpa_ie_len = ieee->wpa_ie_len;
786	u8 erpinfo_content = 0;
787
788	u8* tmp_ht_cap_buf;
789	u8 tmp_ht_cap_len=0;
790	u8* tmp_ht_info_buf;
791	u8 tmp_ht_info_len=0;
792	PRT_HIGH_THROUGHPUT	pHTInfo = ieee->pHTInfo;
793	u8* tmp_generic_ie_buf=NULL;
794	u8 tmp_generic_ie_len=0;
795
796	if(rate_ex_len > 0) rate_ex_len+=2;
797
798	if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
799		atim_len = 4;
800	else
801		atim_len = 0;
802
803#if 1
804	if(ieee80211_is_54g(ieee->current_network))
805		erp_len = 3;
806	else
807		erp_len = 0;
808#else
809      if((ieee->current_network.mode == IEEE_G)
810	  	||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
811	  	erp_len = 3;
812		erpinfo_content = 0;
813		if(ieee->current_network.buseprotection)
814			erpinfo_content |= ERP_UseProtection;
815      	}
816	else
817		erp_len = 0;
818#endif
819
820
821	crypt = ieee->crypt[ieee->tx_keyidx];
822
823
824	encrypt = ieee->host_encrypt && crypt && crypt->ops &&
825		((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
826	//HT ralated element
827#if 1
828	tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
829	tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
830	tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
831	tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
832	HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
833	HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
834
835
836        if(pHTInfo->bRegRT2RTAggregation)
837        {
838        	tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
839		tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
840		HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
841        }
842//	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);
843#endif
844	beacon_size = sizeof(struct ieee80211_probe_response)+2+
845		ssid_len
846		+3 //channel
847		+rate_len
848		+rate_ex_len
849		+atim_len
850		+erp_len
851                +wpa_ie_len
852	//	+tmp_ht_cap_len
853	//	+tmp_ht_info_len
854	//	+tmp_generic_ie_len
855//		+wmm_len+2
856		+ieee->tx_headroom;
857	skb = dev_alloc_skb(beacon_size);
858	if (!skb)
859		return NULL;
860	skb_reserve(skb, ieee->tx_headroom);
861	beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
862	memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
863	memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
864	memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
865
866	beacon_buf->header.duration_id = 0; //FIXME
867	beacon_buf->beacon_interval =
868		cpu_to_le16(ieee->current_network.beacon_interval);
869	beacon_buf->capability =
870		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
871	beacon_buf->capability |=
872		cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
873
874	if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
875		cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
876
877	crypt = ieee->crypt[ieee->tx_keyidx];
878#if 0
879	encrypt = ieee->host_encrypt && crypt && crypt->ops &&
880		(0 == strcmp(crypt->ops->name, "WEP"));
881#endif
882	if (encrypt)
883		beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
884
885
886	beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
887	beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
888	beacon_buf->info_element[0].len = ssid_len;
889
890	tag = (u8*) beacon_buf->info_element[0].data;
891
892	memcpy(tag, ssid, ssid_len);
893
894	tag += ssid_len;
895
896	*(tag++) = MFIE_TYPE_RATES;
897	*(tag++) = rate_len-2;
898	memcpy(tag,ieee->current_network.rates,rate_len-2);
899	tag+=rate_len-2;
900
901	*(tag++) = MFIE_TYPE_DS_SET;
902	*(tag++) = 1;
903	*(tag++) = ieee->current_network.channel;
904
905	if(atim_len){
906	u16 val16;
907		*(tag++) = MFIE_TYPE_IBSS_SET;
908		*(tag++) = 2;
909		//*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
910		 val16 = cpu_to_le16(ieee->current_network.atim_window);
911		memcpy((u8 *)tag, (u8 *)&val16, 2);
912		tag+=2;
913	}
914
915	if(erp_len){
916		*(tag++) = MFIE_TYPE_ERP;
917		*(tag++) = 1;
918		*(tag++) = erpinfo_content;
919	}
920#if 0
921	//Include High Throuput capability
922
923	*(tag++) = MFIE_TYPE_HT_CAP;
924	*(tag++) = tmp_ht_cap_len - 2;
925	memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
926	tag += tmp_ht_cap_len - 2;
927#endif
928	if(rate_ex_len){
929		*(tag++) = MFIE_TYPE_RATES_EX;
930		*(tag++) = rate_ex_len-2;
931		memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
932		tag+=rate_ex_len-2;
933	}
934
935#if 0
936	//Include High Throuput info
937
938	*(tag++) = MFIE_TYPE_HT_INFO;
939	*(tag++) = tmp_ht_info_len - 2;
940	memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
941	tag += tmp_ht_info_len - 2;
942#endif
943	if (wpa_ie_len)
944	{
945		if (ieee->iw_mode == IW_MODE_ADHOC)
946		{//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
947			memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
948		}
949		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
950		tag += wpa_ie_len;
951	}
952
953#if 0
954	//
955	// Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
956	//
957	if(pHTInfo->bRegRT2RTAggregation)
958	{
959		(*tag++) = 0xdd;
960		(*tag++) = tmp_generic_ie_len - 2;
961		memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
962		tag += tmp_generic_ie_len -2;
963
964	}
965#endif
966#if 0
967	if(ieee->qos_support)
968	{
969		(*tag++) = 0xdd;
970		(*tag++) = wmm_len;
971		memcpy(tag,QosOui,wmm_len);
972		tag += wmm_len;
973	}
974#endif
975	//skb->dev = ieee->dev;
976	return skb;
977}
978
979
980struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
981{
982	struct sk_buff *skb;
983	u8* tag;
984
985	struct ieee80211_crypt_data* crypt;
986	struct ieee80211_assoc_response_frame *assoc;
987	short encrypt;
988
989	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
990	int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
991
992	skb = dev_alloc_skb(len);
993
994	if (!skb)
995		return NULL;
996
997	skb_reserve(skb, ieee->tx_headroom);
998
999	assoc = (struct ieee80211_assoc_response_frame *)
1000		skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
1001
1002	assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
1003	memcpy(assoc->header.addr1, dest,ETH_ALEN);
1004	memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1005	memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1006	assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
1007		WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
1008
1009
1010	if(ieee->short_slot)
1011		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1012
1013	if (ieee->host_encrypt)
1014		crypt = ieee->crypt[ieee->tx_keyidx];
1015	else crypt = NULL;
1016
1017	encrypt = ( crypt && crypt->ops);
1018
1019	if (encrypt)
1020		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1021
1022	assoc->status = 0;
1023	assoc->aid = cpu_to_le16(ieee->assoc_id);
1024	if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
1025	else ieee->assoc_id++;
1026
1027	tag = (u8*) skb_put(skb, rate_len);
1028
1029	ieee80211_MFIE_Brate(ieee, &tag);
1030	ieee80211_MFIE_Grate(ieee, &tag);
1031
1032	return skb;
1033}
1034
1035struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
1036{
1037	struct sk_buff *skb;
1038	struct ieee80211_authentication *auth;
1039	int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
1040
1041	skb = dev_alloc_skb(len);
1042
1043	if (!skb)
1044		return NULL;
1045
1046	skb->len = sizeof(struct ieee80211_authentication);
1047
1048	auth = (struct ieee80211_authentication *)skb->data;
1049
1050	auth->status = cpu_to_le16(status);
1051	auth->transaction = cpu_to_le16(2);
1052	auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
1053
1054	memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1055	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1056	memcpy(auth->header.addr1, dest, ETH_ALEN);
1057	auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
1058	return skb;
1059
1060
1061}
1062
1063struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
1064{
1065	struct sk_buff *skb;
1066	struct ieee80211_hdr_3addr* hdr;
1067
1068	skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1069
1070	if (!skb)
1071		return NULL;
1072
1073	hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1074
1075	memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1076	memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1077	memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1078
1079	hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
1080		IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1081		(pwr ? IEEE80211_FCTL_PM:0));
1082
1083	return skb;
1084
1085
1086}
1087
1088
1089void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1090{
1091	struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1092
1093	if (buf)
1094		softmac_mgmt_xmit(buf, ieee);
1095}
1096
1097
1098void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1099{
1100	struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1101
1102	if (buf)
1103		softmac_mgmt_xmit(buf, ieee);
1104}
1105
1106
1107void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1108{
1109
1110
1111	struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1112	if (buf)
1113		softmac_mgmt_xmit(buf, ieee);
1114}
1115
1116
1117inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1118{
1119	struct sk_buff *skb;
1120	//unsigned long flags;
1121
1122	struct ieee80211_assoc_request_frame *hdr;
1123	u8 *tag;//,*rsn_ie;
1124	//short info_addr = 0;
1125	//int i;
1126	//u16 suite_count = 0;
1127	//u8 suit_select = 0;
1128	//unsigned int wpa_len = beacon->wpa_ie_len;
1129	//for HT
1130	u8* ht_cap_buf = NULL;
1131	u8 ht_cap_len=0;
1132	u8* realtek_ie_buf=NULL;
1133	u8 realtek_ie_len=0;
1134	int wpa_ie_len= ieee->wpa_ie_len;
1135	unsigned int ckip_ie_len=0;
1136	unsigned int ccxrm_ie_len=0;
1137	unsigned int cxvernum_ie_len=0;
1138	struct ieee80211_crypt_data* crypt;
1139	int encrypt;
1140
1141	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1142	unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1143#ifdef THOMAS_TURBO
1144	unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1145#endif
1146
1147	int len = 0;
1148
1149	crypt = ieee->crypt[ieee->tx_keyidx];
1150	encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1151
1152	//Include High Throuput capability && Realtek proprietary
1153	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1154	{
1155		ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1156		ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1157		HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1158		if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1159		{
1160			realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1161			realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1162			HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1163
1164		}
1165	}
1166	if(ieee->qos_support){
1167		wmm_info_len = beacon->qos_data.supported?9:0;
1168	}
1169
1170
1171	if(beacon->bCkipSupported)
1172	{
1173		ckip_ie_len = 30+2;
1174	}
1175	if(beacon->bCcxRmEnable)
1176	{
1177		ccxrm_ie_len = 6+2;
1178	}
1179	if( beacon->BssCcxVerNumber >= 2 )
1180	{
1181		cxvernum_ie_len = 5+2;
1182	}
1183#ifdef THOMAS_TURBO
1184	len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1185		+ beacon->ssid_len//essid tagged val
1186		+ rate_len//rates tagged val
1187		+ wpa_ie_len
1188		+ wmm_info_len
1189		+ turbo_info_len
1190                + ht_cap_len
1191		+ realtek_ie_len
1192		+ ckip_ie_len
1193		+ ccxrm_ie_len
1194		+ cxvernum_ie_len
1195		+ ieee->tx_headroom;
1196#else
1197	len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1198		+ beacon->ssid_len//essid tagged val
1199		+ rate_len//rates tagged val
1200		+ wpa_ie_len
1201		+ wmm_info_len
1202                + ht_cap_len
1203		+ realtek_ie_len
1204		+ ckip_ie_len
1205		+ ccxrm_ie_len
1206		+ cxvernum_ie_len
1207		+ ieee->tx_headroom;
1208#endif
1209
1210	skb = dev_alloc_skb(len);
1211
1212	if (!skb)
1213		return NULL;
1214
1215	skb_reserve(skb, ieee->tx_headroom);
1216
1217	hdr = (struct ieee80211_assoc_request_frame *)
1218		skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1219
1220
1221	hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1222	hdr->header.duration_id= 37; //FIXME
1223	memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1224	memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1225	memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1226
1227	memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1228
1229	hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1230	if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1231		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1232
1233	if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1234		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1235
1236	if(ieee->short_slot)
1237		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1238 	if (wmm_info_len) //QOS
1239	hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1240
1241	hdr->listen_interval = 0xa; //FIXME
1242
1243	hdr->info_element[0].id = MFIE_TYPE_SSID;
1244
1245	hdr->info_element[0].len = beacon->ssid_len;
1246	tag = skb_put(skb, beacon->ssid_len);
1247	memcpy(tag, beacon->ssid, beacon->ssid_len);
1248
1249	tag = skb_put(skb, rate_len);
1250
1251	ieee80211_MFIE_Brate(ieee, &tag);
1252	ieee80211_MFIE_Grate(ieee, &tag);
1253	// For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1254	if( beacon->bCkipSupported )
1255	{
1256		static u8	AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1257		u8	CcxAironetBuf[30];
1258		OCTET_STRING	osCcxAironetIE;
1259
1260		memset(CcxAironetBuf, 0,30);
1261		osCcxAironetIE.Octet = CcxAironetBuf;
1262		osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1263		//
1264		// Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1265		// We want to make the device type as "4500-client". 060926, by CCW.
1266		//
1267		memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1268
1269		// CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1270		// "The CKIP negotiation is started with the associate request from the client to the access point,
1271		//  containing an Aironet element with both the MIC and KP bits set."
1272		osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=  (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1273		tag = skb_put(skb, ckip_ie_len);
1274		*tag++ = MFIE_TYPE_AIRONET;
1275		*tag++ = osCcxAironetIE.Length;
1276		memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1277		tag += osCcxAironetIE.Length;
1278	}
1279
1280	if(beacon->bCcxRmEnable)
1281	{
1282		static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1283		OCTET_STRING osCcxRmCap;
1284
1285		osCcxRmCap.Octet = CcxRmCapBuf;
1286		osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1287		tag = skb_put(skb,ccxrm_ie_len);
1288		*tag++ = MFIE_TYPE_GENERIC;
1289		*tag++ = osCcxRmCap.Length;
1290		memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1291		tag += osCcxRmCap.Length;
1292	}
1293
1294	if( beacon->BssCcxVerNumber >= 2 )
1295	{
1296		u8			CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1297		OCTET_STRING	osCcxVerNum;
1298		CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1299		osCcxVerNum.Octet = CcxVerNumBuf;
1300		osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1301		tag = skb_put(skb,cxvernum_ie_len);
1302		*tag++ = MFIE_TYPE_GENERIC;
1303		*tag++ = osCcxVerNum.Length;
1304		memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1305		tag += osCcxVerNum.Length;
1306	}
1307        //HT cap element
1308	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1309		if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1310		{
1311			tag = skb_put(skb, ht_cap_len);
1312			*tag++ = MFIE_TYPE_HT_CAP;
1313			*tag++ = ht_cap_len - 2;
1314			memcpy(tag, ht_cap_buf,ht_cap_len -2);
1315			tag += ht_cap_len -2;
1316		}
1317	}
1318
1319
1320	//choose what wpa_supplicant gives to associate.
1321	tag = skb_put(skb, wpa_ie_len);
1322	if (wpa_ie_len){
1323		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1324	}
1325
1326	tag = skb_put(skb,wmm_info_len);
1327	if(wmm_info_len) {
1328	  ieee80211_WMM_Info(ieee, &tag);
1329	}
1330#ifdef THOMAS_TURBO
1331	tag = skb_put(skb,turbo_info_len);
1332        if(turbo_info_len) {
1333                ieee80211_TURBO_Info(ieee, &tag);
1334        }
1335#endif
1336
1337	if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1338		if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1339		{
1340			tag = skb_put(skb, ht_cap_len);
1341			*tag++ = MFIE_TYPE_GENERIC;
1342			*tag++ = ht_cap_len - 2;
1343			memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1344			tag += ht_cap_len -2;
1345		}
1346
1347		if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1348			tag = skb_put(skb, realtek_ie_len);
1349			*tag++ = MFIE_TYPE_GENERIC;
1350			*tag++ = realtek_ie_len - 2;
1351			memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1352		}
1353	}
1354//	printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1355//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1356	return skb;
1357}
1358
1359void ieee80211_associate_abort(struct ieee80211_device *ieee)
1360{
1361
1362	unsigned long flags;
1363	spin_lock_irqsave(&ieee->lock, flags);
1364
1365	ieee->associate_seq++;
1366
1367	/* don't scan, and avoid to have the RX path possibily
1368	 * try again to associate. Even do not react to AUTH or
1369	 * ASSOC response. Just wait for the retry wq to be scheduled.
1370	 * Here we will check if there are good nets to associate
1371	 * with, so we retry or just get back to NO_LINK and scanning
1372	 */
1373	if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1374		IEEE80211_DEBUG_MGMT("Authentication failed\n");
1375		ieee->softmac_stats.no_auth_rs++;
1376	}else{
1377		IEEE80211_DEBUG_MGMT("Association failed\n");
1378		ieee->softmac_stats.no_ass_rs++;
1379	}
1380
1381	ieee->state = IEEE80211_ASSOCIATING_RETRY;
1382
1383#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1384	queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1385                           IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1386#else
1387	schedule_task(&ieee->associate_retry_wq);
1388#endif
1389
1390	spin_unlock_irqrestore(&ieee->lock, flags);
1391}
1392
1393void ieee80211_associate_abort_cb(unsigned long dev)
1394{
1395	ieee80211_associate_abort((struct ieee80211_device *) dev);
1396}
1397
1398
1399void ieee80211_associate_step1(struct ieee80211_device *ieee)
1400{
1401	struct ieee80211_network *beacon = &ieee->current_network;
1402	struct sk_buff *skb;
1403
1404	IEEE80211_DEBUG_MGMT("Stopping scan\n");
1405
1406	ieee->softmac_stats.tx_auth_rq++;
1407	skb=ieee80211_authentication_req(beacon, ieee, 0);
1408
1409	if (!skb)
1410		ieee80211_associate_abort(ieee);
1411	else{
1412		ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1413		IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1414		//printk(KERN_WARNING "Sending authentication request\n");
1415		softmac_mgmt_xmit(skb, ieee);
1416		//BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1417		if(!timer_pending(&ieee->associate_timer)){
1418			ieee->associate_timer.expires = jiffies + (HZ / 2);
1419			add_timer(&ieee->associate_timer);
1420		}
1421		//dev_kfree_skb_any(skb);//edit by thomas
1422	}
1423}
1424
1425void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1426{
1427	u8 *c;
1428	struct sk_buff *skb;
1429	struct ieee80211_network *beacon = &ieee->current_network;
1430//	int hlen = sizeof(struct ieee80211_authentication);
1431
1432	ieee->associate_seq++;
1433	ieee->softmac_stats.tx_auth_rq++;
1434
1435	skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1436	if (!skb)
1437		ieee80211_associate_abort(ieee);
1438	else{
1439		c = skb_put(skb, chlen+2);
1440		*(c++) = MFIE_TYPE_CHALLENGE;
1441		*(c++) = chlen;
1442		memcpy(c, challenge, chlen);
1443
1444		IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1445
1446		ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr  ));
1447
1448		softmac_mgmt_xmit(skb, ieee);
1449		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1450#if 0
1451		ieee->associate_timer.expires = jiffies + (HZ / 2);
1452		add_timer(&ieee->associate_timer);
1453#endif
1454		//dev_kfree_skb_any(skb);//edit by thomas
1455	}
1456	kfree(challenge);
1457}
1458
1459void ieee80211_associate_step2(struct ieee80211_device *ieee)
1460{
1461	struct sk_buff* skb;
1462	struct ieee80211_network *beacon = &ieee->current_network;
1463
1464	del_timer_sync(&ieee->associate_timer);
1465
1466	IEEE80211_DEBUG_MGMT("Sending association request\n");
1467
1468	ieee->softmac_stats.tx_ass_rq++;
1469	skb=ieee80211_association_req(beacon, ieee);
1470	if (!skb)
1471		ieee80211_associate_abort(ieee);
1472	else{
1473		softmac_mgmt_xmit(skb, ieee);
1474		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1475#if 0
1476		ieee->associate_timer.expires = jiffies + (HZ / 2);
1477		add_timer(&ieee->associate_timer);
1478#endif
1479		//dev_kfree_skb_any(skb);//edit by thomas
1480	}
1481}
1482#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1483void ieee80211_associate_complete_wq(struct work_struct *work)
1484{
1485        struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1486#else
1487void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1488{
1489#endif
1490	printk(KERN_INFO "Associated successfully\n");
1491	if(ieee80211_is_54g(ieee->current_network) &&
1492		(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1493
1494		ieee->rate = 108;
1495		printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1496	}else{
1497		ieee->rate = 22;
1498		printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1499	}
1500	if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1501	{
1502		printk("Successfully associated, ht enabled\n");
1503		HTOnAssocRsp(ieee);
1504	}
1505	else
1506	{
1507		printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1508		memset(ieee->dot11HTOperationalRateSet, 0, 16);
1509		//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1510	}
1511	ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1512	// To prevent the immediately calling watch_dog after association.
1513	if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1514	{
1515		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1516		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1517	}
1518	ieee->link_change(ieee->dev);
1519	if(ieee->is_silent_reset == 0){
1520		printk("============>normal associate\n");
1521	notify_wx_assoc_event(ieee);
1522	}
1523	else if(ieee->is_silent_reset == 1)
1524	{
1525		printk("==================>silent reset associate\n");
1526		ieee->is_silent_reset = 0;
1527	}
1528
1529	if (ieee->data_hard_resume)
1530		ieee->data_hard_resume(ieee->dev);
1531	netif_carrier_on(ieee->dev);
1532}
1533
1534void ieee80211_associate_complete(struct ieee80211_device *ieee)
1535{
1536//	int i;
1537//	struct net_device* dev = ieee->dev;
1538	del_timer_sync(&ieee->associate_timer);
1539
1540#if 0
1541	for(i = 0; i < 6; i++) {
1542	  ieee->seq_ctrl[i] = 0;
1543	}
1544#endif
1545	ieee->state = IEEE80211_LINKED;
1546#if 0
1547	if (ieee->pHTInfo->bCurrentHTSupport)
1548	{
1549		printk("Successfully associated, ht enabled\n");
1550		queue_work(ieee->wq, &ieee->ht_onAssRsp);
1551	}
1552	else
1553	{
1554		printk("Successfully associated, ht not enabled\n");
1555		memset(ieee->dot11HTOperationalRateSet, 0, 16);
1556		HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1557	}
1558#endif
1559	//ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1560#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1561	queue_work(ieee->wq, &ieee->associate_complete_wq);
1562#else
1563	schedule_task(&ieee->associate_complete_wq);
1564#endif
1565}
1566
1567#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1568void ieee80211_associate_procedure_wq(struct work_struct *work)
1569{
1570        struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1571#else
1572void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1573{
1574#endif
1575	ieee->sync_scan_hurryup = 1;
1576	down(&ieee->wx_sem);
1577
1578	if (ieee->data_hard_stop)
1579		ieee->data_hard_stop(ieee->dev);
1580
1581	ieee80211_stop_scan(ieee);
1582	printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1583	//ieee->set_chan(ieee->dev, ieee->current_network.channel);
1584	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1585
1586	ieee->associate_seq = 1;
1587	ieee80211_associate_step1(ieee);
1588
1589	up(&ieee->wx_sem);
1590}
1591
1592inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1593{
1594	u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1595	int tmp_ssid_len = 0;
1596
1597	short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1598
1599	/* we are interested in new new only if we are not associated
1600	 * and we are not associating / authenticating
1601	 */
1602	if (ieee->state != IEEE80211_NOLINK)
1603		return;
1604
1605	if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1606		return;
1607
1608	if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1609		return;
1610
1611
1612	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1613		/* if the user specified the AP MAC, we need also the essid
1614		 * This could be obtained by beacons or, if the network does not
1615		 * broadcast it, it can be put manually.
1616		 */
1617		apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1618		ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1619		ssidbroad =  !(net->ssid_len == 0 || net->ssid[0]== '\0');
1620		apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1621		ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1622				(!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1623
1624
1625		if (	/* if the user set the AP check if match.
1626		         * if the network does not broadcast essid we check the user supplyed ANY essid
1627			 * if the network does broadcast and the user does not set essid it is OK
1628			 * if the network does broadcast and the user did set essid chech if essid match
1629			 */
1630			( apset && apmatch &&
1631				((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1632			/* if the ap is not set, check that the user set the bssid
1633			 * and the network does bradcast and that those two bssid matches
1634			 */
1635			(!apset && ssidset && ssidbroad && ssidmatch)
1636			){
1637				/* if the essid is hidden replace it with the
1638				* essid provided by the user.
1639				*/
1640				if (!ssidbroad){
1641					strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1642					tmp_ssid_len = ieee->current_network.ssid_len;
1643				}
1644				memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1645
1646				if (!ssidbroad){
1647					strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1648					ieee->current_network.ssid_len = tmp_ssid_len;
1649				}
1650				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);
1651
1652				//ieee->pHTInfo->IOTAction = 0;
1653				HTResetIOTSetting(ieee->pHTInfo);
1654				if (ieee->iw_mode == IW_MODE_INFRA){
1655					/* Join the network for the first time */
1656					ieee->AsocRetryCount = 0;
1657					//for HT by amy 080514
1658					if((ieee->current_network.qos_data.supported == 1) &&
1659					  // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1660					   ieee->current_network.bssht.bdSupportHT)
1661/*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.*/
1662					{
1663					//	ieee->pHTInfo->bCurrentHTSupport = true;
1664						HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1665					}
1666					else
1667					{
1668						ieee->pHTInfo->bCurrentHTSupport = false;
1669					}
1670
1671					ieee->state = IEEE80211_ASSOCIATING;
1672#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1673					queue_work(ieee->wq, &ieee->associate_procedure_wq);
1674#else
1675					schedule_task(&ieee->associate_procedure_wq);
1676#endif
1677				}else{
1678					if(ieee80211_is_54g(ieee->current_network) &&
1679						(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1680						ieee->rate = 108;
1681						ieee->SetWirelessMode(ieee->dev, IEEE_G);
1682						printk(KERN_INFO"Using G rates\n");
1683					}else{
1684						ieee->rate = 22;
1685						ieee->SetWirelessMode(ieee->dev, IEEE_B);
1686						printk(KERN_INFO"Using B rates\n");
1687					}
1688					memset(ieee->dot11HTOperationalRateSet, 0, 16);
1689					//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1690					ieee->state = IEEE80211_LINKED;
1691				}
1692
1693		}
1694	}
1695
1696}
1697
1698void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1699{
1700	unsigned long flags;
1701	struct ieee80211_network *target;
1702
1703	spin_lock_irqsave(&ieee->lock, flags);
1704
1705	list_for_each_entry(target, &ieee->network_list, list) {
1706
1707		/* if the state become different that NOLINK means
1708		 * we had found what we are searching for
1709		 */
1710
1711		if (ieee->state != IEEE80211_NOLINK)
1712			break;
1713
1714		if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1715		ieee80211_softmac_new_net(ieee, target);
1716	}
1717
1718	spin_unlock_irqrestore(&ieee->lock, flags);
1719
1720}
1721
1722
1723static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1724{
1725	struct ieee80211_authentication *a;
1726	u8 *t;
1727	if (skb->len <  (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1728		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1729		return 0xcafe;
1730	}
1731	*challenge = NULL;
1732	a = (struct ieee80211_authentication*) skb->data;
1733	if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1734		t = skb->data + sizeof(struct ieee80211_authentication);
1735
1736		if(*(t++) == MFIE_TYPE_CHALLENGE){
1737			*chlen = *(t++);
1738			*challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1739			memcpy(*challenge, t, *chlen);
1740		}
1741	}
1742
1743	return cpu_to_le16(a->status);
1744
1745}
1746
1747
1748int auth_rq_parse(struct sk_buff *skb,u8* dest)
1749{
1750	struct ieee80211_authentication *a;
1751
1752	if (skb->len <  (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1753		IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1754		return -1;
1755	}
1756	a = (struct ieee80211_authentication*) skb->data;
1757
1758	memcpy(dest,a->header.addr2, ETH_ALEN);
1759
1760	if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1761		return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1762
1763	return WLAN_STATUS_SUCCESS;
1764}
1765
1766static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1767{
1768	u8 *tag;
1769	u8 *skbend;
1770	u8 *ssid=NULL;
1771	u8 ssidlen = 0;
1772
1773	struct ieee80211_hdr_3addr   *header =
1774		(struct ieee80211_hdr_3addr   *) skb->data;
1775
1776	if (skb->len < sizeof (struct ieee80211_hdr_3addr  ))
1777		return -1; /* corrupted */
1778
1779	memcpy(src,header->addr2, ETH_ALEN);
1780
1781	skbend = (u8*)skb->data + skb->len;
1782
1783	tag = skb->data + sizeof (struct ieee80211_hdr_3addr  );
1784
1785	while (tag+1 < skbend){
1786		if (*tag == 0){
1787			ssid = tag+2;
1788			ssidlen = *(tag+1);
1789			break;
1790		}
1791		tag++; /* point to the len field */
1792		tag = tag + *(tag); /* point to the last data byte of the tag */
1793		tag++; /* point to the next tag */
1794	}
1795
1796	//IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1797	if (ssidlen == 0) return 1;
1798
1799	if (!ssid) return 1; /* ssid not found in tagged param */
1800	return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1801
1802}
1803
1804int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1805{
1806	struct ieee80211_assoc_request_frame *a;
1807
1808	if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1809		sizeof(struct ieee80211_info_element))) {
1810
1811		IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1812		return -1;
1813	}
1814
1815	a = (struct ieee80211_assoc_request_frame*) skb->data;
1816
1817	memcpy(dest,a->header.addr2,ETH_ALEN);
1818
1819	return 0;
1820}
1821
1822static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1823{
1824	struct ieee80211_assoc_response_frame *response_head;
1825	u16 status_code;
1826
1827	if (skb->len <  sizeof(struct ieee80211_assoc_response_frame)){
1828		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1829		return 0xcafe;
1830	}
1831
1832	response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1833	*aid = le16_to_cpu(response_head->aid) & 0x3fff;
1834
1835	status_code = le16_to_cpu(response_head->status);
1836	if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1837	   status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1838	   ((ieee->mode == IEEE_G) &&
1839	    (ieee->current_network.mode == IEEE_N_24G) &&
1840            (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1841                 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1842	}else {
1843		 ieee->AsocRetryCount = 0;
1844	}
1845
1846	return le16_to_cpu(response_head->status);
1847}
1848
1849static inline void
1850ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1851{
1852	u8 dest[ETH_ALEN];
1853
1854	//IEEE80211DMESG("Rx probe");
1855	ieee->softmac_stats.rx_probe_rq++;
1856	//DMESG("Dest is "MACSTR, MAC2STR(dest));
1857	if (probe_rq_parse(ieee, skb, dest)){
1858		//IEEE80211DMESG("Was for me!");
1859		ieee->softmac_stats.tx_probe_rs++;
1860		ieee80211_resp_to_probe(ieee, dest);
1861	}
1862}
1863
1864static inline void
1865ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1866{
1867	u8 dest[ETH_ALEN];
1868	int status;
1869	//IEEE80211DMESG("Rx probe");
1870	ieee->softmac_stats.rx_auth_rq++;
1871
1872	if ((status = auth_rq_parse(skb, dest))!= -1){
1873		ieee80211_resp_to_auth(ieee, status, dest);
1874	}
1875	//DMESG("Dest is "MACSTR, MAC2STR(dest));
1876
1877}
1878
1879static inline void
1880ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1881{
1882
1883	u8 dest[ETH_ALEN];
1884	//unsigned long flags;
1885
1886	ieee->softmac_stats.rx_ass_rq++;
1887	if (assoc_rq_parse(skb,dest) != -1){
1888		ieee80211_resp_to_assoc_rq(ieee, dest);
1889	}
1890
1891	printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
1892	//FIXME
1893	#if 0
1894	spin_lock_irqsave(&ieee->lock,flags);
1895	add_associate(ieee,dest);
1896	spin_unlock_irqrestore(&ieee->lock,flags);
1897	#endif
1898}
1899
1900
1901
1902void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1903{
1904
1905	struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1906
1907	if (buf)
1908		softmac_ps_mgmt_xmit(buf, ieee);
1909
1910}
1911
1912
1913short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1914{
1915	int timeout = ieee->ps_timeout;
1916	u8 dtim;
1917	/*if(ieee->ps == IEEE80211_PS_DISABLED ||
1918		ieee->iw_mode != IW_MODE_INFRA ||
1919		ieee->state != IEEE80211_LINKED)
1920
1921		return 0;
1922	*/
1923	dtim = ieee->current_network.dtim_data;
1924	//printk("DTIM\n");
1925	if(!(dtim & IEEE80211_DTIM_VALID))
1926		return 0;
1927	timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1928	//printk("VALID\n");
1929	ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1930
1931	if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1932		return 2;
1933
1934	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1935		return 0;
1936
1937	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1938		return 0;
1939
1940	if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1941		(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1942		return 0;
1943
1944	if(time_l){
1945		*time_l = ieee->current_network.last_dtim_sta_time[0]
1946			+ (ieee->current_network.beacon_interval
1947			* ieee->current_network.dtim_period) * 1000;
1948	}
1949
1950	if(time_h){
1951		*time_h = ieee->current_network.last_dtim_sta_time[1];
1952		if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1953			*time_h += 1;
1954	}
1955
1956	return 1;
1957
1958
1959}
1960
1961inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1962{
1963
1964	u32 th,tl;
1965	short sleep;
1966
1967	unsigned long flags,flags2;
1968
1969	spin_lock_irqsave(&ieee->lock, flags);
1970
1971	if((ieee->ps == IEEE80211_PS_DISABLED ||
1972		ieee->iw_mode != IW_MODE_INFRA ||
1973		ieee->state != IEEE80211_LINKED)){
1974
1975	//	#warning CHECK_LOCK_HERE
1976		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1977
1978		ieee80211_sta_wakeup(ieee, 1);
1979
1980		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1981	}
1982
1983	sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1984	/* 2 wake, 1 sleep, 0 do nothing */
1985	if(sleep == 0)
1986		goto out;
1987
1988	if(sleep == 1){
1989
1990		if(ieee->sta_sleep == 1)
1991			ieee->enter_sleep_state(ieee->dev,th,tl);
1992
1993		else if(ieee->sta_sleep == 0){
1994		//	printk("send null 1\n");
1995			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1996
1997			if(ieee->ps_is_queue_empty(ieee->dev)){
1998
1999
2000				ieee->sta_sleep = 2;
2001
2002				ieee->ps_request_tx_ack(ieee->dev);
2003
2004				ieee80211_sta_ps_send_null_frame(ieee,1);
2005
2006				ieee->ps_th = th;
2007				ieee->ps_tl = tl;
2008			}
2009			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2010
2011		}
2012
2013
2014	}else if(sleep == 2){
2015//#warning CHECK_LOCK_HERE
2016		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2017
2018		ieee80211_sta_wakeup(ieee,1);
2019
2020		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2021	}
2022
2023out:
2024	spin_unlock_irqrestore(&ieee->lock, flags);
2025
2026}
2027
2028void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2029{
2030	if(ieee->sta_sleep == 0){
2031		if(nl){
2032			printk("Warning: driver is probably failing to report TX ps error\n");
2033			ieee->ps_request_tx_ack(ieee->dev);
2034			ieee80211_sta_ps_send_null_frame(ieee, 0);
2035		}
2036		return;
2037
2038	}
2039
2040	if(ieee->sta_sleep == 1)
2041		ieee->sta_wake_up(ieee->dev);
2042
2043	ieee->sta_sleep = 0;
2044
2045	if(nl){
2046		ieee->ps_request_tx_ack(ieee->dev);
2047		ieee80211_sta_ps_send_null_frame(ieee, 0);
2048	}
2049}
2050
2051void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2052{
2053	unsigned long flags,flags2;
2054
2055	spin_lock_irqsave(&ieee->lock, flags);
2056
2057	if(ieee->sta_sleep == 2){
2058		/* Null frame with PS bit set */
2059		if(success){
2060			ieee->sta_sleep = 1;
2061			ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2062		}
2063		/* if the card report not success we can't be sure the AP
2064		 * has not RXed so we can't assume the AP believe us awake
2065		 */
2066	}
2067	/* 21112005 - tx again null without PS bit if lost */
2068	else {
2069
2070		if((ieee->sta_sleep == 0) && !success){
2071			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2072			ieee80211_sta_ps_send_null_frame(ieee, 0);
2073			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2074		}
2075	}
2076	spin_unlock_irqrestore(&ieee->lock, flags);
2077}
2078void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2079{
2080	struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2081	u8* act = ieee80211_get_payload(header);
2082	u8 tmp = 0;
2083//	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2084	if (act == NULL)
2085	{
2086		IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2087		return;
2088	}
2089	tmp = *act;
2090	act ++;
2091	switch (tmp)
2092	{
2093		case ACT_CAT_BA:
2094			if (*act == ACT_ADDBAREQ)
2095			ieee80211_rx_ADDBAReq(ieee, skb);
2096			else if (*act == ACT_ADDBARSP)
2097			ieee80211_rx_ADDBARsp(ieee, skb);
2098			else if (*act == ACT_DELBA)
2099			ieee80211_rx_DELBA(ieee, skb);
2100			break;
2101		default:
2102//			if (net_ratelimit())
2103//			IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2104			break;
2105	}
2106	return;
2107
2108}
2109inline int
2110ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2111			struct ieee80211_rx_stats *rx_stats, u16 type,
2112			u16 stype)
2113{
2114	struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2115	u16 errcode;
2116	u8* challenge;
2117	int chlen=0;
2118	int aid;
2119	struct ieee80211_assoc_response_frame *assoc_resp;
2120//	struct ieee80211_info_element *info_element;
2121	bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2122
2123	if(!ieee->proto_started)
2124		return 0;
2125
2126	if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2127		ieee->iw_mode == IW_MODE_INFRA &&
2128		ieee->state == IEEE80211_LINKED))
2129
2130		tasklet_schedule(&ieee->ps_task);
2131
2132	if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2133		WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2134		ieee->last_rx_ps_time = jiffies;
2135
2136	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2137
2138		case IEEE80211_STYPE_ASSOC_RESP:
2139		case IEEE80211_STYPE_REASSOC_RESP:
2140
2141			IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2142					WLAN_FC_GET_STYPE(header->frame_ctl));
2143			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2144				ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2145				ieee->iw_mode == IW_MODE_INFRA){
2146				struct ieee80211_network network_resp;
2147				struct ieee80211_network *network = &network_resp;
2148
2149				if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2150					ieee->state=IEEE80211_LINKED;
2151					ieee->assoc_id = aid;
2152					ieee->softmac_stats.rx_ass_ok++;
2153					/* station support qos */
2154					/* Let the register setting defaultly with Legacy station */
2155					if(ieee->qos_support) {
2156						assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2157						memset(network, 0, sizeof(*network));
2158						if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2159									rx_stats->len - sizeof(*assoc_resp),\
2160									network,rx_stats)){
2161							return 1;
2162						}
2163						else
2164						{	//filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2165							memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2166							memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2167						}
2168						if (ieee->handle_assoc_response != NULL)
2169							ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2170					}
2171					ieee80211_associate_complete(ieee);
2172				} else {
2173					/* aid could not been allocated */
2174					ieee->softmac_stats.rx_ass_err++;
2175					printk(
2176						"Association response status code 0x%x\n",
2177						errcode);
2178					IEEE80211_DEBUG_MGMT(
2179						"Association response status code 0x%x\n",
2180						errcode);
2181					if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2182#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2183						queue_work(ieee->wq, &ieee->associate_procedure_wq);
2184#else
2185						schedule_task(&ieee->associate_procedure_wq);
2186#endif
2187					} else {
2188						ieee80211_associate_abort(ieee);
2189					}
2190				}
2191			}
2192			break;
2193
2194		case IEEE80211_STYPE_ASSOC_REQ:
2195		case IEEE80211_STYPE_REASSOC_REQ:
2196
2197			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2198				ieee->iw_mode == IW_MODE_MASTER)
2199
2200				ieee80211_rx_assoc_rq(ieee, skb);
2201			break;
2202
2203		case IEEE80211_STYPE_AUTH:
2204
2205			if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2206				if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2207				ieee->iw_mode == IW_MODE_INFRA){
2208
2209						IEEE80211_DEBUG_MGMT("Received authentication response");
2210
2211						if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2212							if(ieee->open_wep || !challenge){
2213								ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2214								ieee->softmac_stats.rx_auth_rs_ok++;
2215								if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2216								{
2217									if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2218									{
2219												// WEP or TKIP encryption
2220										if(IsHTHalfNmodeAPs(ieee))
2221										{
2222											bSupportNmode = true;
2223											bHalfSupportNmode = true;
2224										}
2225										else
2226										{
2227											bSupportNmode = false;
2228											bHalfSupportNmode = false;
2229										}
2230									printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2231									}
2232								}
2233								/* Dummy wirless mode setting to avoid encryption issue */
2234								if(bSupportNmode) {
2235									//N mode setting
2236									ieee->SetWirelessMode(ieee->dev, \
2237											ieee->current_network.mode);
2238								}else{
2239									//b/g mode setting
2240									/*TODO*/
2241									ieee->SetWirelessMode(ieee->dev, IEEE_G);
2242								}
2243
2244								if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2245								{
2246									printk("===============>entern half N mode\n");
2247									ieee->bHalfWirelessN24GMode = true;
2248								}
2249								else
2250									ieee->bHalfWirelessN24GMode = false;
2251
2252								ieee80211_associate_step2(ieee);
2253							}else{
2254								ieee80211_auth_challenge(ieee, challenge, chlen);
2255							}
2256						}else{
2257							ieee->softmac_stats.rx_auth_rs_err++;
2258							IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2259							ieee80211_associate_abort(ieee);
2260						}
2261
2262					}else if (ieee->iw_mode == IW_MODE_MASTER){
2263						ieee80211_rx_auth_rq(ieee, skb);
2264					}
2265				}
2266			break;
2267
2268		case IEEE80211_STYPE_PROBE_REQ:
2269
2270			if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2271				((ieee->iw_mode == IW_MODE_ADHOC ||
2272				ieee->iw_mode == IW_MODE_MASTER) &&
2273				ieee->state == IEEE80211_LINKED)){
2274				ieee80211_rx_probe_rq(ieee, skb);
2275			}
2276			break;
2277
2278		case IEEE80211_STYPE_DISASSOC:
2279		case IEEE80211_STYPE_DEAUTH:
2280			/* FIXME for now repeat all the association procedure
2281			* both for disassociation and deauthentication
2282			*/
2283			if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2284				ieee->state == IEEE80211_LINKED &&
2285				ieee->iw_mode == IW_MODE_INFRA){
2286
2287				ieee->state = IEEE80211_ASSOCIATING;
2288				ieee->softmac_stats.reassoc++;
2289
2290				notify_wx_assoc_event(ieee);
2291				//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2292				RemovePeerTS(ieee, header->addr2);
2293#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2294				queue_work(ieee->wq, &ieee->associate_procedure_wq);
2295#else
2296				schedule_task(&ieee->associate_procedure_wq);
2297#endif
2298			}
2299			break;
2300		case IEEE80211_STYPE_MANAGE_ACT:
2301			ieee80211_process_action(ieee,skb);
2302			break;
2303		default:
2304			return -1;
2305			break;
2306	}
2307
2308	//dev_kfree_skb_any(skb);
2309	return 0;
2310}
2311
2312/* following are for a simplier TX queue management.
2313 * Instead of using netif_[stop/wake]_queue the driver
2314 * will uses these two function (plus a reset one), that
2315 * will internally uses the kernel netif_* and takes
2316 * care of the ieee802.11 fragmentation.
2317 * So the driver receives a fragment per time and might
2318 * call the stop function when it want without take care
2319 * to have enought room to TX an entire packet.
2320 * This might be useful if each fragment need it's own
2321 * descriptor, thus just keep a total free memory > than
2322 * the max fragmentation treshold is not enought.. If the
2323 * ieee802.11 stack passed a TXB struct then you needed
2324 * to keep N free descriptors where
2325 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2326 * In this way you need just one and the 802.11 stack
2327 * will take care of buffering fragments and pass them to
2328 * to the driver later, when it wakes the queue.
2329 */
2330void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2331{
2332
2333	unsigned int queue_index = txb->queue_index;
2334	unsigned long flags;
2335	int  i;
2336	cb_desc *tcb_desc = NULL;
2337
2338	spin_lock_irqsave(&ieee->lock,flags);
2339
2340	/* called with 2nd parm 0, no tx mgmt lock required */
2341	ieee80211_sta_wakeup(ieee,0);
2342
2343	/* update the tx status */
2344	ieee->stats.tx_bytes += txb->payload_size;
2345	ieee->stats.tx_packets++;
2346	tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2347	if(tcb_desc->bMulticast) {
2348		ieee->stats.multicast++;
2349	}
2350#if 1
2351	/* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2352	for(i = 0; i < txb->nr_frags; i++) {
2353#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2354		if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2355#else
2356		if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2357#endif
2358		(!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2359		     (ieee->queue_stop)) {
2360			/* insert the skb packet to the wait queue */
2361			/* as for the completion function, it does not need
2362			 * to check it any more.
2363			 * */
2364			//printk("error:no descriptor left@queue_index %d\n", queue_index);
2365			//ieee80211_stop_queue(ieee);
2366#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2367			skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2368#else
2369			skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2370#endif
2371		}else{
2372			ieee->softmac_data_hard_start_xmit(
2373					txb->fragments[i],
2374					ieee->dev,ieee->rate);
2375			//ieee->stats.tx_packets++;
2376			//ieee->stats.tx_bytes += txb->fragments[i]->len;
2377			//ieee->dev->trans_start = jiffies;
2378		}
2379	}
2380#endif
2381	ieee80211_txb_free(txb);
2382
2383//exit:
2384	spin_unlock_irqrestore(&ieee->lock,flags);
2385
2386}
2387
2388/* called with ieee->lock acquired */
2389void ieee80211_resume_tx(struct ieee80211_device *ieee)
2390{
2391	int i;
2392	for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2393
2394		if (ieee->queue_stop){
2395			ieee->tx_pending.frag = i;
2396			return;
2397		}else{
2398
2399			ieee->softmac_data_hard_start_xmit(
2400				ieee->tx_pending.txb->fragments[i],
2401				ieee->dev,ieee->rate);
2402				//(i+1)<ieee->tx_pending.txb->nr_frags);
2403			ieee->stats.tx_packets++;
2404			ieee->dev->trans_start = jiffies;
2405		}
2406	}
2407
2408
2409	ieee80211_txb_free(ieee->tx_pending.txb);
2410	ieee->tx_pending.txb = NULL;
2411}
2412
2413
2414void ieee80211_reset_queue(struct ieee80211_device *ieee)
2415{
2416	unsigned long flags;
2417
2418	spin_lock_irqsave(&ieee->lock,flags);
2419	init_mgmt_queue(ieee);
2420	if (ieee->tx_pending.txb){
2421		ieee80211_txb_free(ieee->tx_pending.txb);
2422		ieee->tx_pending.txb = NULL;
2423	}
2424	ieee->queue_stop = 0;
2425	spin_unlock_irqrestore(&ieee->lock,flags);
2426
2427}
2428
2429void ieee80211_wake_queue(struct ieee80211_device *ieee)
2430{
2431
2432	unsigned long flags;
2433	struct sk_buff *skb;
2434	struct ieee80211_hdr_3addr  *header;
2435
2436	spin_lock_irqsave(&ieee->lock,flags);
2437	if (! ieee->queue_stop) goto exit;
2438
2439	ieee->queue_stop = 0;
2440
2441	if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2442		while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2443
2444			header = (struct ieee80211_hdr_3addr  *) skb->data;
2445
2446			header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2447
2448			if (ieee->seq_ctrl[0] == 0xFFF)
2449				ieee->seq_ctrl[0] = 0;
2450			else
2451				ieee->seq_ctrl[0]++;
2452
2453			ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2454			//dev_kfree_skb_any(skb);//edit by thomas
2455		}
2456	}
2457	if (!ieee->queue_stop && ieee->tx_pending.txb)
2458		ieee80211_resume_tx(ieee);
2459
2460	if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2461		ieee->softmac_stats.swtxawake++;
2462		netif_wake_queue(ieee->dev);
2463	}
2464
2465exit :
2466	spin_unlock_irqrestore(&ieee->lock,flags);
2467}
2468
2469
2470void ieee80211_stop_queue(struct ieee80211_device *ieee)
2471{
2472	//unsigned long flags;
2473	//spin_lock_irqsave(&ieee->lock,flags);
2474
2475	if (! netif_queue_stopped(ieee->dev)){
2476		netif_stop_queue(ieee->dev);
2477		ieee->softmac_stats.swtxstop++;
2478	}
2479	ieee->queue_stop = 1;
2480	//spin_unlock_irqrestore(&ieee->lock,flags);
2481
2482}
2483
2484
2485inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2486{
2487
2488	get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2489
2490	/* an IBSS cell address must have the two less significant
2491	 * bits of the first byte = 2
2492	 */
2493	ieee->current_network.bssid[0] &= ~0x01;
2494	ieee->current_network.bssid[0] |= 0x02;
2495}
2496
2497/* called in user context only */
2498void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2499{
2500	ieee->assoc_id = 1;
2501
2502	if (ieee->current_network.ssid_len == 0){
2503		strncpy(ieee->current_network.ssid,
2504			IEEE80211_DEFAULT_TX_ESSID,
2505			IW_ESSID_MAX_SIZE);
2506
2507		ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2508		ieee->ssid_set = 1;
2509	}
2510
2511	memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2512
2513	ieee->set_chan(ieee->dev, ieee->current_network.channel);
2514	ieee->state = IEEE80211_LINKED;
2515	ieee->link_change(ieee->dev);
2516	notify_wx_assoc_event(ieee);
2517
2518	if (ieee->data_hard_resume)
2519		ieee->data_hard_resume(ieee->dev);
2520
2521	netif_carrier_on(ieee->dev);
2522}
2523
2524void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2525{
2526	if(ieee->raw_tx){
2527
2528		if (ieee->data_hard_resume)
2529			ieee->data_hard_resume(ieee->dev);
2530
2531		netif_carrier_on(ieee->dev);
2532	}
2533}
2534#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2535void ieee80211_start_ibss_wq(struct work_struct *work)
2536{
2537
2538        struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2539        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2540#else
2541void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2542{
2543#endif
2544	/* iwconfig mode ad-hoc will schedule this and return
2545	 * on the other hand this will block further iwconfig SET
2546	 * operations because of the wx_sem hold.
2547	 * Anyway some most set operations set a flag to speed-up
2548	 * (abort) this wq (when syncro scanning) before sleeping
2549	 * on the semaphore
2550	 */
2551	if(!ieee->proto_started){
2552		printk("==========oh driver down return\n");
2553		return;
2554	}
2555	down(&ieee->wx_sem);
2556
2557	if (ieee->current_network.ssid_len == 0){
2558		strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2559		ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2560		ieee->ssid_set = 1;
2561	}
2562
2563	/* check if we have this cell in our network list */
2564	ieee80211_softmac_check_all_nets(ieee);
2565
2566
2567#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.
2568//	if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2569	if (ieee->state == IEEE80211_NOLINK)
2570		ieee->current_network.channel = 6;
2571#endif
2572	/* if not then the state is not linked. Maybe the user swithced to
2573	 * ad-hoc mode just after being in monitor mode, or just after
2574	 * being very few time in managed mode (so the card have had no
2575	 * time to scan all the chans..) or we have just run up the iface
2576	 * after setting ad-hoc mode. So we have to give another try..
2577	 * Here, in ibss mode, should be safe to do this without extra care
2578	 * (in bss mode we had to make sure no-one tryed to associate when
2579	 * we had just checked the ieee->state and we was going to start the
2580	 * scan) beacause in ibss mode the ieee80211_new_net function, when
2581	 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2582	 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2583	 * scan, that will stop at the first round because it sees the state
2584	 * associated.
2585	 */
2586	if (ieee->state == IEEE80211_NOLINK)
2587		ieee80211_start_scan_syncro(ieee);
2588
2589	/* the network definitively is not here.. create a new cell */
2590	if (ieee->state == IEEE80211_NOLINK){
2591		printk("creating new IBSS cell\n");
2592		if(!ieee->wap_set)
2593			ieee80211_randomize_cell(ieee);
2594
2595		if(ieee->modulation & IEEE80211_CCK_MODULATION){
2596
2597			ieee->current_network.rates_len = 4;
2598
2599			ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2600			ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2601			ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2602			ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2603
2604		}else
2605			ieee->current_network.rates_len = 0;
2606
2607		if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2608			ieee->current_network.rates_ex_len = 8;
2609
2610			ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2611			ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2612			ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2613			ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2614			ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2615			ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2616			ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2617			ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2618
2619			ieee->rate = 108;
2620		}else{
2621			ieee->current_network.rates_ex_len = 0;
2622			ieee->rate = 22;
2623		}
2624
2625		// By default, WMM function will be disabled in IBSS mode
2626		ieee->current_network.QoS_Enable = 0;
2627		ieee->SetWirelessMode(ieee->dev, IEEE_G);
2628		ieee->current_network.atim_window = 0;
2629		ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2630		if(ieee->short_slot)
2631			ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2632
2633	}
2634
2635	ieee->state = IEEE80211_LINKED;
2636
2637	ieee->set_chan(ieee->dev, ieee->current_network.channel);
2638	ieee->link_change(ieee->dev);
2639
2640	notify_wx_assoc_event(ieee);
2641
2642	ieee80211_start_send_beacons(ieee);
2643
2644	if (ieee->data_hard_resume)
2645		ieee->data_hard_resume(ieee->dev);
2646	netif_carrier_on(ieee->dev);
2647
2648	up(&ieee->wx_sem);
2649}
2650
2651inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2652{
2653#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2654	queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2655#else
2656	schedule_task(&ieee->start_ibss_wq);
2657#endif
2658}
2659
2660/* this is called only in user context, with wx_sem held */
2661void ieee80211_start_bss(struct ieee80211_device *ieee)
2662{
2663	unsigned long flags;
2664#ifdef ENABLE_DOT11D
2665	//
2666	// Ref: 802.11d 11.1.3.3
2667	// STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2668	//
2669	if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2670	{
2671		if(! ieee->bGlobalDomain)
2672		{
2673			return;
2674		}
2675	}
2676#endif
2677	/* check if we have already found the net we
2678	 * are interested in (if any).
2679	 * if not (we are disassociated and we are not
2680	 * in associating / authenticating phase) start the background scanning.
2681	 */
2682	ieee80211_softmac_check_all_nets(ieee);
2683
2684	/* ensure no-one start an associating process (thus setting
2685	 * the ieee->state to ieee80211_ASSOCIATING) while we
2686	 * have just cheked it and we are going to enable scan.
2687	 * The ieee80211_new_net function is always called with
2688	 * lock held (from both ieee80211_softmac_check_all_nets and
2689	 * the rx path), so we cannot be in the middle of such function
2690	 */
2691	spin_lock_irqsave(&ieee->lock, flags);
2692
2693	if (ieee->state == IEEE80211_NOLINK){
2694		ieee->actscanning = true;
2695		ieee80211_start_scan(ieee);
2696	}
2697	spin_unlock_irqrestore(&ieee->lock, flags);
2698}
2699
2700/* called only in userspace context */
2701void ieee80211_disassociate(struct ieee80211_device *ieee)
2702{
2703
2704
2705	netif_carrier_off(ieee->dev);
2706	if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2707			ieee80211_reset_queue(ieee);
2708
2709	if (ieee->data_hard_stop)
2710			ieee->data_hard_stop(ieee->dev);
2711#ifdef ENABLE_DOT11D
2712	if(IS_DOT11D_ENABLE(ieee))
2713		Dot11d_Reset(ieee);
2714#endif
2715	ieee->state = IEEE80211_NOLINK;
2716	ieee->is_set_key = false;
2717	ieee->link_change(ieee->dev);
2718	//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2719	notify_wx_assoc_event(ieee);
2720
2721}
2722#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2723void ieee80211_associate_retry_wq(struct work_struct *work)
2724{
2725        struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2726        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2727#else
2728void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2729{
2730#endif
2731	unsigned long flags;
2732
2733	down(&ieee->wx_sem);
2734	if(!ieee->proto_started)
2735		goto exit;
2736
2737	if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2738		goto exit;
2739
2740	/* until we do not set the state to IEEE80211_NOLINK
2741	* there are no possibility to have someone else trying
2742	* to start an association procdure (we get here with
2743	* ieee->state = IEEE80211_ASSOCIATING).
2744	* When we set the state to IEEE80211_NOLINK it is possible
2745	* that the RX path run an attempt to associate, but
2746	* both ieee80211_softmac_check_all_nets and the
2747	* RX path works with ieee->lock held so there are no
2748	* problems. If we are still disassociated then start a scan.
2749	* the lock here is necessary to ensure no one try to start
2750	* an association procedure when we have just checked the
2751	* state and we are going to start the scan.
2752	*/
2753	ieee->state = IEEE80211_NOLINK;
2754
2755	ieee80211_softmac_check_all_nets(ieee);
2756
2757	spin_lock_irqsave(&ieee->lock, flags);
2758
2759	if(ieee->state == IEEE80211_NOLINK)
2760		ieee80211_start_scan(ieee);
2761
2762	spin_unlock_irqrestore(&ieee->lock, flags);
2763
2764exit:
2765	up(&ieee->wx_sem);
2766}
2767
2768struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2769{
2770	u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2771
2772	struct sk_buff *skb;
2773	struct ieee80211_probe_response *b;
2774
2775	skb = ieee80211_probe_resp(ieee, broadcast_addr);
2776
2777	if (!skb)
2778		return NULL;
2779
2780	b = (struct ieee80211_probe_response *) skb->data;
2781	b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2782
2783	return skb;
2784
2785}
2786
2787struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2788{
2789	struct sk_buff *skb;
2790	struct ieee80211_probe_response *b;
2791
2792	skb = ieee80211_get_beacon_(ieee);
2793	if(!skb)
2794		return NULL;
2795
2796	b = (struct ieee80211_probe_response *) skb->data;
2797	b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2798
2799	if (ieee->seq_ctrl[0] == 0xFFF)
2800		ieee->seq_ctrl[0] = 0;
2801	else
2802		ieee->seq_ctrl[0]++;
2803
2804	return skb;
2805}
2806
2807void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2808{
2809	ieee->sync_scan_hurryup = 1;
2810	down(&ieee->wx_sem);
2811	ieee80211_stop_protocol(ieee);
2812	up(&ieee->wx_sem);
2813}
2814
2815
2816void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2817{
2818	if (!ieee->proto_started)
2819		return;
2820
2821	ieee->proto_started = 0;
2822
2823	ieee80211_stop_send_beacons(ieee);
2824	del_timer_sync(&ieee->associate_timer);
2825#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2826	cancel_delayed_work(&ieee->associate_retry_wq);
2827	cancel_delayed_work(&ieee->start_ibss_wq);
2828#endif
2829	ieee80211_stop_scan(ieee);
2830
2831	ieee80211_disassociate(ieee);
2832	RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2833}
2834
2835void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2836{
2837	ieee->sync_scan_hurryup = 0;
2838	down(&ieee->wx_sem);
2839	ieee80211_start_protocol(ieee);
2840	up(&ieee->wx_sem);
2841}
2842
2843void ieee80211_start_protocol(struct ieee80211_device *ieee)
2844{
2845	short ch = 0;
2846 	int i = 0;
2847	if (ieee->proto_started)
2848		return;
2849
2850	ieee->proto_started = 1;
2851
2852	if (ieee->current_network.channel == 0){
2853		do{
2854			ch++;
2855			if (ch > MAX_CHANNEL_NUMBER)
2856				return; /* no channel found */
2857#ifdef ENABLE_DOT11D
2858		}while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2859#else
2860		}while(!ieee->channel_map[ch]);
2861#endif
2862		ieee->current_network.channel = ch;
2863	}
2864
2865	if (ieee->current_network.beacon_interval == 0)
2866		ieee->current_network.beacon_interval = 100;
2867//	printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2868//	ieee->set_chan(ieee->dev,ieee->current_network.channel);
2869
2870       	for(i = 0; i < 17; i++) {
2871	  ieee->last_rxseq_num[i] = -1;
2872	  ieee->last_rxfrag_num[i] = -1;
2873	  ieee->last_packet_time[i] = 0;
2874	}
2875
2876	ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2877
2878
2879	/* if the user set the MAC of the ad-hoc cell and then
2880	 * switch to managed mode, shall we  make sure that association
2881	 * attempts does not fail just because the user provide the essid
2882	 * and the nic is still checking for the AP MAC ??
2883	 */
2884	if (ieee->iw_mode == IW_MODE_INFRA)
2885		ieee80211_start_bss(ieee);
2886
2887	else if (ieee->iw_mode == IW_MODE_ADHOC)
2888		ieee80211_start_ibss(ieee);
2889
2890	else if (ieee->iw_mode == IW_MODE_MASTER)
2891		ieee80211_start_master_bss(ieee);
2892
2893	else if(ieee->iw_mode == IW_MODE_MONITOR)
2894		ieee80211_start_monitor_mode(ieee);
2895}
2896
2897
2898#define DRV_NAME  "Ieee80211"
2899void ieee80211_softmac_init(struct ieee80211_device *ieee)
2900{
2901	int i;
2902	memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2903
2904	ieee->state = IEEE80211_NOLINK;
2905	ieee->sync_scan_hurryup = 0;
2906	for(i = 0; i < 5; i++) {
2907	  ieee->seq_ctrl[i] = 0;
2908	}
2909#ifdef ENABLE_DOT11D
2910	ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2911	if (!ieee->pDot11dInfo)
2912		IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2913	memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
2914#endif
2915	//added for  AP roaming
2916	ieee->LinkDetectInfo.SlotNum = 2;
2917	ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2918        ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2919
2920	ieee->assoc_id = 0;
2921	ieee->queue_stop = 0;
2922	ieee->scanning = 0;
2923	ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2924	ieee->wap_set = 0;
2925	ieee->ssid_set = 0;
2926	ieee->proto_started = 0;
2927	ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2928	ieee->rate = 22;
2929	ieee->ps = IEEE80211_PS_DISABLED;
2930	ieee->sta_sleep = 0;
2931	ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2932	ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2933	ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2934	//added by amy
2935	ieee->actscanning = false;
2936	ieee->beinretry = false;
2937	ieee->is_set_key = false;
2938	init_mgmt_queue(ieee);
2939
2940	ieee->sta_edca_param[0] = 0x0000A403;
2941	ieee->sta_edca_param[1] = 0x0000A427;
2942	ieee->sta_edca_param[2] = 0x005E4342;
2943	ieee->sta_edca_param[3] = 0x002F3262;
2944	ieee->aggregation = true;
2945	ieee->enable_rx_imm_BA = 1;
2946#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
2947	init_timer(&ieee->scan_timer);
2948	ieee->scan_timer.data = (unsigned long)ieee;
2949	ieee->scan_timer.function = ieee80211_softmac_scan_cb;
2950#endif
2951	ieee->tx_pending.txb = NULL;
2952
2953	init_timer(&ieee->associate_timer);
2954	ieee->associate_timer.data = (unsigned long)ieee;
2955	ieee->associate_timer.function = ieee80211_associate_abort_cb;
2956
2957	init_timer(&ieee->beacon_timer);
2958	ieee->beacon_timer.data = (unsigned long) ieee;
2959	ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2960
2961#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2962#ifdef PF_SYNCTHREAD
2963	ieee->wq = create_workqueue(DRV_NAME,0);
2964#else
2965	ieee->wq = create_workqueue(DRV_NAME);
2966#endif
2967#endif
2968
2969#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2970#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
2971        INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2972        INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2973        INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2974        INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2975        INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2976        INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2977
2978#else
2979	INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
2980	INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
2981	INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
2982	INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
2983	INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
2984	INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
2985#endif
2986
2987#else
2988	tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
2989	tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
2990	tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
2991	tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
2992	tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
2993	tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
2994#endif
2995	sema_init(&ieee->wx_sem, 1);
2996	sema_init(&ieee->scan_sem, 1);
2997
2998	spin_lock_init(&ieee->mgmt_tx_lock);
2999	spin_lock_init(&ieee->beacon_lock);
3000
3001	tasklet_init(&ieee->ps_task,
3002	     (void(*)(unsigned long)) ieee80211_sta_ps,
3003	     (unsigned long)ieee);
3004
3005}
3006
3007void ieee80211_softmac_free(struct ieee80211_device *ieee)
3008{
3009	down(&ieee->wx_sem);
3010#ifdef ENABLE_DOT11D
3011	if(NULL != ieee->pDot11dInfo)
3012	{
3013		kfree(ieee->pDot11dInfo);
3014		ieee->pDot11dInfo = NULL;
3015	}
3016#endif
3017	del_timer_sync(&ieee->associate_timer);
3018
3019#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3020	cancel_delayed_work(&ieee->associate_retry_wq);
3021	destroy_workqueue(ieee->wq);
3022#endif
3023
3024	up(&ieee->wx_sem);
3025}
3026
3027/********************************************************
3028 * Start of WPA code.                                   *
3029 * this is stolen from the ipw2200 driver               *
3030 ********************************************************/
3031
3032
3033static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3034{
3035	/* This is called when wpa_supplicant loads and closes the driver
3036	 * interface. */
3037	printk("%s WPA\n",value ? "enabling" : "disabling");
3038	ieee->wpa_enabled = value;
3039	return 0;
3040}
3041
3042
3043void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3044{
3045	/* make sure WPA is enabled */
3046	ieee80211_wpa_enable(ieee, 1);
3047
3048	ieee80211_disassociate(ieee);
3049}
3050
3051
3052static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3053{
3054
3055	int ret = 0;
3056
3057	switch (command) {
3058	case IEEE_MLME_STA_DEAUTH:
3059		// silently ignore
3060		break;
3061
3062	case IEEE_MLME_STA_DISASSOC:
3063		ieee80211_disassociate(ieee);
3064		break;
3065
3066	default:
3067		printk("Unknown MLME request: %d\n", command);
3068		ret = -EOPNOTSUPP;
3069	}
3070
3071	return ret;
3072}
3073
3074
3075static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3076			      struct ieee_param *param, int plen)
3077{
3078	u8 *buf;
3079
3080	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3081	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3082		return -EINVAL;
3083
3084	if (param->u.wpa_ie.len) {
3085		buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
3086		if (buf == NULL)
3087			return -ENOMEM;
3088
3089		memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
3090		kfree(ieee->wpa_ie);
3091		ieee->wpa_ie = buf;
3092		ieee->wpa_ie_len = param->u.wpa_ie.len;
3093	} else {
3094		kfree(ieee->wpa_ie);
3095		ieee->wpa_ie = NULL;
3096		ieee->wpa_ie_len = 0;
3097	}
3098
3099	ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3100	return 0;
3101}
3102
3103#define AUTH_ALG_OPEN_SYSTEM			0x1
3104#define AUTH_ALG_SHARED_KEY			0x2
3105
3106static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3107{
3108
3109	struct ieee80211_security sec = {
3110		.flags = SEC_AUTH_MODE,
3111	};
3112	int ret = 0;
3113
3114	if (value & AUTH_ALG_SHARED_KEY) {
3115		sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3116		ieee->open_wep = 0;
3117		ieee->auth_mode = 1;
3118	} else if (value & AUTH_ALG_OPEN_SYSTEM){
3119		sec.auth_mode = WLAN_AUTH_OPEN;
3120		ieee->open_wep = 1;
3121		ieee->auth_mode = 0;
3122	}
3123	else if (value & IW_AUTH_ALG_LEAP){
3124		sec.auth_mode = WLAN_AUTH_LEAP;
3125		ieee->open_wep = 1;
3126		ieee->auth_mode = 2;
3127	}
3128
3129
3130	if (ieee->set_security)
3131		ieee->set_security(ieee->dev, &sec);
3132	//else
3133	//	ret = -EOPNOTSUPP;
3134
3135	return ret;
3136}
3137
3138static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3139{
3140	int ret=0;
3141	unsigned long flags;
3142
3143	switch (name) {
3144	case IEEE_PARAM_WPA_ENABLED:
3145		ret = ieee80211_wpa_enable(ieee, value);
3146		break;
3147
3148	case IEEE_PARAM_TKIP_COUNTERMEASURES:
3149		ieee->tkip_countermeasures=value;
3150		break;
3151
3152	case IEEE_PARAM_DROP_UNENCRYPTED: {
3153		/* HACK:
3154		 *
3155		 * wpa_supplicant calls set_wpa_enabled when the driver
3156		 * is loaded and unloaded, regardless of if WPA is being
3157		 * used.  No other calls are made which can be used to
3158		 * determine if encryption will be used or not prior to
3159		 * association being expected.  If encryption is not being
3160		 * used, drop_unencrypted is set to false, else true -- we
3161		 * can use this to determine if the CAP_PRIVACY_ON bit should
3162		 * be set.
3163		 */
3164		struct ieee80211_security sec = {
3165			.flags = SEC_ENABLED,
3166			.enabled = value,
3167		};
3168 		ieee->drop_unencrypted = value;
3169		/* We only change SEC_LEVEL for open mode. Others
3170		 * are set by ipw_wpa_set_encryption.
3171		 */
3172		if (!value) {
3173			sec.flags |= SEC_LEVEL;
3174			sec.level = SEC_LEVEL_0;
3175		}
3176		else {
3177			sec.flags |= SEC_LEVEL;
3178			sec.level = SEC_LEVEL_1;
3179		}
3180		if (ieee->set_security)
3181			ieee->set_security(ieee->dev, &sec);
3182		break;
3183	}
3184
3185	case IEEE_PARAM_PRIVACY_INVOKED:
3186		ieee->privacy_invoked=value;
3187		break;
3188
3189	case IEEE_PARAM_AUTH_ALGS:
3190		ret = ieee80211_wpa_set_auth_algs(ieee, value);
3191		break;
3192
3193	case IEEE_PARAM_IEEE_802_1X:
3194		ieee->ieee802_1x=value;
3195		break;
3196	case IEEE_PARAM_WPAX_SELECT:
3197		// added for WPA2 mixed mode
3198		spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3199		ieee->wpax_type_set = 1;
3200		ieee->wpax_type_notify = value;
3201		spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3202		break;
3203
3204	default:
3205		printk("Unknown WPA param: %d\n",name);
3206		ret = -EOPNOTSUPP;
3207	}
3208
3209	return ret;
3210}
3211
3212/* implementation borrowed from hostap driver */
3213
3214static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3215				  struct ieee_param *param, int param_len)
3216{
3217	int ret = 0;
3218
3219	struct ieee80211_crypto_ops *ops;
3220	struct ieee80211_crypt_data **crypt;
3221
3222	struct ieee80211_security sec = {
3223		.flags = 0,
3224	};
3225
3226	param->u.crypt.err = 0;
3227	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3228
3229	if (param_len !=
3230	    (int) ((char *) param->u.crypt.key - (char *) param) +
3231	    param->u.crypt.key_len) {
3232		printk("Len mismatch %d, %d\n", param_len,
3233			       param->u.crypt.key_len);
3234		return -EINVAL;
3235	}
3236	if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3237	    param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3238	    param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3239		if (param->u.crypt.idx >= WEP_KEYS)
3240			return -EINVAL;
3241		crypt = &ieee->crypt[param->u.crypt.idx];
3242	} else {
3243		return -EINVAL;
3244	}
3245
3246	if (strcmp(param->u.crypt.alg, "none") == 0) {
3247		if (crypt) {
3248			sec.enabled = 0;
3249			// FIXME FIXME
3250			//sec.encrypt = 0;
3251			sec.level = SEC_LEVEL_0;
3252			sec.flags |= SEC_ENABLED | SEC_LEVEL;
3253			ieee80211_crypt_delayed_deinit(ieee, crypt);
3254		}
3255		goto done;
3256	}
3257	sec.enabled = 1;
3258// FIXME FIXME
3259//	sec.encrypt = 1;
3260	sec.flags |= SEC_ENABLED;
3261
3262	/* IPW HW cannot build TKIP MIC, host decryption still needed. */
3263	if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3264	    strcmp(param->u.crypt.alg, "TKIP"))
3265		goto skip_host_crypt;
3266
3267	ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3268	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3269		request_module("ieee80211_crypt_wep");
3270		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3271		//set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3272	} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3273		request_module("ieee80211_crypt_tkip");
3274		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3275	} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3276		request_module("ieee80211_crypt_ccmp");
3277		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3278	}
3279	if (ops == NULL) {
3280		printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3281		param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3282		ret = -EINVAL;
3283		goto done;
3284	}
3285
3286	if (*crypt == NULL || (*crypt)->ops != ops) {
3287		struct ieee80211_crypt_data *new_crypt;
3288
3289		ieee80211_crypt_delayed_deinit(ieee, crypt);
3290
3291		new_crypt = (struct ieee80211_crypt_data *)
3292			kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3293		if (new_crypt == NULL) {
3294			ret = -ENOMEM;
3295			goto done;
3296		}
3297		memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3298		new_crypt->ops = ops;
3299#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
3300		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3301#else
3302		if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
3303#endif
3304			new_crypt->priv =
3305				new_crypt->ops->init(param->u.crypt.idx);
3306
3307		if (new_crypt->priv == NULL) {
3308			kfree(new_crypt);
3309			param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3310			ret = -EINVAL;
3311			goto done;
3312		}
3313
3314		*crypt = new_crypt;
3315	}
3316
3317	if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3318	    (*crypt)->ops->set_key(param->u.crypt.key,
3319				   param->u.crypt.key_len, param->u.crypt.seq,
3320				   (*crypt)->priv) < 0) {
3321		printk("key setting failed\n");
3322		param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3323		ret = -EINVAL;
3324		goto done;
3325	}
3326
3327 skip_host_crypt:
3328	if (param->u.crypt.set_tx) {
3329		ieee->tx_keyidx = param->u.crypt.idx;
3330		sec.active_key = param->u.crypt.idx;
3331		sec.flags |= SEC_ACTIVE_KEY;
3332	} else
3333		sec.flags &= ~SEC_ACTIVE_KEY;
3334
3335	if (param->u.crypt.alg != NULL) {
3336		memcpy(sec.keys[param->u.crypt.idx],
3337		       param->u.crypt.key,
3338		       param->u.crypt.key_len);
3339		sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3340		sec.flags |= (1 << param->u.crypt.idx);
3341
3342		if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3343			sec.flags |= SEC_LEVEL;
3344			sec.level = SEC_LEVEL_1;
3345		} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3346			sec.flags |= SEC_LEVEL;
3347			sec.level = SEC_LEVEL_2;
3348		} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3349			sec.flags |= SEC_LEVEL;
3350			sec.level = SEC_LEVEL_3;
3351		}
3352	}
3353 done:
3354	if (ieee->set_security)
3355		ieee->set_security(ieee->dev, &sec);
3356
3357	/* Do not reset port if card is in Managed mode since resetting will
3358	 * generate new IEEE 802.11 authentication which may end up in looping
3359	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
3360	 * configuration (for example... Prism2), implement the reset_port in
3361	 * the callbacks structures used to initialize the 802.11 stack. */
3362	if (ieee->reset_on_keychange &&
3363	    ieee->iw_mode != IW_MODE_INFRA &&
3364	    ieee->reset_port &&
3365	    ieee->reset_port(ieee->dev)) {
3366		printk("reset_port failed\n");
3367		param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3368		return -EINVAL;
3369	}
3370
3371	return ret;
3372}
3373
3374inline struct sk_buff *ieee80211_disassociate_skb(
3375							struct ieee80211_network *beacon,
3376							struct ieee80211_device *ieee,
3377							u8	asRsn)
3378{
3379	struct sk_buff *skb;
3380	struct ieee80211_disassoc *disass;
3381
3382	skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3383	if (!skb)
3384		return NULL;
3385
3386	disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3387	disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3388	disass->header.duration_id = 0;
3389
3390	memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3391	memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3392	memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3393
3394	disass->reason = asRsn;
3395	return skb;
3396}
3397
3398
3399void
3400SendDisassociation(
3401		struct ieee80211_device *ieee,
3402		u8* 					asSta,
3403		u8						asRsn
3404)
3405{
3406		struct ieee80211_network *beacon = &ieee->current_network;
3407		struct sk_buff *skb;
3408		skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3409		if (skb){
3410				softmac_mgmt_xmit(skb, ieee);
3411				//dev_kfree_skb_any(skb);//edit by thomas
3412		}
3413}
3414
3415int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3416{
3417	struct ieee_param *param;
3418	int ret=0;
3419
3420	down(&ieee->wx_sem);
3421	//IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3422
3423	if (p->length < sizeof(struct ieee_param) || !p->pointer){
3424		ret = -EINVAL;
3425		goto out;
3426	}
3427
3428	param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3429	if (param == NULL){
3430		ret = -ENOMEM;
3431		goto out;
3432	}
3433	if (copy_from_user(param, p->pointer, p->length)) {
3434		kfree(param);
3435		ret = -EFAULT;
3436		goto out;
3437	}
3438
3439	switch (param->cmd) {
3440
3441	case IEEE_CMD_SET_WPA_PARAM:
3442		ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3443					param->u.wpa_param.value);
3444		break;
3445
3446	case IEEE_CMD_SET_WPA_IE:
3447		ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3448		break;
3449
3450	case IEEE_CMD_SET_ENCRYPTION:
3451		ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3452		break;
3453
3454	case IEEE_CMD_MLME:
3455		ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3456				   param->u.mlme.reason_code);
3457		break;
3458
3459	default:
3460		printk("Unknown WPA supplicant request: %d\n",param->cmd);
3461		ret = -EOPNOTSUPP;
3462		break;
3463	}
3464
3465	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3466		ret = -EFAULT;
3467
3468	kfree(param);
3469out:
3470	up(&ieee->wx_sem);
3471
3472	return ret;
3473}
3474
3475void notify_wx_assoc_event(struct ieee80211_device *ieee)
3476{
3477	union iwreq_data wrqu;
3478	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3479	if (ieee->state == IEEE80211_LINKED)
3480		memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3481	else
3482		memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3483	wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3484}
3485
3486#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3487EXPORT_SYMBOL(ieee80211_get_beacon);
3488EXPORT_SYMBOL(ieee80211_wake_queue);
3489EXPORT_SYMBOL(ieee80211_stop_queue);
3490EXPORT_SYMBOL(ieee80211_reset_queue);
3491EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3492EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3493EXPORT_SYMBOL(ieee80211_is_shortslot);
3494EXPORT_SYMBOL(ieee80211_is_54g);
3495EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3496EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3497EXPORT_SYMBOL(ieee80211_softmac_xmit);
3498EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3499EXPORT_SYMBOL(notify_wx_assoc_event);
3500EXPORT_SYMBOL(SendDisassociation);
3501EXPORT_SYMBOL(ieee80211_disassociate);
3502EXPORT_SYMBOL(ieee80211_start_send_beacons);
3503EXPORT_SYMBOL(ieee80211_stop_scan);
3504EXPORT_SYMBOL(ieee80211_send_probe_requests);
3505EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3506EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3507#else
3508EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3509EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue);
3510EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue);
3511EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3512EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3513EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3514EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3515EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3516EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3517EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3518EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3519EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3520EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3521EXPORT_SYMBOL_NOVERS(SendDisassociation);
3522EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3523EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3524EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3525EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3526EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3527EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3528#endif
3529//EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);
3530