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