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