ext4: fix undefined behavior in ext4_fill_flex_info()
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rtl8192su / ieee80211 / ieee80211_softmac.c
blobfd8e11252f1b254ca5e5a8b01182839d3ee024bd
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/version.h>
22 #include <asm/uaccess.h>
23 #include "dot11d.h"
25 u8 rsn_authen_cipher_suite[16][4] = {
26 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
27 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
28 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
29 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
30 {0x00,0x0F,0xAC,0x04}, //CCMP
31 {0x00,0x0F,0xAC,0x05}, //WEP-104
34 short ieee80211_is_54g(struct ieee80211_network net)
36 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
39 short ieee80211_is_shortslot(struct ieee80211_network net)
41 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
44 /* returns the total length needed for pleacing the RATE MFIE
45 * tag and the EXTENDED RATE MFIE tag if needed.
46 * It encludes two bytes per tag for the tag itself and its len
48 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
50 unsigned int rate_len = 0;
52 if (ieee->modulation & IEEE80211_CCK_MODULATION)
53 rate_len = IEEE80211_CCK_RATE_LEN + 2;
55 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
57 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
59 return rate_len;
62 /* pleace the MFIE rate, tag to the memory (double) poined.
63 * Then it updates the pointer so that
64 * it points after the new MFIE tag added.
66 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
68 u8 *tag = *tag_p;
70 if (ieee->modulation & IEEE80211_CCK_MODULATION){
71 *tag++ = MFIE_TYPE_RATES;
72 *tag++ = 4;
73 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
74 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
79 /* We may add an option for custom rates that specific HW might support */
80 *tag_p = tag;
83 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
85 u8 *tag = *tag_p;
87 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
89 *tag++ = MFIE_TYPE_RATES_EX;
90 *tag++ = 8;
91 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
102 /* We may add an option for custom rates that specific HW might support */
103 *tag_p = tag;
107 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
108 u8 *tag = *tag_p;
110 *tag++ = MFIE_TYPE_GENERIC; //0
111 *tag++ = 7;
112 *tag++ = 0x00;
113 *tag++ = 0x50;
114 *tag++ = 0xf2;
115 *tag++ = 0x02;//5
116 *tag++ = 0x00;
117 *tag++ = 0x01;
118 #ifdef SUPPORT_USPD
119 if(ieee->current_network.wmm_info & 0x80) {
120 *tag++ = 0x0f|MAX_SP_Len;
121 } else {
122 *tag++ = MAX_SP_Len;
124 #else
125 *tag++ = MAX_SP_Len;
126 #endif
127 *tag_p = tag;
130 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
131 u8 *tag = *tag_p;
133 *tag++ = MFIE_TYPE_GENERIC; //0
134 *tag++ = 7;
135 *tag++ = 0x00;
136 *tag++ = 0xe0;
137 *tag++ = 0x4c;
138 *tag++ = 0x01;//5
139 *tag++ = 0x02;
140 *tag++ = 0x11;
141 *tag++ = 0x00;
143 *tag_p = tag;
144 printk(KERN_ALERT "This is enable turbo mode IE process\n");
147 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
149 int nh;
150 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
153 * if the queue is full but we have newer frames then
154 * just overwrites the oldest.
156 * if (nh == ieee->mgmt_queue_tail)
157 * return -1;
159 ieee->mgmt_queue_head = nh;
160 ieee->mgmt_queue_ring[nh] = skb;
162 //return 0;
165 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
167 struct sk_buff *ret;
169 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
170 return NULL;
172 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
174 ieee->mgmt_queue_tail =
175 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
177 return ret;
180 void init_mgmt_queue(struct ieee80211_device *ieee)
182 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
185 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
187 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
188 u8 rate;
190 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
191 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
192 rate = 0x0c;
193 else
194 rate = ieee->basic_rate & 0x7f;
196 if(rate == 0){
197 // 2005.01.26, by rcnjko.
198 if(ieee->mode == IEEE_A||
199 ieee->mode== IEEE_N_5G||
200 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
201 rate = 0x0c;
202 else
203 rate = 0x02;
207 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
208 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
210 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
211 rate = 0x0c;
212 else
213 rate = 0x02;
216 return rate;
220 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
222 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
224 unsigned long flags;
225 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
226 struct ieee80211_hdr_3addr *header=
227 (struct ieee80211_hdr_3addr *) skb->data;
229 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
230 spin_lock_irqsave(&ieee->lock, flags);
232 /* called with 2nd param 0, no mgmt lock required */
233 ieee80211_sta_wakeup(ieee,0);
235 tcb_desc->queue_index = MGNT_QUEUE;
236 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
237 tcb_desc->RATRIndex = 7;
238 tcb_desc->bTxDisableRateFallBack = 1;
239 tcb_desc->bTxUseDriverAssingedRate = 1;
241 if(single){
242 if(ieee->queue_stop){
243 enqueue_mgmt(ieee,skb);
244 }else{
245 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
247 if (ieee->seq_ctrl[0] == 0xFFF)
248 ieee->seq_ctrl[0] = 0;
249 else
250 ieee->seq_ctrl[0]++;
252 /* avoid watchdog triggers */
253 // ieee->dev->trans_start = jiffies;
254 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
255 //dev_kfree_skb_any(skb);//edit by thomas
258 spin_unlock_irqrestore(&ieee->lock, flags);
259 }else{
260 spin_unlock_irqrestore(&ieee->lock, flags);
261 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
263 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
265 if (ieee->seq_ctrl[0] == 0xFFF)
266 ieee->seq_ctrl[0] = 0;
267 else
268 ieee->seq_ctrl[0]++;
270 /* check wether the managed packet queued greater than 5 */
271 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
272 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
273 (ieee->queue_stop) ) {
274 /* insert the skb packet to the management queue */
275 /* as for the completion function, it does not need
276 * to check it any more.
277 * */
278 printk("%s():insert to waitqueue!\n",__FUNCTION__);
279 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
280 } else {
281 //printk("TX packet!\n");
282 ieee->softmac_hard_start_xmit(skb,ieee->dev);
283 //dev_kfree_skb_any(skb);//edit by thomas
285 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
289 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
292 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
293 struct ieee80211_hdr_3addr *header =
294 (struct ieee80211_hdr_3addr *) skb->data;
295 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
297 tcb_desc->queue_index = MGNT_QUEUE;
298 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
299 tcb_desc->RATRIndex = 7;
300 tcb_desc->bTxDisableRateFallBack = 1;
301 tcb_desc->bTxUseDriverAssingedRate = 1;
302 //printk("=============>%s()\n", __FUNCTION__);
303 if(single){
305 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
307 if (ieee->seq_ctrl[0] == 0xFFF)
308 ieee->seq_ctrl[0] = 0;
309 else
310 ieee->seq_ctrl[0]++;
312 /* avoid watchdog triggers */
313 // ieee->dev->trans_start = jiffies;
314 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
316 }else{
318 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
320 if (ieee->seq_ctrl[0] == 0xFFF)
321 ieee->seq_ctrl[0] = 0;
322 else
323 ieee->seq_ctrl[0]++;
325 ieee->softmac_hard_start_xmit(skb,ieee->dev);
328 //dev_kfree_skb_any(skb);//edit by thomas
331 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
333 unsigned int len,rate_len;
334 u8 *tag;
335 struct sk_buff *skb;
336 struct ieee80211_probe_request *req;
338 len = ieee->current_network.ssid_len;
340 rate_len = ieee80211_MFIE_rate_len(ieee);
342 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
343 2 + len + rate_len + ieee->tx_headroom);
344 if (!skb)
345 return NULL;
347 skb_reserve(skb, ieee->tx_headroom);
349 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
350 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
351 req->header.duration_id = 0; //FIXME: is this OK ?
353 memset(req->header.addr1, 0xff, ETH_ALEN);
354 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
355 memset(req->header.addr3, 0xff, ETH_ALEN);
357 tag = (u8 *) skb_put(skb,len+2+rate_len);
359 *tag++ = MFIE_TYPE_SSID;
360 *tag++ = len;
361 memcpy(tag, ieee->current_network.ssid, len);
362 tag += len;
364 ieee80211_MFIE_Brate(ieee,&tag);
365 ieee80211_MFIE_Grate(ieee,&tag);
366 return skb;
369 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
370 void ieee80211_send_beacon(struct ieee80211_device *ieee)
372 struct sk_buff *skb;
373 if(!ieee->ieee_up)
374 return;
375 //unsigned long flags;
376 skb = ieee80211_get_beacon_(ieee);
378 if (skb){
379 softmac_mgmt_xmit(skb, ieee);
380 ieee->softmac_stats.tx_beacons++;
381 //dev_kfree_skb_any(skb);//edit by thomas
383 // ieee->beacon_timer.expires = jiffies +
384 // (MSECS( ieee->current_network.beacon_interval -5));
386 //spin_lock_irqsave(&ieee->beacon_lock,flags);
387 if(ieee->beacon_txing && ieee->ieee_up){
388 // if(!timer_pending(&ieee->beacon_timer))
389 // add_timer(&ieee->beacon_timer);
390 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
392 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
396 void ieee80211_send_beacon_cb(unsigned long _ieee)
398 struct ieee80211_device *ieee =
399 (struct ieee80211_device *) _ieee;
400 unsigned long flags;
402 spin_lock_irqsave(&ieee->beacon_lock, flags);
403 ieee80211_send_beacon(ieee);
404 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
408 void ieee80211_send_probe(struct ieee80211_device *ieee)
410 struct sk_buff *skb;
412 skb = ieee80211_probe_req(ieee);
413 if (skb){
414 softmac_mgmt_xmit(skb, ieee);
415 ieee->softmac_stats.tx_probe_rq++;
416 //dev_kfree_skb_any(skb);//edit by thomas
420 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
422 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
423 ieee80211_send_probe(ieee);
424 ieee80211_send_probe(ieee);
428 /* this performs syncro scan blocking the caller until all channels
429 * in the allowed channel map has been checked.
431 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
433 short ch = 0;
434 u8 channel_map[MAX_CHANNEL_NUMBER+1];
435 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
436 ieee->be_scan_inprogress = true;
437 down(&ieee->scan_sem);
439 while(1)
443 ch++;
444 if (ch > MAX_CHANNEL_NUMBER)
445 goto out; /* scan completed */
446 }while(!channel_map[ch]);
448 /* this fuction can be called in two situations
449 * 1- We have switched to ad-hoc mode and we are
450 * performing a complete syncro scan before conclude
451 * there are no interesting cell and to create a
452 * new one. In this case the link state is
453 * IEEE80211_NOLINK until we found an interesting cell.
454 * If so the ieee8021_new_net, called by the RX path
455 * will set the state to IEEE80211_LINKED, so we stop
456 * scanning
457 * 2- We are linked and the root uses run iwlist scan.
458 * So we switch to IEEE80211_LINKED_SCANNING to remember
459 * that we are still logically linked (not interested in
460 * new network events, despite for updating the net list,
461 * but we are temporarly 'unlinked' as the driver shall
462 * not filter RX frames and the channel is changing.
463 * So the only situation in witch are interested is to check
464 * if the state become LINKED because of the #1 situation
467 if (ieee->state == IEEE80211_LINKED)
468 goto out;
469 ieee->set_chan(ieee->dev, ch);
470 if(channel_map[ch] == 1)
471 ieee80211_send_probe_requests(ieee);
473 /* this prevent excessive time wait when we
474 * need to wait for a syncro scan to end..
476 if(ieee->state < IEEE80211_LINKED)
478 else
479 if (ieee->sync_scan_hurryup)
480 goto out;
483 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
486 out:
487 if(ieee->state < IEEE80211_LINKED){
488 ieee->actscanning = false;
489 up(&ieee->scan_sem);
490 ieee->be_scan_inprogress = false;
492 else{
493 ieee->sync_scan_hurryup = 0;
494 if(IS_DOT11D_ENABLE(ieee))
495 DOT11D_ScanComplete(ieee);
496 up(&ieee->scan_sem);
497 ieee->be_scan_inprogress = false;
501 void ieee80211_softmac_scan_wq(struct work_struct *work)
503 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
504 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
505 u8 last_channel = ieee->current_network.channel; //recored init channel inorder not change current channel when comming out the scan unexpectedly. WB.
506 u8 channel_map[MAX_CHANNEL_NUMBER+1];
507 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
508 if(!ieee->ieee_up)
509 return;
510 down(&ieee->scan_sem);
512 ieee->current_network.channel =
513 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
514 if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER)
516 //if current channel is not in channel map, set to default channel.
517 if (!channel_map[ieee->current_network.channel]);
518 ieee->current_network.channel = 6;
519 goto out; /* no good chans */
521 }while(!channel_map[ieee->current_network.channel]);
522 if (ieee->scanning == 0 )
523 goto out;
524 ieee->set_chan(ieee->dev, ieee->current_network.channel);
525 if(channel_map[ieee->current_network.channel] == 1)
526 ieee80211_send_probe_requests(ieee);
528 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
530 up(&ieee->scan_sem);
531 return;
532 out:
533 if(IS_DOT11D_ENABLE(ieee))
534 DOT11D_ScanComplete(ieee);
535 ieee->current_network.channel = last_channel;
536 ieee->actscanning = false;
537 ieee->scan_watch_dog = 0;
538 ieee->scanning = 0;
539 up(&ieee->scan_sem);
542 void ieee80211_beacons_start(struct ieee80211_device *ieee)
544 unsigned long flags;
545 spin_lock_irqsave(&ieee->beacon_lock,flags);
547 ieee->beacon_txing = 1;
548 ieee80211_send_beacon(ieee);
550 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
553 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
555 unsigned long flags;
557 spin_lock_irqsave(&ieee->beacon_lock,flags);
559 ieee->beacon_txing = 0;
560 del_timer_sync(&ieee->beacon_timer);
562 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
567 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
569 if(ieee->stop_send_beacons)
570 ieee->stop_send_beacons(ieee->dev);
571 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
572 ieee80211_beacons_stop(ieee);
576 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
578 if(ieee->start_send_beacons)
579 ieee->start_send_beacons(ieee->dev);
580 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
581 ieee80211_beacons_start(ieee);
585 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
587 // unsigned long flags;
589 //ieee->sync_scan_hurryup = 1;
591 down(&ieee->scan_sem);
592 // spin_lock_irqsave(&ieee->lock, flags);
593 ieee->scan_watch_dog = 0;
594 if (ieee->scanning == 1){
595 ieee->scanning = 0;
597 cancel_delayed_work(&ieee->softmac_scan_wq);
600 // spin_unlock_irqrestore(&ieee->lock, flags);
601 up(&ieee->scan_sem);
604 void ieee80211_stop_scan(struct ieee80211_device *ieee)
606 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
607 ieee80211_softmac_stop_scan(ieee);
608 else
609 ieee->stop_scan(ieee->dev);
612 /* called with ieee->lock held */
613 void ieee80211_start_scan(struct ieee80211_device *ieee)
615 if(IS_DOT11D_ENABLE(ieee) )
617 if(IS_COUNTRY_IE_VALID(ieee))
619 RESET_CIE_WATCHDOG(ieee);
622 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
623 if (ieee->scanning == 0){
624 ieee->scanning = 1;
625 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
627 }else
628 ieee->start_scan(ieee->dev);
632 /* called with wx_sem held */
633 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
635 if(IS_DOT11D_ENABLE(ieee) )
637 if(IS_COUNTRY_IE_VALID(ieee))
639 RESET_CIE_WATCHDOG(ieee);
642 ieee->sync_scan_hurryup = 0;
643 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
644 ieee80211_softmac_scan_syncro(ieee);
645 else
646 ieee->scan_syncro(ieee->dev);
650 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
651 struct ieee80211_device *ieee, int challengelen)
653 struct sk_buff *skb;
654 struct ieee80211_authentication *auth;
655 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
658 skb = dev_alloc_skb(len);
659 if (!skb) return NULL;
661 skb_reserve(skb, ieee->tx_headroom);
662 auth = (struct ieee80211_authentication *)
663 skb_put(skb, sizeof(struct ieee80211_authentication));
665 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
666 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
668 auth->header.duration_id = 0x013a; //FIXME
670 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
671 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
672 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
674 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
675 if(ieee->auth_mode == 0)
676 auth->algorithm = WLAN_AUTH_OPEN;
677 else if(ieee->auth_mode == 1)
678 auth->algorithm = WLAN_AUTH_SHARED_KEY;
679 else if(ieee->auth_mode == 2)
680 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
681 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
682 auth->transaction = cpu_to_le16(ieee->associate_seq);
683 ieee->associate_seq++;
685 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
687 return skb;
692 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
694 u8 *tag;
695 int beacon_size;
696 struct ieee80211_probe_response *beacon_buf;
697 struct sk_buff *skb = NULL;
698 int encrypt;
699 int atim_len,erp_len;
700 struct ieee80211_crypt_data* crypt;
702 char *ssid = ieee->current_network.ssid;
703 int ssid_len = ieee->current_network.ssid_len;
704 int rate_len = ieee->current_network.rates_len+2;
705 int rate_ex_len = ieee->current_network.rates_ex_len;
706 int wpa_ie_len = ieee->wpa_ie_len;
707 u8 erpinfo_content = 0;
709 u8* tmp_ht_cap_buf;
710 u8 tmp_ht_cap_len=0;
711 u8* tmp_ht_info_buf;
712 u8 tmp_ht_info_len=0;
713 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
714 u8* tmp_generic_ie_buf=NULL;
715 u8 tmp_generic_ie_len=0;
717 if(rate_ex_len > 0) rate_ex_len+=2;
719 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
720 atim_len = 4;
721 else
722 atim_len = 0;
724 #if 1
725 if(ieee80211_is_54g(ieee->current_network))
726 erp_len = 3;
727 else
728 erp_len = 0;
729 #else
730 if((ieee->current_network.mode == IEEE_G)
731 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
732 erp_len = 3;
733 erpinfo_content = 0;
734 if(ieee->current_network.buseprotection)
735 erpinfo_content |= ERP_UseProtection;
737 else
738 erp_len = 0;
739 #endif
742 crypt = ieee->crypt[ieee->tx_keyidx];
745 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
746 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
747 //HT ralated element
748 #if 1
749 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
750 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
751 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
752 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
753 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
754 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
757 if(pHTInfo->bRegRT2RTAggregation)
759 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
760 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
761 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
763 // 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);
764 #endif
765 beacon_size = sizeof(struct ieee80211_probe_response)+2+
766 ssid_len
767 +3 //channel
768 +rate_len
769 +rate_ex_len
770 +atim_len
771 +erp_len
772 +wpa_ie_len
773 // +tmp_ht_cap_len
774 // +tmp_ht_info_len
775 // +tmp_generic_ie_len
776 // +wmm_len+2
777 +ieee->tx_headroom;
778 skb = dev_alloc_skb(beacon_size);
779 if (!skb)
780 return NULL;
781 skb_reserve(skb, ieee->tx_headroom);
782 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
783 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
784 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
785 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
787 beacon_buf->header.duration_id = 0; //FIXME
788 beacon_buf->beacon_interval =
789 cpu_to_le16(ieee->current_network.beacon_interval);
790 beacon_buf->capability =
791 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
792 beacon_buf->capability |=
793 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
795 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
796 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
798 crypt = ieee->crypt[ieee->tx_keyidx];
800 if (encrypt)
801 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
804 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
805 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
806 beacon_buf->info_element[0].len = ssid_len;
808 tag = (u8*) beacon_buf->info_element[0].data;
810 memcpy(tag, ssid, ssid_len);
812 tag += ssid_len;
814 *(tag++) = MFIE_TYPE_RATES;
815 *(tag++) = rate_len-2;
816 memcpy(tag,ieee->current_network.rates,rate_len-2);
817 tag+=rate_len-2;
819 *(tag++) = MFIE_TYPE_DS_SET;
820 *(tag++) = 1;
821 *(tag++) = ieee->current_network.channel;
823 if(atim_len){
824 u16 val16;
825 *(tag++) = MFIE_TYPE_IBSS_SET;
826 *(tag++) = 2;
827 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
828 val16 = cpu_to_le16(ieee->current_network.atim_window);
829 memcpy((u8 *)tag, (u8 *)&val16, 2);
830 tag+=2;
833 if(erp_len){
834 *(tag++) = MFIE_TYPE_ERP;
835 *(tag++) = 1;
836 *(tag++) = erpinfo_content;
839 if(rate_ex_len){
840 *(tag++) = MFIE_TYPE_RATES_EX;
841 *(tag++) = rate_ex_len-2;
842 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
843 tag+=rate_ex_len-2;
846 if (wpa_ie_len)
848 if (ieee->iw_mode == IW_MODE_ADHOC)
849 {//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
850 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
852 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
853 tag += wpa_ie_len;
856 //skb->dev = ieee->dev;
857 return skb;
861 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
863 struct sk_buff *skb;
864 u8* tag;
866 struct ieee80211_crypt_data* crypt;
867 struct ieee80211_assoc_response_frame *assoc;
868 short encrypt;
870 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
871 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
873 skb = dev_alloc_skb(len);
875 if (!skb)
876 return NULL;
878 skb_reserve(skb, ieee->tx_headroom);
880 assoc = (struct ieee80211_assoc_response_frame *)
881 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
883 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
884 memcpy(assoc->header.addr1, dest,ETH_ALEN);
885 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
886 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
887 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
888 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
891 if(ieee->short_slot)
892 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
894 if (ieee->host_encrypt)
895 crypt = ieee->crypt[ieee->tx_keyidx];
896 else crypt = NULL;
898 encrypt = ( crypt && crypt->ops);
900 if (encrypt)
901 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
903 assoc->status = 0;
904 assoc->aid = cpu_to_le16(ieee->assoc_id);
905 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
906 else ieee->assoc_id++;
908 tag = (u8*) skb_put(skb, rate_len);
910 ieee80211_MFIE_Brate(ieee, &tag);
911 ieee80211_MFIE_Grate(ieee, &tag);
913 return skb;
916 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
918 struct sk_buff *skb;
919 struct ieee80211_authentication *auth;
920 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
922 skb = dev_alloc_skb(len);
924 if (!skb)
925 return NULL;
927 skb->len = sizeof(struct ieee80211_authentication);
929 auth = (struct ieee80211_authentication *)skb->data;
931 auth->status = cpu_to_le16(status);
932 auth->transaction = cpu_to_le16(2);
933 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
935 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
936 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
937 memcpy(auth->header.addr1, dest, ETH_ALEN);
938 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
939 return skb;
944 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
946 struct sk_buff *skb;
947 struct ieee80211_hdr_3addr* hdr;
949 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
951 if (!skb)
952 return NULL;
954 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
956 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
957 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
958 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
960 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
961 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
962 (pwr ? IEEE80211_FCTL_PM:0));
964 return skb;
970 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
972 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
974 if (buf)
975 softmac_mgmt_xmit(buf, ieee);
979 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
981 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
983 if (buf)
984 softmac_mgmt_xmit(buf, ieee);
988 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
992 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
993 if (buf)
994 softmac_mgmt_xmit(buf, ieee);
998 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1000 struct sk_buff *skb;
1001 //unsigned long flags;
1003 struct ieee80211_assoc_request_frame *hdr;
1004 u8 *tag;//,*rsn_ie;
1005 //short info_addr = 0;
1006 //int i;
1007 //u16 suite_count = 0;
1008 //u8 suit_select = 0;
1009 //unsigned int wpa_len = beacon->wpa_ie_len;
1010 //for HT
1011 u8* ht_cap_buf = NULL;
1012 u8 ht_cap_len=0;
1013 u8* realtek_ie_buf=NULL;
1014 u8 realtek_ie_len=0;
1015 int wpa_ie_len= ieee->wpa_ie_len;
1016 unsigned int ckip_ie_len=0;
1017 unsigned int ccxrm_ie_len=0;
1018 unsigned int cxvernum_ie_len=0;
1019 struct ieee80211_crypt_data* crypt;
1020 int encrypt;
1022 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1023 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1024 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1026 int len = 0;
1028 crypt = ieee->crypt[ieee->tx_keyidx];
1029 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1031 //Include High Throuput capability && Realtek proprietary
1032 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1034 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1035 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1036 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1037 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1039 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1040 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1041 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1045 if(ieee->qos_support){
1046 wmm_info_len = beacon->qos_data.supported?9:0;
1050 if(beacon->bCkipSupported)
1052 ckip_ie_len = 30+2;
1054 if(beacon->bCcxRmEnable)
1056 ccxrm_ie_len = 6+2;
1058 if( beacon->BssCcxVerNumber >= 2 )
1060 cxvernum_ie_len = 5+2;
1062 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1063 + beacon->ssid_len//essid tagged val
1064 + rate_len//rates tagged val
1065 + wpa_ie_len
1066 + wmm_info_len
1067 + turbo_info_len
1068 + ht_cap_len
1069 + realtek_ie_len
1070 + ckip_ie_len
1071 + ccxrm_ie_len
1072 + cxvernum_ie_len
1073 + ieee->tx_headroom;
1075 skb = dev_alloc_skb(len);
1077 if (!skb)
1078 return NULL;
1080 skb_reserve(skb, ieee->tx_headroom);
1082 hdr = (struct ieee80211_assoc_request_frame *)
1083 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1086 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1087 hdr->header.duration_id= 37; //FIXME
1088 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1089 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1090 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1092 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1094 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1095 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1096 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1098 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1099 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1101 if(ieee->short_slot)
1102 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1103 if (wmm_info_len) //QOS
1104 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1106 hdr->listen_interval = 0xa; //FIXME
1108 hdr->info_element[0].id = MFIE_TYPE_SSID;
1110 hdr->info_element[0].len = beacon->ssid_len;
1111 tag = skb_put(skb, beacon->ssid_len);
1112 memcpy(tag, beacon->ssid, beacon->ssid_len);
1114 tag = skb_put(skb, rate_len);
1116 ieee80211_MFIE_Brate(ieee, &tag);
1117 ieee80211_MFIE_Grate(ieee, &tag);
1118 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1119 if( beacon->bCkipSupported )
1121 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1122 u8 CcxAironetBuf[30];
1123 OCTET_STRING osCcxAironetIE;
1125 memset(CcxAironetBuf, 0,30);
1126 osCcxAironetIE.Octet = CcxAironetBuf;
1127 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1129 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1130 // We want to make the device type as "4500-client". 060926, by CCW.
1132 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1134 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1135 // "The CKIP negotiation is started with the associate request from the client to the access point,
1136 // containing an Aironet element with both the MIC and KP bits set."
1137 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1138 tag = skb_put(skb, ckip_ie_len);
1139 *tag++ = MFIE_TYPE_AIRONET;
1140 *tag++ = osCcxAironetIE.Length;
1141 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1142 tag += osCcxAironetIE.Length;
1145 if(beacon->bCcxRmEnable)
1147 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1148 OCTET_STRING osCcxRmCap;
1150 osCcxRmCap.Octet = CcxRmCapBuf;
1151 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1152 tag = skb_put(skb,ccxrm_ie_len);
1153 *tag++ = MFIE_TYPE_GENERIC;
1154 *tag++ = osCcxRmCap.Length;
1155 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1156 tag += osCcxRmCap.Length;
1159 if( beacon->BssCcxVerNumber >= 2 )
1161 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1162 OCTET_STRING osCcxVerNum;
1163 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1164 osCcxVerNum.Octet = CcxVerNumBuf;
1165 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1166 tag = skb_put(skb,cxvernum_ie_len);
1167 *tag++ = MFIE_TYPE_GENERIC;
1168 *tag++ = osCcxVerNum.Length;
1169 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1170 tag += osCcxVerNum.Length;
1172 //HT cap element
1173 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1174 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1176 tag = skb_put(skb, ht_cap_len);
1177 *tag++ = MFIE_TYPE_HT_CAP;
1178 *tag++ = ht_cap_len - 2;
1179 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1180 tag += ht_cap_len -2;
1185 //choose what wpa_supplicant gives to associate.
1186 tag = skb_put(skb, wpa_ie_len);
1187 if (wpa_ie_len){
1188 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1191 tag = skb_put(skb,wmm_info_len);
1192 if(wmm_info_len) {
1193 ieee80211_WMM_Info(ieee, &tag);
1195 tag = skb_put(skb,turbo_info_len);
1196 if(turbo_info_len) {
1197 ieee80211_TURBO_Info(ieee, &tag);
1200 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1201 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1203 tag = skb_put(skb, ht_cap_len);
1204 *tag++ = MFIE_TYPE_GENERIC;
1205 *tag++ = ht_cap_len - 2;
1206 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1207 tag += ht_cap_len -2;
1210 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1211 tag = skb_put(skb, realtek_ie_len);
1212 *tag++ = MFIE_TYPE_GENERIC;
1213 *tag++ = realtek_ie_len - 2;
1214 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1217 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1218 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1219 return skb;
1222 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1225 unsigned long flags;
1226 spin_lock_irqsave(&ieee->lock, flags);
1228 ieee->associate_seq++;
1230 /* don't scan, and avoid to have the RX path possibily
1231 * try again to associate. Even do not react to AUTH or
1232 * ASSOC response. Just wait for the retry wq to be scheduled.
1233 * Here we will check if there are good nets to associate
1234 * with, so we retry or just get back to NO_LINK and scanning
1236 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1237 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1238 ieee->softmac_stats.no_auth_rs++;
1239 }else{
1240 IEEE80211_DEBUG_MGMT("Association failed\n");
1241 ieee->softmac_stats.no_ass_rs++;
1244 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1246 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1247 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1249 spin_unlock_irqrestore(&ieee->lock, flags);
1252 void ieee80211_associate_abort_cb(unsigned long dev)
1254 ieee80211_associate_abort((struct ieee80211_device *) dev);
1258 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1260 struct ieee80211_network *beacon = &ieee->current_network;
1261 struct sk_buff *skb;
1263 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1265 ieee->softmac_stats.tx_auth_rq++;
1266 skb=ieee80211_authentication_req(beacon, ieee, 0);
1268 if (!skb)
1269 ieee80211_associate_abort(ieee);
1270 else{
1271 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1272 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1273 //printk(KERN_WARNING "Sending authentication request\n");
1274 softmac_mgmt_xmit(skb, ieee);
1275 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1276 if(!timer_pending(&ieee->associate_timer)){
1277 ieee->associate_timer.expires = jiffies + (HZ / 2);
1278 add_timer(&ieee->associate_timer);
1280 //dev_kfree_skb_any(skb);//edit by thomas
1284 void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1286 u8 *c;
1287 struct sk_buff *skb;
1288 struct ieee80211_network *beacon = &ieee->current_network;
1289 // int hlen = sizeof(struct ieee80211_authentication);
1291 ieee->associate_seq++;
1292 ieee->softmac_stats.tx_auth_rq++;
1294 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1295 if (!skb)
1296 ieee80211_associate_abort(ieee);
1297 else{
1298 c = skb_put(skb, chlen+2);
1299 *(c++) = MFIE_TYPE_CHALLENGE;
1300 *(c++) = chlen;
1301 memcpy(c, challenge, chlen);
1303 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1305 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1307 softmac_mgmt_xmit(skb, ieee);
1308 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1309 //dev_kfree_skb_any(skb);//edit by thomas
1311 kfree(challenge);
1314 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1316 struct sk_buff* skb;
1317 struct ieee80211_network *beacon = &ieee->current_network;
1319 del_timer_sync(&ieee->associate_timer);
1321 IEEE80211_DEBUG_MGMT("Sending association request\n");
1323 ieee->softmac_stats.tx_ass_rq++;
1324 skb=ieee80211_association_req(beacon, ieee);
1325 if (!skb)
1326 ieee80211_associate_abort(ieee);
1327 else{
1328 softmac_mgmt_xmit(skb, ieee);
1329 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1330 //dev_kfree_skb_any(skb);//edit by thomas
1334 void ieee80211_associate_complete_wq(struct work_struct *work)
1336 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1338 printk(KERN_INFO "Associated successfully\n");
1339 ieee->is_roaming = false;
1340 if(ieee80211_is_54g(ieee->current_network) &&
1341 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1343 ieee->rate = 108;
1344 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1345 }else{
1346 ieee->rate = 22;
1347 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1349 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1351 printk("Successfully associated, ht enabled\n");
1352 HTOnAssocRsp(ieee);
1354 else
1356 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1357 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1358 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1360 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1361 // To prevent the immediately calling watch_dog after association.
1362 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1364 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1365 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1367 ieee->link_change(ieee->dev);
1368 if(ieee->is_silent_reset == 0){
1369 printk("============>normal associate\n");
1370 notify_wx_assoc_event(ieee);
1372 else if(ieee->is_silent_reset == 1)
1374 printk("==================>silent reset associate\n");
1375 ieee->is_silent_reset = 0;
1378 if (ieee->data_hard_resume)
1379 ieee->data_hard_resume(ieee->dev);
1380 netif_carrier_on(ieee->dev);
1383 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1385 // int i;
1386 // struct net_device* dev = ieee->dev;
1387 del_timer_sync(&ieee->associate_timer);
1389 ieee->state = IEEE80211_LINKED;
1390 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1391 queue_work(ieee->wq, &ieee->associate_complete_wq);
1394 void ieee80211_associate_procedure_wq(struct work_struct *work)
1396 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1398 ieee->sync_scan_hurryup = 1;
1399 down(&ieee->wx_sem);
1401 if (ieee->data_hard_stop)
1402 ieee->data_hard_stop(ieee->dev);
1404 ieee80211_stop_scan(ieee);
1405 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1406 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1407 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1409 ieee->associate_seq = 1;
1410 ieee80211_associate_step1(ieee);
1412 up(&ieee->wx_sem);
1415 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1417 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1418 int tmp_ssid_len = 0;
1420 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1422 /* we are interested in new new only if we are not associated
1423 * and we are not associating / authenticating
1425 if (ieee->state != IEEE80211_NOLINK)
1426 return;
1428 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1429 return;
1431 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1432 return;
1435 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1436 /* if the user specified the AP MAC, we need also the essid
1437 * This could be obtained by beacons or, if the network does not
1438 * broadcast it, it can be put manually.
1440 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1441 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1442 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1443 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1444 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1445 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1448 if ( /* if the user set the AP check if match.
1449 * if the network does not broadcast essid we check the user supplyed ANY essid
1450 * if the network does broadcast and the user does not set essid it is OK
1451 * if the network does broadcast and the user did set essid chech if essid match
1453 ( apset && apmatch &&
1454 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1455 /* if the ap is not set, check that the user set the bssid
1456 * and the network does bradcast and that those two bssid matches
1458 (!apset && ssidset && ssidbroad && ssidmatch)
1460 /* if the essid is hidden replace it with the
1461 * essid provided by the user.
1463 if (!ssidbroad){
1464 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1465 tmp_ssid_len = ieee->current_network.ssid_len;
1467 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1469 if (!ssidbroad){
1470 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1471 ieee->current_network.ssid_len = tmp_ssid_len;
1473 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT, ieee->current_network.mode);
1475 //ieee->pHTInfo->IOTAction = 0;
1476 HTResetIOTSetting(ieee->pHTInfo);
1477 if (ieee->iw_mode == IW_MODE_INFRA){
1478 /* Join the network for the first time */
1479 ieee->AsocRetryCount = 0;
1480 //for HT by amy 080514
1481 if((ieee->current_network.qos_data.supported == 1) &&
1482 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1483 ieee->current_network.bssht.bdSupportHT)
1484 /*WB, 2008.09.09:bCurrentHTSupport and bEnableHT two flags are going to put together to check whether we are in HT now, so needn't to check bEnableHT flags here. That's is to say we will set to HT support whenever joined AP has the ability to support HT. And whether we are in HT or not, please check bCurrentHTSupport&&bEnableHT now please.*/
1486 // ieee->pHTInfo->bCurrentHTSupport = true;
1487 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1489 else
1491 ieee->pHTInfo->bCurrentHTSupport = false;
1494 ieee->state = IEEE80211_ASSOCIATING;
1495 if(ieee->LedControlHandler != NULL)
1496 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK);
1497 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1498 }else{
1499 if(ieee80211_is_54g(ieee->current_network) &&
1500 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1501 ieee->rate = 108;
1502 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1503 printk(KERN_INFO"Using G rates\n");
1504 }else{
1505 ieee->rate = 22;
1506 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1507 printk(KERN_INFO"Using B rates\n");
1509 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1510 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1511 ieee->state = IEEE80211_LINKED;
1519 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1521 unsigned long flags;
1522 struct ieee80211_network *target;
1524 spin_lock_irqsave(&ieee->lock, flags);
1526 list_for_each_entry(target, &ieee->network_list, list) {
1528 /* if the state become different that NOLINK means
1529 * we had found what we are searching for
1532 if (ieee->state != IEEE80211_NOLINK)
1533 break;
1535 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1536 ieee80211_softmac_new_net(ieee, target);
1539 spin_unlock_irqrestore(&ieee->lock, flags);
1544 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1546 struct ieee80211_authentication *a;
1547 u8 *t;
1548 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1549 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1550 return 0xcafe;
1552 *challenge = NULL;
1553 a = (struct ieee80211_authentication*) skb->data;
1554 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1555 t = skb->data + sizeof(struct ieee80211_authentication);
1557 if(*(t++) == MFIE_TYPE_CHALLENGE){
1558 *chlen = *(t++);
1559 *challenge = (u8*)kmalloc(*chlen, GFP_ATOMIC);
1560 memcpy(*challenge, t, *chlen);
1564 return cpu_to_le16(a->status);
1569 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1571 struct ieee80211_authentication *a;
1573 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1574 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1575 return -1;
1577 a = (struct ieee80211_authentication*) skb->data;
1579 memcpy(dest,a->header.addr2, ETH_ALEN);
1581 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1582 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1584 return WLAN_STATUS_SUCCESS;
1587 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1589 u8 *tag;
1590 u8 *skbend;
1591 u8 *ssid=NULL;
1592 u8 ssidlen = 0;
1594 struct ieee80211_hdr_3addr *header =
1595 (struct ieee80211_hdr_3addr *) skb->data;
1597 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1598 return -1; /* corrupted */
1600 memcpy(src,header->addr2, ETH_ALEN);
1602 skbend = (u8*)skb->data + skb->len;
1604 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1606 while (tag+1 < skbend){
1607 if (*tag == 0){
1608 ssid = tag+2;
1609 ssidlen = *(tag+1);
1610 break;
1612 tag++; /* point to the len field */
1613 tag = tag + *(tag); /* point to the last data byte of the tag */
1614 tag++; /* point to the next tag */
1617 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1618 if (ssidlen == 0) return 1;
1620 if (!ssid) return 1; /* ssid not found in tagged param */
1621 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1625 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1627 struct ieee80211_assoc_request_frame *a;
1629 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1630 sizeof(struct ieee80211_info_element))) {
1632 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1633 return -1;
1636 a = (struct ieee80211_assoc_request_frame*) skb->data;
1638 memcpy(dest,a->header.addr2,ETH_ALEN);
1640 return 0;
1643 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1645 struct ieee80211_assoc_response_frame *response_head;
1646 u16 status_code;
1648 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1649 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1650 return 0xcafe;
1653 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1654 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1656 status_code = le16_to_cpu(response_head->status);
1657 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1658 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1659 ((ieee->mode == IEEE_G) &&
1660 (ieee->current_network.mode == IEEE_N_24G) &&
1661 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1662 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1663 }else {
1664 ieee->AsocRetryCount = 0;
1667 return le16_to_cpu(response_head->status);
1670 static inline void
1671 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1673 u8 dest[ETH_ALEN];
1675 //IEEE80211DMESG("Rx probe");
1676 ieee->softmac_stats.rx_probe_rq++;
1677 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1678 if (probe_rq_parse(ieee, skb, dest)){
1679 //IEEE80211DMESG("Was for me!");
1680 ieee->softmac_stats.tx_probe_rs++;
1681 ieee80211_resp_to_probe(ieee, dest);
1685 static inline void
1686 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1688 u8 dest[ETH_ALEN];
1689 int status;
1690 //IEEE80211DMESG("Rx probe");
1691 ieee->softmac_stats.rx_auth_rq++;
1693 if ((status = auth_rq_parse(skb, dest))!= -1){
1694 ieee80211_resp_to_auth(ieee, status, dest);
1696 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1700 static inline void
1701 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1704 u8 dest[ETH_ALEN];
1705 //unsigned long flags;
1707 ieee->softmac_stats.rx_ass_rq++;
1708 if (assoc_rq_parse(skb,dest) != -1){
1709 ieee80211_resp_to_assoc_rq(ieee, dest);
1712 printk(KERN_INFO"New client associated: "MAC_FMT"\n", MAC_ARG(dest));
1713 //FIXME
1718 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1721 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1723 if (buf)
1724 softmac_ps_mgmt_xmit(buf, ieee);
1729 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1731 int timeout = ieee->ps_timeout;
1732 u8 dtim;
1733 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1734 ieee->iw_mode != IW_MODE_INFRA ||
1735 ieee->state != IEEE80211_LINKED)
1737 return 0;
1739 dtim = ieee->current_network.dtim_data;
1740 //printk("DTIM\n");
1741 if(!(dtim & IEEE80211_DTIM_VALID))
1742 return 0;
1743 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1744 //printk("VALID\n");
1745 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1747 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1748 return 2;
1750 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1751 return 0;
1753 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1754 return 0;
1756 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1757 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1758 return 0;
1760 if(time_l){
1761 *time_l = ieee->current_network.last_dtim_sta_time[0]
1762 + (ieee->current_network.beacon_interval);
1763 // * ieee->current_network.dtim_period) * 1000;
1766 if(time_h){
1767 *time_h = ieee->current_network.last_dtim_sta_time[1];
1768 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1769 *time_h += 1;
1772 return 1;
1777 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1780 u32 th,tl;
1781 short sleep;
1783 unsigned long flags,flags2;
1785 spin_lock_irqsave(&ieee->lock, flags);
1787 if((ieee->ps == IEEE80211_PS_DISABLED ||
1788 ieee->iw_mode != IW_MODE_INFRA ||
1789 ieee->state != IEEE80211_LINKED)){
1791 // #warning CHECK_LOCK_HERE
1792 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1794 ieee80211_sta_wakeup(ieee, 1);
1796 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1799 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1800 /* 2 wake, 1 sleep, 0 do nothing */
1801 if(sleep == 0)
1802 goto out;
1804 if(sleep == 1){
1806 if(ieee->sta_sleep == 1)
1807 ieee->enter_sleep_state(ieee->dev,th,tl);
1809 else if(ieee->sta_sleep == 0){
1810 // printk("send null 1\n");
1811 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1813 if(ieee->ps_is_queue_empty(ieee->dev)){
1816 ieee->sta_sleep = 2;
1818 ieee->ack_tx_to_ieee = 1;
1820 ieee80211_sta_ps_send_null_frame(ieee,1);
1822 ieee->ps_th = th;
1823 ieee->ps_tl = tl;
1825 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1830 }else if(sleep == 2){
1831 //#warning CHECK_LOCK_HERE
1832 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1834 ieee80211_sta_wakeup(ieee,1);
1836 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1839 out:
1840 spin_unlock_irqrestore(&ieee->lock, flags);
1844 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1846 if(ieee->sta_sleep == 0){
1847 if(nl){
1848 printk("Warning: driver is probably failing to report TX ps error\n");
1849 ieee->ack_tx_to_ieee = 1;
1850 ieee80211_sta_ps_send_null_frame(ieee, 0);
1852 return;
1856 if(ieee->sta_sleep == 1)
1857 ieee->sta_wake_up(ieee->dev);
1859 ieee->sta_sleep = 0;
1861 if(nl){
1862 ieee->ack_tx_to_ieee = 1;
1863 ieee80211_sta_ps_send_null_frame(ieee, 0);
1867 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1869 unsigned long flags,flags2;
1871 spin_lock_irqsave(&ieee->lock, flags);
1873 if(ieee->sta_sleep == 2){
1874 /* Null frame with PS bit set */
1875 if(success){
1876 ieee->sta_sleep = 1;
1877 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1879 /* if the card report not success we can't be sure the AP
1880 * has not RXed so we can't assume the AP believe us awake
1883 /* 21112005 - tx again null without PS bit if lost */
1884 else {
1886 if((ieee->sta_sleep == 0) && !success){
1887 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1888 ieee80211_sta_ps_send_null_frame(ieee, 0);
1889 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1892 spin_unlock_irqrestore(&ieee->lock, flags);
1894 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1896 struct rtl_ieee80211_hdr *header =
1897 (struct rtl_ieee80211_hdr *)skb->data;
1898 u8* act = ieee80211_get_payload(header);
1899 u8 tmp = 0;
1900 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1901 if (act == NULL)
1903 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1904 return;
1906 tmp = *act;
1907 act ++;
1908 switch (tmp)
1910 case ACT_CAT_BA:
1911 if (*act == ACT_ADDBAREQ)
1912 ieee80211_rx_ADDBAReq(ieee, skb);
1913 else if (*act == ACT_ADDBARSP)
1914 ieee80211_rx_ADDBARsp(ieee, skb);
1915 else if (*act == ACT_DELBA)
1916 ieee80211_rx_DELBA(ieee, skb);
1917 break;
1918 default:
1919 // if (net_ratelimit())
1920 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
1921 break;
1923 return;
1926 inline int
1927 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1928 struct ieee80211_rx_stats *rx_stats, u16 type,
1929 u16 stype)
1931 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1932 u16 errcode;
1933 u8* challenge;
1934 int chlen=0;
1935 int aid;
1936 struct ieee80211_assoc_response_frame *assoc_resp;
1937 // struct ieee80211_info_element *info_element;
1938 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1940 if(!ieee->proto_started)
1941 return 0;
1943 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1945 case IEEE80211_STYPE_ASSOC_RESP:
1946 case IEEE80211_STYPE_REASSOC_RESP:
1948 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1949 WLAN_FC_GET_STYPE(header->frame_ctl));
1950 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1951 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1952 ieee->iw_mode == IW_MODE_INFRA){
1953 struct ieee80211_network network_resp;
1954 struct ieee80211_network *network = &network_resp;
1956 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
1957 ieee->state=IEEE80211_LINKED;
1958 ieee->assoc_id = aid;
1959 ieee->softmac_stats.rx_ass_ok++;
1960 /* station support qos */
1961 /* Let the register setting defaultly with Legacy station */
1962 if(ieee->qos_support) {
1963 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
1964 memset(network, 0, sizeof(*network));
1965 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1966 rx_stats->len - sizeof(*assoc_resp),\
1967 network,rx_stats)){
1968 return 1;
1970 else
1971 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
1972 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1973 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1975 if (ieee->handle_assoc_response != NULL)
1976 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
1978 ieee80211_associate_complete(ieee);
1979 } else {
1980 /* aid could not been allocated */
1981 ieee->softmac_stats.rx_ass_err++;
1982 printk(
1983 "Association response status code 0x%x\n",
1984 errcode);
1985 IEEE80211_DEBUG_MGMT(
1986 "Association response status code 0x%x\n",
1987 errcode);
1988 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
1989 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1990 } else {
1991 ieee80211_associate_abort(ieee);
1995 break;
1997 case IEEE80211_STYPE_ASSOC_REQ:
1998 case IEEE80211_STYPE_REASSOC_REQ:
2000 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2001 ieee->iw_mode == IW_MODE_MASTER)
2003 ieee80211_rx_assoc_rq(ieee, skb);
2004 break;
2006 case IEEE80211_STYPE_AUTH:
2008 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2009 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2010 ieee->iw_mode == IW_MODE_INFRA){
2012 IEEE80211_DEBUG_MGMT("Received authentication response");
2014 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2015 if(ieee->open_wep || !challenge){
2016 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2017 ieee->softmac_stats.rx_auth_rs_ok++;
2018 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2020 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2022 // WEP or TKIP encryption
2023 if(IsHTHalfNmodeAPs(ieee))
2025 bSupportNmode = true;
2026 bHalfSupportNmode = true;
2028 else
2030 bSupportNmode = false;
2031 bHalfSupportNmode = false;
2033 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2036 /* Dummy wirless mode setting to avoid encryption issue */
2037 if(bSupportNmode) {
2038 //N mode setting
2039 ieee->SetWirelessMode(ieee->dev, \
2040 ieee->current_network.mode);
2041 }else{
2042 //b/g mode setting
2043 /*TODO*/
2044 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2047 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2049 printk("===============>entern half N mode\n");
2050 ieee->bHalfWirelessN24GMode = true;
2052 else
2053 ieee->bHalfWirelessN24GMode = false;
2055 ieee80211_associate_step2(ieee);
2056 }else{
2057 ieee80211_auth_challenge(ieee, challenge, chlen);
2059 }else{
2060 ieee->softmac_stats.rx_auth_rs_err++;
2061 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2063 printk("Authentication respose status code 0x%x",errcode);
2064 ieee80211_associate_abort(ieee);
2067 }else if (ieee->iw_mode == IW_MODE_MASTER){
2068 ieee80211_rx_auth_rq(ieee, skb);
2071 break;
2073 case IEEE80211_STYPE_PROBE_REQ:
2075 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2076 ((ieee->iw_mode == IW_MODE_ADHOC ||
2077 ieee->iw_mode == IW_MODE_MASTER) &&
2078 ieee->state == IEEE80211_LINKED)){
2079 ieee80211_rx_probe_rq(ieee, skb);
2081 break;
2083 case IEEE80211_STYPE_DISASSOC:
2084 case IEEE80211_STYPE_DEAUTH:
2085 /* FIXME for now repeat all the association procedure
2086 * both for disassociation and deauthentication
2088 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2089 ieee->state == IEEE80211_LINKED &&
2090 ieee->iw_mode == IW_MODE_INFRA){
2091 printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_ctl), ((struct ieee80211_disassoc*)skb->data)->reason);
2092 ieee->state = IEEE80211_ASSOCIATING;
2093 ieee->softmac_stats.reassoc++;
2094 ieee->is_roaming = true;
2095 ieee80211_disassociate(ieee);
2096 // notify_wx_assoc_event(ieee);
2097 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2098 RemovePeerTS(ieee, header->addr2);
2099 if(ieee->LedControlHandler != NULL)
2100 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); //added by amy for LED 090318
2101 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2103 break;
2104 case IEEE80211_STYPE_MANAGE_ACT:
2105 ieee80211_process_action(ieee,skb);
2106 break;
2107 default:
2108 return -1;
2109 break;
2112 //dev_kfree_skb_any(skb);
2113 return 0;
2116 /* following are for a simplier TX queue management.
2117 * Instead of using netif_[stop/wake]_queue the driver
2118 * will uses these two function (plus a reset one), that
2119 * will internally uses the kernel netif_* and takes
2120 * care of the ieee802.11 fragmentation.
2121 * So the driver receives a fragment per time and might
2122 * call the stop function when it want without take care
2123 * to have enought room to TX an entire packet.
2124 * This might be useful if each fragment need it's own
2125 * descriptor, thus just keep a total free memory > than
2126 * the max fragmentation treshold is not enought.. If the
2127 * ieee802.11 stack passed a TXB struct then you needed
2128 * to keep N free descriptors where
2129 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2130 * In this way you need just one and the 802.11 stack
2131 * will take care of buffering fragments and pass them to
2132 * to the driver later, when it wakes the queue.
2134 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2137 unsigned int queue_index = txb->queue_index;
2138 unsigned long flags;
2139 int i;
2140 cb_desc *tcb_desc = NULL;
2142 spin_lock_irqsave(&ieee->lock,flags);
2144 /* called with 2nd parm 0, no tx mgmt lock required */
2145 ieee80211_sta_wakeup(ieee,0);
2147 /* update the tx status */
2148 // ieee->stats.tx_bytes += txb->payload_size;
2149 // ieee->stats.tx_packets++;
2150 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2151 if(tcb_desc->bMulticast) {
2152 ieee->stats.multicast++;
2154 #if 1
2155 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2156 for(i = 0; i < txb->nr_frags; i++) {
2157 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2158 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2159 (ieee->queue_stop)) {
2160 /* insert the skb packet to the wait queue */
2161 /* as for the completion function, it does not need
2162 * to check it any more.
2163 * */
2164 //printk("error:no descriptor left@queue_index %d, %d, %d\n", queue_index, skb_queue_len(&ieee->skb_waitQ[queue_index]), ieee->check_nic_enough_desc(ieee->dev,queue_index));
2165 //ieee80211_stop_queue(ieee);
2166 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2167 }else{
2168 ieee->softmac_data_hard_start_xmit(
2169 txb->fragments[i],
2170 ieee->dev,ieee->rate);
2171 //ieee->stats.tx_packets++;
2172 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2173 //ieee->dev->trans_start = jiffies;
2176 #endif
2177 ieee80211_txb_free(txb);
2179 //exit:
2180 spin_unlock_irqrestore(&ieee->lock,flags);
2184 /* called with ieee->lock acquired */
2185 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2187 int i;
2188 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2190 if (ieee->queue_stop){
2191 ieee->tx_pending.frag = i;
2192 return;
2193 }else{
2195 ieee->softmac_data_hard_start_xmit(
2196 ieee->tx_pending.txb->fragments[i],
2197 ieee->dev,ieee->rate);
2198 //(i+1)<ieee->tx_pending.txb->nr_frags);
2199 ieee->stats.tx_packets++;
2200 // ieee->dev->trans_start = jiffies;
2205 ieee80211_txb_free(ieee->tx_pending.txb);
2206 ieee->tx_pending.txb = NULL;
2210 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2212 unsigned long flags;
2214 spin_lock_irqsave(&ieee->lock,flags);
2215 init_mgmt_queue(ieee);
2216 if (ieee->tx_pending.txb){
2217 ieee80211_txb_free(ieee->tx_pending.txb);
2218 ieee->tx_pending.txb = NULL;
2220 ieee->queue_stop = 0;
2221 spin_unlock_irqrestore(&ieee->lock,flags);
2225 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2228 unsigned long flags;
2229 struct sk_buff *skb;
2230 struct ieee80211_hdr_3addr *header;
2232 spin_lock_irqsave(&ieee->lock,flags);
2233 if (! ieee->queue_stop) goto exit;
2235 ieee->queue_stop = 0;
2237 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2238 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2240 header = (struct ieee80211_hdr_3addr *) skb->data;
2242 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2244 if (ieee->seq_ctrl[0] == 0xFFF)
2245 ieee->seq_ctrl[0] = 0;
2246 else
2247 ieee->seq_ctrl[0]++;
2249 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2250 //dev_kfree_skb_any(skb);//edit by thomas
2253 if (!ieee->queue_stop && ieee->tx_pending.txb)
2254 ieee80211_resume_tx(ieee);
2256 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2257 ieee->softmac_stats.swtxawake++;
2258 netif_wake_queue(ieee->dev);
2261 exit :
2262 spin_unlock_irqrestore(&ieee->lock,flags);
2266 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2268 //unsigned long flags;
2269 //spin_lock_irqsave(&ieee->lock,flags);
2271 if (! netif_queue_stopped(ieee->dev)){
2272 netif_stop_queue(ieee->dev);
2273 ieee->softmac_stats.swtxstop++;
2275 ieee->queue_stop = 1;
2276 //spin_unlock_irqrestore(&ieee->lock,flags);
2281 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2284 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2286 /* an IBSS cell address must have the two less significant
2287 * bits of the first byte = 2
2289 ieee->current_network.bssid[0] &= ~0x01;
2290 ieee->current_network.bssid[0] |= 0x02;
2293 /* called in user context only */
2294 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2296 ieee->assoc_id = 1;
2298 if (ieee->current_network.ssid_len == 0){
2299 strncpy(ieee->current_network.ssid,
2300 IEEE80211_DEFAULT_TX_ESSID,
2301 IW_ESSID_MAX_SIZE);
2303 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2304 ieee->ssid_set = 1;
2307 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2309 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2310 ieee->state = IEEE80211_LINKED;
2311 ieee->link_change(ieee->dev);
2312 notify_wx_assoc_event(ieee);
2314 if (ieee->data_hard_resume)
2315 ieee->data_hard_resume(ieee->dev);
2317 netif_carrier_on(ieee->dev);
2320 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2322 if(ieee->raw_tx){
2324 if (ieee->data_hard_resume)
2325 ieee->data_hard_resume(ieee->dev);
2327 netif_carrier_on(ieee->dev);
2331 void ieee80211_start_ibss_wq(struct work_struct *work)
2334 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2335 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2336 /* iwconfig mode ad-hoc will schedule this and return
2337 * on the other hand this will block further iwconfig SET
2338 * operations because of the wx_sem hold.
2339 * Anyway some most set operations set a flag to speed-up
2340 * (abort) this wq (when syncro scanning) before sleeping
2341 * on the semaphore
2343 if(!ieee->proto_started){
2344 printk("==========oh driver down return\n");
2345 return;
2347 down(&ieee->wx_sem);
2348 //FIXME:set back to 20M whenever HT for ibss is not ready. Otherwise,after being connected to 40M AP, it will still stay in 40M when set to ibss mode. WB 2009.02.04
2349 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2351 if (ieee->current_network.ssid_len == 0){
2352 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2353 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2354 ieee->ssid_set = 1;
2357 /* check if we have this cell in our network list */
2358 ieee80211_softmac_check_all_nets(ieee);
2361 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2362 if (ieee->state == IEEE80211_NOLINK)
2363 ieee->current_network.channel = 6;
2364 /* if not then the state is not linked. Maybe the user swithced to
2365 * ad-hoc mode just after being in monitor mode, or just after
2366 * being very few time in managed mode (so the card have had no
2367 * time to scan all the chans..) or we have just run up the iface
2368 * after setting ad-hoc mode. So we have to give another try..
2369 * Here, in ibss mode, should be safe to do this without extra care
2370 * (in bss mode we had to make sure no-one tryed to associate when
2371 * we had just checked the ieee->state and we was going to start the
2372 * scan) beacause in ibss mode the ieee80211_new_net function, when
2373 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2374 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2375 * scan, that will stop at the first round because it sees the state
2376 * associated.
2378 if (ieee->state == IEEE80211_NOLINK)
2379 ieee80211_start_scan_syncro(ieee);
2381 /* the network definitively is not here.. create a new cell */
2382 if (ieee->state == IEEE80211_NOLINK){
2383 printk("creating new IBSS cell\n");
2384 if(!ieee->wap_set)
2385 ieee80211_randomize_cell(ieee);
2387 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2389 ieee->current_network.rates_len = 4;
2391 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2392 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2393 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2394 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2396 }else
2397 ieee->current_network.rates_len = 0;
2399 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2400 ieee->current_network.rates_ex_len = 8;
2402 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2403 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2404 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2405 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2406 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2407 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2408 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2409 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2411 ieee->rate = 108;
2412 }else{
2413 ieee->current_network.rates_ex_len = 0;
2414 ieee->rate = 22;
2417 // By default, WMM function will be disabled in IBSS mode
2418 ieee->current_network.QoS_Enable = 0;
2419 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2420 ieee->current_network.atim_window = 0;
2421 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2422 if(ieee->short_slot)
2423 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2427 ieee->state = IEEE80211_LINKED;
2429 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2430 ieee->link_change(ieee->dev);
2431 if(ieee->LedControlHandler != NULL)
2432 ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
2433 notify_wx_assoc_event(ieee);
2435 ieee80211_start_send_beacons(ieee);
2437 if (ieee->data_hard_resume)
2438 ieee->data_hard_resume(ieee->dev);
2439 netif_carrier_on(ieee->dev);
2441 up(&ieee->wx_sem);
2444 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2446 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2449 /* this is called only in user context, with wx_sem held */
2450 void ieee80211_start_bss(struct ieee80211_device *ieee)
2452 unsigned long flags;
2454 // Ref: 802.11d 11.1.3.3
2455 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2457 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2459 if(! ieee->bGlobalDomain)
2461 return;
2464 /* check if we have already found the net we
2465 * are interested in (if any).
2466 * if not (we are disassociated and we are not
2467 * in associating / authenticating phase) start the background scanning.
2469 ieee80211_softmac_check_all_nets(ieee);
2471 /* ensure no-one start an associating process (thus setting
2472 * the ieee->state to ieee80211_ASSOCIATING) while we
2473 * have just cheked it and we are going to enable scan.
2474 * The ieee80211_new_net function is always called with
2475 * lock held (from both ieee80211_softmac_check_all_nets and
2476 * the rx path), so we cannot be in the middle of such function
2478 spin_lock_irqsave(&ieee->lock, flags);
2480 if (ieee->state == IEEE80211_NOLINK){
2481 ieee->actscanning = true;
2482 ieee80211_start_scan(ieee);
2484 spin_unlock_irqrestore(&ieee->lock, flags);
2487 void ieee80211_link_change_wq(struct work_struct *work)
2489 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2490 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, link_change_wq);
2492 ieee->link_change(ieee->dev);
2494 /* called only in userspace context */
2495 void ieee80211_disassociate(struct ieee80211_device *ieee)
2499 netif_carrier_off(ieee->dev);
2500 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2501 ieee80211_reset_queue(ieee);
2503 if (ieee->data_hard_stop)
2504 ieee->data_hard_stop(ieee->dev);
2505 if(IS_DOT11D_ENABLE(ieee))
2506 Dot11d_Reset(ieee);
2507 ieee->state = IEEE80211_NOLINK;
2508 ieee->is_set_key = false;
2510 //LZM for usb dev crash.
2511 //ieee->link_change(ieee->dev);
2512 queue_delayed_work(ieee->wq, &ieee->link_change_wq, 0);
2514 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2515 notify_wx_assoc_event(ieee);
2519 void ieee80211_associate_retry_wq(struct work_struct *work)
2521 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2522 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2523 unsigned long flags;
2525 down(&ieee->wx_sem);
2526 if(!ieee->proto_started)
2527 goto exit;
2529 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2530 goto exit;
2532 /* until we do not set the state to IEEE80211_NOLINK
2533 * there are no possibility to have someone else trying
2534 * to start an association procdure (we get here with
2535 * ieee->state = IEEE80211_ASSOCIATING).
2536 * When we set the state to IEEE80211_NOLINK it is possible
2537 * that the RX path run an attempt to associate, but
2538 * both ieee80211_softmac_check_all_nets and the
2539 * RX path works with ieee->lock held so there are no
2540 * problems. If we are still disassociated then start a scan.
2541 * the lock here is necessary to ensure no one try to start
2542 * an association procedure when we have just checked the
2543 * state and we are going to start the scan.
2545 ieee->beinretry = true;
2546 ieee->state = IEEE80211_NOLINK;
2548 ieee80211_softmac_check_all_nets(ieee);
2550 spin_lock_irqsave(&ieee->lock, flags);
2552 if(ieee->state == IEEE80211_NOLINK)
2554 ieee->actscanning = true;
2555 ieee80211_start_scan(ieee);
2557 spin_unlock_irqrestore(&ieee->lock, flags);
2559 ieee->beinretry = false;
2560 exit:
2561 up(&ieee->wx_sem);
2564 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2566 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2568 struct sk_buff *skb;
2569 struct ieee80211_probe_response *b;
2571 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2573 if (!skb)
2574 return NULL;
2576 b = (struct ieee80211_probe_response *) skb->data;
2577 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2579 return skb;
2583 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2585 struct sk_buff *skb;
2586 struct ieee80211_probe_response *b;
2588 skb = ieee80211_get_beacon_(ieee);
2589 if(!skb)
2590 return NULL;
2592 b = (struct ieee80211_probe_response *) skb->data;
2593 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2595 if (ieee->seq_ctrl[0] == 0xFFF)
2596 ieee->seq_ctrl[0] = 0;
2597 else
2598 ieee->seq_ctrl[0]++;
2600 return skb;
2603 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2605 ieee->sync_scan_hurryup = 1;
2606 down(&ieee->wx_sem);
2607 ieee80211_stop_protocol(ieee);
2608 up(&ieee->wx_sem);
2612 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2614 if (!ieee->proto_started)
2615 return;
2617 ieee->proto_started = 0;
2619 ieee80211_stop_send_beacons(ieee);
2620 del_timer_sync(&ieee->associate_timer);
2621 cancel_delayed_work(&ieee->associate_retry_wq);
2622 cancel_delayed_work(&ieee->start_ibss_wq);
2623 cancel_delayed_work(&ieee->link_change_wq);
2624 ieee80211_stop_scan(ieee);
2626 ieee80211_disassociate(ieee);
2627 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2630 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2632 ieee->sync_scan_hurryup = 0;
2633 down(&ieee->wx_sem);
2634 ieee80211_start_protocol(ieee);
2635 up(&ieee->wx_sem);
2638 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2640 short ch = 0;
2641 int i = 0;
2642 if (ieee->proto_started)
2643 return;
2645 ieee->proto_started = 1;
2647 if (ieee->current_network.channel == 0){
2649 ch++;
2650 if (ch > MAX_CHANNEL_NUMBER)
2651 return; /* no channel found */
2652 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2653 ieee->current_network.channel = ch;
2656 if (ieee->current_network.beacon_interval == 0)
2657 ieee->current_network.beacon_interval = 100;
2658 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2659 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2661 for(i = 0; i < 17; i++) {
2662 ieee->last_rxseq_num[i] = -1;
2663 ieee->last_rxfrag_num[i] = -1;
2664 ieee->last_packet_time[i] = 0;
2667 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2670 /* if the user set the MAC of the ad-hoc cell and then
2671 * switch to managed mode, shall we make sure that association
2672 * attempts does not fail just because the user provide the essid
2673 * and the nic is still checking for the AP MAC ??
2675 if (ieee->iw_mode == IW_MODE_INFRA)
2676 ieee80211_start_bss(ieee);
2678 else if (ieee->iw_mode == IW_MODE_ADHOC)
2679 ieee80211_start_ibss(ieee);
2681 else if (ieee->iw_mode == IW_MODE_MASTER)
2682 ieee80211_start_master_bss(ieee);
2684 else if(ieee->iw_mode == IW_MODE_MONITOR)
2685 ieee80211_start_monitor_mode(ieee);
2689 #define DRV_NAME "Ieee80211"
2690 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2692 int i;
2693 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2695 ieee->state = IEEE80211_NOLINK;
2696 ieee->sync_scan_hurryup = 0;
2697 for(i = 0; i < 5; i++) {
2698 ieee->seq_ctrl[i] = 0;
2700 ieee->pDot11dInfo = kmalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2701 if (!ieee->pDot11dInfo)
2702 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2703 memset(ieee->pDot11dInfo, 0, sizeof(RT_DOT11D_INFO));
2704 //added for AP roaming
2705 ieee->LinkDetectInfo.SlotNum = 2;
2706 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2707 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2709 ieee->assoc_id = 0;
2710 ieee->queue_stop = 0;
2711 ieee->scanning = 0;
2712 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2713 ieee->wap_set = 0;
2714 ieee->ssid_set = 0;
2715 ieee->proto_started = 0;
2716 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2717 ieee->rate = 22;
2718 ieee->ps = IEEE80211_PS_DISABLED;
2719 ieee->sta_sleep = 0;
2720 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2721 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2722 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2723 //added by amy
2724 ieee->actscanning = false;
2725 ieee->beinretry = false;
2726 ieee->is_set_key = false;
2727 init_mgmt_queue(ieee);
2729 ieee->sta_edca_param[0] = 0x0000A403;
2730 ieee->sta_edca_param[1] = 0x0000A427;
2731 ieee->sta_edca_param[2] = 0x005E4342;
2732 ieee->sta_edca_param[3] = 0x002F3262;
2733 ieee->aggregation = true;
2734 ieee->enable_rx_imm_BA = 1;
2735 ieee->tx_pending.txb = NULL;
2737 init_timer(&ieee->associate_timer);
2738 ieee->associate_timer.data = (unsigned long)ieee;
2739 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2741 init_timer(&ieee->beacon_timer);
2742 ieee->beacon_timer.data = (unsigned long) ieee;
2743 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2745 #ifdef PF_SYNCTHREAD
2746 ieee->wq = create_workqueue(DRV_NAME,0);
2747 #else
2748 ieee->wq = create_workqueue(DRV_NAME);
2749 #endif
2751 INIT_DELAYED_WORK(&ieee->link_change_wq,ieee80211_link_change_wq);
2752 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2753 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2754 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2755 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2756 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2757 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2759 sema_init(&ieee->wx_sem, 1);
2760 sema_init(&ieee->scan_sem, 1);
2762 spin_lock_init(&ieee->mgmt_tx_lock);
2763 spin_lock_init(&ieee->beacon_lock);
2765 tasklet_init(&ieee->ps_task,
2766 (void(*)(unsigned long)) ieee80211_sta_ps,
2767 (unsigned long)ieee);
2771 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2773 down(&ieee->wx_sem);
2774 if(NULL != ieee->pDot11dInfo)
2776 kfree(ieee->pDot11dInfo);
2777 ieee->pDot11dInfo = NULL;
2779 del_timer_sync(&ieee->associate_timer);
2781 cancel_delayed_work(&ieee->associate_retry_wq);
2782 destroy_workqueue(ieee->wq);
2784 up(&ieee->wx_sem);
2787 /********************************************************
2788 * Start of WPA code. *
2789 * this is stolen from the ipw2200 driver *
2790 ********************************************************/
2793 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2795 /* This is called when wpa_supplicant loads and closes the driver
2796 * interface. */
2797 printk("%s WPA\n",value ? "enabling" : "disabling");
2798 ieee->wpa_enabled = value;
2799 memset(ieee->ap_mac_addr, 0, 6); //reset ap_mac_addr everytime it starts wpa.
2800 return 0;
2804 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2806 /* make sure WPA is enabled */
2807 ieee80211_wpa_enable(ieee, 1);
2809 ieee80211_disassociate(ieee);
2813 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2816 int ret = 0;
2818 switch (command) {
2819 case IEEE_MLME_STA_DEAUTH:
2820 // silently ignore
2821 break;
2823 case IEEE_MLME_STA_DISASSOC:
2824 ieee80211_disassociate(ieee);
2825 break;
2827 default:
2828 printk("Unknown MLME request: %d\n", command);
2829 ret = -EOPNOTSUPP;
2832 return ret;
2836 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2837 struct ieee_param *param, int plen)
2839 u8 *buf;
2841 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2842 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2843 return -EINVAL;
2845 if (param->u.wpa_ie.len) {
2846 buf = kmalloc(param->u.wpa_ie.len, GFP_KERNEL);
2847 if (buf == NULL)
2848 return -ENOMEM;
2850 memcpy(buf, param->u.wpa_ie.data, param->u.wpa_ie.len);
2851 kfree(ieee->wpa_ie);
2852 ieee->wpa_ie = buf;
2853 ieee->wpa_ie_len = param->u.wpa_ie.len;
2854 } else {
2855 kfree(ieee->wpa_ie);
2856 ieee->wpa_ie = NULL;
2857 ieee->wpa_ie_len = 0;
2860 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2861 return 0;
2864 #define AUTH_ALG_OPEN_SYSTEM 0x1
2865 #define AUTH_ALG_SHARED_KEY 0x2
2866 #define AUTH_ALG_LEAP 0x4
2867 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2870 struct ieee80211_security sec = {
2871 .flags = SEC_AUTH_MODE,
2873 int ret = 0;
2875 if (value & AUTH_ALG_SHARED_KEY) {
2876 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2877 ieee->open_wep = 0;
2878 ieee->auth_mode = 1;
2879 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2880 sec.auth_mode = WLAN_AUTH_OPEN;
2881 ieee->open_wep = 1;
2882 ieee->auth_mode = 0;
2884 else if (value & AUTH_ALG_LEAP){
2885 sec.auth_mode = RTL_WLAN_AUTH_LEAP;
2886 ieee->open_wep = 1;
2887 ieee->auth_mode = 2;
2891 if (ieee->set_security)
2892 ieee->set_security(ieee->dev, &sec);
2893 //else
2894 // ret = -EOPNOTSUPP;
2896 return ret;
2899 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2901 int ret=0;
2902 unsigned long flags;
2904 switch (name) {
2905 case IEEE_PARAM_WPA_ENABLED:
2906 ret = ieee80211_wpa_enable(ieee, value);
2907 break;
2909 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2910 ieee->tkip_countermeasures=value;
2911 break;
2913 case IEEE_PARAM_DROP_UNENCRYPTED: {
2914 /* HACK:
2916 * wpa_supplicant calls set_wpa_enabled when the driver
2917 * is loaded and unloaded, regardless of if WPA is being
2918 * used. No other calls are made which can be used to
2919 * determine if encryption will be used or not prior to
2920 * association being expected. If encryption is not being
2921 * used, drop_unencrypted is set to false, else true -- we
2922 * can use this to determine if the CAP_PRIVACY_ON bit should
2923 * be set.
2925 struct ieee80211_security sec = {
2926 .flags = SEC_ENABLED,
2927 .enabled = value,
2929 ieee->drop_unencrypted = value;
2930 /* We only change SEC_LEVEL for open mode. Others
2931 * are set by ipw_wpa_set_encryption.
2933 if (!value) {
2934 sec.flags |= SEC_LEVEL;
2935 sec.level = SEC_LEVEL_0;
2937 else {
2938 sec.flags |= SEC_LEVEL;
2939 sec.level = SEC_LEVEL_1;
2941 if (ieee->set_security)
2942 ieee->set_security(ieee->dev, &sec);
2943 break;
2946 case IEEE_PARAM_PRIVACY_INVOKED:
2947 ieee->privacy_invoked=value;
2948 break;
2950 case IEEE_PARAM_AUTH_ALGS:
2951 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2952 break;
2954 case IEEE_PARAM_IEEE_802_1X:
2955 ieee->ieee802_1x=value;
2956 break;
2957 case IEEE_PARAM_WPAX_SELECT:
2958 // added for WPA2 mixed mode
2959 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2960 ieee->wpax_type_set = 1;
2961 ieee->wpax_type_notify = value;
2962 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
2963 break;
2965 default:
2966 printk("Unknown WPA param: %d\n",name);
2967 ret = -EOPNOTSUPP;
2970 return ret;
2973 /* implementation borrowed from hostap driver */
2975 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2976 struct ieee_param *param, int param_len)
2978 int ret = 0;
2980 struct ieee80211_crypto_ops *ops;
2981 struct ieee80211_crypt_data **crypt;
2983 struct ieee80211_security sec = {
2984 .flags = 0,
2987 param->u.crypt.err = 0;
2988 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2990 if (param_len !=
2991 (int) ((char *) param->u.crypt.key - (char *) param) +
2992 param->u.crypt.key_len) {
2993 printk("Len mismatch %d, %d\n", param_len,
2994 param->u.crypt.key_len);
2995 return -EINVAL;
2997 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2998 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2999 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3000 if (param->u.crypt.idx >= WEP_KEYS)
3001 return -EINVAL;
3002 crypt = &ieee->crypt[param->u.crypt.idx];
3003 } else {
3004 return -EINVAL;
3007 if (strcmp(param->u.crypt.alg, "none") == 0) {
3008 if (crypt) {
3009 sec.enabled = 0;
3010 // FIXME FIXME
3011 //sec.encrypt = 0;
3012 sec.level = SEC_LEVEL_0;
3013 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3014 ieee80211_crypt_delayed_deinit(ieee, crypt);
3016 goto done;
3018 sec.enabled = 1;
3019 // FIXME FIXME
3020 // sec.encrypt = 1;
3021 sec.flags |= SEC_ENABLED;
3023 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3024 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3025 strcmp(param->u.crypt.alg, "TKIP"))
3026 goto skip_host_crypt;
3028 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3029 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3030 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3031 /* set WEP40 first, it will be modified according to WEP104 or
3032 * WEP40 at other place */
3033 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3034 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3035 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3036 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3037 if (ops == NULL) {
3038 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3039 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3040 ret = -EINVAL;
3041 goto done;
3044 if (*crypt == NULL || (*crypt)->ops != ops) {
3045 struct ieee80211_crypt_data *new_crypt;
3047 ieee80211_crypt_delayed_deinit(ieee, crypt);
3049 new_crypt = (struct ieee80211_crypt_data *)
3050 kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3051 if (new_crypt == NULL) {
3052 ret = -ENOMEM;
3053 goto done;
3055 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3056 new_crypt->ops = ops;
3058 if (new_crypt->ops)
3059 new_crypt->priv =
3060 new_crypt->ops->init(param->u.crypt.idx);
3062 if (new_crypt->priv == NULL) {
3063 kfree(new_crypt);
3064 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3065 ret = -EINVAL;
3066 goto done;
3069 *crypt = new_crypt;
3072 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3073 (*crypt)->ops->set_key(param->u.crypt.key,
3074 param->u.crypt.key_len, param->u.crypt.seq,
3075 (*crypt)->priv) < 0) {
3076 printk("key setting failed\n");
3077 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3078 ret = -EINVAL;
3079 goto done;
3082 skip_host_crypt:
3083 if (param->u.crypt.set_tx) {
3084 ieee->tx_keyidx = param->u.crypt.idx;
3085 sec.active_key = param->u.crypt.idx;
3086 sec.flags |= SEC_ACTIVE_KEY;
3087 } else
3088 sec.flags &= ~SEC_ACTIVE_KEY;
3090 if (param->u.crypt.alg != NULL) {
3091 memcpy(sec.keys[param->u.crypt.idx],
3092 param->u.crypt.key,
3093 param->u.crypt.key_len);
3094 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3095 sec.flags |= (1 << param->u.crypt.idx);
3097 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3098 sec.flags |= SEC_LEVEL;
3099 sec.level = SEC_LEVEL_1;
3100 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3101 sec.flags |= SEC_LEVEL;
3102 sec.level = SEC_LEVEL_2;
3103 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3104 sec.flags |= SEC_LEVEL;
3105 sec.level = SEC_LEVEL_3;
3108 done:
3109 if (ieee->set_security)
3110 ieee->set_security(ieee->dev, &sec);
3112 /* Do not reset port if card is in Managed mode since resetting will
3113 * generate new IEEE 802.11 authentication which may end up in looping
3114 * with IEEE 802.1X. If your hardware requires a reset after WEP
3115 * configuration (for example... Prism2), implement the reset_port in
3116 * the callbacks structures used to initialize the 802.11 stack. */
3117 if (ieee->reset_on_keychange &&
3118 ieee->iw_mode != IW_MODE_INFRA &&
3119 ieee->reset_port &&
3120 ieee->reset_port(ieee->dev)) {
3121 printk("reset_port failed\n");
3122 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3123 return -EINVAL;
3126 return ret;
3129 inline struct sk_buff *ieee80211_disassociate_skb(
3130 struct ieee80211_network *beacon,
3131 struct ieee80211_device *ieee,
3132 u8 asRsn)
3134 struct sk_buff *skb;
3135 struct ieee80211_disassoc *disass;
3137 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3138 if (!skb)
3139 return NULL;
3141 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3142 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3143 disass->header.duration_id = 0;
3145 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3146 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3147 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3149 disass->reason = asRsn;
3150 return skb;
3154 void
3155 SendDisassociation(
3156 struct ieee80211_device *ieee,
3157 u8* asSta,
3158 u8 asRsn
3161 struct ieee80211_network *beacon = &ieee->current_network;
3162 struct sk_buff *skb;
3163 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3164 if (skb){
3165 softmac_mgmt_xmit(skb, ieee);
3166 //dev_kfree_skb_any(skb);//edit by thomas
3170 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3172 struct ieee_param *param;
3173 int ret=0;
3175 down(&ieee->wx_sem);
3176 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3178 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3179 ret = -EINVAL;
3180 goto out;
3183 param = (struct ieee_param *)kmalloc(p->length, GFP_KERNEL);
3184 if (param == NULL){
3185 ret = -ENOMEM;
3186 goto out;
3188 if (copy_from_user(param, p->pointer, p->length)) {
3189 kfree(param);
3190 ret = -EFAULT;
3191 goto out;
3194 switch (param->cmd) {
3196 case IEEE_CMD_SET_WPA_PARAM:
3197 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3198 param->u.wpa_param.value);
3199 break;
3201 case IEEE_CMD_SET_WPA_IE:
3202 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3203 break;
3205 case IEEE_CMD_SET_ENCRYPTION:
3206 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3207 break;
3209 case IEEE_CMD_MLME:
3210 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3211 param->u.mlme.reason_code);
3212 break;
3214 default:
3215 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3216 ret = -EOPNOTSUPP;
3217 break;
3220 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3221 ret = -EFAULT;
3223 kfree(param);
3224 out:
3225 up(&ieee->wx_sem);
3227 return ret;
3230 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3232 union iwreq_data wrqu;
3233 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3234 if (ieee->state == IEEE80211_LINKED)
3235 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3236 else
3237 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3238 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);