eae7c4579a681d8ab4b0f2fb9a4ec98e013c6197
[safe/jmp/linux-2.6] / drivers / staging / rtl8192e / ieee80211 / ieee80211_softmac.c
1 /* IEEE 802.11 SoftMAC layer
2  * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
3  *
4  * Mostly extracted from the rtl8180-sa2400 driver for the
5  * in-kernel generic ieee802.11 stack.
6  *
7  * Few lines might be stolen from other part of the ieee80211
8  * stack. Copyright who own it's copyright
9  *
10  * WPA code stolen from the ipw2200 driver.
11  * Copyright who own it's copyright.
12  *
13  * released under the GPL
14  */
15
16
17 #include "ieee80211.h"
18
19 #include <linux/random.h>
20 #include <linux/delay.h>
21 #include <linux/version.h>
22 #include <asm/uaccess.h>
23 #ifdef ENABLE_DOT11D
24 #include "dot11d.h"
25 #endif
26
27 u8 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
36 short ieee80211_is_54g(struct ieee80211_network net)
37 {
38         return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39 }
40
41 short 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  */
50 unsigned 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  */
68 void 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
85 void 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
109 void 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
133 void 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
151 void 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
169 struct 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
184 void init_mgmt_queue(struct ieee80211_device *ieee)
185 {
186         ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
187 }
188
189 u8 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
224 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
225
226 inline 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                          * */
282                         //printk("%s():insert to waitqueue!\n",__FUNCTION__);
283                         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
293 inline 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
335 inline 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
373 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
374 void 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
400 void 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
412 void 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
424 void 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  */
435 void 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         }
497 out:
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 */
514 void 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))
532 void 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
537 void 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;
587 out:
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)
600 void 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
612 void 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
623 void 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
637 void 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
646 void 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
655 void 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
678 void 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 */
687 void 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 */
718 void 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
737 inline 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
779 static 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
988 struct 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
1043 struct 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
1071 struct 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
1097 void 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
1106 void 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
1115 void 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
1125 inline 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
1367 void 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
1401 void ieee80211_associate_abort_cb(unsigned long dev)
1402 {
1403         ieee80211_associate_abort((struct ieee80211_device *) dev);
1404 }
1405
1406
1407 void 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
1433 void 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
1467 void 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))
1491 void 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
1495 void 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
1543 void 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))
1577 void 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
1581 void 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
1601 inline 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
1707 void 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
1732 static 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
1757 int 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
1775 static 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
1813 int 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
1831 static 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
1858 static inline void
1859 ieee80211_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
1873 static inline void
1874 ieee80211_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
1888 static inline void
1889 ieee80211_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
1911 void 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
1922 short 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
1970 inline 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
2032 out:
2033         spin_unlock_irqrestore(&ieee->lock, flags);
2034
2035 }
2036
2037 void 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
2060 void 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 }
2087 void 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 }
2118 inline int
2119 ieee80211_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  */
2344 void 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 */
2403 void 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
2428 void 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
2443 void 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
2479 exit :
2480         spin_unlock_irqrestore(&ieee->lock,flags);
2481 }
2482
2483
2484 void 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
2499 inline 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 */
2512 void 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
2538 void 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))
2549 void 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
2555 void 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
2665 inline 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 */
2675 void 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 */
2715 void 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))
2737 void 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
2742 void 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;
2783 exit:
2784         up(&ieee->wx_sem);
2785 }
2786
2787 struct 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
2806 struct 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
2826 void 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
2835 void 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
2854 void 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
2862 void 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"
2918 void 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
3026 void 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
3052 static 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
3062 void 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
3071 static 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
3094 static 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
3125 static 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
3157 static 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
3233 static 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);
3287         if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3288                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3289                 /* 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)
3292                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3293         else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3294                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3295         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;
3315                 if (new_crypt->ops)
3316                         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
3386 inline 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
3411 void
3412 SendDisassociation(
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
3427 int 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);
3481 out:
3482         up(&ieee->wx_sem);
3483
3484         return ret;
3485 }
3486
3487 void 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
3520 EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3521 EXPORT_SYMBOL_NOVERS(ieee80211_wake_queue);
3522 EXPORT_SYMBOL_NOVERS(ieee80211_stop_queue);
3523 EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3524 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3525 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3526 EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3527 EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3528 EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3529 EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3530 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3531 EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3532 EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3533 EXPORT_SYMBOL_NOVERS(SendDisassociation);
3534 EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3535 EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3536 EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3537 EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3538 EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3539 EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3540 #endif
3541 //EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);