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