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