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