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