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