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