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