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