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