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