Remove unneeded version.h includes from drivers/staging/rtl*/
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / rtl8192u / ieee80211 / ieee80211_softmac.c
blob2fb407226d4e9a822f08602dfffeb5b1430314af
1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
13 * released under the GPL
17 #include "ieee80211.h"
19 #include <linux/random.h>
20 #include <linux/delay.h>
21 #include <linux/slab.h>
22 #include <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 #ifdef THOMAS_TURBO
131 void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p) {
132 u8 *tag = *tag_p;
134 *tag++ = MFIE_TYPE_GENERIC; //0
135 *tag++ = 7;
136 *tag++ = 0x00;
137 *tag++ = 0xe0;
138 *tag++ = 0x4c;
139 *tag++ = 0x01;//5
140 *tag++ = 0x02;
141 *tag++ = 0x11;
142 *tag++ = 0x00;
144 *tag_p = tag;
145 printk(KERN_ALERT "This is enable turbo mode IE process\n");
147 #endif
149 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
151 int nh;
152 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
155 * if the queue is full but we have newer frames then
156 * just overwrites the oldest.
158 * if (nh == ieee->mgmt_queue_tail)
159 * return -1;
161 ieee->mgmt_queue_head = nh;
162 ieee->mgmt_queue_ring[nh] = skb;
164 //return 0;
167 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
169 struct sk_buff *ret;
171 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
172 return NULL;
174 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
176 ieee->mgmt_queue_tail =
177 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
179 return ret;
182 void init_mgmt_queue(struct ieee80211_device *ieee)
184 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
187 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
189 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
190 u8 rate;
192 // 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M.
193 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
194 rate = 0x0c;
195 else
196 rate = ieee->basic_rate & 0x7f;
198 if(rate == 0){
199 // 2005.01.26, by rcnjko.
200 if(ieee->mode == IEEE_A||
201 ieee->mode== IEEE_N_5G||
202 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
203 rate = 0x0c;
204 else
205 rate = 0x02;
209 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
210 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
212 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
213 rate = 0x0c;
214 else
215 rate = 0x02;
218 return rate;
222 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
224 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
226 unsigned long flags;
227 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
228 struct ieee80211_hdr_3addr *header=
229 (struct ieee80211_hdr_3addr *) skb->data;
231 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
232 spin_lock_irqsave(&ieee->lock, flags);
234 /* called with 2nd param 0, no mgmt lock required */
235 ieee80211_sta_wakeup(ieee,0);
237 tcb_desc->queue_index = MGNT_QUEUE;
238 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
239 tcb_desc->RATRIndex = 7;
240 tcb_desc->bTxDisableRateFallBack = 1;
241 tcb_desc->bTxUseDriverAssingedRate = 1;
243 if(single){
244 if(ieee->queue_stop){
245 enqueue_mgmt(ieee,skb);
246 }else{
247 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
249 if (ieee->seq_ctrl[0] == 0xFFF)
250 ieee->seq_ctrl[0] = 0;
251 else
252 ieee->seq_ctrl[0]++;
254 /* avoid watchdog triggers */
255 ieee->dev->trans_start = jiffies;
256 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
257 //dev_kfree_skb_any(skb);//edit by thomas
260 spin_unlock_irqrestore(&ieee->lock, flags);
261 }else{
262 spin_unlock_irqrestore(&ieee->lock, flags);
263 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
265 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
267 if (ieee->seq_ctrl[0] == 0xFFF)
268 ieee->seq_ctrl[0] = 0;
269 else
270 ieee->seq_ctrl[0]++;
272 /* check wether the managed packet queued greater than 5 */
273 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
274 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
275 (ieee->queue_stop) ) {
276 /* insert the skb packet to the management queue */
277 /* as for the completion function, it does not need
278 * to check it any more.
279 * */
280 printk("%s():insert to waitqueue!\n",__FUNCTION__);
281 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
282 } else {
283 //printk("TX packet!\n");
284 ieee->softmac_hard_start_xmit(skb,ieee->dev);
285 //dev_kfree_skb_any(skb);//edit by thomas
287 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
291 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
294 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
295 struct ieee80211_hdr_3addr *header =
296 (struct ieee80211_hdr_3addr *) skb->data;
299 if(single){
301 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
303 if (ieee->seq_ctrl[0] == 0xFFF)
304 ieee->seq_ctrl[0] = 0;
305 else
306 ieee->seq_ctrl[0]++;
308 /* avoid watchdog triggers */
309 ieee->dev->trans_start = jiffies;
310 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
312 }else{
314 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
316 if (ieee->seq_ctrl[0] == 0xFFF)
317 ieee->seq_ctrl[0] = 0;
318 else
319 ieee->seq_ctrl[0]++;
321 ieee->softmac_hard_start_xmit(skb,ieee->dev);
324 //dev_kfree_skb_any(skb);//edit by thomas
327 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
329 unsigned int len,rate_len;
330 u8 *tag;
331 struct sk_buff *skb;
332 struct ieee80211_probe_request *req;
334 len = ieee->current_network.ssid_len;
336 rate_len = ieee80211_MFIE_rate_len(ieee);
338 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
339 2 + len + rate_len + ieee->tx_headroom);
340 if (!skb)
341 return NULL;
343 skb_reserve(skb, ieee->tx_headroom);
345 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
346 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
347 req->header.duration_id = 0; //FIXME: is this OK ?
349 memset(req->header.addr1, 0xff, ETH_ALEN);
350 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
351 memset(req->header.addr3, 0xff, ETH_ALEN);
353 tag = (u8 *) skb_put(skb,len+2+rate_len);
355 *tag++ = MFIE_TYPE_SSID;
356 *tag++ = len;
357 memcpy(tag, ieee->current_network.ssid, len);
358 tag += len;
360 ieee80211_MFIE_Brate(ieee,&tag);
361 ieee80211_MFIE_Grate(ieee,&tag);
362 return skb;
365 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
366 void ieee80211_send_beacon(struct ieee80211_device *ieee)
368 struct sk_buff *skb;
369 if(!ieee->ieee_up)
370 return;
371 //unsigned long flags;
372 skb = ieee80211_get_beacon_(ieee);
374 if (skb){
375 softmac_mgmt_xmit(skb, ieee);
376 ieee->softmac_stats.tx_beacons++;
377 //dev_kfree_skb_any(skb);//edit by thomas
379 // ieee->beacon_timer.expires = jiffies +
380 // (MSECS( ieee->current_network.beacon_interval -5));
382 //spin_lock_irqsave(&ieee->beacon_lock,flags);
383 if(ieee->beacon_txing && ieee->ieee_up){
384 // if(!timer_pending(&ieee->beacon_timer))
385 // add_timer(&ieee->beacon_timer);
386 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
388 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
392 void ieee80211_send_beacon_cb(unsigned long _ieee)
394 struct ieee80211_device *ieee =
395 (struct ieee80211_device *) _ieee;
396 unsigned long flags;
398 spin_lock_irqsave(&ieee->beacon_lock, flags);
399 ieee80211_send_beacon(ieee);
400 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
404 void ieee80211_send_probe(struct ieee80211_device *ieee)
406 struct sk_buff *skb;
408 skb = ieee80211_probe_req(ieee);
409 if (skb){
410 softmac_mgmt_xmit(skb, ieee);
411 ieee->softmac_stats.tx_probe_rq++;
412 //dev_kfree_skb_any(skb);//edit by thomas
416 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
418 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
419 ieee80211_send_probe(ieee);
420 ieee80211_send_probe(ieee);
424 /* this performs syncro scan blocking the caller until all channels
425 * in the allowed channel map has been checked.
427 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
429 short ch = 0;
430 u8 channel_map[MAX_CHANNEL_NUMBER+1];
431 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
432 down(&ieee->scan_sem);
434 while(1)
438 ch++;
439 if (ch > MAX_CHANNEL_NUMBER)
440 goto out; /* scan completed */
441 }while(!channel_map[ch]);
443 /* this function can be called in two situations
444 * 1- We have switched to ad-hoc mode and we are
445 * performing a complete syncro scan before conclude
446 * there are no interesting cell and to create a
447 * new one. In this case the link state is
448 * IEEE80211_NOLINK until we found an interesting cell.
449 * If so the ieee8021_new_net, called by the RX path
450 * will set the state to IEEE80211_LINKED, so we stop
451 * scanning
452 * 2- We are linked and the root uses run iwlist scan.
453 * So we switch to IEEE80211_LINKED_SCANNING to remember
454 * that we are still logically linked (not interested in
455 * new network events, despite for updating the net list,
456 * but we are temporarly 'unlinked' as the driver shall
457 * not filter RX frames and the channel is changing.
458 * So the only situation in witch are interested is to check
459 * if the state become LINKED because of the #1 situation
462 if (ieee->state == IEEE80211_LINKED)
463 goto out;
464 ieee->set_chan(ieee->dev, ch);
465 if(channel_map[ch] == 1)
466 ieee80211_send_probe_requests(ieee);
468 /* this prevent excessive time wait when we
469 * need to wait for a syncro scan to end..
471 if(ieee->state < IEEE80211_LINKED)
473 else
474 if (ieee->sync_scan_hurryup)
475 goto out;
478 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
481 out:
482 if(ieee->state < IEEE80211_LINKED){
483 ieee->actscanning = false;
484 up(&ieee->scan_sem);
486 else{
487 ieee->sync_scan_hurryup = 0;
488 if(IS_DOT11D_ENABLE(ieee))
489 DOT11D_ScanComplete(ieee);
490 up(&ieee->scan_sem);
495 void ieee80211_softmac_scan_wq(struct work_struct *work)
497 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
498 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
499 static short watchdog = 0;
500 u8 channel_map[MAX_CHANNEL_NUMBER+1];
501 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
502 if(!ieee->ieee_up)
503 return;
504 down(&ieee->scan_sem);
506 ieee->current_network.channel =
507 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
508 if (watchdog++ > MAX_CHANNEL_NUMBER)
510 //if current channel is not in channel map, set to default channel.
511 if (!channel_map[ieee->current_network.channel]) {
512 ieee->current_network.channel = 6;
513 goto out; /* no good chans */
516 }while(!channel_map[ieee->current_network.channel]);
517 if (ieee->scanning == 0 )
518 goto out;
519 ieee->set_chan(ieee->dev, ieee->current_network.channel);
520 if(channel_map[ieee->current_network.channel] == 1)
521 ieee80211_send_probe_requests(ieee);
524 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
526 up(&ieee->scan_sem);
527 return;
528 out:
529 if(IS_DOT11D_ENABLE(ieee))
530 DOT11D_ScanComplete(ieee);
531 ieee->actscanning = false;
532 watchdog = 0;
533 ieee->scanning = 0;
534 up(&ieee->scan_sem);
539 void ieee80211_beacons_start(struct ieee80211_device *ieee)
541 unsigned long flags;
542 spin_lock_irqsave(&ieee->beacon_lock,flags);
544 ieee->beacon_txing = 1;
545 ieee80211_send_beacon(ieee);
547 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
550 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
552 unsigned long flags;
554 spin_lock_irqsave(&ieee->beacon_lock,flags);
556 ieee->beacon_txing = 0;
557 del_timer_sync(&ieee->beacon_timer);
559 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
564 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
566 if(ieee->stop_send_beacons)
567 ieee->stop_send_beacons(ieee->dev);
568 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
569 ieee80211_beacons_stop(ieee);
573 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
575 if(ieee->start_send_beacons)
576 ieee->start_send_beacons(ieee->dev,ieee->basic_rate);
577 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
578 ieee80211_beacons_start(ieee);
582 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
584 // unsigned long flags;
586 //ieee->sync_scan_hurryup = 1;
588 down(&ieee->scan_sem);
589 // spin_lock_irqsave(&ieee->lock, flags);
591 if (ieee->scanning == 1){
592 ieee->scanning = 0;
594 cancel_delayed_work(&ieee->softmac_scan_wq);
597 // spin_unlock_irqrestore(&ieee->lock, flags);
598 up(&ieee->scan_sem);
601 void ieee80211_stop_scan(struct ieee80211_device *ieee)
603 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
604 ieee80211_softmac_stop_scan(ieee);
605 else
606 ieee->stop_scan(ieee->dev);
609 /* called with ieee->lock held */
610 void ieee80211_start_scan(struct ieee80211_device *ieee)
612 if(IS_DOT11D_ENABLE(ieee) )
614 if(IS_COUNTRY_IE_VALID(ieee))
616 RESET_CIE_WATCHDOG(ieee);
619 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
620 if (ieee->scanning == 0){
621 ieee->scanning = 1;
622 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
624 }else
625 ieee->start_scan(ieee->dev);
629 /* called with wx_sem held */
630 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
632 if(IS_DOT11D_ENABLE(ieee) )
634 if(IS_COUNTRY_IE_VALID(ieee))
636 RESET_CIE_WATCHDOG(ieee);
639 ieee->sync_scan_hurryup = 0;
640 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
641 ieee80211_softmac_scan_syncro(ieee);
642 else
643 ieee->scan_syncro(ieee->dev);
647 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
648 struct ieee80211_device *ieee, int challengelen)
650 struct sk_buff *skb;
651 struct ieee80211_authentication *auth;
652 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
655 skb = dev_alloc_skb(len);
656 if (!skb) return NULL;
658 skb_reserve(skb, ieee->tx_headroom);
659 auth = (struct ieee80211_authentication *)
660 skb_put(skb, sizeof(struct ieee80211_authentication));
662 auth->header.frame_ctl = IEEE80211_STYPE_AUTH;
663 if (challengelen) auth->header.frame_ctl |= IEEE80211_FCTL_WEP;
665 auth->header.duration_id = 0x013a; //FIXME
667 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
668 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
669 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
671 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
672 if(ieee->auth_mode == 0)
673 auth->algorithm = WLAN_AUTH_OPEN;
674 else if(ieee->auth_mode == 1)
675 auth->algorithm = WLAN_AUTH_SHARED_KEY;
676 else if(ieee->auth_mode == 2)
677 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
678 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
679 auth->transaction = cpu_to_le16(ieee->associate_seq);
680 ieee->associate_seq++;
682 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
684 return skb;
689 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
691 u8 *tag;
692 int beacon_size;
693 struct ieee80211_probe_response *beacon_buf;
694 struct sk_buff *skb = NULL;
695 int encrypt;
696 int atim_len,erp_len;
697 struct ieee80211_crypt_data* crypt;
699 char *ssid = ieee->current_network.ssid;
700 int ssid_len = ieee->current_network.ssid_len;
701 int rate_len = ieee->current_network.rates_len+2;
702 int rate_ex_len = ieee->current_network.rates_ex_len;
703 int wpa_ie_len = ieee->wpa_ie_len;
704 u8 erpinfo_content = 0;
706 u8* tmp_ht_cap_buf;
707 u8 tmp_ht_cap_len=0;
708 u8* tmp_ht_info_buf;
709 u8 tmp_ht_info_len=0;
710 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
711 u8* tmp_generic_ie_buf=NULL;
712 u8 tmp_generic_ie_len=0;
714 if(rate_ex_len > 0) rate_ex_len+=2;
716 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
717 atim_len = 4;
718 else
719 atim_len = 0;
721 if(ieee80211_is_54g(ieee->current_network))
722 erp_len = 3;
723 else
724 erp_len = 0;
727 crypt = ieee->crypt[ieee->tx_keyidx];
730 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
731 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
732 //HT ralated element
733 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
734 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
735 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
736 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
737 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
738 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
741 if(pHTInfo->bRegRT2RTAggregation)
743 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
744 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
745 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
747 // 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);
748 beacon_size = sizeof(struct ieee80211_probe_response)+2+
749 ssid_len
750 +3 //channel
751 +rate_len
752 +rate_ex_len
753 +atim_len
754 +erp_len
755 +wpa_ie_len
756 // +tmp_ht_cap_len
757 // +tmp_ht_info_len
758 // +tmp_generic_ie_len
759 // +wmm_len+2
760 +ieee->tx_headroom;
761 skb = dev_alloc_skb(beacon_size);
762 if (!skb)
763 return NULL;
764 skb_reserve(skb, ieee->tx_headroom);
765 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
766 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
767 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
768 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
770 beacon_buf->header.duration_id = 0; //FIXME
771 beacon_buf->beacon_interval =
772 cpu_to_le16(ieee->current_network.beacon_interval);
773 beacon_buf->capability =
774 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
775 beacon_buf->capability |=
776 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
778 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
779 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
781 crypt = ieee->crypt[ieee->tx_keyidx];
782 if (encrypt)
783 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
786 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
787 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
788 beacon_buf->info_element[0].len = ssid_len;
790 tag = (u8*) beacon_buf->info_element[0].data;
792 memcpy(tag, ssid, ssid_len);
794 tag += ssid_len;
796 *(tag++) = MFIE_TYPE_RATES;
797 *(tag++) = rate_len-2;
798 memcpy(tag,ieee->current_network.rates,rate_len-2);
799 tag+=rate_len-2;
801 *(tag++) = MFIE_TYPE_DS_SET;
802 *(tag++) = 1;
803 *(tag++) = ieee->current_network.channel;
805 if(atim_len){
806 u16 val16;
807 *(tag++) = MFIE_TYPE_IBSS_SET;
808 *(tag++) = 2;
809 //*((u16*)(tag)) = cpu_to_le16(ieee->current_network.atim_window);
810 val16 = cpu_to_le16(ieee->current_network.atim_window);
811 memcpy((u8 *)tag, (u8 *)&val16, 2);
812 tag+=2;
815 if(erp_len){
816 *(tag++) = MFIE_TYPE_ERP;
817 *(tag++) = 1;
818 *(tag++) = erpinfo_content;
820 if(rate_ex_len){
821 *(tag++) = MFIE_TYPE_RATES_EX;
822 *(tag++) = rate_ex_len-2;
823 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
824 tag+=rate_ex_len-2;
827 if (wpa_ie_len)
829 if (ieee->iw_mode == IW_MODE_ADHOC)
830 {//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
831 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
833 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
834 tag += wpa_ie_len;
837 //skb->dev = ieee->dev;
838 return skb;
842 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
844 struct sk_buff *skb;
845 u8* tag;
847 struct ieee80211_crypt_data* crypt;
848 struct ieee80211_assoc_response_frame *assoc;
849 short encrypt;
851 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
852 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
854 skb = dev_alloc_skb(len);
856 if (!skb)
857 return NULL;
859 skb_reserve(skb, ieee->tx_headroom);
861 assoc = (struct ieee80211_assoc_response_frame *)
862 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
864 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
865 memcpy(assoc->header.addr1, dest,ETH_ALEN);
866 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
867 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
868 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
869 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
872 if(ieee->short_slot)
873 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
875 if (ieee->host_encrypt)
876 crypt = ieee->crypt[ieee->tx_keyidx];
877 else crypt = NULL;
879 encrypt = ( crypt && crypt->ops);
881 if (encrypt)
882 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
884 assoc->status = 0;
885 assoc->aid = cpu_to_le16(ieee->assoc_id);
886 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
887 else ieee->assoc_id++;
889 tag = (u8*) skb_put(skb, rate_len);
891 ieee80211_MFIE_Brate(ieee, &tag);
892 ieee80211_MFIE_Grate(ieee, &tag);
894 return skb;
897 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
899 struct sk_buff *skb;
900 struct ieee80211_authentication *auth;
901 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
903 skb = dev_alloc_skb(len);
905 if (!skb)
906 return NULL;
908 skb->len = sizeof(struct ieee80211_authentication);
910 auth = (struct ieee80211_authentication *)skb->data;
912 auth->status = cpu_to_le16(status);
913 auth->transaction = cpu_to_le16(2);
914 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
916 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
917 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
918 memcpy(auth->header.addr1, dest, ETH_ALEN);
919 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
920 return skb;
925 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
927 struct sk_buff *skb;
928 struct ieee80211_hdr_3addr* hdr;
930 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
932 if (!skb)
933 return NULL;
935 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
937 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
938 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
939 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
941 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
942 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
943 (pwr ? IEEE80211_FCTL_PM:0));
945 return skb;
951 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
953 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
955 if (buf)
956 softmac_mgmt_xmit(buf, ieee);
960 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
962 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
964 if (buf)
965 softmac_mgmt_xmit(buf, ieee);
969 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
973 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
974 if (buf)
975 softmac_mgmt_xmit(buf, ieee);
979 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
981 struct sk_buff *skb;
982 //unsigned long flags;
984 struct ieee80211_assoc_request_frame *hdr;
985 u8 *tag;//,*rsn_ie;
986 //short info_addr = 0;
987 //int i;
988 //u16 suite_count = 0;
989 //u8 suit_select = 0;
990 //unsigned int wpa_len = beacon->wpa_ie_len;
991 //for HT
992 u8* ht_cap_buf = NULL;
993 u8 ht_cap_len=0;
994 u8* realtek_ie_buf=NULL;
995 u8 realtek_ie_len=0;
996 int wpa_ie_len= ieee->wpa_ie_len;
997 unsigned int ckip_ie_len=0;
998 unsigned int ccxrm_ie_len=0;
999 unsigned int cxvernum_ie_len=0;
1000 struct ieee80211_crypt_data* crypt;
1001 int encrypt;
1003 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1004 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1005 #ifdef THOMAS_TURBO
1006 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1007 #endif
1009 int len = 0;
1011 crypt = ieee->crypt[ieee->tx_keyidx];
1012 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1014 //Include High Throuput capability && Realtek proprietary
1015 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1017 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1018 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1019 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1020 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1022 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1023 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1024 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1028 if(ieee->qos_support){
1029 wmm_info_len = beacon->qos_data.supported?9:0;
1033 if(beacon->bCkipSupported)
1035 ckip_ie_len = 30+2;
1037 if(beacon->bCcxRmEnable)
1039 ccxrm_ie_len = 6+2;
1041 if( beacon->BssCcxVerNumber >= 2 )
1043 cxvernum_ie_len = 5+2;
1045 #ifdef THOMAS_TURBO
1046 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1047 + beacon->ssid_len//essid tagged val
1048 + rate_len//rates tagged val
1049 + wpa_ie_len
1050 + wmm_info_len
1051 + turbo_info_len
1052 + ht_cap_len
1053 + realtek_ie_len
1054 + ckip_ie_len
1055 + ccxrm_ie_len
1056 + cxvernum_ie_len
1057 + ieee->tx_headroom;
1058 #else
1059 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1060 + beacon->ssid_len//essid tagged val
1061 + rate_len//rates tagged val
1062 + wpa_ie_len
1063 + wmm_info_len
1064 + ht_cap_len
1065 + realtek_ie_len
1066 + ckip_ie_len
1067 + ccxrm_ie_len
1068 + cxvernum_ie_len
1069 + ieee->tx_headroom;
1070 #endif
1072 skb = dev_alloc_skb(len);
1074 if (!skb)
1075 return NULL;
1077 skb_reserve(skb, ieee->tx_headroom);
1079 hdr = (struct ieee80211_assoc_request_frame *)
1080 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1083 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1084 hdr->header.duration_id= 37; //FIXME
1085 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1086 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1087 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1089 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1091 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1092 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1093 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1095 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1096 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1098 if(ieee->short_slot)
1099 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1100 if (wmm_info_len) //QOS
1101 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1103 hdr->listen_interval = 0xa; //FIXME
1105 hdr->info_element[0].id = MFIE_TYPE_SSID;
1107 hdr->info_element[0].len = beacon->ssid_len;
1108 tag = skb_put(skb, beacon->ssid_len);
1109 memcpy(tag, beacon->ssid, beacon->ssid_len);
1111 tag = skb_put(skb, rate_len);
1113 ieee80211_MFIE_Brate(ieee, &tag);
1114 ieee80211_MFIE_Grate(ieee, &tag);
1115 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1116 if( beacon->bCkipSupported )
1118 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1119 u8 CcxAironetBuf[30];
1120 OCTET_STRING osCcxAironetIE;
1122 memset(CcxAironetBuf, 0,30);
1123 osCcxAironetIE.Octet = CcxAironetBuf;
1124 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1126 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1127 // We want to make the device type as "4500-client". 060926, by CCW.
1129 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1131 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1132 // "The CKIP negotiation is started with the associate request from the client to the access point,
1133 // containing an Aironet element with both the MIC and KP bits set."
1134 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1135 tag = skb_put(skb, ckip_ie_len);
1136 *tag++ = MFIE_TYPE_AIRONET;
1137 *tag++ = osCcxAironetIE.Length;
1138 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1139 tag += osCcxAironetIE.Length;
1142 if(beacon->bCcxRmEnable)
1144 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1145 OCTET_STRING osCcxRmCap;
1147 osCcxRmCap.Octet = CcxRmCapBuf;
1148 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1149 tag = skb_put(skb,ccxrm_ie_len);
1150 *tag++ = MFIE_TYPE_GENERIC;
1151 *tag++ = osCcxRmCap.Length;
1152 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1153 tag += osCcxRmCap.Length;
1156 if( beacon->BssCcxVerNumber >= 2 )
1158 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1159 OCTET_STRING osCcxVerNum;
1160 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1161 osCcxVerNum.Octet = CcxVerNumBuf;
1162 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1163 tag = skb_put(skb,cxvernum_ie_len);
1164 *tag++ = MFIE_TYPE_GENERIC;
1165 *tag++ = osCcxVerNum.Length;
1166 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1167 tag += osCcxVerNum.Length;
1169 //HT cap element
1170 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1171 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1173 tag = skb_put(skb, ht_cap_len);
1174 *tag++ = MFIE_TYPE_HT_CAP;
1175 *tag++ = ht_cap_len - 2;
1176 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1177 tag += ht_cap_len -2;
1182 //choose what wpa_supplicant gives to associate.
1183 tag = skb_put(skb, wpa_ie_len);
1184 if (wpa_ie_len){
1185 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1188 tag = skb_put(skb,wmm_info_len);
1189 if(wmm_info_len) {
1190 ieee80211_WMM_Info(ieee, &tag);
1192 #ifdef THOMAS_TURBO
1193 tag = skb_put(skb,turbo_info_len);
1194 if(turbo_info_len) {
1195 ieee80211_TURBO_Info(ieee, &tag);
1197 #endif
1199 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1200 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1202 tag = skb_put(skb, ht_cap_len);
1203 *tag++ = MFIE_TYPE_GENERIC;
1204 *tag++ = ht_cap_len - 2;
1205 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1206 tag += ht_cap_len -2;
1209 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1210 tag = skb_put(skb, realtek_ie_len);
1211 *tag++ = MFIE_TYPE_GENERIC;
1212 *tag++ = realtek_ie_len - 2;
1213 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1216 // printk("<=====%s(), %p, %p\n", __FUNCTION__, ieee->dev, ieee->dev->dev_addr);
1217 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1218 return skb;
1221 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1224 unsigned long flags;
1225 spin_lock_irqsave(&ieee->lock, flags);
1227 ieee->associate_seq++;
1229 /* don't scan, and avoid to have the RX path possibily
1230 * try again to associate. Even do not react to AUTH or
1231 * ASSOC response. Just wait for the retry wq to be scheduled.
1232 * Here we will check if there are good nets to associate
1233 * with, so we retry or just get back to NO_LINK and scanning
1235 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1236 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1237 ieee->softmac_stats.no_auth_rs++;
1238 }else{
1239 IEEE80211_DEBUG_MGMT("Association failed\n");
1240 ieee->softmac_stats.no_ass_rs++;
1243 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1245 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1246 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1248 spin_unlock_irqrestore(&ieee->lock, flags);
1251 void ieee80211_associate_abort_cb(unsigned long dev)
1253 ieee80211_associate_abort((struct ieee80211_device *) dev);
1257 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1259 struct ieee80211_network *beacon = &ieee->current_network;
1260 struct sk_buff *skb;
1262 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1264 ieee->softmac_stats.tx_auth_rq++;
1265 skb=ieee80211_authentication_req(beacon, ieee, 0);
1267 if (!skb)
1268 ieee80211_associate_abort(ieee);
1269 else{
1270 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1271 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1272 //printk(KERN_WARNING "Sending authentication request\n");
1273 softmac_mgmt_xmit(skb, ieee);
1274 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1275 if(!timer_pending(&ieee->associate_timer)){
1276 ieee->associate_timer.expires = jiffies + (HZ / 2);
1277 add_timer(&ieee->associate_timer);
1279 //dev_kfree_skb_any(skb);//edit by thomas
1283 void ieee80211_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1285 u8 *c;
1286 struct sk_buff *skb;
1287 struct ieee80211_network *beacon = &ieee->current_network;
1288 // int hlen = sizeof(struct ieee80211_authentication);
1290 ieee->associate_seq++;
1291 ieee->softmac_stats.tx_auth_rq++;
1293 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1294 if (!skb)
1295 ieee80211_associate_abort(ieee);
1296 else{
1297 c = skb_put(skb, chlen+2);
1298 *(c++) = MFIE_TYPE_CHALLENGE;
1299 *(c++) = chlen;
1300 memcpy(c, challenge, chlen);
1302 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1304 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1306 softmac_mgmt_xmit(skb, ieee);
1307 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1308 //dev_kfree_skb_any(skb);//edit by thomas
1310 kfree(challenge);
1313 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1315 struct sk_buff* skb;
1316 struct ieee80211_network *beacon = &ieee->current_network;
1318 del_timer_sync(&ieee->associate_timer);
1320 IEEE80211_DEBUG_MGMT("Sending association request\n");
1322 ieee->softmac_stats.tx_ass_rq++;
1323 skb=ieee80211_association_req(beacon, ieee);
1324 if (!skb)
1325 ieee80211_associate_abort(ieee);
1326 else{
1327 softmac_mgmt_xmit(skb, ieee);
1328 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1329 //dev_kfree_skb_any(skb);//edit by thomas
1332 void ieee80211_associate_complete_wq(struct work_struct *work)
1334 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1335 printk(KERN_INFO "Associated successfully\n");
1336 if(ieee80211_is_54g(ieee->current_network) &&
1337 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1339 ieee->rate = 108;
1340 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1341 }else{
1342 ieee->rate = 22;
1343 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1345 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1347 printk("Successfully associated, ht enabled\n");
1348 HTOnAssocRsp(ieee);
1350 else
1352 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1353 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1354 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1356 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1357 // To prevent the immediately calling watch_dog after association.
1358 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1360 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1361 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1363 ieee->link_change(ieee->dev);
1364 if(ieee->is_silent_reset == 0){
1365 printk("============>normal associate\n");
1366 notify_wx_assoc_event(ieee);
1368 else if(ieee->is_silent_reset == 1)
1370 printk("==================>silent reset associate\n");
1371 ieee->is_silent_reset = 0;
1374 if (ieee->data_hard_resume)
1375 ieee->data_hard_resume(ieee->dev);
1376 netif_carrier_on(ieee->dev);
1379 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1381 // int i;
1382 // struct net_device* dev = ieee->dev;
1383 del_timer_sync(&ieee->associate_timer);
1385 ieee->state = IEEE80211_LINKED;
1386 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1387 queue_work(ieee->wq, &ieee->associate_complete_wq);
1390 void ieee80211_associate_procedure_wq(struct work_struct *work)
1392 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1393 ieee->sync_scan_hurryup = 1;
1394 down(&ieee->wx_sem);
1396 if (ieee->data_hard_stop)
1397 ieee->data_hard_stop(ieee->dev);
1399 ieee80211_stop_scan(ieee);
1400 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1401 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1402 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1404 ieee->associate_seq = 1;
1405 ieee80211_associate_step1(ieee);
1407 up(&ieee->wx_sem);
1410 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1412 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1413 int tmp_ssid_len = 0;
1415 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1417 /* we are interested in new new only if we are not associated
1418 * and we are not associating / authenticating
1420 if (ieee->state != IEEE80211_NOLINK)
1421 return;
1423 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1424 return;
1426 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1427 return;
1430 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1431 /* if the user specified the AP MAC, we need also the essid
1432 * This could be obtained by beacons or, if the network does not
1433 * broadcast it, it can be put manually.
1435 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1436 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1437 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1438 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1439 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1440 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1443 if ( /* if the user set the AP check if match.
1444 * if the network does not broadcast essid we check the user supplyed ANY essid
1445 * if the network does broadcast and the user does not set essid it is OK
1446 * if the network does broadcast and the user did set essid chech if essid match
1448 ( apset && apmatch &&
1449 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1450 /* if the ap is not set, check that the user set the bssid
1451 * and the network does bradcast and that those two bssid matches
1453 (!apset && ssidset && ssidbroad && ssidmatch)
1455 /* if the essid is hidden replace it with the
1456 * essid provided by the user.
1458 if (!ssidbroad){
1459 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1460 tmp_ssid_len = ieee->current_network.ssid_len;
1462 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1464 if (!ssidbroad){
1465 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1466 ieee->current_network.ssid_len = tmp_ssid_len;
1468 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1470 //ieee->pHTInfo->IOTAction = 0;
1471 HTResetIOTSetting(ieee->pHTInfo);
1472 if (ieee->iw_mode == IW_MODE_INFRA){
1473 /* Join the network for the first time */
1474 ieee->AsocRetryCount = 0;
1475 //for HT by amy 080514
1476 if((ieee->current_network.qos_data.supported == 1) &&
1477 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1478 ieee->current_network.bssht.bdSupportHT)
1479 /*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.*/
1481 // ieee->pHTInfo->bCurrentHTSupport = true;
1482 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1484 else
1486 ieee->pHTInfo->bCurrentHTSupport = false;
1489 ieee->state = IEEE80211_ASSOCIATING;
1490 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1491 }else{
1492 if(ieee80211_is_54g(ieee->current_network) &&
1493 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1494 ieee->rate = 108;
1495 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1496 printk(KERN_INFO"Using G rates\n");
1497 }else{
1498 ieee->rate = 22;
1499 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1500 printk(KERN_INFO"Using B rates\n");
1502 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1503 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1504 ieee->state = IEEE80211_LINKED;
1512 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1514 unsigned long flags;
1515 struct ieee80211_network *target;
1517 spin_lock_irqsave(&ieee->lock, flags);
1519 list_for_each_entry(target, &ieee->network_list, list) {
1521 /* if the state become different that NOLINK means
1522 * we had found what we are searching for
1525 if (ieee->state != IEEE80211_NOLINK)
1526 break;
1528 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1529 ieee80211_softmac_new_net(ieee, target);
1532 spin_unlock_irqrestore(&ieee->lock, flags);
1537 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1539 struct ieee80211_authentication *a;
1540 u8 *t;
1541 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1542 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1543 return 0xcafe;
1545 *challenge = NULL;
1546 a = (struct ieee80211_authentication*) skb->data;
1547 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1548 t = skb->data + sizeof(struct ieee80211_authentication);
1550 if(*(t++) == MFIE_TYPE_CHALLENGE){
1551 *chlen = *(t++);
1552 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1553 if (!*challenge)
1554 return -ENOMEM;
1558 return cpu_to_le16(a->status);
1563 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1565 struct ieee80211_authentication *a;
1567 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1568 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1569 return -1;
1571 a = (struct ieee80211_authentication*) skb->data;
1573 memcpy(dest,a->header.addr2, ETH_ALEN);
1575 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1576 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1578 return WLAN_STATUS_SUCCESS;
1581 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1583 u8 *tag;
1584 u8 *skbend;
1585 u8 *ssid=NULL;
1586 u8 ssidlen = 0;
1588 struct ieee80211_hdr_3addr *header =
1589 (struct ieee80211_hdr_3addr *) skb->data;
1591 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1592 return -1; /* corrupted */
1594 memcpy(src,header->addr2, ETH_ALEN);
1596 skbend = (u8*)skb->data + skb->len;
1598 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1600 while (tag+1 < skbend){
1601 if (*tag == 0){
1602 ssid = tag+2;
1603 ssidlen = *(tag+1);
1604 break;
1606 tag++; /* point to the len field */
1607 tag = tag + *(tag); /* point to the last data byte of the tag */
1608 tag++; /* point to the next tag */
1611 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1612 if (ssidlen == 0) return 1;
1614 if (!ssid) return 1; /* ssid not found in tagged param */
1615 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1619 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1621 struct ieee80211_assoc_request_frame *a;
1623 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1624 sizeof(struct ieee80211_info_element))) {
1626 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1627 return -1;
1630 a = (struct ieee80211_assoc_request_frame*) skb->data;
1632 memcpy(dest,a->header.addr2,ETH_ALEN);
1634 return 0;
1637 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1639 struct ieee80211_assoc_response_frame *response_head;
1640 u16 status_code;
1642 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1643 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1644 return 0xcafe;
1647 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1648 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1650 status_code = le16_to_cpu(response_head->status);
1651 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1652 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1653 ((ieee->mode == IEEE_G) &&
1654 (ieee->current_network.mode == IEEE_N_24G) &&
1655 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1656 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1657 }else {
1658 ieee->AsocRetryCount = 0;
1661 return le16_to_cpu(response_head->status);
1664 static inline void
1665 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1667 u8 dest[ETH_ALEN];
1669 //IEEE80211DMESG("Rx probe");
1670 ieee->softmac_stats.rx_probe_rq++;
1671 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1672 if (probe_rq_parse(ieee, skb, dest)){
1673 //IEEE80211DMESG("Was for me!");
1674 ieee->softmac_stats.tx_probe_rs++;
1675 ieee80211_resp_to_probe(ieee, dest);
1679 static inline void
1680 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1682 u8 dest[ETH_ALEN];
1683 int status;
1684 //IEEE80211DMESG("Rx probe");
1685 ieee->softmac_stats.rx_auth_rq++;
1687 status = auth_rq_parse(skb, dest);
1688 if (status != -1) {
1689 ieee80211_resp_to_auth(ieee, status, dest);
1691 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1695 static inline void
1696 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1699 u8 dest[ETH_ALEN];
1700 //unsigned long flags;
1702 ieee->softmac_stats.rx_ass_rq++;
1703 if (assoc_rq_parse(skb,dest) != -1){
1704 ieee80211_resp_to_assoc_rq(ieee, dest);
1707 printk(KERN_INFO"New client associated: %pM\n", dest);
1708 //FIXME
1713 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1716 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1718 if (buf)
1719 softmac_ps_mgmt_xmit(buf, ieee);
1724 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1726 int timeout = ieee->ps_timeout;
1727 u8 dtim;
1728 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1729 ieee->iw_mode != IW_MODE_INFRA ||
1730 ieee->state != IEEE80211_LINKED)
1732 return 0;
1734 dtim = ieee->current_network.dtim_data;
1735 //printk("DTIM\n");
1736 if(!(dtim & IEEE80211_DTIM_VALID))
1737 return 0;
1738 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1739 //printk("VALID\n");
1740 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1742 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1743 return 2;
1745 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1746 return 0;
1748 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1749 return 0;
1751 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1752 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1753 return 0;
1755 if(time_l){
1756 *time_l = ieee->current_network.last_dtim_sta_time[0]
1757 + (ieee->current_network.beacon_interval
1758 * ieee->current_network.dtim_period) * 1000;
1761 if(time_h){
1762 *time_h = ieee->current_network.last_dtim_sta_time[1];
1763 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1764 *time_h += 1;
1767 return 1;
1772 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1775 u32 th,tl;
1776 short sleep;
1778 unsigned long flags,flags2;
1780 spin_lock_irqsave(&ieee->lock, flags);
1782 if((ieee->ps == IEEE80211_PS_DISABLED ||
1783 ieee->iw_mode != IW_MODE_INFRA ||
1784 ieee->state != IEEE80211_LINKED)){
1786 // #warning CHECK_LOCK_HERE
1787 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1789 ieee80211_sta_wakeup(ieee, 1);
1791 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1794 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1795 /* 2 wake, 1 sleep, 0 do nothing */
1796 if(sleep == 0)
1797 goto out;
1799 if(sleep == 1){
1801 if(ieee->sta_sleep == 1)
1802 ieee->enter_sleep_state(ieee->dev,th,tl);
1804 else if(ieee->sta_sleep == 0){
1805 // printk("send null 1\n");
1806 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1808 if(ieee->ps_is_queue_empty(ieee->dev)){
1811 ieee->sta_sleep = 2;
1813 ieee->ps_request_tx_ack(ieee->dev);
1815 ieee80211_sta_ps_send_null_frame(ieee,1);
1817 ieee->ps_th = th;
1818 ieee->ps_tl = tl;
1820 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1825 }else if(sleep == 2){
1826 //#warning CHECK_LOCK_HERE
1827 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1829 ieee80211_sta_wakeup(ieee,1);
1831 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1834 out:
1835 spin_unlock_irqrestore(&ieee->lock, flags);
1839 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1841 if(ieee->sta_sleep == 0){
1842 if(nl){
1843 printk("Warning: driver is probably failing to report TX ps error\n");
1844 ieee->ps_request_tx_ack(ieee->dev);
1845 ieee80211_sta_ps_send_null_frame(ieee, 0);
1847 return;
1851 if(ieee->sta_sleep == 1)
1852 ieee->sta_wake_up(ieee->dev);
1854 ieee->sta_sleep = 0;
1856 if(nl){
1857 ieee->ps_request_tx_ack(ieee->dev);
1858 ieee80211_sta_ps_send_null_frame(ieee, 0);
1862 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1864 unsigned long flags,flags2;
1866 spin_lock_irqsave(&ieee->lock, flags);
1868 if(ieee->sta_sleep == 2){
1869 /* Null frame with PS bit set */
1870 if(success){
1871 ieee->sta_sleep = 1;
1872 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1874 /* if the card report not success we can't be sure the AP
1875 * has not RXed so we can't assume the AP believe us awake
1878 /* 21112005 - tx again null without PS bit if lost */
1879 else {
1881 if((ieee->sta_sleep == 0) && !success){
1882 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1883 ieee80211_sta_ps_send_null_frame(ieee, 0);
1884 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1887 spin_unlock_irqrestore(&ieee->lock, flags);
1889 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1891 struct ieee80211_hdr* header = (struct ieee80211_hdr*)skb->data;
1892 u8* act = ieee80211_get_payload(header);
1893 u8 tmp = 0;
1894 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1895 if (act == NULL)
1897 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1898 return;
1900 tmp = *act;
1901 act ++;
1902 switch (tmp)
1904 case ACT_CAT_BA:
1905 if (*act == ACT_ADDBAREQ)
1906 ieee80211_rx_ADDBAReq(ieee, skb);
1907 else if (*act == ACT_ADDBARSP)
1908 ieee80211_rx_ADDBARsp(ieee, skb);
1909 else if (*act == ACT_DELBA)
1910 ieee80211_rx_DELBA(ieee, skb);
1911 break;
1912 default:
1913 // if (net_ratelimit())
1914 // IEEE80211_DEBUG(IEEE80211_DL_BA, "unknown action frame(%d)\n", tmp);
1915 break;
1917 return;
1920 inline int
1921 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1922 struct ieee80211_rx_stats *rx_stats, u16 type,
1923 u16 stype)
1925 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
1926 u16 errcode;
1927 u8* challenge;
1928 int chlen=0;
1929 int aid;
1930 struct ieee80211_assoc_response_frame *assoc_resp;
1931 // struct ieee80211_info_element *info_element;
1932 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
1934 if(!ieee->proto_started)
1935 return 0;
1937 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1938 ieee->iw_mode == IW_MODE_INFRA &&
1939 ieee->state == IEEE80211_LINKED))
1941 tasklet_schedule(&ieee->ps_task);
1943 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1944 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1945 ieee->last_rx_ps_time = jiffies;
1947 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1949 case IEEE80211_STYPE_ASSOC_RESP:
1950 case IEEE80211_STYPE_REASSOC_RESP:
1952 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1953 WLAN_FC_GET_STYPE(header->frame_ctl));
1954 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1955 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1956 ieee->iw_mode == IW_MODE_INFRA){
1957 struct ieee80211_network network_resp;
1958 struct ieee80211_network *network = &network_resp;
1960 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
1961 ieee->state=IEEE80211_LINKED;
1962 ieee->assoc_id = aid;
1963 ieee->softmac_stats.rx_ass_ok++;
1964 /* station support qos */
1965 /* Let the register setting defaultly with Legacy station */
1966 if(ieee->qos_support) {
1967 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
1968 memset(network, 0, sizeof(*network));
1969 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
1970 rx_stats->len - sizeof(*assoc_resp),\
1971 network,rx_stats)){
1972 return 1;
1974 else
1975 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
1976 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1977 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1979 if (ieee->handle_assoc_response != NULL)
1980 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
1982 ieee80211_associate_complete(ieee);
1983 } else {
1984 /* aid could not been allocated */
1985 ieee->softmac_stats.rx_ass_err++;
1986 printk(
1987 "Association response status code 0x%x\n",
1988 errcode);
1989 IEEE80211_DEBUG_MGMT(
1990 "Association response status code 0x%x\n",
1991 errcode);
1992 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
1993 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1994 } else {
1995 ieee80211_associate_abort(ieee);
1999 break;
2001 case IEEE80211_STYPE_ASSOC_REQ:
2002 case IEEE80211_STYPE_REASSOC_REQ:
2004 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2005 ieee->iw_mode == IW_MODE_MASTER)
2007 ieee80211_rx_assoc_rq(ieee, skb);
2008 break;
2010 case IEEE80211_STYPE_AUTH:
2012 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2013 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2014 ieee->iw_mode == IW_MODE_INFRA){
2016 IEEE80211_DEBUG_MGMT("Received authentication response");
2018 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2019 if(ieee->open_wep || !challenge){
2020 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2021 ieee->softmac_stats.rx_auth_rs_ok++;
2022 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2024 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2026 // WEP or TKIP encryption
2027 if(IsHTHalfNmodeAPs(ieee))
2029 bSupportNmode = true;
2030 bHalfSupportNmode = true;
2032 else
2034 bSupportNmode = false;
2035 bHalfSupportNmode = false;
2037 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2040 /* Dummy wirless mode setting to avoid encryption issue */
2041 if(bSupportNmode) {
2042 //N mode setting
2043 ieee->SetWirelessMode(ieee->dev, \
2044 ieee->current_network.mode);
2045 }else{
2046 //b/g mode setting
2047 /*TODO*/
2048 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2051 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2053 printk("===============>entern half N mode\n");
2054 ieee->bHalfWirelessN24GMode = true;
2056 else
2057 ieee->bHalfWirelessN24GMode = false;
2059 ieee80211_associate_step2(ieee);
2060 }else{
2061 ieee80211_auth_challenge(ieee, challenge, chlen);
2063 }else{
2064 ieee->softmac_stats.rx_auth_rs_err++;
2065 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2066 ieee80211_associate_abort(ieee);
2069 }else if (ieee->iw_mode == IW_MODE_MASTER){
2070 ieee80211_rx_auth_rq(ieee, skb);
2073 break;
2075 case IEEE80211_STYPE_PROBE_REQ:
2077 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2078 ((ieee->iw_mode == IW_MODE_ADHOC ||
2079 ieee->iw_mode == IW_MODE_MASTER) &&
2080 ieee->state == IEEE80211_LINKED)){
2081 ieee80211_rx_probe_rq(ieee, skb);
2083 break;
2085 case IEEE80211_STYPE_DISASSOC:
2086 case IEEE80211_STYPE_DEAUTH:
2087 /* FIXME for now repeat all the association procedure
2088 * both for disassociation and deauthentication
2090 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2091 ieee->state == IEEE80211_LINKED &&
2092 ieee->iw_mode == IW_MODE_INFRA){
2094 ieee->state = IEEE80211_ASSOCIATING;
2095 ieee->softmac_stats.reassoc++;
2097 notify_wx_assoc_event(ieee);
2098 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2099 RemovePeerTS(ieee, header->addr2);
2100 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2102 break;
2103 case IEEE80211_STYPE_MANAGE_ACT:
2104 ieee80211_process_action(ieee,skb);
2105 break;
2106 default:
2107 return -1;
2108 break;
2111 //dev_kfree_skb_any(skb);
2112 return 0;
2115 /* following are for a simpler TX queue management.
2116 * Instead of using netif_[stop/wake]_queue the driver
2117 * will uses these two function (plus a reset one), that
2118 * will internally uses the kernel netif_* and takes
2119 * care of the ieee802.11 fragmentation.
2120 * So the driver receives a fragment per time and might
2121 * call the stop function when it want without take care
2122 * to have enought room to TX an entire packet.
2123 * This might be useful if each fragment need it's own
2124 * descriptor, thus just keep a total free memory > than
2125 * the max fragmentation treshold is not enought.. If the
2126 * ieee802.11 stack passed a TXB struct then you needed
2127 * to keep N free descriptors where
2128 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2129 * In this way you need just one and the 802.11 stack
2130 * will take care of buffering fragments and pass them to
2131 * to the driver later, when it wakes the queue.
2133 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2136 unsigned int queue_index = txb->queue_index;
2137 unsigned long flags;
2138 int i;
2139 cb_desc *tcb_desc = NULL;
2141 spin_lock_irqsave(&ieee->lock,flags);
2143 /* called with 2nd parm 0, no tx mgmt lock required */
2144 ieee80211_sta_wakeup(ieee,0);
2146 /* update the tx status */
2147 ieee->stats.tx_bytes += txb->payload_size;
2148 ieee->stats.tx_packets++;
2149 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2150 if(tcb_desc->bMulticast) {
2151 ieee->stats.multicast++;
2153 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2154 for(i = 0; i < txb->nr_frags; i++) {
2155 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2156 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2157 #else
2158 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2159 #endif
2160 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2161 (ieee->queue_stop)) {
2162 /* insert the skb packet to the wait queue */
2163 /* as for the completion function, it does not need
2164 * to check it any more.
2165 * */
2166 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2167 //ieee80211_stop_queue(ieee);
2168 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2169 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2170 #else
2171 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2172 #endif
2173 }else{
2174 ieee->softmac_data_hard_start_xmit(
2175 txb->fragments[i],
2176 ieee->dev,ieee->rate);
2177 //ieee->stats.tx_packets++;
2178 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2179 //ieee->dev->trans_start = jiffies;
2182 ieee80211_txb_free(txb);
2184 //exit:
2185 spin_unlock_irqrestore(&ieee->lock,flags);
2189 /* called with ieee->lock acquired */
2190 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2192 int i;
2193 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2195 if (ieee->queue_stop){
2196 ieee->tx_pending.frag = i;
2197 return;
2198 }else{
2200 ieee->softmac_data_hard_start_xmit(
2201 ieee->tx_pending.txb->fragments[i],
2202 ieee->dev,ieee->rate);
2203 //(i+1)<ieee->tx_pending.txb->nr_frags);
2204 ieee->stats.tx_packets++;
2205 ieee->dev->trans_start = jiffies;
2210 ieee80211_txb_free(ieee->tx_pending.txb);
2211 ieee->tx_pending.txb = NULL;
2215 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2217 unsigned long flags;
2219 spin_lock_irqsave(&ieee->lock,flags);
2220 init_mgmt_queue(ieee);
2221 if (ieee->tx_pending.txb){
2222 ieee80211_txb_free(ieee->tx_pending.txb);
2223 ieee->tx_pending.txb = NULL;
2225 ieee->queue_stop = 0;
2226 spin_unlock_irqrestore(&ieee->lock,flags);
2230 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2233 unsigned long flags;
2234 struct sk_buff *skb;
2235 struct ieee80211_hdr_3addr *header;
2237 spin_lock_irqsave(&ieee->lock,flags);
2238 if (! ieee->queue_stop) goto exit;
2240 ieee->queue_stop = 0;
2242 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2243 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2245 header = (struct ieee80211_hdr_3addr *) skb->data;
2247 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2249 if (ieee->seq_ctrl[0] == 0xFFF)
2250 ieee->seq_ctrl[0] = 0;
2251 else
2252 ieee->seq_ctrl[0]++;
2254 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2255 //dev_kfree_skb_any(skb);//edit by thomas
2258 if (!ieee->queue_stop && ieee->tx_pending.txb)
2259 ieee80211_resume_tx(ieee);
2261 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2262 ieee->softmac_stats.swtxawake++;
2263 netif_wake_queue(ieee->dev);
2266 exit :
2267 spin_unlock_irqrestore(&ieee->lock,flags);
2271 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2273 //unsigned long flags;
2274 //spin_lock_irqsave(&ieee->lock,flags);
2276 if (! netif_queue_stopped(ieee->dev)){
2277 netif_stop_queue(ieee->dev);
2278 ieee->softmac_stats.swtxstop++;
2280 ieee->queue_stop = 1;
2281 //spin_unlock_irqrestore(&ieee->lock,flags);
2286 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2289 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2291 /* an IBSS cell address must have the two less significant
2292 * bits of the first byte = 2
2294 ieee->current_network.bssid[0] &= ~0x01;
2295 ieee->current_network.bssid[0] |= 0x02;
2298 /* called in user context only */
2299 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2301 ieee->assoc_id = 1;
2303 if (ieee->current_network.ssid_len == 0){
2304 strncpy(ieee->current_network.ssid,
2305 IEEE80211_DEFAULT_TX_ESSID,
2306 IW_ESSID_MAX_SIZE);
2308 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2309 ieee->ssid_set = 1;
2312 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2314 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2315 ieee->state = IEEE80211_LINKED;
2316 ieee->link_change(ieee->dev);
2317 notify_wx_assoc_event(ieee);
2319 if (ieee->data_hard_resume)
2320 ieee->data_hard_resume(ieee->dev);
2322 netif_carrier_on(ieee->dev);
2325 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2327 if(ieee->raw_tx){
2329 if (ieee->data_hard_resume)
2330 ieee->data_hard_resume(ieee->dev);
2332 netif_carrier_on(ieee->dev);
2335 void ieee80211_start_ibss_wq(struct work_struct *work)
2338 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2339 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2340 /* iwconfig mode ad-hoc will schedule this and return
2341 * on the other hand this will block further iwconfig SET
2342 * operations because of the wx_sem hold.
2343 * Anyway some most set operations set a flag to speed-up
2344 * (abort) this wq (when syncro scanning) before sleeping
2345 * on the semaphore
2347 if(!ieee->proto_started){
2348 printk("==========oh driver down return\n");
2349 return;
2351 down(&ieee->wx_sem);
2353 if (ieee->current_network.ssid_len == 0){
2354 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2355 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2356 ieee->ssid_set = 1;
2359 /* check if we have this cell in our network list */
2360 ieee80211_softmac_check_all_nets(ieee);
2363 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2364 if (ieee->state == IEEE80211_NOLINK)
2365 ieee->current_network.channel = 6;
2366 /* if not then the state is not linked. Maybe the user swithced to
2367 * ad-hoc mode just after being in monitor mode, or just after
2368 * being very few time in managed mode (so the card have had no
2369 * time to scan all the chans..) or we have just run up the iface
2370 * after setting ad-hoc mode. So we have to give another try..
2371 * Here, in ibss mode, should be safe to do this without extra care
2372 * (in bss mode we had to make sure no-one tryed to associate when
2373 * we had just checked the ieee->state and we was going to start the
2374 * scan) beacause in ibss mode the ieee80211_new_net function, when
2375 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2376 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2377 * scan, that will stop at the first round because it sees the state
2378 * associated.
2380 if (ieee->state == IEEE80211_NOLINK)
2381 ieee80211_start_scan_syncro(ieee);
2383 /* the network definitively is not here.. create a new cell */
2384 if (ieee->state == IEEE80211_NOLINK){
2385 printk("creating new IBSS cell\n");
2386 if(!ieee->wap_set)
2387 ieee80211_randomize_cell(ieee);
2389 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2391 ieee->current_network.rates_len = 4;
2393 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2394 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2395 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2396 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2398 }else
2399 ieee->current_network.rates_len = 0;
2401 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2402 ieee->current_network.rates_ex_len = 8;
2404 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2405 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2406 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2407 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2408 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2409 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2410 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2411 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2413 ieee->rate = 108;
2414 }else{
2415 ieee->current_network.rates_ex_len = 0;
2416 ieee->rate = 22;
2419 // By default, WMM function will be disabled in IBSS mode
2420 ieee->current_network.QoS_Enable = 0;
2421 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2422 ieee->current_network.atim_window = 0;
2423 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2424 if(ieee->short_slot)
2425 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2429 ieee->state = IEEE80211_LINKED;
2431 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2432 ieee->link_change(ieee->dev);
2434 notify_wx_assoc_event(ieee);
2436 ieee80211_start_send_beacons(ieee);
2438 if (ieee->data_hard_resume)
2439 ieee->data_hard_resume(ieee->dev);
2440 netif_carrier_on(ieee->dev);
2442 up(&ieee->wx_sem);
2445 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2447 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2450 /* this is called only in user context, with wx_sem held */
2451 void ieee80211_start_bss(struct ieee80211_device *ieee)
2453 unsigned long flags;
2455 // Ref: 802.11d 11.1.3.3
2456 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2458 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2460 if(! ieee->bGlobalDomain)
2462 return;
2465 /* check if we have already found the net we
2466 * are interested in (if any).
2467 * if not (we are disassociated and we are not
2468 * in associating / authenticating phase) start the background scanning.
2470 ieee80211_softmac_check_all_nets(ieee);
2472 /* ensure no-one start an associating process (thus setting
2473 * the ieee->state to ieee80211_ASSOCIATING) while we
2474 * have just cheked it and we are going to enable scan.
2475 * The ieee80211_new_net function is always called with
2476 * lock held (from both ieee80211_softmac_check_all_nets and
2477 * the rx path), so we cannot be in the middle of such function
2479 spin_lock_irqsave(&ieee->lock, flags);
2481 if (ieee->state == IEEE80211_NOLINK){
2482 ieee->actscanning = true;
2483 ieee80211_start_scan(ieee);
2485 spin_unlock_irqrestore(&ieee->lock, flags);
2488 /* called only in userspace context */
2489 void ieee80211_disassociate(struct ieee80211_device *ieee)
2493 netif_carrier_off(ieee->dev);
2494 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2495 ieee80211_reset_queue(ieee);
2497 if (ieee->data_hard_stop)
2498 ieee->data_hard_stop(ieee->dev);
2499 if(IS_DOT11D_ENABLE(ieee))
2500 Dot11d_Reset(ieee);
2501 ieee->state = IEEE80211_NOLINK;
2502 ieee->is_set_key = false;
2503 ieee->link_change(ieee->dev);
2504 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2505 notify_wx_assoc_event(ieee);
2508 void ieee80211_associate_retry_wq(struct work_struct *work)
2510 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2511 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2512 unsigned long flags;
2514 down(&ieee->wx_sem);
2515 if(!ieee->proto_started)
2516 goto exit;
2518 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2519 goto exit;
2521 /* until we do not set the state to IEEE80211_NOLINK
2522 * there are no possibility to have someone else trying
2523 * to start an association procdure (we get here with
2524 * ieee->state = IEEE80211_ASSOCIATING).
2525 * When we set the state to IEEE80211_NOLINK it is possible
2526 * that the RX path run an attempt to associate, but
2527 * both ieee80211_softmac_check_all_nets and the
2528 * RX path works with ieee->lock held so there are no
2529 * problems. If we are still disassociated then start a scan.
2530 * the lock here is necessary to ensure no one try to start
2531 * an association procedure when we have just checked the
2532 * state and we are going to start the scan.
2534 ieee->state = IEEE80211_NOLINK;
2536 ieee80211_softmac_check_all_nets(ieee);
2538 spin_lock_irqsave(&ieee->lock, flags);
2540 if(ieee->state == IEEE80211_NOLINK)
2541 ieee80211_start_scan(ieee);
2543 spin_unlock_irqrestore(&ieee->lock, flags);
2545 exit:
2546 up(&ieee->wx_sem);
2549 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2551 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2553 struct sk_buff *skb;
2554 struct ieee80211_probe_response *b;
2556 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2558 if (!skb)
2559 return NULL;
2561 b = (struct ieee80211_probe_response *) skb->data;
2562 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2564 return skb;
2568 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2570 struct sk_buff *skb;
2571 struct ieee80211_probe_response *b;
2573 skb = ieee80211_get_beacon_(ieee);
2574 if(!skb)
2575 return NULL;
2577 b = (struct ieee80211_probe_response *) skb->data;
2578 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2580 if (ieee->seq_ctrl[0] == 0xFFF)
2581 ieee->seq_ctrl[0] = 0;
2582 else
2583 ieee->seq_ctrl[0]++;
2585 return skb;
2588 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2590 ieee->sync_scan_hurryup = 1;
2591 down(&ieee->wx_sem);
2592 ieee80211_stop_protocol(ieee);
2593 up(&ieee->wx_sem);
2597 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2599 if (!ieee->proto_started)
2600 return;
2602 ieee->proto_started = 0;
2604 ieee80211_stop_send_beacons(ieee);
2605 del_timer_sync(&ieee->associate_timer);
2606 cancel_delayed_work(&ieee->associate_retry_wq);
2607 cancel_delayed_work(&ieee->start_ibss_wq);
2608 ieee80211_stop_scan(ieee);
2610 ieee80211_disassociate(ieee);
2611 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2614 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2616 ieee->sync_scan_hurryup = 0;
2617 down(&ieee->wx_sem);
2618 ieee80211_start_protocol(ieee);
2619 up(&ieee->wx_sem);
2622 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2624 short ch = 0;
2625 int i = 0;
2626 if (ieee->proto_started)
2627 return;
2629 ieee->proto_started = 1;
2631 if (ieee->current_network.channel == 0){
2633 ch++;
2634 if (ch > MAX_CHANNEL_NUMBER)
2635 return; /* no channel found */
2636 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2637 ieee->current_network.channel = ch;
2640 if (ieee->current_network.beacon_interval == 0)
2641 ieee->current_network.beacon_interval = 100;
2642 // printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
2643 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2645 for(i = 0; i < 17; i++) {
2646 ieee->last_rxseq_num[i] = -1;
2647 ieee->last_rxfrag_num[i] = -1;
2648 ieee->last_packet_time[i] = 0;
2651 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2654 /* if the user set the MAC of the ad-hoc cell and then
2655 * switch to managed mode, shall we make sure that association
2656 * attempts does not fail just because the user provide the essid
2657 * and the nic is still checking for the AP MAC ??
2659 if (ieee->iw_mode == IW_MODE_INFRA)
2660 ieee80211_start_bss(ieee);
2662 else if (ieee->iw_mode == IW_MODE_ADHOC)
2663 ieee80211_start_ibss(ieee);
2665 else if (ieee->iw_mode == IW_MODE_MASTER)
2666 ieee80211_start_master_bss(ieee);
2668 else if(ieee->iw_mode == IW_MODE_MONITOR)
2669 ieee80211_start_monitor_mode(ieee);
2673 #define DRV_NAME "Ieee80211"
2674 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2676 int i;
2677 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2679 ieee->state = IEEE80211_NOLINK;
2680 ieee->sync_scan_hurryup = 0;
2681 for(i = 0; i < 5; i++) {
2682 ieee->seq_ctrl[i] = 0;
2684 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2685 if (!ieee->pDot11dInfo)
2686 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2687 //added for AP roaming
2688 ieee->LinkDetectInfo.SlotNum = 2;
2689 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2690 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2692 ieee->assoc_id = 0;
2693 ieee->queue_stop = 0;
2694 ieee->scanning = 0;
2695 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2696 ieee->wap_set = 0;
2697 ieee->ssid_set = 0;
2698 ieee->proto_started = 0;
2699 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2700 ieee->rate = 22;
2701 ieee->ps = IEEE80211_PS_DISABLED;
2702 ieee->sta_sleep = 0;
2703 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2704 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2705 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2706 //added by amy
2707 ieee->actscanning = false;
2708 ieee->beinretry = false;
2709 ieee->is_set_key = false;
2710 init_mgmt_queue(ieee);
2712 ieee->sta_edca_param[0] = 0x0000A403;
2713 ieee->sta_edca_param[1] = 0x0000A427;
2714 ieee->sta_edca_param[2] = 0x005E4342;
2715 ieee->sta_edca_param[3] = 0x002F3262;
2716 ieee->aggregation = true;
2717 ieee->enable_rx_imm_BA = 1;
2718 ieee->tx_pending.txb = NULL;
2720 init_timer(&ieee->associate_timer);
2721 ieee->associate_timer.data = (unsigned long)ieee;
2722 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2724 init_timer(&ieee->beacon_timer);
2725 ieee->beacon_timer.data = (unsigned long) ieee;
2726 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2728 ieee->wq = create_workqueue(DRV_NAME);
2730 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2731 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2732 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2733 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2734 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2735 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2738 sema_init(&ieee->wx_sem, 1);
2739 sema_init(&ieee->scan_sem, 1);
2741 spin_lock_init(&ieee->mgmt_tx_lock);
2742 spin_lock_init(&ieee->beacon_lock);
2744 tasklet_init(&ieee->ps_task,
2745 (void(*)(unsigned long)) ieee80211_sta_ps,
2746 (unsigned long)ieee);
2750 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2752 down(&ieee->wx_sem);
2753 kfree(ieee->pDot11dInfo);
2754 ieee->pDot11dInfo = NULL;
2755 del_timer_sync(&ieee->associate_timer);
2757 cancel_delayed_work(&ieee->associate_retry_wq);
2758 destroy_workqueue(ieee->wq);
2760 up(&ieee->wx_sem);
2763 /********************************************************
2764 * Start of WPA code. *
2765 * this is stolen from the ipw2200 driver *
2766 ********************************************************/
2769 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2771 /* This is called when wpa_supplicant loads and closes the driver
2772 * interface. */
2773 printk("%s WPA\n",value ? "enabling" : "disabling");
2774 ieee->wpa_enabled = value;
2775 return 0;
2779 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2781 /* make sure WPA is enabled */
2782 ieee80211_wpa_enable(ieee, 1);
2784 ieee80211_disassociate(ieee);
2788 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2791 int ret = 0;
2793 switch (command) {
2794 case IEEE_MLME_STA_DEAUTH:
2795 // silently ignore
2796 break;
2798 case IEEE_MLME_STA_DISASSOC:
2799 ieee80211_disassociate(ieee);
2800 break;
2802 default:
2803 printk("Unknown MLME request: %d\n", command);
2804 ret = -EOPNOTSUPP;
2807 return ret;
2811 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2812 struct ieee_param *param, int plen)
2814 u8 *buf;
2816 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2817 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2818 return -EINVAL;
2820 if (param->u.wpa_ie.len) {
2821 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2822 GFP_KERNEL);
2823 if (buf == NULL)
2824 return -ENOMEM;
2826 kfree(ieee->wpa_ie);
2827 ieee->wpa_ie = buf;
2828 ieee->wpa_ie_len = param->u.wpa_ie.len;
2829 } else {
2830 kfree(ieee->wpa_ie);
2831 ieee->wpa_ie = NULL;
2832 ieee->wpa_ie_len = 0;
2835 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2836 return 0;
2839 #define AUTH_ALG_OPEN_SYSTEM 0x1
2840 #define AUTH_ALG_SHARED_KEY 0x2
2842 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2845 struct ieee80211_security sec = {
2846 .flags = SEC_AUTH_MODE,
2848 int ret = 0;
2850 if (value & AUTH_ALG_SHARED_KEY) {
2851 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2852 ieee->open_wep = 0;
2853 ieee->auth_mode = 1;
2854 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2855 sec.auth_mode = WLAN_AUTH_OPEN;
2856 ieee->open_wep = 1;
2857 ieee->auth_mode = 0;
2859 else if (value & IW_AUTH_ALG_LEAP){
2860 sec.auth_mode = WLAN_AUTH_LEAP;
2861 ieee->open_wep = 1;
2862 ieee->auth_mode = 2;
2866 if (ieee->set_security)
2867 ieee->set_security(ieee->dev, &sec);
2868 //else
2869 // ret = -EOPNOTSUPP;
2871 return ret;
2874 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2876 int ret=0;
2877 unsigned long flags;
2879 switch (name) {
2880 case IEEE_PARAM_WPA_ENABLED:
2881 ret = ieee80211_wpa_enable(ieee, value);
2882 break;
2884 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2885 ieee->tkip_countermeasures=value;
2886 break;
2888 case IEEE_PARAM_DROP_UNENCRYPTED: {
2889 /* HACK:
2891 * wpa_supplicant calls set_wpa_enabled when the driver
2892 * is loaded and unloaded, regardless of if WPA is being
2893 * used. No other calls are made which can be used to
2894 * determine if encryption will be used or not prior to
2895 * association being expected. If encryption is not being
2896 * used, drop_unencrypted is set to false, else true -- we
2897 * can use this to determine if the CAP_PRIVACY_ON bit should
2898 * be set.
2900 struct ieee80211_security sec = {
2901 .flags = SEC_ENABLED,
2902 .enabled = value,
2904 ieee->drop_unencrypted = value;
2905 /* We only change SEC_LEVEL for open mode. Others
2906 * are set by ipw_wpa_set_encryption.
2908 if (!value) {
2909 sec.flags |= SEC_LEVEL;
2910 sec.level = SEC_LEVEL_0;
2912 else {
2913 sec.flags |= SEC_LEVEL;
2914 sec.level = SEC_LEVEL_1;
2916 if (ieee->set_security)
2917 ieee->set_security(ieee->dev, &sec);
2918 break;
2921 case IEEE_PARAM_PRIVACY_INVOKED:
2922 ieee->privacy_invoked=value;
2923 break;
2925 case IEEE_PARAM_AUTH_ALGS:
2926 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2927 break;
2929 case IEEE_PARAM_IEEE_802_1X:
2930 ieee->ieee802_1x=value;
2931 break;
2932 case IEEE_PARAM_WPAX_SELECT:
2933 // added for WPA2 mixed mode
2934 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2935 ieee->wpax_type_set = 1;
2936 ieee->wpax_type_notify = value;
2937 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
2938 break;
2940 default:
2941 printk("Unknown WPA param: %d\n",name);
2942 ret = -EOPNOTSUPP;
2945 return ret;
2948 /* implementation borrowed from hostap driver */
2950 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2951 struct ieee_param *param, int param_len)
2953 int ret = 0;
2955 struct ieee80211_crypto_ops *ops;
2956 struct ieee80211_crypt_data **crypt;
2958 struct ieee80211_security sec = {
2959 .flags = 0,
2962 param->u.crypt.err = 0;
2963 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2965 if (param_len !=
2966 (int) ((char *) param->u.crypt.key - (char *) param) +
2967 param->u.crypt.key_len) {
2968 printk("Len mismatch %d, %d\n", param_len,
2969 param->u.crypt.key_len);
2970 return -EINVAL;
2972 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
2973 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
2974 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
2975 if (param->u.crypt.idx >= WEP_KEYS)
2976 return -EINVAL;
2977 crypt = &ieee->crypt[param->u.crypt.idx];
2978 } else {
2979 return -EINVAL;
2982 if (strcmp(param->u.crypt.alg, "none") == 0) {
2983 if (crypt) {
2984 sec.enabled = 0;
2985 // FIXME FIXME
2986 //sec.encrypt = 0;
2987 sec.level = SEC_LEVEL_0;
2988 sec.flags |= SEC_ENABLED | SEC_LEVEL;
2989 ieee80211_crypt_delayed_deinit(ieee, crypt);
2991 goto done;
2993 sec.enabled = 1;
2994 // FIXME FIXME
2995 // sec.encrypt = 1;
2996 sec.flags |= SEC_ENABLED;
2998 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2999 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3000 strcmp(param->u.crypt.alg, "TKIP"))
3001 goto skip_host_crypt;
3003 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3004 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3005 request_module("ieee80211_crypt_wep");
3006 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3007 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3008 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3009 request_module("ieee80211_crypt_tkip");
3010 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3011 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3012 request_module("ieee80211_crypt_ccmp");
3013 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3015 if (ops == NULL) {
3016 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3017 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3018 ret = -EINVAL;
3019 goto done;
3022 if (*crypt == NULL || (*crypt)->ops != ops) {
3023 struct ieee80211_crypt_data *new_crypt;
3025 ieee80211_crypt_delayed_deinit(ieee, crypt);
3027 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3028 if (new_crypt == NULL) {
3029 ret = -ENOMEM;
3030 goto done;
3032 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3033 new_crypt->ops = ops;
3034 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3035 new_crypt->priv =
3036 new_crypt->ops->init(param->u.crypt.idx);
3038 if (new_crypt->priv == NULL) {
3039 kfree(new_crypt);
3040 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3041 ret = -EINVAL;
3042 goto done;
3045 *crypt = new_crypt;
3048 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3049 (*crypt)->ops->set_key(param->u.crypt.key,
3050 param->u.crypt.key_len, param->u.crypt.seq,
3051 (*crypt)->priv) < 0) {
3052 printk("key setting failed\n");
3053 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3054 ret = -EINVAL;
3055 goto done;
3058 skip_host_crypt:
3059 if (param->u.crypt.set_tx) {
3060 ieee->tx_keyidx = param->u.crypt.idx;
3061 sec.active_key = param->u.crypt.idx;
3062 sec.flags |= SEC_ACTIVE_KEY;
3063 } else
3064 sec.flags &= ~SEC_ACTIVE_KEY;
3066 if (param->u.crypt.alg != NULL) {
3067 memcpy(sec.keys[param->u.crypt.idx],
3068 param->u.crypt.key,
3069 param->u.crypt.key_len);
3070 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3071 sec.flags |= (1 << param->u.crypt.idx);
3073 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3074 sec.flags |= SEC_LEVEL;
3075 sec.level = SEC_LEVEL_1;
3076 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3077 sec.flags |= SEC_LEVEL;
3078 sec.level = SEC_LEVEL_2;
3079 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3080 sec.flags |= SEC_LEVEL;
3081 sec.level = SEC_LEVEL_3;
3084 done:
3085 if (ieee->set_security)
3086 ieee->set_security(ieee->dev, &sec);
3088 /* Do not reset port if card is in Managed mode since resetting will
3089 * generate new IEEE 802.11 authentication which may end up in looping
3090 * with IEEE 802.1X. If your hardware requires a reset after WEP
3091 * configuration (for example... Prism2), implement the reset_port in
3092 * the callbacks structures used to initialize the 802.11 stack. */
3093 if (ieee->reset_on_keychange &&
3094 ieee->iw_mode != IW_MODE_INFRA &&
3095 ieee->reset_port &&
3096 ieee->reset_port(ieee->dev)) {
3097 printk("reset_port failed\n");
3098 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3099 return -EINVAL;
3102 return ret;
3105 inline struct sk_buff *ieee80211_disassociate_skb(
3106 struct ieee80211_network *beacon,
3107 struct ieee80211_device *ieee,
3108 u8 asRsn)
3110 struct sk_buff *skb;
3111 struct ieee80211_disassoc *disass;
3113 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3114 if (!skb)
3115 return NULL;
3117 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3118 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3119 disass->header.duration_id = 0;
3121 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3122 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3123 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3125 disass->reason = asRsn;
3126 return skb;
3130 void
3131 SendDisassociation(
3132 struct ieee80211_device *ieee,
3133 u8* asSta,
3134 u8 asRsn
3137 struct ieee80211_network *beacon = &ieee->current_network;
3138 struct sk_buff *skb;
3139 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3140 if (skb){
3141 softmac_mgmt_xmit(skb, ieee);
3142 //dev_kfree_skb_any(skb);//edit by thomas
3146 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3148 struct ieee_param *param;
3149 int ret=0;
3151 down(&ieee->wx_sem);
3152 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3154 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3155 ret = -EINVAL;
3156 goto out;
3159 param = kmalloc(p->length, GFP_KERNEL);
3160 if (param == NULL){
3161 ret = -ENOMEM;
3162 goto out;
3164 if (copy_from_user(param, p->pointer, p->length)) {
3165 kfree(param);
3166 ret = -EFAULT;
3167 goto out;
3170 switch (param->cmd) {
3172 case IEEE_CMD_SET_WPA_PARAM:
3173 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3174 param->u.wpa_param.value);
3175 break;
3177 case IEEE_CMD_SET_WPA_IE:
3178 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3179 break;
3181 case IEEE_CMD_SET_ENCRYPTION:
3182 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3183 break;
3185 case IEEE_CMD_MLME:
3186 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3187 param->u.mlme.reason_code);
3188 break;
3190 default:
3191 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3192 ret = -EOPNOTSUPP;
3193 break;
3196 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3197 ret = -EFAULT;
3199 kfree(param);
3200 out:
3201 up(&ieee->wx_sem);
3203 return ret;
3206 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3208 union iwreq_data wrqu;
3209 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3210 if (ieee->state == IEEE80211_LINKED)
3211 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3212 else
3213 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3214 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3217 EXPORT_SYMBOL(ieee80211_get_beacon);
3218 EXPORT_SYMBOL(ieee80211_wake_queue);
3219 EXPORT_SYMBOL(ieee80211_stop_queue);
3220 EXPORT_SYMBOL(ieee80211_reset_queue);
3221 EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
3222 EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
3223 EXPORT_SYMBOL(ieee80211_is_shortslot);
3224 EXPORT_SYMBOL(ieee80211_is_54g);
3225 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3226 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
3227 EXPORT_SYMBOL(ieee80211_softmac_xmit);
3228 EXPORT_SYMBOL(ieee80211_stop_send_beacons);
3229 EXPORT_SYMBOL(notify_wx_assoc_event);
3230 EXPORT_SYMBOL(SendDisassociation);
3231 EXPORT_SYMBOL(ieee80211_disassociate);
3232 EXPORT_SYMBOL(ieee80211_start_send_beacons);
3233 EXPORT_SYMBOL(ieee80211_stop_scan);
3234 EXPORT_SYMBOL(ieee80211_send_probe_requests);
3235 EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
3236 EXPORT_SYMBOL(ieee80211_start_scan_syncro);
3237 //EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame);