]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
staging: rtl8192u: Fixing no new typedef warning
[karo-tx-linux.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(skb, beacon->ssid_len);
1119         memcpy(tag, beacon->ssid, beacon->ssid_len);
1120
1121         tag = skb_put(skb, rate_len);
1122
1123         ieee80211_MFIE_Brate(ieee, &tag);
1124         ieee80211_MFIE_Grate(ieee, &tag);
1125         // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1126         if (beacon->bCkipSupported) {
1127                 static u8       AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1128                 u8      CcxAironetBuf[30];
1129                 OCTET_STRING    osCcxAironetIE;
1130
1131                 memset(CcxAironetBuf, 0, 30);
1132                 osCcxAironetIE.Octet = CcxAironetBuf;
1133                 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1134                 //
1135                 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1136                 // We want to make the device type as "4500-client". 060926, by CCW.
1137                 //
1138                 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1139
1140                 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1141                 // "The CKIP negotiation is started with the associate request from the client to the access point,
1142                 //  containing an Aironet element with both the MIC and KP bits set."
1143                 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |=  (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1144                 tag = skb_put(skb, ckip_ie_len);
1145                 *tag++ = MFIE_TYPE_AIRONET;
1146                 *tag++ = osCcxAironetIE.Length;
1147                 memcpy(tag, osCcxAironetIE.Octet, osCcxAironetIE.Length);
1148                 tag += osCcxAironetIE.Length;
1149         }
1150
1151         if (beacon->bCcxRmEnable)
1152         {
1153                 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1154                 OCTET_STRING osCcxRmCap;
1155
1156                 osCcxRmCap.Octet = CcxRmCapBuf;
1157                 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1158                 tag = skb_put(skb, ccxrm_ie_len);
1159                 *tag++ = MFIE_TYPE_GENERIC;
1160                 *tag++ = osCcxRmCap.Length;
1161                 memcpy(tag, osCcxRmCap.Octet, osCcxRmCap.Length);
1162                 tag += osCcxRmCap.Length;
1163         }
1164
1165         if (beacon->BssCcxVerNumber >= 2) {
1166                 u8                      CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1167                 OCTET_STRING    osCcxVerNum;
1168                 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1169                 osCcxVerNum.Octet = CcxVerNumBuf;
1170                 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1171                 tag = skb_put(skb, cxvernum_ie_len);
1172                 *tag++ = MFIE_TYPE_GENERIC;
1173                 *tag++ = osCcxVerNum.Length;
1174                 memcpy(tag, osCcxVerNum.Octet, osCcxVerNum.Length);
1175                 tag += osCcxVerNum.Length;
1176         }
1177         //HT cap element
1178         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1179                 if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1180                 {
1181                         tag = skb_put(skb, ht_cap_len);
1182                         *tag++ = MFIE_TYPE_HT_CAP;
1183                         *tag++ = ht_cap_len - 2;
1184                         memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1185                         tag += ht_cap_len -2;
1186                 }
1187         }
1188
1189
1190         //choose what wpa_supplicant gives to associate.
1191         tag = skb_put(skb, wpa_ie_len);
1192         if (wpa_ie_len) {
1193                 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1194         }
1195
1196         tag = skb_put(skb, wmm_info_len);
1197         if (wmm_info_len) {
1198           ieee80211_WMM_Info(ieee, &tag);
1199         }
1200 #ifdef THOMAS_TURBO
1201         tag = skb_put(skb, turbo_info_len);
1202         if (turbo_info_len) {
1203                 ieee80211_TURBO_Info(ieee, &tag);
1204         }
1205 #endif
1206
1207         if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1208                 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1209                 {
1210                         tag = skb_put(skb, ht_cap_len);
1211                         *tag++ = MFIE_TYPE_GENERIC;
1212                         *tag++ = ht_cap_len - 2;
1213                         memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1214                         tag += ht_cap_len -2;
1215                 }
1216
1217                 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1218                         tag = skb_put(skb, realtek_ie_len);
1219                         *tag++ = MFIE_TYPE_GENERIC;
1220                         *tag++ = realtek_ie_len - 2;
1221                         memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
1222                 }
1223         }
1224 //      printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1225 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1226         return skb;
1227 }
1228
1229 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1230 {
1231
1232         unsigned long flags;
1233         spin_lock_irqsave(&ieee->lock, flags);
1234
1235         ieee->associate_seq++;
1236
1237         /* don't scan, and avoid to have the RX path possibily
1238          * try again to associate. Even do not react to AUTH or
1239          * ASSOC response. Just wait for the retry wq to be scheduled.
1240          * Here we will check if there are good nets to associate
1241          * with, so we retry or just get back to NO_LINK and scanning
1242          */
1243         if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1244                 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1245                 ieee->softmac_stats.no_auth_rs++;
1246         }else{
1247                 IEEE80211_DEBUG_MGMT("Association failed\n");
1248                 ieee->softmac_stats.no_ass_rs++;
1249         }
1250
1251         ieee->state = IEEE80211_ASSOCIATING_RETRY;
1252
1253         schedule_delayed_work(&ieee->associate_retry_wq, \
1254                            IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1255
1256         spin_unlock_irqrestore(&ieee->lock, flags);
1257 }
1258
1259 static void ieee80211_associate_abort_cb(unsigned long dev)
1260 {
1261         ieee80211_associate_abort((struct ieee80211_device *) dev);
1262 }
1263
1264
1265 static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1266 {
1267         struct ieee80211_network *beacon = &ieee->current_network;
1268         struct sk_buff *skb;
1269
1270         IEEE80211_DEBUG_MGMT("Stopping scan\n");
1271
1272         ieee->softmac_stats.tx_auth_rq++;
1273         skb=ieee80211_authentication_req(beacon, ieee, 0);
1274
1275         if (!skb)
1276                 ieee80211_associate_abort(ieee);
1277         else{
1278                 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1279                 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1280                 softmac_mgmt_xmit(skb, ieee);
1281                 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1282                 if (!timer_pending(&ieee->associate_timer)) {
1283                         ieee->associate_timer.expires = jiffies + (HZ / 2);
1284                         add_timer(&ieee->associate_timer);
1285                 }
1286                 //dev_kfree_skb_any(skb);//edit by thomas
1287         }
1288 }
1289
1290 static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1291                                      u8 *challenge,
1292                                      int chlen)
1293 {
1294         u8 *c;
1295         struct sk_buff *skb;
1296         struct ieee80211_network *beacon = &ieee->current_network;
1297 //      int hlen = sizeof(struct ieee80211_authentication);
1298
1299         ieee->associate_seq++;
1300         ieee->softmac_stats.tx_auth_rq++;
1301
1302         skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1303         if (!skb)
1304                 ieee80211_associate_abort(ieee);
1305         else{
1306                 c = skb_put(skb, chlen+2);
1307                 *(c++) = MFIE_TYPE_CHALLENGE;
1308                 *(c++) = chlen;
1309                 memcpy(c, challenge, chlen);
1310
1311                 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1312
1313                 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr  ));
1314
1315                 softmac_mgmt_xmit(skb, ieee);
1316                 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1317                 //dev_kfree_skb_any(skb);//edit by thomas
1318         }
1319         kfree(challenge);
1320 }
1321
1322 static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1323 {
1324         struct sk_buff *skb;
1325         struct ieee80211_network *beacon = &ieee->current_network;
1326
1327         del_timer_sync(&ieee->associate_timer);
1328
1329         IEEE80211_DEBUG_MGMT("Sending association request\n");
1330
1331         ieee->softmac_stats.tx_ass_rq++;
1332         skb=ieee80211_association_req(beacon, ieee);
1333         if (!skb)
1334                 ieee80211_associate_abort(ieee);
1335         else{
1336                 softmac_mgmt_xmit(skb, ieee);
1337                 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1338                 //dev_kfree_skb_any(skb);//edit by thomas
1339         }
1340 }
1341 static void ieee80211_associate_complete_wq(struct work_struct *work)
1342 {
1343         struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1344         printk(KERN_INFO "Associated successfully\n");
1345         if(ieee80211_is_54g(&ieee->current_network) &&
1346                 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1347
1348                 ieee->rate = 108;
1349                 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1350         }else{
1351                 ieee->rate = 22;
1352                 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1353         }
1354         if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1355         {
1356                 printk("Successfully associated, ht enabled\n");
1357                 HTOnAssocRsp(ieee);
1358         }
1359         else
1360         {
1361                 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1362                 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1363                 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1364         }
1365         ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1366         // To prevent the immediately calling watch_dog after association.
1367         if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1368         {
1369                 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1370                 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1371         }
1372         ieee->link_change(ieee->dev);
1373         if (!ieee->is_silent_reset) {
1374                 printk("============>normal associate\n");
1375                 notify_wx_assoc_event(ieee);
1376         } else {
1377                 printk("==================>silent reset associate\n");
1378                 ieee->is_silent_reset = false;
1379         }
1380
1381         if (ieee->data_hard_resume)
1382                 ieee->data_hard_resume(ieee->dev);
1383         netif_carrier_on(ieee->dev);
1384 }
1385
1386 static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1387 {
1388 //      int i;
1389 //      struct net_device* dev = ieee->dev;
1390         del_timer_sync(&ieee->associate_timer);
1391
1392         ieee->state = IEEE80211_LINKED;
1393         //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1394         schedule_work(&ieee->associate_complete_wq);
1395 }
1396
1397 static void ieee80211_associate_procedure_wq(struct work_struct *work)
1398 {
1399         struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1400         ieee->sync_scan_hurryup = 1;
1401         mutex_lock(&ieee->wx_mutex);
1402
1403         if (ieee->data_hard_stop)
1404                 ieee->data_hard_stop(ieee->dev);
1405
1406         ieee80211_stop_scan(ieee);
1407         printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1408         //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1409         HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1410
1411         ieee->associate_seq = 1;
1412         ieee80211_associate_step1(ieee);
1413
1414         mutex_unlock(&ieee->wx_mutex);
1415 }
1416
1417 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1418 {
1419         u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1420         int tmp_ssid_len = 0;
1421
1422         short apset, ssidset, ssidbroad, apmatch, ssidmatch;
1423
1424         /* we are interested in new new only if we are not associated
1425          * and we are not associating / authenticating
1426          */
1427         if (ieee->state != IEEE80211_NOLINK)
1428                 return;
1429
1430         if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1431                 return;
1432
1433         if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1434                 return;
1435
1436
1437         if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
1438                 /* if the user specified the AP MAC, we need also the essid
1439                  * This could be obtained by beacons or, if the network does not
1440                  * broadcast it, it can be put manually.
1441                  */
1442                 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1443                 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1444                 ssidbroad =  !(net->ssid_len == 0 || net->ssid[0]== '\0');
1445                 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1446                 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1447                                 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1448
1449
1450                 if (    /* if the user set the AP check if match.
1451                          * if the network does not broadcast essid we check the user supplyed ANY essid
1452                          * if the network does broadcast and the user does not set essid it is OK
1453                          * if the network does broadcast and the user did set essid chech if essid match
1454                          */
1455                         (apset && apmatch &&
1456                                 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1457                         /* if the ap is not set, check that the user set the bssid
1458                          * and the network does broadcast and that those two bssid matches
1459                          */
1460                         (!apset && ssidset && ssidbroad && ssidmatch)
1461                         ){
1462                                 /* if the essid is hidden replace it with the
1463                                 * essid provided by the user.
1464                                 */
1465                                 if (!ssidbroad) {
1466                                         strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1467                                         tmp_ssid_len = ieee->current_network.ssid_len;
1468                                 }
1469                                 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1470
1471                                 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1472                                 ieee->current_network.ssid_len = tmp_ssid_len;
1473                                 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);
1474
1475                                 //ieee->pHTInfo->IOTAction = 0;
1476                                 HTResetIOTSetting(ieee->pHTInfo);
1477                                 if (ieee->iw_mode == IW_MODE_INFRA){
1478                                         /* Join the network for the first time */
1479                                         ieee->AsocRetryCount = 0;
1480                                         //for HT by amy 080514
1481                                         if((ieee->current_network.qos_data.supported == 1) &&
1482                                           // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1483                                            ieee->current_network.bssht.bdSupportHT)
1484 /*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
1485                                         {
1486                                         //      ieee->pHTInfo->bCurrentHTSupport = true;
1487                                                 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1488                                         }
1489                                         else
1490                                         {
1491                                                 ieee->pHTInfo->bCurrentHTSupport = false;
1492                                         }
1493
1494                                         ieee->state = IEEE80211_ASSOCIATING;
1495                                         schedule_work(&ieee->associate_procedure_wq);
1496                                 }else{
1497                                         if(ieee80211_is_54g(&ieee->current_network) &&
1498                                                 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1499                                                 ieee->rate = 108;
1500                                                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1501                                                 printk(KERN_INFO"Using G rates\n");
1502                                         }else{
1503                                                 ieee->rate = 22;
1504                                                 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1505                                                 printk(KERN_INFO"Using B rates\n");
1506                                         }
1507                                         memset(ieee->dot11HTOperationalRateSet, 0, 16);
1508                                         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1509                                         ieee->state = IEEE80211_LINKED;
1510                                 }
1511
1512                 }
1513         }
1514
1515 }
1516
1517 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1518 {
1519         unsigned long flags;
1520         struct ieee80211_network *target;
1521
1522         spin_lock_irqsave(&ieee->lock, flags);
1523
1524         list_for_each_entry(target, &ieee->network_list, list) {
1525
1526                 /* if the state become different that NOLINK means
1527                  * we had found what we are searching for
1528                  */
1529
1530                 if (ieee->state != IEEE80211_NOLINK)
1531                         break;
1532
1533                 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1534                         ieee80211_softmac_new_net(ieee, target);
1535         }
1536
1537         spin_unlock_irqrestore(&ieee->lock, flags);
1538
1539 }
1540
1541
1542 static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1543 {
1544         struct ieee80211_authentication *a;
1545         u8 *t;
1546         if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1547                 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1548                 return 0xcafe;
1549         }
1550         *challenge = NULL;
1551         a = (struct ieee80211_authentication *) skb->data;
1552         if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1553                 t = skb->data + sizeof(struct ieee80211_authentication);
1554
1555                 if (*(t++) == MFIE_TYPE_CHALLENGE) {
1556                         *chlen = *(t++);
1557                         *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1558                         if (!*challenge)
1559                                 return -ENOMEM;
1560                 }
1561         }
1562
1563         return le16_to_cpu(a->status);
1564
1565 }
1566
1567
1568 static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1569 {
1570         struct ieee80211_authentication *a;
1571
1572         if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1573                 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1574                 return -1;
1575         }
1576         a = (struct ieee80211_authentication *) skb->data;
1577
1578         memcpy(dest,a->header.addr2, ETH_ALEN);
1579
1580         if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1581                 return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1582
1583         return WLAN_STATUS_SUCCESS;
1584 }
1585
1586 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1587 {
1588         u8 *tag;
1589         u8 *skbend;
1590         u8 *ssid=NULL;
1591         u8 ssidlen = 0;
1592
1593         struct rtl_80211_hdr_3addr   *header =
1594                 (struct rtl_80211_hdr_3addr   *) skb->data;
1595
1596         if (skb->len < sizeof (struct rtl_80211_hdr_3addr  ))
1597                 return -1; /* corrupted */
1598
1599         memcpy(src,header->addr2, ETH_ALEN);
1600
1601         skbend = (u8 *)skb->data + skb->len;
1602
1603         tag = skb->data + sizeof (struct rtl_80211_hdr_3addr  );
1604
1605         while (tag+1 < skbend){
1606                 if (*tag == 0) {
1607                         ssid = tag+2;
1608                         ssidlen = *(tag+1);
1609                         break;
1610                 }
1611                 tag++; /* point to the len field */
1612                 tag = tag + *(tag); /* point to the last data byte of the tag */
1613                 tag++; /* point to the next tag */
1614         }
1615
1616         //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1617         if (ssidlen == 0) return 1;
1618
1619         if (!ssid) return 1; /* ssid not found in tagged param */
1620         return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1621
1622 }
1623
1624 static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1625 {
1626         struct ieee80211_assoc_request_frame *a;
1627
1628         if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1629                 sizeof(struct ieee80211_info_element))) {
1630
1631                 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1632                 return -1;
1633         }
1634
1635         a = (struct ieee80211_assoc_request_frame *) skb->data;
1636
1637         memcpy(dest,a->header.addr2,ETH_ALEN);
1638
1639         return 0;
1640 }
1641
1642 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1643 {
1644         struct ieee80211_assoc_response_frame *response_head;
1645         u16 status_code;
1646
1647         if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1648                 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1649                 return 0xcafe;
1650         }
1651
1652         response_head = (struct ieee80211_assoc_response_frame *) skb->data;
1653         *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1654
1655         status_code = le16_to_cpu(response_head->status);
1656         if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1657            status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1658            ((ieee->mode == IEEE_G) &&
1659             (ieee->current_network.mode == IEEE_N_24G) &&
1660             (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1661                  ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1662         }else {
1663                  ieee->AsocRetryCount = 0;
1664         }
1665
1666         return le16_to_cpu(response_head->status);
1667 }
1668
1669 static inline void
1670 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1671 {
1672         u8 dest[ETH_ALEN];
1673
1674         //IEEE80211DMESG("Rx probe");
1675         ieee->softmac_stats.rx_probe_rq++;
1676         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1677         if (probe_rq_parse(ieee, skb, dest)) {
1678                 //IEEE80211DMESG("Was for me!");
1679                 ieee->softmac_stats.tx_probe_rs++;
1680                 ieee80211_resp_to_probe(ieee, dest);
1681         }
1682 }
1683
1684 static inline void
1685 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1686 {
1687         u8 dest[ETH_ALEN];
1688         int status;
1689         //IEEE80211DMESG("Rx probe");
1690         ieee->softmac_stats.rx_auth_rq++;
1691
1692         status = auth_rq_parse(skb, dest);
1693         if (status != -1) {
1694                 ieee80211_resp_to_auth(ieee, status, dest);
1695         }
1696         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1697
1698 }
1699
1700 static inline void
1701 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1702 {
1703
1704         u8 dest[ETH_ALEN];
1705         //unsigned long flags;
1706
1707         ieee->softmac_stats.rx_ass_rq++;
1708         if (assoc_rq_parse(skb, dest) != -1) {
1709                 ieee80211_resp_to_assoc_rq(ieee, dest);
1710         }
1711
1712         printk(KERN_INFO"New client associated: %pM\n", dest);
1713         //FIXME
1714 }
1715
1716 static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1717                                              short pwr)
1718 {
1719
1720         struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1721
1722         if (buf)
1723                 softmac_ps_mgmt_xmit(buf, ieee);
1724
1725 }
1726 /* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1727
1728 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1729                                     u32 *time_l)
1730 {
1731         int timeout = ieee->ps_timeout;
1732         u8 dtim;
1733         /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1734                 ieee->iw_mode != IW_MODE_INFRA ||
1735                 ieee->state != IEEE80211_LINKED)
1736
1737                 return 0;
1738         */
1739         dtim = ieee->current_network.dtim_data;
1740         if(!(dtim & IEEE80211_DTIM_VALID))
1741                 return 0;
1742         timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1743         ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1744
1745         if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1746                 return 2;
1747
1748         if(!time_after(jiffies,
1749                        dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
1750                 return 0;
1751
1752         if(!time_after(jiffies,
1753                        ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
1754                 return 0;
1755
1756         if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1757                 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1758                 return 0;
1759
1760         if (time_l) {
1761                 *time_l = ieee->current_network.last_dtim_sta_time[0]
1762                         + (ieee->current_network.beacon_interval
1763                         * ieee->current_network.dtim_period) * 1000;
1764         }
1765
1766         if (time_h) {
1767                 *time_h = ieee->current_network.last_dtim_sta_time[1];
1768                 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1769                         *time_h += 1;
1770         }
1771
1772         return 1;
1773
1774
1775 }
1776
1777 static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1778 {
1779
1780         u32 th, tl;
1781         short sleep;
1782
1783         unsigned long flags, flags2;
1784
1785         spin_lock_irqsave(&ieee->lock, flags);
1786
1787         if ((ieee->ps == IEEE80211_PS_DISABLED ||
1788                 ieee->iw_mode != IW_MODE_INFRA ||
1789                 ieee->state != IEEE80211_LINKED)){
1790
1791         //      #warning CHECK_LOCK_HERE
1792                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1793
1794                 ieee80211_sta_wakeup(ieee, 1);
1795
1796                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1797         }
1798
1799         sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1800         /* 2 wake, 1 sleep, 0 do nothing */
1801         if(sleep == 0)
1802                 goto out;
1803
1804         if(sleep == 1){
1805
1806                 if(ieee->sta_sleep == 1)
1807                         ieee->enter_sleep_state(ieee->dev, th, tl);
1808
1809                 else if(ieee->sta_sleep == 0){
1810                 //      printk("send null 1\n");
1811                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1812
1813                         if(ieee->ps_is_queue_empty(ieee->dev)){
1814
1815
1816                                 ieee->sta_sleep = 2;
1817
1818                                 ieee->ps_request_tx_ack(ieee->dev);
1819
1820                                 ieee80211_sta_ps_send_null_frame(ieee, 1);
1821
1822                                 ieee->ps_th = th;
1823                                 ieee->ps_tl = tl;
1824                         }
1825                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1826
1827                 }
1828
1829
1830         }else if(sleep == 2){
1831 //#warning CHECK_LOCK_HERE
1832                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1833
1834                 ieee80211_sta_wakeup(ieee, 1);
1835
1836                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1837         }
1838
1839 out:
1840         spin_unlock_irqrestore(&ieee->lock, flags);
1841
1842 }
1843
1844 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1845 {
1846         if (ieee->sta_sleep == 0) {
1847                 if (nl) {
1848                         printk("Warning: driver is probably failing to report TX ps error\n");
1849                         ieee->ps_request_tx_ack(ieee->dev);
1850                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1851                 }
1852                 return;
1853
1854         }
1855
1856         if(ieee->sta_sleep == 1)
1857                 ieee->sta_wake_up(ieee->dev);
1858
1859         ieee->sta_sleep = 0;
1860
1861         if (nl) {
1862                 ieee->ps_request_tx_ack(ieee->dev);
1863                 ieee80211_sta_ps_send_null_frame(ieee, 0);
1864         }
1865 }
1866
1867 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1868 {
1869         unsigned long flags, flags2;
1870
1871         spin_lock_irqsave(&ieee->lock, flags);
1872
1873         if(ieee->sta_sleep == 2){
1874                 /* Null frame with PS bit set */
1875                 if (success) {
1876                         ieee->sta_sleep = 1;
1877                         ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1878                 }
1879                 /* if the card report not success we can't be sure the AP
1880                  * has not RXed so we can't assume the AP believe us awake
1881                  */
1882         }
1883         /* 21112005 - tx again null without PS bit if lost */
1884         else {
1885
1886                 if ((ieee->sta_sleep == 0) && !success) {
1887                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1888                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1889                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1890                 }
1891         }
1892         spin_unlock_irqrestore(&ieee->lock, flags);
1893 }
1894 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1895
1896 static void ieee80211_process_action(struct ieee80211_device *ieee,
1897                                      struct sk_buff *skb)
1898 {
1899         struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
1900         u8 *act = ieee80211_get_payload(header);
1901         u8 tmp = 0;
1902 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1903         if (act == NULL)
1904         {
1905                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1906                 return;
1907         }
1908         tmp = *act;
1909         act ++;
1910         switch (tmp) {
1911         case ACT_CAT_BA:
1912                 if (*act == ACT_ADDBAREQ)
1913                         ieee80211_rx_ADDBAReq(ieee, skb);
1914                 else if (*act == ACT_ADDBARSP)
1915                         ieee80211_rx_ADDBARsp(ieee, skb);
1916                 else if (*act == ACT_DELBA)
1917                         ieee80211_rx_DELBA(ieee, skb);
1918                 break;
1919         default:
1920                 break;
1921         }
1922         return;
1923
1924 }
1925
1926 static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1927                                           struct sk_buff *skb)
1928 {
1929         /* default support N mode, disable halfNmode */
1930         bool bSupportNmode = true, bHalfSupportNmode = false;
1931         u16 errcode;
1932         u8 *challenge;
1933         int chlen = 0;
1934         u32 iotAction;
1935
1936         errcode = auth_parse(skb, &challenge, &chlen);
1937         if (!errcode) {
1938                 if (ieee->open_wep || !challenge) {
1939                         ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1940                         ieee->softmac_stats.rx_auth_rs_ok++;
1941                         iotAction = ieee->pHTInfo->IOTAction;
1942                         if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1943                                 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1944                                         /* WEP or TKIP encryption */
1945                                         if (IsHTHalfNmodeAPs(ieee)) {
1946                                                 bSupportNmode = true;
1947                                                 bHalfSupportNmode = true;
1948                                         } else {
1949                                                 bSupportNmode = false;
1950                                                 bHalfSupportNmode = false;
1951                                         }
1952                                         netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1953                                                         bSupportNmode,
1954                                                         bHalfSupportNmode);
1955                                 }
1956                         }
1957                         /* Dummy wirless mode setting- avoid encryption issue */
1958                         if (bSupportNmode) {
1959                                 /* N mode setting */
1960                                 ieee->SetWirelessMode(ieee->dev,
1961                                                 ieee->current_network.mode);
1962                         } else {
1963                                 /* b/g mode setting - TODO */
1964                                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1965                         }
1966
1967                         if (ieee->current_network.mode == IEEE_N_24G &&
1968                                         bHalfSupportNmode) {
1969                                 netdev_dbg(ieee->dev, "enter half N mode\n");
1970                                 ieee->bHalfWirelessN24GMode = true;
1971                         } else
1972                                 ieee->bHalfWirelessN24GMode = false;
1973
1974                         ieee80211_associate_step2(ieee);
1975                 } else {
1976                         ieee80211_auth_challenge(ieee, challenge, chlen);
1977                 }
1978         } else {
1979                 ieee->softmac_stats.rx_auth_rs_err++;
1980                 IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1981                 ieee80211_associate_abort(ieee);
1982         }
1983 }
1984
1985 inline int
1986 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1987                         struct ieee80211_rx_stats *rx_stats, u16 type,
1988                         u16 stype)
1989 {
1990         struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *) skb->data;
1991         u16 errcode;
1992         int aid;
1993         struct ieee80211_assoc_response_frame *assoc_resp;
1994 //      struct ieee80211_info_element *info_element;
1995
1996         if(!ieee->proto_started)
1997                 return 0;
1998
1999         if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2000                 ieee->iw_mode == IW_MODE_INFRA &&
2001                 ieee->state == IEEE80211_LINKED))
2002
2003                 tasklet_schedule(&ieee->ps_task);
2004
2005         if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2006                 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2007                 ieee->last_rx_ps_time = jiffies;
2008
2009         switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2010
2011         case IEEE80211_STYPE_ASSOC_RESP:
2012         case IEEE80211_STYPE_REASSOC_RESP:
2013
2014                 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2015                                 WLAN_FC_GET_STYPE(header->frame_ctl));
2016                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2017                         ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2018                         ieee->iw_mode == IW_MODE_INFRA){
2019                         struct ieee80211_network network_resp;
2020                         struct ieee80211_network *network = &network_resp;
2021
2022                         errcode = assoc_parse(ieee, skb, &aid);
2023                         if (!errcode) {
2024                                 ieee->state=IEEE80211_LINKED;
2025                                 ieee->assoc_id = aid;
2026                                 ieee->softmac_stats.rx_ass_ok++;
2027                                 /* station support qos */
2028                                 /* Let the register setting defaultly with Legacy station */
2029                                 if (ieee->qos_support) {
2030                                         assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
2031                                         memset(network, 0, sizeof(*network));
2032                                         if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2033                                                                 rx_stats->len - sizeof(*assoc_resp),\
2034                                                                 network,rx_stats)){
2035                                                 return 1;
2036                                         }
2037                                         else
2038                                         {       //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2039                                                 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2040                                                 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2041                                         }
2042                                         if (ieee->handle_assoc_response != NULL)
2043                                                 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
2044                                 }
2045                                 ieee80211_associate_complete(ieee);
2046                         } else {
2047                                 /* aid could not been allocated */
2048                                 ieee->softmac_stats.rx_ass_err++;
2049                                 printk(
2050                                         "Association response status code 0x%x\n",
2051                                         errcode);
2052                                 IEEE80211_DEBUG_MGMT(
2053                                         "Association response status code 0x%x\n",
2054                                         errcode);
2055                                 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2056                                         schedule_work(&ieee->associate_procedure_wq);
2057                                 } else {
2058                                         ieee80211_associate_abort(ieee);
2059                                 }
2060                         }
2061                 }
2062                 break;
2063
2064         case IEEE80211_STYPE_ASSOC_REQ:
2065         case IEEE80211_STYPE_REASSOC_REQ:
2066
2067                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2068                         ieee->iw_mode == IW_MODE_MASTER)
2069
2070                         ieee80211_rx_assoc_rq(ieee, skb);
2071                 break;
2072
2073         case IEEE80211_STYPE_AUTH:
2074
2075                 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
2076                         if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
2077                                 && ieee->iw_mode == IW_MODE_INFRA) {
2078
2079                                 IEEE80211_DEBUG_MGMT("Received auth response");
2080                                 ieee80211_check_auth_response(ieee, skb);
2081                         } else if (ieee->iw_mode == IW_MODE_MASTER) {
2082                                 ieee80211_rx_auth_rq(ieee, skb);
2083                         }
2084                 }
2085                 break;
2086
2087         case IEEE80211_STYPE_PROBE_REQ:
2088
2089                 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2090                         ((ieee->iw_mode == IW_MODE_ADHOC ||
2091                         ieee->iw_mode == IW_MODE_MASTER) &&
2092                         ieee->state == IEEE80211_LINKED)){
2093                         ieee80211_rx_probe_rq(ieee, skb);
2094                 }
2095                 break;
2096
2097         case IEEE80211_STYPE_DISASSOC:
2098         case IEEE80211_STYPE_DEAUTH:
2099                 /* FIXME for now repeat all the association procedure
2100                 * both for disassociation and deauthentication
2101                 */
2102                 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2103                         ieee->state == IEEE80211_LINKED &&
2104                         ieee->iw_mode == IW_MODE_INFRA){
2105
2106                         ieee->state = IEEE80211_ASSOCIATING;
2107                         ieee->softmac_stats.reassoc++;
2108
2109                         notify_wx_assoc_event(ieee);
2110                         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2111                         RemovePeerTS(ieee, header->addr2);
2112                         schedule_work(&ieee->associate_procedure_wq);
2113                 }
2114                 break;
2115         case IEEE80211_STYPE_MANAGE_ACT:
2116                 ieee80211_process_action(ieee, skb);
2117                 break;
2118         default:
2119                 return -1;
2120         }
2121
2122         //dev_kfree_skb_any(skb);
2123         return 0;
2124 }
2125
2126 /* The following are for a simpler TX queue management.
2127  * Instead of using netif_[stop/wake]_queue, the driver
2128  * will use these two functions (plus a reset one) that
2129  * will internally call the kernel netif_* and take care
2130  * of the ieee802.11 fragmentation.
2131  * So, the driver receives a fragment at a time and might
2132  * call the stop function when it wants, without taking
2133  * care to have enough room to TX an entire packet.
2134  * This might be useful if each fragment needs its own
2135  * descriptor. Thus, just keeping a total free memory > than
2136  * the max fragmentation threshold is not enough. If the
2137  * ieee802.11 stack passed a TXB struct, then you would need
2138  * to keep N free descriptors where
2139  * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
2140  * In this way you need just one and the 802.11 stack
2141  * will take care of buffering fragments and pass them to
2142  * to the driver later, when it wakes the queue.
2143  */
2144 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2145 {
2146
2147         unsigned int queue_index = txb->queue_index;
2148         unsigned long flags;
2149         int  i;
2150         struct cb_desc *tcb_desc = NULL;
2151
2152         spin_lock_irqsave(&ieee->lock, flags);
2153
2154         /* called with 2nd parm 0, no tx mgmt lock required */
2155         ieee80211_sta_wakeup(ieee, 0);
2156
2157         /* update the tx status */
2158         ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2159         ieee->stats.tx_packets++;
2160         tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2161         if (tcb_desc->bMulticast) {
2162                 ieee->stats.multicast++;
2163         }
2164         /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2165         for(i = 0; i < txb->nr_frags; i++) {
2166 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2167                 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2168 #else
2169                 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2170 #endif
2171                 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2172                      (ieee->queue_stop)) {
2173                         /* insert the skb packet to the wait queue */
2174                         /* as for the completion function, it does not need
2175                          * to check it any more.
2176                          * */
2177                         //printk("error:no descriptor left@queue_index %d\n", queue_index);
2178                         //ieee80211_stop_queue(ieee);
2179 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2180                         skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2181 #else
2182                         skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2183 #endif
2184                 }else{
2185                         ieee->softmac_data_hard_start_xmit(
2186                                         txb->fragments[i],
2187                                         ieee->dev, ieee->rate);
2188                         //ieee->stats.tx_packets++;
2189                         //ieee->stats.tx_bytes += txb->fragments[i]->len;
2190                         //ieee->dev->trans_start = jiffies;
2191                 }
2192         }
2193         ieee80211_txb_free(txb);
2194
2195 //exit:
2196         spin_unlock_irqrestore(&ieee->lock, flags);
2197
2198 }
2199 EXPORT_SYMBOL(ieee80211_softmac_xmit);
2200
2201 /* called with ieee->lock acquired */
2202 static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2203 {
2204         int i;
2205         for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2206
2207                 if (ieee->queue_stop){
2208                         ieee->tx_pending.frag = i;
2209                         return;
2210                 }else{
2211
2212                         ieee->softmac_data_hard_start_xmit(
2213                                 ieee->tx_pending.txb->fragments[i],
2214                                 ieee->dev, ieee->rate);
2215                                 //(i+1)<ieee->tx_pending.txb->nr_frags);
2216                         ieee->stats.tx_packets++;
2217                         netif_trans_update(ieee->dev);
2218                 }
2219         }
2220
2221
2222         ieee80211_txb_free(ieee->tx_pending.txb);
2223         ieee->tx_pending.txb = NULL;
2224 }
2225
2226
2227 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2228 {
2229         unsigned long flags;
2230
2231         spin_lock_irqsave(&ieee->lock, flags);
2232         init_mgmt_queue(ieee);
2233         if (ieee->tx_pending.txb) {
2234                 ieee80211_txb_free(ieee->tx_pending.txb);
2235                 ieee->tx_pending.txb = NULL;
2236         }
2237         ieee->queue_stop = 0;
2238         spin_unlock_irqrestore(&ieee->lock, flags);
2239
2240 }
2241 EXPORT_SYMBOL(ieee80211_reset_queue);
2242
2243 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2244 {
2245
2246         unsigned long flags;
2247         struct sk_buff *skb;
2248         struct rtl_80211_hdr_3addr  *header;
2249
2250         spin_lock_irqsave(&ieee->lock, flags);
2251         if (! ieee->queue_stop) goto exit;
2252
2253         ieee->queue_stop = 0;
2254
2255         if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2256                 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2257
2258                         header = (struct rtl_80211_hdr_3addr  *) skb->data;
2259
2260                         header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2261
2262                         if (ieee->seq_ctrl[0] == 0xFFF)
2263                                 ieee->seq_ctrl[0] = 0;
2264                         else
2265                                 ieee->seq_ctrl[0]++;
2266
2267                         ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2268                         //dev_kfree_skb_any(skb);//edit by thomas
2269                 }
2270         }
2271         if (!ieee->queue_stop && ieee->tx_pending.txb)
2272                 ieee80211_resume_tx(ieee);
2273
2274         if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2275                 ieee->softmac_stats.swtxawake++;
2276                 netif_wake_queue(ieee->dev);
2277         }
2278
2279 exit :
2280         spin_unlock_irqrestore(&ieee->lock, flags);
2281 }
2282 EXPORT_SYMBOL(ieee80211_wake_queue);
2283
2284 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2285 {
2286         //unsigned long flags;
2287         //spin_lock_irqsave(&ieee->lock,flags);
2288
2289         if (!netif_queue_stopped(ieee->dev)) {
2290                 netif_stop_queue(ieee->dev);
2291                 ieee->softmac_stats.swtxstop++;
2292         }
2293         ieee->queue_stop = 1;
2294         //spin_unlock_irqrestore(&ieee->lock,flags);
2295
2296 }
2297 EXPORT_SYMBOL(ieee80211_stop_queue);
2298
2299 /* called in user context only */
2300 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2301 {
2302         ieee->assoc_id = 1;
2303
2304         if (ieee->current_network.ssid_len == 0) {
2305                 strncpy(ieee->current_network.ssid,
2306                         IEEE80211_DEFAULT_TX_ESSID,
2307                         IW_ESSID_MAX_SIZE);
2308
2309                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2310                 ieee->ssid_set = 1;
2311         }
2312
2313         memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2314
2315         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2316         ieee->state = IEEE80211_LINKED;
2317         ieee->link_change(ieee->dev);
2318         notify_wx_assoc_event(ieee);
2319
2320         if (ieee->data_hard_resume)
2321                 ieee->data_hard_resume(ieee->dev);
2322
2323         netif_carrier_on(ieee->dev);
2324 }
2325
2326 static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2327 {
2328         if (ieee->raw_tx) {
2329
2330                 if (ieee->data_hard_resume)
2331                         ieee->data_hard_resume(ieee->dev);
2332
2333                 netif_carrier_on(ieee->dev);
2334         }
2335 }
2336 static void ieee80211_start_ibss_wq(struct work_struct *work)
2337 {
2338
2339         struct delayed_work *dwork = to_delayed_work(work);
2340         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2341         /* iwconfig mode ad-hoc will schedule this and return
2342          * on the other hand this will block further iwconfig SET
2343          * operations because of the wx_mutex hold.
2344          * Anyway some most set operations set a flag to speed-up
2345          * (abort) this wq (when syncro scanning) before sleeping
2346          * on the semaphore
2347          */
2348         if (!ieee->proto_started) {
2349                 printk("==========oh driver down return\n");
2350                 return;
2351         }
2352         mutex_lock(&ieee->wx_mutex);
2353
2354         if (ieee->current_network.ssid_len == 0) {
2355                 strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
2356                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2357                 ieee->ssid_set = 1;
2358         }
2359
2360         /* check if we have this cell in our network list */
2361         ieee80211_softmac_check_all_nets(ieee);
2362
2363
2364 //      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2365         if (ieee->state == IEEE80211_NOLINK)
2366                 ieee->current_network.channel = 6;
2367         /* if not then the state is not linked. Maybe the user swithced to
2368          * ad-hoc mode just after being in monitor mode, or just after
2369          * being very few time in managed mode (so the card have had no
2370          * time to scan all the chans..) or we have just run up the iface
2371          * after setting ad-hoc mode. So we have to give another try..
2372          * Here, in ibss mode, should be safe to do this without extra care
2373          * (in bss mode we had to make sure no-one tryed to associate when
2374          * we had just checked the ieee->state and we was going to start the
2375          * scan) beacause in ibss mode the ieee80211_new_net function, when
2376          * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2377          * so, at worst, we waste a bit of time to initiate an unneeded syncro
2378          * scan, that will stop at the first round because it sees the state
2379          * associated.
2380          */
2381         if (ieee->state == IEEE80211_NOLINK)
2382                 ieee80211_start_scan_syncro(ieee);
2383
2384         /* the network definitively is not here.. create a new cell */
2385         if (ieee->state == IEEE80211_NOLINK) {
2386                 printk("creating new IBSS cell\n");
2387                 if(!ieee->wap_set)
2388                         random_ether_addr(ieee->current_network.bssid);
2389
2390                 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2391
2392                         ieee->current_network.rates_len = 4;
2393
2394                         ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2395                         ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2396                         ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2397                         ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2398
2399                 }else
2400                         ieee->current_network.rates_len = 0;
2401
2402                 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2403                         ieee->current_network.rates_ex_len = 8;
2404
2405                         ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2406                         ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2407                         ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2408                         ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2409                         ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2410                         ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2411                         ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2412                         ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2413
2414                         ieee->rate = 108;
2415                 }else{
2416                         ieee->current_network.rates_ex_len = 0;
2417                         ieee->rate = 22;
2418                 }
2419
2420                 // By default, WMM function will be disabled in IBSS mode
2421                 ieee->current_network.QoS_Enable = 0;
2422                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2423                 ieee->current_network.atim_window = 0;
2424                 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2425                 if(ieee->short_slot)
2426                         ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2427
2428         }
2429
2430         ieee->state = IEEE80211_LINKED;
2431
2432         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2433         ieee->link_change(ieee->dev);
2434
2435         notify_wx_assoc_event(ieee);
2436
2437         ieee80211_start_send_beacons(ieee);
2438
2439         if (ieee->data_hard_resume)
2440                 ieee->data_hard_resume(ieee->dev);
2441         netif_carrier_on(ieee->dev);
2442
2443         mutex_unlock(&ieee->wx_mutex);
2444 }
2445
2446 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2447 {
2448         schedule_delayed_work(&ieee->start_ibss_wq, 150);
2449 }
2450
2451 /* this is called only in user context, with wx_mutex held */
2452 void ieee80211_start_bss(struct ieee80211_device *ieee)
2453 {
2454         unsigned long flags;
2455         //
2456         // Ref: 802.11d 11.1.3.3
2457         // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2458         //
2459         if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2460         {
2461                 if (! ieee->bGlobalDomain)
2462                 {
2463                         return;
2464                 }
2465         }
2466         /* check if we have already found the net we
2467          * are interested in (if any).
2468          * if not (we are disassociated and we are not
2469          * in associating / authenticating phase) start the background scanning.
2470          */
2471         ieee80211_softmac_check_all_nets(ieee);
2472
2473         /* ensure no-one start an associating process (thus setting
2474          * the ieee->state to ieee80211_ASSOCIATING) while we
2475          * have just cheked it and we are going to enable scan.
2476          * The ieee80211_new_net function is always called with
2477          * lock held (from both ieee80211_softmac_check_all_nets and
2478          * the rx path), so we cannot be in the middle of such function
2479          */
2480         spin_lock_irqsave(&ieee->lock, flags);
2481
2482         if (ieee->state == IEEE80211_NOLINK) {
2483                 ieee->actscanning = true;
2484                 ieee80211_start_scan(ieee);
2485         }
2486         spin_unlock_irqrestore(&ieee->lock, flags);
2487 }
2488
2489 /* called only in userspace context */
2490 void ieee80211_disassociate(struct ieee80211_device *ieee)
2491 {
2492
2493
2494         netif_carrier_off(ieee->dev);
2495         if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2496                         ieee80211_reset_queue(ieee);
2497
2498         if (ieee->data_hard_stop)
2499                         ieee->data_hard_stop(ieee->dev);
2500         if(IS_DOT11D_ENABLE(ieee))
2501                 Dot11d_Reset(ieee);
2502         ieee->state = IEEE80211_NOLINK;
2503         ieee->is_set_key = false;
2504         ieee->link_change(ieee->dev);
2505         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2506         notify_wx_assoc_event(ieee);
2507
2508 }
2509 EXPORT_SYMBOL(ieee80211_disassociate);
2510
2511 static void ieee80211_associate_retry_wq(struct work_struct *work)
2512 {
2513         struct delayed_work *dwork = to_delayed_work(work);
2514         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2515         unsigned long flags;
2516
2517         mutex_lock(&ieee->wx_mutex);
2518         if(!ieee->proto_started)
2519                 goto exit;
2520
2521         if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2522                 goto exit;
2523
2524         /* until we do not set the state to IEEE80211_NOLINK
2525         * there are no possibility to have someone else trying
2526         * to start an association procedure (we get here with
2527         * ieee->state = IEEE80211_ASSOCIATING).
2528         * When we set the state to IEEE80211_NOLINK it is possible
2529         * that the RX path run an attempt to associate, but
2530         * both ieee80211_softmac_check_all_nets and the
2531         * RX path works with ieee->lock held so there are no
2532         * problems. If we are still disassociated then start a scan.
2533         * the lock here is necessary to ensure no one try to start
2534         * an association procedure when we have just checked the
2535         * state and we are going to start the scan.
2536         */
2537         ieee->state = IEEE80211_NOLINK;
2538
2539         ieee80211_softmac_check_all_nets(ieee);
2540
2541         spin_lock_irqsave(&ieee->lock, flags);
2542
2543         if(ieee->state == IEEE80211_NOLINK)
2544                 ieee80211_start_scan(ieee);
2545
2546         spin_unlock_irqrestore(&ieee->lock, flags);
2547
2548 exit:
2549         mutex_unlock(&ieee->wx_mutex);
2550 }
2551
2552 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2553 {
2554         u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2555
2556         struct sk_buff *skb;
2557         struct ieee80211_probe_response *b;
2558
2559         skb = ieee80211_probe_resp(ieee, broadcast_addr);
2560
2561         if (!skb)
2562                 return NULL;
2563
2564         b = (struct ieee80211_probe_response *) skb->data;
2565         b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2566
2567         return skb;
2568
2569 }
2570
2571 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2572 {
2573         struct sk_buff *skb;
2574         struct ieee80211_probe_response *b;
2575
2576         skb = ieee80211_get_beacon_(ieee);
2577         if(!skb)
2578                 return NULL;
2579
2580         b = (struct ieee80211_probe_response *) skb->data;
2581         b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2582
2583         if (ieee->seq_ctrl[0] == 0xFFF)
2584                 ieee->seq_ctrl[0] = 0;
2585         else
2586                 ieee->seq_ctrl[0]++;
2587
2588         return skb;
2589 }
2590 EXPORT_SYMBOL(ieee80211_get_beacon);
2591
2592 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2593 {
2594         ieee->sync_scan_hurryup = 1;
2595         mutex_lock(&ieee->wx_mutex);
2596         ieee80211_stop_protocol(ieee);
2597         mutex_unlock(&ieee->wx_mutex);
2598 }
2599 EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2600
2601 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2602 {
2603         if (!ieee->proto_started)
2604                 return;
2605
2606         ieee->proto_started = 0;
2607
2608         ieee80211_stop_send_beacons(ieee);
2609         del_timer_sync(&ieee->associate_timer);
2610         cancel_delayed_work(&ieee->associate_retry_wq);
2611         cancel_delayed_work(&ieee->start_ibss_wq);
2612         ieee80211_stop_scan(ieee);
2613
2614         ieee80211_disassociate(ieee);
2615         RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2616 }
2617
2618 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2619 {
2620         ieee->sync_scan_hurryup = 0;
2621         mutex_lock(&ieee->wx_mutex);
2622         ieee80211_start_protocol(ieee);
2623         mutex_unlock(&ieee->wx_mutex);
2624 }
2625 EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2626
2627 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2628 {
2629         short ch = 0;
2630         int i = 0;
2631
2632         if (ieee->proto_started)
2633                 return;
2634
2635         ieee->proto_started = 1;
2636
2637         if (ieee->current_network.channel == 0) {
2638                 do{
2639                         ch++;
2640                         if (ch > MAX_CHANNEL_NUMBER)
2641                                 return; /* no channel found */
2642                 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2643                 ieee->current_network.channel = ch;
2644         }
2645
2646         if (ieee->current_network.beacon_interval == 0)
2647                 ieee->current_network.beacon_interval = 100;
2648 //      printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2649 //      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2650
2651         for(i = 0; i < 17; i++) {
2652           ieee->last_rxseq_num[i] = -1;
2653           ieee->last_rxfrag_num[i] = -1;
2654           ieee->last_packet_time[i] = 0;
2655         }
2656
2657         ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2658
2659
2660         /* if the user set the MAC of the ad-hoc cell and then
2661          * switch to managed mode, shall we  make sure that association
2662          * attempts does not fail just because the user provide the essid
2663          * and the nic is still checking for the AP MAC ??
2664          */
2665         if (ieee->iw_mode == IW_MODE_INFRA)
2666                 ieee80211_start_bss(ieee);
2667
2668         else if (ieee->iw_mode == IW_MODE_ADHOC)
2669                 ieee80211_start_ibss(ieee);
2670
2671         else if (ieee->iw_mode == IW_MODE_MASTER)
2672                 ieee80211_start_master_bss(ieee);
2673
2674         else if(ieee->iw_mode == IW_MODE_MONITOR)
2675                 ieee80211_start_monitor_mode(ieee);
2676 }
2677
2678
2679 #define DRV_NAME  "Ieee80211"
2680 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2681 {
2682         int i;
2683         memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2684
2685         ieee->state = IEEE80211_NOLINK;
2686         ieee->sync_scan_hurryup = 0;
2687         for(i = 0; i < 5; i++) {
2688           ieee->seq_ctrl[i] = 0;
2689         }
2690         ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2691         if (!ieee->pDot11dInfo)
2692                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2693         //added for  AP roaming
2694         ieee->LinkDetectInfo.SlotNum = 2;
2695         ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2696         ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2697
2698         ieee->assoc_id = 0;
2699         ieee->queue_stop = 0;
2700         ieee->scanning = 0;
2701         ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2702         ieee->wap_set = 0;
2703         ieee->ssid_set = 0;
2704         ieee->proto_started = 0;
2705         ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2706         ieee->rate = 22;
2707         ieee->ps = IEEE80211_PS_DISABLED;
2708         ieee->sta_sleep = 0;
2709         ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2710         ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2711         ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2712         //added by amy
2713         ieee->actscanning = false;
2714         ieee->beinretry = false;
2715         ieee->is_set_key = false;
2716         init_mgmt_queue(ieee);
2717
2718         ieee->sta_edca_param[0] = 0x0000A403;
2719         ieee->sta_edca_param[1] = 0x0000A427;
2720         ieee->sta_edca_param[2] = 0x005E4342;
2721         ieee->sta_edca_param[3] = 0x002F3262;
2722         ieee->aggregation = true;
2723         ieee->enable_rx_imm_BA = true;
2724         ieee->tx_pending.txb = NULL;
2725
2726         setup_timer(&ieee->associate_timer, ieee80211_associate_abort_cb,
2727                     (unsigned long)ieee);
2728
2729         setup_timer(&ieee->beacon_timer, ieee80211_send_beacon_cb,
2730                     (unsigned long)ieee);
2731
2732
2733         INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2734         INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2735         INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2736         INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2737         INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2738         INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2739
2740
2741         mutex_init(&ieee->wx_mutex);
2742         mutex_init(&ieee->scan_mutex);
2743
2744         spin_lock_init(&ieee->mgmt_tx_lock);
2745         spin_lock_init(&ieee->beacon_lock);
2746
2747         tasklet_init(&ieee->ps_task,
2748              (void(*)(unsigned long)) ieee80211_sta_ps,
2749              (unsigned long)ieee);
2750
2751 }
2752
2753 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2754 {
2755         mutex_lock(&ieee->wx_mutex);
2756         kfree(ieee->pDot11dInfo);
2757         ieee->pDot11dInfo = NULL;
2758         del_timer_sync(&ieee->associate_timer);
2759
2760         cancel_delayed_work(&ieee->associate_retry_wq);
2761
2762         mutex_unlock(&ieee->wx_mutex);
2763 }
2764
2765 /********************************************************
2766  * Start of WPA code.                                   *
2767  * this is stolen from the ipw2200 driver               *
2768  ********************************************************/
2769
2770
2771 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2772 {
2773         /* This is called when wpa_supplicant loads and closes the driver
2774          * interface. */
2775         printk("%s WPA\n", value ? "enabling" : "disabling");
2776         ieee->wpa_enabled = value;
2777         return 0;
2778 }
2779
2780
2781 static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2782                                       char *wpa_ie, int wpa_ie_len)
2783 {
2784         /* make sure WPA is enabled */
2785         ieee80211_wpa_enable(ieee, 1);
2786
2787         ieee80211_disassociate(ieee);
2788 }
2789
2790
2791 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2792 {
2793
2794         int ret = 0;
2795
2796         switch (command) {
2797         case IEEE_MLME_STA_DEAUTH:
2798                 // silently ignore
2799                 break;
2800
2801         case IEEE_MLME_STA_DISASSOC:
2802                 ieee80211_disassociate(ieee);
2803                 break;
2804
2805         default:
2806                 printk("Unknown MLME request: %d\n", command);
2807                 ret = -EOPNOTSUPP;
2808         }
2809
2810         return ret;
2811 }
2812
2813
2814 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2815                               struct ieee_param *param, int plen)
2816 {
2817         u8 *buf;
2818
2819         if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2820             (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2821                 return -EINVAL;
2822
2823         if (param->u.wpa_ie.len) {
2824                 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2825                               GFP_KERNEL);
2826                 if (buf == NULL)
2827                         return -ENOMEM;
2828
2829                 kfree(ieee->wpa_ie);
2830                 ieee->wpa_ie = buf;
2831                 ieee->wpa_ie_len = param->u.wpa_ie.len;
2832         } else {
2833                 kfree(ieee->wpa_ie);
2834                 ieee->wpa_ie = NULL;
2835                 ieee->wpa_ie_len = 0;
2836         }
2837
2838         ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2839         return 0;
2840 }
2841
2842 #define AUTH_ALG_OPEN_SYSTEM                    0x1
2843 #define AUTH_ALG_SHARED_KEY                     0x2
2844
2845 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2846 {
2847
2848         struct ieee80211_security sec = {
2849                 .flags = SEC_AUTH_MODE,
2850         };
2851
2852         if (value & AUTH_ALG_SHARED_KEY) {
2853                 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2854                 ieee->open_wep = 0;
2855                 ieee->auth_mode = 1;
2856         } else if (value & AUTH_ALG_OPEN_SYSTEM){
2857                 sec.auth_mode = WLAN_AUTH_OPEN;
2858                 ieee->open_wep = 1;
2859                 ieee->auth_mode = 0;
2860         }
2861         else if (value & IW_AUTH_ALG_LEAP){
2862                 sec.auth_mode = WLAN_AUTH_LEAP;
2863                 ieee->open_wep = 1;
2864                 ieee->auth_mode = 2;
2865         }
2866
2867
2868         if (ieee->set_security)
2869                 ieee->set_security(ieee->dev, &sec);
2870         //else
2871         //      ret = -EOPNOTSUPP;
2872
2873         return 0;
2874 }
2875
2876 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2877 {
2878         int ret = 0;
2879         unsigned long flags;
2880
2881         switch (name) {
2882         case IEEE_PARAM_WPA_ENABLED:
2883                 ret = ieee80211_wpa_enable(ieee, value);
2884                 break;
2885
2886         case IEEE_PARAM_TKIP_COUNTERMEASURES:
2887                 ieee->tkip_countermeasures = value;
2888                 break;
2889
2890         case IEEE_PARAM_DROP_UNENCRYPTED: {
2891                 /* HACK:
2892                  *
2893                  * wpa_supplicant calls set_wpa_enabled when the driver
2894                  * is loaded and unloaded, regardless of if WPA is being
2895                  * used.  No other calls are made which can be used to
2896                  * determine if encryption will be used or not prior to
2897                  * association being expected.  If encryption is not being
2898                  * used, drop_unencrypted is set to false, else true -- we
2899                  * can use this to determine if the CAP_PRIVACY_ON bit should
2900                  * be set.
2901                  */
2902                 struct ieee80211_security sec = {
2903                         .flags = SEC_ENABLED,
2904                         .enabled = value,
2905                 };
2906                 ieee->drop_unencrypted = value;
2907                 /* We only change SEC_LEVEL for open mode. Others
2908                  * are set by ipw_wpa_set_encryption.
2909                  */
2910                 if (!value) {
2911                         sec.flags |= SEC_LEVEL;
2912                         sec.level = SEC_LEVEL_0;
2913                 }
2914                 else {
2915                         sec.flags |= SEC_LEVEL;
2916                         sec.level = SEC_LEVEL_1;
2917                 }
2918                 if (ieee->set_security)
2919                         ieee->set_security(ieee->dev, &sec);
2920                 break;
2921         }
2922
2923         case IEEE_PARAM_PRIVACY_INVOKED:
2924                 ieee->privacy_invoked = value;
2925                 break;
2926
2927         case IEEE_PARAM_AUTH_ALGS:
2928                 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2929                 break;
2930
2931         case IEEE_PARAM_IEEE_802_1X:
2932                 ieee->ieee802_1x = value;
2933                 break;
2934         case IEEE_PARAM_WPAX_SELECT:
2935                 // added for WPA2 mixed mode
2936                 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2937                 ieee->wpax_type_set = 1;
2938                 ieee->wpax_type_notify = value;
2939                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2940                 break;
2941
2942         default:
2943                 printk("Unknown WPA param: %d\n", name);
2944                 ret = -EOPNOTSUPP;
2945         }
2946
2947         return ret;
2948 }
2949
2950 /* implementation borrowed from hostap driver */
2951
2952 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2953                                   struct ieee_param *param, int param_len)
2954 {
2955         int ret = 0;
2956
2957         struct ieee80211_crypto_ops *ops;
2958         struct ieee80211_crypt_data **crypt;
2959
2960         struct ieee80211_security sec = {
2961                 .flags = 0,
2962         };
2963
2964         param->u.crypt.err = 0;
2965         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2966
2967         if (param_len !=
2968             (int) ((char *) param->u.crypt.key - (char *) param) +
2969             param->u.crypt.key_len) {
2970                 printk("Len mismatch %d, %d\n", param_len,
2971                                param->u.crypt.key_len);
2972                 return -EINVAL;
2973         }
2974         if (is_broadcast_ether_addr(param->sta_addr)) {
2975                 if (param->u.crypt.idx >= WEP_KEYS)
2976                         return -EINVAL;
2977                 crypt = &ieee->crypt[param->u.crypt.idx];
2978         } else {
2979                 return -EINVAL;
2980         }
2981
2982         if (strcmp(param->u.crypt.alg, "none") == 0) {
2983                 if (crypt) {
2984                         sec.enabled = 0;
2985                         // FIXME FIXME
2986                         //sec.encrypt = 0;
2987                         sec.level = SEC_LEVEL_0;
2988                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
2989                         ieee80211_crypt_delayed_deinit(ieee, crypt);
2990                 }
2991                 goto done;
2992         }
2993         sec.enabled = 1;
2994 // FIXME FIXME
2995 //      sec.encrypt = 1;
2996         sec.flags |= SEC_ENABLED;
2997
2998         /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2999         if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3000             strcmp(param->u.crypt.alg, "TKIP"))
3001                 goto skip_host_crypt;
3002
3003         ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3004         if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3005                 request_module("ieee80211_crypt_wep");
3006                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3007                 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3008         } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3009                 request_module("ieee80211_crypt_tkip");
3010                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3011         } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3012                 request_module("ieee80211_crypt_ccmp");
3013                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3014         }
3015         if (ops == NULL) {
3016                 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3017                 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3018                 ret = -EINVAL;
3019                 goto done;
3020         }
3021
3022         if (*crypt == NULL || (*crypt)->ops != ops) {
3023                 struct ieee80211_crypt_data *new_crypt;
3024
3025                 ieee80211_crypt_delayed_deinit(ieee, crypt);
3026
3027                 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
3028                 if (new_crypt == NULL) {
3029                         ret = -ENOMEM;
3030                         goto done;
3031                 }
3032                 new_crypt->ops = ops;
3033                 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3034                         new_crypt->priv =
3035                                 new_crypt->ops->init(param->u.crypt.idx);
3036
3037                 if (new_crypt->priv == NULL) {
3038                         kfree(new_crypt);
3039                         param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3040                         ret = -EINVAL;
3041                         goto done;
3042                 }
3043
3044                 *crypt = new_crypt;
3045         }
3046
3047         if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3048             (*crypt)->ops->set_key(param->u.crypt.key,
3049                                    param->u.crypt.key_len, param->u.crypt.seq,
3050                                    (*crypt)->priv) < 0) {
3051                 printk("key setting failed\n");
3052                 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3053                 ret = -EINVAL;
3054                 goto done;
3055         }
3056
3057  skip_host_crypt:
3058         if (param->u.crypt.set_tx) {
3059                 ieee->tx_keyidx = param->u.crypt.idx;
3060                 sec.active_key = param->u.crypt.idx;
3061                 sec.flags |= SEC_ACTIVE_KEY;
3062         } else
3063                 sec.flags &= ~SEC_ACTIVE_KEY;
3064
3065         memcpy(sec.keys[param->u.crypt.idx],
3066                param->u.crypt.key,
3067                param->u.crypt.key_len);
3068         sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3069         sec.flags |= (1 << param->u.crypt.idx);
3070
3071         if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3072                 sec.flags |= SEC_LEVEL;
3073                 sec.level = SEC_LEVEL_1;
3074         } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3075                 sec.flags |= SEC_LEVEL;
3076                 sec.level = SEC_LEVEL_2;
3077         } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3078                 sec.flags |= SEC_LEVEL;
3079                 sec.level = SEC_LEVEL_3;
3080         }
3081  done:
3082         if (ieee->set_security)
3083                 ieee->set_security(ieee->dev, &sec);
3084
3085         /* Do not reset port if card is in Managed mode since resetting will
3086          * generate new IEEE 802.11 authentication which may end up in looping
3087          * with IEEE 802.1X.  If your hardware requires a reset after WEP
3088          * configuration (for example... Prism2), implement the reset_port in
3089          * the callbacks structures used to initialize the 802.11 stack. */
3090         if (ieee->reset_on_keychange &&
3091             ieee->iw_mode != IW_MODE_INFRA &&
3092             ieee->reset_port &&
3093             ieee->reset_port(ieee->dev)) {
3094                 printk("reset_port failed\n");
3095                 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3096                 return -EINVAL;
3097         }
3098
3099         return ret;
3100 }
3101
3102 static inline struct sk_buff *ieee80211_disassociate_skb(
3103                                                         struct ieee80211_network *beacon,
3104                                                         struct ieee80211_device *ieee,
3105                                                         u8      asRsn)
3106 {
3107         struct sk_buff *skb;
3108         struct ieee80211_disassoc *disass;
3109
3110         skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3111         if (!skb)
3112                 return NULL;
3113
3114         disass = (struct ieee80211_disassoc *) skb_put(skb, sizeof(struct ieee80211_disassoc));
3115         disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3116         disass->header.duration_id = 0;
3117
3118         memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3119         memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3120         memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3121
3122         disass->reason = cpu_to_le16(asRsn);
3123         return skb;
3124 }
3125
3126
3127 void
3128 SendDisassociation(
3129                 struct ieee80211_device *ieee,
3130                 u8                                      *asSta,
3131                 u8                                              asRsn
3132 )
3133 {
3134                 struct ieee80211_network *beacon = &ieee->current_network;
3135                 struct sk_buff *skb;
3136
3137                 skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
3138                 if (skb) {
3139                                 softmac_mgmt_xmit(skb, ieee);
3140                                 //dev_kfree_skb_any(skb);//edit by thomas
3141                 }
3142 }
3143 EXPORT_SYMBOL(SendDisassociation);
3144
3145 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3146 {
3147         struct ieee_param *param;
3148         int ret = 0;
3149
3150         mutex_lock(&ieee->wx_mutex);
3151         //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3152
3153         if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3154                 ret = -EINVAL;
3155                 goto out;
3156         }
3157
3158         param = memdup_user(p->pointer, p->length);
3159         if (IS_ERR(param)) {
3160                 ret = PTR_ERR(param);
3161                 goto out;
3162         }
3163
3164         switch (param->cmd) {
3165
3166         case IEEE_CMD_SET_WPA_PARAM:
3167                 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3168                                         param->u.wpa_param.value);
3169                 break;
3170
3171         case IEEE_CMD_SET_WPA_IE:
3172                 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3173                 break;
3174
3175         case IEEE_CMD_SET_ENCRYPTION:
3176                 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3177                 break;
3178
3179         case IEEE_CMD_MLME:
3180                 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3181                                    param->u.mlme.reason_code);
3182                 break;
3183
3184         default:
3185                 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3186                 ret = -EOPNOTSUPP;
3187                 break;
3188         }
3189
3190         if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3191                 ret = -EFAULT;
3192
3193         kfree(param);
3194 out:
3195         mutex_unlock(&ieee->wx_mutex);
3196
3197         return ret;
3198 }
3199 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3200
3201 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3202 {
3203         union iwreq_data wrqu;
3204
3205         wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3206         if (ieee->state == IEEE80211_LINKED)
3207                 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3208         else
3209                 eth_zero_addr(wrqu.ap_addr.sa_data);
3210         wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3211 }
3212 EXPORT_SYMBOL(notify_wx_assoc_event);