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