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