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