GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / staging / rtl8192su / ieee80211 / ieee80211_softmac.c
blob1eac08a20eb7a7f538d00c5221cc1eff15cb5dd2
1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andreamrl@tiscali.it>
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
13 * released under the GPL
17 #include "ieee80211.h"
19 #include <linux/random.h>
20 #include <linux/delay.h>
21 #include <linux/slab.h>
22 #include <linux/version.h>
23 #include <asm/uaccess.h>
24 #include "dot11d.h"
26 u8 rsn_authen_cipher_suite[16][4] = {
27 {0x00,0x0F,0xAC,0x00}, //Use group key, //Reserved
28 {0x00,0x0F,0xAC,0x01}, //WEP-40 //RSNA default
29 {0x00,0x0F,0xAC,0x02}, //TKIP //NONE //{used just as default}
30 {0x00,0x0F,0xAC,0x03}, //WRAP-historical
31 {0x00,0x0F,0xAC,0x04}, //CCMP
32 {0x00,0x0F,0xAC,0x05}, //WEP-104
35 short ieee80211_is_54g(struct ieee80211_network net)
37 return ((net.rates_ex_len > 0) || (net.rates_len > 4));
40 short ieee80211_is_shortslot(struct ieee80211_network net)
42 return (net.capability & WLAN_CAPABILITY_SHORT_SLOT);
45 /* returns the total length needed for pleacing the RATE MFIE
46 * tag and the EXTENDED RATE MFIE tag if needed.
47 * It encludes two bytes per tag for the tag itself and its len
49 unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
51 unsigned int rate_len = 0;
53 if (ieee->modulation & IEEE80211_CCK_MODULATION)
54 rate_len = IEEE80211_CCK_RATE_LEN + 2;
56 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
58 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
60 return rate_len;
63 /* pleace the MFIE rate, tag to the memory (double) poined.
64 * Then it updates the pointer so that
65 * it points after the new MFIE tag added.
67 void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
69 u8 *tag = *tag_p;
71 if (ieee->modulation & IEEE80211_CCK_MODULATION){
72 *tag++ = MFIE_TYPE_RATES;
73 *tag++ = 4;
74 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
75 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
76 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
77 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
80 /* We may add an option for custom rates that specific HW might support */
81 *tag_p = tag;
84 void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
86 u8 *tag = *tag_p;
88 if (ieee->modulation & IEEE80211_OFDM_MODULATION){
90 *tag++ = MFIE_TYPE_RATES_EX;
91 *tag++ = 8;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
94 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
95 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
96 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
97 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
98 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
99 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
103 /* We may add an option for custom rates that specific HW might support */
104 *tag_p = tag;
108 void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p) {
109 u8 *tag = *tag_p;
111 *tag++ = MFIE_TYPE_GENERIC; //0
112 *tag++ = 7;
113 *tag++ = 0x00;
114 *tag++ = 0x50;
115 *tag++ = 0xf2;
116 *tag++ = 0x02;//5
117 *tag++ = 0x00;
118 *tag++ = 0x01;
119 #ifdef SUPPORT_USPD
120 if(ieee->current_network.wmm_info & 0x80) {
121 *tag++ = 0x0f|MAX_SP_Len;
122 } else {
123 *tag++ = MAX_SP_Len;
125 #else
126 *tag++ = MAX_SP_Len;
127 #endif
128 *tag_p = tag;
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");
148 void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
150 int nh;
151 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
154 * if the queue is full but we have newer frames then
155 * just overwrites the oldest.
157 * if (nh == ieee->mgmt_queue_tail)
158 * return -1;
160 ieee->mgmt_queue_head = nh;
161 ieee->mgmt_queue_ring[nh] = skb;
165 struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
167 struct sk_buff *ret;
169 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
170 return NULL;
172 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
174 ieee->mgmt_queue_tail =
175 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
177 return ret;
180 void init_mgmt_queue(struct ieee80211_device *ieee)
182 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
186 MgntQuery_TxRateExcludeCCKRates(struct ieee80211_device *ieee)
188 u16 i;
189 u8 QueryRate = 0;
190 u8 BasicRate;
193 for( i = 0; i < ieee->current_network.rates_len; i++)
195 BasicRate = ieee->current_network.rates[i]&0x7F;
196 if(!ieee80211_is_cck_rate(BasicRate))
198 if(QueryRate == 0)
200 QueryRate = BasicRate;
202 else
204 if(BasicRate < QueryRate)
206 QueryRate = BasicRate;
212 if(QueryRate == 0)
214 QueryRate = 12;
215 printk("No BasicRate found!!\n");
217 return QueryRate;
219 u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
221 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
222 u8 rate;
224 if(pHTInfo->IOTAction & HT_IOT_ACT_WA_IOT_Broadcom)
226 rate = MgntQuery_TxRateExcludeCCKRates(ieee);
228 else
229 rate = ieee->basic_rate & 0x7f;
231 if(rate == 0){
232 if(ieee->mode == IEEE_A||
233 ieee->mode== IEEE_N_5G||
234 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
235 rate = 0x0c;
236 else
237 rate = 0x02;
239 return rate;
243 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
245 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
247 unsigned long flags;
248 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
249 struct ieee80211_hdr_3addr *header=
250 (struct ieee80211_hdr_3addr *) skb->data;
252 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
253 spin_lock_irqsave(&ieee->lock, flags);
255 /* called with 2nd param 0, no mgmt lock required */
256 ieee80211_sta_wakeup(ieee,0);
258 tcb_desc->queue_index = MGNT_QUEUE;
259 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
260 tcb_desc->RATRIndex = 7;
261 tcb_desc->bTxDisableRateFallBack = 1;
262 tcb_desc->bTxUseDriverAssingedRate = 1;
264 if(single){
265 if(ieee->queue_stop){
266 enqueue_mgmt(ieee,skb);
267 }else{
268 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
270 if (ieee->seq_ctrl[0] == 0xFFF)
271 ieee->seq_ctrl[0] = 0;
272 else
273 ieee->seq_ctrl[0]++;
275 /* avoid watchdog triggers */
276 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
279 spin_unlock_irqrestore(&ieee->lock, flags);
280 }else{
281 spin_unlock_irqrestore(&ieee->lock, flags);
282 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
284 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
286 if (ieee->seq_ctrl[0] == 0xFFF)
287 ieee->seq_ctrl[0] = 0;
288 else
289 ieee->seq_ctrl[0]++;
291 /* check wether the managed packet queued greater than 5 */
292 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
293 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
294 (ieee->queue_stop) ) {
295 /* insert the skb packet to the management queue */
296 /* as for the completion function, it does not need
297 * to check it any more.
298 * */
299 printk("%s():insert to waitqueue!\n",__FUNCTION__);
300 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
301 } else {
302 ieee->softmac_hard_start_xmit(skb,ieee->dev);
304 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
308 inline void softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
311 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
312 struct ieee80211_hdr_3addr *header =
313 (struct ieee80211_hdr_3addr *) skb->data;
314 u16 fc,type,stype;
315 cb_desc *tcb_desc = (cb_desc *)(skb->cb + 8);
317 fc = header->frame_control;
318 type = WLAN_FC_GET_TYPE(fc);
319 stype = WLAN_FC_GET_STYPE(fc);
322 if(stype != IEEE80211_STYPE_PSPOLL)
323 tcb_desc->queue_index = MGNT_QUEUE;
324 else
325 tcb_desc->queue_index = HIGH_QUEUE;
326 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
327 tcb_desc->RATRIndex = 7;
328 tcb_desc->bTxDisableRateFallBack = 1;
329 tcb_desc->bTxUseDriverAssingedRate = 1;
330 if(single){
331 if(!(type == IEEE80211_FTYPE_CTL)) {
332 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
334 if (ieee->seq_ctrl[0] == 0xFFF)
335 ieee->seq_ctrl[0] = 0;
336 else
337 ieee->seq_ctrl[0]++;
340 /* avoid watchdog triggers */
341 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
343 }else{
344 if(!(type == IEEE80211_FTYPE_CTL)) {
345 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
347 if (ieee->seq_ctrl[0] == 0xFFF)
348 ieee->seq_ctrl[0] = 0;
349 else
350 ieee->seq_ctrl[0]++;
353 ieee->softmac_hard_start_xmit(skb,ieee->dev);
358 inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
360 unsigned int len,rate_len;
361 u8 *tag;
362 struct sk_buff *skb;
363 struct ieee80211_probe_request *req;
365 len = ieee->current_network.ssid_len;
367 rate_len = ieee80211_MFIE_rate_len(ieee);
369 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
370 2 + len + rate_len + ieee->tx_headroom);
371 if (!skb)
372 return NULL;
374 skb_reserve(skb, ieee->tx_headroom);
376 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
377 req->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
378 req->header.duration_id = 0;
380 memset(req->header.addr1, 0xff, ETH_ALEN);
381 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
382 memset(req->header.addr3, 0xff, ETH_ALEN);
384 tag = (u8 *) skb_put(skb,len+2+rate_len);
386 *tag++ = MFIE_TYPE_SSID;
387 *tag++ = len;
388 memcpy(tag, ieee->current_network.ssid, len);
389 tag += len;
391 ieee80211_MFIE_Brate(ieee,&tag);
392 ieee80211_MFIE_Grate(ieee,&tag);
393 return skb;
396 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
397 void ieee80211_send_beacon(struct ieee80211_device *ieee)
399 struct sk_buff *skb;
400 if(!ieee->ieee_up)
401 return;
402 skb = ieee80211_get_beacon_(ieee);
404 if (skb){
405 softmac_mgmt_xmit(skb, ieee);
406 ieee->softmac_stats.tx_beacons++;
409 if(ieee->beacon_txing && ieee->ieee_up){
410 mod_timer(&ieee->beacon_timer,jiffies+(MSECS(ieee->current_network.beacon_interval-5)));
415 void ieee80211_send_beacon_cb(unsigned long _ieee)
417 struct ieee80211_device *ieee =
418 (struct ieee80211_device *) _ieee;
419 unsigned long flags;
421 spin_lock_irqsave(&ieee->beacon_lock, flags);
422 ieee80211_send_beacon(ieee);
423 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
427 void ieee80211_send_probe(struct ieee80211_device *ieee)
429 struct sk_buff *skb;
431 skb = ieee80211_probe_req(ieee);
432 if (skb){
433 softmac_mgmt_xmit(skb, ieee);
434 ieee->softmac_stats.tx_probe_rq++;
438 void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
440 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)){
441 ieee80211_send_probe(ieee);
442 ieee80211_send_probe(ieee);
446 /* this performs syncro scan blocking the caller until all channels
447 * in the allowed channel map has been checked.
449 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
451 short ch = 0;
452 u8 channel_map[MAX_CHANNEL_NUMBER+1];
453 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
454 ieee->be_scan_inprogress = true;
455 down(&ieee->scan_sem);
457 while(1)
461 ch++;
462 if (ch > MAX_CHANNEL_NUMBER)
463 goto out; /* scan completed */
464 }while(!channel_map[ch]);
466 /* this fuction can be called in two situations
467 * 1- We have switched to ad-hoc mode and we are
468 * performing a complete syncro scan before conclude
469 * there are no interesting cell and to create a
470 * new one. In this case the link state is
471 * IEEE80211_NOLINK until we found an interesting cell.
472 * If so the ieee8021_new_net, called by the RX path
473 * will set the state to IEEE80211_LINKED, so we stop
474 * scanning
475 * 2- We are linked and the root uses run iwlist scan.
476 * So we switch to IEEE80211_LINKED_SCANNING to remember
477 * that we are still logically linked (not interested in
478 * new network events, despite for updating the net list,
479 * but we are temporarly 'unlinked' as the driver shall
480 * not filter RX frames and the channel is changing.
481 * So the only situation in witch are interested is to check
482 * if the state become LINKED because of the #1 situation
485 if (ieee->state == IEEE80211_LINKED)
486 goto out;
487 ieee->set_chan(ieee->dev, ch);
488 if(channel_map[ch] == 1)
489 ieee80211_send_probe_requests(ieee);
491 /* this prevent excessive time wait when we
492 * need to wait for a syncro scan to end..
494 if(ieee->state < IEEE80211_LINKED)
496 else
497 if (ieee->sync_scan_hurryup)
498 goto out;
501 msleep_interruptible_rsl(IEEE80211_SOFTMAC_SCAN_TIME);
504 out:
505 if(ieee->state < IEEE80211_LINKED){
506 ieee->actscanning = false;
507 up(&ieee->scan_sem);
508 ieee->be_scan_inprogress = false;
510 else{
511 ieee->sync_scan_hurryup = 0;
512 if(IS_DOT11D_ENABLE(ieee))
513 DOT11D_ScanComplete(ieee);
514 up(&ieee->scan_sem);
515 ieee->be_scan_inprogress = false;
519 void ieee80211_softmac_scan_wq(struct work_struct *work)
521 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
522 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
523 u8 last_channel = ieee->current_network.channel; //recored init channel inorder not change current channel when comming out the scan unexpectedly. WB.
524 u8 channel_map[MAX_CHANNEL_NUMBER+1];
525 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
526 if(!ieee->ieee_up)
527 return;
528 down(&ieee->scan_sem);
530 ieee->current_network.channel =
531 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
532 if (ieee->scan_watch_dog++ > MAX_CHANNEL_NUMBER)
534 //if current channel is not in channel map, set to default channel.
535 if (!channel_map[ieee->current_network.channel]);
536 ieee->current_network.channel = 6;
537 goto out; /* no good chans */
539 }while(!channel_map[ieee->current_network.channel]);
540 if (ieee->scanning == 0 )
541 goto out;
542 ieee->set_chan(ieee->dev, ieee->current_network.channel);
543 if(channel_map[ieee->current_network.channel] == 1)
544 ieee80211_send_probe_requests(ieee);
546 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
548 up(&ieee->scan_sem);
549 return;
550 out:
551 if(IS_DOT11D_ENABLE(ieee))
552 DOT11D_ScanComplete(ieee);
553 ieee->current_network.channel = last_channel;
554 ieee->actscanning = false;
555 ieee->scan_watch_dog = 0;
556 ieee->scanning = 0;
557 up(&ieee->scan_sem);
560 void ieee80211_beacons_start(struct ieee80211_device *ieee)
562 unsigned long flags;
563 spin_lock_irqsave(&ieee->beacon_lock,flags);
565 ieee->beacon_txing = 1;
566 ieee80211_send_beacon(ieee);
568 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
571 void ieee80211_beacons_stop(struct ieee80211_device *ieee)
573 unsigned long flags;
575 spin_lock_irqsave(&ieee->beacon_lock,flags);
577 ieee->beacon_txing = 0;
578 del_timer_sync(&ieee->beacon_timer);
580 spin_unlock_irqrestore(&ieee->beacon_lock,flags);
585 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
587 if(ieee->stop_send_beacons)
588 ieee->stop_send_beacons(ieee->dev);
589 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
590 ieee80211_beacons_stop(ieee);
594 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
596 if(ieee->start_send_beacons)
597 ieee->start_send_beacons(ieee->dev);
598 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
599 ieee80211_beacons_start(ieee);
603 void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
606 down(&ieee->scan_sem);
607 ieee->scan_watch_dog = 0;
608 if (ieee->scanning == 1){
609 ieee->scanning = 0;
611 cancel_delayed_work(&ieee->softmac_scan_wq);
614 up(&ieee->scan_sem);
617 void ieee80211_stop_scan(struct ieee80211_device *ieee)
619 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
620 ieee80211_softmac_stop_scan(ieee);
621 else
622 ieee->stop_scan(ieee->dev);
625 /* called with ieee->lock held */
626 void ieee80211_rtl_start_scan(struct ieee80211_device *ieee)
628 if(IS_DOT11D_ENABLE(ieee) )
630 if(IS_COUNTRY_IE_VALID(ieee))
632 RESET_CIE_WATCHDOG(ieee);
635 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
636 if (ieee->scanning == 0){
637 ieee->scanning = 1;
638 queue_delayed_work(ieee->wq, &ieee->softmac_scan_wq, 0);
640 }else
641 ieee->start_scan(ieee->dev);
645 /* called with wx_sem held */
646 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
648 if(IS_DOT11D_ENABLE(ieee) )
650 if(IS_COUNTRY_IE_VALID(ieee))
652 RESET_CIE_WATCHDOG(ieee);
655 ieee->sync_scan_hurryup = 0;
656 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
657 ieee80211_softmac_scan_syncro(ieee);
658 else
659 ieee->scan_syncro(ieee->dev);
663 inline struct sk_buff *ieee80211_authentication_req(struct ieee80211_network *beacon,
664 struct ieee80211_device *ieee, int challengelen)
666 struct sk_buff *skb;
667 struct ieee80211_authentication *auth;
668 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
671 skb = dev_alloc_skb(len);
672 if (!skb) return NULL;
674 skb_reserve(skb, ieee->tx_headroom);
675 auth = (struct ieee80211_authentication *)
676 skb_put(skb, sizeof(struct ieee80211_authentication));
678 auth->header.frame_control = IEEE80211_STYPE_AUTH;
679 if (challengelen) auth->header.frame_control |= IEEE80211_FCTL_WEP;
681 auth->header.duration_id = 0x013a;
683 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
684 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
685 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
687 if(ieee->auth_mode == 0)
688 auth->algorithm = WLAN_AUTH_OPEN;
689 else if(ieee->auth_mode == 1)
690 auth->algorithm = WLAN_AUTH_SHARED_KEY;
691 else if(ieee->auth_mode == 2)
692 auth->algorithm = WLAN_AUTH_OPEN;//0x80;
693 printk("=================>%s():auth->algorithm is %d\n",__FUNCTION__,auth->algorithm);
694 auth->transaction = cpu_to_le16(ieee->associate_seq);
695 ieee->associate_seq++;
697 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
699 return skb;
703 void constructWMMIE(u8* wmmie, u8* wmm_len,u8 oui_subtype)
705 u8 szQoSOUI[] ={221, 0, 0x00, 0x50, 0xf2, 0x02, 0, 1};
707 if (oui_subtype == OUI_SUBTYPE_QOS_CAPABI)
709 szQoSOUI[0] = 46;
710 szQoSOUI[1] = *wmm_len;
711 memcpy(wmmie,szQoSOUI,3);
712 *wmm_len = 3;
714 else
716 szQoSOUI[1] = *wmm_len + 6;
717 szQoSOUI[6] = oui_subtype;
718 memcpy(wmmie, szQoSOUI, 8);
719 *(wmmie+8) = 0;
720 *wmm_len = 9;
724 static struct sk_buff* ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
726 u8 *tag;
727 int beacon_size;
728 struct ieee80211_probe_response *beacon_buf;
729 struct sk_buff *skb = NULL;
730 int encrypt;
731 int atim_len,erp_len;
732 struct ieee80211_crypt_data* crypt;
734 char *ssid = ieee->current_network.ssid;
735 int ssid_len = ieee->current_network.ssid_len;
736 int rate_len = ieee->current_network.rates_len+2;
737 int rate_ex_len = ieee->current_network.rates_ex_len;
738 int wpa_ie_len = ieee->wpa_ie_len;
739 u8 erpinfo_content = 0;
741 u8* tmp_ht_cap_buf=NULL;
742 u8 tmp_ht_cap_len=0;
743 u8* tmp_ht_info_buf=NULL;
744 u8 tmp_ht_info_len=0;
745 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
746 u8* tmp_generic_ie_buf=NULL;
747 u8 tmp_generic_ie_len=0;
750 u8 wmmie[9] = {0};
751 u8 wmm_len = 0;
753 if(rate_ex_len > 0) rate_ex_len+=2;
755 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
756 atim_len = 4;
757 else
758 atim_len = 0;
760 if((ieee->current_network.mode == IEEE_G)
761 ||( ieee->current_network.mode == IEEE_N_24G && ieee->pHTInfo->bCurSuppCCK)) {
762 erp_len = 3;
763 erpinfo_content = 0;
764 if(ieee->current_network.buseprotection)
765 erpinfo_content |= ERP_UseProtection;
767 else
768 erp_len = 0;
771 crypt = ieee->crypt[ieee->tx_keyidx];
774 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
775 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
776 //HT ralated element
777 if(ieee->pHTInfo->bCurrentHTSupport){
778 tmp_ht_cap_buf =(u8*) &(ieee->pHTInfo->SelfHTCap);
779 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
780 tmp_ht_info_buf =(u8*) &(ieee->pHTInfo->SelfHTInfo);
781 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
783 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
785 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
788 if(pHTInfo->bRegRT2RTAggregation)
790 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
791 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
792 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
796 if(ieee->qos_support){
798 if(ieee->iw_mode == IW_MODE_ADHOC)
800 wmm_len = 1;
801 constructWMMIE(wmmie,&wmm_len,OUI_SUBTYPE_WMM_INFO);
805 beacon_size = sizeof(struct ieee80211_probe_response)+2+
806 ssid_len
807 +3 //channel
808 +rate_len
809 +rate_ex_len
810 +atim_len
811 +erp_len
812 +wpa_ie_len
813 // +tmp_ht_cap_len
814 // +tmp_ht_info_len
815 // +tmp_generic_ie_len
816 // +wmm_len+2
817 +ieee->tx_headroom;
818 skb = dev_alloc_skb(beacon_size);
819 if (!skb)
820 return NULL;
821 skb_reserve(skb, ieee->tx_headroom);
822 beacon_buf = (struct ieee80211_probe_response*) skb_put(skb, (beacon_size - ieee->tx_headroom));
823 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
824 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
825 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
827 beacon_buf->header.duration_id = 0;
828 beacon_buf->beacon_interval =
829 cpu_to_le16(ieee->current_network.beacon_interval);
830 beacon_buf->capability =
831 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
832 beacon_buf->capability |=
833 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); //add short preamble here
835 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
836 cpu_to_le16((beacon_buf->capability |= WLAN_CAPABILITY_SHORT_SLOT));
838 crypt = ieee->crypt[ieee->tx_keyidx];
840 if (encrypt)
841 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
844 beacon_buf->header.frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
845 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
846 beacon_buf->info_element[0].len = ssid_len;
848 tag = (u8*) beacon_buf->info_element[0].data;
850 memcpy(tag, ssid, ssid_len);
852 tag += ssid_len;
854 *(tag++) = MFIE_TYPE_RATES;
855 *(tag++) = rate_len-2;
856 memcpy(tag,ieee->current_network.rates,rate_len-2);
857 tag+=rate_len-2;
859 *(tag++) = MFIE_TYPE_DS_SET;
860 *(tag++) = 1;
861 *(tag++) = ieee->current_network.channel;
863 if(atim_len){
864 u16 val16;
865 *(tag++) = MFIE_TYPE_IBSS_SET;
866 *(tag++) = 2;
867 val16 = cpu_to_le16(ieee->current_network.atim_window);
868 memcpy((u8 *)tag, (u8 *)&val16, 2);
869 tag+=2;
872 if(erp_len){
873 *(tag++) = MFIE_TYPE_ERP;
874 *(tag++) = 1;
875 *(tag++) = erpinfo_content;
878 if(rate_ex_len){
879 *(tag++) = MFIE_TYPE_RATES_EX;
880 *(tag++) = rate_ex_len-2;
881 memcpy(tag,ieee->current_network.rates_ex,rate_ex_len-2);
882 tag+=rate_ex_len-2;
885 if (wpa_ie_len)
887 if (ieee->iw_mode == IW_MODE_ADHOC)
888 {//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
889 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
891 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
892 tag += wpa_ie_len;
895 return skb;
899 struct sk_buff* ieee80211_assoc_resp(struct ieee80211_device *ieee, u8 *dest)
901 struct sk_buff *skb;
902 u8* tag;
904 struct ieee80211_crypt_data* crypt;
905 struct ieee80211_assoc_response_frame *assoc;
906 short encrypt;
908 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
909 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
911 skb = dev_alloc_skb(len);
913 if (!skb)
914 return NULL;
916 skb_reserve(skb, ieee->tx_headroom);
918 assoc = (struct ieee80211_assoc_response_frame *)
919 skb_put(skb,sizeof(struct ieee80211_assoc_response_frame));
921 assoc->header.frame_control = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
922 memcpy(assoc->header.addr1, dest,ETH_ALEN);
923 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
924 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
925 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
926 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
929 if(ieee->short_slot)
930 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
932 if (ieee->host_encrypt)
933 crypt = ieee->crypt[ieee->tx_keyidx];
934 else crypt = NULL;
936 encrypt = ( crypt && crypt->ops);
938 if (encrypt)
939 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
941 assoc->status = 0;
942 assoc->aid = cpu_to_le16(ieee->assoc_id);
943 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
944 else ieee->assoc_id++;
946 tag = (u8*) skb_put(skb, rate_len);
948 ieee80211_MFIE_Brate(ieee, &tag);
949 ieee80211_MFIE_Grate(ieee, &tag);
951 return skb;
954 struct sk_buff* ieee80211_auth_resp(struct ieee80211_device *ieee,int status, u8 *dest)
956 struct sk_buff *skb;
957 struct ieee80211_authentication *auth;
958 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
960 skb = dev_alloc_skb(len);
962 if (!skb)
963 return NULL;
965 skb->len = sizeof(struct ieee80211_authentication);
967 auth = (struct ieee80211_authentication *)skb->data;
969 auth->status = cpu_to_le16(status);
970 auth->transaction = cpu_to_le16(2);
971 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
973 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
974 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
975 memcpy(auth->header.addr1, dest, ETH_ALEN);
976 auth->header.frame_control = cpu_to_le16(IEEE80211_STYPE_AUTH);
977 return skb;
982 struct sk_buff* ieee80211_null_func(struct ieee80211_device *ieee,short pwr)
984 struct sk_buff *skb;
985 struct ieee80211_hdr_3addr* hdr;
987 skb = dev_alloc_skb(sizeof(struct ieee80211_hdr_3addr));
989 if (!skb)
990 return NULL;
992 hdr = (struct ieee80211_hdr_3addr*)skb_put(skb,sizeof(struct ieee80211_hdr_3addr));
994 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
995 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
996 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
998 hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
999 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
1000 (pwr ? IEEE80211_FCTL_PM:0));
1002 return skb;
1008 void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8* dest)
1010 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
1012 if (buf)
1013 softmac_mgmt_xmit(buf, ieee);
1017 void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s, u8* dest)
1019 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
1021 if (buf)
1022 softmac_mgmt_xmit(buf, ieee);
1026 void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
1030 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
1031 if (buf)
1032 softmac_mgmt_xmit(buf, ieee);
1036 inline int SecIsInPMKIDList(struct ieee80211_device *ieee, u8 *bssid)
1038 int i = 0;
1042 if ((ieee->PMKIDList[i].bUsed) && (memcmp(ieee->PMKIDList[i].Bssid, bssid, ETH_ALEN) == 0))
1044 break;
1046 else
1048 i++;
1050 } while (i < NUM_PMKID_CACHE);
1052 if (i == NUM_PMKID_CACHE)
1054 i = -1;
1056 else
1060 return (i);
1063 inline struct sk_buff *ieee80211_association_req(struct ieee80211_network *beacon,struct ieee80211_device *ieee)
1065 struct sk_buff *skb;
1067 struct ieee80211_assoc_request_frame *hdr;
1068 u8 *tag;//,*rsn_ie;
1069 u8* ht_cap_buf = NULL;
1070 u8 ht_cap_len=0;
1071 u8* realtek_ie_buf=NULL;
1072 u8 realtek_ie_len=0;
1073 int wpa_ie_len= ieee->wpa_ie_len;
1074 unsigned int ckip_ie_len=0;
1075 unsigned int ccxrm_ie_len=0;
1076 unsigned int cxvernum_ie_len=0;
1077 struct ieee80211_crypt_data* crypt;
1078 int encrypt;
1079 int PMKCacheIdx;
1081 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1082 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1083 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1085 int len = 0;
1087 crypt = ieee->crypt[ieee->tx_keyidx];
1088 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1090 //Include High Throuput capability && Realtek proprietary
1091 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1093 ht_cap_buf = (u8*)&(ieee->pHTInfo->SelfHTCap);
1094 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1095 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1096 if(ieee->pHTInfo->bCurrentRT2RTAggregation)
1098 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1099 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1100 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1104 if(ieee->qos_support){
1105 wmm_info_len = beacon->qos_data.supported?9:0;
1109 if(beacon->bCkipSupported)
1111 ckip_ie_len = 30+2;
1113 if(beacon->bCcxRmEnable)
1115 ccxrm_ie_len = 6+2;
1117 if( beacon->BssCcxVerNumber >= 2 )
1119 cxvernum_ie_len = 5+2;
1122 PMKCacheIdx = SecIsInPMKIDList(ieee, ieee->current_network.bssid);
1123 if (PMKCacheIdx >= 0)
1125 wpa_ie_len += 18;
1126 printk("[PMK cache]: WPA2 IE length: %x\n", wpa_ie_len);
1129 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1130 + beacon->ssid_len//essid tagged val
1131 + rate_len//rates tagged val
1132 + wpa_ie_len
1133 + wmm_info_len
1134 + turbo_info_len
1135 + ht_cap_len
1136 + realtek_ie_len
1137 + ckip_ie_len
1138 + ccxrm_ie_len
1139 + cxvernum_ie_len
1140 + ieee->tx_headroom;
1142 skb = dev_alloc_skb(len);
1144 if (!skb)
1145 return NULL;
1147 skb_reserve(skb, ieee->tx_headroom);
1149 hdr = (struct ieee80211_assoc_request_frame *)
1150 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1153 hdr->header.frame_control = IEEE80211_STYPE_ASSOC_REQ;
1154 hdr->header.duration_id= 37;
1155 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1156 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1157 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1159 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1161 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1162 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1163 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1165 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1166 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1168 if(ieee->short_slot)
1169 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1170 if (wmm_info_len) //QOS
1171 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1173 hdr->listen_interval = 0xa;
1175 hdr->info_element[0].id = MFIE_TYPE_SSID;
1177 hdr->info_element[0].len = beacon->ssid_len;
1178 tag = skb_put(skb, beacon->ssid_len);
1179 memcpy(tag, beacon->ssid, beacon->ssid_len);
1181 tag = skb_put(skb, rate_len);
1183 ieee80211_MFIE_Brate(ieee, &tag);
1184 ieee80211_MFIE_Grate(ieee, &tag);
1185 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1186 if( beacon->bCkipSupported )
1188 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1189 u8 CcxAironetBuf[30];
1190 OCTET_STRING osCcxAironetIE;
1192 memset(CcxAironetBuf, 0,30);
1193 osCcxAironetIE.Octet = CcxAironetBuf;
1194 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1196 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1197 // We want to make the device type as "4500-client". 060926, by CCW.
1199 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1201 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1202 // "The CKIP negotiation is started with the associate request from the client to the access point,
1203 // containing an Aironet element with both the MIC and KP bits set."
1204 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1205 tag = skb_put(skb, ckip_ie_len);
1206 *tag++ = MFIE_TYPE_AIRONET;
1207 *tag++ = osCcxAironetIE.Length;
1208 memcpy(tag,osCcxAironetIE.Octet,osCcxAironetIE.Length);
1209 tag += osCcxAironetIE.Length;
1212 if(beacon->bCcxRmEnable)
1214 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1215 OCTET_STRING osCcxRmCap;
1217 osCcxRmCap.Octet = CcxRmCapBuf;
1218 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1219 tag = skb_put(skb,ccxrm_ie_len);
1220 *tag++ = MFIE_TYPE_GENERIC;
1221 *tag++ = osCcxRmCap.Length;
1222 memcpy(tag,osCcxRmCap.Octet,osCcxRmCap.Length);
1223 tag += osCcxRmCap.Length;
1226 if( beacon->BssCcxVerNumber >= 2 )
1228 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1229 OCTET_STRING osCcxVerNum;
1230 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1231 osCcxVerNum.Octet = CcxVerNumBuf;
1232 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1233 tag = skb_put(skb,cxvernum_ie_len);
1234 *tag++ = MFIE_TYPE_GENERIC;
1235 *tag++ = osCcxVerNum.Length;
1236 memcpy(tag,osCcxVerNum.Octet,osCcxVerNum.Length);
1237 tag += osCcxVerNum.Length;
1239 //HT cap element
1240 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1241 if(ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1243 tag = skb_put(skb, ht_cap_len);
1244 *tag++ = MFIE_TYPE_HT_CAP;
1245 *tag++ = ht_cap_len - 2;
1246 memcpy(tag, ht_cap_buf,ht_cap_len -2);
1247 tag += ht_cap_len -2;
1252 //choose what wpa_supplicant gives to associate.
1253 tag = skb_put(skb, wpa_ie_len);
1254 if (wpa_ie_len){
1255 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1256 if (PMKCacheIdx >= 0)
1258 tag = skb_put(skb, 18);
1259 *tag = 1;
1260 *(tag + 1) = 0;
1261 memcpy((tag + 2), &ieee->PMKIDList[PMKCacheIdx].PMKID, 16);
1265 tag = skb_put(skb,wmm_info_len);
1266 if(wmm_info_len) {
1267 ieee80211_WMM_Info(ieee, &tag);
1269 tag = skb_put(skb,turbo_info_len);
1270 if(turbo_info_len) {
1271 ieee80211_TURBO_Info(ieee, &tag);
1274 if(ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT){
1275 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1277 tag = skb_put(skb, ht_cap_len);
1278 *tag++ = MFIE_TYPE_GENERIC;
1279 *tag++ = ht_cap_len - 2;
1280 memcpy(tag, ht_cap_buf,ht_cap_len - 2);
1281 tag += ht_cap_len -2;
1284 if(ieee->pHTInfo->bCurrentRT2RTAggregation){
1285 tag = skb_put(skb, realtek_ie_len);
1286 *tag++ = MFIE_TYPE_GENERIC;
1287 *tag++ = realtek_ie_len - 2;
1288 memcpy(tag, realtek_ie_buf,realtek_ie_len -2 );
1291 return skb;
1294 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1297 unsigned long flags;
1298 spin_lock_irqsave(&ieee->lock, flags);
1300 ieee->associate_seq++;
1302 /* don't scan, and avoid to have the RX path possibily
1303 * try again to associate. Even do not react to AUTH or
1304 * ASSOC response. Just wait for the retry wq to be scheduled.
1305 * Here we will check if there are good nets to associate
1306 * with, so we retry or just get back to NO_LINK and scanning
1308 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1309 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1310 ieee->softmac_stats.no_auth_rs++;
1311 }else{
1312 IEEE80211_DEBUG_MGMT("Association failed\n");
1313 ieee->softmac_stats.no_ass_rs++;
1316 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1318 queue_delayed_work(ieee->wq, &ieee->associate_retry_wq, \
1319 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1321 spin_unlock_irqrestore(&ieee->lock, flags);
1324 void ieee80211_associate_abort_cb(unsigned long dev)
1326 ieee80211_associate_abort((struct ieee80211_device *) dev);
1330 void ieee80211_associate_step1(struct ieee80211_device *ieee)
1332 struct ieee80211_network *beacon = &ieee->current_network;
1333 struct sk_buff *skb;
1335 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1337 ieee->softmac_stats.tx_auth_rq++;
1338 skb=ieee80211_authentication_req(beacon, ieee, 0);
1340 if (!skb)
1341 ieee80211_associate_abort(ieee);
1342 else{
1343 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1344 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1345 softmac_mgmt_xmit(skb, ieee);
1346 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1347 if(!timer_pending(&ieee->associate_timer)){
1348 ieee->associate_timer.expires = jiffies + (HZ / 2);
1349 add_timer(&ieee->associate_timer);
1351 //dev_kfree_skb_any(skb);//edit by thomas
1355 void ieee80211_rtl_auth_challenge(struct ieee80211_device *ieee, u8 *challenge, int chlen)
1357 u8 *c;
1358 struct sk_buff *skb;
1359 struct ieee80211_network *beacon = &ieee->current_network;
1361 ieee->associate_seq++;
1362 ieee->softmac_stats.tx_auth_rq++;
1364 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1365 if (!skb)
1366 ieee80211_associate_abort(ieee);
1367 else{
1368 c = skb_put(skb, chlen+2);
1369 *(c++) = MFIE_TYPE_CHALLENGE;
1370 *(c++) = chlen;
1371 memcpy(c, challenge, chlen);
1373 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1375 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct ieee80211_hdr_3addr ));
1377 softmac_mgmt_xmit(skb, ieee);
1378 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1380 kfree(challenge);
1383 void ieee80211_associate_step2(struct ieee80211_device *ieee)
1385 struct sk_buff* skb;
1386 struct ieee80211_network *beacon = &ieee->current_network;
1388 del_timer_sync(&ieee->associate_timer);
1390 IEEE80211_DEBUG_MGMT("Sending association request\n");
1392 ieee->softmac_stats.tx_ass_rq++;
1393 skb=ieee80211_association_req(beacon, ieee);
1394 if (!skb)
1395 ieee80211_associate_abort(ieee);
1396 else{
1397 softmac_mgmt_xmit(skb, ieee);
1398 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1402 void ieee80211_associate_complete_wq(struct work_struct *work)
1404 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1406 printk(KERN_INFO "Associated successfully\n");
1407 ieee->is_roaming = false;
1408 if(ieee80211_is_54g(ieee->current_network) &&
1409 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1411 ieee->rate = 108;
1412 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1413 }else{
1414 ieee->rate = 22;
1415 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1417 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1419 printk("Successfully associated, ht enabled\n");
1420 HTOnAssocRsp(ieee);
1422 else
1424 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1425 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1427 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1428 // To prevent the immediately calling watch_dog after association.
1429 if(ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1431 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1432 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1434 ieee->link_change(ieee->dev);
1435 if(ieee->is_silent_reset == 0){
1436 printk("============>normal associate\n");
1437 notify_wx_assoc_event(ieee);
1439 else if(ieee->is_silent_reset == 1)
1441 printk("==================>silent reset associate\n");
1442 ieee->is_silent_reset = 0;
1445 if (ieee->data_hard_resume)
1446 ieee->data_hard_resume(ieee->dev);
1447 netif_carrier_on(ieee->dev);
1450 void ieee80211_associate_complete(struct ieee80211_device *ieee)
1452 // int i;
1453 // struct net_device* dev = ieee->dev;
1454 del_timer_sync(&ieee->associate_timer);
1456 ieee->state = IEEE80211_LINKED;
1457 queue_work(ieee->wq, &ieee->associate_complete_wq);
1460 void ieee80211_associate_procedure_wq(struct work_struct *work)
1462 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1464 ieee->sync_scan_hurryup = 1;
1465 down(&ieee->wx_sem);
1467 if (ieee->data_hard_stop)
1468 ieee->data_hard_stop(ieee->dev);
1470 ieee80211_stop_scan(ieee);
1471 printk("===>%s(), chan:%d\n", __FUNCTION__, ieee->current_network.channel);
1472 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1474 if(ieee->eRFPowerState == eRfOff)
1476 printk("=============>%s():Rf state is eRfOff, schedule ipsleave wq again,return\n",__FUNCTION__);
1477 up(&ieee->wx_sem);
1478 return;
1480 ieee->associate_seq = 1;
1481 ieee80211_associate_step1(ieee);
1483 up(&ieee->wx_sem);
1486 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1488 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1489 int tmp_ssid_len = 0;
1491 short apset,ssidset,ssidbroad,apmatch,ssidmatch;
1493 /* we are interested in new new only if we are not associated
1494 * and we are not associating / authenticating
1496 if (ieee->state != IEEE80211_NOLINK)
1497 return;
1499 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1500 return;
1502 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1503 return;
1505 if ((ieee->iw_mode == IW_MODE_ADHOC) && (net->channel > ieee->ibss_maxjoin_chal))
1506 return;
1508 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC){
1509 /* if the user specified the AP MAC, we need also the essid
1510 * This could be obtained by beacons or, if the network does not
1511 * broadcast it, it can be put manually.
1513 apset = ieee->wap_set;
1514 ssidset = ieee->ssid_set;
1515 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1516 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1517 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1518 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1521 if ( /* if the user set the AP check if match.
1522 * if the network does not broadcast essid we check the user supplyed ANY essid
1523 * if the network does broadcast and the user does not set essid it is OK
1524 * if the network does broadcast and the user did set essid chech if essid match
1526 ( apset && apmatch &&
1527 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1528 /* if the ap is not set, check that the user set the bssid
1529 * and the network does bradcast and that those two bssid matches
1531 (!apset && ssidset && ssidbroad && ssidmatch)
1533 /* if the essid is hidden replace it with the
1534 * essid provided by the user.
1536 if (!ssidbroad){
1537 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1538 tmp_ssid_len = ieee->current_network.ssid_len;
1540 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1542 if (!ssidbroad){
1543 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1544 ieee->current_network.ssid_len = tmp_ssid_len;
1546 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d, mode:%x\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT, ieee->current_network.mode);
1548 //ieee->pHTInfo->IOTAction = 0;
1549 HTResetIOTSetting(ieee->pHTInfo);
1550 if (ieee->iw_mode == IW_MODE_INFRA){
1551 /* Join the network for the first time */
1552 ieee->AsocRetryCount = 0;
1553 //for HT by amy 080514
1554 if((ieee->current_network.qos_data.supported == 1) &&
1555 ieee->current_network.bssht.bdSupportHT)
1556 /*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.*/
1558 // ieee->pHTInfo->bCurrentHTSupport = true;
1559 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1561 else
1563 ieee->pHTInfo->bCurrentHTSupport = false;
1566 ieee->state = IEEE80211_ASSOCIATING;
1567 if(ieee->LedControlHandler != NULL)
1568 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK);
1569 queue_work(ieee->wq, &ieee->associate_procedure_wq);
1570 }else{
1571 if(ieee80211_is_54g(ieee->current_network) &&
1572 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1573 ieee->rate = 108;
1574 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1575 printk(KERN_INFO"Using G rates\n");
1576 }else{
1577 ieee->rate = 22;
1578 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1579 printk(KERN_INFO"Using B rates\n");
1581 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1582 ieee->state = IEEE80211_LINKED;
1590 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1592 unsigned long flags;
1593 struct ieee80211_network *target;
1595 spin_lock_irqsave(&ieee->lock, flags);
1597 list_for_each_entry(target, &ieee->network_list, list) {
1599 /* if the state become different that NOLINK means
1600 * we had found what we are searching for
1603 if (ieee->state != IEEE80211_NOLINK)
1604 break;
1606 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1607 ieee80211_softmac_new_net(ieee, target);
1610 spin_unlock_irqrestore(&ieee->lock, flags);
1615 static inline u16 auth_parse(struct sk_buff *skb, u8** challenge, int *chlen)
1617 struct ieee80211_authentication *a;
1618 u8 *t;
1619 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1620 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1621 return 0xcafe;
1623 *challenge = NULL;
1624 a = (struct ieee80211_authentication*) skb->data;
1625 if(skb->len > (sizeof(struct ieee80211_authentication) +3)){
1626 t = skb->data + sizeof(struct ieee80211_authentication);
1628 if(*(t++) == MFIE_TYPE_CHALLENGE){
1629 *chlen = *(t++);
1630 *challenge = kmalloc(*chlen, GFP_ATOMIC);
1631 memcpy(*challenge, t, *chlen);
1635 return cpu_to_le16(a->status);
1640 int auth_rq_parse(struct sk_buff *skb,u8* dest)
1642 struct ieee80211_authentication *a;
1644 if (skb->len < (sizeof(struct ieee80211_authentication)-sizeof(struct ieee80211_info_element))){
1645 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1646 return -1;
1648 a = (struct ieee80211_authentication*) skb->data;
1650 memcpy(dest,a->header.addr2, ETH_ALEN);
1652 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1653 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1655 return WLAN_STATUS_SUCCESS;
1658 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1660 u8 *tag;
1661 u8 *skbend;
1662 u8 *ssid=NULL;
1663 u8 ssidlen = 0;
1665 struct ieee80211_hdr_3addr *header =
1666 (struct ieee80211_hdr_3addr *) skb->data;
1668 if (skb->len < sizeof (struct ieee80211_hdr_3addr ))
1669 return -1; /* corrupted */
1671 if((memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) != 0)&&
1672 (memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) != 0)) {
1673 return -1;
1676 if(memcmp(header->addr3,ieee->current_network.bssid,ETH_ALEN) == 0) {
1679 if(memcmp(header->addr3,"\xff\xff\xff\xff\xff\xff",ETH_ALEN) == 0) {
1681 memcpy(src,header->addr2, ETH_ALEN);
1683 skbend = (u8*)skb->data + skb->len;
1685 tag = skb->data + sizeof (struct ieee80211_hdr_3addr );
1687 while (tag+1 < skbend){
1688 if (*tag == 0){
1689 ssid = tag+2;
1690 ssidlen = *(tag+1);
1691 break;
1693 tag++; /* point to the len field */
1694 tag = tag + *(tag); /* point to the last data byte of the tag */
1695 tag++; /* point to the next tag */
1698 if (ssidlen == 0) return 1;
1700 if (!ssid) return 1; /* ssid not found in tagged param */
1701 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1705 int assoc_rq_parse(struct sk_buff *skb,u8* dest)
1707 struct ieee80211_assoc_request_frame *a;
1709 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1710 sizeof(struct ieee80211_info_element))) {
1712 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1713 return -1;
1716 a = (struct ieee80211_assoc_request_frame*) skb->data;
1718 memcpy(dest,a->header.addr2,ETH_ALEN);
1720 return 0;
1723 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1725 struct ieee80211_assoc_response_frame *response_head;
1726 u16 status_code;
1728 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)){
1729 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1730 return 0xcafe;
1733 response_head = (struct ieee80211_assoc_response_frame*) skb->data;
1734 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1736 status_code = le16_to_cpu(response_head->status);
1737 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1738 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1739 ((ieee->mode == IEEE_G) &&
1740 (ieee->current_network.mode == IEEE_N_24G) &&
1741 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1742 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1743 }else {
1744 ieee->AsocRetryCount = 0;
1747 return le16_to_cpu(response_head->status);
1750 static inline void
1751 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1753 u8 dest[ETH_ALEN];
1755 ieee->softmac_stats.rx_probe_rq++;
1756 if (probe_rq_parse(ieee, skb, dest)){
1757 ieee->softmac_stats.tx_probe_rs++;
1758 ieee80211_resp_to_probe(ieee, dest);
1762 static inline void
1763 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1765 u8 dest[ETH_ALEN];
1766 int status;
1767 ieee->softmac_stats.rx_auth_rq++;
1769 status = auth_rq_parse(skb, dest);
1770 if (status != -1) {
1771 ieee80211_resp_to_auth(ieee, status, dest);
1776 static inline void
1777 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1780 u8 dest[ETH_ALEN];
1782 ieee->softmac_stats.rx_ass_rq++;
1783 if (assoc_rq_parse(skb,dest) != -1){
1784 ieee80211_resp_to_assoc_rq(ieee, dest);
1787 printk(KERN_INFO"New client associated: %pM\n", dest);
1792 void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee, short pwr)
1795 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1797 if (buf)
1798 softmac_ps_mgmt_xmit(buf, ieee);
1803 short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h, u32 *time_l)
1805 int timeout = ieee->ps_timeout;
1806 u8 dtim;
1807 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1808 ieee->iw_mode != IW_MODE_INFRA ||
1809 ieee->state != IEEE80211_LINKED)
1811 return 0;
1813 dtim = ieee->current_network.dtim_data;
1814 if(!(dtim & IEEE80211_DTIM_VALID))
1815 return 0;
1816 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1817 //printk("VALID\n");
1818 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1820 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1821 return 2;
1823 if(!time_after(jiffies, ieee->dev->trans_start + MSECS(timeout)))
1824 return 0;
1826 if(!time_after(jiffies, ieee->last_rx_ps_time + MSECS(timeout)))
1827 return 0;
1829 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1830 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1831 return 0;
1833 if(time_l){
1834 *time_l = ieee->current_network.last_dtim_sta_time[0]
1835 + (ieee->current_network.beacon_interval);
1838 if(time_h){
1839 *time_h = ieee->current_network.last_dtim_sta_time[1];
1840 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1841 *time_h += 1;
1844 return 1;
1849 inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1852 u32 th,tl;
1853 short sleep;
1855 unsigned long flags,flags2;
1857 spin_lock_irqsave(&ieee->lock, flags);
1859 if((ieee->ps == IEEE80211_PS_DISABLED ||
1860 ieee->iw_mode != IW_MODE_INFRA ||
1861 ieee->state != IEEE80211_LINKED)){
1863 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1865 ieee80211_sta_wakeup(ieee, 1);
1867 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1870 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1871 /* 2 wake, 1 sleep, 0 do nothing */
1872 if(sleep == 0)
1873 goto out;
1875 if(sleep == 1){
1877 if(ieee->sta_sleep == 1)
1878 ieee->enter_sleep_state(ieee->dev,th,tl);
1880 else if(ieee->sta_sleep == 0){
1881 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1883 if(ieee->ps_is_queue_empty(ieee->dev)){
1886 ieee->sta_sleep = 2;
1888 ieee->ack_tx_to_ieee = 1;
1890 ieee80211_sta_ps_send_null_frame(ieee,1);
1892 ieee->ps_th = th;
1893 ieee->ps_tl = tl;
1895 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1900 }else if(sleep == 2){
1901 //#warning CHECK_LOCK_HERE
1902 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1904 ieee80211_sta_wakeup(ieee,1);
1906 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1909 out:
1910 spin_unlock_irqrestore(&ieee->lock, flags);
1914 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1916 if(ieee->sta_sleep == 0){
1917 if(nl){
1918 printk("Warning: driver is probably failing to report TX ps error\n");
1919 ieee->ack_tx_to_ieee = 1;
1920 ieee80211_sta_ps_send_null_frame(ieee, 0);
1922 return;
1926 if(ieee->sta_sleep == 1)
1927 ieee->sta_wake_up(ieee->dev);
1929 ieee->sta_sleep = 0;
1931 if(nl){
1932 ieee->ack_tx_to_ieee = 1;
1933 ieee80211_sta_ps_send_null_frame(ieee, 0);
1937 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1939 unsigned long flags,flags2;
1941 spin_lock_irqsave(&ieee->lock, flags);
1943 if(ieee->sta_sleep == 2){
1944 /* Null frame with PS bit set */
1945 if(success){
1946 ieee->sta_sleep = 1;
1947 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1949 /* if the card report not success we can't be sure the AP
1950 * has not RXed so we can't assume the AP believe us awake
1953 /* 21112005 - tx again null without PS bit if lost */
1954 else {
1956 if((ieee->sta_sleep == 0) && !success){
1957 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1958 ieee80211_sta_ps_send_null_frame(ieee, 0);
1959 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1962 spin_unlock_irqrestore(&ieee->lock, flags);
1964 void ieee80211_process_action(struct ieee80211_device* ieee, struct sk_buff* skb)
1966 struct rtl_ieee80211_hdr *header =
1967 (struct rtl_ieee80211_hdr *)skb->data;
1968 u8* act = ieee80211_get_payload(header);
1969 u8 tmp = 0;
1970 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1971 if (act == NULL)
1973 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1974 return;
1976 tmp = *act;
1977 act ++;
1978 switch (tmp)
1980 case ACT_CAT_BA:
1981 if (*act == ACT_ADDBAREQ)
1982 ieee80211_rx_ADDBAReq(ieee, skb);
1983 else if (*act == ACT_ADDBARSP)
1984 ieee80211_rx_ADDBARsp(ieee, skb);
1985 else if (*act == ACT_DELBA)
1986 ieee80211_rx_DELBA(ieee, skb);
1987 break;
1988 default:
1989 break;
1991 return;
1994 inline int
1995 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1996 struct ieee80211_rx_stats *rx_stats, u16 type,
1997 u16 stype)
1999 struct ieee80211_hdr_3addr *header = (struct ieee80211_hdr_3addr *) skb->data;
2000 u16 errcode;
2001 u8* challenge;
2002 int chlen=0;
2003 int aid;
2004 struct ieee80211_assoc_response_frame *assoc_resp;
2005 bool bSupportNmode = true, bHalfSupportNmode = false; //default support N mode, disable halfNmode
2007 if(!ieee->proto_started)
2008 return 0;
2010 switch (WLAN_FC_GET_STYPE(header->frame_control)) {
2012 case IEEE80211_STYPE_ASSOC_RESP:
2013 case IEEE80211_STYPE_REASSOC_RESP:
2015 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2016 WLAN_FC_GET_STYPE(header->frame_control));
2017 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2018 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2019 ieee->iw_mode == IW_MODE_INFRA){
2020 struct ieee80211_network network_resp;
2021 struct ieee80211_network *network = &network_resp;
2023 if (0 == (errcode=assoc_parse(ieee,skb, &aid))){
2024 ieee->state=IEEE80211_LINKED;
2025 ieee->assoc_id = aid;
2026 ieee->softmac_stats.rx_ass_ok++;
2027 /* station support qos */
2028 /* Let the register setting defaultly with Legacy station */
2029 if(ieee->qos_support) {
2030 assoc_resp = (struct ieee80211_assoc_response_frame*)skb->data;
2031 memset(network, 0, sizeof(*network));
2032 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2033 rx_stats->len - sizeof(*assoc_resp),\
2034 network,rx_stats)){
2035 return 1;
2037 else
2038 { //filling the PeerHTCap. //maybe not neccesary as we can get its info from current_network.
2039 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2040 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2042 if (ieee->handle_assoc_response != NULL)
2043 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame*)header, network);
2045 ieee80211_associate_complete(ieee);
2046 } else {
2047 /* aid could not been allocated */
2048 ieee->softmac_stats.rx_ass_err++;
2049 printk(
2050 "Association response status code 0x%x\n",
2051 errcode);
2052 IEEE80211_DEBUG_MGMT(
2053 "Association response status code 0x%x\n",
2054 errcode);
2055 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2056 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2057 } else {
2058 ieee80211_associate_abort(ieee);
2062 break;
2064 case IEEE80211_STYPE_ASSOC_REQ:
2065 case IEEE80211_STYPE_REASSOC_REQ:
2067 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2068 ieee->iw_mode == IW_MODE_MASTER)
2070 ieee80211_rx_assoc_rq(ieee, skb);
2071 break;
2073 case IEEE80211_STYPE_AUTH:
2075 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE){
2076 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING &&
2077 ieee->iw_mode == IW_MODE_INFRA){
2079 IEEE80211_DEBUG_MGMT("Received authentication response");
2081 if (0 == (errcode=auth_parse(skb, &challenge, &chlen))){
2082 if(ieee->open_wep || !challenge){
2083 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
2084 ieee->softmac_stats.rx_auth_rs_ok++;
2085 if(!(ieee->pHTInfo->IOTAction&HT_IOT_ACT_PURE_N_MODE))
2087 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev))
2089 // WEP or TKIP encryption
2090 if(IsHTHalfNmodeAPs(ieee))
2092 bSupportNmode = true;
2093 bHalfSupportNmode = true;
2095 else
2097 bSupportNmode = false;
2098 bHalfSupportNmode = false;
2100 printk("==========>to link with AP using SEC(%d, %d)", bSupportNmode, bHalfSupportNmode);
2103 /* Dummy wirless mode setting to avoid encryption issue */
2104 if(bSupportNmode) {
2105 //N mode setting
2106 ieee->SetWirelessMode(ieee->dev, \
2107 ieee->current_network.mode);
2108 }else{
2109 //b/g mode setting
2110 /*TODO*/
2111 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2114 if (ieee->current_network.mode == IEEE_N_24G && bHalfSupportNmode == true)
2116 printk("===============>entern half N mode\n");
2117 ieee->bHalfWirelessN24GMode = true;
2119 else
2120 ieee->bHalfWirelessN24GMode = false;
2122 ieee80211_associate_step2(ieee);
2123 }else{
2124 ieee80211_rtl_auth_challenge(ieee, challenge, chlen);
2126 }else{
2127 ieee->softmac_stats.rx_auth_rs_err++;
2128 IEEE80211_DEBUG_MGMT("Authentication respose status code 0x%x",errcode);
2130 printk("Authentication respose status code 0x%x",errcode);
2131 ieee80211_associate_abort(ieee);
2134 }else if (ieee->iw_mode == IW_MODE_MASTER){
2135 ieee80211_rx_auth_rq(ieee, skb);
2138 break;
2140 case IEEE80211_STYPE_PROBE_REQ:
2142 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2143 ((ieee->iw_mode == IW_MODE_ADHOC ||
2144 ieee->iw_mode == IW_MODE_MASTER) &&
2145 ieee->state == IEEE80211_LINKED)){
2146 ieee80211_rx_probe_rq(ieee, skb);
2148 break;
2150 case IEEE80211_STYPE_DISASSOC:
2151 case IEEE80211_STYPE_DEAUTH:
2152 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2153 ieee->state == IEEE80211_LINKED &&
2154 ieee->iw_mode == IW_MODE_INFRA){
2155 printk("==========>received disassoc/deauth(%x) frame, reason code:%x\n",WLAN_FC_GET_STYPE(header->frame_control), ((struct ieee80211_disassoc*)skb->data)->reason);
2156 ieee->state = IEEE80211_ASSOCIATING;
2157 ieee->softmac_stats.reassoc++;
2158 ieee->is_roaming = true;
2159 ieee80211_disassociate(ieee);
2160 RemovePeerTS(ieee, header->addr2);
2161 if(ieee->LedControlHandler != NULL)
2162 ieee->LedControlHandler(ieee->dev, LED_CTL_START_TO_LINK); //added by amy for LED 090318
2163 queue_work(ieee->wq, &ieee->associate_procedure_wq);
2165 break;
2166 case IEEE80211_STYPE_MANAGE_ACT:
2167 ieee80211_process_action(ieee,skb);
2168 break;
2169 default:
2170 return -1;
2171 break;
2174 return 0;
2177 /* following are for a simplier TX queue management.
2178 * Instead of using netif_[stop/wake]_queue the driver
2179 * will uses these two function (plus a reset one), that
2180 * will internally uses the kernel netif_* and takes
2181 * care of the ieee802.11 fragmentation.
2182 * So the driver receives a fragment per time and might
2183 * call the stop function when it want without take care
2184 * to have enough room to TX an entire packet.
2185 * This might be useful if each fragment need it's own
2186 * descriptor, thus just keep a total free memory > than
2187 * the max fragmentation threshold is not enough.. If the
2188 * ieee802.11 stack passed a TXB struct then you needed
2189 * to keep N free descriptors where
2190 * N = MAX_PACKET_SIZE / MIN_FRAG_TRESHOLD
2191 * In this way you need just one and the 802.11 stack
2192 * will take care of buffering fragments and pass them to
2193 * to the driver later, when it wakes the queue.
2195 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2198 unsigned int queue_index = txb->queue_index;
2199 unsigned long flags;
2200 int i;
2201 cb_desc *tcb_desc = NULL;
2203 spin_lock_irqsave(&ieee->lock,flags);
2205 /* called with 2nd parm 0, no tx mgmt lock required */
2206 ieee80211_sta_wakeup(ieee,0);
2208 /* update the tx status */
2209 ieee->stats.tx_bytes += txb->payload_size;
2210 ieee->stats.tx_packets++;
2211 tcb_desc = (cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2212 if(tcb_desc->bMulticast) {
2213 ieee->stats.multicast++;
2215 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2216 for(i = 0; i < txb->nr_frags; i++) {
2217 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2218 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2219 (ieee->queue_stop)) {
2220 /* insert the skb packet to the wait queue */
2221 /* as for the completion function, it does not need
2222 * to check it any more.
2223 * */
2224 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2225 }else{
2226 ieee->softmac_data_hard_start_xmit(
2227 txb->fragments[i],
2228 ieee->dev,ieee->rate);
2231 ieee80211_txb_free(txb);
2233 spin_unlock_irqrestore(&ieee->lock,flags);
2237 /* called with ieee->lock acquired */
2238 void ieee80211_resume_tx(struct ieee80211_device *ieee)
2240 int i;
2241 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2243 if (ieee->queue_stop){
2244 ieee->tx_pending.frag = i;
2245 return;
2246 }else{
2248 ieee->softmac_data_hard_start_xmit(
2249 ieee->tx_pending.txb->fragments[i],
2250 ieee->dev,ieee->rate);
2251 ieee->stats.tx_packets++;
2256 ieee80211_txb_free(ieee->tx_pending.txb);
2257 ieee->tx_pending.txb = NULL;
2261 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2263 unsigned long flags;
2265 spin_lock_irqsave(&ieee->lock,flags);
2266 init_mgmt_queue(ieee);
2267 if (ieee->tx_pending.txb){
2268 ieee80211_txb_free(ieee->tx_pending.txb);
2269 ieee->tx_pending.txb = NULL;
2271 ieee->queue_stop = 0;
2272 spin_unlock_irqrestore(&ieee->lock,flags);
2276 void ieee80211_rtl_wake_queue(struct ieee80211_device *ieee)
2279 unsigned long flags;
2280 struct sk_buff *skb;
2281 struct ieee80211_hdr_3addr *header;
2283 spin_lock_irqsave(&ieee->lock,flags);
2284 if (! ieee->queue_stop) goto exit;
2286 ieee->queue_stop = 0;
2288 if(ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE){
2289 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2291 header = (struct ieee80211_hdr_3addr *) skb->data;
2293 header->seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2295 if (ieee->seq_ctrl[0] == 0xFFF)
2296 ieee->seq_ctrl[0] = 0;
2297 else
2298 ieee->seq_ctrl[0]++;
2300 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2303 if (!ieee->queue_stop && ieee->tx_pending.txb)
2304 ieee80211_resume_tx(ieee);
2306 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)){
2307 ieee->softmac_stats.swtxawake++;
2308 netif_wake_queue(ieee->dev);
2311 exit :
2312 spin_unlock_irqrestore(&ieee->lock,flags);
2316 void ieee80211_rtl_stop_queue(struct ieee80211_device *ieee)
2319 if (! netif_queue_stopped(ieee->dev)){
2320 netif_stop_queue(ieee->dev);
2321 ieee->softmac_stats.swtxstop++;
2323 ieee->queue_stop = 1;
2328 inline void ieee80211_randomize_cell(struct ieee80211_device *ieee)
2331 get_random_bytes(ieee->current_network.bssid, ETH_ALEN);
2333 /* an IBSS cell address must have the two less significant
2334 * bits of the first byte = 2
2336 ieee->current_network.bssid[0] &= ~0x01;
2337 ieee->current_network.bssid[0] |= 0x02;
2340 /* called in user context only */
2341 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2343 ieee->assoc_id = 1;
2345 if (ieee->current_network.ssid_len == 0){
2346 strncpy(ieee->current_network.ssid,
2347 IEEE80211_DEFAULT_TX_ESSID,
2348 IW_ESSID_MAX_SIZE);
2350 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2351 ieee->ssid_set = 1;
2354 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2356 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2357 ieee->state = IEEE80211_LINKED;
2358 ieee->link_change(ieee->dev);
2359 notify_wx_assoc_event(ieee);
2361 if (ieee->data_hard_resume)
2362 ieee->data_hard_resume(ieee->dev);
2364 netif_carrier_on(ieee->dev);
2367 void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2369 if(ieee->raw_tx){
2371 if (ieee->data_hard_resume)
2372 ieee->data_hard_resume(ieee->dev);
2374 netif_carrier_on(ieee->dev);
2378 void ieee80211_start_ibss_wq(struct work_struct *work)
2381 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2382 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2383 /* iwconfig mode ad-hoc will schedule this and return
2384 * on the other hand this will block further iwconfig SET
2385 * operations because of the wx_sem hold.
2386 * Anyway some most set operations set a flag to speed-up
2387 * (abort) this wq (when syncro scanning) before sleeping
2388 * on the semaphore
2390 if(!ieee->proto_started){
2391 printk("==========oh driver down return\n");
2392 return;
2394 down(&ieee->wx_sem);
2395 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2397 if (ieee->current_network.ssid_len == 0){
2398 strcpy(ieee->current_network.ssid,IEEE80211_DEFAULT_TX_ESSID);
2399 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2400 ieee->ssid_set = 1;
2403 /* check if we have this cell in our network list */
2404 ieee80211_softmac_check_all_nets(ieee);
2407 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2408 if (ieee->state == IEEE80211_NOLINK)
2409 ieee->current_network.channel = ieee->IbssStartChnl;
2410 /* if not then the state is not linked. Maybe the user swithced to
2411 * ad-hoc mode just after being in monitor mode, or just after
2412 * being very few time in managed mode (so the card have had no
2413 * time to scan all the chans..) or we have just run up the iface
2414 * after setting ad-hoc mode. So we have to give another try..
2415 * Here, in ibss mode, should be safe to do this without extra care
2416 * (in bss mode we had to make sure no-one tryed to associate when
2417 * we had just checked the ieee->state and we was going to start the
2418 * scan) beacause in ibss mode the ieee80211_new_net function, when
2419 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2420 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2421 * scan, that will stop at the first round because it sees the state
2422 * associated.
2424 if (ieee->state == IEEE80211_NOLINK)
2425 ieee80211_start_scan_syncro(ieee);
2427 /* the network definitively is not here.. create a new cell */
2428 if (ieee->state == IEEE80211_NOLINK){
2429 printk("creating new IBSS cell\n");
2430 if(!ieee->wap_set)
2431 ieee80211_randomize_cell(ieee);
2433 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2435 ieee->current_network.rates_len = 4;
2437 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2438 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2439 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2440 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2442 }else
2443 ieee->current_network.rates_len = 0;
2445 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2446 ieee->current_network.rates_ex_len = 8;
2448 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2449 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2450 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2451 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2452 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2453 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2454 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2455 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2457 ieee->rate = 108;
2458 }else{
2459 ieee->current_network.rates_ex_len = 0;
2460 ieee->rate = 22;
2463 // By default, WMM function will be disabled in IBSS mode
2464 ieee->current_network.QoS_Enable = 0;
2465 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2466 ieee->current_network.atim_window = 0;
2467 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2468 if(ieee->short_slot)
2469 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2473 ieee->state = IEEE80211_LINKED;
2475 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2476 ieee->link_change(ieee->dev);
2477 if(ieee->LedControlHandler != NULL)
2478 ieee->LedControlHandler(ieee->dev,LED_CTL_LINK);
2479 notify_wx_assoc_event(ieee);
2481 ieee80211_start_send_beacons(ieee);
2483 if (ieee->data_hard_resume)
2484 ieee->data_hard_resume(ieee->dev);
2485 netif_carrier_on(ieee->dev);
2487 up(&ieee->wx_sem);
2490 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2492 queue_delayed_work(ieee->wq, &ieee->start_ibss_wq, 150);
2495 /* this is called only in user context, with wx_sem held */
2496 void ieee80211_start_bss(struct ieee80211_device *ieee)
2498 unsigned long flags;
2500 // Ref: 802.11d 11.1.3.3
2501 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2503 if(IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2505 if(! ieee->bGlobalDomain)
2507 return;
2510 /* check if we have already found the net we
2511 * are interested in (if any).
2512 * if not (we are disassociated and we are not
2513 * in associating / authenticating phase) start the background scanning.
2515 ieee80211_softmac_check_all_nets(ieee);
2517 /* ensure no-one start an associating process (thus setting
2518 * the ieee->state to ieee80211_ASSOCIATING) while we
2519 * have just cheked it and we are going to enable scan.
2520 * The ieee80211_new_net function is always called with
2521 * lock held (from both ieee80211_softmac_check_all_nets and
2522 * the rx path), so we cannot be in the middle of such function
2524 spin_lock_irqsave(&ieee->lock, flags);
2526 if (ieee->state == IEEE80211_NOLINK){
2527 ieee->actscanning = true;
2528 ieee80211_rtl_start_scan(ieee);
2530 spin_unlock_irqrestore(&ieee->lock, flags);
2533 void ieee80211_link_change_wq(struct work_struct *work)
2535 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2536 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, link_change_wq);
2538 ieee->link_change(ieee->dev);
2540 /* called only in userspace context */
2541 void ieee80211_disassociate(struct ieee80211_device *ieee)
2545 netif_carrier_off(ieee->dev);
2546 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2547 ieee80211_reset_queue(ieee);
2549 if (ieee->data_hard_stop)
2550 ieee->data_hard_stop(ieee->dev);
2551 if(IS_DOT11D_ENABLE(ieee))
2552 Dot11d_Reset(ieee);
2553 ieee->state = IEEE80211_NOLINK;
2554 ieee->is_set_key = false;
2556 queue_delayed_work(ieee->wq, &ieee->link_change_wq, 0);
2559 notify_wx_assoc_event(ieee);
2563 void ieee80211_associate_retry_wq(struct work_struct *work)
2565 struct delayed_work *dwork = container_of(work, struct delayed_work, work);
2566 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2567 unsigned long flags;
2569 down(&ieee->wx_sem);
2570 if(!ieee->proto_started)
2571 goto exit;
2573 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2574 goto exit;
2576 /* until we do not set the state to IEEE80211_NOLINK
2577 * there are no possibility to have someone else trying
2578 * to start an association procdure (we get here with
2579 * ieee->state = IEEE80211_ASSOCIATING).
2580 * When we set the state to IEEE80211_NOLINK it is possible
2581 * that the RX path run an attempt to associate, but
2582 * both ieee80211_softmac_check_all_nets and the
2583 * RX path works with ieee->lock held so there are no
2584 * problems. If we are still disassociated then start a scan.
2585 * the lock here is necessary to ensure no one try to start
2586 * an association procedure when we have just checked the
2587 * state and we are going to start the scan.
2589 ieee->beinretry = true;
2590 ieee->state = IEEE80211_NOLINK;
2592 ieee80211_softmac_check_all_nets(ieee);
2594 spin_lock_irqsave(&ieee->lock, flags);
2596 if(ieee->state == IEEE80211_NOLINK)
2598 ieee->actscanning = true;
2599 ieee80211_rtl_start_scan(ieee);
2601 spin_unlock_irqrestore(&ieee->lock, flags);
2603 ieee->beinretry = false;
2604 exit:
2605 up(&ieee->wx_sem);
2608 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2610 u8 broadcast_addr[] = {0xff,0xff,0xff,0xff,0xff,0xff};
2612 struct sk_buff *skb;
2613 struct ieee80211_probe_response *b;
2615 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2617 if (!skb)
2618 return NULL;
2620 b = (struct ieee80211_probe_response *) skb->data;
2621 b->header.frame_control = cpu_to_le16(IEEE80211_STYPE_BEACON);
2623 return skb;
2627 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2629 struct sk_buff *skb;
2630 struct ieee80211_probe_response *b;
2632 skb = ieee80211_get_beacon_(ieee);
2633 if(!skb)
2634 return NULL;
2636 b = (struct ieee80211_probe_response *) skb->data;
2637 b->header.seq_ctrl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2639 if (ieee->seq_ctrl[0] == 0xFFF)
2640 ieee->seq_ctrl[0] = 0;
2641 else
2642 ieee->seq_ctrl[0]++;
2644 return skb;
2647 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2649 ieee->sync_scan_hurryup = 1;
2650 down(&ieee->wx_sem);
2651 ieee80211_stop_protocol(ieee);
2652 up(&ieee->wx_sem);
2656 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2658 if (!ieee->proto_started)
2659 return;
2661 ieee->proto_started = 0;
2663 ieee80211_stop_send_beacons(ieee);
2664 del_timer_sync(&ieee->associate_timer);
2665 cancel_delayed_work(&ieee->associate_retry_wq);
2666 cancel_delayed_work(&ieee->start_ibss_wq);
2667 cancel_delayed_work(&ieee->link_change_wq);
2668 ieee80211_stop_scan(ieee);
2670 ieee80211_disassociate(ieee);
2671 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2674 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2676 ieee->sync_scan_hurryup = 0;
2677 down(&ieee->wx_sem);
2678 ieee80211_start_protocol(ieee);
2679 up(&ieee->wx_sem);
2682 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2684 short ch = 0;
2685 int i = 0;
2686 if (ieee->proto_started)
2687 return;
2689 ieee->proto_started = 1;
2691 if (ieee->current_network.channel == 0){
2693 ch++;
2694 if (ch > MAX_CHANNEL_NUMBER)
2695 return; /* no channel found */
2696 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2697 ieee->current_network.channel = ch;
2700 if (ieee->current_network.beacon_interval == 0)
2701 ieee->current_network.beacon_interval = 100;
2703 for(i = 0; i < 17; i++) {
2704 ieee->last_rxseq_num[i] = -1;
2705 ieee->last_rxfrag_num[i] = -1;
2706 ieee->last_packet_time[i] = 0;
2709 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2712 /* if the user set the MAC of the ad-hoc cell and then
2713 * switch to managed mode, shall we make sure that association
2714 * attempts does not fail just because the user provide the essid
2715 * and the nic is still checking for the AP MAC ??
2717 if (ieee->iw_mode == IW_MODE_INFRA)
2718 ieee80211_start_bss(ieee);
2720 else if (ieee->iw_mode == IW_MODE_ADHOC)
2721 ieee80211_start_ibss(ieee);
2723 else if (ieee->iw_mode == IW_MODE_MASTER)
2724 ieee80211_start_master_bss(ieee);
2726 else if(ieee->iw_mode == IW_MODE_MONITOR)
2727 ieee80211_start_monitor_mode(ieee);
2731 #define DRV_NAME "Ieee80211"
2732 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2734 int i;
2735 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2737 ieee->state = IEEE80211_NOLINK;
2738 ieee->sync_scan_hurryup = 0;
2739 for(i = 0; i < 5; i++) {
2740 ieee->seq_ctrl[i] = 0;
2742 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
2743 if (!ieee->pDot11dInfo)
2744 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2745 //added for AP roaming
2746 ieee->LinkDetectInfo.SlotNum = 2;
2747 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2748 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2750 ieee->assoc_id = 0;
2751 ieee->queue_stop = 0;
2752 ieee->scanning = 0;
2753 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2754 ieee->wap_set = 0;
2755 ieee->ssid_set = 0;
2756 ieee->proto_started = 0;
2757 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2758 ieee->rate = 22;
2759 ieee->ps = IEEE80211_PS_DISABLED;
2760 ieee->sta_sleep = 0;
2761 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2762 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2763 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2764 ieee->actscanning = false;
2765 ieee->beinretry = false;
2766 ieee->is_set_key = false;
2767 init_mgmt_queue(ieee);
2769 ieee->sta_edca_param[0] = 0x0000A403;
2770 ieee->sta_edca_param[1] = 0x0000A427;
2771 ieee->sta_edca_param[2] = 0x005E4342;
2772 ieee->sta_edca_param[3] = 0x002F3262;
2773 ieee->aggregation = true;
2774 ieee->enable_rx_imm_BA = 1;
2775 ieee->tx_pending.txb = NULL;
2777 init_timer(&ieee->associate_timer);
2778 ieee->associate_timer.data = (unsigned long)ieee;
2779 ieee->associate_timer.function = ieee80211_associate_abort_cb;
2781 init_timer(&ieee->beacon_timer);
2782 ieee->beacon_timer.data = (unsigned long) ieee;
2783 ieee->beacon_timer.function = ieee80211_send_beacon_cb;
2785 #ifdef PF_SYNCTHREAD
2786 ieee->wq = create_workqueue(DRV_NAME,0);
2787 #else
2788 ieee->wq = create_workqueue(DRV_NAME);
2789 #endif
2791 INIT_DELAYED_WORK(&ieee->link_change_wq,ieee80211_link_change_wq);
2792 INIT_DELAYED_WORK(&ieee->start_ibss_wq,ieee80211_start_ibss_wq);
2793 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2794 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2795 INIT_DELAYED_WORK(&ieee->softmac_scan_wq,ieee80211_softmac_scan_wq);
2796 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2797 INIT_WORK(&ieee->wx_sync_scan_wq,ieee80211_wx_sync_scan_wq);
2799 sema_init(&ieee->wx_sem, 1);
2800 sema_init(&ieee->scan_sem, 1);
2802 spin_lock_init(&ieee->mgmt_tx_lock);
2803 spin_lock_init(&ieee->beacon_lock);
2805 tasklet_init(&ieee->ps_task,
2806 (void(*)(unsigned long)) ieee80211_sta_ps,
2807 (unsigned long)ieee);
2811 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2813 down(&ieee->wx_sem);
2814 if(NULL != ieee->pDot11dInfo)
2816 kfree(ieee->pDot11dInfo);
2817 ieee->pDot11dInfo = NULL;
2819 del_timer_sync(&ieee->associate_timer);
2821 cancel_delayed_work(&ieee->associate_retry_wq);
2822 destroy_workqueue(ieee->wq);
2824 up(&ieee->wx_sem);
2827 /********************************************************
2828 * Start of WPA code. *
2829 * this is stolen from the ipw2200 driver *
2830 ********************************************************/
2833 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2835 /* This is called when wpa_supplicant loads and closes the driver
2836 * interface. */
2837 printk("%s WPA\n",value ? "enabling" : "disabling");
2838 ieee->wpa_enabled = value;
2839 memset(ieee->ap_mac_addr, 0, 6); //reset ap_mac_addr everytime it starts wpa.
2840 return 0;
2844 void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee, char *wpa_ie, int wpa_ie_len)
2846 /* make sure WPA is enabled */
2847 ieee80211_wpa_enable(ieee, 1);
2849 ieee80211_disassociate(ieee);
2853 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2856 int ret = 0;
2858 switch (command) {
2859 case IEEE_MLME_STA_DEAUTH:
2860 // silently ignore
2861 break;
2863 case IEEE_MLME_STA_DISASSOC:
2864 ieee80211_disassociate(ieee);
2865 break;
2867 default:
2868 printk("Unknown MLME request: %d\n", command);
2869 ret = -EOPNOTSUPP;
2872 return ret;
2876 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2877 struct ieee_param *param, int plen)
2879 u8 *buf;
2881 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2882 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2883 return -EINVAL;
2885 if (param->u.wpa_ie.len) {
2886 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2887 GFP_KERNEL);
2888 if (buf == NULL)
2889 return -ENOMEM;
2891 kfree(ieee->wpa_ie);
2892 ieee->wpa_ie = buf;
2893 ieee->wpa_ie_len = param->u.wpa_ie.len;
2894 } else {
2895 kfree(ieee->wpa_ie);
2896 ieee->wpa_ie = NULL;
2897 ieee->wpa_ie_len = 0;
2900 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2901 return 0;
2904 #define AUTH_ALG_OPEN_SYSTEM 0x1
2905 #define AUTH_ALG_SHARED_KEY 0x2
2906 #define AUTH_ALG_LEAP 0x4
2907 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2910 struct ieee80211_security sec = {
2911 .flags = SEC_AUTH_MODE,
2913 int ret = 0;
2915 if (value & AUTH_ALG_SHARED_KEY) {
2916 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2917 ieee->open_wep = 0;
2918 ieee->auth_mode = 1;
2919 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2920 sec.auth_mode = WLAN_AUTH_OPEN;
2921 ieee->open_wep = 1;
2922 ieee->auth_mode = 0;
2924 else if (value & AUTH_ALG_LEAP){
2925 sec.auth_mode = RTL_WLAN_AUTH_LEAP;
2926 ieee->open_wep = 1;
2927 ieee->auth_mode = 2;
2931 if (ieee->set_security)
2932 ieee->set_security(ieee->dev, &sec);
2934 return ret;
2937 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2939 int ret=0;
2940 unsigned long flags;
2942 switch (name) {
2943 case IEEE_PARAM_WPA_ENABLED:
2944 ret = ieee80211_wpa_enable(ieee, value);
2945 break;
2947 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2948 ieee->tkip_countermeasures=value;
2949 break;
2951 case IEEE_PARAM_DROP_UNENCRYPTED: {
2952 /* HACK:
2954 * wpa_supplicant calls set_wpa_enabled when the driver
2955 * is loaded and unloaded, regardless of if WPA is being
2956 * used. No other calls are made which can be used to
2957 * determine if encryption will be used or not prior to
2958 * association being expected. If encryption is not being
2959 * used, drop_unencrypted is set to false, else true -- we
2960 * can use this to determine if the CAP_PRIVACY_ON bit should
2961 * be set.
2963 struct ieee80211_security sec = {
2964 .flags = SEC_ENABLED,
2965 .enabled = value,
2967 ieee->drop_unencrypted = value;
2968 /* We only change SEC_LEVEL for open mode. Others
2969 * are set by ipw_wpa_set_encryption.
2971 if (!value) {
2972 sec.flags |= SEC_LEVEL;
2973 sec.level = SEC_LEVEL_0;
2975 else {
2976 sec.flags |= SEC_LEVEL;
2977 sec.level = SEC_LEVEL_1;
2979 if (ieee->set_security)
2980 ieee->set_security(ieee->dev, &sec);
2981 break;
2984 case IEEE_PARAM_PRIVACY_INVOKED:
2985 ieee->privacy_invoked=value;
2986 break;
2988 case IEEE_PARAM_AUTH_ALGS:
2989 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2990 break;
2992 case IEEE_PARAM_IEEE_802_1X:
2993 ieee->ieee802_1x=value;
2994 break;
2995 case IEEE_PARAM_WPAX_SELECT:
2996 // added for WPA2 mixed mode
2997 spin_lock_irqsave(&ieee->wpax_suitlist_lock,flags);
2998 ieee->wpax_type_set = 1;
2999 ieee->wpax_type_notify = value;
3000 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock,flags);
3001 break;
3003 default:
3004 printk("Unknown WPA param: %d\n",name);
3005 ret = -EOPNOTSUPP;
3008 return ret;
3011 /* implementation borrowed from hostap driver */
3013 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
3014 struct ieee_param *param, int param_len)
3016 int ret = 0;
3018 struct ieee80211_crypto_ops *ops;
3019 struct ieee80211_crypt_data **crypt;
3021 struct ieee80211_security sec = {
3022 .flags = 0,
3025 param->u.crypt.err = 0;
3026 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
3028 if (param_len !=
3029 (int) ((char *) param->u.crypt.key - (char *) param) +
3030 param->u.crypt.key_len) {
3031 printk("Len mismatch %d, %d\n", param_len,
3032 param->u.crypt.key_len);
3033 return -EINVAL;
3035 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
3036 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
3037 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
3038 if (param->u.crypt.idx >= WEP_KEYS)
3039 return -EINVAL;
3040 crypt = &ieee->crypt[param->u.crypt.idx];
3041 } else {
3042 return -EINVAL;
3045 if (strcmp(param->u.crypt.alg, "none") == 0) {
3046 if (crypt) {
3047 sec.enabled = 0;
3048 //sec.encrypt = 0;
3049 sec.level = SEC_LEVEL_0;
3050 sec.flags |= SEC_ENABLED | SEC_LEVEL;
3051 ieee80211_crypt_delayed_deinit(ieee, crypt);
3053 goto done;
3055 sec.enabled = 1;
3056 // sec.encrypt = 1;
3057 sec.flags |= SEC_ENABLED;
3059 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
3060 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
3061 strcmp(param->u.crypt.alg, "TKIP"))
3062 goto skip_host_crypt;
3064 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3065 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
3066 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3067 /* set WEP40 first, it will be modified according to WEP104 or
3068 * WEP40 at other place */
3069 else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
3070 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3071 else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
3072 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3073 if (ops == NULL) {
3074 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3075 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3076 ret = -EINVAL;
3077 goto done;
3080 if (*crypt == NULL || (*crypt)->ops != ops) {
3081 struct ieee80211_crypt_data *new_crypt;
3083 ieee80211_crypt_delayed_deinit(ieee, crypt);
3085 new_crypt = kmalloc(sizeof(*new_crypt), GFP_KERNEL);
3086 if (new_crypt == NULL) {
3087 ret = -ENOMEM;
3088 goto done;
3090 memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
3091 new_crypt->ops = ops;
3093 if (new_crypt->ops)
3094 new_crypt->priv =
3095 new_crypt->ops->init(param->u.crypt.idx);
3097 if (new_crypt->priv == NULL) {
3098 kfree(new_crypt);
3099 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3100 ret = -EINVAL;
3101 goto done;
3104 *crypt = new_crypt;
3107 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3108 (*crypt)->ops->set_key(param->u.crypt.key,
3109 param->u.crypt.key_len, param->u.crypt.seq,
3110 (*crypt)->priv) < 0) {
3111 printk("key setting failed\n");
3112 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3113 ret = -EINVAL;
3114 goto done;
3117 skip_host_crypt:
3118 if (param->u.crypt.set_tx) {
3119 ieee->tx_keyidx = param->u.crypt.idx;
3120 sec.active_key = param->u.crypt.idx;
3121 sec.flags |= SEC_ACTIVE_KEY;
3122 } else
3123 sec.flags &= ~SEC_ACTIVE_KEY;
3125 if (param->u.crypt.alg != NULL) {
3126 memcpy(sec.keys[param->u.crypt.idx],
3127 param->u.crypt.key,
3128 param->u.crypt.key_len);
3129 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3130 sec.flags |= (1 << param->u.crypt.idx);
3132 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3133 sec.flags |= SEC_LEVEL;
3134 sec.level = SEC_LEVEL_1;
3135 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3136 sec.flags |= SEC_LEVEL;
3137 sec.level = SEC_LEVEL_2;
3138 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3139 sec.flags |= SEC_LEVEL;
3140 sec.level = SEC_LEVEL_3;
3143 done:
3144 if (ieee->set_security)
3145 ieee->set_security(ieee->dev, &sec);
3147 /* Do not reset port if card is in Managed mode since resetting will
3148 * generate new IEEE 802.11 authentication which may end up in looping
3149 * with IEEE 802.1X. If your hardware requires a reset after WEP
3150 * configuration (for example... Prism2), implement the reset_port in
3151 * the callbacks structures used to initialize the 802.11 stack. */
3152 if (ieee->reset_on_keychange &&
3153 ieee->iw_mode != IW_MODE_INFRA &&
3154 ieee->reset_port &&
3155 ieee->reset_port(ieee->dev)) {
3156 printk("reset_port failed\n");
3157 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3158 return -EINVAL;
3161 return ret;
3164 inline struct sk_buff *ieee80211_disassociate_skb(
3165 struct ieee80211_network *beacon,
3166 struct ieee80211_device *ieee,
3167 u8 asRsn)
3169 struct sk_buff *skb;
3170 struct ieee80211_disassoc *disass;
3172 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3173 if (!skb)
3174 return NULL;
3176 disass = (struct ieee80211_disassoc *) skb_put(skb,sizeof(struct ieee80211_disassoc));
3177 disass->header.frame_control = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3178 disass->header.duration_id = 0;
3180 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3181 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3182 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3184 disass->reason = asRsn;
3185 return skb;
3189 void
3190 SendDisassociation(
3191 struct ieee80211_device *ieee,
3192 u8* asSta,
3193 u8 asRsn
3196 struct ieee80211_network *beacon = &ieee->current_network;
3197 struct sk_buff *skb;
3198 skb = ieee80211_disassociate_skb(beacon,ieee,asRsn);
3199 if (skb){
3200 softmac_mgmt_xmit(skb, ieee);
3201 //dev_kfree_skb_any(skb);//edit by thomas
3205 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3207 struct ieee_param *param;
3208 int ret=0;
3210 down(&ieee->wx_sem);
3212 if (p->length < sizeof(struct ieee_param) || !p->pointer){
3213 ret = -EINVAL;
3214 goto out;
3217 param = kmalloc(p->length, GFP_KERNEL);
3218 if (param == NULL){
3219 ret = -ENOMEM;
3220 goto out;
3222 if (copy_from_user(param, p->pointer, p->length)) {
3223 kfree(param);
3224 ret = -EFAULT;
3225 goto out;
3228 switch (param->cmd) {
3230 case IEEE_CMD_SET_WPA_PARAM:
3231 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3232 param->u.wpa_param.value);
3233 break;
3235 case IEEE_CMD_SET_WPA_IE:
3236 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3237 break;
3239 case IEEE_CMD_SET_ENCRYPTION:
3240 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3241 break;
3243 case IEEE_CMD_MLME:
3244 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3245 param->u.mlme.reason_code);
3246 break;
3248 default:
3249 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3250 ret = -EOPNOTSUPP;
3251 break;
3254 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3255 ret = -EFAULT;
3257 kfree(param);
3258 out:
3259 up(&ieee->wx_sem);
3261 return ret;
3264 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3266 union iwreq_data wrqu;
3267 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3268 if (ieee->state == IEEE80211_LINKED)
3269 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3270 else
3271 memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN);
3272 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);