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