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