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