Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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