1
/* IEEE 802.11 SoftMAC layer
2
* Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
4
* Mostly extracted from the rtl8180-sa2400 driver for the
5
* in-kernel generic ieee802.11 stack.
7
* Few lines might be stolen from other part of the ieee80211
8
* stack. Copyright who own it's copyright
10
* WPA code stolen from the ipw2200 driver.
11
* Copyright who own it's copyright.
13
* released under the GPL
17
#include "ieee80211.h"
19
#include <linux/random.h>
20
#include <linux/delay.h>
21
#include <linux/slab.h>
22
#include <linux/version.h>
23
#include <asm/uaccess.h>
28
u8 rsn_authen_cipher_suite[16][4] = {
29
{0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
30
{0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
31
{0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
32
{0x00,0x0F,0xAC,0x03}, //WRAP-historical
33
{0x00,0x0F,0xAC,0x04}, //CCMP
34
{0x00,0x0F,0xAC,0x05}, //WEP-104
37
short ieee80211_is_54g(struct ieee80211_network net)
39
return ((net.rates_ex_len > 0) || (net.rates_len > 4));
42
short ieee80211_is_shortslot(struct ieee80211_network net)
44
return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
47
/* returns the total length needed for pleacing the RATE MFIE
48
* tag and the EXTENDED RATE MFIE tag if needed.
49
* It encludes two bytes per tag for the tag itself and its len
51
unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
53
unsigned int rate_len = 0;
55
if (ieee->modulation & IEEE80211_CCK_MODULATION)
56
rate_len = IEEE80211_CCK_RATE_LEN + 2;
58
if (ieee->modulation & IEEE80211_OFDM_MODULATION)
60
rate_len += IEEE80211_OFDM_RATE_LEN + 2;
65
/* pleace the MFIE rate, tag to the memory (double) poined.
66
* Then it updates the pointer so that
67
* it points after the new MFIE tag added.
69
void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
73
if (ieee->modulation & IEEE80211_CCK_MODULATION){
74
*tag++ = MFIE_TYPE_RATES;
76
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
77
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
78
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
79
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
82
/* We may add an option for custom rates that specific HW might support */
86
void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
90
if (ieee->modulation & IEEE80211_OFDM_MODULATION){
92
*tag++ = MFIE_TYPE_RATES_EX;
94
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
95
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
96
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
97
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
98
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
99
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
100
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
101
*tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
105
/* We may add an option for custom rates that specific HW might support */
110
void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
113
*tag++ = MFIE_TYPE_GENERIC; //0
122
if(ieee->current_network.wmm_info & 0x80) {
123
*tag++ = 0x0f|MAX_SP_Len;
134
void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
137
*tag++ = MFIE_TYPE_GENERIC; //0
148
printk(KERN_ALERT "This is enable turbo mode IE process\n");
152
void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
155
nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
158
* if the queue is full but we have newer frames then
159
* just overwrites the oldest.
161
* if (nh == ieee->mgmt_queue_tail)
164
ieee->mgmt_queue_head = nh;
165
ieee->mgmt_queue_ring[nh] = skb;
170
struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
174
if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
177
ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
179
ieee->mgmt_queue_tail =
180
(ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
185
void init_mgmt_queue(struct ieee80211_device *ieee)
187
ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
190
u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
192
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
195
// 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
196
if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
199
rate = ieee->basic_rate & 0x7f;
202
// 2005.01.26, by rcnjko.
203
if(ieee->mode == IEEE_A||
204
ieee->mode== IEEE_N_5G||
205
(ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
212
// Data rate of ProbeReq is already decided. Annie, 2005-03-31
213
if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
215
if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
225
void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
227
inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
230
short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
231
struct ieee80211_hdr_3addr *header=
232
(struct ieee80211_hdr_3addr *) skb->data;
234
cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
235
spin_lock_irqsave(&ieee->lock, flags);
237
/* called with 2nd param 0, no mgmt lock required */
238
ieee80211_sta_wakeup(ieee,0);
240
tcb_desc->queue_index = MGNT_QUEUE;
241
tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
242
tcb_desc->RATRIndex = 7;
243
tcb_desc->bTxDisableRateFallBack = 1;
244
tcb_desc->bTxUseDriverAssingedRate = 1;
247
if(ieee->queue_stop){
248
enqueue_mgmt(ieee,skb);
250
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
252
if (ieee->seq_ctrl[0] == 0xFFF)
253
ieee->seq_ctrl[0] = 0;
257
/* avoid watchdog triggers */
258
// ieee->dev->trans_start = jiffies;
259
ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
260
//dev_kfree_skb_any(skb);//edit by thomas
263
spin_unlock_irqrestore(&ieee->lock, flags);
265
spin_unlock_irqrestore(&ieee->lock, flags);
266
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
268
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
270
if (ieee->seq_ctrl[0] == 0xFFF)
271
ieee->seq_ctrl[0] = 0;
275
/* check wether the managed packet queued greater than 5 */
276
if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
277
(skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
278
(ieee->queue_stop) ) {
279
/* insert the skb packet to the management queue */
280
/* as for the completion function, it does not need
281
* to check it any more.
283
//printk("%s():insert to waitqueue!\n",__FUNCTION__);
284
skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
286
//printk("TX packet!\n");
287
ieee->softmac_hard_start_xmit(skb,ieee->dev);
288
//dev_kfree_skb_any(skb);//edit by thomas
290
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
294
inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
297
short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
298
struct ieee80211_hdr_3addr *header =
299
(struct ieee80211_hdr_3addr *) skb->data;
300
cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
302
tcb_desc->queue_index = MGNT_QUEUE;
303
tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
304
tcb_desc->RATRIndex = 7;
305
tcb_desc->bTxDisableRateFallBack = 1;
306
tcb_desc->bTxUseDriverAssingedRate = 1;
307
//printk("=============>%s()\n", __FUNCTION__);
310
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
312
if (ieee->seq_ctrl[0] == 0xFFF)
313
ieee->seq_ctrl[0] = 0;
317
/* avoid watchdog triggers */
318
// ieee->dev->trans_start = jiffies;
319
ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
323
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
325
if (ieee->seq_ctrl[0] == 0xFFF)
326
ieee->seq_ctrl[0] = 0;
330
ieee->softmac_hard_start_xmit(skb,ieee->dev);
333
//dev_kfree_skb_any(skb);//edit by thomas
336
inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
338
unsigned int len,rate_len;
341
struct ieee80211_probe_request *req;
343
len = ieee->current_network.ssid_len;
345
rate_len = ieee80211_MFIE_rate_len(ieee);
347
skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
348
2 + len + rate_len + ieee->tx_headroom);
352
skb_reserve(skb, ieee->tx_headroom);
354
req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
355
req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
356
req->header.duration_id = 0; //FIXME: is this OK ?
358
memset(req->header.addr1, 0xff, ETH_ALEN);
359
memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
360
memset(req->header.addr3, 0xff, ETH_ALEN);
362
tag = (u8 *) skb_put(skb,len+2+rate_len);
364
*tag++ = MFIE_TYPE_SSID;
366
memcpy(tag, ieee->current_network.ssid, len);
369
ieee80211_MFIE_Brate(ieee,&tag);
370
ieee80211_MFIE_Grate(ieee,&tag);
374
struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
375
void ieee80211_send_beacon(struct ieee80211_device *ieee)
380
//unsigned long flags;
381
skb = ieee80211_get_beacon_(ieee);
384
softmac_mgmt_xmit(skb, ieee);
385
ieee->softmac_stats.tx_beacons++;
386
//dev_kfree_skb_any(skb);//edit by thomas
388
// ieee->beacon_timer.expires = jiffies +
389
// (MSECS( ieee->current_network.beacon_interval -5));
391
//spin_lock_irqsave(&ieee->beacon_lock,flags);
392
if(ieee->beacon_txing && ieee->ieee_up){
393
// if(!timer_pending(&ieee->beacon_timer))
394
// add_timer(&ieee->beacon_timer);
395
mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
397
//spin_unlock_irqrestore(&ieee->beacon_lock,flags);
401
void ieee80211_send_beacon_cb(unsigned long _ieee)
403
struct ieee80211_device *ieee =
404
(struct ieee80211_device *) _ieee;
407
spin_lock_irqsave(&ieee->beacon_lock, flags);
408
ieee80211_send_beacon(ieee);
409
spin_unlock_irqrestore(&ieee->beacon_lock, flags);
413
void ieee80211_send_probe(struct ieee80211_device *ieee)
417
skb = ieee80211_probe_req(ieee);
419
softmac_mgmt_xmit(skb, ieee);
420
ieee->softmac_stats.tx_probe_rq++;
421
//dev_kfree_skb_any(skb);//edit by thomas
425
void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
427
if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
428
ieee80211_send_probe(ieee);
429
ieee80211_send_probe(ieee);
433
/* this performs syncro scan blocking the caller until all channels
434
* in the allowed channel map has been checked.
436
void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
440
u8 channel_map[MAX_CHANNEL_NUMBER+1];
441
memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
443
down(&ieee->scan_sem);
450
if (ch > MAX_CHANNEL_NUMBER)
451
goto out; /* scan completed */
453
}while(!channel_map[ch]);
455
}while(!ieee->channel_map[ch]);
458
/* this fuction can be called in two situations
459
* 1- We have switched to ad-hoc mode and we are
460
* performing a complete syncro scan before conclude
461
* there are no interesting cell and to create a
462
* new one. In this case the link state is
463
* IEEE80211_NOLINK until we found an interesting cell.
464
* If so the ieee8021_new_net, called by the RX path
465
* will set the state to IEEE80211_LINKED, so we stop
467
* 2- We are linked and the root uses run iwlist scan.
468
* So we switch to IEEE80211_LINKED_SCANNING to remember
469
* that we are still logically linked (not interested in
470
* new network events, despite for updating the net list,
471
* but we are temporarly 'unlinked' as the driver shall
472
* not filter RX frames and the channel is changing.
473
* So the only situation in witch are interested is to check
474
* if the state become LINKED because of the #1 situation
477
if (ieee->state == IEEE80211_LINKED)
479
ieee->set_chan(ieee->dev, ch);
481
if(channel_map[ch] == 1)
483
ieee80211_send_probe_requests(ieee);
485
/* this prevent excessive time wait when we
486
* need to wait for a syncro scan to end..
488
if(ieee->state < IEEE80211_LINKED)
491
if (ieee->sync_scan_hurryup)
495
msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
499
if(ieee->state < IEEE80211_LINKED){
500
ieee->actscanning = false;
504
ieee->sync_scan_hurryup = 0;
506
if(IS_DOT11D_ENABLE(ieee))
507
DOT11D_ScanComplete(ieee);
513
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
514
/* called both by wq with ieee->lock held */
515
void ieee80211_softmac_scan(struct ieee80211_device *ieee)
520
ieee->current_network.channel =
521
(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
522
if (watchdog++ > MAX_CHANNEL_NUMBER)
523
return; /* no good chans */
525
}while(!ieee->channel_map[ieee->current_network.channel]);
528
schedule_task(&ieee->softmac_scan_wq);
532
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
533
void ieee80211_softmac_scan_wq(struct work_struct *work)
535
struct delayed_work *dwork = container_of(work, struct delayed_work, work);
536
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
538
void ieee80211_softmac_scan_wq(struct ieee80211_device *ieee)
541
static short watchdog = 0;
542
u8 last_channel = ieee->current_network.channel;
544
u8 channel_map[MAX_CHANNEL_NUMBER+1];
545
memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
549
down(&ieee->scan_sem);
551
ieee->current_network.channel =
552
(ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
553
if (watchdog++ > MAX_CHANNEL_NUMBER)
555
//if current channel is not in channel map, set to default channel.
557
if (!channel_map[ieee->current_network.channel]);
559
if (!ieee->channel_map[ieee->current_network.channel]);
561
ieee->current_network.channel = 6;
562
goto out; /* no good chans */
565
}while(!channel_map[ieee->current_network.channel]);
567
}while(!ieee->channel_map[ieee->current_network.channel]);
569
if (ieee->scanning == 0 )
571
ieee->set_chan(ieee->dev, ieee->current_network.channel);
573
if(channel_map[ieee->current_network.channel] == 1)
575
ieee80211_send_probe_requests(ieee);
578
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
579
queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
581
//ieee->scan_timer.expires = jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME);
582
if (ieee->scanning == 1)
583
mod_timer(&ieee->scan_timer,(jiffies + MSECS(IEEE80211_SOFTMAC_SCAN_TIME)));
590
if(IS_DOT11D_ENABLE(ieee))
591
DOT11D_ScanComplete(ieee);
593
ieee->current_network.channel = last_channel;
594
ieee->actscanning = false;
600
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
601
void ieee80211_softmac_scan_cb(unsigned long _dev)
604
struct ieee80211_device *ieee = (struct ieee80211_device *)_dev;
606
spin_lock_irqsave(&ieee->lock, flags);
607
ieee80211_softmac_scan(ieee);
608
spin_unlock_irqrestore(&ieee->lock, flags);
613
void ieee80211_beacons_start(struct ieee80211_device *ieee)
616
spin_lock_irqsave(&ieee->beacon_lock,flags);
618
ieee->beacon_txing = 1;
619
ieee80211_send_beacon(ieee);
621
spin_unlock_irqrestore(&ieee->beacon_lock,flags);
624
void ieee80211_beacons_stop(struct ieee80211_device *ieee)
628
spin_lock_irqsave(&ieee->beacon_lock,flags);
630
ieee->beacon_txing = 0;
631
del_timer_sync(&ieee->beacon_timer);
633
spin_unlock_irqrestore(&ieee->beacon_lock,flags);
638
void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
640
if(ieee->stop_send_beacons)
641
ieee->stop_send_beacons(ieee->dev);
642
if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
643
ieee80211_beacons_stop(ieee);
647
void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
649
if(ieee->start_send_beacons)
650
ieee->start_send_beacons(ieee->dev);
651
if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
652
ieee80211_beacons_start(ieee);
656
void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
658
// unsigned long flags;
660
//ieee->sync_scan_hurryup = 1;
662
down(&ieee->scan_sem);
663
// spin_lock_irqsave(&ieee->lock, flags);
665
if (ieee->scanning == 1){
668
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
669
cancel_delayed_work(&ieee->softmac_scan_wq);
671
del_timer_sync(&ieee->scan_timer);
675
// spin_unlock_irqrestore(&ieee->lock, flags);
679
void ieee80211_stop_scan(struct ieee80211_device *ieee)
681
if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
682
ieee80211_softmac_stop_scan(ieee);
684
ieee->stop_scan(ieee->dev);
687
/* called with ieee->lock held */
688
void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
691
if(ieee->ieee80211_ips_leave_wq != NULL)
692
ieee->ieee80211_ips_leave_wq(ieee->dev);
696
if(IS_DOT11D_ENABLE(ieee) )
698
if(IS_COUNTRY_IE_VALID(ieee))
700
RESET_CIE_WATCHDOG(ieee);
704
if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
705
if (ieee->scanning == 0){
707
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
708
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
709
queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
712
queue_work(ieee->wq, &ieee->softmac_scan_wq);
715
ieee80211_softmac_scan(ieee);
719
ieee->start_scan(ieee->dev);
723
/* called with wx_sem held */
724
void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
727
if(IS_DOT11D_ENABLE(ieee) )
729
if(IS_COUNTRY_IE_VALID(ieee))
731
RESET_CIE_WATCHDOG(ieee);
735
ieee->sync_scan_hurryup = 0;
736
if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
737
ieee80211_softmac_scan_syncro(ieee);
739
ieee->scan_syncro(ieee->dev);
743
inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
744
struct ieee80211_device *ieee, int challengelen)
747
struct ieee80211_authentication *auth;
748
int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
751
skb = dev_alloc_skb(len);
752
if (!skb) return NULL;
754
skb_reserve(skb, ieee->tx_headroom);
755
auth = (struct ieee80211_authentication *)
756
skb_put(skb, sizeof(struct ieee80211_authentication));
758
auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
759
if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
761
auth->header.duration_id = 0x013a; //FIXME
763
memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
764
memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
765
memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
767
//auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
768
if(ieee->auth_mode == 0)
769
auth->algorithm = WLAN_AUTH_OPEN;
770
else if(ieee->auth_mode == 1)
771
auth->algorithm = WLAN_AUTH_SHARED_KEY;
772
else if(ieee->auth_mode == 2)
773
auth->algorithm = WLAN_AUTH_OPEN;//0x80;
774
printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
775
auth->transaction = cpu_to_le16(ieee->associate_seq);
776
ieee->associate_seq++;
778
auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
785
static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
789
struct ieee80211_probe_response *beacon_buf;
790
struct sk_buff *skb = NULL;
792
int atim_len,erp_len;
793
struct ieee80211_crypt_data* crypt;
795
char *ssid = ieee->current_network.ssid;
796
int ssid_len = ieee->current_network.ssid_len;
797
int rate_len = ieee->current_network.rates_len+2;
798
int rate_ex_len = ieee->current_network.rates_ex_len;
799
int wpa_ie_len = ieee->wpa_ie_len;
800
u8 erpinfo_content = 0;
805
u8 tmp_ht_info_len=0;
806
PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
807
u8* tmp_generic_ie_buf=NULL;
808
u8 tmp_generic_ie_len=0;
810
if(rate_ex_len > 0) rate_ex_len+=2;
812
if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
818
if(ieee80211_is_54g(ieee->current_network))
823
if((ieee->current_network.mode == IEEE_G)
824
||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
827
if(ieee->current_network.buseprotection)
828
erpinfo_content |= ERP_UseProtection;
835
crypt = ieee->crypt[ieee->tx_keyidx];
838
encrypt = ieee->host_encrypt && crypt && crypt->ops &&
839
((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
842
tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
843
tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
844
tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
845
tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
846
HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
847
HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
850
if(pHTInfo->bRegRT2RTAggregation)
852
tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
853
tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
854
HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
856
// 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);
858
beacon_size = sizeof(struct ieee80211_probe_response)+2+
868
// +tmp_generic_ie_len
871
skb = dev_alloc_skb(beacon_size);
874
skb_reserve(skb, ieee->tx_headroom);
875
beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
876
memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
877
memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
878
memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
880
beacon_buf->header.duration_id = 0; //FIXME
881
beacon_buf->beacon_interval =
882
cpu_to_le16(ieee->current_network.beacon_interval);
883
beacon_buf->capability =
884
cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
885
beacon_buf->capability |=
886
cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
888
if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
889
cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
891
crypt = ieee->crypt[ieee->tx_keyidx];
893
encrypt = ieee->host_encrypt && crypt && crypt->ops &&
894
(0 == strcmp(crypt->ops->name, "WEP"));
897
beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
900
beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
901
beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
902
beacon_buf->info_element[0].len = ssid_len;
904
tag = (u8*) beacon_buf->info_element[0].data;
906
memcpy(tag, ssid, ssid_len);
910
*(tag++) = MFIE_TYPE_RATES;
911
*(tag++) = rate_len-2;
912
memcpy(tag,ieee->current_network.rates,rate_len-2);
915
*(tag++) = MFIE_TYPE_DS_SET;
917
*(tag++) = ieee->current_network.channel;
921
*(tag++) = MFIE_TYPE_IBSS_SET;
923
//*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
924
val16 = cpu_to_le16(ieee->current_network.atim_window);
925
memcpy((u8 *)tag, (u8 *)&val16, 2);
930
*(tag++) = MFIE_TYPE_ERP;
932
*(tag++) = erpinfo_content;
935
//Include High Throuput capability
937
*(tag++) = MFIE_TYPE_HT_CAP;
938
*(tag++) = tmp_ht_cap_len - 2;
939
memcpy(tag, tmp_ht_cap_buf, tmp_ht_cap_len - 2);
940
tag += tmp_ht_cap_len - 2;
943
*(tag++) = MFIE_TYPE_RATES_EX;
944
*(tag++) = rate_ex_len-2;
945
memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
950
//Include High Throuput info
952
*(tag++) = MFIE_TYPE_HT_INFO;
953
*(tag++) = tmp_ht_info_len - 2;
954
memcpy(tag, tmp_ht_info_buf, tmp_ht_info_len -2);
955
tag += tmp_ht_info_len - 2;
959
if (ieee->iw_mode == IW_MODE_ADHOC)
960
{//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
961
memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
963
memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
969
// Construct Realtek Proprietary Aggregation mode (Set AMPDU Factor to 2, 32k)
971
if(pHTInfo->bRegRT2RTAggregation)
974
(*tag++) = tmp_generic_ie_len - 2;
975
memcpy(tag,tmp_generic_ie_buf,tmp_generic_ie_len -2);
976
tag += tmp_generic_ie_len -2;
981
if(ieee->qos_support)
985
memcpy(tag,QosOui,wmm_len);
989
//skb->dev = ieee->dev;
994
struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
999
struct ieee80211_crypt_data* crypt;
1000
struct ieee80211_assoc_response_frame *assoc;
1003
unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1004
int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
1006
skb = dev_alloc_skb(len);
1011
skb_reserve(skb, ieee->tx_headroom);
1013
assoc = (struct ieee80211_assoc_response_frame *)
1014
skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
1016
assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
1017
memcpy(assoc->header.addr1, dest,ETH_ALEN);
1018
memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1019
memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1020
assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
1021
WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
1024
if(ieee->short_slot)
1025
assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1027
if (ieee->host_encrypt)
1028
crypt = ieee->crypt[ieee->tx_keyidx];
1031
encrypt = ( crypt && crypt->ops);
1034
assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1037
assoc->aid = cpu_to_le16(ieee->assoc_id);
1038
if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
1039
else ieee->assoc_id++;
1041
tag = (u8*) skb_put(skb, rate_len);
1043
ieee80211_MFIE_Brate(ieee, &tag);
1044
ieee80211_MFIE_Grate(ieee, &tag);
1049
struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
1051
struct sk_buff *skb;
1052
struct ieee80211_authentication *auth;
1053
int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
1055
skb = dev_alloc_skb(len);
1060
skb->len = sizeof(struct ieee80211_authentication);
1062
auth = (struct ieee80211_authentication *)skb->data;
1064
auth->status = cpu_to_le16(status);
1065
auth->transaction = cpu_to_le16(2);
1066
auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
1068
memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
1069
memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1070
memcpy(auth->header.addr1, dest, ETH_ALEN);
1071
auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
1077
struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
1079
struct sk_buff *skb;
1080
struct ieee80211_hdr_3addr* hdr;
1082
skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
1087
hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
1089
memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
1090
memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
1091
memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
1093
hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
1094
IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1095
(pwr ? IEEE80211_FCTL_PM:0));
1102
struct sk_buff* ieee80211_pspoll_func(struct ieee80211_device *ieee)
1104
struct sk_buff *skb;
1105
struct ieee80211_pspoll_hdr* hdr;
1107
#ifdef USB_USE_ALIGNMENT
1110
skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr) + ieee->tx_headroom + USB_512B_ALIGNMENT_SIZE);
1112
skb = dev_alloc_skb(sizeof(struct ieee80211_pspoll_hdr)+ieee->tx_headroom);
1117
#ifdef USB_USE_ALIGNMENT
1118
Tmpaddr = (u32)skb->data;
1119
alignment = Tmpaddr & 0x1ff;
1120
skb_reserve(skb,(USB_512B_ALIGNMENT_SIZE - alignment));
1122
skb_reserve(skb, ieee->tx_headroom);
1124
hdr = (struct ieee80211_pspoll_hdr*)skb_put(skb,sizeof(struct ieee80211_pspoll_hdr));
1126
memcpy(hdr->bssid, ieee->current_network.bssid, ETH_ALEN);
1127
memcpy(hdr->ta, ieee->dev->dev_addr, ETH_ALEN);
1129
hdr->aid = cpu_to_le16(ieee->assoc_id | 0xc000);
1130
hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_CTL |IEEE80211_STYPE_PSPOLL | IEEE80211_FCTL_PM);
1137
void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1139
struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1142
softmac_mgmt_xmit(buf, ieee);
1146
void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1148
struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1151
softmac_mgmt_xmit(buf, ieee);
1155
void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1159
struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1161
softmac_mgmt_xmit(buf, ieee);
1165
inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1167
struct sk_buff *skb;
1168
//unsigned long flags;
1170
struct ieee80211_assoc_request_frame *hdr;
1172
//short info_addr = 0;
1174
//u16 suite_count = 0;
1175
//u8 suit_select = 0;
1176
//unsigned int wpa_len = beacon->wpa_ie_len;
1178
u8* ht_cap_buf = NULL;
1180
u8* realtek_ie_buf=NULL;
1181
u8 realtek_ie_len=0;
1182
int wpa_ie_len= ieee->wpa_ie_len;
1183
unsigned int ckip_ie_len=0;
1184
unsigned int ccxrm_ie_len=0;
1185
unsigned int cxvernum_ie_len=0;
1186
struct ieee80211_crypt_data* crypt;
1189
unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1190
unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1192
unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1197
crypt = ieee->crypt[ieee->tx_keyidx];
1198
encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1200
//Include High Throuput capability && Realtek proprietary
1201
if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1203
ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1204
ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1205
HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1206
if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1208
realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1209
realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1210
HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1214
if(ieee->qos_support){
1215
wmm_info_len = beacon->qos_data.supported?9:0;
1219
if(beacon->bCkipSupported)
1223
if(beacon->bCcxRmEnable)
1227
if( beacon->BssCcxVerNumber >= 2 )
1229
cxvernum_ie_len = 5+2;
1232
len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1233
+ beacon->ssid_len//essid tagged val
1234
+ rate_len//rates tagged val
1243
+ ieee->tx_headroom;
1245
len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1246
+ beacon->ssid_len//essid tagged val
1247
+ rate_len//rates tagged val
1255
+ ieee->tx_headroom;
1258
skb = dev_alloc_skb(len);
1263
skb_reserve(skb, ieee->tx_headroom);
1265
hdr = (struct ieee80211_assoc_request_frame *)
1266
skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1269
hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1270
hdr->header.duration_id= 37; //FIXME
1271
memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1272
memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1273
memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1275
memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1277
hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1278
if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1279
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1281
if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1282
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1284
if(ieee->short_slot)
1285
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1286
if (wmm_info_len) //QOS
1287
hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1289
hdr->listen_interval = 0xa; //FIXME
1291
hdr->info_element[0].id = MFIE_TYPE_SSID;
1293
hdr->info_element[0].len = beacon->ssid_len;
1294
tag = skb_put(skb, beacon->ssid_len);
1295
memcpy(tag, beacon->ssid, beacon->ssid_len);
1297
tag = skb_put(skb, rate_len);
1299
ieee80211_MFIE_Brate(ieee, &tag);
1300
ieee80211_MFIE_Grate(ieee, &tag);
1301
// For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1302
if( beacon->bCkipSupported )
1304
static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1305
u8 CcxAironetBuf[30];
1306
OCTET_STRING osCcxAironetIE;
1308
memset(CcxAironetBuf, 0,30);
1309
osCcxAironetIE.Octet = CcxAironetBuf;
1310
osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1312
// Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1313
// We want to make the device type as "4500-client". 060926, by CCW.
1315
memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1317
// CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1318
// "The CKIP negotiation is started with the associate request from the client to the access point,
1319
// containing an Aironet element with both the MIC and KP bits set."
1320
osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1321
tag = skb_put(skb, ckip_ie_len);
1322
*tag++ = MFIE_TYPE_AIRONET;
1323
*tag++ = osCcxAironetIE.Length;
1324
memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1325
tag += osCcxAironetIE.Length;
1328
if(beacon->bCcxRmEnable)
1330
static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1331
OCTET_STRING osCcxRmCap;
1333
osCcxRmCap.Octet = CcxRmCapBuf;
1334
osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1335
tag = skb_put(skb,ccxrm_ie_len);
1336
*tag++ = MFIE_TYPE_GENERIC;
1337
*tag++ = osCcxRmCap.Length;
1338
memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1339
tag += osCcxRmCap.Length;
1342
if( beacon->BssCcxVerNumber >= 2 )
1344
u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1345
OCTET_STRING osCcxVerNum;
1346
CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1347
osCcxVerNum.Octet = CcxVerNumBuf;
1348
osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1349
tag = skb_put(skb,cxvernum_ie_len);
1350
*tag++ = MFIE_TYPE_GENERIC;
1351
*tag++ = osCcxVerNum.Length;
1352
memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1353
tag += osCcxVerNum.Length;
1356
if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1357
if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1359
tag = skb_put(skb, ht_cap_len);
1360
*tag++ = MFIE_TYPE_HT_CAP;
1361
*tag++ = ht_cap_len - 2;
1362
memcpy(tag, ht_cap_buf,ht_cap_len -2);
1363
tag += ht_cap_len -2;
1368
//choose what wpa_supplicant gives to associate.
1369
tag = skb_put(skb, wpa_ie_len);
1371
memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1374
tag = skb_put(skb,wmm_info_len);
1376
ieee80211_WMM_Info(ieee, &tag);
1379
tag = skb_put(skb,turbo_info_len);
1380
if(turbo_info_len) {
1381
ieee80211_TURBO_Info(ieee, &tag);
1385
if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1386
if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1388
tag = skb_put(skb, ht_cap_len);
1389
*tag++ = MFIE_TYPE_GENERIC;
1390
*tag++ = ht_cap_len - 2;
1391
memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1392
tag += ht_cap_len -2;
1395
if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1396
tag = skb_put(skb, realtek_ie_len);
1397
*tag++ = MFIE_TYPE_GENERIC;
1398
*tag++ = realtek_ie_len - 2;
1399
memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1402
// printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1403
// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1407
void ieee80211_associate_abort(struct ieee80211_device *ieee)
1410
unsigned long flags;
1411
spin_lock_irqsave(&ieee->lock, flags);
1413
ieee->associate_seq++;
1415
/* don't scan, and avoid to have the RX path possibily
1416
* try again to associate. Even do not react to AUTH or
1417
* ASSOC response. Just wait for the retry wq to be scheduled.
1418
* Here we will check if there are good nets to associate
1419
* with, so we retry or just get back to NO_LINK and scanning
1421
if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1422
IEEE80211_DEBUG_MGMT("Authentication failed\n");
1423
ieee->softmac_stats.no_auth_rs++;
1425
IEEE80211_DEBUG_MGMT("Association failed\n");
1426
ieee->softmac_stats.no_ass_rs++;
1429
ieee->state = IEEE80211_ASSOCIATING_RETRY;
1431
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1432
queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1433
IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1435
schedule_task(&ieee->associate_retry_wq);
1438
spin_unlock_irqrestore(&ieee->lock, flags);
1441
void ieee80211_associate_abort_cb(unsigned long dev)
1443
ieee80211_associate_abort((struct ieee80211_device *) dev);
1447
void ieee80211_associate_step1(struct ieee80211_device *ieee)
1449
struct ieee80211_network *beacon = &ieee->current_network;
1450
struct sk_buff *skb;
1452
IEEE80211_DEBUG_MGMT("Stopping scan\n");
1454
ieee->softmac_stats.tx_auth_rq++;
1455
skb=ieee80211_authentication_req(beacon, ieee, 0);
1458
ieee80211_associate_abort(ieee);
1460
ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1461
IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1462
//printk(KERN_WARNING "Sending authentication request\n");
1463
softmac_mgmt_xmit(skb, ieee);
1464
//BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1465
if(!timer_pending(&ieee->associate_timer)){
1466
ieee->associate_timer.expires = jiffies + (HZ / 2);
1467
add_timer(&ieee->associate_timer);
1469
//dev_kfree_skb_any(skb);//edit by thomas
1473
void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1476
struct sk_buff *skb;
1477
struct ieee80211_network *beacon = &ieee->current_network;
1478
// int hlen = sizeof(struct ieee80211_authentication);
1480
ieee->associate_seq++;
1481
ieee->softmac_stats.tx_auth_rq++;
1483
skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1485
ieee80211_associate_abort(ieee);
1487
c = skb_put(skb, chlen+2);
1488
*(c++) = MFIE_TYPE_CHALLENGE;
1490
memcpy(c, challenge, chlen);
1492
IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1494
ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1496
softmac_mgmt_xmit(skb, ieee);
1497
mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1499
ieee->associate_timer.expires = jiffies + (HZ / 2);
1500
add_timer(&ieee->associate_timer);
1502
//dev_kfree_skb_any(skb);//edit by thomas
1507
void ieee80211_associate_step2(struct ieee80211_device *ieee)
1509
struct sk_buff* skb;
1510
struct ieee80211_network *beacon = &ieee->current_network;
1512
del_timer_sync(&ieee->associate_timer);
1514
IEEE80211_DEBUG_MGMT("Sending association request\n");
1516
ieee->softmac_stats.tx_ass_rq++;
1517
skb=ieee80211_association_req(beacon, ieee);
1519
ieee80211_associate_abort(ieee);
1521
softmac_mgmt_xmit(skb, ieee);
1522
mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1524
ieee->associate_timer.expires = jiffies + (HZ / 2);
1525
add_timer(&ieee->associate_timer);
1527
//dev_kfree_skb_any(skb);//edit by thomas
1530
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1531
void ieee80211_associate_complete_wq(struct work_struct *work)
1533
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1535
void ieee80211_associate_complete_wq(struct ieee80211_device *ieee)
1538
printk(KERN_INFO "Associated successfully\n");
1539
ieee->is_roaming = false;
1540
if(ieee80211_is_54g(ieee->current_network) &&
1541
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1544
printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1547
printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1549
if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1551
printk("Successfully associated, ht enabled\n");
1556
printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1557
memset(ieee->dot11HTOperationalRateSet, 0, 16);
1558
//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1560
ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1561
// To prevent the immediately calling watch_dog after association.
1562
if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1564
ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1565
ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1567
ieee->link_change(ieee->dev);
1568
if(ieee->is_silent_reset == 0){
1569
printk("============>normal associate\n");
1570
notify_wx_assoc_event(ieee);
1572
else if(ieee->is_silent_reset == 1)
1574
printk("==================>silent reset associate\n");
1575
ieee->is_silent_reset = 0;
1578
if (ieee->data_hard_resume)
1579
ieee->data_hard_resume(ieee->dev);
1580
netif_carrier_on(ieee->dev);
1583
void ieee80211_associate_complete(struct ieee80211_device *ieee)
1586
// struct net_device* dev = ieee->dev;
1587
del_timer_sync(&ieee->associate_timer);
1590
for(i = 0; i < 6; i++) {
1591
ieee->seq_ctrl[i] = 0;
1594
ieee->state = IEEE80211_LINKED;
1596
if (ieee->pHTInfo->bCurrentHTSupport)
1598
printk("Successfully associated, ht enabled\n");
1599
queue_work(ieee->wq, &ieee->ht_onAssRsp);
1603
printk("Successfully associated, ht not enabled\n");
1604
memset(ieee->dot11HTOperationalRateSet, 0, 16);
1605
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1608
//ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1609
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1610
queue_work(ieee->wq, &ieee->associate_complete_wq);
1612
schedule_task(&ieee->associate_complete_wq);
1616
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
1617
void ieee80211_associate_procedure_wq(struct work_struct *work)
1619
struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1621
void ieee80211_associate_procedure_wq(struct ieee80211_device *ieee)
1624
ieee->sync_scan_hurryup = 1;
1626
if(ieee->ieee80211_ips_leave != NULL)
1627
ieee->ieee80211_ips_leave(ieee->dev);
1630
down(&ieee->wx_sem);
1632
if (ieee->data_hard_stop)
1633
ieee->data_hard_stop(ieee->dev);
1635
ieee80211_stop_scan(ieee);
1636
printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1637
//ieee->set_chan(ieee->dev, ieee->current_network.channel);
1638
HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1641
if(ieee->eRFPowerState == eRfOff)
1643
if(ieee->ieee80211_ips_leave_wq != NULL)
1644
ieee->ieee80211_ips_leave_wq(ieee->dev);
1651
ieee->associate_seq = 1;
1652
ieee80211_associate_step1(ieee);
1657
inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1659
u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1660
int tmp_ssid_len = 0;
1662
short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1664
/* we are interested in new new only if we are not associated
1665
* and we are not associating / authenticating
1667
if (ieee->state != IEEE80211_NOLINK)
1670
if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1673
if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1677
if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1678
/* if the user specified the AP MAC, we need also the essid
1679
* This could be obtained by beacons or, if the network does not
1680
* broadcast it, it can be put manually.
1682
apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1683
ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1684
ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1685
apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1686
ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1687
(!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1690
if ( /* if the user set the AP check if match.
1691
* if the network does not broadcast essid we check the user supplyed ANY essid
1692
* if the network does broadcast and the user does not set essid it is OK
1693
* if the network does broadcast and the user did set essid chech if essid match
1695
( apset && apmatch &&
1696
((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1697
/* if the ap is not set, check that the user set the bssid
1698
* and the network does bradcast and that those two bssid matches
1700
(!apset && ssidset && ssidbroad && ssidmatch)
1702
/* if the essid is hidden replace it with the
1703
* essid provided by the user.
1706
strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1707
tmp_ssid_len = ieee->current_network.ssid_len;
1709
memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1712
strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1713
ieee->current_network.ssid_len = tmp_ssid_len;
1715
printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1717
//ieee->pHTInfo->IOTAction = 0;
1718
HTResetIOTSetting(ieee->pHTInfo);
1719
if (ieee->iw_mode == IW_MODE_INFRA){
1720
/* Join the network for the first time */
1721
ieee->AsocRetryCount = 0;
1722
//for HT by amy 080514
1723
if((ieee->current_network.qos_data.supported == 1) &&
1724
// (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1725
ieee->current_network.bssht.bdSupportHT)
1726
/*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.*/
1728
// ieee->pHTInfo->bCurrentHTSupport = true;
1729
HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1733
ieee->pHTInfo->bCurrentHTSupport = false;
1736
ieee->state = IEEE80211_ASSOCIATING;
1737
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
1738
queue_work(ieee->wq, &ieee->associate_procedure_wq);
1740
schedule_task(&ieee->associate_procedure_wq);
1743
if(ieee80211_is_54g(ieee->current_network) &&
1744
(ieee->modulation & IEEE80211_OFDM_MODULATION)){
1746
ieee->SetWirelessMode(ieee->dev, IEEE_G);
1747
printk(KERN_INFO"Using G rates\n");
1750
ieee->SetWirelessMode(ieee->dev, IEEE_B);
1751
printk(KERN_INFO"Using B rates\n");
1753
memset(ieee->dot11HTOperationalRateSet, 0, 16);
1754
//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1755
ieee->state = IEEE80211_LINKED;
1763
void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1765
unsigned long flags;
1766
struct ieee80211_network *target;
1768
spin_lock_irqsave(&ieee->lock, flags);
1770
list_for_each_entry(target, &ieee->network_list, list) {
1772
/* if the state become different that NOLINK means
1773
* we had found what we are searching for
1776
if (ieee->state != IEEE80211_NOLINK)
1779
if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1780
ieee80211_softmac_new_net(ieee, target);
1783
spin_unlock_irqrestore(&ieee->lock, flags);
1788
static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1790
struct ieee80211_authentication *a;
1792
if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1793
IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1797
a = (struct ieee80211_authentication*) skb->data;
1798
if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1799
t = skb->data + sizeof(struct ieee80211_authentication);
1801
if(*(t++) == MFIE_TYPE_CHALLENGE){
1803
*challenge = kmalloc(*chlen, GFP_ATOMIC);
1804
memcpy(*challenge, t, *chlen);
1808
return cpu_to_le16(a->status);
1813
int auth_rq_parse(struct sk_buff *skb,u8* dest)
1815
struct ieee80211_authentication *a;
1817
if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1818
IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1821
a = (struct ieee80211_authentication*) skb->data;
1823
memcpy(dest,a->header.addr2, ETH_ALEN);
1825
if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1826
return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1828
return WLAN_STATUS_SUCCESS;
1831
static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1838
struct ieee80211_hdr_3addr *header =
1839
(struct ieee80211_hdr_3addr *) skb->data;
1841
if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1842
return -1; /* corrupted */
1844
memcpy(src,header->addr2, ETH_ALEN);
1846
skbend = (u8*)skb->data + skb->len;
1848
tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1850
while (tag+1 < skbend){
1856
tag++; /* point to the len field */
1857
tag = tag + *(tag); /* point to the last data byte of the tag */
1858
tag++; /* point to the next tag */
1861
//IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1862
if (ssidlen == 0) return 1;
1864
if (!ssid) return 1; /* ssid not found in tagged param */
1865
return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1869
int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1871
struct ieee80211_assoc_request_frame *a;
1873
if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1874
sizeof(struct ieee80211_info_element))) {
1876
IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1880
a = (struct ieee80211_assoc_request_frame*) skb->data;
1882
memcpy(dest,a->header.addr2,ETH_ALEN);
1887
static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1889
struct ieee80211_assoc_response_frame *response_head;
1892
if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1893
IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1897
response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1898
*aid = le16_to_cpu(response_head->aid) & 0x3fff;
1900
status_code = le16_to_cpu(response_head->status);
1901
if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1902
status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1903
((ieee->mode == IEEE_G) &&
1904
(ieee->current_network.mode == IEEE_N_24G) &&
1905
(ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1906
ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1908
ieee->AsocRetryCount = 0;
1911
return le16_to_cpu(response_head->status);
1915
ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1919
//IEEE80211DMESG("Rx probe");
1920
ieee->softmac_stats.rx_probe_rq++;
1921
//DMESG("Dest is "MACSTR, MAC2STR(dest));
1922
if (probe_rq_parse(ieee, skb, dest)){
1923
//IEEE80211DMESG("Was for me!");
1924
ieee->softmac_stats.tx_probe_rs++;
1925
ieee80211_resp_to_probe(ieee, dest);
1930
ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1934
//IEEE80211DMESG("Rx probe");
1935
ieee->softmac_stats.rx_auth_rq++;
1937
status = auth_rq_parse(skb, dest);
1939
ieee80211_resp_to_auth(ieee, status, dest);
1941
//DMESG("Dest is "MACSTR, MAC2STR(dest));
1946
ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1950
//unsigned long flags;
1952
ieee->softmac_stats.rx_ass_rq++;
1953
if (assoc_rq_parse(skb,dest) != -1){
1954
ieee80211_resp_to_assoc_rq(ieee, dest);
1957
printk(KERN_INFO"New client associated: %pM\n", dest);
1960
spin_lock_irqsave(&ieee->lock,flags);
1961
add_associate(ieee,dest);
1962
spin_unlock_irqrestore(&ieee->lock,flags);
1968
void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1971
struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1974
softmac_ps_mgmt_xmit(buf, ieee);
1978
void ieee80211_sta_ps_send_pspoll_frame(struct ieee80211_device *ieee)
1981
struct sk_buff *buf = ieee80211_pspoll_func(ieee);
1984
softmac_ps_mgmt_xmit(buf, ieee);
1988
short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1990
int timeout = ieee->ps_timeout;
1992
PRT_POWER_SAVE_CONTROL pPSC = (PRT_POWER_SAVE_CONTROL)(&(ieee->PowerSaveControl));
1994
if(ieee->LPSDelayCnt)
1996
//printk("===============>Delay enter LPS for DHCP and ARP packets...\n");
1997
ieee->LPSDelayCnt --;
2001
dtim = ieee->current_network.dtim_data;
2002
// printk("%s():DTIM:%d\n",__FUNCTION__,dtim);
2003
if(!(dtim & IEEE80211_DTIM_VALID))
2005
timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
2006
//printk("VALID\n");
2007
ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
2008
/* there's no need to nofity AP that I find you buffered with broadcast packet */
2009
if(dtim & (IEEE80211_DTIM_UCAST & ieee->ps))
2012
if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout))){
2013
// printk("%s():111Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2016
if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout))){
2017
// printk("%s():222Oh Oh ,it is not time out return 0\n",__FUNCTION__);
2020
if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
2021
(ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
2025
if(ieee->bAwakePktSent == true) {
2026
pPSC->LPSAwakeIntvl = 1;//tx wake one beacon
2030
if(pPSC->LPSAwakeIntvl == 0)
2031
pPSC->LPSAwakeIntvl = 1;
2032
//pNdisCommon->RegLPSMaxIntvl /// 0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl
2033
if(pPSC->RegMaxLPSAwakeIntvl == 0) // Default (0x0 - eFastPs, 0xFF -DTIM, 0xNN - 0xNN * BeaconIntvl)
2034
MaxPeriod = 1; // 1 Beacon interval
2035
else if(pPSC->RegMaxLPSAwakeIntvl == 0xFF) // DTIM
2036
MaxPeriod = ieee->current_network.dtim_period;
2038
MaxPeriod = pPSC->RegMaxLPSAwakeIntvl;
2039
pPSC->LPSAwakeIntvl = (pPSC->LPSAwakeIntvl >= MaxPeriod) ? MaxPeriod : (pPSC->LPSAwakeIntvl + 1);
2042
u8 LPSAwakeIntvl_tmp = 0;
2043
u8 period = ieee->current_network.dtim_period;
2044
u8 count = ieee->current_network.tim.tim_count;
2046
if(pPSC->LPSAwakeIntvl > period)
2047
LPSAwakeIntvl_tmp = period + (pPSC->LPSAwakeIntvl - period) -((pPSC->LPSAwakeIntvl-period)%period);
2049
LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;
2052
if(pPSC->LPSAwakeIntvl > ieee->current_network.tim.tim_count)
2053
LPSAwakeIntvl_tmp = count + (pPSC->LPSAwakeIntvl - count) -((pPSC->LPSAwakeIntvl-count)%period);
2055
LPSAwakeIntvl_tmp = pPSC->LPSAwakeIntvl;//ieee->current_network.tim.tim_count;//pPSC->LPSAwakeIntvl;
2057
//printk("=========>%s()assoc_id:%d(%#x),bAwakePktSent:%d,DTIM:%d, sleep interval:%d, LPSAwakeIntvl_tmp:%d, count:%d\n",__func__,ieee->assoc_id,cpu_to_le16(ieee->assoc_id),ieee->bAwakePktSent,ieee->current_network.dtim_period,pPSC->LPSAwakeIntvl,LPSAwakeIntvl_tmp,count);
2059
*time_l = ieee->current_network.last_dtim_sta_time[0]
2060
+ MSECS(ieee->current_network.beacon_interval * LPSAwakeIntvl_tmp);
2061
// * ieee->current_network.dtim_period) * 1000;
2066
*time_h = ieee->current_network.last_dtim_sta_time[1];
2067
if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
2076
inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
2082
unsigned long flags,flags2;
2084
spin_lock_irqsave(&ieee->lock, flags);
2086
if((ieee->ps == IEEE80211_PS_DISABLED ||
2087
ieee->iw_mode != IW_MODE_INFRA ||
2088
ieee->state != IEEE80211_LINKED)){
2090
// #warning CHECK_LOCK_HERE
2091
printk("=====>%s(): no need to ps,wake up!! ieee->ps is %d,ieee->iw_mode is %d,ieee->state is %d\n",
2092
__FUNCTION__,ieee->ps,ieee->iw_mode,ieee->state);
2093
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2095
ieee80211_sta_wakeup(ieee, 1);
2097
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2100
sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
2101
/* 2 wake, 1 sleep, 0 do nothing */
2102
if(sleep == 0)//it is not time out or dtim is not valid
2104
//printk("===========>sleep is 0,do nothing\n");
2108
//printk("===========>sleep is 1,to sleep\n");
2109
if(ieee->sta_sleep == 1){
2110
//printk("%s(1): sta_sleep = 1, sleep again ++++++++++ \n", __func__);
2111
ieee->enter_sleep_state(ieee->dev,th,tl);
2114
else if(ieee->sta_sleep == 0){
2115
// printk("send null 1\n");
2116
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2118
if(ieee->ps_is_queue_empty(ieee->dev)){
2119
ieee->sta_sleep = 2;
2120
ieee->ack_tx_to_ieee = 1;
2121
//printk("%s(2): sta_sleep = 0, notify AP we will sleeped ++++++++++ SendNullFunctionData\n", __func__);
2122
ieee80211_sta_ps_send_null_frame(ieee,1);
2126
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2130
ieee->bAwakePktSent = false;//after null to power save we set it to false. not listen every beacon.
2132
}else if(sleep == 2){
2133
//printk("==========>sleep is 2,to wakeup\n");
2134
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2136
//printk("%s(3): pkt buffered in ap will awake ++++++++++ ieee80211_sta_wakeup\n", __func__);
2137
ieee80211_sta_wakeup(ieee,1);
2139
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2143
spin_unlock_irqrestore(&ieee->lock, flags);
2147
void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
2149
if(ieee->sta_sleep == 0){
2151
if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2153
//printk("%s(1): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2154
//printk("Warning: driver is probably failing to report TX ps error\n");
2155
ieee->ack_tx_to_ieee = 1;
2156
ieee80211_sta_ps_send_null_frame(ieee, 0);
2160
ieee->ack_tx_to_ieee = 1;
2161
//printk("%s(2): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2162
ieee80211_sta_ps_send_pspoll_frame(ieee);
2169
if(ieee->sta_sleep == 1)
2170
ieee->sta_wake_up(ieee->dev);
2173
if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2175
//printk("%s(3): notify AP we are awaked ++++++++++ SendNullFunctionData\n", __func__);
2176
//printk("Warning: driver is probably failing to report TX ps error\n");
2177
ieee->ack_tx_to_ieee = 1;
2178
ieee80211_sta_ps_send_null_frame(ieee, 0);
2182
ieee->ack_tx_to_ieee = 1;
2183
ieee->polling = true;
2184
//printk("%s(4): notify AP we are awaked ++++++++++ Send PS-Poll\n", __func__);
2185
//ieee80211_sta_ps_send_null_frame(ieee, 0);
2186
ieee80211_sta_ps_send_pspoll_frame(ieee);
2190
ieee->sta_sleep = 0;
2191
ieee->polling = false;
2195
void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
2197
unsigned long flags,flags2;
2199
spin_lock_irqsave(&ieee->lock, flags);
2201
if(ieee->sta_sleep == 2){
2202
/* Null frame with PS bit set */
2204
ieee->sta_sleep = 1;
2205
//printk("notify AP we will sleep and send null ok, so sleep now++++++++++ enter_sleep_state\n");
2206
ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
2208
} else {/* 21112005 - tx again null without PS bit if lost */
2210
if((ieee->sta_sleep == 0) && !success){
2211
spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
2212
//ieee80211_sta_ps_send_null_frame(ieee, 0);
2213
if(ieee->pHTInfo->IOTAction & HT_IOT_ACT_NULL_DATA_POWER_SAVING)
2215
//printk("notify AP we will sleep but send bull failed, so resend++++++++++ SendNullFunctionData\n");
2216
ieee80211_sta_ps_send_null_frame(ieee, 0);
2220
//printk("notify AP we are awaked but send pspoll failed, so resend++++++++++ Send PS-Poll\n");
2221
ieee80211_sta_ps_send_pspoll_frame(ieee);
2223
spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
2226
spin_unlock_irqrestore(&ieee->lock, flags);
2229
void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
2231
struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
2232
u8* act = ieee80211_get_payload(header);
2234
// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
2237
IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
2245
if (*act == ACT_ADDBAREQ)
2246
ieee80211_rx_ADDBAReq(ieee, skb);
2247
else if (*act == ACT_ADDBARSP)
2248
ieee80211_rx_ADDBARsp(ieee, skb);
2249
else if (*act == ACT_DELBA)
2250
ieee80211_rx_DELBA(ieee, skb);
2253
// if (net_ratelimit())
2254
// IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
2261
ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
2262
struct ieee80211_rx_stats *rx_stats, u16 type,
2265
struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2270
struct ieee80211_assoc_response_frame *assoc_resp;
2271
// struct ieee80211_info_element *info_element;
2272
bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2274
if(!ieee->proto_started)
2277
printk("%d, %d, %d, %d\n", ieee->sta_sleep, ieee->ps, ieee->iw_mode, ieee->state);
2278
if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
2279
ieee->iw_mode == IW_MODE_INFRA &&
2280
ieee->state == IEEE80211_LINKED))
2282
tasklet_schedule(&ieee->ps_task);
2284
if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2285
WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2286
ieee->last_rx_ps_time = jiffies;
2289
switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2291
case IEEE80211_STYPE_ASSOC_RESP:
2292
case IEEE80211_STYPE_REASSOC_RESP:
2294
IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2295
WLAN_FC_GET_STYPE(header->frame_ctl));
2296
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2297
ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2298
ieee->iw_mode == IW_MODE_INFRA){
2299
struct ieee80211_network network_resp;
2300
struct ieee80211_network *network = &network_resp;
2302
if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2303
ieee->state=IEEE80211_LINKED;
2304
ieee->assoc_id = aid;
2305
ieee->softmac_stats.rx_ass_ok++;
2306
/* station support qos */
2307
/* Let the register setting defaultly with Legacy station */
2308
if(ieee->qos_support) {
2309
assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2310
memset(network, 0, sizeof(*network));
2311
if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2312
rx_stats->len - sizeof(*assoc_resp),\
2317
{ //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2318
memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2319
memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2321
if (ieee->handle_assoc_response != NULL)
2322
ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2324
ieee80211_associate_complete(ieee);
2326
/* aid could not been allocated */
2327
ieee->softmac_stats.rx_ass_err++;
2329
"Association response status code 0x%x\n",
2331
IEEE80211_DEBUG_MGMT(
2332
"Association response status code 0x%x\n",
2334
if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2335
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2336
queue_work(ieee->wq, &ieee->associate_procedure_wq);
2338
schedule_task(&ieee->associate_procedure_wq);
2341
ieee80211_associate_abort(ieee);
2347
case IEEE80211_STYPE_ASSOC_REQ:
2348
case IEEE80211_STYPE_REASSOC_REQ:
2350
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2351
ieee->iw_mode == IW_MODE_MASTER)
2353
ieee80211_rx_assoc_rq(ieee, skb);
2356
case IEEE80211_STYPE_AUTH:
2358
if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2359
if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2360
ieee->iw_mode == IW_MODE_INFRA){
2362
IEEE80211_DEBUG_MGMT("Received authentication response");
2364
if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2365
if(ieee->open_wep || !challenge){
2366
ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2367
ieee->softmac_stats.rx_auth_rs_ok++;
2368
if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2370
if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2372
// WEP or TKIP encryption
2373
if(IsHTHalfNmodeAPs(ieee))
2375
bSupportNmode = true;
2376
bHalfSupportNmode = true;
2380
bSupportNmode = false;
2381
bHalfSupportNmode = false;
2383
printk("==========>to link with AP using SEC(%d, %d)\n", bSupportNmode, bHalfSupportNmode);
2386
/* Dummy wirless mode setting to avoid encryption issue */
2389
ieee->SetWirelessMode(ieee->dev, \
2390
ieee->current_network.mode);
2394
ieee->SetWirelessMode(ieee->dev, IEEE_G);
2397
if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2399
printk("===============>entern half N mode\n");
2400
ieee->bHalfWirelessN24GMode = true;
2403
ieee->bHalfWirelessN24GMode = false;
2405
ieee80211_associate_step2(ieee);
2407
ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2410
ieee->softmac_stats.rx_auth_rs_err++;
2411
IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2413
printk("Authentication respose status code 0x%x",errcode);
2414
ieee80211_associate_abort(ieee);
2417
}else if (ieee->iw_mode == IW_MODE_MASTER){
2418
ieee80211_rx_auth_rq(ieee, skb);
2423
case IEEE80211_STYPE_PROBE_REQ:
2425
if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2426
((ieee->iw_mode == IW_MODE_ADHOC ||
2427
ieee->iw_mode == IW_MODE_MASTER) &&
2428
ieee->state == IEEE80211_LINKED)){
2429
ieee80211_rx_probe_rq(ieee, skb);
2433
case IEEE80211_STYPE_DISASSOC:
2434
case IEEE80211_STYPE_DEAUTH:
2435
/* FIXME for now repeat all the association procedure
2436
* both for disassociation and deauthentication
2438
if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2439
ieee->state == IEEE80211_LINKED &&
2440
ieee->iw_mode == IW_MODE_INFRA){
2442
ieee->state = IEEE80211_ASSOCIATING;
2443
ieee->softmac_stats.reassoc++;
2444
ieee->is_roaming = true;
2445
ieee80211_disassociate(ieee);
2446
// notify_wx_assoc_event(ieee);
2447
//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2448
RemovePeerTS(ieee, header->addr2);
2449
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2450
queue_work(ieee->wq, &ieee->associate_procedure_wq);
2452
schedule_task(&ieee->associate_procedure_wq);
2456
case IEEE80211_STYPE_MANAGE_ACT:
2457
ieee80211_process_action(ieee,skb);
2464
//dev_kfree_skb_any(skb);
2468
/* following are for a simplier TX queue management.
2469
* Instead of using netif_[stop/wake]_queue the driver
2470
* will uses these two function (plus a reset one), that
2471
* will internally uses the kernel netif_* and takes
2472
* care of the ieee802.11 fragmentation.
2473
* So the driver receives a fragment per time and might
2474
* call the stop function when it want without take care
2475
* to have enough room to TX an entire packet.
2476
* This might be useful if each fragment need it's own
2477
* descriptor, thus just keep a total free memory > than
2478
* the max fragmentation threshold is not enough.. If the
2479
* ieee802.11 stack passed a TXB struct then you needed
2480
* to keep N free descriptors where
2481
* N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2482
* In this way you need just one and the 802.11 stack
2483
* will take care of buffering fragments and pass them to
2484
* to the driver later, when it wakes the queue.
2486
void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2489
unsigned int queue_index = txb->queue_index;
2490
unsigned long flags;
2492
cb_desc *tcb_desc = NULL;
2494
spin_lock_irqsave(&ieee->lock,flags);
2496
/* called with 2nd parm 0, no tx mgmt lock required */
2497
ieee80211_sta_wakeup(ieee,0);
2499
/* update the tx status */
2500
// ieee->stats.tx_bytes += txb->payload_size;
2501
// ieee->stats.tx_packets++;
2502
tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2503
if(tcb_desc->bMulticast) {
2504
ieee->stats.multicast++;
2507
/* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2508
for(i = 0; i < txb->nr_frags; i++) {
2509
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2510
if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2512
if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2514
(!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2515
(ieee->queue_stop)) {
2516
/* insert the skb packet to the wait queue */
2517
/* as for the completion function, it does not need
2518
* to check it any more.
2520
//printk("error:no descriptor left@queue_index %d\n", queue_index);
2521
//ieee80211_rtl_stop_queue(ieee);
2522
#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2523
skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2525
skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2528
ieee->softmac_data_hard_start_xmit(
2530
ieee->dev,ieee->rate);
2531
//ieee->stats.tx_packets++;
2532
//ieee->stats.tx_bytes += txb->fragments[i]->len;
2533
//ieee->dev->trans_start = jiffies;
2537
ieee80211_txb_free(txb);
2540
spin_unlock_irqrestore(&ieee->lock,flags);
2544
/* called with ieee->lock acquired */
2545
void ieee80211_resume_tx(struct ieee80211_device *ieee)
2548
for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2550
if (ieee->queue_stop){
2551
ieee->tx_pending.frag = i;
2555
ieee->softmac_data_hard_start_xmit(
2556
ieee->tx_pending.txb->fragments[i],
2557
ieee->dev,ieee->rate);
2558
//(i+1)<ieee->tx_pending.txb->nr_frags);
2559
ieee->stats.tx_packets++;
2560
// ieee->dev->trans_start = jiffies;
2565
ieee80211_txb_free(ieee->tx_pending.txb);
2566
ieee->tx_pending.txb = NULL;
2570
void ieee80211_reset_queue(struct ieee80211_device *ieee)
2572
unsigned long flags;
2574
spin_lock_irqsave(&ieee->lock,flags);
2575
init_mgmt_queue(ieee);
2576
if (ieee->tx_pending.txb){
2577
ieee80211_txb_free(ieee->tx_pending.txb);
2578
ieee->tx_pending.txb = NULL;
2580
ieee->queue_stop = 0;
2581
spin_unlock_irqrestore(&ieee->lock,flags);
2585
void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2588
unsigned long flags;
2589
struct sk_buff *skb;
2590
struct ieee80211_hdr_3addr *header;
2592
spin_lock_irqsave(&ieee->lock,flags);
2593
if (! ieee->queue_stop) goto exit;
2595
ieee->queue_stop = 0;
2597
if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2598
while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2600
header = (struct ieee80211_hdr_3addr *) skb->data;
2602
header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2604
if (ieee->seq_ctrl[0] == 0xFFF)
2605
ieee->seq_ctrl[0] = 0;
2607
ieee->seq_ctrl[0]++;
2609
ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2610
//dev_kfree_skb_any(skb);//edit by thomas
2613
if (!ieee->queue_stop && ieee->tx_pending.txb)
2614
ieee80211_resume_tx(ieee);
2616
if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2617
ieee->softmac_stats.swtxawake++;
2618
netif_wake_queue(ieee->dev);
2622
spin_unlock_irqrestore(&ieee->lock,flags);
2626
void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2628
//unsigned long flags;
2629
//spin_lock_irqsave(&ieee->lock,flags);
2631
if (! netif_queue_stopped(ieee->dev)){
2632
netif_stop_queue(ieee->dev);
2633
ieee->softmac_stats.swtxstop++;
2635
ieee->queue_stop = 1;
2636
//spin_unlock_irqrestore(&ieee->lock,flags);
2641
inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2644
get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2646
/* an IBSS cell address must have the two less significant
2647
* bits of the first byte = 2
2649
ieee->current_network.bssid[0] &= ~0x01;
2650
ieee->current_network.bssid[0] |= 0x02;
2653
/* called in user context only */
2654
void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2658
if (ieee->current_network.ssid_len == 0){
2659
strncpy(ieee->current_network.ssid,
2660
IEEE80211_DEFAULT_TX_ESSID,
2663
ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2667
memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2669
ieee->set_chan(ieee->dev, ieee->current_network.channel);
2670
ieee->state = IEEE80211_LINKED;
2671
ieee->link_change(ieee->dev);
2672
notify_wx_assoc_event(ieee);
2674
if (ieee->data_hard_resume)
2675
ieee->data_hard_resume(ieee->dev);
2677
netif_carrier_on(ieee->dev);
2680
void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2684
if (ieee->data_hard_resume)
2685
ieee->data_hard_resume(ieee->dev);
2687
netif_carrier_on(ieee->dev);
2690
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2691
void ieee80211_start_ibss_wq(struct work_struct *work)
2694
struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2695
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2697
void ieee80211_start_ibss_wq(struct ieee80211_device *ieee)
2700
/* iwconfig mode ad-hoc will schedule this and return
2701
* on the other hand this will block further iwconfig SET
2702
* operations because of the wx_sem hold.
2703
* Anyway some most set operations set a flag to speed-up
2704
* (abort) this wq (when syncro scanning) before sleeping
2707
if(!ieee->proto_started){
2708
printk("==========oh driver down return\n");
2711
down(&ieee->wx_sem);
2713
if (ieee->current_network.ssid_len == 0){
2714
strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2715
ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2719
ieee->state = IEEE80211_NOLINK;
2720
/* check if we have this cell in our network list */
2721
ieee80211_softmac_check_all_nets(ieee);
2724
#ifdef ENABLE_DOT11D //if creating an ad-hoc, set its channel to 10 temporarily--this is the requirement for ASUS, not 11D, so disable 11d.
2725
// if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2726
if (ieee->state == IEEE80211_NOLINK)
2727
ieee->current_network.channel = 6;
2729
/* if not then the state is not linked. Maybe the user swithced to
2730
* ad-hoc mode just after being in monitor mode, or just after
2731
* being very few time in managed mode (so the card have had no
2732
* time to scan all the chans..) or we have just run up the iface
2733
* after setting ad-hoc mode. So we have to give another try..
2734
* Here, in ibss mode, should be safe to do this without extra care
2735
* (in bss mode we had to make sure no-one tryed to associate when
2736
* we had just checked the ieee->state and we was going to start the
2737
* scan) beacause in ibss mode the ieee80211_new_net function, when
2738
* finds a good net, just set the ieee->state to IEEE80211_LINKED,
2739
* so, at worst, we waste a bit of time to initiate an unneeded syncro
2740
* scan, that will stop at the first round because it sees the state
2743
if (ieee->state == IEEE80211_NOLINK)
2744
ieee80211_start_scan_syncro(ieee);
2746
/* the network definitively is not here.. create a new cell */
2747
if (ieee->state == IEEE80211_NOLINK){
2748
printk("creating new IBSS cell\n");
2750
ieee80211_randomize_cell(ieee);
2752
if(ieee->modulation & IEEE80211_CCK_MODULATION){
2754
ieee->current_network.rates_len = 4;
2756
ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2757
ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2758
ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2759
ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2762
ieee->current_network.rates_len = 0;
2764
if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2765
ieee->current_network.rates_ex_len = 8;
2767
ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2768
ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2769
ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2770
ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2771
ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2772
ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2773
ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2774
ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2778
ieee->current_network.rates_ex_len = 0;
2782
// By default, WMM function will be disabled in IBSS mode
2783
ieee->current_network.QoS_Enable = 0;
2784
ieee->SetWirelessMode(ieee->dev, IEEE_G);
2785
ieee->current_network.atim_window = 0;
2786
ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2787
if(ieee->short_slot)
2788
ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2792
ieee->state = IEEE80211_LINKED;
2794
ieee->set_chan(ieee->dev, ieee->current_network.channel);
2795
ieee->link_change(ieee->dev);
2797
notify_wx_assoc_event(ieee);
2799
ieee80211_start_send_beacons(ieee);
2801
if (ieee->data_hard_resume)
2802
ieee->data_hard_resume(ieee->dev);
2803
netif_carrier_on(ieee->dev);
2808
inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2810
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2811
queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2813
schedule_task(&ieee->start_ibss_wq);
2817
/* this is called only in user context, with wx_sem held */
2818
void ieee80211_start_bss(struct ieee80211_device *ieee)
2820
unsigned long flags;
2821
#ifdef ENABLE_DOT11D
2823
// Ref: 802.11d 11.1.3.3
2824
// STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2826
if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2828
if(! ieee->bGlobalDomain)
2834
/* check if we have already found the net we
2835
* are interested in (if any).
2836
* if not (we are disassociated and we are not
2837
* in associating / authenticating phase) start the background scanning.
2839
ieee80211_softmac_check_all_nets(ieee);
2841
/* ensure no-one start an associating process (thus setting
2842
* the ieee->state to ieee80211_ASSOCIATING) while we
2843
* have just cheked it and we are going to enable scan.
2844
* The ieee80211_new_net function is always called with
2845
* lock held (from both ieee80211_softmac_check_all_nets and
2846
* the rx path), so we cannot be in the middle of such function
2848
spin_lock_irqsave(&ieee->lock, flags);
2850
if (ieee->state == IEEE80211_NOLINK){
2852
if(ieee->ieee80211_ips_leave_wq != NULL)
2853
ieee->ieee80211_ips_leave_wq(ieee->dev);
2855
ieee->actscanning = true;
2856
ieee80211_rtl_start_scan(ieee);
2858
spin_unlock_irqrestore(&ieee->lock, flags);
2861
/* called only in userspace context */
2862
void ieee80211_disassociate(struct ieee80211_device *ieee)
2866
netif_carrier_off(ieee->dev);
2867
if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2868
ieee80211_reset_queue(ieee);
2870
if (ieee->data_hard_stop)
2871
ieee->data_hard_stop(ieee->dev);
2872
#ifdef ENABLE_DOT11D
2873
if(IS_DOT11D_ENABLE(ieee))
2876
ieee->state = IEEE80211_NOLINK;
2877
ieee->is_set_key = false;
2878
ieee->link_change(ieee->dev);
2879
//HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2880
notify_wx_assoc_event(ieee);
2883
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20))
2884
void ieee80211_associate_retry_wq(struct work_struct *work)
2886
struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2887
struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2889
void ieee80211_associate_retry_wq(struct ieee80211_device *ieee)
2892
unsigned long flags;
2894
down(&ieee->wx_sem);
2895
if(!ieee->proto_started)
2898
if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2901
/* until we do not set the state to IEEE80211_NOLINK
2902
* there are no possibility to have someone else trying
2903
* to start an association procdure (we get here with
2904
* ieee->state = IEEE80211_ASSOCIATING).
2905
* When we set the state to IEEE80211_NOLINK it is possible
2906
* that the RX path run an attempt to associate, but
2907
* both ieee80211_softmac_check_all_nets and the
2908
* RX path works with ieee->lock held so there are no
2909
* problems. If we are still disassociated then start a scan.
2910
* the lock here is necessary to ensure no one try to start
2911
* an association procedure when we have just checked the
2912
* state and we are going to start the scan.
2914
ieee->beinretry = true;
2915
ieee->state = IEEE80211_NOLINK;
2917
ieee80211_softmac_check_all_nets(ieee);
2919
spin_lock_irqsave(&ieee->lock, flags);
2921
if(ieee->state == IEEE80211_NOLINK)
2923
ieee->is_roaming= false;
2924
ieee->actscanning = true;
2925
ieee80211_rtl_start_scan(ieee);
2927
spin_unlock_irqrestore(&ieee->lock, flags);
2929
ieee->beinretry = false;
2934
struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2936
u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2938
struct sk_buff *skb;
2939
struct ieee80211_probe_response *b;
2941
skb = ieee80211_probe_resp(ieee, broadcast_addr);
2946
b = (struct ieee80211_probe_response *) skb->data;
2947
b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2953
struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2955
struct sk_buff *skb;
2956
struct ieee80211_probe_response *b;
2958
skb = ieee80211_get_beacon_(ieee);
2962
b = (struct ieee80211_probe_response *) skb->data;
2963
b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2965
if (ieee->seq_ctrl[0] == 0xFFF)
2966
ieee->seq_ctrl[0] = 0;
2968
ieee->seq_ctrl[0]++;
2973
void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2975
ieee->sync_scan_hurryup = 1;
2976
down(&ieee->wx_sem);
2977
ieee80211_stop_protocol(ieee, shutdown);
2982
void ieee80211_stop_protocol(struct ieee80211_device *ieee, u8 shutdown)
2984
if (!ieee->proto_started)
2988
ieee->proto_started = 0;
2989
ieee->proto_stoppping = 1;
2991
ieee80211_stop_send_beacons(ieee);
2992
del_timer_sync(&ieee->associate_timer);
2993
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2994
cancel_delayed_work(&ieee->associate_retry_wq);
2995
cancel_delayed_work(&ieee->start_ibss_wq);
2997
ieee80211_stop_scan(ieee);
2999
ieee80211_disassociate(ieee);
3000
RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
3002
ieee->proto_stoppping = 0;
3005
void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
3007
ieee->sync_scan_hurryup = 0;
3008
down(&ieee->wx_sem);
3009
ieee80211_start_protocol(ieee);
3013
void ieee80211_start_protocol(struct ieee80211_device *ieee)
3017
if (ieee->proto_started)
3020
ieee->proto_started = 1;
3022
if (ieee->current_network.channel == 0){
3025
if (ch > MAX_CHANNEL_NUMBER)
3026
return; /* no channel found */
3027
#ifdef ENABLE_DOT11D
3028
}while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
3030
}while(!ieee->channel_map[ch]);
3032
ieee->current_network.channel = ch;
3035
if (ieee->current_network.beacon_interval == 0)
3036
ieee->current_network.beacon_interval = 100;
3037
// printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
3038
// ieee->set_chan(ieee->dev,ieee->current_network.channel);
3040
for(i = 0; i < 17; i++) {
3041
ieee->last_rxseq_num[i] = -1;
3042
ieee->last_rxfrag_num[i] = -1;
3043
ieee->last_packet_time[i] = 0;
3046
ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
3048
ieee->state = IEEE80211_NOLINK;
3051
/* if the user set the MAC of the ad-hoc cell and then
3052
* switch to managed mode, shall we make sure that association
3053
* attempts does not fail just because the user provide the essid
3054
* and the nic is still checking for the AP MAC ??
3056
if (ieee->iw_mode == IW_MODE_INFRA)
3057
ieee80211_start_bss(ieee);
3059
else if (ieee->iw_mode == IW_MODE_ADHOC)
3060
ieee80211_start_ibss(ieee);
3062
else if (ieee->iw_mode == IW_MODE_MASTER)
3063
ieee80211_start_master_bss(ieee);
3065
else if(ieee->iw_mode == IW_MODE_MONITOR)
3066
ieee80211_start_monitor_mode(ieee);
3070
#define DRV_NAME "Ieee80211"
3071
void ieee80211_softmac_init(struct ieee80211_device *ieee)
3074
memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
3076
ieee->state = IEEE80211_NOLINK;
3077
ieee->sync_scan_hurryup = 0;
3078
for(i = 0; i < 5; i++) {
3079
ieee->seq_ctrl[i] = 0;
3081
#ifdef ENABLE_DOT11D
3082
ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
3083
if (!ieee->pDot11dInfo)
3084
IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
3086
//added for AP roaming
3087
ieee->LinkDetectInfo.SlotNum = 2;
3088
ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
3089
ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
3092
ieee->queue_stop = 0;
3094
ieee->softmac_features = 0; //so IEEE2100-like driver are happy
3097
ieee->proto_started = 0;
3098
ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
3100
ieee->ps = IEEE80211_PS_DISABLED;
3101
ieee->sta_sleep = 0;
3102
ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
3103
ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
3104
ieee->Regdot11HTOperationalRateSet[4]= 0x01;
3106
ieee->actscanning = false;
3107
ieee->beinretry = false;
3108
ieee->is_set_key = false;
3109
init_mgmt_queue(ieee);
3111
ieee->sta_edca_param[0] = 0x0000A403;
3112
ieee->sta_edca_param[1] = 0x0000A427;
3113
ieee->sta_edca_param[2] = 0x005E4342;
3114
ieee->sta_edca_param[3] = 0x002F3262;
3115
ieee->aggregation = true;
3116
ieee->enable_rx_imm_BA = 1;
3117
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
3118
init_timer(&ieee->scan_timer);
3119
ieee->scan_timer.data = (unsigned long)ieee;
3120
ieee->scan_timer.function = ieee80211_softmac_scan_cb;
3122
ieee->tx_pending.txb = NULL;
3124
init_timer(&ieee->associate_timer);
3125
ieee->associate_timer.data = (unsigned long)ieee;
3126
ieee->associate_timer.function = ieee80211_associate_abort_cb;
3128
init_timer(&ieee->beacon_timer);
3129
ieee->beacon_timer.data = (unsigned long) ieee;
3130
ieee->beacon_timer.function = ieee80211_send_beacon_cb;
3132
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3133
#ifdef PF_SYNCTHREAD
3134
ieee->wq = create_workqueue(DRV_NAME,0);
3136
ieee->wq = create_workqueue(DRV_NAME);
3140
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3141
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20)
3142
INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
3143
INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
3144
INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
3145
INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
3146
INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
3147
INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
3150
INIT_WORK(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3151
INIT_WORK(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3152
INIT_WORK(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3153
INIT_WORK(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3154
INIT_WORK(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3155
INIT_WORK(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3159
tq_init(&ieee->start_ibss_wq,(void(*)(void*)) ieee80211_start_ibss_wq,ieee);
3160
tq_init(&ieee->associate_retry_wq,(void(*)(void*)) ieee80211_associate_retry_wq,ieee);
3161
tq_init(&ieee->associate_complete_wq,(void(*)(void*)) ieee80211_associate_complete_wq,ieee);
3162
tq_init(&ieee->associate_procedure_wq,(void(*)(void*)) ieee80211_associate_procedure_wq,ieee);
3163
tq_init(&ieee->softmac_scan_wq,(void(*)(void*)) ieee80211_softmac_scan_wq,ieee);
3164
tq_init(&ieee->wx_sync_scan_wq,(void(*)(void*)) ieee80211_wx_sync_scan_wq,ieee);
3166
sema_init(&ieee->wx_sem, 1);
3167
sema_init(&ieee->scan_sem, 1);
3169
sema_init(&ieee->ips_sem,1);
3171
spin_lock_init(&ieee->mgmt_tx_lock);
3172
spin_lock_init(&ieee->beacon_lock);
3174
tasklet_init(&ieee->ps_task,
3175
(void(*)(unsigned long)) ieee80211_sta_ps,
3176
(unsigned long)ieee);
3180
void ieee80211_softmac_free(struct ieee80211_device *ieee)
3182
down(&ieee->wx_sem);
3183
#ifdef ENABLE_DOT11D
3184
if(NULL != ieee->pDot11dInfo)
3186
kfree(ieee->pDot11dInfo);
3187
ieee->pDot11dInfo = NULL;
3190
del_timer_sync(&ieee->associate_timer);
3192
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3193
cancel_delayed_work(&ieee->associate_retry_wq);
3194
destroy_workqueue(ieee->wq);
3200
/********************************************************
3201
* Start of WPA code. *
3202
* this is stolen from the ipw2200 driver *
3203
********************************************************/
3206
static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
3208
/* This is called when wpa_supplicant loads and closes the driver
3210
printk("%s WPA\n",value ? "enabling" : "disabling");
3211
ieee->wpa_enabled = value;
3216
void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
3218
/* make sure WPA is enabled */
3219
ieee80211_wpa_enable(ieee, 1);
3221
ieee80211_disassociate(ieee);
3225
static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
3231
case IEEE_MLME_STA_DEAUTH:
3235
case IEEE_MLME_STA_DISASSOC:
3236
ieee80211_disassociate(ieee);
3240
printk("Unknown MLME request: %d\n", command);
3248
static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
3249
struct ieee_param *param, int plen)
3253
if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
3254
(param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
3257
if (param->u.wpa_ie.len) {
3258
buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
3263
kfree(ieee->wpa_ie);
3265
ieee->wpa_ie_len = param->u.wpa_ie.len;
3267
kfree(ieee->wpa_ie);
3268
ieee->wpa_ie = NULL;
3269
ieee->wpa_ie_len = 0;
3272
ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
3276
#define AUTH_ALG_OPEN_SYSTEM 0x1
3277
#define AUTH_ALG_SHARED_KEY 0x2
3279
static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
3282
struct ieee80211_security sec = {
3283
.flags = SEC_AUTH_MODE,
3287
if (value & AUTH_ALG_SHARED_KEY) {
3288
sec.auth_mode = WLAN_AUTH_SHARED_KEY;
3290
ieee->auth_mode = 1;
3291
} else if (value & AUTH_ALG_OPEN_SYSTEM){
3292
sec.auth_mode = WLAN_AUTH_OPEN;
3294
ieee->auth_mode = 0;
3296
else if (value & IW_AUTH_ALG_LEAP){
3297
sec.auth_mode = WLAN_AUTH_LEAP;
3299
ieee->auth_mode = 2;
3303
if (ieee->set_security)
3304
ieee->set_security(ieee->dev, &sec);
3306
// ret = -EOPNOTSUPP;
3311
static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
3314
unsigned long flags;
3317
case IEEE_PARAM_WPA_ENABLED:
3318
ret = ieee80211_wpa_enable(ieee, value);
3321
case IEEE_PARAM_TKIP_COUNTERMEASURES:
3322
ieee->tkip_countermeasures=value;
3325
case IEEE_PARAM_DROP_UNENCRYPTED: {
3328
* wpa_supplicant calls set_wpa_enabled when the driver
3329
* is loaded and unloaded, regardless of if WPA is being
3330
* used. No other calls are made which can be used to
3331
* determine if encryption will be used or not prior to
3332
* association being expected. If encryption is not being
3333
* used, drop_unencrypted is set to false, else true -- we
3334
* can use this to determine if the CAP_PRIVACY_ON bit should
3337
struct ieee80211_security sec = {
3338
.flags = SEC_ENABLED,
3341
ieee->drop_unencrypted = value;
3342
/* We only change SEC_LEVEL for open mode. Others
3343
* are set by ipw_wpa_set_encryption.
3346
sec.flags |= SEC_LEVEL;
3347
sec.level = SEC_LEVEL_0;
3350
sec.flags |= SEC_LEVEL;
3351
sec.level = SEC_LEVEL_1;
3353
if (ieee->set_security)
3354
ieee->set_security(ieee->dev, &sec);
3358
case IEEE_PARAM_PRIVACY_INVOKED:
3359
ieee->privacy_invoked=value;
3362
case IEEE_PARAM_AUTH_ALGS:
3363
ret = ieee80211_wpa_set_auth_algs(ieee, value);
3366
case IEEE_PARAM_IEEE_802_1X:
3367
ieee->ieee802_1x=value;
3369
case IEEE_PARAM_WPAX_SELECT:
3370
// added for WPA2 mixed mode
3371
spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
3372
ieee->wpax_type_set = 1;
3373
ieee->wpax_type_notify = value;
3374
spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3378
printk("Unknown WPA param: %d\n",name);
3385
/* implementation borrowed from hostap driver */
3387
static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3388
struct ieee_param *param, int param_len)
3392
struct ieee80211_crypto_ops *ops;
3393
struct ieee80211_crypt_data **crypt;
3395
struct ieee80211_security sec = {
3399
param->u.crypt.err = 0;
3400
param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3403
(int) ((char *) param->u.crypt.key - (char *) param) +
3404
param->u.crypt.key_len) {
3405
printk("Len mismatch %d, %d\n", param_len,
3406
param->u.crypt.key_len);
3409
if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3410
param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3411
param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3412
if (param->u.crypt.idx >= WEP_KEYS)
3414
crypt = &ieee->crypt[param->u.crypt.idx];
3419
if (strcmp(param->u.crypt.alg, "none") == 0) {
3424
sec.level = SEC_LEVEL_0;
3425
sec.flags |= SEC_ENABLED | SEC_LEVEL;
3426
ieee80211_crypt_delayed_deinit(ieee, crypt);
3433
sec.flags |= SEC_ENABLED;
3435
/* IPW HW cannot build TKIP MIC, host decryption still needed. */
3436
if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3437
strcmp(param->u.crypt.alg, "TKIP"))
3438
goto skip_host_crypt;
3440
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3441
if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3442
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3443
/* set WEP40 first, it will be modified according to WEP104 or
3444
* WEP40 at other place */
3445
else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3446
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3447
else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3448
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3450
printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3451
param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3456
if (*crypt == NULL || (*crypt)->ops != ops) {
3457
struct ieee80211_crypt_data *new_crypt;
3459
ieee80211_crypt_delayed_deinit(ieee, crypt);
3461
new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3462
if (new_crypt == NULL) {
3466
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3467
new_crypt->ops = ops;
3470
new_crypt->ops->init(param->u.crypt.idx);
3472
if (new_crypt->priv == NULL) {
3474
param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3482
if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3483
(*crypt)->ops->set_key(param->u.crypt.key,
3484
param->u.crypt.key_len, param->u.crypt.seq,
3485
(*crypt)->priv) < 0) {
3486
printk("key setting failed\n");
3487
param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3493
if (param->u.crypt.set_tx) {
3494
ieee->tx_keyidx = param->u.crypt.idx;
3495
sec.active_key = param->u.crypt.idx;
3496
sec.flags |= SEC_ACTIVE_KEY;
3498
sec.flags &= ~SEC_ACTIVE_KEY;
3500
if (param->u.crypt.alg != NULL) {
3501
memcpy(sec.keys[param->u.crypt.idx],
3503
param->u.crypt.key_len);
3504
sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3505
sec.flags |= (1 << param->u.crypt.idx);
3507
if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3508
sec.flags |= SEC_LEVEL;
3509
sec.level = SEC_LEVEL_1;
3510
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3511
sec.flags |= SEC_LEVEL;
3512
sec.level = SEC_LEVEL_2;
3513
} else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3514
sec.flags |= SEC_LEVEL;
3515
sec.level = SEC_LEVEL_3;
3519
if (ieee->set_security)
3520
ieee->set_security(ieee->dev, &sec);
3522
/* Do not reset port if card is in Managed mode since resetting will
3523
* generate new IEEE 802.11 authentication which may end up in looping
3524
* with IEEE 802.1X. If your hardware requires a reset after WEP
3525
* configuration (for example... Prism2), implement the reset_port in
3526
* the callbacks structures used to initialize the 802.11 stack. */
3527
if (ieee->reset_on_keychange &&
3528
ieee->iw_mode != IW_MODE_INFRA &&
3530
ieee->reset_port(ieee->dev)) {
3531
printk("reset_port failed\n");
3532
param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3539
inline struct sk_buff *ieee80211_disassociate_skb(
3540
struct ieee80211_network *beacon,
3541
struct ieee80211_device *ieee,
3544
struct sk_buff *skb;
3545
struct ieee80211_disassoc *disass;
3547
skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3551
disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3552
disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3553
disass->header.duration_id = 0;
3555
memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3556
memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3557
memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3559
disass->reason = asRsn;
3566
struct ieee80211_device *ieee,
3571
struct ieee80211_network *beacon = &ieee->current_network;
3572
struct sk_buff *skb;
3573
skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3575
softmac_mgmt_xmit(skb, ieee);
3576
//dev_kfree_skb_any(skb);//edit by thomas
3580
int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3582
struct ieee_param *param;
3585
down(&ieee->wx_sem);
3586
//IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3588
if (p->length < sizeof(struct ieee_param) || !p->pointer){
3593
param = kmalloc(p->length, GFP_KERNEL);
3598
if (copy_from_user(param, p->pointer, p->length)) {
3604
switch (param->cmd) {
3606
case IEEE_CMD_SET_WPA_PARAM:
3607
ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3608
param->u.wpa_param.value);
3611
case IEEE_CMD_SET_WPA_IE:
3612
ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3615
case IEEE_CMD_SET_ENCRYPTION:
3616
ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3620
ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3621
param->u.mlme.reason_code);
3625
printk("Unknown WPA supplicant request: %d\n",param->cmd);
3630
if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3640
void notify_wx_assoc_event(struct ieee80211_device *ieee)
3642
union iwreq_data wrqu;
3643
wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3644
if (ieee->state == IEEE80211_LINKED)
3645
memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3647
memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3648
wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3651
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0))
3652
//EXPORT_SYMBOL(ieee80211_get_beacon);
3653
//EXPORT_SYMBOL(ieee80211_rtl_wake_queue);
3654
//EXPORT_SYMBOL(ieee80211_rtl_stop_queue);
3655
//EXPORT_SYMBOL(ieee80211_reset_queue);
3656
//EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3657
//EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3658
//EXPORT_SYMBOL(ieee80211_is_shortslot);
3659
//EXPORT_SYMBOL(ieee80211_is_54g);
3660
//EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3661
//EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3662
//EXPORT_SYMBOL(ieee80211_softmac_xmit);
3663
//EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3664
//EXPORT_SYMBOL(notify_wx_assoc_event);
3665
//EXPORT_SYMBOL(SendDisassociation);
3666
//EXPORT_SYMBOL(ieee80211_disassociate);
3667
//EXPORT_SYMBOL(ieee80211_start_send_beacons);
3668
//EXPORT_SYMBOL(ieee80211_stop_scan);
3669
//EXPORT_SYMBOL(ieee80211_send_probe_requests);
3670
//EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3671
//EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3673
EXPORT_SYMBOL_NOVERS(ieee80211_get_beacon);
3674
EXPORT_SYMBOL_NOVERS(ieee80211_rtl_wake_queue);
3675
EXPORT_SYMBOL_NOVERS(ieee80211_rtl_stop_queue);
3676
EXPORT_SYMBOL_NOVERS(ieee80211_reset_queue);
3677
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_stop_protocol);
3678
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_start_protocol);
3679
EXPORT_SYMBOL_NOVERS(ieee80211_is_shortslot);
3680
EXPORT_SYMBOL_NOVERS(ieee80211_is_54g);
3681
EXPORT_SYMBOL_NOVERS(ieee80211_wpa_supplicant_ioctl);
3682
EXPORT_SYMBOL_NOVERS(ieee80211_ps_tx_ack);
3683
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_xmit);
3684
EXPORT_SYMBOL_NOVERS(ieee80211_stop_send_beacons);
3685
EXPORT_SYMBOL_NOVERS(notify_wx_assoc_event);
3686
EXPORT_SYMBOL_NOVERS(SendDisassociation);
3687
EXPORT_SYMBOL_NOVERS(ieee80211_disassociate);
3688
EXPORT_SYMBOL_NOVERS(ieee80211_start_send_beacons);
3689
EXPORT_SYMBOL_NOVERS(ieee80211_stop_scan);
3690
EXPORT_SYMBOL_NOVERS(ieee80211_send_probe_requests);
3691
EXPORT_SYMBOL_NOVERS(ieee80211_softmac_scan_syncro);
3692
EXPORT_SYMBOL_NOVERS(ieee80211_start_scan_syncro);
3693
EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_null_frame);
3694
EXPORT_SYMBOL_NOVERS(ieee80211_sta_ps_send_pspoll_frame);