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 static 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 		*(tag++) = MFIE_TYPE_IBSS_SET;
808 		*(tag++) = 2;
809 
810 		put_unaligned_le16(ieee->current_network.atim_window,
811 				   (u8 *)tag);
812 		tag+=2;
813 	}
814 
815 	if (erp_len) {
816 		*(tag++) = MFIE_TYPE_ERP;
817 		*(tag++) = 1;
818 		*(tag++) = erpinfo_content;
819 	}
820 	if (rate_ex_len) {
821 		*(tag++) = MFIE_TYPE_RATES_EX;
822 		*(tag++) = rate_ex_len-2;
823 		memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
824 		tag+=rate_ex_len-2;
825 	}
826 
827 	if (wpa_ie_len)
828 	{
829 		if (ieee->iw_mode == IW_MODE_ADHOC)
830 		{//as Windows will set pairwise key same as the group key which is not allowed in Linux, so set this for IOT issue. WB 2008.07.07
831 			memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
832 		}
833 		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
834 		tag += wpa_ie_len;
835 	}
836 
837 	//skb->dev = ieee->dev;
838 	return skb;
839 }
840 
841 
ieee80211_assoc_resp(struct ieee80211_device * ieee,u8 * dest)842 static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
843 					    u8 *dest)
844 {
845 	struct sk_buff *skb;
846 	u8 *tag;
847 
848 	struct ieee80211_crypt_data *crypt;
849 	struct ieee80211_assoc_response_frame *assoc;
850 	short encrypt;
851 
852 	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
853 	int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
854 
855 	skb = dev_alloc_skb(len);
856 
857 	if (!skb)
858 		return NULL;
859 
860 	skb_reserve(skb, ieee->tx_headroom);
861 
862 	assoc = (struct ieee80211_assoc_response_frame *)
863 		skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
864 
865 	assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
866 	memcpy(assoc->header.addr1, dest,ETH_ALEN);
867 	memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
868 	memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
869 	assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
870 		WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
871 
872 
873 	if(ieee->short_slot)
874 		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
875 
876 	if (ieee->host_encrypt)
877 		crypt = ieee->crypt[ieee->tx_keyidx];
878 	else crypt = NULL;
879 
880 	encrypt = crypt && crypt->ops;
881 
882 	if (encrypt)
883 		assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
884 
885 	assoc->status = 0;
886 	assoc->aid = cpu_to_le16(ieee->assoc_id);
887 	if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
888 	else ieee->assoc_id++;
889 
890 	tag = (u8 *) skb_put(skb, rate_len);
891 
892 	ieee80211_MFIE_Brate(ieee, &tag);
893 	ieee80211_MFIE_Grate(ieee, &tag);
894 
895 	return skb;
896 }
897 
ieee80211_auth_resp(struct ieee80211_device * ieee,int status,u8 * dest)898 static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
899 					   int status, u8 *dest)
900 {
901 	struct sk_buff *skb;
902 	struct ieee80211_authentication *auth;
903 	int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
904 
905 	skb = dev_alloc_skb(len);
906 
907 	if (!skb)
908 		return NULL;
909 
910 	skb->len = sizeof(struct ieee80211_authentication);
911 
912 	auth = (struct ieee80211_authentication *)skb->data;
913 
914 	auth->status = cpu_to_le16(status);
915 	auth->transaction = cpu_to_le16(2);
916 	auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
917 
918 	memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
919 	memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
920 	memcpy(auth->header.addr1, dest, ETH_ALEN);
921 	auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
922 	return skb;
923 
924 
925 }
926 
ieee80211_null_func(struct ieee80211_device * ieee,short pwr)927 static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
928 					   short pwr)
929 {
930 	struct sk_buff *skb;
931 	struct ieee80211_hdr_3addr *hdr;
932 
933 	skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
934 
935 	if (!skb)
936 		return NULL;
937 
938 	hdr = (struct ieee80211_hdr_3addr *)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
939 
940 	memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
941 	memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
942 	memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
943 
944 	hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
945 		IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
946 		(pwr ? IEEE80211_FCTL_PM:0));
947 
948 	return skb;
949 
950 
951 }
952 
953 
ieee80211_resp_to_assoc_rq(struct ieee80211_device * ieee,u8 * dest)954 static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
955 {
956 	struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
957 
958 	if (buf)
959 		softmac_mgmt_xmit(buf, ieee);
960 }
961 
962 
ieee80211_resp_to_auth(struct ieee80211_device * ieee,int s,u8 * dest)963 static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
964 				   u8 *dest)
965 {
966 	struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
967 
968 	if (buf)
969 		softmac_mgmt_xmit(buf, ieee);
970 }
971 
972 
ieee80211_resp_to_probe(struct ieee80211_device * ieee,u8 * dest)973 static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
974 {
975 
976 
977 	struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
978 	if (buf)
979 		softmac_mgmt_xmit(buf, ieee);
980 }
981 
982 
ieee80211_association_req(struct ieee80211_network * beacon,struct ieee80211_device * ieee)983 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
984 {
985 	struct sk_buff *skb;
986 	//unsigned long flags;
987 
988 	struct ieee80211_assoc_request_frame *hdr;
989 	u8 *tag;//,*rsn_ie;
990 	//short info_addr = 0;
991 	//int i;
992 	//u16 suite_count = 0;
993 	//u8 suit_select = 0;
994 	//unsigned int wpa_len = beacon->wpa_ie_len;
995 	//for HT
996 	u8 *ht_cap_buf = NULL;
997 	u8 ht_cap_len=0;
998 	u8 *realtek_ie_buf=NULL;
999 	u8 realtek_ie_len=0;
1000 	int wpa_ie_len= ieee->wpa_ie_len;
1001 	unsigned int ckip_ie_len=0;
1002 	unsigned int ccxrm_ie_len=0;
1003 	unsigned int cxvernum_ie_len=0;
1004 	struct ieee80211_crypt_data *crypt;
1005 	int encrypt;
1006 
1007 	unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1008 	unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1009 #ifdef THOMAS_TURBO
1010 	unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1011 #endif
1012 
1013 	int len = 0;
1014 
1015 	crypt = ieee->crypt[ieee->tx_keyidx];
1016 	encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1017 
1018 	//Include High Throuput capability && Realtek proprietary
1019 	if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1020 	{
1021 		ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
1022 		ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1023 		HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1024 		if (ieee->pHTInfo->bCurrentRT2RTAggregation)
1025 		{
1026 			realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1027 			realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1028 			HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1029 
1030 		}
1031 	}
1032 	if (ieee->qos_support) {
1033 		wmm_info_len = beacon->qos_data.supported?9:0;
1034 	}
1035 
1036 
1037 	if (beacon->bCkipSupported)
1038 	{
1039 		ckip_ie_len = 30+2;
1040 	}
1041 	if (beacon->bCcxRmEnable)
1042 	{
1043 		ccxrm_ie_len = 6+2;
1044 	}
1045 	if (beacon->BssCcxVerNumber >= 2)
1046 		cxvernum_ie_len = 5+2;
1047 
1048 #ifdef THOMAS_TURBO
1049 	len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1050 		+ beacon->ssid_len//essid tagged val
1051 		+ rate_len//rates tagged val
1052 		+ wpa_ie_len
1053 		+ wmm_info_len
1054 		+ turbo_info_len
1055 		+ ht_cap_len
1056 		+ realtek_ie_len
1057 		+ ckip_ie_len
1058 		+ ccxrm_ie_len
1059 		+ cxvernum_ie_len
1060 		+ ieee->tx_headroom;
1061 #else
1062 	len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1063 		+ beacon->ssid_len//essid tagged val
1064 		+ rate_len//rates tagged val
1065 		+ wpa_ie_len
1066 		+ wmm_info_len
1067 		+ ht_cap_len
1068 		+ realtek_ie_len
1069 		+ ckip_ie_len
1070 		+ ccxrm_ie_len
1071 		+ cxvernum_ie_len
1072 		+ ieee->tx_headroom;
1073 #endif
1074 
1075 	skb = dev_alloc_skb(len);
1076 
1077 	if (!skb)
1078 		return NULL;
1079 
1080 	skb_reserve(skb, ieee->tx_headroom);
1081 
1082 	hdr = (struct ieee80211_assoc_request_frame *)
1083 		skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1084 
1085 
1086 	hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1087 	hdr->header.duration_id= 37; //FIXME
1088 	memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1089 	memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1090 	memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1091 
1092 	memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1093 
1094 	hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1095 	if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1096 		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1097 
1098 	if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1099 		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1100 
1101 	if(ieee->short_slot)
1102 		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1103 	if (wmm_info_len) //QOS
1104 		hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1105 
1106 	hdr->listen_interval = 0xa; //FIXME
1107 
1108 	hdr->info_element[0].id = MFIE_TYPE_SSID;
1109 
1110 	hdr->info_element[0].len = beacon->ssid_len;
1111 	tag = skb_put(skb, beacon->ssid_len);
1112 	memcpy(tag, beacon->ssid, beacon->ssid_len);
1113 
1114 	tag = skb_put(skb, rate_len);
1115 
1116 	ieee80211_MFIE_Brate(ieee, &tag);
1117 	ieee80211_MFIE_Grate(ieee, &tag);
1118 	// For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1119 	if (beacon->bCkipSupported) {
1120 		static u8	AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1121 		u8	CcxAironetBuf[30];
1122 		OCTET_STRING	osCcxAironetIE;
1123 
1124 		memset(CcxAironetBuf, 0, 30);
1125 		osCcxAironetIE.Octet = CcxAironetBuf;
1126 		osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1127 		//
1128 		// Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1129 		// We want to make the device type as "4500-client". 060926, by CCW.
1130 		//
1131 		memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1132 
1133 		// CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1134 		// "The CKIP negotiation is started with the associate request from the client to the access point,
1135 		//  containing an Aironet element with both the MIC and KP bits set."
1136 		osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=  (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1137 		tag = skb_put(skb, ckip_ie_len);
1138 		*tag++ = MFIE_TYPE_AIRONET;
1139 		*tag++ = osCcxAironetIE.Length;
1140 		memcpy(tag, osCcxAironetIE.Octet, osCcxAironetIE.Length);
1141 		tag += osCcxAironetIE.Length;
1142 	}
1143 
1144 	if (beacon->bCcxRmEnable)
1145 	{
1146 		static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1147 		OCTET_STRING osCcxRmCap;
1148 
1149 		osCcxRmCap.Octet = CcxRmCapBuf;
1150 		osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1151 		tag = skb_put(skb, ccxrm_ie_len);
1152 		*tag++ = MFIE_TYPE_GENERIC;
1153 		*tag++ = osCcxRmCap.Length;
1154 		memcpy(tag, osCcxRmCap.Octet, osCcxRmCap.Length);
1155 		tag += osCcxRmCap.Length;
1156 	}
1157 
1158 	if (beacon->BssCcxVerNumber >= 2) {
1159 		u8			CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1160 		OCTET_STRING	osCcxVerNum;
1161 		CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1162 		osCcxVerNum.Octet = CcxVerNumBuf;
1163 		osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1164 		tag = skb_put(skb, cxvernum_ie_len);
1165 		*tag++ = MFIE_TYPE_GENERIC;
1166 		*tag++ = osCcxVerNum.Length;
1167 		memcpy(tag, osCcxVerNum.Octet, osCcxVerNum.Length);
1168 		tag += osCcxVerNum.Length;
1169 	}
1170 	//HT cap element
1171 	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1172 		if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1173 		{
1174 			tag = skb_put(skb, ht_cap_len);
1175 			*tag++ = MFIE_TYPE_HT_CAP;
1176 			*tag++ = ht_cap_len - 2;
1177 			memcpy(tag, ht_cap_buf,ht_cap_len -2);
1178 			tag += ht_cap_len -2;
1179 		}
1180 	}
1181 
1182 
1183 	//choose what wpa_supplicant gives to associate.
1184 	tag = skb_put(skb, wpa_ie_len);
1185 	if (wpa_ie_len) {
1186 		memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1187 	}
1188 
1189 	tag = skb_put(skb, wmm_info_len);
1190 	if (wmm_info_len) {
1191 	  ieee80211_WMM_Info(ieee, &tag);
1192 	}
1193 #ifdef THOMAS_TURBO
1194 	tag = skb_put(skb, turbo_info_len);
1195 	if (turbo_info_len) {
1196 		ieee80211_TURBO_Info(ieee, &tag);
1197 	}
1198 #endif
1199 
1200 	if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1201 		if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1202 		{
1203 			tag = skb_put(skb, ht_cap_len);
1204 			*tag++ = MFIE_TYPE_GENERIC;
1205 			*tag++ = ht_cap_len - 2;
1206 			memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1207 			tag += ht_cap_len -2;
1208 		}
1209 
1210 		if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1211 			tag = skb_put(skb, realtek_ie_len);
1212 			*tag++ = MFIE_TYPE_GENERIC;
1213 			*tag++ = realtek_ie_len - 2;
1214 			memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1215 		}
1216 	}
1217 //	printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1218 //	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1219 	return skb;
1220 }
1221 
ieee80211_associate_abort(struct ieee80211_device * ieee)1222 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1223 {
1224 
1225 	unsigned long flags;
1226 	spin_lock_irqsave(&ieee->lock, flags);
1227 
1228 	ieee->associate_seq++;
1229 
1230 	/* don't scan, and avoid to have the RX path possibily
1231 	 * try again to associate. Even do not react to AUTH or
1232 	 * ASSOC response. Just wait for the retry wq to be scheduled.
1233 	 * Here we will check if there are good nets to associate
1234 	 * with, so we retry or just get back to NO_LINK and scanning
1235 	 */
1236 	if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1237 		IEEE80211_DEBUG_MGMT("Authentication failed\n");
1238 		ieee->softmac_stats.no_auth_rs++;
1239 	}else{
1240 		IEEE80211_DEBUG_MGMT("Association failed\n");
1241 		ieee->softmac_stats.no_ass_rs++;
1242 	}
1243 
1244 	ieee->state = IEEE80211_ASSOCIATING_RETRY;
1245 
1246 	queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1247 			   IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1248 
1249 	spin_unlock_irqrestore(&ieee->lock, flags);
1250 }
1251 
ieee80211_associate_abort_cb(unsigned long dev)1252 static void ieee80211_associate_abort_cb(unsigned long dev)
1253 {
1254 	ieee80211_associate_abort((struct ieee80211_device *) dev);
1255 }
1256 
1257 
ieee80211_associate_step1(struct ieee80211_device * ieee)1258 static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1259 {
1260 	struct ieee80211_network *beacon = &ieee->current_network;
1261 	struct sk_buff *skb;
1262 
1263 	IEEE80211_DEBUG_MGMT("Stopping scan\n");
1264 
1265 	ieee->softmac_stats.tx_auth_rq++;
1266 	skb=ieee80211_authentication_req(beacon, ieee, 0);
1267 
1268 	if (!skb)
1269 		ieee80211_associate_abort(ieee);
1270 	else{
1271 		ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1272 		IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1273 		//printk(KERN_WARNING "Sending authentication request\n");
1274 		softmac_mgmt_xmit(skb, ieee);
1275 		//BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1276 		if (!timer_pending(&ieee->associate_timer)) {
1277 			ieee->associate_timer.expires = jiffies + (HZ / 2);
1278 			add_timer(&ieee->associate_timer);
1279 		}
1280 		//dev_kfree_skb_any(skb);//edit by thomas
1281 	}
1282 }
1283 
ieee80211_auth_challenge(struct ieee80211_device * ieee,u8 * challenge,int chlen)1284 static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1285 				     u8 *challenge,
1286 				     int chlen)
1287 {
1288 	u8 *c;
1289 	struct sk_buff *skb;
1290 	struct ieee80211_network *beacon = &ieee->current_network;
1291 //	int hlen = sizeof(struct ieee80211_authentication);
1292 
1293 	ieee->associate_seq++;
1294 	ieee->softmac_stats.tx_auth_rq++;
1295 
1296 	skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1297 	if (!skb)
1298 		ieee80211_associate_abort(ieee);
1299 	else{
1300 		c = skb_put(skb, chlen+2);
1301 		*(c++) = MFIE_TYPE_CHALLENGE;
1302 		*(c++) = chlen;
1303 		memcpy(c, challenge, chlen);
1304 
1305 		IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1306 
1307 		ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr  ));
1308 
1309 		softmac_mgmt_xmit(skb, ieee);
1310 		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1311 		//dev_kfree_skb_any(skb);//edit by thomas
1312 	}
1313 	kfree(challenge);
1314 }
1315 
ieee80211_associate_step2(struct ieee80211_device * ieee)1316 static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1317 {
1318 	struct sk_buff *skb;
1319 	struct ieee80211_network *beacon = &ieee->current_network;
1320 
1321 	del_timer_sync(&ieee->associate_timer);
1322 
1323 	IEEE80211_DEBUG_MGMT("Sending association request\n");
1324 
1325 	ieee->softmac_stats.tx_ass_rq++;
1326 	skb=ieee80211_association_req(beacon, ieee);
1327 	if (!skb)
1328 		ieee80211_associate_abort(ieee);
1329 	else{
1330 		softmac_mgmt_xmit(skb, ieee);
1331 		mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1332 		//dev_kfree_skb_any(skb);//edit by thomas
1333 	}
1334 }
ieee80211_associate_complete_wq(struct work_struct * work)1335 static void ieee80211_associate_complete_wq(struct work_struct *work)
1336 {
1337 	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1338 	printk(KERN_INFO "Associated successfully\n");
1339 	if(ieee80211_is_54g(&ieee->current_network) &&
1340 		(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1341 
1342 		ieee->rate = 108;
1343 		printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1344 	}else{
1345 		ieee->rate = 22;
1346 		printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1347 	}
1348 	if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1349 	{
1350 		printk("Successfully associated, ht enabled\n");
1351 		HTOnAssocRsp(ieee);
1352 	}
1353 	else
1354 	{
1355 		printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1356 		memset(ieee->dot11HTOperationalRateSet, 0, 16);
1357 		//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1358 	}
1359 	ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1360 	// To prevent the immediately calling watch_dog after association.
1361 	if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1362 	{
1363 		ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1364 		ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1365 	}
1366 	ieee->link_change(ieee->dev);
1367 	if(ieee->is_silent_reset == 0){
1368 		printk("============>normal associate\n");
1369 	notify_wx_assoc_event(ieee);
1370 	}
1371 	else if(ieee->is_silent_reset == 1)
1372 	{
1373 		printk("==================>silent reset associate\n");
1374 		ieee->is_silent_reset = false;
1375 	}
1376 
1377 	if (ieee->data_hard_resume)
1378 		ieee->data_hard_resume(ieee->dev);
1379 	netif_carrier_on(ieee->dev);
1380 }
1381 
ieee80211_associate_complete(struct ieee80211_device * ieee)1382 static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1383 {
1384 //	int i;
1385 //	struct net_device* dev = ieee->dev;
1386 	del_timer_sync(&ieee->associate_timer);
1387 
1388 	ieee->state = IEEE80211_LINKED;
1389 	//ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1390 	queue_work(ieee->wq, &ieee->associate_complete_wq);
1391 }
1392 
ieee80211_associate_procedure_wq(struct work_struct * work)1393 static void ieee80211_associate_procedure_wq(struct work_struct *work)
1394 {
1395 	struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1396 	ieee->sync_scan_hurryup = 1;
1397 	down(&ieee->wx_sem);
1398 
1399 	if (ieee->data_hard_stop)
1400 		ieee->data_hard_stop(ieee->dev);
1401 
1402 	ieee80211_stop_scan(ieee);
1403 	printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1404 	//ieee->set_chan(ieee->dev, ieee->current_network.channel);
1405 	HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1406 
1407 	ieee->associate_seq = 1;
1408 	ieee80211_associate_step1(ieee);
1409 
1410 	up(&ieee->wx_sem);
1411 }
1412 
ieee80211_softmac_new_net(struct ieee80211_device * ieee,struct ieee80211_network * net)1413 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1414 {
1415 	u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1416 	int tmp_ssid_len = 0;
1417 
1418 	short apset, ssidset, ssidbroad, apmatch, ssidmatch;
1419 
1420 	/* we are interested in new new only if we are not associated
1421 	 * and we are not associating / authenticating
1422 	 */
1423 	if (ieee->state != IEEE80211_NOLINK)
1424 		return;
1425 
1426 	if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1427 		return;
1428 
1429 	if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1430 		return;
1431 
1432 
1433 	if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
1434 		/* if the user specified the AP MAC, we need also the essid
1435 		 * This could be obtained by beacons or, if the network does not
1436 		 * broadcast it, it can be put manually.
1437 		 */
1438 		apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1439 		ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1440 		ssidbroad =  !(net->ssid_len == 0 || net->ssid[0]== '\0');
1441 		apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1442 		ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1443 				(!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1444 
1445 
1446 		if (	/* if the user set the AP check if match.
1447 			 * if the network does not broadcast essid we check the user supplyed ANY essid
1448 			 * if the network does broadcast and the user does not set essid it is OK
1449 			 * if the network does broadcast and the user did set essid chech if essid match
1450 			 */
1451 			(apset && apmatch &&
1452 				((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1453 			/* if the ap is not set, check that the user set the bssid
1454 			 * and the network does broadcast and that those two bssid matches
1455 			 */
1456 			(!apset && ssidset && ssidbroad && ssidmatch)
1457 			){
1458 				/* if the essid is hidden replace it with the
1459 				* essid provided by the user.
1460 				*/
1461 				if (!ssidbroad) {
1462 					strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1463 					tmp_ssid_len = ieee->current_network.ssid_len;
1464 				}
1465 				memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1466 
1467 				if (!ssidbroad) {
1468 					strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1469 					ieee->current_network.ssid_len = tmp_ssid_len;
1470 				}
1471 				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);
1472 
1473 				//ieee->pHTInfo->IOTAction = 0;
1474 				HTResetIOTSetting(ieee->pHTInfo);
1475 				if (ieee->iw_mode == IW_MODE_INFRA){
1476 					/* Join the network for the first time */
1477 					ieee->AsocRetryCount = 0;
1478 					//for HT by amy 080514
1479 					if((ieee->current_network.qos_data.supported == 1) &&
1480 					  // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1481 					   ieee->current_network.bssht.bdSupportHT)
1482 /*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.*/
1483 					{
1484 					//	ieee->pHTInfo->bCurrentHTSupport = true;
1485 						HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1486 					}
1487 					else
1488 					{
1489 						ieee->pHTInfo->bCurrentHTSupport = false;
1490 					}
1491 
1492 					ieee->state = IEEE80211_ASSOCIATING;
1493 					queue_work(ieee->wq, &ieee->associate_procedure_wq);
1494 				}else{
1495 					if(ieee80211_is_54g(&ieee->current_network) &&
1496 						(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1497 						ieee->rate = 108;
1498 						ieee->SetWirelessMode(ieee->dev, IEEE_G);
1499 						printk(KERN_INFO"Using G rates\n");
1500 					}else{
1501 						ieee->rate = 22;
1502 						ieee->SetWirelessMode(ieee->dev, IEEE_B);
1503 						printk(KERN_INFO"Using B rates\n");
1504 					}
1505 					memset(ieee->dot11HTOperationalRateSet, 0, 16);
1506 					//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1507 					ieee->state = IEEE80211_LINKED;
1508 				}
1509 
1510 		}
1511 	}
1512 
1513 }
1514 
ieee80211_softmac_check_all_nets(struct ieee80211_device * ieee)1515 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1516 {
1517 	unsigned long flags;
1518 	struct ieee80211_network *target;
1519 
1520 	spin_lock_irqsave(&ieee->lock, flags);
1521 
1522 	list_for_each_entry(target, &ieee->network_list, list) {
1523 
1524 		/* if the state become different that NOLINK means
1525 		 * we had found what we are searching for
1526 		 */
1527 
1528 		if (ieee->state != IEEE80211_NOLINK)
1529 			break;
1530 
1531 		if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1532 			ieee80211_softmac_new_net(ieee, target);
1533 	}
1534 
1535 	spin_unlock_irqrestore(&ieee->lock, flags);
1536 
1537 }
1538 
1539 
auth_parse(struct sk_buff * skb,u8 ** challenge,int * chlen)1540 static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1541 {
1542 	struct ieee80211_authentication *a;
1543 	u8 *t;
1544 	if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1545 		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1546 		return 0xcafe;
1547 	}
1548 	*challenge = NULL;
1549 	a = (struct ieee80211_authentication *) skb->data;
1550 	if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1551 		t = skb->data + sizeof(struct ieee80211_authentication);
1552 
1553 		if (*(t++) == MFIE_TYPE_CHALLENGE) {
1554 			*chlen = *(t++);
1555 			*challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1556 			if (!*challenge)
1557 				return -ENOMEM;
1558 		}
1559 	}
1560 
1561 	return cpu_to_le16(a->status);
1562 
1563 }
1564 
1565 
auth_rq_parse(struct sk_buff * skb,u8 * dest)1566 static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1567 {
1568 	struct ieee80211_authentication *a;
1569 
1570 	if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1571 		IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1572 		return -1;
1573 	}
1574 	a = (struct ieee80211_authentication *) skb->data;
1575 
1576 	memcpy(dest,a->header.addr2, ETH_ALEN);
1577 
1578 	if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1579 		return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1580 
1581 	return WLAN_STATUS_SUCCESS;
1582 }
1583 
probe_rq_parse(struct ieee80211_device * ieee,struct sk_buff * skb,u8 * src)1584 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1585 {
1586 	u8 *tag;
1587 	u8 *skbend;
1588 	u8 *ssid=NULL;
1589 	u8 ssidlen = 0;
1590 
1591 	struct ieee80211_hdr_3addr   *header =
1592 		(struct ieee80211_hdr_3addr   *) skb->data;
1593 
1594 	if (skb->len < sizeof (struct ieee80211_hdr_3addr  ))
1595 		return -1; /* corrupted */
1596 
1597 	memcpy(src,header->addr2, ETH_ALEN);
1598 
1599 	skbend = (u8 *)skb->data + skb->len;
1600 
1601 	tag = skb->data + sizeof (struct ieee80211_hdr_3addr  );
1602 
1603 	while (tag+1 < skbend){
1604 		if (*tag == 0) {
1605 			ssid = tag+2;
1606 			ssidlen = *(tag+1);
1607 			break;
1608 		}
1609 		tag++; /* point to the len field */
1610 		tag = tag + *(tag); /* point to the last data byte of the tag */
1611 		tag++; /* point to the next tag */
1612 	}
1613 
1614 	//IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1615 	if (ssidlen == 0) return 1;
1616 
1617 	if (!ssid) return 1; /* ssid not found in tagged param */
1618 	return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1619 
1620 }
1621 
assoc_rq_parse(struct sk_buff * skb,u8 * dest)1622 static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1623 {
1624 	struct ieee80211_assoc_request_frame *a;
1625 
1626 	if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1627 		sizeof(struct ieee80211_info_element))) {
1628 
1629 		IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1630 		return -1;
1631 	}
1632 
1633 	a = (struct ieee80211_assoc_request_frame *) skb->data;
1634 
1635 	memcpy(dest,a->header.addr2,ETH_ALEN);
1636 
1637 	return 0;
1638 }
1639 
assoc_parse(struct ieee80211_device * ieee,struct sk_buff * skb,int * aid)1640 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1641 {
1642 	struct ieee80211_assoc_response_frame *response_head;
1643 	u16 status_code;
1644 
1645 	if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1646 		IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1647 		return 0xcafe;
1648 	}
1649 
1650 	response_head = (struct ieee80211_assoc_response_frame *) skb->data;
1651 	*aid = le16_to_cpu(response_head->aid) & 0x3fff;
1652 
1653 	status_code = le16_to_cpu(response_head->status);
1654 	if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1655 	   status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1656 	   ((ieee->mode == IEEE_G) &&
1657 	    (ieee->current_network.mode == IEEE_N_24G) &&
1658 	    (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1659 		 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1660 	}else {
1661 		 ieee->AsocRetryCount = 0;
1662 	}
1663 
1664 	return le16_to_cpu(response_head->status);
1665 }
1666 
1667 static inline void
ieee80211_rx_probe_rq(struct ieee80211_device * ieee,struct sk_buff * skb)1668 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1669 {
1670 	u8 dest[ETH_ALEN];
1671 
1672 	//IEEE80211DMESG("Rx probe");
1673 	ieee->softmac_stats.rx_probe_rq++;
1674 	//DMESG("Dest is "MACSTR, MAC2STR(dest));
1675 	if (probe_rq_parse(ieee, skb, dest)) {
1676 		//IEEE80211DMESG("Was for me!");
1677 		ieee->softmac_stats.tx_probe_rs++;
1678 		ieee80211_resp_to_probe(ieee, dest);
1679 	}
1680 }
1681 
1682 static inline void
ieee80211_rx_auth_rq(struct ieee80211_device * ieee,struct sk_buff * skb)1683 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1684 {
1685 	u8 dest[ETH_ALEN];
1686 	int status;
1687 	//IEEE80211DMESG("Rx probe");
1688 	ieee->softmac_stats.rx_auth_rq++;
1689 
1690 	status = auth_rq_parse(skb, dest);
1691 	if (status != -1) {
1692 		ieee80211_resp_to_auth(ieee, status, dest);
1693 	}
1694 	//DMESG("Dest is "MACSTR, MAC2STR(dest));
1695 
1696 }
1697 
1698 static inline void
ieee80211_rx_assoc_rq(struct ieee80211_device * ieee,struct sk_buff * skb)1699 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1700 {
1701 
1702 	u8 dest[ETH_ALEN];
1703 	//unsigned long flags;
1704 
1705 	ieee->softmac_stats.rx_ass_rq++;
1706 	if (assoc_rq_parse(skb, dest) != -1) {
1707 		ieee80211_resp_to_assoc_rq(ieee, dest);
1708 	}
1709 
1710 	printk(KERN_INFO"New client associated: %pM\n", dest);
1711 	//FIXME
1712 }
1713 
ieee80211_sta_ps_send_null_frame(struct ieee80211_device * ieee,short pwr)1714 static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1715 					     short pwr)
1716 {
1717 
1718 	struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1719 
1720 	if (buf)
1721 		softmac_ps_mgmt_xmit(buf, ieee);
1722 
1723 }
1724 /* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1725 
ieee80211_sta_ps_sleep(struct ieee80211_device * ieee,u32 * time_h,u32 * time_l)1726 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1727 				    u32 *time_l)
1728 {
1729 	int timeout = ieee->ps_timeout;
1730 	u8 dtim;
1731 	/*if(ieee->ps == IEEE80211_PS_DISABLED ||
1732 		ieee->iw_mode != IW_MODE_INFRA ||
1733 		ieee->state != IEEE80211_LINKED)
1734 
1735 		return 0;
1736 	*/
1737 	dtim = ieee->current_network.dtim_data;
1738 	//printk("DTIM\n");
1739 	if(!(dtim & IEEE80211_DTIM_VALID))
1740 		return 0;
1741 	timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1742 	//printk("VALID\n");
1743 	ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1744 
1745 	if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1746 		return 2;
1747 
1748 	if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1749 		return 0;
1750 
1751 	if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1752 		return 0;
1753 
1754 	if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1755 		(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1756 		return 0;
1757 
1758 	if (time_l) {
1759 		*time_l = ieee->current_network.last_dtim_sta_time[0]
1760 			+ (ieee->current_network.beacon_interval
1761 			* ieee->current_network.dtim_period) * 1000;
1762 	}
1763 
1764 	if (time_h) {
1765 		*time_h = ieee->current_network.last_dtim_sta_time[1];
1766 		if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1767 			*time_h += 1;
1768 	}
1769 
1770 	return 1;
1771 
1772 
1773 }
1774 
ieee80211_sta_ps(struct ieee80211_device * ieee)1775 static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1776 {
1777 
1778 	u32 th, tl;
1779 	short sleep;
1780 
1781 	unsigned long flags, flags2;
1782 
1783 	spin_lock_irqsave(&ieee->lock, flags);
1784 
1785 	if ((ieee->ps == IEEE80211_PS_DISABLED ||
1786 		ieee->iw_mode != IW_MODE_INFRA ||
1787 		ieee->state != IEEE80211_LINKED)){
1788 
1789 	//	#warning CHECK_LOCK_HERE
1790 		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1791 
1792 		ieee80211_sta_wakeup(ieee, 1);
1793 
1794 		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1795 	}
1796 
1797 	sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1798 	/* 2 wake, 1 sleep, 0 do nothing */
1799 	if(sleep == 0)
1800 		goto out;
1801 
1802 	if(sleep == 1){
1803 
1804 		if(ieee->sta_sleep == 1)
1805 			ieee->enter_sleep_state(ieee->dev, th, tl);
1806 
1807 		else if(ieee->sta_sleep == 0){
1808 		//	printk("send null 1\n");
1809 			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1810 
1811 			if(ieee->ps_is_queue_empty(ieee->dev)){
1812 
1813 
1814 				ieee->sta_sleep = 2;
1815 
1816 				ieee->ps_request_tx_ack(ieee->dev);
1817 
1818 				ieee80211_sta_ps_send_null_frame(ieee, 1);
1819 
1820 				ieee->ps_th = th;
1821 				ieee->ps_tl = tl;
1822 			}
1823 			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1824 
1825 		}
1826 
1827 
1828 	}else if(sleep == 2){
1829 //#warning CHECK_LOCK_HERE
1830 		spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1831 
1832 		ieee80211_sta_wakeup(ieee, 1);
1833 
1834 		spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1835 	}
1836 
1837 out:
1838 	spin_unlock_irqrestore(&ieee->lock, flags);
1839 
1840 }
1841 
ieee80211_sta_wakeup(struct ieee80211_device * ieee,short nl)1842 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1843 {
1844 	if (ieee->sta_sleep == 0) {
1845 		if (nl) {
1846 			printk("Warning: driver is probably failing to report TX ps error\n");
1847 			ieee->ps_request_tx_ack(ieee->dev);
1848 			ieee80211_sta_ps_send_null_frame(ieee, 0);
1849 		}
1850 		return;
1851 
1852 	}
1853 
1854 	if(ieee->sta_sleep == 1)
1855 		ieee->sta_wake_up(ieee->dev);
1856 
1857 	ieee->sta_sleep = 0;
1858 
1859 	if (nl) {
1860 		ieee->ps_request_tx_ack(ieee->dev);
1861 		ieee80211_sta_ps_send_null_frame(ieee, 0);
1862 	}
1863 }
1864 
ieee80211_ps_tx_ack(struct ieee80211_device * ieee,short success)1865 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1866 {
1867 	unsigned long flags, flags2;
1868 
1869 	spin_lock_irqsave(&ieee->lock, flags);
1870 
1871 	if(ieee->sta_sleep == 2){
1872 		/* Null frame with PS bit set */
1873 		if (success) {
1874 			ieee->sta_sleep = 1;
1875 			ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1876 		}
1877 		/* if the card report not success we can't be sure the AP
1878 		 * has not RXed so we can't assume the AP believe us awake
1879 		 */
1880 	}
1881 	/* 21112005 - tx again null without PS bit if lost */
1882 	else {
1883 
1884 		if ((ieee->sta_sleep == 0) && !success) {
1885 			spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1886 			ieee80211_sta_ps_send_null_frame(ieee, 0);
1887 			spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1888 		}
1889 	}
1890 	spin_unlock_irqrestore(&ieee->lock, flags);
1891 }
1892 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1893 
ieee80211_process_action(struct ieee80211_device * ieee,struct sk_buff * skb)1894 static void ieee80211_process_action(struct ieee80211_device *ieee,
1895 				     struct sk_buff *skb)
1896 {
1897 	struct ieee80211_hdr *header = (struct ieee80211_hdr *)skb->data;
1898 	u8 *act = ieee80211_get_payload(header);
1899 	u8 tmp = 0;
1900 //	IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1901 	if (act == NULL)
1902 	{
1903 		IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1904 		return;
1905 	}
1906 	tmp = *act;
1907 	act ++;
1908 	switch (tmp) {
1909 	case ACT_CAT_BA:
1910 		if (*act == ACT_ADDBAREQ)
1911 			ieee80211_rx_ADDBAReq(ieee, skb);
1912 		else if (*act == ACT_ADDBARSP)
1913 			ieee80211_rx_ADDBARsp(ieee, skb);
1914 		else if (*act == ACT_DELBA)
1915 			ieee80211_rx_DELBA(ieee, skb);
1916 		break;
1917 	default:
1918 		break;
1919 	}
1920 	return;
1921 
1922 }
1923 
ieee80211_check_auth_response(struct ieee80211_device * ieee,struct sk_buff * skb)1924 static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1925 					  struct sk_buff *skb)
1926 {
1927 	/* default support N mode, disable halfNmode */
1928 	bool bSupportNmode = true, bHalfSupportNmode = false;
1929 	u16 errcode;
1930 	u8 *challenge;
1931 	int chlen = 0;
1932 	u32 iotAction;
1933 
1934 	errcode = auth_parse(skb, &challenge, &chlen);
1935 	if (!errcode) {
1936 		if (ieee->open_wep || !challenge) {
1937 			ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1938 			ieee->softmac_stats.rx_auth_rs_ok++;
1939 			iotAction = ieee->pHTInfo->IOTAction;
1940 			if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1941 				if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1942 					/* WEP or TKIP encryption */
1943 					if (IsHTHalfNmodeAPs(ieee)) {
1944 						bSupportNmode = true;
1945 						bHalfSupportNmode = true;
1946 					} else {
1947 						bSupportNmode = false;
1948 						bHalfSupportNmode = false;
1949 					}
1950 					netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1951 							bSupportNmode,
1952 							bHalfSupportNmode);
1953 				}
1954 			}
1955 			/* Dummy wirless mode setting- avoid encryption issue */
1956 			if (bSupportNmode) {
1957 				/* N mode setting */
1958 				ieee->SetWirelessMode(ieee->dev,
1959 						ieee->current_network.mode);
1960 			} else {
1961 				/* b/g mode setting - TODO */
1962 				ieee->SetWirelessMode(ieee->dev, IEEE_G);
1963 			}
1964 
1965 			if (ieee->current_network.mode == IEEE_N_24G &&
1966 					bHalfSupportNmode == true) {
1967 				netdev_dbg(ieee->dev, "enter half N mode\n");
1968 				ieee->bHalfWirelessN24GMode = true;
1969 			} else
1970 				ieee->bHalfWirelessN24GMode = false;
1971 
1972 			ieee80211_associate_step2(ieee);
1973 		} else {
1974 			ieee80211_auth_challenge(ieee, challenge, chlen);
1975 		}
1976 	} else {
1977 		ieee->softmac_stats.rx_auth_rs_err++;
1978 		IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1979 		ieee80211_associate_abort(ieee);
1980 	}
1981 }
1982 
1983 inline int
ieee80211_rx_frame_softmac(struct ieee80211_device * ieee,struct sk_buff * skb,struct ieee80211_rx_stats * rx_stats,u16 type,u16 stype)1984 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1985 			struct ieee80211_rx_stats *rx_stats, u16 type,
1986 			u16 stype)
1987 {
1988 	struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1989 	u16 errcode;
1990 	int aid;
1991 	struct ieee80211_assoc_response_frame *assoc_resp;
1992 //	struct ieee80211_info_element *info_element;
1993 
1994 	if(!ieee->proto_started)
1995 		return 0;
1996 
1997 	if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1998 		ieee->iw_mode == IW_MODE_INFRA &&
1999 		ieee->state == IEEE80211_LINKED))
2000 
2001 		tasklet_schedule(&ieee->ps_task);
2002 
2003 	if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2004 		WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2005 		ieee->last_rx_ps_time = jiffies;
2006 
2007 	switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2008 
2009 	case IEEE80211_STYPE_ASSOC_RESP:
2010 	case IEEE80211_STYPE_REASSOC_RESP:
2011 
2012 		IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2013 				WLAN_FC_GET_STYPE(header->frame_ctl));
2014 		if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2015 			ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2016 			ieee->iw_mode == IW_MODE_INFRA){
2017 			struct ieee80211_network network_resp;
2018 			struct ieee80211_network *network = &network_resp;
2019 
2020 			errcode = assoc_parse(ieee, skb, &aid);
2021 			if (!errcode) {
2022 				ieee->state=IEEE80211_LINKED;
2023 				ieee->assoc_id = aid;
2024 				ieee->softmac_stats.rx_ass_ok++;
2025 				/* station support qos */
2026 				/* Let the register setting defaultly with Legacy station */
2027 				if (ieee->qos_support) {
2028 					assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
2029 					memset(network, 0, sizeof(*network));
2030 					if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2031 								rx_stats->len - sizeof(*assoc_resp),\
2032 								network,rx_stats)){
2033 						return 1;
2034 					}
2035 					else
2036 					{	//filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2037 						memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2038 						memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2039 					}
2040 					if (ieee->handle_assoc_response != NULL)
2041 						ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
2042 				}
2043 				ieee80211_associate_complete(ieee);
2044 			} else {
2045 				/* aid could not been allocated */
2046 				ieee->softmac_stats.rx_ass_err++;
2047 				printk(
2048 					"Association response status code 0x%x\n",
2049 					errcode);
2050 				IEEE80211_DEBUG_MGMT(
2051 					"Association response status code 0x%x\n",
2052 					errcode);
2053 				if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2054 					queue_work(ieee->wq, &ieee->associate_procedure_wq);
2055 				} else {
2056 					ieee80211_associate_abort(ieee);
2057 				}
2058 			}
2059 		}
2060 		break;
2061 
2062 	case IEEE80211_STYPE_ASSOC_REQ:
2063 	case IEEE80211_STYPE_REASSOC_REQ:
2064 
2065 		if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2066 			ieee->iw_mode == IW_MODE_MASTER)
2067 
2068 			ieee80211_rx_assoc_rq(ieee, skb);
2069 		break;
2070 
2071 	case IEEE80211_STYPE_AUTH:
2072 
2073 		if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
2074 			if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
2075 				&& ieee->iw_mode == IW_MODE_INFRA) {
2076 
2077 				IEEE80211_DEBUG_MGMT("Received auth response");
2078 				ieee80211_check_auth_response(ieee, skb);
2079 			} else if (ieee->iw_mode == IW_MODE_MASTER) {
2080 				ieee80211_rx_auth_rq(ieee, skb);
2081 			}
2082 		}
2083 		break;
2084 
2085 	case IEEE80211_STYPE_PROBE_REQ:
2086 
2087 		if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2088 			((ieee->iw_mode == IW_MODE_ADHOC ||
2089 			ieee->iw_mode == IW_MODE_MASTER) &&
2090 			ieee->state == IEEE80211_LINKED)){
2091 			ieee80211_rx_probe_rq(ieee, skb);
2092 		}
2093 		break;
2094 
2095 	case IEEE80211_STYPE_DISASSOC:
2096 	case IEEE80211_STYPE_DEAUTH:
2097 		/* FIXME for now repeat all the association procedure
2098 		* both for disassociation and deauthentication
2099 		*/
2100 		if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2101 			ieee->state == IEEE80211_LINKED &&
2102 			ieee->iw_mode == IW_MODE_INFRA){
2103 
2104 			ieee->state = IEEE80211_ASSOCIATING;
2105 			ieee->softmac_stats.reassoc++;
2106 
2107 			notify_wx_assoc_event(ieee);
2108 			//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2109 			RemovePeerTS(ieee, header->addr2);
2110 			queue_work(ieee->wq, &ieee->associate_procedure_wq);
2111 		}
2112 		break;
2113 	case IEEE80211_STYPE_MANAGE_ACT:
2114 		ieee80211_process_action(ieee, skb);
2115 		break;
2116 	default:
2117 		return -1;
2118 	}
2119 
2120 	//dev_kfree_skb_any(skb);
2121 	return 0;
2122 }
2123 
2124 /* The following are for a simpler TX queue management.
2125  * Instead of using netif_[stop/wake]_queue, the driver
2126  * will use these two functions (plus a reset one) that
2127  * will internally call the kernel netif_* and take care
2128  * of the ieee802.11 fragmentation.
2129  * So, the driver receives a fragment at a time and might
2130  * call the stop function when it wants, without taking
2131  * care to have enough room to TX an entire packet.
2132  * This might be useful if each fragment needs its own
2133  * descriptor. Thus, just keeping a total free memory > than
2134  * the max fragmentation threshold is not enough. If the
2135  * ieee802.11 stack passed a TXB struct, then you would need
2136  * to keep N free descriptors where
2137  * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
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 = true;
2727 	ieee->tx_pending.txb = NULL;
2728 
2729 	setup_timer(&ieee->associate_timer, ieee80211_associate_abort_cb,
2730 		    (unsigned long)ieee);
2731 
2732 	setup_timer(&ieee->beacon_timer, ieee80211_send_beacon_cb,
2733 		    (unsigned long)ieee);
2734 
2735 	ieee->wq = create_workqueue(DRV_NAME);
2736 
2737 	INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2738 	INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2739 	INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2740 	INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2741 	INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2742 	INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2743 
2744 
2745 	sema_init(&ieee->wx_sem, 1);
2746 	sema_init(&ieee->scan_sem, 1);
2747 
2748 	spin_lock_init(&ieee->mgmt_tx_lock);
2749 	spin_lock_init(&ieee->beacon_lock);
2750 
2751 	tasklet_init(&ieee->ps_task,
2752 	     (void(*)(unsigned long)) ieee80211_sta_ps,
2753 	     (unsigned long)ieee);
2754 
2755 }
2756 
ieee80211_softmac_free(struct ieee80211_device * ieee)2757 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2758 {
2759 	down(&ieee->wx_sem);
2760 	kfree(ieee->pDot11dInfo);
2761 	ieee->pDot11dInfo = NULL;
2762 	del_timer_sync(&ieee->associate_timer);
2763 
2764 	cancel_delayed_work(&ieee->associate_retry_wq);
2765 	destroy_workqueue(ieee->wq);
2766 
2767 	up(&ieee->wx_sem);
2768 }
2769 
2770 /********************************************************
2771  * Start of WPA code.                                   *
2772  * this is stolen from the ipw2200 driver               *
2773  ********************************************************/
2774 
2775 
ieee80211_wpa_enable(struct ieee80211_device * ieee,int value)2776 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2777 {
2778 	/* This is called when wpa_supplicant loads and closes the driver
2779 	 * interface. */
2780 	printk("%s WPA\n",value ? "enabling" : "disabling");
2781 	ieee->wpa_enabled = value;
2782 	return 0;
2783 }
2784 
2785 
ieee80211_wpa_assoc_frame(struct ieee80211_device * ieee,char * wpa_ie,int wpa_ie_len)2786 static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2787 				      char *wpa_ie, int wpa_ie_len)
2788 {
2789 	/* make sure WPA is enabled */
2790 	ieee80211_wpa_enable(ieee, 1);
2791 
2792 	ieee80211_disassociate(ieee);
2793 }
2794 
2795 
ieee80211_wpa_mlme(struct ieee80211_device * ieee,int command,int reason)2796 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2797 {
2798 
2799 	int ret = 0;
2800 
2801 	switch (command) {
2802 	case IEEE_MLME_STA_DEAUTH:
2803 		// silently ignore
2804 		break;
2805 
2806 	case IEEE_MLME_STA_DISASSOC:
2807 		ieee80211_disassociate(ieee);
2808 		break;
2809 
2810 	default:
2811 		printk("Unknown MLME request: %d\n", command);
2812 		ret = -EOPNOTSUPP;
2813 	}
2814 
2815 	return ret;
2816 }
2817 
2818 
ieee80211_wpa_set_wpa_ie(struct ieee80211_device * ieee,struct ieee_param * param,int plen)2819 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2820 			      struct ieee_param *param, int plen)
2821 {
2822 	u8 *buf;
2823 
2824 	if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2825 	    (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2826 		return -EINVAL;
2827 
2828 	if (param->u.wpa_ie.len) {
2829 		buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2830 			      GFP_KERNEL);
2831 		if (buf == NULL)
2832 			return -ENOMEM;
2833 
2834 		kfree(ieee->wpa_ie);
2835 		ieee->wpa_ie = buf;
2836 		ieee->wpa_ie_len = param->u.wpa_ie.len;
2837 	} else {
2838 		kfree(ieee->wpa_ie);
2839 		ieee->wpa_ie = NULL;
2840 		ieee->wpa_ie_len = 0;
2841 	}
2842 
2843 	ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2844 	return 0;
2845 }
2846 
2847 #define AUTH_ALG_OPEN_SYSTEM			0x1
2848 #define AUTH_ALG_SHARED_KEY			0x2
2849 
ieee80211_wpa_set_auth_algs(struct ieee80211_device * ieee,int value)2850 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2851 {
2852 
2853 	struct ieee80211_security sec = {
2854 		.flags = SEC_AUTH_MODE,
2855 	};
2856 
2857 	if (value & AUTH_ALG_SHARED_KEY) {
2858 		sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2859 		ieee->open_wep = 0;
2860 		ieee->auth_mode = 1;
2861 	} else if (value & AUTH_ALG_OPEN_SYSTEM){
2862 		sec.auth_mode = WLAN_AUTH_OPEN;
2863 		ieee->open_wep = 1;
2864 		ieee->auth_mode = 0;
2865 	}
2866 	else if (value & IW_AUTH_ALG_LEAP){
2867 		sec.auth_mode = WLAN_AUTH_LEAP;
2868 		ieee->open_wep = 1;
2869 		ieee->auth_mode = 2;
2870 	}
2871 
2872 
2873 	if (ieee->set_security)
2874 		ieee->set_security(ieee->dev, &sec);
2875 	//else
2876 	//	ret = -EOPNOTSUPP;
2877 
2878 	return 0;
2879 }
2880 
ieee80211_wpa_set_param(struct ieee80211_device * ieee,u8 name,u32 value)2881 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2882 {
2883 	int ret=0;
2884 	unsigned long flags;
2885 
2886 	switch (name) {
2887 	case IEEE_PARAM_WPA_ENABLED:
2888 		ret = ieee80211_wpa_enable(ieee, value);
2889 		break;
2890 
2891 	case IEEE_PARAM_TKIP_COUNTERMEASURES:
2892 		ieee->tkip_countermeasures=value;
2893 		break;
2894 
2895 	case IEEE_PARAM_DROP_UNENCRYPTED: {
2896 		/* HACK:
2897 		 *
2898 		 * wpa_supplicant calls set_wpa_enabled when the driver
2899 		 * is loaded and unloaded, regardless of if WPA is being
2900 		 * used.  No other calls are made which can be used to
2901 		 * determine if encryption will be used or not prior to
2902 		 * association being expected.  If encryption is not being
2903 		 * used, drop_unencrypted is set to false, else true -- we
2904 		 * can use this to determine if the CAP_PRIVACY_ON bit should
2905 		 * be set.
2906 		 */
2907 		struct ieee80211_security sec = {
2908 			.flags = SEC_ENABLED,
2909 			.enabled = value,
2910 		};
2911 		ieee->drop_unencrypted = value;
2912 		/* We only change SEC_LEVEL for open mode. Others
2913 		 * are set by ipw_wpa_set_encryption.
2914 		 */
2915 		if (!value) {
2916 			sec.flags |= SEC_LEVEL;
2917 			sec.level = SEC_LEVEL_0;
2918 		}
2919 		else {
2920 			sec.flags |= SEC_LEVEL;
2921 			sec.level = SEC_LEVEL_1;
2922 		}
2923 		if (ieee->set_security)
2924 			ieee->set_security(ieee->dev, &sec);
2925 		break;
2926 	}
2927 
2928 	case IEEE_PARAM_PRIVACY_INVOKED:
2929 		ieee->privacy_invoked=value;
2930 		break;
2931 
2932 	case IEEE_PARAM_AUTH_ALGS:
2933 		ret = ieee80211_wpa_set_auth_algs(ieee, value);
2934 		break;
2935 
2936 	case IEEE_PARAM_IEEE_802_1X:
2937 		ieee->ieee802_1x=value;
2938 		break;
2939 	case IEEE_PARAM_WPAX_SELECT:
2940 		// added for WPA2 mixed mode
2941 		spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2942 		ieee->wpax_type_set = 1;
2943 		ieee->wpax_type_notify = value;
2944 		spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2945 		break;
2946 
2947 	default:
2948 		printk("Unknown WPA param: %d\n",name);
2949 		ret = -EOPNOTSUPP;
2950 	}
2951 
2952 	return ret;
2953 }
2954 
2955 /* implementation borrowed from hostap driver */
2956 
ieee80211_wpa_set_encryption(struct ieee80211_device * ieee,struct ieee_param * param,int param_len)2957 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2958 				  struct ieee_param *param, int param_len)
2959 {
2960 	int ret = 0;
2961 
2962 	struct ieee80211_crypto_ops *ops;
2963 	struct ieee80211_crypt_data **crypt;
2964 
2965 	struct ieee80211_security sec = {
2966 		.flags = 0,
2967 	};
2968 
2969 	param->u.crypt.err = 0;
2970 	param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2971 
2972 	if (param_len !=
2973 	    (int) ((char *) param->u.crypt.key - (char *) param) +
2974 	    param->u.crypt.key_len) {
2975 		printk("Len mismatch %d, %d\n", param_len,
2976 			       param->u.crypt.key_len);
2977 		return -EINVAL;
2978 	}
2979 	if (is_broadcast_ether_addr(param->sta_addr)) {
2980 		if (param->u.crypt.idx >= WEP_KEYS)
2981 			return -EINVAL;
2982 		crypt = &ieee->crypt[param->u.crypt.idx];
2983 	} else {
2984 		return -EINVAL;
2985 	}
2986 
2987 	if (strcmp(param->u.crypt.alg, "none") == 0) {
2988 		if (crypt) {
2989 			sec.enabled = 0;
2990 			// FIXME FIXME
2991 			//sec.encrypt = 0;
2992 			sec.level = SEC_LEVEL_0;
2993 			sec.flags |= SEC_ENABLED | SEC_LEVEL;
2994 			ieee80211_crypt_delayed_deinit(ieee, crypt);
2995 		}
2996 		goto done;
2997 	}
2998 	sec.enabled = 1;
2999 // FIXME FIXME
3000 //	sec.encrypt = 1;
3001 	sec.flags |= SEC_ENABLED;
3002 
3003 	/* IPW HW cannot build TKIP MIC, host decryption still needed. */
3004 	if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3005 	    strcmp(param->u.crypt.alg, "TKIP"))
3006 		goto skip_host_crypt;
3007 
3008 	ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3009 	if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3010 		request_module("ieee80211_crypt_wep");
3011 		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3012 		//set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3013 	} else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3014 		request_module("ieee80211_crypt_tkip");
3015 		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3016 	} else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3017 		request_module("ieee80211_crypt_ccmp");
3018 		ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3019 	}
3020 	if (ops == NULL) {
3021 		printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3022 		param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3023 		ret = -EINVAL;
3024 		goto done;
3025 	}
3026 
3027 	if (*crypt == NULL || (*crypt)->ops != ops) {
3028 		struct ieee80211_crypt_data *new_crypt;
3029 
3030 		ieee80211_crypt_delayed_deinit(ieee, crypt);
3031 
3032 		new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
3033 		if (new_crypt == NULL) {
3034 			ret = -ENOMEM;
3035 			goto done;
3036 		}
3037 		new_crypt->ops = ops;
3038 		if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3039 			new_crypt->priv =
3040 				new_crypt->ops->init(param->u.crypt.idx);
3041 
3042 		if (new_crypt->priv == NULL) {
3043 			kfree(new_crypt);
3044 			param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3045 			ret = -EINVAL;
3046 			goto done;
3047 		}
3048 
3049 		*crypt = new_crypt;
3050 	}
3051 
3052 	if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3053 	    (*crypt)->ops->set_key(param->u.crypt.key,
3054 				   param->u.crypt.key_len, param->u.crypt.seq,
3055 				   (*crypt)->priv) < 0) {
3056 		printk("key setting failed\n");
3057 		param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3058 		ret = -EINVAL;
3059 		goto done;
3060 	}
3061 
3062  skip_host_crypt:
3063 	if (param->u.crypt.set_tx) {
3064 		ieee->tx_keyidx = param->u.crypt.idx;
3065 		sec.active_key = param->u.crypt.idx;
3066 		sec.flags |= SEC_ACTIVE_KEY;
3067 	} else
3068 		sec.flags &= ~SEC_ACTIVE_KEY;
3069 
3070 	if (param->u.crypt.alg != NULL) {
3071 		memcpy(sec.keys[param->u.crypt.idx],
3072 		       param->u.crypt.key,
3073 		       param->u.crypt.key_len);
3074 		sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3075 		sec.flags |= (1 << param->u.crypt.idx);
3076 
3077 		if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3078 			sec.flags |= SEC_LEVEL;
3079 			sec.level = SEC_LEVEL_1;
3080 		} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3081 			sec.flags |= SEC_LEVEL;
3082 			sec.level = SEC_LEVEL_2;
3083 		} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3084 			sec.flags |= SEC_LEVEL;
3085 			sec.level = SEC_LEVEL_3;
3086 		}
3087 	}
3088  done:
3089 	if (ieee->set_security)
3090 		ieee->set_security(ieee->dev, &sec);
3091 
3092 	/* Do not reset port if card is in Managed mode since resetting will
3093 	 * generate new IEEE 802.11 authentication which may end up in looping
3094 	 * with IEEE 802.1X.  If your hardware requires a reset after WEP
3095 	 * configuration (for example... Prism2), implement the reset_port in
3096 	 * the callbacks structures used to initialize the 802.11 stack. */
3097 	if (ieee->reset_on_keychange &&
3098 	    ieee->iw_mode != IW_MODE_INFRA &&
3099 	    ieee->reset_port &&
3100 	    ieee->reset_port(ieee->dev)) {
3101 		printk("reset_port failed\n");
3102 		param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3103 		return -EINVAL;
3104 	}
3105 
3106 	return ret;
3107 }
3108 
ieee80211_disassociate_skb(struct ieee80211_network * beacon,struct ieee80211_device * ieee,u8 asRsn)3109 inline struct sk_buff *ieee80211_disassociate_skb(
3110 							struct ieee80211_network *beacon,
3111 							struct ieee80211_device *ieee,
3112 							u8	asRsn)
3113 {
3114 	struct sk_buff *skb;
3115 	struct ieee80211_disassoc *disass;
3116 
3117 	skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3118 	if (!skb)
3119 		return NULL;
3120 
3121 	disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3122 	disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3123 	disass->header.duration_id = 0;
3124 
3125 	memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3126 	memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3127 	memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3128 
3129 	disass->reason = asRsn;
3130 	return skb;
3131 }
3132 
3133 
3134 void
SendDisassociation(struct ieee80211_device * ieee,u8 * asSta,u8 asRsn)3135 SendDisassociation(
3136 		struct ieee80211_device *ieee,
3137 		u8					*asSta,
3138 		u8						asRsn
3139 )
3140 {
3141 		struct ieee80211_network *beacon = &ieee->current_network;
3142 		struct sk_buff *skb;
3143 		skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3144 		if (skb) {
3145 				softmac_mgmt_xmit(skb, ieee);
3146 				//dev_kfree_skb_any(skb);//edit by thomas
3147 		}
3148 }
3149 EXPORT_SYMBOL(SendDisassociation);
3150 
ieee80211_wpa_supplicant_ioctl(struct ieee80211_device * ieee,struct iw_point * p)3151 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3152 {
3153 	struct ieee_param *param;
3154 	int ret=0;
3155 
3156 	down(&ieee->wx_sem);
3157 	//IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3158 
3159 	if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3160 		ret = -EINVAL;
3161 		goto out;
3162 	}
3163 
3164 	param = memdup_user(p->pointer, p->length);
3165 	if (IS_ERR(param)) {
3166 		ret = PTR_ERR(param);
3167 		goto out;
3168 	}
3169 
3170 	switch (param->cmd) {
3171 
3172 	case IEEE_CMD_SET_WPA_PARAM:
3173 		ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3174 					param->u.wpa_param.value);
3175 		break;
3176 
3177 	case IEEE_CMD_SET_WPA_IE:
3178 		ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3179 		break;
3180 
3181 	case IEEE_CMD_SET_ENCRYPTION:
3182 		ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3183 		break;
3184 
3185 	case IEEE_CMD_MLME:
3186 		ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3187 				   param->u.mlme.reason_code);
3188 		break;
3189 
3190 	default:
3191 		printk("Unknown WPA supplicant request: %d\n",param->cmd);
3192 		ret = -EOPNOTSUPP;
3193 		break;
3194 	}
3195 
3196 	if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3197 		ret = -EFAULT;
3198 
3199 	kfree(param);
3200 out:
3201 	up(&ieee->wx_sem);
3202 
3203 	return ret;
3204 }
3205 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3206 
notify_wx_assoc_event(struct ieee80211_device * ieee)3207 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3208 {
3209 	union iwreq_data wrqu;
3210 	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3211 	if (ieee->state == IEEE80211_LINKED)
3212 		memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3213 	else
3214 		eth_zero_addr(wrqu.ap_addr.sa_data);
3215 	wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3216 }
3217 EXPORT_SYMBOL(notify_wx_assoc_event);
3218