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