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