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