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