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