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