fs/dlm: Drop unnecessary null test
[sfrench/cifs-2.6.git] / 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 = 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         status = auth_rq_parse(skb, dest);
1695         if (status != -1) {
1696                 ieee80211_resp_to_auth(ieee, status, dest);
1697         }
1698         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1699
1700 }
1701
1702 static inline void
1703 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1704 {
1705
1706         u8 dest[ETH_ALEN];
1707         //unsigned long flags;
1708
1709         ieee->softmac_stats.rx_ass_rq++;
1710         if (assoc_rq_parse(skb,dest) != -1){
1711                 ieee80211_resp_to_assoc_rq(ieee, dest);
1712         }
1713
1714         printk(KERN_INFO"New client associated: %pM\n", dest);
1715         //FIXME
1716 }
1717
1718
1719
1720 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1721 {
1722
1723         struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1724
1725         if (buf)
1726                 softmac_ps_mgmt_xmit(buf, ieee);
1727
1728 }
1729
1730
1731 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1732 {
1733         int timeout = ieee->ps_timeout;
1734         u8 dtim;
1735         /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1736                 ieee->iw_mode != IW_MODE_INFRA ||
1737                 ieee->state != IEEE80211_LINKED)
1738
1739                 return 0;
1740         */
1741         dtim = ieee->current_network.dtim_data;
1742         //printk("DTIM\n");
1743         if(!(dtim & IEEE80211_DTIM_VALID))
1744                 return 0;
1745         timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1746         //printk("VALID\n");
1747         ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1748
1749         if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1750                 return 2;
1751
1752         if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1753                 return 0;
1754
1755         if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1756                 return 0;
1757
1758         if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1759                 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1760                 return 0;
1761
1762         if(time_l){
1763                 *time_l = ieee->current_network.last_dtim_sta_time[0]
1764                         + (ieee->current_network.beacon_interval);
1765                 //      * ieee->current_network.dtim_period) * 1000;
1766         }
1767
1768         if(time_h){
1769                 *time_h = ieee->current_network.last_dtim_sta_time[1];
1770                 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1771                         *time_h += 1;
1772         }
1773
1774         return 1;
1775
1776
1777 }
1778
1779 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1780 {
1781
1782         u32 th,tl;
1783         short sleep;
1784
1785         unsigned long flags,flags2;
1786
1787         spin_lock_irqsave(&ieee->lock, flags);
1788
1789         if((ieee->ps == IEEE80211_PS_DISABLED ||
1790                 ieee->iw_mode != IW_MODE_INFRA ||
1791                 ieee->state != IEEE80211_LINKED)){
1792
1793         //      #warning CHECK_LOCK_HERE
1794                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1795
1796                 ieee80211_sta_wakeup(ieee, 1);
1797
1798                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1799         }
1800
1801         sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1802         /* 2 wake, 1 sleep, 0 do nothing */
1803         if(sleep == 0)
1804                 goto out;
1805
1806         if(sleep == 1){
1807
1808                 if(ieee->sta_sleep == 1)
1809                         ieee->enter_sleep_state(ieee->dev,th,tl);
1810
1811                 else if(ieee->sta_sleep == 0){
1812                 //      printk("send null 1\n");
1813                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1814
1815                         if(ieee->ps_is_queue_empty(ieee->dev)){
1816
1817
1818                                 ieee->sta_sleep = 2;
1819
1820                                 ieee->ack_tx_to_ieee = 1;
1821
1822                                 ieee80211_sta_ps_send_null_frame(ieee,1);
1823
1824                                 ieee->ps_th = th;
1825                                 ieee->ps_tl = tl;
1826                         }
1827                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1828
1829                 }
1830
1831
1832         }else if(sleep == 2){
1833 //#warning CHECK_LOCK_HERE
1834                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1835
1836                 ieee80211_sta_wakeup(ieee,1);
1837
1838                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1839         }
1840
1841 out:
1842         spin_unlock_irqrestore(&ieee->lock, flags);
1843
1844 }
1845
1846 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1847 {
1848         if(ieee->sta_sleep == 0){
1849                 if(nl){
1850                         printk("Warning: driver is probably failing to report TX ps error\n");
1851                         ieee->ack_tx_to_ieee = 1;
1852                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1853                 }
1854                 return;
1855
1856         }
1857
1858         if(ieee->sta_sleep == 1)
1859                 ieee->sta_wake_up(ieee->dev);
1860
1861         ieee->sta_sleep = 0;
1862
1863         if(nl){
1864                 ieee->ack_tx_to_ieee = 1;
1865                 ieee80211_sta_ps_send_null_frame(ieee, 0);
1866         }
1867 }
1868
1869 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1870 {
1871         unsigned long flags,flags2;
1872
1873         spin_lock_irqsave(&ieee->lock, flags);
1874
1875         if(ieee->sta_sleep == 2){
1876                 /* Null frame with PS bit set */
1877                 if(success){
1878                         ieee->sta_sleep = 1;
1879                         ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1880                 }
1881                 /* if the card report not success we can't be sure the AP
1882                  * has not RXed so we can't assume the AP believe us awake
1883                  */
1884         }
1885         /* 21112005 - tx again null without PS bit if lost */
1886         else {
1887
1888                 if((ieee->sta_sleep == 0) && !success){
1889                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1890                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1891                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1892                 }
1893         }
1894         spin_unlock_irqrestore(&ieee->lock, flags);
1895 }
1896 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1897 {
1898         struct rtl_ieee80211_hdr *header =
1899                 (struct rtl_ieee80211_hdr *)skb->data;
1900         u8* act = ieee80211_get_payload(header);
1901         u8 tmp = 0;
1902 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1903         if (act == NULL)
1904         {
1905                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1906                 return;
1907         }
1908         tmp = *act;
1909         act ++;
1910         switch (tmp)
1911         {
1912                 case ACT_CAT_BA:
1913                         if (*act == ACT_ADDBAREQ)
1914                         ieee80211_rx_ADDBAReq(ieee, skb);
1915                         else if (*act == ACT_ADDBARSP)
1916                         ieee80211_rx_ADDBARsp(ieee, skb);
1917                         else if (*act == ACT_DELBA)
1918                         ieee80211_rx_DELBA(ieee, skb);
1919                         break;
1920                 default:
1921 //                      if (net_ratelimit())
1922 //                      IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
1923                         break;
1924         }
1925         return;
1926
1927 }
1928 inline int
1929 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1930                         struct ieee80211_rx_stats *rx_stats, u16 type,
1931                         u16 stype)
1932 {
1933         struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1934         u16 errcode;
1935         u8* challenge;
1936         int chlen=0;
1937         int aid;
1938         struct ieee80211_assoc_response_frame *assoc_resp;
1939 //      struct ieee80211_info_element *info_element;
1940         bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1941
1942         if(!ieee->proto_started)
1943                 return 0;
1944
1945         switch (WLAN_FC_GET_STYPE(header->frame_control)) {
1946
1947                 case IEEE80211_STYPE_ASSOC_RESP:
1948                 case IEEE80211_STYPE_REASSOC_RESP:
1949
1950                         IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1951                                         WLAN_FC_GET_STYPE(header->frame_control));
1952                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1953                                 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1954                                 ieee->iw_mode == IW_MODE_INFRA){
1955                                 struct ieee80211_network network_resp;
1956                                 struct ieee80211_network *network = &network_resp;
1957
1958                                 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
1959                                         ieee->state=IEEE80211_LINKED;
1960                                         ieee->assoc_id = aid;
1961                                         ieee->softmac_stats.rx_ass_ok++;
1962                                         /* station support qos */
1963                                         /* Let the register setting defaultly with Legacy station */
1964                                         if(ieee->qos_support) {
1965                                                 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
1966                                                 memset(network, 0, sizeof(*network));
1967                                                 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1968                                                                         rx_stats->len - sizeof(*assoc_resp),\
1969                                                                         network,rx_stats)){
1970                                                         return 1;
1971                                                 }
1972                                                 else
1973                                                 {       //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
1974                                                         memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1975                                                         memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1976                                                 }
1977                                                 if (ieee->handle_assoc_response != NULL)
1978                                                         ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
1979                                         }
1980                                         ieee80211_associate_complete(ieee);
1981                                 } else {
1982                                         /* aid could not been allocated */
1983                                         ieee->softmac_stats.rx_ass_err++;
1984                                         printk(
1985                                                 "Association response status code 0x%x\n",
1986                                                 errcode);
1987                                         IEEE80211_DEBUG_MGMT(
1988                                                 "Association response status code 0x%x\n",
1989                                                 errcode);
1990                                         if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
1991                                                 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1992                                         } else {
1993                                                 ieee80211_associate_abort(ieee);
1994                                         }
1995                                 }
1996                         }
1997                         break;
1998
1999                 case IEEE80211_STYPE_ASSOC_REQ:
2000                 case IEEE80211_STYPE_REASSOC_REQ:
2001
2002                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2003                                 ieee->iw_mode == IW_MODE_MASTER)
2004
2005                                 ieee80211_rx_assoc_rq(ieee, skb);
2006                         break;
2007
2008                 case IEEE80211_STYPE_AUTH:
2009
2010                         if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2011                                 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2012                                 ieee->iw_mode == IW_MODE_INFRA){
2013
2014                                                 IEEE80211_DEBUG_MGMT("Received authentication response");
2015
2016                                                 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2017                                                         if(ieee->open_wep || !challenge){
2018                                                                 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2019                                                                 ieee->softmac_stats.rx_auth_rs_ok++;
2020                                                                 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2021                                                                 {
2022                                                                         if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2023                                                                         {
2024                                                                                                 // WEP or TKIP encryption
2025                                                                                 if(IsHTHalfNmodeAPs(ieee))
2026                                                                                 {
2027                                                                                         bSupportNmode = true;
2028                                                                                         bHalfSupportNmode = true;
2029                                                                                 }
2030                                                                                 else
2031                                                                                 {
2032                                                                                         bSupportNmode = false;
2033                                                                                         bHalfSupportNmode = false;
2034                                                                                 }
2035                                                                         printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2036                                                                         }
2037                                                                 }
2038                                                                 /* Dummy wirless mode setting to avoid encryption issue */
2039                                                                 if(bSupportNmode) {
2040                                                                         //N mode setting
2041                                                                         ieee->SetWirelessMode(ieee->dev, \
2042                                                                                         ieee->current_network.mode);
2043                                                                 }else{
2044                                                                         //b/g mode setting
2045                                                                         /*TODO*/
2046                                                                         ieee->SetWirelessMode(ieee->dev, IEEE_G);
2047                                                                 }
2048
2049                                                                 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2050                                                                 {
2051                                                                         printk("===============>entern half N mode\n");
2052                                                                         ieee->bHalfWirelessN24GMode = true;
2053                                                                 }
2054                                                                 else
2055                                                                         ieee->bHalfWirelessN24GMode = false;
2056
2057                                                                 ieee80211_associate_step2(ieee);
2058                                                         }else{
2059                                                                 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2060                                                         }
2061                                                 }else{
2062                                                         ieee->softmac_stats.rx_auth_rs_err++;
2063                                                         IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2064
2065                                                         printk("Authentication respose status code 0x%x",errcode);
2066                                                         ieee80211_associate_abort(ieee);
2067                                                 }
2068
2069                                         }else if (ieee->iw_mode == IW_MODE_MASTER){
2070                                                 ieee80211_rx_auth_rq(ieee, skb);
2071                                         }
2072                                 }
2073                         break;
2074
2075                 case IEEE80211_STYPE_PROBE_REQ:
2076
2077                         if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2078                                 ((ieee->iw_mode == IW_MODE_ADHOC ||
2079                                 ieee->iw_mode == IW_MODE_MASTER) &&
2080                                 ieee->state == IEEE80211_LINKED)){
2081                                 ieee80211_rx_probe_rq(ieee, skb);
2082                         }
2083                         break;
2084
2085                 case IEEE80211_STYPE_DISASSOC:
2086                 case IEEE80211_STYPE_DEAUTH:
2087                         /* FIXME for now repeat all the association procedure
2088                         * both for disassociation and deauthentication
2089                         */
2090                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2091                                 ieee->state == IEEE80211_LINKED &&
2092                                 ieee->iw_mode == IW_MODE_INFRA){
2093                                 printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason);
2094                                 ieee->state = IEEE80211_ASSOCIATING;
2095                                 ieee->softmac_stats.reassoc++;
2096                                 ieee->is_roaming = true;
2097                                 ieee80211_disassociate(ieee);
2098                         //      notify_wx_assoc_event(ieee);
2099                                 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2100                                 RemovePeerTS(ieee, header->addr2);
2101                                 if(ieee->LedControlHandler != NULL)
2102                                         ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); //added by amy for LED 090318
2103                                 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2104                         }
2105                         break;
2106                 case IEEE80211_STYPE_MANAGE_ACT:
2107                         ieee80211_process_action(ieee,skb);
2108                         break;
2109                 default:
2110                         return -1;
2111                         break;
2112         }
2113
2114         //dev_kfree_skb_any(skb);
2115         return 0;
2116 }
2117
2118 /* following are for a simplier TX queue management.
2119  * Instead of using netif_[stop/wake]_queue the driver
2120  * will uses these two function (plus a reset one), that
2121  * will internally uses the kernel netif_* and takes
2122  * care of the ieee802.11 fragmentation.
2123  * So the driver receives a fragment per time and might
2124  * call the stop function when it want without take care
2125  * to have enough room to TX an entire packet.
2126  * This might be useful if each fragment need it's own
2127  * descriptor, thus just keep a total free memory > than
2128  * the max fragmentation threshold is not enough.. If the
2129  * ieee802.11 stack passed a TXB struct then you needed
2130  * to keep N free descriptors where
2131  * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2132  * In this way you need just one and the 802.11 stack
2133  * will take care of buffering fragments and pass them to
2134  * to the driver later, when it wakes the queue.
2135  */
2136 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2137 {
2138
2139         unsigned int queue_index = txb->queue_index;
2140         unsigned long flags;
2141         int  i;
2142         cb_desc *tcb_desc = NULL;
2143
2144         spin_lock_irqsave(&ieee->lock,flags);
2145
2146         /* called with 2nd parm 0, no tx mgmt lock required */
2147         ieee80211_sta_wakeup(ieee,0);
2148
2149         /* update the tx status */
2150         ieee->stats.tx_bytes += txb->payload_size;
2151         ieee->stats.tx_packets++;
2152         tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2153         if(tcb_desc->bMulticast) {
2154                 ieee->stats.multicast++;
2155         }
2156 #if 1
2157         /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2158         for(i = 0; i < txb->nr_frags; i++) {
2159                 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2160                 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2161                      (ieee->queue_stop)) {
2162                         /* insert the skb packet to the wait queue */
2163                         /* as for the completion function, it does not need
2164                          * to check it any more.
2165                          * */
2166                         //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));
2167                         //ieee80211_rtl_stop_queue(ieee);
2168                         skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2169                 }else{
2170                         ieee->softmac_data_hard_start_xmit(
2171                                         txb->fragments[i],
2172                                         ieee->dev,ieee->rate);
2173                         //ieee->stats.tx_packets++;
2174                         //ieee->stats.tx_bytes += txb->fragments[i]->len;
2175                         //ieee->dev->trans_start = jiffies;
2176                 }
2177         }
2178 #endif
2179         ieee80211_txb_free(txb);
2180
2181 //exit:
2182         spin_unlock_irqrestore(&ieee->lock,flags);
2183
2184 }
2185
2186 /* called with ieee->lock acquired */
2187 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2188 {
2189         int i;
2190         for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2191
2192                 if (ieee->queue_stop){
2193                         ieee->tx_pending.frag = i;
2194                         return;
2195                 }else{
2196
2197                         ieee->softmac_data_hard_start_xmit(
2198                                 ieee->tx_pending.txb->fragments[i],
2199                                 ieee->dev,ieee->rate);
2200                                 //(i+1)<ieee->tx_pending.txb->nr_frags);
2201                         ieee->stats.tx_packets++;
2202                 //      ieee->dev->trans_start = jiffies;
2203                 }
2204         }
2205
2206
2207         ieee80211_txb_free(ieee->tx_pending.txb);
2208         ieee->tx_pending.txb = NULL;
2209 }
2210
2211
2212 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2213 {
2214         unsigned long flags;
2215
2216         spin_lock_irqsave(&ieee->lock,flags);
2217         init_mgmt_queue(ieee);
2218         if (ieee->tx_pending.txb){
2219                 ieee80211_txb_free(ieee->tx_pending.txb);
2220                 ieee->tx_pending.txb = NULL;
2221         }
2222         ieee->queue_stop = 0;
2223         spin_unlock_irqrestore(&ieee->lock,flags);
2224
2225 }
2226
2227 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2228 {
2229
2230         unsigned long flags;
2231         struct sk_buff *skb;
2232         struct ieee80211_hdr_3addr  *header;
2233
2234         spin_lock_irqsave(&ieee->lock,flags);
2235         if (! ieee->queue_stop) goto exit;
2236
2237         ieee->queue_stop = 0;
2238
2239         if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2240                 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2241
2242                         header = (struct ieee80211_hdr_3addr  *) skb->data;
2243
2244                         header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2245
2246                         if (ieee->seq_ctrl[0] == 0xFFF)
2247                                 ieee->seq_ctrl[0] = 0;
2248                         else
2249                                 ieee->seq_ctrl[0]++;
2250
2251                         ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2252                         //dev_kfree_skb_any(skb);//edit by thomas
2253                 }
2254         }
2255         if (!ieee->queue_stop && ieee->tx_pending.txb)
2256                 ieee80211_resume_tx(ieee);
2257
2258         if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2259                 ieee->softmac_stats.swtxawake++;
2260                 netif_wake_queue(ieee->dev);
2261         }
2262
2263 exit :
2264         spin_unlock_irqrestore(&ieee->lock,flags);
2265 }
2266
2267
2268 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2269 {
2270         //unsigned long flags;
2271         //spin_lock_irqsave(&ieee->lock,flags);
2272
2273         if (! netif_queue_stopped(ieee->dev)){
2274                 netif_stop_queue(ieee->dev);
2275                 ieee->softmac_stats.swtxstop++;
2276         }
2277         ieee->queue_stop = 1;
2278         //spin_unlock_irqrestore(&ieee->lock,flags);
2279
2280 }
2281
2282
2283 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2284 {
2285
2286         get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2287
2288         /* an IBSS cell address must have the two less significant
2289          * bits of the first byte = 2
2290          */
2291         ieee->current_network.bssid[0] &= ~0x01;
2292         ieee->current_network.bssid[0] |= 0x02;
2293 }
2294
2295 /* called in user context only */
2296 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2297 {
2298         ieee->assoc_id = 1;
2299
2300         if (ieee->current_network.ssid_len == 0){
2301                 strncpy(ieee->current_network.ssid,
2302                         IEEE80211_DEFAULT_TX_ESSID,
2303                         IW_ESSID_MAX_SIZE);
2304
2305                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2306                 ieee->ssid_set = 1;
2307         }
2308
2309         memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2310
2311         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2312         ieee->state = IEEE80211_LINKED;
2313         ieee->link_change(ieee->dev);
2314         notify_wx_assoc_event(ieee);
2315
2316         if (ieee->data_hard_resume)
2317                 ieee->data_hard_resume(ieee->dev);
2318
2319         netif_carrier_on(ieee->dev);
2320 }
2321
2322 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2323 {
2324         if(ieee->raw_tx){
2325
2326                 if (ieee->data_hard_resume)
2327                         ieee->data_hard_resume(ieee->dev);
2328
2329                 netif_carrier_on(ieee->dev);
2330         }
2331 }
2332
2333 void ieee80211_start_ibss_wq(struct work_struct *work)
2334 {
2335
2336         struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2337         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2338         /* iwconfig mode ad-hoc will schedule this and return
2339          * on the other hand this will block further iwconfig SET
2340          * operations because of the wx_sem hold.
2341          * Anyway some most set operations set a flag to speed-up
2342          * (abort) this wq (when syncro scanning) before sleeping
2343          * on the semaphore
2344          */
2345         if(!ieee->proto_started){
2346                 printk("==========oh driver down return\n");
2347                 return;
2348         }
2349         down(&ieee->wx_sem);
2350         //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
2351         HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2352
2353         if (ieee->current_network.ssid_len == 0){
2354                 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2355                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2356                 ieee->ssid_set = 1;
2357         }
2358
2359         /* check if we have this cell in our network list */
2360         ieee80211_softmac_check_all_nets(ieee);
2361
2362
2363 //      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2364         if (ieee->state == IEEE80211_NOLINK)
2365                 ieee->current_network.channel = 6;
2366         /* if not then the state is not linked. Maybe the user swithced to
2367          * ad-hoc mode just after being in monitor mode, or just after
2368          * being very few time in managed mode (so the card have had no
2369          * time to scan all the chans..) or we have just run up the iface
2370          * after setting ad-hoc mode. So we have to give another try..
2371          * Here, in ibss mode, should be safe to do this without extra care
2372          * (in bss mode we had to make sure no-one tryed to associate when
2373          * we had just checked the ieee->state and we was going to start the
2374          * scan) beacause in ibss mode the ieee80211_new_net function, when
2375          * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2376          * so, at worst, we waste a bit of time to initiate an unneeded syncro
2377          * scan, that will stop at the first round because it sees the state
2378          * associated.
2379          */
2380         if (ieee->state == IEEE80211_NOLINK)
2381                 ieee80211_start_scan_syncro(ieee);
2382
2383         /* the network definitively is not here.. create a new cell */
2384         if (ieee->state == IEEE80211_NOLINK){
2385                 printk("creating new IBSS cell\n");
2386                 if(!ieee->wap_set)
2387                         ieee80211_randomize_cell(ieee);
2388
2389                 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2390
2391                         ieee->current_network.rates_len = 4;
2392
2393                         ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2394                         ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2395                         ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2396                         ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2397
2398                 }else
2399                         ieee->current_network.rates_len = 0;
2400
2401                 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2402                         ieee->current_network.rates_ex_len = 8;
2403
2404                         ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2405                         ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2406                         ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2407                         ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2408                         ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2409                         ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2410                         ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2411                         ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2412
2413                         ieee->rate = 108;
2414                 }else{
2415                         ieee->current_network.rates_ex_len = 0;
2416                         ieee->rate = 22;
2417                 }
2418
2419                 // By default, WMM function will be disabled in IBSS mode
2420                 ieee->current_network.QoS_Enable = 0;
2421                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2422                 ieee->current_network.atim_window = 0;
2423                 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2424                 if(ieee->short_slot)
2425                         ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2426
2427         }
2428
2429         ieee->state = IEEE80211_LINKED;
2430
2431         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2432         ieee->link_change(ieee->dev);
2433         if(ieee->LedControlHandler != NULL)
2434                 ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
2435         notify_wx_assoc_event(ieee);
2436
2437         ieee80211_start_send_beacons(ieee);
2438
2439         if (ieee->data_hard_resume)
2440                 ieee->data_hard_resume(ieee->dev);
2441         netif_carrier_on(ieee->dev);
2442
2443         up(&ieee->wx_sem);
2444 }
2445
2446 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2447 {
2448         queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2449 }
2450
2451 /* this is called only in user context, with wx_sem held */
2452 void ieee80211_start_bss(struct ieee80211_device *ieee)
2453 {
2454         unsigned long flags;
2455         //
2456         // Ref: 802.11d 11.1.3.3
2457         // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2458         //
2459         if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2460         {
2461                 if(! ieee->bGlobalDomain)
2462                 {
2463                         return;
2464                 }
2465         }
2466         /* check if we have already found the net we
2467          * are interested in (if any).
2468          * if not (we are disassociated and we are not
2469          * in associating / authenticating phase) start the background scanning.
2470          */
2471         ieee80211_softmac_check_all_nets(ieee);
2472
2473         /* ensure no-one start an associating process (thus setting
2474          * the ieee->state to ieee80211_ASSOCIATING) while we
2475          * have just cheked it and we are going to enable scan.
2476          * The ieee80211_new_net function is always called with
2477          * lock held (from both ieee80211_softmac_check_all_nets and
2478          * the rx path), so we cannot be in the middle of such function
2479          */
2480         spin_lock_irqsave(&ieee->lock, flags);
2481
2482         if (ieee->state == IEEE80211_NOLINK){
2483                 ieee->actscanning = true;
2484                 ieee80211_rtl_start_scan(ieee);
2485         }
2486         spin_unlock_irqrestore(&ieee->lock, flags);
2487 }
2488
2489 void ieee80211_link_change_wq(struct work_struct *work)
2490 {
2491         struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2492         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, link_change_wq);
2493
2494         ieee->link_change(ieee->dev);
2495 }
2496 /* called only in userspace context */
2497 void ieee80211_disassociate(struct ieee80211_device *ieee)
2498 {
2499
2500
2501         netif_carrier_off(ieee->dev);
2502         if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2503                         ieee80211_reset_queue(ieee);
2504
2505         if (ieee->data_hard_stop)
2506                         ieee->data_hard_stop(ieee->dev);
2507         if(IS_DOT11D_ENABLE(ieee))
2508                 Dot11d_Reset(ieee);
2509         ieee->state = IEEE80211_NOLINK;
2510         ieee->is_set_key = false;
2511
2512         //LZM for usb dev crash.
2513         //ieee->link_change(ieee->dev);
2514         queue_delayed_work(ieee->wq, &ieee->link_change_wq, 0);
2515
2516         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2517         notify_wx_assoc_event(ieee);
2518
2519 }
2520
2521 void ieee80211_associate_retry_wq(struct work_struct *work)
2522 {
2523         struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2524         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2525         unsigned long flags;
2526
2527         down(&ieee->wx_sem);
2528         if(!ieee->proto_started)
2529                 goto exit;
2530
2531         if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2532                 goto exit;
2533
2534         /* until we do not set the state to IEEE80211_NOLINK
2535         * there are no possibility to have someone else trying
2536         * to start an association procdure (we get here with
2537         * ieee->state = IEEE80211_ASSOCIATING).
2538         * When we set the state to IEEE80211_NOLINK it is possible
2539         * that the RX path run an attempt to associate, but
2540         * both ieee80211_softmac_check_all_nets and the
2541         * RX path works with ieee->lock held so there are no
2542         * problems. If we are still disassociated then start a scan.
2543         * the lock here is necessary to ensure no one try to start
2544         * an association procedure when we have just checked the
2545         * state and we are going to start the scan.
2546         */
2547         ieee->beinretry = true;
2548         ieee->state = IEEE80211_NOLINK;
2549
2550         ieee80211_softmac_check_all_nets(ieee);
2551
2552         spin_lock_irqsave(&ieee->lock, flags);
2553
2554         if(ieee->state == IEEE80211_NOLINK)
2555         {
2556                 ieee->actscanning = true;
2557                 ieee80211_rtl_start_scan(ieee);
2558         }
2559         spin_unlock_irqrestore(&ieee->lock, flags);
2560
2561         ieee->beinretry = false;
2562 exit:
2563         up(&ieee->wx_sem);
2564 }
2565
2566 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2567 {
2568         u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2569
2570         struct sk_buff *skb;
2571         struct ieee80211_probe_response *b;
2572
2573         skb = ieee80211_probe_resp(ieee, broadcast_addr);
2574
2575         if (!skb)
2576                 return NULL;
2577
2578         b = (struct ieee80211_probe_response *) skb->data;
2579         b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON);
2580
2581         return skb;
2582
2583 }
2584
2585 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2586 {
2587         struct sk_buff *skb;
2588         struct ieee80211_probe_response *b;
2589
2590         skb = ieee80211_get_beacon_(ieee);
2591         if(!skb)
2592                 return NULL;
2593
2594         b = (struct ieee80211_probe_response *) skb->data;
2595         b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2596
2597         if (ieee->seq_ctrl[0] == 0xFFF)
2598                 ieee->seq_ctrl[0] = 0;
2599         else
2600                 ieee->seq_ctrl[0]++;
2601
2602         return skb;
2603 }
2604
2605 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2606 {
2607         ieee->sync_scan_hurryup = 1;
2608         down(&ieee->wx_sem);
2609         ieee80211_stop_protocol(ieee);
2610         up(&ieee->wx_sem);
2611 }
2612
2613
2614 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2615 {
2616         if (!ieee->proto_started)
2617                 return;
2618
2619         ieee->proto_started = 0;
2620
2621         ieee80211_stop_send_beacons(ieee);
2622         del_timer_sync(&ieee->associate_timer);
2623         cancel_delayed_work(&ieee->associate_retry_wq);
2624         cancel_delayed_work(&ieee->start_ibss_wq);
2625         cancel_delayed_work(&ieee->link_change_wq);
2626         ieee80211_stop_scan(ieee);
2627
2628         ieee80211_disassociate(ieee);
2629         RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2630 }
2631
2632 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2633 {
2634         ieee->sync_scan_hurryup = 0;
2635         down(&ieee->wx_sem);
2636         ieee80211_start_protocol(ieee);
2637         up(&ieee->wx_sem);
2638 }
2639
2640 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2641 {
2642         short ch = 0;
2643         int i = 0;
2644         if (ieee->proto_started)
2645                 return;
2646
2647         ieee->proto_started = 1;
2648
2649         if (ieee->current_network.channel == 0){
2650                 do{
2651                         ch++;
2652                         if (ch > MAX_CHANNEL_NUMBER)
2653                                 return; /* no channel found */
2654                 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2655                 ieee->current_network.channel = ch;
2656         }
2657
2658         if (ieee->current_network.beacon_interval == 0)
2659                 ieee->current_network.beacon_interval = 100;
2660 //      printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2661 //      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2662
2663         for(i = 0; i < 17; i++) {
2664           ieee->last_rxseq_num[i] = -1;
2665           ieee->last_rxfrag_num[i] = -1;
2666           ieee->last_packet_time[i] = 0;
2667         }
2668
2669         ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2670
2671
2672         /* if the user set the MAC of the ad-hoc cell and then
2673          * switch to managed mode, shall we  make sure that association
2674          * attempts does not fail just because the user provide the essid
2675          * and the nic is still checking for the AP MAC ??
2676          */
2677         if (ieee->iw_mode == IW_MODE_INFRA)
2678                 ieee80211_start_bss(ieee);
2679
2680         else if (ieee->iw_mode == IW_MODE_ADHOC)
2681                 ieee80211_start_ibss(ieee);
2682
2683         else if (ieee->iw_mode == IW_MODE_MASTER)
2684                 ieee80211_start_master_bss(ieee);
2685
2686         else if(ieee->iw_mode == IW_MODE_MONITOR)
2687                 ieee80211_start_monitor_mode(ieee);
2688 }
2689
2690
2691 #define DRV_NAME  "Ieee80211"
2692 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2693 {
2694         int i;
2695         memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2696
2697         ieee->state = IEEE80211_NOLINK;
2698         ieee->sync_scan_hurryup = 0;
2699         for(i = 0; i < 5; i++) {
2700           ieee->seq_ctrl[i] = 0;
2701         }
2702         ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2703         if (!ieee->pDot11dInfo)
2704                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
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 = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2848                               GFP_KERNEL);
2849                 if (buf == NULL)
2850                         return -ENOMEM;
2851
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 = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3051                 if (new_crypt == NULL) {
3052                         ret = -ENOMEM;
3053                         goto done;
3054                 }
3055                 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3056                 new_crypt->ops = ops;
3057
3058                 if (new_crypt->ops)
3059                         new_crypt->priv =
3060                                 new_crypt->ops->init(param->u.crypt.idx);
3061
3062                 if (new_crypt->priv == NULL) {
3063                         kfree(new_crypt);
3064                         param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3065                         ret = -EINVAL;
3066                         goto done;
3067                 }
3068
3069                 *crypt = new_crypt;
3070         }
3071
3072         if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3073             (*crypt)->ops->set_key(param->u.crypt.key,
3074                                    param->u.crypt.key_len, param->u.crypt.seq,
3075                                    (*crypt)->priv) < 0) {
3076                 printk("key setting failed\n");
3077                 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3078                 ret = -EINVAL;
3079                 goto done;
3080         }
3081
3082  skip_host_crypt:
3083         if (param->u.crypt.set_tx) {
3084                 ieee->tx_keyidx = param->u.crypt.idx;
3085                 sec.active_key = param->u.crypt.idx;
3086                 sec.flags |= SEC_ACTIVE_KEY;
3087         } else
3088                 sec.flags &= ~SEC_ACTIVE_KEY;
3089
3090         if (param->u.crypt.alg != NULL) {
3091                 memcpy(sec.keys[param->u.crypt.idx],
3092                        param->u.crypt.key,
3093                        param->u.crypt.key_len);
3094                 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3095                 sec.flags |= (1 << param->u.crypt.idx);
3096
3097                 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3098                         sec.flags |= SEC_LEVEL;
3099                         sec.level = SEC_LEVEL_1;
3100                 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3101                         sec.flags |= SEC_LEVEL;
3102                         sec.level = SEC_LEVEL_2;
3103                 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3104                         sec.flags |= SEC_LEVEL;
3105                         sec.level = SEC_LEVEL_3;
3106                 }
3107         }
3108  done:
3109         if (ieee->set_security)
3110                 ieee->set_security(ieee->dev, &sec);
3111
3112         /* Do not reset port if card is in Managed mode since resetting will
3113          * generate new IEEE 802.11 authentication which may end up in looping
3114          * with IEEE 802.1X.  If your hardware requires a reset after WEP
3115          * configuration (for example... Prism2), implement the reset_port in
3116          * the callbacks structures used to initialize the 802.11 stack. */
3117         if (ieee->reset_on_keychange &&
3118             ieee->iw_mode != IW_MODE_INFRA &&
3119             ieee->reset_port &&
3120             ieee->reset_port(ieee->dev)) {
3121                 printk("reset_port failed\n");
3122                 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3123                 return -EINVAL;
3124         }
3125
3126         return ret;
3127 }
3128
3129 inline struct sk_buff *ieee80211_disassociate_skb(
3130                                                         struct ieee80211_network *beacon,
3131                                                         struct ieee80211_device *ieee,
3132                                                         u8      asRsn)
3133 {
3134         struct sk_buff *skb;
3135         struct ieee80211_disassoc *disass;
3136
3137         skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3138         if (!skb)
3139                 return NULL;
3140
3141         disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3142         disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3143         disass->header.duration_id = 0;
3144
3145         memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3146         memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3147         memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3148
3149         disass->reason = asRsn;
3150         return skb;
3151 }
3152
3153
3154 void
3155 SendDisassociation(
3156                 struct ieee80211_device *ieee,
3157                 u8*                                     asSta,
3158                 u8                                              asRsn
3159 )
3160 {
3161                 struct ieee80211_network *beacon = &ieee->current_network;
3162                 struct sk_buff *skb;
3163                 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3164                 if (skb){
3165                                 softmac_mgmt_xmit(skb, ieee);
3166                                 //dev_kfree_skb_any(skb);//edit by thomas
3167                 }
3168 }
3169
3170 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3171 {
3172         struct ieee_param *param;
3173         int ret=0;
3174
3175         down(&ieee->wx_sem);
3176         //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3177
3178         if (p->length < sizeof(struct ieee_param) || !p->pointer){
3179                 ret = -EINVAL;
3180                 goto out;
3181         }
3182
3183         param = kmalloc(p->length, GFP_KERNEL);
3184         if (param == NULL){
3185                 ret = -ENOMEM;
3186                 goto out;
3187         }
3188         if (copy_from_user(param, p->pointer, p->length)) {
3189                 kfree(param);
3190                 ret = -EFAULT;
3191                 goto out;
3192         }
3193
3194         switch (param->cmd) {
3195
3196         case IEEE_CMD_SET_WPA_PARAM:
3197                 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3198                                         param->u.wpa_param.value);
3199                 break;
3200
3201         case IEEE_CMD_SET_WPA_IE:
3202                 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3203                 break;
3204
3205         case IEEE_CMD_SET_ENCRYPTION:
3206                 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3207                 break;
3208
3209         case IEEE_CMD_MLME:
3210                 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3211                                    param->u.mlme.reason_code);
3212                 break;
3213
3214         default:
3215                 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3216                 ret = -EOPNOTSUPP;
3217                 break;
3218         }
3219
3220         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3221                 ret = -EFAULT;
3222
3223         kfree(param);
3224 out:
3225         up(&ieee->wx_sem);
3226
3227         return ret;
3228 }
3229
3230 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3231 {
3232         union iwreq_data wrqu;
3233         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3234         if (ieee->state == IEEE80211_LINKED)
3235                 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3236         else
3237                 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3238         wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3239 }