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