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