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