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