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