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