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