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