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