staging: rtl8192e: Move variables to ieee80211 struct
[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 */
ecdfa446 246 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,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 */
262 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
263 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
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 {
ecdfa446 271 ieee->softmac_hard_start_xmit(skb,ieee->dev);
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 */
ecdfa446
GKH
300 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
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
311 ieee->softmac_hard_start_xmit(skb,ieee->dev);
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;
451 ieee->set_chan(ieee->dev, ch);
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;
520 ieee->set_chan(ieee->dev, ieee->current_network.channel);
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)
571 ieee->stop_send_beacons(ieee->dev);
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)
65a43784 580 ieee->start_send_beacons(ieee->dev);
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
604 ieee->stop_scan(ieee->dev);
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)
612 ieee->ieee80211_ips_leave_wq(ieee->dev);
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
630 ieee->start_scan(ieee->dev);
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
650 ieee->scan_syncro(ieee->dev);
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 }
1381 ieee->link_change(ieee->dev);
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)
1393 ieee->data_hard_resume(ieee->dev);
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)
1411 ieee->ieee80211_ips_leave(ieee->dev);
1412#endif
1413
ecdfa446
GKH
1414 down(&ieee->wx_sem);
1415
1416 if (ieee->data_hard_stop)
1417 ieee->data_hard_stop(ieee->dev);
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;
1511 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1512 printk(KERN_INFO"Using G rates\n");
1513 }else{
1514 ieee->rate = 22;
1515 ieee->SetWirelessMode(ieee->dev, IEEE_B);
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++);
32414878 1567 *challenge = kmalloc(*chlen, GFP_ATOMIC);
ecdfa446
GKH
1568 memcpy(*challenge, t, *chlen);
1569 }
1570 }
1571
1572 return cpu_to_le16(a->status);
1573
1574}
1575
1576
1577int auth_rq_parse(struct sk_buff *skb,u8* dest)
1578{
1579 struct ieee80211_authentication *a;
1580
1581 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1582 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1583 return -1;
1584 }
1585 a = (struct ieee80211_authentication*) skb->data;
1586
1587 memcpy(dest,a->header.addr2, ETH_ALEN);
1588
1589 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1590 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1591
1592 return WLAN_STATUS_SUCCESS;
1593}
1594
1595static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1596{
1597 u8 *tag;
1598 u8 *skbend;
1599 u8 *ssid=NULL;
1600 u8 ssidlen = 0;
1601
1602 struct ieee80211_hdr_3addr *header =
1603 (struct ieee80211_hdr_3addr *) skb->data;
1604
1605 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1606 return -1; /* corrupted */
1607
1608 memcpy(src,header->addr2, ETH_ALEN);
1609
1610 skbend = (u8*)skb->data + skb->len;
1611
1612 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1613
1614 while (tag+1 < skbend){
1615 if (*tag == 0){
1616 ssid = tag+2;
1617 ssidlen = *(tag+1);
1618 break;
1619 }
1620 tag++; /* point to the len field */
1621 tag = tag + *(tag); /* point to the last data byte of the tag */
1622 tag++; /* point to the next tag */
1623 }
1624
ecdfa446
GKH
1625 if (ssidlen == 0) return 1;
1626
1627 if (!ssid) return 1; /* ssid not found in tagged param */
1628 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1629
1630}
1631
1632int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1633{
1634 struct ieee80211_assoc_request_frame *a;
1635
1636 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1637 sizeof(struct ieee80211_info_element))) {
1638
1639 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1640 return -1;
1641 }
1642
1643 a = (struct ieee80211_assoc_request_frame*) skb->data;
1644
1645 memcpy(dest,a->header.addr2,ETH_ALEN);
1646
1647 return 0;
1648}
1649
1650static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1651{
1652 struct ieee80211_assoc_response_frame *response_head;
1653 u16 status_code;
1654
1655 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1656 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1657 return 0xcafe;
1658 }
1659
1660 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1661 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1662
1663 status_code = le16_to_cpu(response_head->status);
1664 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1665 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1666 ((ieee->mode == IEEE_G) &&
1667 (ieee->current_network.mode == IEEE_N_24G) &&
1668 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1669 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1670 }else {
1671 ieee->AsocRetryCount = 0;
1672 }
1673
1674 return le16_to_cpu(response_head->status);
1675}
1676
1677static inline void
1678ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1679{
1680 u8 dest[ETH_ALEN];
1681
ecdfa446 1682 ieee->softmac_stats.rx_probe_rq++;
ecdfa446 1683 if (probe_rq_parse(ieee, skb, dest)){
ecdfa446
GKH
1684 ieee->softmac_stats.tx_probe_rs++;
1685 ieee80211_resp_to_probe(ieee, dest);
1686 }
1687}
1688
1689static inline void
1690ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1691{
1692 u8 dest[ETH_ALEN];
1693 int status;
ecdfa446
GKH
1694 ieee->softmac_stats.rx_auth_rq++;
1695
d6d42dfb
JP
1696 status = auth_rq_parse(skb, dest);
1697 if (status != -1) {
ecdfa446
GKH
1698 ieee80211_resp_to_auth(ieee, status, dest);
1699 }
ecdfa446
GKH
1700}
1701
1702static inline void
1703ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1704{
ecdfa446 1705 u8 dest[ETH_ALEN];
ecdfa446
GKH
1706
1707 ieee->softmac_stats.rx_ass_rq++;
1708 if (assoc_rq_parse(skb,dest) != -1){
1709 ieee80211_resp_to_assoc_rq(ieee, dest);
1710 }
1711
0ee9f67c 1712 printk(KERN_INFO"New client associated: %pM\n", dest);
ecdfa446
GKH
1713}
1714
1715
1716
1717void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1718{
1719
1720 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1721
1722 if (buf)
1723 softmac_ps_mgmt_xmit(buf, ieee);
1724
1725}
1726
65a43784 1727void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1728{
1729
1730 struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1731
1732 if (buf)
1733 softmac_ps_mgmt_xmit(buf, ieee);
1734
1735}
ecdfa446
GKH
1736
1737short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1738{
1739 int timeout = ieee->ps_timeout;
1740 u8 dtim;
ecdfa446 1741
65a43784 1742 if(ieee->LPSDelayCnt)
1743 {
65a43784 1744 ieee->LPSDelayCnt --;
ecdfa446 1745 return 0;
65a43784 1746 }
1747
ecdfa446 1748 dtim = ieee->current_network.dtim_data;
ecdfa446
GKH
1749 if(!(dtim & IEEE80211_DTIM_VALID))
1750 return 0;
1751 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
ecdfa446 1752 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
65a43784 1753 /* there's no need to nofity AP that I find you buffered with broadcast packet */
1754 if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
ecdfa446
GKH
1755 return 2;
1756
65a43784 1757 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
ecdfa446 1758 return 0;
65a43784 1759 }
1760 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
ecdfa446 1761 return 0;
65a43784 1762 }
ecdfa446
GKH
1763 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1764 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1765 return 0;
1766
1767 if(time_l){
65a43784 1768 if(ieee->bAwakePktSent == true) {
774dee1c 1769 ieee->LPSAwakeIntvl = 1;//tx wake one beacon
65a43784 1770 } else {
1771 u8 MaxPeriod = 1;
1772
774dee1c
MM
1773 if(ieee->LPSAwakeIntvl == 0)
1774 ieee->LPSAwakeIntvl = 1;
1775 if(ieee->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
65a43784 1776 MaxPeriod = 1; // 1 Beacon interval
774dee1c 1777 else if(ieee->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
65a43784 1778 MaxPeriod = ieee->current_network.dtim_period;
1779 else
774dee1c
MM
1780 MaxPeriod = ieee->RegMaxLPSAwakeIntvl;
1781 ieee->LPSAwakeIntvl = (ieee->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (ieee->LPSAwakeIntvl + 1);
65a43784 1782 }
1783 {
1784 u8 LPSAwakeIntvl_tmp = 0;
1785 u8 period = ieee->current_network.dtim_period;
1786 u8 count = ieee->current_network.tim.tim_count;
1787 if(count == 0 ) {
774dee1c
MM
1788 if(ieee->LPSAwakeIntvl > period)
1789 LPSAwakeIntvl_tmp = period + (ieee->LPSAwakeIntvl - period) -((ieee->LPSAwakeIntvl-period)%period);
65a43784 1790 else
774dee1c 1791 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
65a43784 1792
1793 } else {
774dee1c
MM
1794 if(ieee->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
1795 LPSAwakeIntvl_tmp = count + (ieee->LPSAwakeIntvl - count) -((ieee->LPSAwakeIntvl-count)%period);
65a43784 1796 else
774dee1c 1797 LPSAwakeIntvl_tmp = ieee->LPSAwakeIntvl;
65a43784 1798 }
65a43784 1799
ecdfa446 1800 *time_l = ieee->current_network.last_dtim_sta_time[0]
65a43784 1801 + MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
ecdfa446 1802 }
65a43784 1803 }
ecdfa446
GKH
1804
1805 if(time_h){
1806 *time_h = ieee->current_network.last_dtim_sta_time[1];
1807 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1808 *time_h += 1;
1809 }
1810
1811 return 1;
1812
1813
1814}
1815
1816inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1817{
1818
1819 u32 th,tl;
1820 short sleep;
0cfc6185 1821 unsigned long flags;
ecdfa446
GKH
1822
1823 spin_lock_irqsave(&ieee->lock, flags);
1824
1825 if((ieee->ps == IEEE80211_PS_DISABLED ||
1826 ieee->iw_mode != IW_MODE_INFRA ||
1827 ieee->state != IEEE80211_LINKED)){
1828
1829 // #warning CHECK_LOCK_HERE
65a43784 1830 printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
1831 __FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
0cfc6185 1832 spin_lock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1833
1834 ieee80211_sta_wakeup(ieee, 1);
1835
0cfc6185 1836 spin_unlock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1837 }
1838
1839 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1840 /* 2 wake, 1 sleep, 0 do nothing */
65a43784 1841 if(sleep == 0)//it is not time out or dtim is not valid
1842 {
ecdfa446 1843 goto out;
65a43784 1844 }
ecdfa446 1845 if(sleep == 1){
65a43784 1846 if(ieee->sta_sleep == 1){
ecdfa446 1847 ieee->enter_sleep_state(ieee->dev,th,tl);
65a43784 1848 }
ecdfa446
GKH
1849
1850 else if(ieee->sta_sleep == 0){
0cfc6185 1851 spin_lock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1852
1853 if(ieee->ps_is_queue_empty(ieee->dev)){
ecdfa446 1854 ieee->sta_sleep = 2;
ecdfa446 1855 ieee->ack_tx_to_ieee = 1;
ecdfa446 1856 ieee80211_sta_ps_send_null_frame(ieee,1);
ecdfa446
GKH
1857 ieee->ps_th = th;
1858 ieee->ps_tl = tl;
1859 }
0cfc6185 1860 spin_unlock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1861
1862 }
1863
65a43784 1864 ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
ecdfa446
GKH
1865
1866 }else if(sleep == 2){
0cfc6185 1867 spin_lock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1868
1869 ieee80211_sta_wakeup(ieee,1);
1870
0cfc6185 1871 spin_unlock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1872 }
1873
1874out:
1875 spin_unlock_irqrestore(&ieee->lock, flags);
1876
1877}
1878
1879void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1880{
1881 if(ieee->sta_sleep == 0){
1882 if(nl){
65a43784 1883 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1884 {
65a43784 1885 ieee->ack_tx_to_ieee = 1;
1886 ieee80211_sta_ps_send_null_frame(ieee, 0);
1887 }
1888 else
1889 {
1890 ieee->ack_tx_to_ieee = 1;
65a43784 1891 ieee80211_sta_ps_send_pspoll_frame(ieee);
1892 }
ecdfa446
GKH
1893 }
1894 return;
1895
1896 }
1897
1898 if(ieee->sta_sleep == 1)
1899 ieee->sta_wake_up(ieee->dev);
65a43784 1900 if(nl){
ecdfa446 1901
65a43784 1902 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1903 {
65a43784 1904 ieee->ack_tx_to_ieee = 1;
1905 ieee80211_sta_ps_send_null_frame(ieee, 0);
1906 }
1907 else
1908 {
1909 ieee->ack_tx_to_ieee = 1;
1910 ieee->polling = true;
65a43784 1911 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1912 ieee80211_sta_ps_send_pspoll_frame(ieee);
1913 }
ecdfa446 1914
65a43784 1915 } else {
1916 ieee->sta_sleep = 0;
1917 ieee->polling = false;
ecdfa446
GKH
1918 }
1919}
1920
1921void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1922{
0cfc6185 1923 unsigned long flags;
ecdfa446
GKH
1924
1925 spin_lock_irqsave(&ieee->lock, flags);
1926
1927 if(ieee->sta_sleep == 2){
1928 /* Null frame with PS bit set */
1929 if(success){
1930 ieee->sta_sleep = 1;
1931 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1932 }
65a43784 1933 } else {/* 21112005 - tx again null without PS bit if lost */
ecdfa446
GKH
1934
1935 if((ieee->sta_sleep == 0) && !success){
0cfc6185 1936 spin_lock(&ieee->mgmt_tx_lock);
65a43784 1937 //ieee80211_sta_ps_send_null_frame(ieee, 0);
1938 if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
1939 {
65a43784 1940 ieee80211_sta_ps_send_null_frame(ieee, 0);
1941 }
1942 else
1943 {
65a43784 1944 ieee80211_sta_ps_send_pspoll_frame(ieee);
1945 }
0cfc6185 1946 spin_unlock(&ieee->mgmt_tx_lock);
ecdfa446
GKH
1947 }
1948 }
1949 spin_unlock_irqrestore(&ieee->lock, flags);
1950}
65a43784 1951
ecdfa446
GKH
1952void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1953{
1954 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
1955 u8* act = ieee80211_get_payload(header);
1956 u8 tmp = 0;
85c876e4 1957
ecdfa446
GKH
1958 if (act == NULL)
1959 {
1960 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1961 return;
1962 }
1963 tmp = *act;
1964 act ++;
1965 switch (tmp)
1966 {
1967 case ACT_CAT_BA:
1968 if (*act == ACT_ADDBAREQ)
1969 ieee80211_rx_ADDBAReq(ieee, skb);
1970 else if (*act == ACT_ADDBARSP)
1971 ieee80211_rx_ADDBARsp(ieee, skb);
1972 else if (*act == ACT_DELBA)
1973 ieee80211_rx_DELBA(ieee, skb);
1974 break;
1975 default:
ecdfa446
GKH
1976 break;
1977 }
1978 return;
1979
1980}
1981inline int
1982ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1983 struct ieee80211_rx_stats *rx_stats, u16 type,
1984 u16 stype)
1985{
1986 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1987 u16 errcode;
1988 u8* challenge;
1989 int chlen=0;
1990 int aid;
1991 struct ieee80211_assoc_response_frame *assoc_resp;
ecdfa446
GKH
1992 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1993
1994 if(!ieee->proto_started)
1995 return 0;
ecdfa446
GKH
1996
1997 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1998
1999 case IEEE80211_STYPE_ASSOC_RESP:
2000 case IEEE80211_STYPE_REASSOC_RESP:
2001
2002 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2003 WLAN_FC_GET_STYPE(header->frame_ctl));
2004 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2005 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2006 ieee->iw_mode == IW_MODE_INFRA){
2007 struct ieee80211_network network_resp;
2008 struct ieee80211_network *network = &network_resp;
2009
2010 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2011 ieee->state=IEEE80211_LINKED;
2012 ieee->assoc_id = aid;
2013 ieee->softmac_stats.rx_ass_ok++;
2014 /* station support qos */
2015 /* Let the register setting defaultly with Legacy station */
2016 if(ieee->qos_support) {
2017 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2018 memset(network, 0, sizeof(*network));
2019 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2020 rx_stats->len - sizeof(*assoc_resp),\
2021 network,rx_stats)){
2022 return 1;
2023 }
2024 else
2025 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2026 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2027 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2028 }
2029 if (ieee->handle_assoc_response != NULL)
2030 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2031 }
2032 ieee80211_associate_complete(ieee);
2033 } else {
2034 /* aid could not been allocated */
2035 ieee->softmac_stats.rx_ass_err++;
2036 printk(
2037 "Association response status code 0x%x\n",
2038 errcode);
2039 IEEE80211_DEBUG_MGMT(
2040 "Association response status code 0x%x\n",
2041 errcode);
2042 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
ecdfa446 2043 queue_work(ieee->wq, &ieee->associate_procedure_wq);
ecdfa446
GKH
2044 } else {
2045 ieee80211_associate_abort(ieee);
2046 }
2047 }
2048 }
2049 break;
2050
2051 case IEEE80211_STYPE_ASSOC_REQ:
2052 case IEEE80211_STYPE_REASSOC_REQ:
2053
2054 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2055 ieee->iw_mode == IW_MODE_MASTER)
2056
2057 ieee80211_rx_assoc_rq(ieee, skb);
2058 break;
2059
2060 case IEEE80211_STYPE_AUTH:
2061
2062 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2063 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2064 ieee->iw_mode == IW_MODE_INFRA){
2065
2066 IEEE80211_DEBUG_MGMT("Received authentication response");
2067
2068 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2069 if(ieee->open_wep || !challenge){
2070 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2071 ieee->softmac_stats.rx_auth_rs_ok++;
2072 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2073 {
2074 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2075 {
65a43784 2076 // WEP or TKIP encryption
ecdfa446
GKH
2077 if(IsHTHalfNmodeAPs(ieee))
2078 {
2079 bSupportNmode = true;
2080 bHalfSupportNmode = true;
2081 }
2082 else
2083 {
2084 bSupportNmode = false;
2085 bHalfSupportNmode = false;
2086 }
65a43784 2087 printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
ecdfa446
GKH
2088 }
2089 }
2090 /* Dummy wirless mode setting to avoid encryption issue */
2091 if(bSupportNmode) {
2092 //N mode setting
2093 ieee->SetWirelessMode(ieee->dev, \
2094 ieee->current_network.mode);
2095 }else{
2096 //b/g mode setting
2097 /*TODO*/
2098 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2099 }
2100
2101 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2102 {
2103 printk("===============>entern half N mode\n");
2104 ieee->bHalfWirelessN24GMode = true;
2105 }
2106 else
2107 ieee->bHalfWirelessN24GMode = false;
2108
2109 ieee80211_associate_step2(ieee);
2110 }else{
fb5fe277 2111 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
ecdfa446
GKH
2112 }
2113 }else{
2114 ieee->softmac_stats.rx_auth_rs_err++;
2115 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2116
2117 printk("Authentication respose status code 0x%x",errcode);
2118 ieee80211_associate_abort(ieee);
2119 }
2120
2121 }else if (ieee->iw_mode == IW_MODE_MASTER){
2122 ieee80211_rx_auth_rq(ieee, skb);
2123 }
2124 }
2125 break;
2126
2127 case IEEE80211_STYPE_PROBE_REQ:
2128
2129 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2130 ((ieee->iw_mode == IW_MODE_ADHOC ||
2131 ieee->iw_mode == IW_MODE_MASTER) &&
2132 ieee->state == IEEE80211_LINKED)){
2133 ieee80211_rx_probe_rq(ieee, skb);
2134 }
2135 break;
2136
2137 case IEEE80211_STYPE_DISASSOC:
2138 case IEEE80211_STYPE_DEAUTH:
2139 /* FIXME for now repeat all the association procedure
2140 * both for disassociation and deauthentication
2141 */
2142 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2143 ieee->state == IEEE80211_LINKED &&
2144 ieee->iw_mode == IW_MODE_INFRA){
2145
2146 ieee->state = IEEE80211_ASSOCIATING;
2147 ieee->softmac_stats.reassoc++;
2148 ieee->is_roaming = true;
2149 ieee80211_disassociate(ieee);
ecdfa446 2150 RemovePeerTS(ieee, header->addr2);
ecdfa446 2151 queue_work(ieee->wq, &ieee->associate_procedure_wq);
ecdfa446
GKH
2152 }
2153 break;
2154 case IEEE80211_STYPE_MANAGE_ACT:
2155 ieee80211_process_action(ieee,skb);
2156 break;
2157 default:
2158 return -1;
2159 break;
2160 }
2161
ecdfa446
GKH
2162 return 0;
2163}
2164
2165/* following are for a simplier TX queue management.
2166 * Instead of using netif_[stop/wake]_queue the driver
2167 * will uses these two function (plus a reset one), that
2168 * will internally uses the kernel netif_* and takes
2169 * care of the ieee802.11 fragmentation.
2170 * So the driver receives a fragment per time and might
2171 * call the stop function when it want without take care
bbc9a991 2172 * to have enough room to TX an entire packet.
ecdfa446
GKH
2173 * This might be useful if each fragment need it's own
2174 * descriptor, thus just keep a total free memory > than
bbc9a991 2175 * the max fragmentation threshold is not enough.. If the
ecdfa446
GKH
2176 * ieee802.11 stack passed a TXB struct then you needed
2177 * to keep N free descriptors where
2178 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2179 * In this way you need just one and the 802.11 stack
2180 * will take care of buffering fragments and pass them to
2181 * to the driver later, when it wakes the queue.
2182 */
2183void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2184{
2185
2186 unsigned int queue_index = txb->queue_index;
2187 unsigned long flags;
2188 int i;
2189 cb_desc *tcb_desc = NULL;
2190
2191 spin_lock_irqsave(&ieee->lock,flags);
2192
2193 /* called with 2nd parm 0, no tx mgmt lock required */
2194 ieee80211_sta_wakeup(ieee,0);
2195
2196 /* update the tx status */
ecdfa446
GKH
2197 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2198 if(tcb_desc->bMulticast) {
2199 ieee->stats.multicast++;
2200 }
85c876e4 2201
ecdfa446
GKH
2202 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2203 for(i = 0; i < txb->nr_frags; i++) {
2204#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2205 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2206#else
2207 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2208#endif
2209 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2210 (ieee->queue_stop)) {
2211 /* insert the skb packet to the wait queue */
2212 /* as for the completion function, it does not need
2213 * to check it any more.
2214 * */
ecdfa446
GKH
2215#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2216 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2217#else
2218 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2219#endif
2220 }else{
2221 ieee->softmac_data_hard_start_xmit(
2222 txb->fragments[i],
2223 ieee->dev,ieee->rate);
ecdfa446
GKH
2224 }
2225 }
85c876e4 2226
ecdfa446
GKH
2227 ieee80211_txb_free(txb);
2228
ecdfa446
GKH
2229 spin_unlock_irqrestore(&ieee->lock,flags);
2230
2231}
2232
2233/* called with ieee->lock acquired */
2234void ieee80211_resume_tx(struct ieee80211_device *ieee)
2235{
2236 int i;
2237 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2238
2239 if (ieee->queue_stop){
2240 ieee->tx_pending.frag = i;
2241 return;
2242 }else{
2243
2244 ieee->softmac_data_hard_start_xmit(
2245 ieee->tx_pending.txb->fragments[i],
2246 ieee->dev,ieee->rate);
ecdfa446 2247 ieee->stats.tx_packets++;
ecdfa446
GKH
2248 }
2249 }
2250
2251
2252 ieee80211_txb_free(ieee->tx_pending.txb);
2253 ieee->tx_pending.txb = NULL;
2254}
2255
2256
2257void ieee80211_reset_queue(struct ieee80211_device *ieee)
2258{
2259 unsigned long flags;
2260
2261 spin_lock_irqsave(&ieee->lock,flags);
2262 init_mgmt_queue(ieee);
2263 if (ieee->tx_pending.txb){
2264 ieee80211_txb_free(ieee->tx_pending.txb);
2265 ieee->tx_pending.txb = NULL;
2266 }
2267 ieee->queue_stop = 0;
2268 spin_unlock_irqrestore(&ieee->lock,flags);
2269
2270}
2271
fb5fe277 2272void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
ecdfa446
GKH
2273{
2274
2275 unsigned long flags;
2276 struct sk_buff *skb;
2277 struct ieee80211_hdr_3addr *header;
2278
2279 spin_lock_irqsave(&ieee->lock,flags);
2280 if (! ieee->queue_stop) goto exit;
2281
2282 ieee->queue_stop = 0;
2283
2284 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2285 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2286
2287 header = (struct ieee80211_hdr_3addr *) skb->data;
2288
2289 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2290
2291 if (ieee->seq_ctrl[0] == 0xFFF)
2292 ieee->seq_ctrl[0] = 0;
2293 else
2294 ieee->seq_ctrl[0]++;
2295
2296 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
ecdfa446
GKH
2297 }
2298 }
2299 if (!ieee->queue_stop && ieee->tx_pending.txb)
2300 ieee80211_resume_tx(ieee);
2301
2302 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2303 ieee->softmac_stats.swtxawake++;
2304 netif_wake_queue(ieee->dev);
2305 }
2306
2307exit :
2308 spin_unlock_irqrestore(&ieee->lock,flags);
2309}
2310
2311
fb5fe277 2312void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
ecdfa446 2313{
ecdfa446
GKH
2314 if (! netif_queue_stopped(ieee->dev)){
2315 netif_stop_queue(ieee->dev);
2316 ieee->softmac_stats.swtxstop++;
2317 }
2318 ieee->queue_stop = 1;
ecdfa446
GKH
2319}
2320
2321
2322inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2323{
2324
2325 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2326
2327 /* an IBSS cell address must have the two less significant
2328 * bits of the first byte = 2
2329 */
2330 ieee->current_network.bssid[0] &= ~0x01;
2331 ieee->current_network.bssid[0] |= 0x02;
2332}
2333
2334/* called in user context only */
2335void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2336{
2337 ieee->assoc_id = 1;
2338
2339 if (ieee->current_network.ssid_len == 0){
2340 strncpy(ieee->current_network.ssid,
2341 IEEE80211_DEFAULT_TX_ESSID,
2342 IW_ESSID_MAX_SIZE);
2343
2344 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2345 ieee->ssid_set = 1;
2346 }
2347
2348 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2349
2350 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2351 ieee->state = IEEE80211_LINKED;
2352 ieee->link_change(ieee->dev);
2353 notify_wx_assoc_event(ieee);
2354
2355 if (ieee->data_hard_resume)
2356 ieee->data_hard_resume(ieee->dev);
2357
2358 netif_carrier_on(ieee->dev);
2359}
2360
2361void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2362{
2363 if(ieee->raw_tx){
2364
2365 if (ieee->data_hard_resume)
2366 ieee->data_hard_resume(ieee->dev);
2367
2368 netif_carrier_on(ieee->dev);
2369 }
2370}
ecdfa446
GKH
2371void ieee80211_start_ibss_wq(struct work_struct *work)
2372{
2373
2374 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2375 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
ecdfa446
GKH
2376 /* iwconfig mode ad-hoc will schedule this and return
2377 * on the other hand this will block further iwconfig SET
2378 * operations because of the wx_sem hold.
2379 * Anyway some most set operations set a flag to speed-up
2380 * (abort) this wq (when syncro scanning) before sleeping
2381 * on the semaphore
2382 */
2383 if(!ieee->proto_started){
2384 printk("==========oh driver down return\n");
2385 return;
2386 }
2387 down(&ieee->wx_sem);
2388
2389 if (ieee->current_network.ssid_len == 0){
2390 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2391 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2392 ieee->ssid_set = 1;
2393 }
2394
65a43784 2395 ieee->state = IEEE80211_NOLINK;
ecdfa446
GKH
2396 /* check if we have this cell in our network list */
2397 ieee80211_softmac_check_all_nets(ieee);
2398
2399
2400#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
2401 if (ieee->state == IEEE80211_NOLINK)
2402 ieee->current_network.channel = 6;
2403#endif
2404 /* if not then the state is not linked. Maybe the user swithced to
2405 * ad-hoc mode just after being in monitor mode, or just after
2406 * being very few time in managed mode (so the card have had no
2407 * time to scan all the chans..) or we have just run up the iface
2408 * after setting ad-hoc mode. So we have to give another try..
2409 * Here, in ibss mode, should be safe to do this without extra care
2410 * (in bss mode we had to make sure no-one tryed to associate when
2411 * we had just checked the ieee->state and we was going to start the
2412 * scan) beacause in ibss mode the ieee80211_new_net function, when
2413 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2414 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2415 * scan, that will stop at the first round because it sees the state
2416 * associated.
2417 */
2418 if (ieee->state == IEEE80211_NOLINK)
2419 ieee80211_start_scan_syncro(ieee);
2420
2421 /* the network definitively is not here.. create a new cell */
2422 if (ieee->state == IEEE80211_NOLINK){
2423 printk("creating new IBSS cell\n");
2424 if(!ieee->wap_set)
2425 ieee80211_randomize_cell(ieee);
2426
2427 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2428
2429 ieee->current_network.rates_len = 4;
2430
2431 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2432 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2433 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2434 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2435
2436 }else
2437 ieee->current_network.rates_len = 0;
2438
2439 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2440 ieee->current_network.rates_ex_len = 8;
2441
2442 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2443 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2444 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2445 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2446 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2447 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2448 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2449 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2450
2451 ieee->rate = 108;
2452 }else{
2453 ieee->current_network.rates_ex_len = 0;
2454 ieee->rate = 22;
2455 }
2456
2457 // By default, WMM function will be disabled in IBSS mode
2458 ieee->current_network.QoS_Enable = 0;
2459 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2460 ieee->current_network.atim_window = 0;
2461 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2462 if(ieee->short_slot)
2463 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2464
2465 }
2466
2467 ieee->state = IEEE80211_LINKED;
2468
2469 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2470 ieee->link_change(ieee->dev);
2471
2472 notify_wx_assoc_event(ieee);
2473
2474 ieee80211_start_send_beacons(ieee);
2475
2476 if (ieee->data_hard_resume)
2477 ieee->data_hard_resume(ieee->dev);
2478 netif_carrier_on(ieee->dev);
2479
2480 up(&ieee->wx_sem);
2481}
2482
2483inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2484{
ecdfa446 2485 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
ecdfa446
GKH
2486}
2487
2488/* this is called only in user context, with wx_sem held */
2489void ieee80211_start_bss(struct ieee80211_device *ieee)
2490{
2491 unsigned long flags;
2492#ifdef ENABLE_DOT11D
2493 //
2494 // Ref: 802.11d 11.1.3.3
2495 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2496 //
2497 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2498 {
2499 if(! ieee->bGlobalDomain)
2500 {
2501 return;
2502 }
2503 }
2504#endif
2505 /* check if we have already found the net we
2506 * are interested in (if any).
2507 * if not (we are disassociated and we are not
2508 * in associating / authenticating phase) start the background scanning.
2509 */
2510 ieee80211_softmac_check_all_nets(ieee);
2511
2512 /* ensure no-one start an associating process (thus setting
2513 * the ieee->state to ieee80211_ASSOCIATING) while we
2514 * have just cheked it and we are going to enable scan.
2515 * The ieee80211_new_net function is always called with
2516 * lock held (from both ieee80211_softmac_check_all_nets and
2517 * the rx path), so we cannot be in the middle of such function
2518 */
2519 spin_lock_irqsave(&ieee->lock, flags);
2520
2521 if (ieee->state == IEEE80211_NOLINK){
65a43784 2522#ifdef ENABLE_IPS
2523 if(ieee->ieee80211_ips_leave_wq != NULL)
2524 ieee->ieee80211_ips_leave_wq(ieee->dev);
2525#endif
ecdfa446 2526 ieee->actscanning = true;
fb5fe277 2527 ieee80211_rtl_start_scan(ieee);
ecdfa446
GKH
2528 }
2529 spin_unlock_irqrestore(&ieee->lock, flags);
2530}
2531
2532/* called only in userspace context */
2533void ieee80211_disassociate(struct ieee80211_device *ieee)
2534{
2535
2536
2537 netif_carrier_off(ieee->dev);
2538 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2539 ieee80211_reset_queue(ieee);
2540
2541 if (ieee->data_hard_stop)
2542 ieee->data_hard_stop(ieee->dev);
2543#ifdef ENABLE_DOT11D
2544 if(IS_DOT11D_ENABLE(ieee))
2545 Dot11d_Reset(ieee);
2546#endif
ecdfa446
GKH
2547 ieee->is_set_key = false;
2548 ieee->link_change(ieee->dev);
ae67b584
SO
2549 if (ieee->state == IEEE80211_LINKED ||
2550 ieee->state == IEEE80211_ASSOCIATING) {
2551 ieee->state = IEEE80211_NOLINK;
2552 notify_wx_assoc_event(ieee);
2553 }
2554
2555 ieee->state = IEEE80211_NOLINK;
ecdfa446
GKH
2556
2557}
ecdfa446
GKH
2558void ieee80211_associate_retry_wq(struct work_struct *work)
2559{
2560 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2561 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
ecdfa446
GKH
2562 unsigned long flags;
2563
2564 down(&ieee->wx_sem);
2565 if(!ieee->proto_started)
2566 goto exit;
2567
2568 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2569 goto exit;
2570
2571 /* until we do not set the state to IEEE80211_NOLINK
2572 * there are no possibility to have someone else trying
2573 * to start an association procdure (we get here with
2574 * ieee->state = IEEE80211_ASSOCIATING).
2575 * When we set the state to IEEE80211_NOLINK it is possible
2576 * that the RX path run an attempt to associate, but
2577 * both ieee80211_softmac_check_all_nets and the
2578 * RX path works with ieee->lock held so there are no
2579 * problems. If we are still disassociated then start a scan.
2580 * the lock here is necessary to ensure no one try to start
2581 * an association procedure when we have just checked the
2582 * state and we are going to start the scan.
2583 */
2584 ieee->beinretry = true;
2585 ieee->state = IEEE80211_NOLINK;
2586
2587 ieee80211_softmac_check_all_nets(ieee);
2588
2589 spin_lock_irqsave(&ieee->lock, flags);
2590
2591 if(ieee->state == IEEE80211_NOLINK)
2592 {
2593 ieee->is_roaming= false;
2594 ieee->actscanning = true;
fb5fe277 2595 ieee80211_rtl_start_scan(ieee);
ecdfa446
GKH
2596 }
2597 spin_unlock_irqrestore(&ieee->lock, flags);
2598
2599 ieee->beinretry = false;
2600exit:
2601 up(&ieee->wx_sem);
2602}
2603
2604struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2605{
2606 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2607
2608 struct sk_buff *skb;
2609 struct ieee80211_probe_response *b;
2610
2611 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2612
2613 if (!skb)
2614 return NULL;
2615
2616 b = (struct ieee80211_probe_response *) skb->data;
2617 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2618
2619 return skb;
2620
2621}
2622
2623struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2624{
2625 struct sk_buff *skb;
2626 struct ieee80211_probe_response *b;
2627
2628 skb = ieee80211_get_beacon_(ieee);
2629 if(!skb)
2630 return NULL;
2631
2632 b = (struct ieee80211_probe_response *) skb->data;
2633 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2634
2635 if (ieee->seq_ctrl[0] == 0xFFF)
2636 ieee->seq_ctrl[0] = 0;
2637 else
2638 ieee->seq_ctrl[0]++;
2639
2640 return skb;
2641}
2642
65a43784 2643void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
ecdfa446
GKH
2644{
2645 ieee->sync_scan_hurryup = 1;
2646 down(&ieee->wx_sem);
65a43784 2647 ieee80211_stop_protocol(ieee, shutdown);
ecdfa446
GKH
2648 up(&ieee->wx_sem);
2649}
2650
2651
65a43784 2652void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
ecdfa446
GKH
2653{
2654 if (!ieee->proto_started)
2655 return;
2656
65a43784 2657 if(shutdown)
2658 ieee->proto_started = 0;
2659 ieee->proto_stoppping = 1;
ecdfa446
GKH
2660
2661 ieee80211_stop_send_beacons(ieee);
2662 del_timer_sync(&ieee->associate_timer);
ecdfa446
GKH
2663 cancel_delayed_work(&ieee->associate_retry_wq);
2664 cancel_delayed_work(&ieee->start_ibss_wq);
ecdfa446
GKH
2665 ieee80211_stop_scan(ieee);
2666
2667 ieee80211_disassociate(ieee);
2668 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
65a43784 2669
2670 ieee->proto_stoppping = 0;
ecdfa446
GKH
2671}
2672
2673void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2674{
2675 ieee->sync_scan_hurryup = 0;
2676 down(&ieee->wx_sem);
2677 ieee80211_start_protocol(ieee);
2678 up(&ieee->wx_sem);
2679}
2680
2681void ieee80211_start_protocol(struct ieee80211_device *ieee)
2682{
2683 short ch = 0;
2684 int i = 0;
2685 if (ieee->proto_started)
2686 return;
2687
2688 ieee->proto_started = 1;
2689
2690 if (ieee->current_network.channel == 0){
2691 do{
2692 ch++;
2693 if (ch > MAX_CHANNEL_NUMBER)
2694 return; /* no channel found */
2695#ifdef ENABLE_DOT11D
2696 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2697#else
2698 }while(!ieee->channel_map[ch]);
2699#endif
2700 ieee->current_network.channel = ch;
2701 }
2702
2703 if (ieee->current_network.beacon_interval == 0)
2704 ieee->current_network.beacon_interval = 100;
ecdfa446
GKH
2705
2706 for(i = 0; i < 17; i++) {
2707 ieee->last_rxseq_num[i] = -1;
2708 ieee->last_rxfrag_num[i] = -1;
2709 ieee->last_packet_time[i] = 0;
2710 }
2711
2712 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2713
65a43784 2714 ieee->state = IEEE80211_NOLINK;
2715
ecdfa446
GKH
2716
2717 /* if the user set the MAC of the ad-hoc cell and then
2718 * switch to managed mode, shall we make sure that association
2719 * attempts does not fail just because the user provide the essid
2720 * and the nic is still checking for the AP MAC ??
2721 */
2722 if (ieee->iw_mode == IW_MODE_INFRA)
2723 ieee80211_start_bss(ieee);
2724
2725 else if (ieee->iw_mode == IW_MODE_ADHOC)
2726 ieee80211_start_ibss(ieee);
2727
2728 else if (ieee->iw_mode == IW_MODE_MASTER)
2729 ieee80211_start_master_bss(ieee);
2730
2731 else if(ieee->iw_mode == IW_MODE_MONITOR)
2732 ieee80211_start_monitor_mode(ieee);
2733}
2734
2735
2736#define DRV_NAME "Ieee80211"
2737void ieee80211_softmac_init(struct ieee80211_device *ieee)
2738{
2739 int i;
2740 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2741
2742 ieee->state = IEEE80211_NOLINK;
2743 ieee->sync_scan_hurryup = 0;
2744 for(i = 0; i < 5; i++) {
2745 ieee->seq_ctrl[i] = 0;
2746 }
2747#ifdef ENABLE_DOT11D
7a6cb0d5 2748 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
ecdfa446
GKH
2749 if (!ieee->pDot11dInfo)
2750 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
ecdfa446
GKH
2751#endif
2752 //added for AP roaming
2753 ieee->LinkDetectInfo.SlotNum = 2;
2754 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2755 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2756
2757 ieee->assoc_id = 0;
2758 ieee->queue_stop = 0;
2759 ieee->scanning = 0;
2760 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2761 ieee->wap_set = 0;
2762 ieee->ssid_set = 0;
2763 ieee->proto_started = 0;
2764 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2765 ieee->rate = 22;
2766 ieee->ps = IEEE80211_PS_DISABLED;
2767 ieee->sta_sleep = 0;
2768 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2769 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2770 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2771 //added by amy
2772 ieee->actscanning = false;
2773 ieee->beinretry = false;
2774 ieee->is_set_key = false;
2775 init_mgmt_queue(ieee);
2776
2777 ieee->sta_edca_param[0] = 0x0000A403;
2778 ieee->sta_edca_param[1] = 0x0000A427;
2779 ieee->sta_edca_param[2] = 0x005E4342;
2780 ieee->sta_edca_param[3] = 0x002F3262;
2781 ieee->aggregation = true;
2782 ieee->enable_rx_imm_BA = 1;
ecdfa446
GKH
2783 ieee->tx_pending.txb = NULL;
2784
2785 init_timer(&ieee->associate_timer);
2786 ieee->associate_timer.data = (unsigned long)ieee;
2787 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2788
2789 init_timer(&ieee->beacon_timer);
2790 ieee->beacon_timer.data = (unsigned long) ieee;
2791 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2792
ecdfa446 2793 ieee->wq = create_workqueue(DRV_NAME);
ecdfa446 2794
ecdfa446
GKH
2795 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2796 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2797 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2798 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2799 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2800 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2801
ecdfa446
GKH
2802 sema_init(&ieee->wx_sem, 1);
2803 sema_init(&ieee->scan_sem, 1);
65a43784 2804#ifdef ENABLE_IPS
2805 sema_init(&ieee->ips_sem,1);
2806#endif
ecdfa446
GKH
2807 spin_lock_init(&ieee->mgmt_tx_lock);
2808 spin_lock_init(&ieee->beacon_lock);
2809
2810 tasklet_init(&ieee->ps_task,
2811 (void(*)(unsigned long)) ieee80211_sta_ps,
2812 (unsigned long)ieee);
2813
2814}
2815
2816void ieee80211_softmac_free(struct ieee80211_device *ieee)
2817{
2818 down(&ieee->wx_sem);
2819#ifdef ENABLE_DOT11D
2820 if(NULL != ieee->pDot11dInfo)
2821 {
2822 kfree(ieee->pDot11dInfo);
2823 ieee->pDot11dInfo = NULL;
2824 }
2825#endif
2826 del_timer_sync(&ieee->associate_timer);
2827
ecdfa446
GKH
2828 cancel_delayed_work(&ieee->associate_retry_wq);
2829 destroy_workqueue(ieee->wq);
ecdfa446
GKH
2830
2831 up(&ieee->wx_sem);
2832}
2833
2834/********************************************************
2835 * Start of WPA code. *
2836 * this is stolen from the ipw2200 driver *
2837 ********************************************************/
2838
2839
2840static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2841{
2842 /* This is called when wpa_supplicant loads and closes the driver
2843 * interface. */
2844 printk("%s WPA\n",value ? "enabling" : "disabling");
2845 ieee->wpa_enabled = value;
2846 return 0;
2847}
2848
2849
2850void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2851{
2852 /* make sure WPA is enabled */
2853 ieee80211_wpa_enable(ieee, 1);
2854
2855 ieee80211_disassociate(ieee);
2856}
2857
2858
2859static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2860{
2861
2862 int ret = 0;
2863
2864 switch (command) {
2865 case IEEE_MLME_STA_DEAUTH:
2866 // silently ignore
2867 break;
2868
2869 case IEEE_MLME_STA_DISASSOC:
2870 ieee80211_disassociate(ieee);
2871 break;
2872
2873 default:
2874 printk("Unknown MLME request: %d\n", command);
2875 ret = -EOPNOTSUPP;
2876 }
2877
2878 return ret;
2879}
2880
2881
2882static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2883 struct ieee_param *param, int plen)
2884{
2885 u8 *buf;
2886
2887 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2888 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2889 return -EINVAL;
2890
2891 if (param->u.wpa_ie.len) {
94002c07
JL
2892 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2893 GFP_KERNEL);
ecdfa446
GKH
2894 if (buf == NULL)
2895 return -ENOMEM;
2896
ecdfa446
GKH
2897 kfree(ieee->wpa_ie);
2898 ieee->wpa_ie = buf;
2899 ieee->wpa_ie_len = param->u.wpa_ie.len;
2900 } else {
2901 kfree(ieee->wpa_ie);
2902 ieee->wpa_ie = NULL;
2903 ieee->wpa_ie_len = 0;
2904 }
2905
2906 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2907 return 0;
2908}
2909
2910#define AUTH_ALG_OPEN_SYSTEM 0x1
2911#define AUTH_ALG_SHARED_KEY 0x2
2912
2913static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2914{
2915
2916 struct ieee80211_security sec = {
2917 .flags = SEC_AUTH_MODE,
2918 };
2919 int ret = 0;
2920
2921 if (value & AUTH_ALG_SHARED_KEY) {
2922 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2923 ieee->open_wep = 0;
2924 ieee->auth_mode = 1;
2925 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2926 sec.auth_mode = WLAN_AUTH_OPEN;
2927 ieee->open_wep = 1;
2928 ieee->auth_mode = 0;
2929 }
2930 else if (value & IW_AUTH_ALG_LEAP){
2931 sec.auth_mode = WLAN_AUTH_LEAP;
2932 ieee->open_wep = 1;
2933 ieee->auth_mode = 2;
2934 }
2935
2936
2937 if (ieee->set_security)
2938 ieee->set_security(ieee->dev, &sec);
ecdfa446
GKH
2939
2940 return ret;
2941}
2942
2943static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2944{
2945 int ret=0;
2946 unsigned long flags;
2947
2948 switch (name) {
2949 case IEEE_PARAM_WPA_ENABLED:
2950 ret = ieee80211_wpa_enable(ieee, value);
2951 break;
2952
2953 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2954 ieee->tkip_countermeasures=value;
2955 break;
2956
2957 case IEEE_PARAM_DROP_UNENCRYPTED: {
2958 /* HACK:
2959 *
2960 * wpa_supplicant calls set_wpa_enabled when the driver
2961 * is loaded and unloaded, regardless of if WPA is being
2962 * used. No other calls are made which can be used to
2963 * determine if encryption will be used or not prior to
2964 * association being expected. If encryption is not being
2965 * used, drop_unencrypted is set to false, else true -- we
2966 * can use this to determine if the CAP_PRIVACY_ON bit should
2967 * be set.
2968 */
2969 struct ieee80211_security sec = {
2970 .flags = SEC_ENABLED,
2971 .enabled = value,
2972 };
2973 ieee->drop_unencrypted = value;
2974 /* We only change SEC_LEVEL for open mode. Others
2975 * are set by ipw_wpa_set_encryption.
2976 */
2977 if (!value) {
2978 sec.flags |= SEC_LEVEL;
2979 sec.level = SEC_LEVEL_0;
2980 }
2981 else {
2982 sec.flags |= SEC_LEVEL;
2983 sec.level = SEC_LEVEL_1;
2984 }
2985 if (ieee->set_security)
2986 ieee->set_security(ieee->dev, &sec);
2987 break;
2988 }
2989
2990 case IEEE_PARAM_PRIVACY_INVOKED:
2991 ieee->privacy_invoked=value;
2992 break;
2993
2994 case IEEE_PARAM_AUTH_ALGS:
2995 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2996 break;
2997
2998 case IEEE_PARAM_IEEE_802_1X:
2999 ieee->ieee802_1x=value;
3000 break;
3001 case IEEE_PARAM_WPAX_SELECT:
3002 // added for WPA2 mixed mode
3003 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3004 ieee->wpax_type_set = 1;
3005 ieee->wpax_type_notify = value;
3006 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3007 break;
3008
3009 default:
3010 printk("Unknown WPA param: %d\n",name);
3011 ret = -EOPNOTSUPP;
3012 }
3013
3014 return ret;
3015}
3016
3017/* implementation borrowed from hostap driver */
3018
3019static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3020 struct ieee_param *param, int param_len)
3021{
3022 int ret = 0;
3023
3024 struct ieee80211_crypto_ops *ops;
3025 struct ieee80211_crypt_data **crypt;
3026
3027 struct ieee80211_security sec = {
3028 .flags = 0,
3029 };
3030
3031 param->u.crypt.err = 0;
3032 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3033
3034 if (param_len !=
3035 (int) ((char *) param->u.crypt.key - (char *) param) +
3036 param->u.crypt.key_len) {
3037 printk("Len mismatch %d, %d\n", param_len,
3038 param->u.crypt.key_len);
3039 return -EINVAL;
3040 }
3041 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3042 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3043 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3044 if (param->u.crypt.idx >= WEP_KEYS)
3045 return -EINVAL;
3046 crypt = &ieee->crypt[param->u.crypt.idx];
3047 } else {
3048 return -EINVAL;
3049 }
3050
3051 if (strcmp(param->u.crypt.alg, "none") == 0) {
3052 if (crypt) {
3053 sec.enabled = 0;
3054 // FIXME FIXME
3055 //sec.encrypt = 0;
3056 sec.level = SEC_LEVEL_0;
3057 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3058 ieee80211_crypt_delayed_deinit(ieee, crypt);
3059 }
3060 goto done;
3061 }
3062 sec.enabled = 1;
3063// FIXME FIXME
3064// sec.encrypt = 1;
3065 sec.flags |= SEC_ENABLED;
3066
3067 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3068 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3069 strcmp(param->u.crypt.alg, "TKIP"))
3070 goto skip_host_crypt;
3071
3072 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
a010a337 3073 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
ecdfa446 3074 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
a010a337
HRK
3075 /* set WEP40 first, it will be modified according to WEP104 or
3076 * WEP40 at other place */
3077 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
ecdfa446 3078 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
a010a337 3079 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
ecdfa446 3080 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
ecdfa446
GKH
3081 if (ops == NULL) {
3082 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3083 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3084 ret = -EINVAL;
3085 goto done;
3086 }
3087
3088 if (*crypt == NULL || (*crypt)->ops != ops) {
3089 struct ieee80211_crypt_data *new_crypt;
3090
3091 ieee80211_crypt_delayed_deinit(ieee, crypt);
3092
32414878 3093 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
ecdfa446
GKH
3094 if (new_crypt == NULL) {
3095 ret = -ENOMEM;
3096 goto done;
3097 }
3098 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3099 new_crypt->ops = ops;
a010a337 3100 if (new_crypt->ops)
ecdfa446
GKH
3101 new_crypt->priv =
3102 new_crypt->ops->init(param->u.crypt.idx);
3103
3104 if (new_crypt->priv == NULL) {
3105 kfree(new_crypt);
3106 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3107 ret = -EINVAL;
3108 goto done;
3109 }
3110
3111 *crypt = new_crypt;
3112 }
3113
3114 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3115 (*crypt)->ops->set_key(param->u.crypt.key,
3116 param->u.crypt.key_len, param->u.crypt.seq,
3117 (*crypt)->priv) < 0) {
3118 printk("key setting failed\n");
3119 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3120 ret = -EINVAL;
3121 goto done;
3122 }
3123
3124 skip_host_crypt:
3125 if (param->u.crypt.set_tx) {
3126 ieee->tx_keyidx = param->u.crypt.idx;
3127 sec.active_key = param->u.crypt.idx;
3128 sec.flags |= SEC_ACTIVE_KEY;
3129 } else
3130 sec.flags &= ~SEC_ACTIVE_KEY;
3131
3132 if (param->u.crypt.alg != NULL) {
3133 memcpy(sec.keys[param->u.crypt.idx],
3134 param->u.crypt.key,
3135 param->u.crypt.key_len);
3136 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3137 sec.flags |= (1 << param->u.crypt.idx);
3138
3139 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3140 sec.flags |= SEC_LEVEL;
3141 sec.level = SEC_LEVEL_1;
3142 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3143 sec.flags |= SEC_LEVEL;
3144 sec.level = SEC_LEVEL_2;
3145 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3146 sec.flags |= SEC_LEVEL;
3147 sec.level = SEC_LEVEL_3;
3148 }
3149 }
3150 done:
3151 if (ieee->set_security)
3152 ieee->set_security(ieee->dev, &sec);
3153
3154 /* Do not reset port if card is in Managed mode since resetting will
3155 * generate new IEEE 802.11 authentication which may end up in looping
3156 * with IEEE 802.1X. If your hardware requires a reset after WEP
3157 * configuration (for example... Prism2), implement the reset_port in
3158 * the callbacks structures used to initialize the 802.11 stack. */
3159 if (ieee->reset_on_keychange &&
3160 ieee->iw_mode != IW_MODE_INFRA &&
3161 ieee->reset_port &&
3162 ieee->reset_port(ieee->dev)) {
3163 printk("reset_port failed\n");
3164 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3165 return -EINVAL;
3166 }
3167
3168 return ret;
3169}
3170
3171inline struct sk_buff *ieee80211_disassociate_skb(
3172 struct ieee80211_network *beacon,
3173 struct ieee80211_device *ieee,
3174 u8 asRsn)
3175{
3176 struct sk_buff *skb;
3177 struct ieee80211_disassoc *disass;
3178
3179 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3180 if (!skb)
3181 return NULL;
3182
3183 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3184 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3185 disass->header.duration_id = 0;
3186
3187 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3188 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3189 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3190
3191 disass->reason = asRsn;
3192 return skb;
3193}
3194
3195
3196void
3197SendDisassociation(
3198 struct ieee80211_device *ieee,
3199 u8* asSta,
3200 u8 asRsn
3201)
3202{
3203 struct ieee80211_network *beacon = &ieee->current_network;
3204 struct sk_buff *skb;
3205 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3206 if (skb){
3207 softmac_mgmt_xmit(skb, ieee);
3208 //dev_kfree_skb_any(skb);//edit by thomas
3209 }
3210}
3211
3212int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3213{
3214 struct ieee_param *param;
3215 int ret=0;
3216
3217 down(&ieee->wx_sem);
3218 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3219
3220 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3221 ret = -EINVAL;
3222 goto out;
3223 }
3224
32414878 3225 param = kmalloc(p->length, GFP_KERNEL);
ecdfa446
GKH
3226 if (param == NULL){
3227 ret = -ENOMEM;
3228 goto out;
3229 }
3230 if (copy_from_user(param, p->pointer, p->length)) {
3231 kfree(param);
3232 ret = -EFAULT;
3233 goto out;
3234 }
3235
3236 switch (param->cmd) {
3237
3238 case IEEE_CMD_SET_WPA_PARAM:
3239 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3240 param->u.wpa_param.value);
3241 break;
3242
3243 case IEEE_CMD_SET_WPA_IE:
3244 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3245 break;
3246
3247 case IEEE_CMD_SET_ENCRYPTION:
3248 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3249 break;
3250
3251 case IEEE_CMD_MLME:
3252 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3253 param->u.mlme.reason_code);
3254 break;
3255
3256 default:
3257 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3258 ret = -EOPNOTSUPP;
3259 break;
3260 }
3261
3262 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3263 ret = -EFAULT;
3264
3265 kfree(param);
3266out:
3267 up(&ieee->wx_sem);
3268
3269 return ret;
3270}
3271
3272void notify_wx_assoc_event(struct ieee80211_device *ieee)
3273{
3274 union iwreq_data wrqu;
3275 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3276 if (ieee->state == IEEE80211_LINKED)
3277 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3278 else
3279 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3280 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3281}
This page took 0.29459 seconds and 5 git commands to generate.