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