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