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