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