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