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