]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[net-next-2.6.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 = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1583                         memcpy(*challenge, t, *chlen);
1584                 }
1585         }
1586
1587         return cpu_to_le16(a->status);
1588
1589 }
1590
1591
1592 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1593 {
1594         struct ieee80211_authentication *a;
1595
1596         if (skb->len <  (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1597                 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1598                 return -1;
1599         }
1600         a = (struct ieee80211_authentication*) skb->data;
1601
1602         memcpy(dest,a->header.addr2, ETH_ALEN);
1603
1604         if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1605                 return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1606
1607         return WLAN_STATUS_SUCCESS;
1608 }
1609
1610 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1611 {
1612         u8 *tag;
1613         u8 *skbend;
1614         u8 *ssid=NULL;
1615         u8 ssidlen = 0;
1616
1617         struct ieee80211_hdr_3addr   *header =
1618                 (struct ieee80211_hdr_3addr   *) skb->data;
1619
1620         if (skb->len < sizeof (struct ieee80211_hdr_3addr  ))
1621                 return -1; /* corrupted */
1622
1623         memcpy(src,header->addr2, ETH_ALEN);
1624
1625         skbend = (u8*)skb->data + skb->len;
1626
1627         tag = skb->data + sizeof (struct ieee80211_hdr_3addr  );
1628
1629         while (tag+1 < skbend){
1630                 if (*tag == 0){
1631                         ssid = tag+2;
1632                         ssidlen = *(tag+1);
1633                         break;
1634                 }
1635                 tag++; /* point to the len field */
1636                 tag = tag + *(tag); /* point to the last data byte of the tag */
1637                 tag++; /* point to the next tag */
1638         }
1639
1640         //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1641         if (ssidlen == 0) return 1;
1642
1643         if (!ssid) return 1; /* ssid not found in tagged param */
1644         return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1645
1646 }
1647
1648 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1649 {
1650         struct ieee80211_assoc_request_frame *a;
1651
1652         if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1653                 sizeof(struct ieee80211_info_element))) {
1654
1655                 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1656                 return -1;
1657         }
1658
1659         a = (struct ieee80211_assoc_request_frame*) skb->data;
1660
1661         memcpy(dest,a->header.addr2,ETH_ALEN);
1662
1663         return 0;
1664 }
1665
1666 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1667 {
1668         struct ieee80211_assoc_response_frame *response_head;
1669         u16 status_code;
1670
1671         if (skb->len <  sizeof(struct ieee80211_assoc_response_frame)){
1672                 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1673                 return 0xcafe;
1674         }
1675
1676         response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1677         *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1678
1679         status_code = le16_to_cpu(response_head->status);
1680         if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1681            status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1682            ((ieee->mode == IEEE_G) &&
1683             (ieee->current_network.mode == IEEE_N_24G) &&
1684             (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1685                  ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1686         }else {
1687                  ieee->AsocRetryCount = 0;
1688         }
1689
1690         return le16_to_cpu(response_head->status);
1691 }
1692
1693 static inline void
1694 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1695 {
1696         u8 dest[ETH_ALEN];
1697
1698         //IEEE80211DMESG("Rx probe");
1699         ieee->softmac_stats.rx_probe_rq++;
1700         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1701         if (probe_rq_parse(ieee, skb, dest)){
1702                 //IEEE80211DMESG("Was for me!");
1703                 ieee->softmac_stats.tx_probe_rs++;
1704                 ieee80211_resp_to_probe(ieee, dest);
1705         }
1706 }
1707
1708 static inline void
1709 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1710 {
1711         u8 dest[ETH_ALEN];
1712         int status;
1713         //IEEE80211DMESG("Rx probe");
1714         ieee->softmac_stats.rx_auth_rq++;
1715
1716         if ((status = auth_rq_parse(skb, dest))!= -1){
1717                 ieee80211_resp_to_auth(ieee, status, dest);
1718         }
1719         //DMESG("Dest is "MACSTR, MAC2STR(dest));
1720
1721 }
1722
1723 static inline void
1724 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1725 {
1726
1727         u8 dest[ETH_ALEN];
1728         //unsigned long flags;
1729
1730         ieee->softmac_stats.rx_ass_rq++;
1731         if (assoc_rq_parse(skb,dest) != -1){
1732                 ieee80211_resp_to_assoc_rq(ieee, dest);
1733         }
1734
1735         printk(KERN_INFO"New client associated: %pM\n", dest);
1736         //FIXME
1737 }
1738
1739
1740
1741 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1742 {
1743
1744         struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1745
1746         if (buf)
1747                 softmac_ps_mgmt_xmit(buf, ieee);
1748
1749 }
1750
1751
1752 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1753 {
1754         int timeout = ieee->ps_timeout;
1755         u8 dtim;
1756         /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1757                 ieee->iw_mode != IW_MODE_INFRA ||
1758                 ieee->state != IEEE80211_LINKED)
1759
1760                 return 0;
1761         */
1762         dtim = ieee->current_network.dtim_data;
1763         //printk("DTIM\n");
1764         if(!(dtim & IEEE80211_DTIM_VALID))
1765                 return 0;
1766         timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1767         //printk("VALID\n");
1768         ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1769
1770         if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1771                 return 2;
1772
1773         if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1774                 return 0;
1775
1776         if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1777                 return 0;
1778
1779         if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1780                 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1781                 return 0;
1782
1783         if(time_l){
1784                 *time_l = ieee->current_network.last_dtim_sta_time[0]
1785                         + (ieee->current_network.beacon_interval
1786                         * ieee->current_network.dtim_period) * 1000;
1787         }
1788
1789         if(time_h){
1790                 *time_h = ieee->current_network.last_dtim_sta_time[1];
1791                 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1792                         *time_h += 1;
1793         }
1794
1795         return 1;
1796
1797
1798 }
1799
1800 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1801 {
1802
1803         u32 th,tl;
1804         short sleep;
1805
1806         unsigned long flags,flags2;
1807
1808         spin_lock_irqsave(&ieee->lock, flags);
1809
1810         if((ieee->ps == IEEE80211_PS_DISABLED ||
1811                 ieee->iw_mode != IW_MODE_INFRA ||
1812                 ieee->state != IEEE80211_LINKED)){
1813
1814         //      #warning CHECK_LOCK_HERE
1815                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1816
1817                 ieee80211_sta_wakeup(ieee, 1);
1818
1819                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1820         }
1821
1822         sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1823         /* 2 wake, 1 sleep, 0 do nothing */
1824         if(sleep == 0)
1825                 goto out;
1826
1827         if(sleep == 1){
1828
1829                 if(ieee->sta_sleep == 1)
1830                         ieee->enter_sleep_state(ieee->dev,th,tl);
1831
1832                 else if(ieee->sta_sleep == 0){
1833                 //      printk("send null 1\n");
1834                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1835
1836                         if(ieee->ps_is_queue_empty(ieee->dev)){
1837
1838
1839                                 ieee->sta_sleep = 2;
1840
1841                                 ieee->ps_request_tx_ack(ieee->dev);
1842
1843                                 ieee80211_sta_ps_send_null_frame(ieee,1);
1844
1845                                 ieee->ps_th = th;
1846                                 ieee->ps_tl = tl;
1847                         }
1848                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1849
1850                 }
1851
1852
1853         }else if(sleep == 2){
1854 //#warning CHECK_LOCK_HERE
1855                 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1856
1857                 ieee80211_sta_wakeup(ieee,1);
1858
1859                 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1860         }
1861
1862 out:
1863         spin_unlock_irqrestore(&ieee->lock, flags);
1864
1865 }
1866
1867 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1868 {
1869         if(ieee->sta_sleep == 0){
1870                 if(nl){
1871                         printk("Warning: driver is probably failing to report TX ps error\n");
1872                         ieee->ps_request_tx_ack(ieee->dev);
1873                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1874                 }
1875                 return;
1876
1877         }
1878
1879         if(ieee->sta_sleep == 1)
1880                 ieee->sta_wake_up(ieee->dev);
1881
1882         ieee->sta_sleep = 0;
1883
1884         if(nl){
1885                 ieee->ps_request_tx_ack(ieee->dev);
1886                 ieee80211_sta_ps_send_null_frame(ieee, 0);
1887         }
1888 }
1889
1890 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1891 {
1892         unsigned long flags,flags2;
1893
1894         spin_lock_irqsave(&ieee->lock, flags);
1895
1896         if(ieee->sta_sleep == 2){
1897                 /* Null frame with PS bit set */
1898                 if(success){
1899                         ieee->sta_sleep = 1;
1900                         ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1901                 }
1902                 /* if the card report not success we can't be sure the AP
1903                  * has not RXed so we can't assume the AP believe us awake
1904                  */
1905         }
1906         /* 21112005 - tx again null without PS bit if lost */
1907         else {
1908
1909                 if((ieee->sta_sleep == 0) && !success){
1910                         spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1911                         ieee80211_sta_ps_send_null_frame(ieee, 0);
1912                         spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1913                 }
1914         }
1915         spin_unlock_irqrestore(&ieee->lock, flags);
1916 }
1917 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1918 {
1919         struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
1920         u8* act = ieee80211_get_payload(header);
1921         u8 tmp = 0;
1922 //      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1923         if (act == NULL)
1924         {
1925                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1926                 return;
1927         }
1928         tmp = *act;
1929         act ++;
1930         switch (tmp)
1931         {
1932                 case ACT_CAT_BA:
1933                         if (*act == ACT_ADDBAREQ)
1934                         ieee80211_rx_ADDBAReq(ieee, skb);
1935                         else if (*act == ACT_ADDBARSP)
1936                         ieee80211_rx_ADDBARsp(ieee, skb);
1937                         else if (*act == ACT_DELBA)
1938                         ieee80211_rx_DELBA(ieee, skb);
1939                         break;
1940                 default:
1941 //                      if (net_ratelimit())
1942 //                      IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
1943                         break;
1944         }
1945         return;
1946
1947 }
1948 inline int
1949 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1950                         struct ieee80211_rx_stats *rx_stats, u16 type,
1951                         u16 stype)
1952 {
1953         struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1954         u16 errcode;
1955         u8* challenge;
1956         int chlen=0;
1957         int aid;
1958         struct ieee80211_assoc_response_frame *assoc_resp;
1959 //      struct ieee80211_info_element *info_element;
1960         bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1961
1962         if(!ieee->proto_started)
1963                 return 0;
1964
1965         if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1966                 ieee->iw_mode == IW_MODE_INFRA &&
1967                 ieee->state == IEEE80211_LINKED))
1968
1969                 tasklet_schedule(&ieee->ps_task);
1970
1971         if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1972                 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1973                 ieee->last_rx_ps_time = jiffies;
1974
1975         switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1976
1977                 case IEEE80211_STYPE_ASSOC_RESP:
1978                 case IEEE80211_STYPE_REASSOC_RESP:
1979
1980                         IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1981                                         WLAN_FC_GET_STYPE(header->frame_ctl));
1982                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1983                                 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1984                                 ieee->iw_mode == IW_MODE_INFRA){
1985                                 struct ieee80211_network network_resp;
1986                                 struct ieee80211_network *network = &network_resp;
1987
1988                                 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
1989                                         ieee->state=IEEE80211_LINKED;
1990                                         ieee->assoc_id = aid;
1991                                         ieee->softmac_stats.rx_ass_ok++;
1992                                         /* station support qos */
1993                                         /* Let the register setting defaultly with Legacy station */
1994                                         if(ieee->qos_support) {
1995                                                 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
1996                                                 memset(network, 0, sizeof(*network));
1997                                                 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1998                                                                         rx_stats->len - sizeof(*assoc_resp),\
1999                                                                         network,rx_stats)){
2000                                                         return 1;
2001                                                 }
2002                                                 else
2003                                                 {       //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2004                                                         memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2005                                                         memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2006                                                 }
2007                                                 if (ieee->handle_assoc_response != NULL)
2008                                                         ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2009                                         }
2010                                         ieee80211_associate_complete(ieee);
2011                                 } else {
2012                                         /* aid could not been allocated */
2013                                         ieee->softmac_stats.rx_ass_err++;
2014                                         printk(
2015                                                 "Association response status code 0x%x\n",
2016                                                 errcode);
2017                                         IEEE80211_DEBUG_MGMT(
2018                                                 "Association response status code 0x%x\n",
2019                                                 errcode);
2020                                         if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2021                                                 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2022                                         } else {
2023                                                 ieee80211_associate_abort(ieee);
2024                                         }
2025                                 }
2026                         }
2027                         break;
2028
2029                 case IEEE80211_STYPE_ASSOC_REQ:
2030                 case IEEE80211_STYPE_REASSOC_REQ:
2031
2032                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2033                                 ieee->iw_mode == IW_MODE_MASTER)
2034
2035                                 ieee80211_rx_assoc_rq(ieee, skb);
2036                         break;
2037
2038                 case IEEE80211_STYPE_AUTH:
2039
2040                         if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2041                                 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2042                                 ieee->iw_mode == IW_MODE_INFRA){
2043
2044                                                 IEEE80211_DEBUG_MGMT("Received authentication response");
2045
2046                                                 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2047                                                         if(ieee->open_wep || !challenge){
2048                                                                 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2049                                                                 ieee->softmac_stats.rx_auth_rs_ok++;
2050                                                                 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2051                                                                 {
2052                                                                         if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2053                                                                         {
2054                                                                                                 // WEP or TKIP encryption
2055                                                                                 if(IsHTHalfNmodeAPs(ieee))
2056                                                                                 {
2057                                                                                         bSupportNmode = true;
2058                                                                                         bHalfSupportNmode = true;
2059                                                                                 }
2060                                                                                 else
2061                                                                                 {
2062                                                                                         bSupportNmode = false;
2063                                                                                         bHalfSupportNmode = false;
2064                                                                                 }
2065                                                                         printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2066                                                                         }
2067                                                                 }
2068                                                                 /* Dummy wirless mode setting to avoid encryption issue */
2069                                                                 if(bSupportNmode) {
2070                                                                         //N mode setting
2071                                                                         ieee->SetWirelessMode(ieee->dev, \
2072                                                                                         ieee->current_network.mode);
2073                                                                 }else{
2074                                                                         //b/g mode setting
2075                                                                         /*TODO*/
2076                                                                         ieee->SetWirelessMode(ieee->dev, IEEE_G);
2077                                                                 }
2078
2079                                                                 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2080                                                                 {
2081                                                                         printk("===============>entern half N mode\n");
2082                                                                         ieee->bHalfWirelessN24GMode = true;
2083                                                                 }
2084                                                                 else
2085                                                                         ieee->bHalfWirelessN24GMode = false;
2086
2087                                                                 ieee80211_associate_step2(ieee);
2088                                                         }else{
2089                                                                 ieee80211_auth_challenge(ieee, challenge, chlen);
2090                                                         }
2091                                                 }else{
2092                                                         ieee->softmac_stats.rx_auth_rs_err++;
2093                                                         IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2094                                                         ieee80211_associate_abort(ieee);
2095                                                 }
2096
2097                                         }else if (ieee->iw_mode == IW_MODE_MASTER){
2098                                                 ieee80211_rx_auth_rq(ieee, skb);
2099                                         }
2100                                 }
2101                         break;
2102
2103                 case IEEE80211_STYPE_PROBE_REQ:
2104
2105                         if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2106                                 ((ieee->iw_mode == IW_MODE_ADHOC ||
2107                                 ieee->iw_mode == IW_MODE_MASTER) &&
2108                                 ieee->state == IEEE80211_LINKED)){
2109                                 ieee80211_rx_probe_rq(ieee, skb);
2110                         }
2111                         break;
2112
2113                 case IEEE80211_STYPE_DISASSOC:
2114                 case IEEE80211_STYPE_DEAUTH:
2115                         /* FIXME for now repeat all the association procedure
2116                         * both for disassociation and deauthentication
2117                         */
2118                         if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2119                                 ieee->state == IEEE80211_LINKED &&
2120                                 ieee->iw_mode == IW_MODE_INFRA){
2121
2122                                 ieee->state = IEEE80211_ASSOCIATING;
2123                                 ieee->softmac_stats.reassoc++;
2124
2125                                 notify_wx_assoc_event(ieee);
2126                                 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2127                                 RemovePeerTS(ieee, header->addr2);
2128                                 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2129                         }
2130                         break;
2131                 case IEEE80211_STYPE_MANAGE_ACT:
2132                         ieee80211_process_action(ieee,skb);
2133                         break;
2134                 default:
2135                         return -1;
2136                         break;
2137         }
2138
2139         //dev_kfree_skb_any(skb);
2140         return 0;
2141 }
2142
2143 /* following are for a simplier TX queue management.
2144  * Instead of using netif_[stop/wake]_queue the driver
2145  * will uses these two function (plus a reset one), that
2146  * will internally uses the kernel netif_* and takes
2147  * care of the ieee802.11 fragmentation.
2148  * So the driver receives a fragment per time and might
2149  * call the stop function when it want without take care
2150  * to have enought room to TX an entire packet.
2151  * This might be useful if each fragment need it's own
2152  * descriptor, thus just keep a total free memory > than
2153  * the max fragmentation treshold is not enought.. If the
2154  * ieee802.11 stack passed a TXB struct then you needed
2155  * to keep N free descriptors where
2156  * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2157  * In this way you need just one and the 802.11 stack
2158  * will take care of buffering fragments and pass them to
2159  * to the driver later, when it wakes the queue.
2160  */
2161 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2162 {
2163
2164         unsigned int queue_index = txb->queue_index;
2165         unsigned long flags;
2166         int  i;
2167         cb_desc *tcb_desc = NULL;
2168
2169         spin_lock_irqsave(&ieee->lock,flags);
2170
2171         /* called with 2nd parm 0, no tx mgmt lock required */
2172         ieee80211_sta_wakeup(ieee,0);
2173
2174         /* update the tx status */
2175         ieee->stats.tx_bytes += txb->payload_size;
2176         ieee->stats.tx_packets++;
2177         tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2178         if(tcb_desc->bMulticast) {
2179                 ieee->stats.multicast++;
2180         }
2181         /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2182         for(i = 0; i < txb->nr_frags; i++) {
2183 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2184                 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2185 #else
2186                 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2187 #endif
2188                 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2189                      (ieee->queue_stop)) {
2190                         /* insert the skb packet to the wait queue */
2191                         /* as for the completion function, it does not need
2192                          * to check it any more.
2193                          * */
2194                         //printk("error:no descriptor left@queue_index %d\n", queue_index);
2195                         //ieee80211_stop_queue(ieee);
2196 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2197                         skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2198 #else
2199                         skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2200 #endif
2201                 }else{
2202                         ieee->softmac_data_hard_start_xmit(
2203                                         txb->fragments[i],
2204                                         ieee->dev,ieee->rate);
2205                         //ieee->stats.tx_packets++;
2206                         //ieee->stats.tx_bytes += txb->fragments[i]->len;
2207                         //ieee->dev->trans_start = jiffies;
2208                 }
2209         }
2210         ieee80211_txb_free(txb);
2211
2212 //exit:
2213         spin_unlock_irqrestore(&ieee->lock,flags);
2214
2215 }
2216
2217 /* called with ieee->lock acquired */
2218 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2219 {
2220         int i;
2221         for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2222
2223                 if (ieee->queue_stop){
2224                         ieee->tx_pending.frag = i;
2225                         return;
2226                 }else{
2227
2228                         ieee->softmac_data_hard_start_xmit(
2229                                 ieee->tx_pending.txb->fragments[i],
2230                                 ieee->dev,ieee->rate);
2231                                 //(i+1)<ieee->tx_pending.txb->nr_frags);
2232                         ieee->stats.tx_packets++;
2233                         ieee->dev->trans_start = jiffies;
2234                 }
2235         }
2236
2237
2238         ieee80211_txb_free(ieee->tx_pending.txb);
2239         ieee->tx_pending.txb = NULL;
2240 }
2241
2242
2243 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2244 {
2245         unsigned long flags;
2246
2247         spin_lock_irqsave(&ieee->lock,flags);
2248         init_mgmt_queue(ieee);
2249         if (ieee->tx_pending.txb){
2250                 ieee80211_txb_free(ieee->tx_pending.txb);
2251                 ieee->tx_pending.txb = NULL;
2252         }
2253         ieee->queue_stop = 0;
2254         spin_unlock_irqrestore(&ieee->lock,flags);
2255
2256 }
2257
2258 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2259 {
2260
2261         unsigned long flags;
2262         struct sk_buff *skb;
2263         struct ieee80211_hdr_3addr  *header;
2264
2265         spin_lock_irqsave(&ieee->lock,flags);
2266         if (! ieee->queue_stop) goto exit;
2267
2268         ieee->queue_stop = 0;
2269
2270         if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2271                 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2272
2273                         header = (struct ieee80211_hdr_3addr  *) skb->data;
2274
2275                         header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2276
2277                         if (ieee->seq_ctrl[0] == 0xFFF)
2278                                 ieee->seq_ctrl[0] = 0;
2279                         else
2280                                 ieee->seq_ctrl[0]++;
2281
2282                         ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2283                         //dev_kfree_skb_any(skb);//edit by thomas
2284                 }
2285         }
2286         if (!ieee->queue_stop && ieee->tx_pending.txb)
2287                 ieee80211_resume_tx(ieee);
2288
2289         if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2290                 ieee->softmac_stats.swtxawake++;
2291                 netif_wake_queue(ieee->dev);
2292         }
2293
2294 exit :
2295         spin_unlock_irqrestore(&ieee->lock,flags);
2296 }
2297
2298
2299 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2300 {
2301         //unsigned long flags;
2302         //spin_lock_irqsave(&ieee->lock,flags);
2303
2304         if (! netif_queue_stopped(ieee->dev)){
2305                 netif_stop_queue(ieee->dev);
2306                 ieee->softmac_stats.swtxstop++;
2307         }
2308         ieee->queue_stop = 1;
2309         //spin_unlock_irqrestore(&ieee->lock,flags);
2310
2311 }
2312
2313
2314 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2315 {
2316
2317         get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2318
2319         /* an IBSS cell address must have the two less significant
2320          * bits of the first byte = 2
2321          */
2322         ieee->current_network.bssid[0] &= ~0x01;
2323         ieee->current_network.bssid[0] |= 0x02;
2324 }
2325
2326 /* called in user context only */
2327 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2328 {
2329         ieee->assoc_id = 1;
2330
2331         if (ieee->current_network.ssid_len == 0){
2332                 strncpy(ieee->current_network.ssid,
2333                         IEEE80211_DEFAULT_TX_ESSID,
2334                         IW_ESSID_MAX_SIZE);
2335
2336                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2337                 ieee->ssid_set = 1;
2338         }
2339
2340         memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2341
2342         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2343         ieee->state = IEEE80211_LINKED;
2344         ieee->link_change(ieee->dev);
2345         notify_wx_assoc_event(ieee);
2346
2347         if (ieee->data_hard_resume)
2348                 ieee->data_hard_resume(ieee->dev);
2349
2350         netif_carrier_on(ieee->dev);
2351 }
2352
2353 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2354 {
2355         if(ieee->raw_tx){
2356
2357                 if (ieee->data_hard_resume)
2358                         ieee->data_hard_resume(ieee->dev);
2359
2360                 netif_carrier_on(ieee->dev);
2361         }
2362 }
2363 void ieee80211_start_ibss_wq(struct work_struct *work)
2364 {
2365
2366         struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2367         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2368         /* iwconfig mode ad-hoc will schedule this and return
2369          * on the other hand this will block further iwconfig SET
2370          * operations because of the wx_sem hold.
2371          * Anyway some most set operations set a flag to speed-up
2372          * (abort) this wq (when syncro scanning) before sleeping
2373          * on the semaphore
2374          */
2375         if(!ieee->proto_started){
2376                 printk("==========oh driver down return\n");
2377                 return;
2378         }
2379         down(&ieee->wx_sem);
2380
2381         if (ieee->current_network.ssid_len == 0){
2382                 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2383                 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2384                 ieee->ssid_set = 1;
2385         }
2386
2387         /* check if we have this cell in our network list */
2388         ieee80211_softmac_check_all_nets(ieee);
2389
2390
2391 #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.
2392 //      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2393         if (ieee->state == IEEE80211_NOLINK)
2394                 ieee->current_network.channel = 6;
2395 #endif
2396         /* if not then the state is not linked. Maybe the user swithced to
2397          * ad-hoc mode just after being in monitor mode, or just after
2398          * being very few time in managed mode (so the card have had no
2399          * time to scan all the chans..) or we have just run up the iface
2400          * after setting ad-hoc mode. So we have to give another try..
2401          * Here, in ibss mode, should be safe to do this without extra care
2402          * (in bss mode we had to make sure no-one tryed to associate when
2403          * we had just checked the ieee->state and we was going to start the
2404          * scan) beacause in ibss mode the ieee80211_new_net function, when
2405          * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2406          * so, at worst, we waste a bit of time to initiate an unneeded syncro
2407          * scan, that will stop at the first round because it sees the state
2408          * associated.
2409          */
2410         if (ieee->state == IEEE80211_NOLINK)
2411                 ieee80211_start_scan_syncro(ieee);
2412
2413         /* the network definitively is not here.. create a new cell */
2414         if (ieee->state == IEEE80211_NOLINK){
2415                 printk("creating new IBSS cell\n");
2416                 if(!ieee->wap_set)
2417                         ieee80211_randomize_cell(ieee);
2418
2419                 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2420
2421                         ieee->current_network.rates_len = 4;
2422
2423                         ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2424                         ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2425                         ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2426                         ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2427
2428                 }else
2429                         ieee->current_network.rates_len = 0;
2430
2431                 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2432                         ieee->current_network.rates_ex_len = 8;
2433
2434                         ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2435                         ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2436                         ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2437                         ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2438                         ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2439                         ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2440                         ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2441                         ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2442
2443                         ieee->rate = 108;
2444                 }else{
2445                         ieee->current_network.rates_ex_len = 0;
2446                         ieee->rate = 22;
2447                 }
2448
2449                 // By default, WMM function will be disabled in IBSS mode
2450                 ieee->current_network.QoS_Enable = 0;
2451                 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2452                 ieee->current_network.atim_window = 0;
2453                 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2454                 if(ieee->short_slot)
2455                         ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2456
2457         }
2458
2459         ieee->state = IEEE80211_LINKED;
2460
2461         ieee->set_chan(ieee->dev, ieee->current_network.channel);
2462         ieee->link_change(ieee->dev);
2463
2464         notify_wx_assoc_event(ieee);
2465
2466         ieee80211_start_send_beacons(ieee);
2467
2468         if (ieee->data_hard_resume)
2469                 ieee->data_hard_resume(ieee->dev);
2470         netif_carrier_on(ieee->dev);
2471
2472         up(&ieee->wx_sem);
2473 }
2474
2475 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2476 {
2477         queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2478 }
2479
2480 /* this is called only in user context, with wx_sem held */
2481 void ieee80211_start_bss(struct ieee80211_device *ieee)
2482 {
2483         unsigned long flags;
2484 #ifdef ENABLE_DOT11D
2485         //
2486         // Ref: 802.11d 11.1.3.3
2487         // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2488         //
2489         if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2490         {
2491                 if(! ieee->bGlobalDomain)
2492                 {
2493                         return;
2494                 }
2495         }
2496 #endif
2497         /* check if we have already found the net we
2498          * are interested in (if any).
2499          * if not (we are disassociated and we are not
2500          * in associating / authenticating phase) start the background scanning.
2501          */
2502         ieee80211_softmac_check_all_nets(ieee);
2503
2504         /* ensure no-one start an associating process (thus setting
2505          * the ieee->state to ieee80211_ASSOCIATING) while we
2506          * have just cheked it and we are going to enable scan.
2507          * The ieee80211_new_net function is always called with
2508          * lock held (from both ieee80211_softmac_check_all_nets and
2509          * the rx path), so we cannot be in the middle of such function
2510          */
2511         spin_lock_irqsave(&ieee->lock, flags);
2512
2513         if (ieee->state == IEEE80211_NOLINK){
2514                 ieee->actscanning = true;
2515                 ieee80211_start_scan(ieee);
2516         }
2517         spin_unlock_irqrestore(&ieee->lock, flags);
2518 }
2519
2520 /* called only in userspace context */
2521 void ieee80211_disassociate(struct ieee80211_device *ieee)
2522 {
2523
2524
2525         netif_carrier_off(ieee->dev);
2526         if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2527                         ieee80211_reset_queue(ieee);
2528
2529         if (ieee->data_hard_stop)
2530                         ieee->data_hard_stop(ieee->dev);
2531 #ifdef ENABLE_DOT11D
2532         if(IS_DOT11D_ENABLE(ieee))
2533                 Dot11d_Reset(ieee);
2534 #endif
2535         ieee->state = IEEE80211_NOLINK;
2536         ieee->is_set_key = false;
2537         ieee->link_change(ieee->dev);
2538         //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2539         notify_wx_assoc_event(ieee);
2540
2541 }
2542 void ieee80211_associate_retry_wq(struct work_struct *work)
2543 {
2544         struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2545         struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2546         unsigned long flags;
2547
2548         down(&ieee->wx_sem);
2549         if(!ieee->proto_started)
2550                 goto exit;
2551
2552         if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2553                 goto exit;
2554
2555         /* until we do not set the state to IEEE80211_NOLINK
2556         * there are no possibility to have someone else trying
2557         * to start an association procdure (we get here with
2558         * ieee->state = IEEE80211_ASSOCIATING).
2559         * When we set the state to IEEE80211_NOLINK it is possible
2560         * that the RX path run an attempt to associate, but
2561         * both ieee80211_softmac_check_all_nets and the
2562         * RX path works with ieee->lock held so there are no
2563         * problems. If we are still disassociated then start a scan.
2564         * the lock here is necessary to ensure no one try to start
2565         * an association procedure when we have just checked the
2566         * state and we are going to start the scan.
2567         */
2568         ieee->state = IEEE80211_NOLINK;
2569
2570         ieee80211_softmac_check_all_nets(ieee);
2571
2572         spin_lock_irqsave(&ieee->lock, flags);
2573
2574         if(ieee->state == IEEE80211_NOLINK)
2575                 ieee80211_start_scan(ieee);
2576
2577         spin_unlock_irqrestore(&ieee->lock, flags);
2578
2579 exit:
2580         up(&ieee->wx_sem);
2581 }
2582
2583 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2584 {
2585         u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2586
2587         struct sk_buff *skb;
2588         struct ieee80211_probe_response *b;
2589
2590         skb = ieee80211_probe_resp(ieee, broadcast_addr);
2591
2592         if (!skb)
2593                 return NULL;
2594
2595         b = (struct ieee80211_probe_response *) skb->data;
2596         b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2597
2598         return skb;
2599
2600 }
2601
2602 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2603 {
2604         struct sk_buff *skb;
2605         struct ieee80211_probe_response *b;
2606
2607         skb = ieee80211_get_beacon_(ieee);
2608         if(!skb)
2609                 return NULL;
2610
2611         b = (struct ieee80211_probe_response *) skb->data;
2612         b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2613
2614         if (ieee->seq_ctrl[0] == 0xFFF)
2615                 ieee->seq_ctrl[0] = 0;
2616         else
2617                 ieee->seq_ctrl[0]++;
2618
2619         return skb;
2620 }
2621
2622 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2623 {
2624         ieee->sync_scan_hurryup = 1;
2625         down(&ieee->wx_sem);
2626         ieee80211_stop_protocol(ieee);
2627         up(&ieee->wx_sem);
2628 }
2629
2630
2631 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2632 {
2633         if (!ieee->proto_started)
2634                 return;
2635
2636         ieee->proto_started = 0;
2637
2638         ieee80211_stop_send_beacons(ieee);
2639         del_timer_sync(&ieee->associate_timer);
2640         cancel_delayed_work(&ieee->associate_retry_wq);
2641         cancel_delayed_work(&ieee->start_ibss_wq);
2642         ieee80211_stop_scan(ieee);
2643
2644         ieee80211_disassociate(ieee);
2645         RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2646 }
2647
2648 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2649 {
2650         ieee->sync_scan_hurryup = 0;
2651         down(&ieee->wx_sem);
2652         ieee80211_start_protocol(ieee);
2653         up(&ieee->wx_sem);
2654 }
2655
2656 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2657 {
2658         short ch = 0;
2659         int i = 0;
2660         if (ieee->proto_started)
2661                 return;
2662
2663         ieee->proto_started = 1;
2664
2665         if (ieee->current_network.channel == 0){
2666                 do{
2667                         ch++;
2668                         if (ch > MAX_CHANNEL_NUMBER)
2669                                 return; /* no channel found */
2670 #ifdef ENABLE_DOT11D
2671                 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2672 #else
2673                 }while(!ieee->channel_map[ch]);
2674 #endif
2675                 ieee->current_network.channel = ch;
2676         }
2677
2678         if (ieee->current_network.beacon_interval == 0)
2679                 ieee->current_network.beacon_interval = 100;
2680 //      printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2681 //      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2682
2683         for(i = 0; i < 17; i++) {
2684           ieee->last_rxseq_num[i] = -1;
2685           ieee->last_rxfrag_num[i] = -1;
2686           ieee->last_packet_time[i] = 0;
2687         }
2688
2689         ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2690
2691
2692         /* if the user set the MAC of the ad-hoc cell and then
2693          * switch to managed mode, shall we  make sure that association
2694          * attempts does not fail just because the user provide the essid
2695          * and the nic is still checking for the AP MAC ??
2696          */
2697         if (ieee->iw_mode == IW_MODE_INFRA)
2698                 ieee80211_start_bss(ieee);
2699
2700         else if (ieee->iw_mode == IW_MODE_ADHOC)
2701                 ieee80211_start_ibss(ieee);
2702
2703         else if (ieee->iw_mode == IW_MODE_MASTER)
2704                 ieee80211_start_master_bss(ieee);
2705
2706         else if(ieee->iw_mode == IW_MODE_MONITOR)
2707                 ieee80211_start_monitor_mode(ieee);
2708 }
2709
2710
2711 #define DRV_NAME  "Ieee80211"
2712 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2713 {
2714         int i;
2715         memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2716
2717         ieee->state = IEEE80211_NOLINK;
2718         ieee->sync_scan_hurryup = 0;
2719         for(i = 0; i < 5; i++) {
2720           ieee->seq_ctrl[i] = 0;
2721         }
2722 #ifdef ENABLE_DOT11D
2723         ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2724         if (!ieee->pDot11dInfo)
2725                 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2726         memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
2727 #endif
2728         //added for  AP roaming
2729         ieee->LinkDetectInfo.SlotNum = 2;
2730         ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2731         ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2732
2733         ieee->assoc_id = 0;
2734         ieee->queue_stop = 0;
2735         ieee->scanning = 0;
2736         ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2737         ieee->wap_set = 0;
2738         ieee->ssid_set = 0;
2739         ieee->proto_started = 0;
2740         ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2741         ieee->rate = 22;
2742         ieee->ps = IEEE80211_PS_DISABLED;
2743         ieee->sta_sleep = 0;
2744         ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2745         ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2746         ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2747         //added by amy
2748         ieee->actscanning = false;
2749         ieee->beinretry = false;
2750         ieee->is_set_key = false;
2751         init_mgmt_queue(ieee);
2752
2753         ieee->sta_edca_param[0] = 0x0000A403;
2754         ieee->sta_edca_param[1] = 0x0000A427;
2755         ieee->sta_edca_param[2] = 0x005E4342;
2756         ieee->sta_edca_param[3] = 0x002F3262;
2757         ieee->aggregation = true;
2758         ieee->enable_rx_imm_BA = 1;
2759         ieee->tx_pending.txb = NULL;
2760
2761         init_timer(&ieee->associate_timer);
2762         ieee->associate_timer.data = (unsigned long)ieee;
2763         ieee->associate_timer.function = ieee80211_associate_abort_cb;
2764
2765         init_timer(&ieee->beacon_timer);
2766         ieee->beacon_timer.data = (unsigned long) ieee;
2767         ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2768
2769 #ifdef PF_SYNCTHREAD
2770         ieee->wq = create_workqueue(DRV_NAME,0);
2771 #else
2772         ieee->wq = create_workqueue(DRV_NAME);
2773 #endif
2774
2775         INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2776         INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2777         INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2778         INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2779         INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2780         INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2781
2782
2783         sema_init(&ieee->wx_sem, 1);
2784         sema_init(&ieee->scan_sem, 1);
2785
2786         spin_lock_init(&ieee->mgmt_tx_lock);
2787         spin_lock_init(&ieee->beacon_lock);
2788
2789         tasklet_init(&ieee->ps_task,
2790              (void(*)(unsigned long)) ieee80211_sta_ps,
2791              (unsigned long)ieee);
2792
2793 }
2794
2795 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2796 {
2797         down(&ieee->wx_sem);
2798 #ifdef ENABLE_DOT11D
2799         if(NULL != ieee->pDot11dInfo)
2800         {
2801                 kfree(ieee->pDot11dInfo);
2802                 ieee->pDot11dInfo = NULL;
2803         }
2804 #endif
2805         del_timer_sync(&ieee->associate_timer);
2806
2807         cancel_delayed_work(&ieee->associate_retry_wq);
2808         destroy_workqueue(ieee->wq);
2809
2810         up(&ieee->wx_sem);
2811 }
2812
2813 /********************************************************
2814  * Start of WPA code.                                   *
2815  * this is stolen from the ipw2200 driver               *
2816  ********************************************************/
2817
2818
2819 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2820 {
2821         /* This is called when wpa_supplicant loads and closes the driver
2822          * interface. */
2823         printk("%s WPA\n",value ? "enabling" : "disabling");
2824         ieee->wpa_enabled = value;
2825         return 0;
2826 }
2827
2828
2829 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2830 {
2831         /* make sure WPA is enabled */
2832         ieee80211_wpa_enable(ieee, 1);
2833
2834         ieee80211_disassociate(ieee);
2835 }
2836
2837
2838 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2839 {
2840
2841         int ret = 0;
2842
2843         switch (command) {
2844         case IEEE_MLME_STA_DEAUTH:
2845                 // silently ignore
2846                 break;
2847
2848         case IEEE_MLME_STA_DISASSOC:
2849                 ieee80211_disassociate(ieee);
2850                 break;
2851
2852         default:
2853                 printk("Unknown MLME request: %d\n", command);
2854                 ret = -EOPNOTSUPP;
2855         }
2856
2857         return ret;
2858 }
2859
2860
2861 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2862                               struct ieee_param *param, int plen)
2863 {
2864         u8 *buf;
2865
2866         if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2867             (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2868                 return -EINVAL;
2869
2870         if (param->u.wpa_ie.len) {
2871                 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
2872                 if (buf == NULL)
2873                         return -ENOMEM;
2874
2875                 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
2876                 kfree(ieee->wpa_ie);
2877                 ieee->wpa_ie = buf;
2878                 ieee->wpa_ie_len = param->u.wpa_ie.len;
2879         } else {
2880                 kfree(ieee->wpa_ie);
2881                 ieee->wpa_ie = NULL;
2882                 ieee->wpa_ie_len = 0;
2883         }
2884
2885         ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2886         return 0;
2887 }
2888
2889 #define AUTH_ALG_OPEN_SYSTEM                    0x1
2890 #define AUTH_ALG_SHARED_KEY                     0x2
2891
2892 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2893 {
2894
2895         struct ieee80211_security sec = {
2896                 .flags = SEC_AUTH_MODE,
2897         };
2898         int ret = 0;
2899
2900         if (value & AUTH_ALG_SHARED_KEY) {
2901                 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2902                 ieee->open_wep = 0;
2903                 ieee->auth_mode = 1;
2904         } else if (value & AUTH_ALG_OPEN_SYSTEM){
2905                 sec.auth_mode = WLAN_AUTH_OPEN;
2906                 ieee->open_wep = 1;
2907                 ieee->auth_mode = 0;
2908         }
2909         else if (value & IW_AUTH_ALG_LEAP){
2910                 sec.auth_mode = WLAN_AUTH_LEAP;
2911                 ieee->open_wep = 1;
2912                 ieee->auth_mode = 2;
2913         }
2914
2915
2916         if (ieee->set_security)
2917                 ieee->set_security(ieee->dev, &sec);
2918         //else
2919         //      ret = -EOPNOTSUPP;
2920
2921         return ret;
2922 }
2923
2924 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2925 {
2926         int ret=0;
2927         unsigned long flags;
2928
2929         switch (name) {
2930         case IEEE_PARAM_WPA_ENABLED:
2931                 ret = ieee80211_wpa_enable(ieee, value);
2932                 break;
2933
2934         case IEEE_PARAM_TKIP_COUNTERMEASURES:
2935                 ieee->tkip_countermeasures=value;
2936                 break;
2937
2938         case IEEE_PARAM_DROP_UNENCRYPTED: {
2939                 /* HACK:
2940                  *
2941                  * wpa_supplicant calls set_wpa_enabled when the driver
2942                  * is loaded and unloaded, regardless of if WPA is being
2943                  * used.  No other calls are made which can be used to
2944                  * determine if encryption will be used or not prior to
2945                  * association being expected.  If encryption is not being
2946                  * used, drop_unencrypted is set to false, else true -- we
2947                  * can use this to determine if the CAP_PRIVACY_ON bit should
2948                  * be set.
2949                  */
2950                 struct ieee80211_security sec = {
2951                         .flags = SEC_ENABLED,
2952                         .enabled = value,
2953                 };
2954                 ieee->drop_unencrypted = value;
2955                 /* We only change SEC_LEVEL for open mode. Others
2956                  * are set by ipw_wpa_set_encryption.
2957                  */
2958                 if (!value) {
2959                         sec.flags |= SEC_LEVEL;
2960                         sec.level = SEC_LEVEL_0;
2961                 }
2962                 else {
2963                         sec.flags |= SEC_LEVEL;
2964                         sec.level = SEC_LEVEL_1;
2965                 }
2966                 if (ieee->set_security)
2967                         ieee->set_security(ieee->dev, &sec);
2968                 break;
2969         }
2970
2971         case IEEE_PARAM_PRIVACY_INVOKED:
2972                 ieee->privacy_invoked=value;
2973                 break;
2974
2975         case IEEE_PARAM_AUTH_ALGS:
2976                 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2977                 break;
2978
2979         case IEEE_PARAM_IEEE_802_1X:
2980                 ieee->ieee802_1x=value;
2981                 break;
2982         case IEEE_PARAM_WPAX_SELECT:
2983                 // added for WPA2 mixed mode
2984                 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2985                 ieee->wpax_type_set = 1;
2986                 ieee->wpax_type_notify = value;
2987                 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
2988                 break;
2989
2990         default:
2991                 printk("Unknown WPA param: %d\n",name);
2992                 ret = -EOPNOTSUPP;
2993         }
2994
2995         return ret;
2996 }
2997
2998 /* implementation borrowed from hostap driver */
2999
3000 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3001                                   struct ieee_param *param, int param_len)
3002 {
3003         int ret = 0;
3004
3005         struct ieee80211_crypto_ops *ops;
3006         struct ieee80211_crypt_data **crypt;
3007
3008         struct ieee80211_security sec = {
3009                 .flags = 0,
3010         };
3011
3012         param->u.crypt.err = 0;
3013         param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3014
3015         if (param_len !=
3016             (int) ((char *) param->u.crypt.key - (char *) param) +
3017             param->u.crypt.key_len) {
3018                 printk("Len mismatch %d, %d\n", param_len,
3019                                param->u.crypt.key_len);
3020                 return -EINVAL;
3021         }
3022         if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3023             param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3024             param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3025                 if (param->u.crypt.idx >= WEP_KEYS)
3026                         return -EINVAL;
3027                 crypt = &ieee->crypt[param->u.crypt.idx];
3028         } else {
3029                 return -EINVAL;
3030         }
3031
3032         if (strcmp(param->u.crypt.alg, "none") == 0) {
3033                 if (crypt) {
3034                         sec.enabled = 0;
3035                         // FIXME FIXME
3036                         //sec.encrypt = 0;
3037                         sec.level = SEC_LEVEL_0;
3038                         sec.flags |= SEC_ENABLED | SEC_LEVEL;
3039                         ieee80211_crypt_delayed_deinit(ieee, crypt);
3040                 }
3041                 goto done;
3042         }
3043         sec.enabled = 1;
3044 // FIXME FIXME
3045 //      sec.encrypt = 1;
3046         sec.flags |= SEC_ENABLED;
3047
3048         /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3049         if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3050             strcmp(param->u.crypt.alg, "TKIP"))
3051                 goto skip_host_crypt;
3052
3053         ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3054         if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3055                 request_module("ieee80211_crypt_wep");
3056                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3057                 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3058         } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3059                 request_module("ieee80211_crypt_tkip");
3060                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3061         } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3062                 request_module("ieee80211_crypt_ccmp");
3063                 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3064         }
3065         if (ops == NULL) {
3066                 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3067                 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3068                 ret = -EINVAL;
3069                 goto done;
3070         }
3071
3072         if (*crypt == NULL || (*crypt)->ops != ops) {
3073                 struct ieee80211_crypt_data *new_crypt;
3074
3075                 ieee80211_crypt_delayed_deinit(ieee, crypt);
3076
3077                 new_crypt = (struct ieee80211_crypt_data *)
3078                         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 = (struct ieee_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);