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