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