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