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