staging: rtl8192u: Replace GFP_ATOMIC with GFP_KERNEL in ieee80211_softmac_init
[linux-2.6/btrfs-unstable.git] / drivers / staging / rtl8192u / ieee80211 / ieee80211_softmac.c
blob21874e78d8a15a33ab181e810fa8805b42358d46
1 /* IEEE 802.11 SoftMAC layer
2 * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
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/uaccess.h>
23 #include <linux/etherdevice.h>
25 #include "dot11d.h"
27 short ieee80211_is_54g(const struct ieee80211_network *net)
29 return (net->rates_ex_len > 0) || (net->rates_len > 4);
31 EXPORT_SYMBOL(ieee80211_is_54g);
33 short ieee80211_is_shortslot(const struct ieee80211_network *net)
35 return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
37 EXPORT_SYMBOL(ieee80211_is_shortslot);
39 /* returns the total length needed for pleacing the RATE MFIE
40 * tag and the EXTENDED RATE MFIE tag if needed.
41 * It encludes two bytes per tag for the tag itself and its len
43 static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
45 unsigned int rate_len = 0;
47 if (ieee->modulation & IEEE80211_CCK_MODULATION)
48 rate_len = IEEE80211_CCK_RATE_LEN + 2;
50 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
52 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
54 return rate_len;
57 /* pleace the MFIE rate, tag to the memory (double) poined.
58 * Then it updates the pointer so that
59 * it points after the new MFIE tag added.
61 static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
63 u8 *tag = *tag_p;
65 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
66 *tag++ = MFIE_TYPE_RATES;
67 *tag++ = 4;
68 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
69 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
70 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
71 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
74 /* We may add an option for custom rates that specific HW might support */
75 *tag_p = tag;
78 static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
80 u8 *tag = *tag_p;
82 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
84 *tag++ = MFIE_TYPE_RATES_EX;
85 *tag++ = 8;
86 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
87 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
88 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
89 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
90 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
91 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
92 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
93 *tag++ = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
97 /* We may add an option for custom rates that specific HW might support */
98 *tag_p = tag;
102 static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
104 u8 *tag = *tag_p;
106 *tag++ = MFIE_TYPE_GENERIC; /* 0 */
107 *tag++ = 7;
108 *tag++ = 0x00;
109 *tag++ = 0x50;
110 *tag++ = 0xf2;
111 *tag++ = 0x02; /* 5 */
112 *tag++ = 0x00;
113 *tag++ = 0x01;
114 #ifdef SUPPORT_USPD
115 if(ieee->current_network.wmm_info & 0x80) {
116 *tag++ = 0x0f|MAX_SP_Len;
117 } else {
118 *tag++ = MAX_SP_Len;
120 #else
121 *tag++ = MAX_SP_Len;
122 #endif
123 *tag_p = tag;
126 #ifdef THOMAS_TURBO
127 static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
129 u8 *tag = *tag_p;
131 *tag++ = MFIE_TYPE_GENERIC; /* 0 */
132 *tag++ = 7;
133 *tag++ = 0x00;
134 *tag++ = 0xe0;
135 *tag++ = 0x4c;
136 *tag++ = 0x01; /* 5 */
137 *tag++ = 0x02;
138 *tag++ = 0x11;
139 *tag++ = 0x00;
141 *tag_p = tag;
142 printk(KERN_ALERT "This is enable turbo mode IE process\n");
144 #endif
146 static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
148 int nh;
150 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
153 * if the queue is full but we have newer frames then
154 * just overwrites the oldest.
156 * if (nh == ieee->mgmt_queue_tail)
157 * return -1;
159 ieee->mgmt_queue_head = nh;
160 ieee->mgmt_queue_ring[nh] = skb;
162 //return 0;
165 static 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 static void init_mgmt_queue(struct ieee80211_device *ieee)
182 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
185 static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
187 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
188 u8 rate;
190 /* 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. */
191 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
192 rate = 0x0c;
193 else
194 rate = ieee->basic_rate & 0x7f;
196 if (rate == 0) {
197 /* 2005.01.26, by rcnjko. */
198 if(ieee->mode == IEEE_A||
199 ieee->mode== IEEE_N_5G||
200 (ieee->mode== IEEE_N_24G&&!pHTInfo->bCurSuppCCK))
201 rate = 0x0c;
202 else
203 rate = 0x02;
207 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
208 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
210 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
211 rate = 0x0c;
212 else
213 rate = 0x02;
216 return rate;
220 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
222 inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
224 unsigned long flags;
225 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
226 struct rtl_80211_hdr_3addr *header=
227 (struct rtl_80211_hdr_3addr *) skb->data;
229 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8);
231 spin_lock_irqsave(&ieee->lock, flags);
233 /* called with 2nd param 0, no mgmt lock required */
234 ieee80211_sta_wakeup(ieee, 0);
236 tcb_desc->queue_index = MGNT_QUEUE;
237 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
238 tcb_desc->RATRIndex = 7;
239 tcb_desc->bTxDisableRateFallBack = 1;
240 tcb_desc->bTxUseDriverAssingedRate = 1;
242 if(single){
243 if(ieee->queue_stop){
244 enqueue_mgmt(ieee, skb);
245 }else{
246 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
248 if (ieee->seq_ctrl[0] == 0xFFF)
249 ieee->seq_ctrl[0] = 0;
250 else
251 ieee->seq_ctrl[0]++;
253 /* avoid watchdog triggers */
254 netif_trans_update(ieee->dev);
255 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
256 //dev_kfree_skb_any(skb);//edit by thomas
259 spin_unlock_irqrestore(&ieee->lock, flags);
260 }else{
261 spin_unlock_irqrestore(&ieee->lock, flags);
262 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags);
264 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
266 if (ieee->seq_ctrl[0] == 0xFFF)
267 ieee->seq_ctrl[0] = 0;
268 else
269 ieee->seq_ctrl[0]++;
271 /* check whether the managed packet queued greater than 5 */
272 if(!ieee->check_nic_enough_desc(ieee->dev,tcb_desc->queue_index)||\
273 (skb_queue_len(&ieee->skb_waitQ[tcb_desc->queue_index]) != 0)||\
274 (ieee->queue_stop) ) {
275 /* insert the skb packet to the management queue */
276 /* as for the completion function, it does not need
277 * to check it any more.
278 * */
279 printk("%s():insert to waitqueue!\n",__func__);
280 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
281 } else {
282 ieee->softmac_hard_start_xmit(skb, ieee->dev);
283 //dev_kfree_skb_any(skb);//edit by thomas
285 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
289 static inline void
290 softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
293 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
294 struct rtl_80211_hdr_3addr *header =
295 (struct rtl_80211_hdr_3addr *) skb->data;
298 if(single){
300 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
302 if (ieee->seq_ctrl[0] == 0xFFF)
303 ieee->seq_ctrl[0] = 0;
304 else
305 ieee->seq_ctrl[0]++;
307 /* avoid watchdog triggers */
308 netif_trans_update(ieee->dev);
309 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
311 }else{
313 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
315 if (ieee->seq_ctrl[0] == 0xFFF)
316 ieee->seq_ctrl[0] = 0;
317 else
318 ieee->seq_ctrl[0]++;
320 ieee->softmac_hard_start_xmit(skb, ieee->dev);
323 //dev_kfree_skb_any(skb);//edit by thomas
326 static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
328 unsigned int len, rate_len;
329 u8 *tag;
330 struct sk_buff *skb;
331 struct ieee80211_probe_request *req;
333 len = ieee->current_network.ssid_len;
335 rate_len = ieee80211_MFIE_rate_len(ieee);
337 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
338 2 + len + rate_len + ieee->tx_headroom);
339 if (!skb)
340 return NULL;
342 skb_reserve(skb, ieee->tx_headroom);
344 req = skb_put(skb, sizeof(struct ieee80211_probe_request));
345 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
346 req->header.duration_id = 0; /* FIXME: is this OK? */
348 eth_broadcast_addr(req->header.addr1);
349 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
350 eth_broadcast_addr(req->header.addr3);
352 tag = skb_put(skb, len + 2 + rate_len);
354 *tag++ = MFIE_TYPE_SSID;
355 *tag++ = len;
356 memcpy(tag, ieee->current_network.ssid, len);
357 tag += len;
359 ieee80211_MFIE_Brate(ieee,&tag);
360 ieee80211_MFIE_Grate(ieee,&tag);
361 return skb;
364 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
366 static void ieee80211_send_beacon(struct ieee80211_device *ieee)
368 struct sk_buff *skb;
370 if(!ieee->ieee_up)
371 return;
372 //unsigned long flags;
373 skb = ieee80211_get_beacon_(ieee);
375 if (skb) {
376 softmac_mgmt_xmit(skb, ieee);
377 ieee->softmac_stats.tx_beacons++;
378 //dev_kfree_skb_any(skb);//edit by thomas
380 // ieee->beacon_timer.expires = jiffies +
381 // (MSECS( ieee->current_network.beacon_interval -5));
383 //spin_lock_irqsave(&ieee->beacon_lock,flags);
384 if (ieee->beacon_txing && ieee->ieee_up) {
385 // if(!timer_pending(&ieee->beacon_timer))
386 // add_timer(&ieee->beacon_timer);
387 mod_timer(&ieee->beacon_timer,
388 jiffies + msecs_to_jiffies(ieee->current_network.beacon_interval-5));
390 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
394 static void ieee80211_send_beacon_cb(struct timer_list *t)
396 struct ieee80211_device *ieee =
397 from_timer(ieee, t, beacon_timer);
398 unsigned long flags;
400 spin_lock_irqsave(&ieee->beacon_lock, flags);
401 ieee80211_send_beacon(ieee);
402 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
406 static void ieee80211_send_probe(struct ieee80211_device *ieee)
408 struct sk_buff *skb;
410 skb = ieee80211_probe_req(ieee);
411 if (skb) {
412 softmac_mgmt_xmit(skb, ieee);
413 ieee->softmac_stats.tx_probe_rq++;
414 //dev_kfree_skb_any(skb);//edit by thomas
418 static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
420 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
421 ieee80211_send_probe(ieee);
422 ieee80211_send_probe(ieee);
426 /* this performs syncro scan blocking the caller until all channels
427 * in the allowed channel map has been checked.
429 void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
431 short ch = 0;
432 u8 channel_map[MAX_CHANNEL_NUMBER+1];
434 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
435 mutex_lock(&ieee->scan_mutex);
437 while(1)
441 ch++;
442 if (ch > MAX_CHANNEL_NUMBER)
443 goto out; /* scan completed */
444 }while(!channel_map[ch]);
446 /* this function can be called in two situations
447 * 1- We have switched to ad-hoc mode and we are
448 * performing a complete syncro scan before conclude
449 * there are no interesting cell and to create a
450 * new one. In this case the link state is
451 * IEEE80211_NOLINK until we found an interesting cell.
452 * If so the ieee8021_new_net, called by the RX path
453 * will set the state to IEEE80211_LINKED, so we stop
454 * scanning
455 * 2- We are linked and the root uses run iwlist scan.
456 * So we switch to IEEE80211_LINKED_SCANNING to remember
457 * that we are still logically linked (not interested in
458 * new network events, despite for updating the net list,
459 * but we are temporarly 'unlinked' as the driver shall
460 * not filter RX frames and the channel is changing.
461 * So the only situation in witch are interested is to check
462 * if the state become LINKED because of the #1 situation
465 if (ieee->state == IEEE80211_LINKED)
466 goto out;
467 ieee->set_chan(ieee->dev, ch);
468 if(channel_map[ch] == 1)
469 ieee80211_send_probe_requests(ieee);
471 /* this prevent excessive time wait when we
472 * need to wait for a syncro scan to end..
474 if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup)
475 goto out;
477 msleep_interruptible(IEEE80211_SOFTMAC_SCAN_TIME);
480 out:
481 if(ieee->state < IEEE80211_LINKED){
482 ieee->actscanning = false;
483 mutex_unlock(&ieee->scan_mutex);
485 else{
486 ieee->sync_scan_hurryup = 0;
487 if(IS_DOT11D_ENABLE(ieee))
488 DOT11D_ScanComplete(ieee);
489 mutex_unlock(&ieee->scan_mutex);
492 EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
494 static void ieee80211_softmac_scan_wq(struct work_struct *work)
496 struct delayed_work *dwork = to_delayed_work(work);
497 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
498 static short watchdog;
499 u8 channel_map[MAX_CHANNEL_NUMBER+1];
501 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
502 if(!ieee->ieee_up)
503 return;
504 mutex_lock(&ieee->scan_mutex);
506 ieee->current_network.channel =
507 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
508 if (watchdog++ > MAX_CHANNEL_NUMBER)
510 //if current channel is not in channel map, set to default channel.
511 if (!channel_map[ieee->current_network.channel]) {
512 ieee->current_network.channel = 6;
513 goto out; /* no good chans */
516 }while(!channel_map[ieee->current_network.channel]);
517 if (ieee->scanning == 0 )
518 goto out;
519 ieee->set_chan(ieee->dev, ieee->current_network.channel);
520 if(channel_map[ieee->current_network.channel] == 1)
521 ieee80211_send_probe_requests(ieee);
524 schedule_delayed_work(&ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
526 mutex_unlock(&ieee->scan_mutex);
527 return;
528 out:
529 if(IS_DOT11D_ENABLE(ieee))
530 DOT11D_ScanComplete(ieee);
531 ieee->actscanning = false;
532 watchdog = 0;
533 ieee->scanning = 0;
534 mutex_unlock(&ieee->scan_mutex);
539 static void ieee80211_beacons_start(struct ieee80211_device *ieee)
541 unsigned long flags;
542 spin_lock_irqsave(&ieee->beacon_lock,flags);
544 ieee->beacon_txing = 1;
545 ieee80211_send_beacon(ieee);
547 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
550 static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
552 unsigned long flags;
554 spin_lock_irqsave(&ieee->beacon_lock, flags);
556 ieee->beacon_txing = 0;
557 del_timer_sync(&ieee->beacon_timer);
559 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
564 void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
566 if(ieee->stop_send_beacons)
567 ieee->stop_send_beacons(ieee->dev);
568 if (ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
569 ieee80211_beacons_stop(ieee);
571 EXPORT_SYMBOL(ieee80211_stop_send_beacons);
573 void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
575 if(ieee->start_send_beacons)
576 ieee->start_send_beacons(ieee->dev, ieee->basic_rate);
577 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
578 ieee80211_beacons_start(ieee);
580 EXPORT_SYMBOL(ieee80211_start_send_beacons);
582 static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
584 // unsigned long flags;
586 //ieee->sync_scan_hurryup = 1;
588 mutex_lock(&ieee->scan_mutex);
589 // spin_lock_irqsave(&ieee->lock, flags);
591 if (ieee->scanning == 1) {
592 ieee->scanning = 0;
594 cancel_delayed_work(&ieee->softmac_scan_wq);
597 // spin_unlock_irqrestore(&ieee->lock, flags);
598 mutex_unlock(&ieee->scan_mutex);
601 void ieee80211_stop_scan(struct ieee80211_device *ieee)
603 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
604 ieee80211_softmac_stop_scan(ieee);
605 else
606 ieee->stop_scan(ieee->dev);
608 EXPORT_SYMBOL(ieee80211_stop_scan);
610 /* called with ieee->lock held */
611 static void ieee80211_start_scan(struct ieee80211_device *ieee)
613 if (IS_DOT11D_ENABLE(ieee) )
615 if (IS_COUNTRY_IE_VALID(ieee))
617 RESET_CIE_WATCHDOG(ieee);
620 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
621 if (ieee->scanning == 0) {
622 ieee->scanning = 1;
623 schedule_delayed_work(&ieee->softmac_scan_wq, 0);
625 }else
626 ieee->start_scan(ieee->dev);
630 /* called with wx_mutex held */
631 void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
633 if (IS_DOT11D_ENABLE(ieee) )
635 if (IS_COUNTRY_IE_VALID(ieee))
637 RESET_CIE_WATCHDOG(ieee);
640 ieee->sync_scan_hurryup = 0;
641 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
642 ieee80211_softmac_scan_syncro(ieee);
643 else
644 ieee->scan_syncro(ieee->dev);
647 EXPORT_SYMBOL(ieee80211_start_scan_syncro);
649 static inline struct sk_buff *
650 ieee80211_authentication_req(struct ieee80211_network *beacon,
651 struct ieee80211_device *ieee, int challengelen)
653 struct sk_buff *skb;
654 struct ieee80211_authentication *auth;
655 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
658 skb = dev_alloc_skb(len);
659 if (!skb) return NULL;
661 skb_reserve(skb, ieee->tx_headroom);
662 auth = skb_put(skb, sizeof(struct ieee80211_authentication));
664 if (challengelen)
665 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH
666 | IEEE80211_FCTL_WEP);
667 else
668 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
670 auth->header.duration_id = cpu_to_le16(0x013a);
672 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
673 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
674 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
676 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
677 if(ieee->auth_mode == 0)
678 auth->algorithm = WLAN_AUTH_OPEN;
679 else if(ieee->auth_mode == 1)
680 auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY);
681 else if(ieee->auth_mode == 2)
682 auth->algorithm = WLAN_AUTH_OPEN; /* 0x80; */
683 printk("=================>%s():auth->algorithm is %d\n",__func__,auth->algorithm);
684 auth->transaction = cpu_to_le16(ieee->associate_seq);
685 ieee->associate_seq++;
687 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
689 return skb;
694 static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
696 u8 *tag;
697 int beacon_size;
698 struct ieee80211_probe_response *beacon_buf;
699 struct sk_buff *skb = NULL;
700 int encrypt;
701 int atim_len, erp_len;
702 struct ieee80211_crypt_data *crypt;
704 char *ssid = ieee->current_network.ssid;
705 int ssid_len = ieee->current_network.ssid_len;
706 int rate_len = ieee->current_network.rates_len+2;
707 int rate_ex_len = ieee->current_network.rates_ex_len;
708 int wpa_ie_len = ieee->wpa_ie_len;
709 u8 erpinfo_content = 0;
711 u8 *tmp_ht_cap_buf;
712 u8 tmp_ht_cap_len=0;
713 u8 *tmp_ht_info_buf;
714 u8 tmp_ht_info_len=0;
715 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
716 u8 *tmp_generic_ie_buf=NULL;
717 u8 tmp_generic_ie_len=0;
719 if(rate_ex_len > 0) rate_ex_len+=2;
721 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
722 atim_len = 4;
723 else
724 atim_len = 0;
726 if(ieee80211_is_54g(&ieee->current_network))
727 erp_len = 3;
728 else
729 erp_len = 0;
732 crypt = ieee->crypt[ieee->tx_keyidx];
735 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
736 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
737 /* HT ralated element */
738 tmp_ht_cap_buf =(u8 *) &(ieee->pHTInfo->SelfHTCap);
739 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
740 tmp_ht_info_buf =(u8 *) &(ieee->pHTInfo->SelfHTInfo);
741 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
742 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
743 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
746 if (pHTInfo->bRegRT2RTAggregation)
748 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
749 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
750 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
752 // printk("===============>tmp_ht_cap_len is %d,tmp_ht_info_len is %d, tmp_generic_ie_len is %d\n",tmp_ht_cap_len,tmp_ht_info_len,tmp_generic_ie_len);
753 beacon_size = sizeof(struct ieee80211_probe_response)+2+
754 ssid_len
755 +3 //channel
756 +rate_len
757 +rate_ex_len
758 +atim_len
759 +erp_len
760 +wpa_ie_len
761 // +tmp_ht_cap_len
762 // +tmp_ht_info_len
763 // +tmp_generic_ie_len
764 // +wmm_len+2
765 +ieee->tx_headroom;
766 skb = dev_alloc_skb(beacon_size);
767 if (!skb)
768 return NULL;
769 skb_reserve(skb, ieee->tx_headroom);
770 beacon_buf = skb_put(skb, (beacon_size - ieee->tx_headroom));
771 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
772 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
773 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
775 beacon_buf->header.duration_id = 0; /* FIXME */
776 beacon_buf->beacon_interval =
777 cpu_to_le16(ieee->current_network.beacon_interval);
778 beacon_buf->capability =
779 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
780 beacon_buf->capability |=
781 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); /* add short preamble here */
783 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
784 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
786 crypt = ieee->crypt[ieee->tx_keyidx];
787 if (encrypt)
788 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
791 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
792 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
793 beacon_buf->info_element[0].len = ssid_len;
795 tag = (u8 *) beacon_buf->info_element[0].data;
797 memcpy(tag, ssid, ssid_len);
799 tag += ssid_len;
801 *(tag++) = MFIE_TYPE_RATES;
802 *(tag++) = rate_len-2;
803 memcpy(tag, ieee->current_network.rates, rate_len-2);
804 tag+=rate_len-2;
806 *(tag++) = MFIE_TYPE_DS_SET;
807 *(tag++) = 1;
808 *(tag++) = ieee->current_network.channel;
810 if (atim_len) {
811 *(tag++) = MFIE_TYPE_IBSS_SET;
812 *(tag++) = 2;
814 put_unaligned_le16(ieee->current_network.atim_window,
815 tag);
816 tag+=2;
819 if (erp_len) {
820 *(tag++) = MFIE_TYPE_ERP;
821 *(tag++) = 1;
822 *(tag++) = erpinfo_content;
824 if (rate_ex_len) {
825 *(tag++) = MFIE_TYPE_RATES_EX;
826 *(tag++) = rate_ex_len-2;
827 memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
828 tag+=rate_ex_len-2;
831 if (wpa_ie_len)
833 if (ieee->iw_mode == IW_MODE_ADHOC)
834 {//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
835 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
837 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
838 tag += wpa_ie_len;
841 //skb->dev = ieee->dev;
842 return skb;
846 static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
847 u8 *dest)
849 struct sk_buff *skb;
850 u8 *tag;
852 struct ieee80211_crypt_data *crypt;
853 struct ieee80211_assoc_response_frame *assoc;
854 short encrypt;
856 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
857 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
859 skb = dev_alloc_skb(len);
861 if (!skb)
862 return NULL;
864 skb_reserve(skb, ieee->tx_headroom);
866 assoc = skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
868 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
869 memcpy(assoc->header.addr1, dest,ETH_ALEN);
870 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
871 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
872 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
873 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
876 if(ieee->short_slot)
877 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
879 if (ieee->host_encrypt)
880 crypt = ieee->crypt[ieee->tx_keyidx];
881 else crypt = NULL;
883 encrypt = crypt && crypt->ops;
885 if (encrypt)
886 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
888 assoc->status = 0;
889 assoc->aid = cpu_to_le16(ieee->assoc_id);
890 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
891 else ieee->assoc_id++;
893 tag = skb_put(skb, rate_len);
895 ieee80211_MFIE_Brate(ieee, &tag);
896 ieee80211_MFIE_Grate(ieee, &tag);
898 return skb;
901 static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
902 int status, u8 *dest)
904 struct sk_buff *skb;
905 struct ieee80211_authentication *auth;
906 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
908 skb = dev_alloc_skb(len);
910 if (!skb)
911 return NULL;
913 skb->len = sizeof(struct ieee80211_authentication);
915 auth = (struct ieee80211_authentication *)skb->data;
917 auth->status = cpu_to_le16(status);
918 auth->transaction = cpu_to_le16(2);
919 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
921 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
922 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
923 memcpy(auth->header.addr1, dest, ETH_ALEN);
924 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
925 return skb;
930 static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
931 short pwr)
933 struct sk_buff *skb;
934 struct rtl_80211_hdr_3addr *hdr;
936 skb = dev_alloc_skb(sizeof(struct rtl_80211_hdr_3addr));
938 if (!skb)
939 return NULL;
941 hdr = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
943 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
944 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
945 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
947 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
948 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
949 (pwr ? IEEE80211_FCTL_PM:0));
951 return skb;
957 static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
959 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
961 if (buf)
962 softmac_mgmt_xmit(buf, ieee);
966 static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
967 u8 *dest)
969 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
971 if (buf)
972 softmac_mgmt_xmit(buf, ieee);
976 static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
980 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
981 if (buf)
982 softmac_mgmt_xmit(buf, ieee);
986 static inline struct sk_buff *
987 ieee80211_association_req(struct ieee80211_network *beacon,
988 struct ieee80211_device *ieee)
990 struct sk_buff *skb;
991 //unsigned long flags;
993 struct ieee80211_assoc_request_frame *hdr;
994 u8 *tag;//,*rsn_ie;
995 //short info_addr = 0;
996 //int i;
997 //u16 suite_count = 0;
998 //u8 suit_select = 0;
999 //unsigned int wpa_len = beacon->wpa_ie_len;
1000 //for HT
1001 u8 *ht_cap_buf = NULL;
1002 u8 ht_cap_len=0;
1003 u8 *realtek_ie_buf=NULL;
1004 u8 realtek_ie_len=0;
1005 int wpa_ie_len= ieee->wpa_ie_len;
1006 unsigned int ckip_ie_len=0;
1007 unsigned int ccxrm_ie_len=0;
1008 unsigned int cxvernum_ie_len=0;
1009 struct ieee80211_crypt_data *crypt;
1010 int encrypt;
1012 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1013 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1014 #ifdef THOMAS_TURBO
1015 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1016 #endif
1018 int len = 0;
1020 crypt = ieee->crypt[ieee->tx_keyidx];
1021 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1023 /* Include High Throuput capability && Realtek proprietary */
1024 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1026 ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
1027 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1028 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
1029 if (ieee->pHTInfo->bCurrentRT2RTAggregation)
1031 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1032 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1033 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1037 if (ieee->qos_support) {
1038 wmm_info_len = beacon->qos_data.supported?9:0;
1042 if (beacon->bCkipSupported)
1044 ckip_ie_len = 30+2;
1046 if (beacon->bCcxRmEnable)
1048 ccxrm_ie_len = 6+2;
1050 if (beacon->BssCcxVerNumber >= 2)
1051 cxvernum_ie_len = 5+2;
1053 #ifdef THOMAS_TURBO
1054 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1055 + beacon->ssid_len /* essid tagged val */
1056 + rate_len /* rates tagged val */
1057 + wpa_ie_len
1058 + wmm_info_len
1059 + turbo_info_len
1060 + ht_cap_len
1061 + realtek_ie_len
1062 + ckip_ie_len
1063 + ccxrm_ie_len
1064 + cxvernum_ie_len
1065 + ieee->tx_headroom;
1066 #else
1067 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
1068 + beacon->ssid_len /* essid tagged val */
1069 + rate_len /* rates tagged val */
1070 + wpa_ie_len
1071 + wmm_info_len
1072 + ht_cap_len
1073 + realtek_ie_len
1074 + ckip_ie_len
1075 + ccxrm_ie_len
1076 + cxvernum_ie_len
1077 + ieee->tx_headroom;
1078 #endif
1080 skb = dev_alloc_skb(len);
1082 if (!skb)
1083 return NULL;
1085 skb_reserve(skb, ieee->tx_headroom);
1087 hdr = skb_put(skb, sizeof(struct ieee80211_assoc_request_frame) + 2);
1090 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1091 hdr->header.duration_id = cpu_to_le16(37);
1092 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1093 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1094 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1096 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1098 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1099 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1100 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1102 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1103 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1105 if(ieee->short_slot)
1106 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1107 if (wmm_info_len) //QOS
1108 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1110 hdr->listen_interval = cpu_to_le16(0xa);
1112 hdr->info_element[0].id = MFIE_TYPE_SSID;
1114 hdr->info_element[0].len = beacon->ssid_len;
1115 skb_put_data(skb, beacon->ssid, beacon->ssid_len);
1117 tag = skb_put(skb, rate_len);
1119 ieee80211_MFIE_Brate(ieee, &tag);
1120 ieee80211_MFIE_Grate(ieee, &tag);
1121 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1122 if (beacon->bCkipSupported) {
1123 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1124 u8 CcxAironetBuf[30];
1125 OCTET_STRING osCcxAironetIE;
1127 memset(CcxAironetBuf, 0, 30);
1128 osCcxAironetIE.Octet = CcxAironetBuf;
1129 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1131 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1132 // We want to make the device type as "4500-client". 060926, by CCW.
1134 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1136 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1137 // "The CKIP negotiation is started with the associate request from the client to the access point,
1138 // containing an Aironet element with both the MIC and KP bits set."
1139 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1140 tag = skb_put(skb, ckip_ie_len);
1141 *tag++ = MFIE_TYPE_AIRONET;
1142 *tag++ = osCcxAironetIE.Length;
1143 memcpy(tag, osCcxAironetIE.Octet, osCcxAironetIE.Length);
1144 tag += osCcxAironetIE.Length;
1147 if (beacon->bCcxRmEnable)
1149 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1150 OCTET_STRING osCcxRmCap;
1152 osCcxRmCap.Octet = CcxRmCapBuf;
1153 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
1154 tag = skb_put(skb, ccxrm_ie_len);
1155 *tag++ = MFIE_TYPE_GENERIC;
1156 *tag++ = osCcxRmCap.Length;
1157 memcpy(tag, osCcxRmCap.Octet, osCcxRmCap.Length);
1158 tag += osCcxRmCap.Length;
1161 if (beacon->BssCcxVerNumber >= 2) {
1162 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1163 OCTET_STRING osCcxVerNum;
1164 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1165 osCcxVerNum.Octet = CcxVerNumBuf;
1166 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
1167 tag = skb_put(skb, cxvernum_ie_len);
1168 *tag++ = MFIE_TYPE_GENERIC;
1169 *tag++ = osCcxVerNum.Length;
1170 memcpy(tag, osCcxVerNum.Octet, osCcxVerNum.Length);
1171 tag += osCcxVerNum.Length;
1173 //HT cap element
1174 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1175 if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
1177 tag = skb_put(skb, ht_cap_len);
1178 *tag++ = MFIE_TYPE_HT_CAP;
1179 *tag++ = ht_cap_len - 2;
1180 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1181 tag += ht_cap_len -2;
1186 //choose what wpa_supplicant gives to associate.
1187 if (wpa_ie_len) {
1188 skb_put_data(skb, ieee->wpa_ie, wpa_ie_len);
1191 if (wmm_info_len) {
1192 tag = skb_put(skb, wmm_info_len);
1193 ieee80211_WMM_Info(ieee, &tag);
1195 #ifdef THOMAS_TURBO
1196 if (turbo_info_len) {
1197 tag = skb_put(skb, turbo_info_len);
1198 ieee80211_TURBO_Info(ieee, &tag);
1200 #endif
1202 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1203 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1205 tag = skb_put(skb, ht_cap_len);
1206 *tag++ = MFIE_TYPE_GENERIC;
1207 *tag++ = ht_cap_len - 2;
1208 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1209 tag += ht_cap_len -2;
1212 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1213 tag = skb_put(skb, realtek_ie_len);
1214 *tag++ = MFIE_TYPE_GENERIC;
1215 *tag++ = realtek_ie_len - 2;
1216 memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
1219 // printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1220 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1221 return skb;
1224 void ieee80211_associate_abort(struct ieee80211_device *ieee)
1227 unsigned long flags;
1228 spin_lock_irqsave(&ieee->lock, flags);
1230 ieee->associate_seq++;
1232 /* don't scan, and avoid to have the RX path possibily
1233 * try again to associate. Even do not react to AUTH or
1234 * ASSOC response. Just wait for the retry wq to be scheduled.
1235 * Here we will check if there are good nets to associate
1236 * with, so we retry or just get back to NO_LINK and scanning
1238 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1239 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1240 ieee->softmac_stats.no_auth_rs++;
1241 }else{
1242 IEEE80211_DEBUG_MGMT("Association failed\n");
1243 ieee->softmac_stats.no_ass_rs++;
1246 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1248 schedule_delayed_work(&ieee->associate_retry_wq, \
1249 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1251 spin_unlock_irqrestore(&ieee->lock, flags);
1254 static void ieee80211_associate_abort_cb(struct timer_list *t)
1256 struct ieee80211_device *dev = from_timer(dev, t, associate_timer);
1258 ieee80211_associate_abort(dev);
1262 static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1264 struct ieee80211_network *beacon = &ieee->current_network;
1265 struct sk_buff *skb;
1267 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1269 ieee->softmac_stats.tx_auth_rq++;
1270 skb=ieee80211_authentication_req(beacon, ieee, 0);
1272 if (!skb)
1273 ieee80211_associate_abort(ieee);
1274 else{
1275 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1276 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1277 softmac_mgmt_xmit(skb, ieee);
1278 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1279 if (!timer_pending(&ieee->associate_timer)) {
1280 ieee->associate_timer.expires = jiffies + (HZ / 2);
1281 add_timer(&ieee->associate_timer);
1283 //dev_kfree_skb_any(skb);//edit by thomas
1287 static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1288 u8 *challenge,
1289 int chlen)
1291 u8 *c;
1292 struct sk_buff *skb;
1293 struct ieee80211_network *beacon = &ieee->current_network;
1294 // int hlen = sizeof(struct ieee80211_authentication);
1296 ieee->associate_seq++;
1297 ieee->softmac_stats.tx_auth_rq++;
1299 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1300 if (!skb)
1301 ieee80211_associate_abort(ieee);
1302 else{
1303 c = skb_put(skb, chlen+2);
1304 *(c++) = MFIE_TYPE_CHALLENGE;
1305 *(c++) = chlen;
1306 memcpy(c, challenge, chlen);
1308 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1310 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr ));
1312 softmac_mgmt_xmit(skb, ieee);
1313 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1314 //dev_kfree_skb_any(skb);//edit by thomas
1316 kfree(challenge);
1319 static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1321 struct sk_buff *skb;
1322 struct ieee80211_network *beacon = &ieee->current_network;
1324 del_timer_sync(&ieee->associate_timer);
1326 IEEE80211_DEBUG_MGMT("Sending association request\n");
1328 ieee->softmac_stats.tx_ass_rq++;
1329 skb=ieee80211_association_req(beacon, ieee);
1330 if (!skb)
1331 ieee80211_associate_abort(ieee);
1332 else{
1333 softmac_mgmt_xmit(skb, ieee);
1334 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
1335 //dev_kfree_skb_any(skb);//edit by thomas
1338 static void ieee80211_associate_complete_wq(struct work_struct *work)
1340 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1341 printk(KERN_INFO "Associated successfully\n");
1342 if(ieee80211_is_54g(&ieee->current_network) &&
1343 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1345 ieee->rate = 108;
1346 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1347 }else{
1348 ieee->rate = 22;
1349 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1351 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1353 printk("Successfully associated, ht enabled\n");
1354 HTOnAssocRsp(ieee);
1356 else
1358 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1359 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1360 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1362 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1363 // To prevent the immediately calling watch_dog after association.
1364 if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
1366 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1367 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1369 ieee->link_change(ieee->dev);
1370 if (!ieee->is_silent_reset) {
1371 printk("============>normal associate\n");
1372 notify_wx_assoc_event(ieee);
1373 } else {
1374 printk("==================>silent reset associate\n");
1375 ieee->is_silent_reset = false;
1378 if (ieee->data_hard_resume)
1379 ieee->data_hard_resume(ieee->dev);
1380 netif_carrier_on(ieee->dev);
1383 static void ieee80211_associate_complete(struct ieee80211_device *ieee)
1385 // int i;
1386 // struct net_device* dev = ieee->dev;
1387 del_timer_sync(&ieee->associate_timer);
1389 ieee->state = IEEE80211_LINKED;
1390 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1391 schedule_work(&ieee->associate_complete_wq);
1394 static void ieee80211_associate_procedure_wq(struct work_struct *work)
1396 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
1397 ieee->sync_scan_hurryup = 1;
1398 mutex_lock(&ieee->wx_mutex);
1400 if (ieee->data_hard_stop)
1401 ieee->data_hard_stop(ieee->dev);
1403 ieee80211_stop_scan(ieee);
1404 printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
1405 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1406 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1408 ieee->associate_seq = 1;
1409 ieee80211_associate_step1(ieee);
1411 mutex_unlock(&ieee->wx_mutex);
1414 inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1416 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1417 int tmp_ssid_len = 0;
1419 short apset, ssidset, ssidbroad, apmatch, ssidmatch;
1421 /* we are interested in new new only if we are not associated
1422 * and we are not associating / authenticating
1424 if (ieee->state != IEEE80211_NOLINK)
1425 return;
1427 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1428 return;
1430 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1431 return;
1434 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
1435 /* if the user specified the AP MAC, we need also the essid
1436 * This could be obtained by beacons or, if the network does not
1437 * broadcast it, it can be put manually.
1439 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1440 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1441 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1442 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1443 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1444 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1447 if ( /* if the user set the AP check if match.
1448 * if the network does not broadcast essid we check the user supplyed ANY essid
1449 * if the network does broadcast and the user does not set essid it is OK
1450 * if the network does broadcast and the user did set essid chech if essid match
1452 (apset && apmatch &&
1453 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1454 /* if the ap is not set, check that the user set the bssid
1455 * and the network does broadcast and that those two bssid matches
1457 (!apset && ssidset && ssidbroad && ssidmatch)
1459 /* if the essid is hidden replace it with the
1460 * essid provided by the user.
1462 if (!ssidbroad) {
1463 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1464 tmp_ssid_len = ieee->current_network.ssid_len;
1466 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1468 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1469 ieee->current_network.ssid_len = tmp_ssid_len;
1470 printk(KERN_INFO"Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",ieee->current_network.ssid,ieee->current_network.channel, ieee->current_network.qos_data.supported, ieee->pHTInfo->bEnableHT, ieee->current_network.bssht.bdSupportHT);
1472 //ieee->pHTInfo->IOTAction = 0;
1473 HTResetIOTSetting(ieee->pHTInfo);
1474 if (ieee->iw_mode == IW_MODE_INFRA){
1475 /* Join the network for the first time */
1476 ieee->AsocRetryCount = 0;
1477 //for HT by amy 080514
1478 if((ieee->current_network.qos_data.supported == 1) &&
1479 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1480 ieee->current_network.bssht.bdSupportHT)
1481 /*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.*/
1483 // ieee->pHTInfo->bCurrentHTSupport = true;
1484 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1486 else
1488 ieee->pHTInfo->bCurrentHTSupport = false;
1491 ieee->state = IEEE80211_ASSOCIATING;
1492 schedule_work(&ieee->associate_procedure_wq);
1493 }else{
1494 if(ieee80211_is_54g(&ieee->current_network) &&
1495 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1496 ieee->rate = 108;
1497 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1498 printk(KERN_INFO"Using G rates\n");
1499 }else{
1500 ieee->rate = 22;
1501 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1502 printk(KERN_INFO"Using B rates\n");
1504 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1505 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1506 ieee->state = IEEE80211_LINKED;
1514 void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1516 unsigned long flags;
1517 struct ieee80211_network *target;
1519 spin_lock_irqsave(&ieee->lock, flags);
1521 list_for_each_entry(target, &ieee->network_list, list) {
1523 /* if the state become different that NOLINK means
1524 * we had found what we are searching for
1527 if (ieee->state != IEEE80211_NOLINK)
1528 break;
1530 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1531 ieee80211_softmac_new_net(ieee, target);
1534 spin_unlock_irqrestore(&ieee->lock, flags);
1539 static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1541 struct ieee80211_authentication *a;
1542 u8 *t;
1543 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1544 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1545 return 0xcafe;
1547 *challenge = NULL;
1548 a = (struct ieee80211_authentication *) skb->data;
1549 if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1550 t = skb->data + sizeof(struct ieee80211_authentication);
1552 if (*(t++) == MFIE_TYPE_CHALLENGE) {
1553 *chlen = *(t++);
1554 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1555 if (!*challenge)
1556 return -ENOMEM;
1560 return le16_to_cpu(a->status);
1565 static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1567 struct ieee80211_authentication *a;
1569 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1570 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1571 return -1;
1573 a = (struct ieee80211_authentication *) skb->data;
1575 memcpy(dest,a->header.addr2, ETH_ALEN);
1577 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1578 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1580 return WLAN_STATUS_SUCCESS;
1583 static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1585 u8 *tag;
1586 u8 *skbend;
1587 u8 *ssid=NULL;
1588 u8 ssidlen = 0;
1590 struct rtl_80211_hdr_3addr *header =
1591 (struct rtl_80211_hdr_3addr *) skb->data;
1593 if (skb->len < sizeof (struct rtl_80211_hdr_3addr ))
1594 return -1; /* corrupted */
1596 memcpy(src,header->addr2, ETH_ALEN);
1598 skbend = (u8 *)skb->data + skb->len;
1600 tag = skb->data + sizeof (struct rtl_80211_hdr_3addr );
1602 while (tag+1 < skbend){
1603 if (*tag == 0) {
1604 ssid = tag+2;
1605 ssidlen = *(tag+1);
1606 break;
1608 tag++; /* point to the len field */
1609 tag = tag + *(tag); /* point to the last data byte of the tag */
1610 tag++; /* point to the next tag */
1613 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1614 if (ssidlen == 0) return 1;
1616 if (!ssid) return 1; /* ssid not found in tagged param */
1617 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1621 static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1623 struct ieee80211_assoc_request_frame *a;
1625 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1626 sizeof(struct ieee80211_info_element))) {
1628 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1629 return -1;
1632 a = (struct ieee80211_assoc_request_frame *) skb->data;
1634 memcpy(dest,a->header.addr2,ETH_ALEN);
1636 return 0;
1639 static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1641 struct ieee80211_assoc_response_frame *response_head;
1642 u16 status_code;
1644 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1645 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1646 return 0xcafe;
1649 response_head = (struct ieee80211_assoc_response_frame *) skb->data;
1650 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1652 status_code = le16_to_cpu(response_head->status);
1653 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1654 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1655 ((ieee->mode == IEEE_G) &&
1656 (ieee->current_network.mode == IEEE_N_24G) &&
1657 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1658 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1659 }else {
1660 ieee->AsocRetryCount = 0;
1663 return le16_to_cpu(response_head->status);
1666 static inline void
1667 ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1669 u8 dest[ETH_ALEN];
1671 //IEEE80211DMESG("Rx probe");
1672 ieee->softmac_stats.rx_probe_rq++;
1673 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1674 if (probe_rq_parse(ieee, skb, dest)) {
1675 //IEEE80211DMESG("Was for me!");
1676 ieee->softmac_stats.tx_probe_rs++;
1677 ieee80211_resp_to_probe(ieee, dest);
1681 static inline void
1682 ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1684 u8 dest[ETH_ALEN];
1685 int status;
1686 //IEEE80211DMESG("Rx probe");
1687 ieee->softmac_stats.rx_auth_rq++;
1689 status = auth_rq_parse(skb, dest);
1690 if (status != -1) {
1691 ieee80211_resp_to_auth(ieee, status, dest);
1693 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1697 static inline void
1698 ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1701 u8 dest[ETH_ALEN];
1702 //unsigned long flags;
1704 ieee->softmac_stats.rx_ass_rq++;
1705 if (assoc_rq_parse(skb, dest) != -1) {
1706 ieee80211_resp_to_assoc_rq(ieee, dest);
1709 printk(KERN_INFO"New client associated: %pM\n", dest);
1710 //FIXME
1713 static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1714 short pwr)
1717 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1719 if (buf)
1720 softmac_ps_mgmt_xmit(buf, ieee);
1723 /* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1725 static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1726 u32 *time_l)
1728 int timeout;
1729 u8 dtim;
1730 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1731 ieee->iw_mode != IW_MODE_INFRA ||
1732 ieee->state != IEEE80211_LINKED)
1734 return 0;
1736 dtim = ieee->current_network.dtim_data;
1737 if(!(dtim & IEEE80211_DTIM_VALID))
1738 return 0;
1739 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1740 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1742 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1743 return 2;
1745 if(!time_after(jiffies,
1746 dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
1747 return 0;
1749 if(!time_after(jiffies,
1750 ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
1751 return 0;
1753 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1754 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1755 return 0;
1757 if (time_l) {
1758 *time_l = ieee->current_network.last_dtim_sta_time[0]
1759 + (ieee->current_network.beacon_interval
1760 * ieee->current_network.dtim_period) * 1000;
1763 if (time_h) {
1764 *time_h = ieee->current_network.last_dtim_sta_time[1];
1765 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1766 *time_h += 1;
1769 return 1;
1774 static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
1777 u32 th, tl;
1778 short sleep;
1780 unsigned long flags, flags2;
1782 spin_lock_irqsave(&ieee->lock, flags);
1784 if ((ieee->ps == IEEE80211_PS_DISABLED ||
1785 ieee->iw_mode != IW_MODE_INFRA ||
1786 ieee->state != IEEE80211_LINKED)){
1788 // #warning CHECK_LOCK_HERE
1789 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1791 ieee80211_sta_wakeup(ieee, 1);
1793 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1796 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1797 /* 2 wake, 1 sleep, 0 do nothing */
1798 if(sleep == 0)
1799 goto out;
1801 if(sleep == 1){
1803 if(ieee->sta_sleep == 1)
1804 ieee->enter_sleep_state(ieee->dev, th, tl);
1806 else if(ieee->sta_sleep == 0){
1807 // printk("send null 1\n");
1808 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1810 if(ieee->ps_is_queue_empty(ieee->dev)){
1813 ieee->sta_sleep = 2;
1815 ieee->ps_request_tx_ack(ieee->dev);
1817 ieee80211_sta_ps_send_null_frame(ieee, 1);
1819 ieee->ps_th = th;
1820 ieee->ps_tl = tl;
1822 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1827 }else if(sleep == 2){
1828 //#warning CHECK_LOCK_HERE
1829 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1831 ieee80211_sta_wakeup(ieee, 1);
1833 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1836 out:
1837 spin_unlock_irqrestore(&ieee->lock, flags);
1841 void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1843 if (ieee->sta_sleep == 0) {
1844 if (nl) {
1845 printk("Warning: driver is probably failing to report TX ps error\n");
1846 ieee->ps_request_tx_ack(ieee->dev);
1847 ieee80211_sta_ps_send_null_frame(ieee, 0);
1849 return;
1853 if(ieee->sta_sleep == 1)
1854 ieee->sta_wake_up(ieee->dev);
1856 ieee->sta_sleep = 0;
1858 if (nl) {
1859 ieee->ps_request_tx_ack(ieee->dev);
1860 ieee80211_sta_ps_send_null_frame(ieee, 0);
1864 void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1866 unsigned long flags, flags2;
1868 spin_lock_irqsave(&ieee->lock, flags);
1870 if(ieee->sta_sleep == 2){
1871 /* Null frame with PS bit set */
1872 if (success) {
1873 ieee->sta_sleep = 1;
1874 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1876 /* if the card report not success we can't be sure the AP
1877 * has not RXed so we can't assume the AP believe us awake
1880 /* 21112005 - tx again null without PS bit if lost */
1881 else {
1883 if ((ieee->sta_sleep == 0) && !success) {
1884 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1885 ieee80211_sta_ps_send_null_frame(ieee, 0);
1886 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1889 spin_unlock_irqrestore(&ieee->lock, flags);
1891 EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1893 static void ieee80211_process_action(struct ieee80211_device *ieee,
1894 struct sk_buff *skb)
1896 struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
1897 u8 *act = ieee80211_get_payload(header);
1898 u8 tmp = 0;
1899 // IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1900 if (act == NULL)
1902 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1903 return;
1905 tmp = *act;
1906 act ++;
1907 switch (tmp) {
1908 case ACT_CAT_BA:
1909 if (*act == ACT_ADDBAREQ)
1910 ieee80211_rx_ADDBAReq(ieee, skb);
1911 else if (*act == ACT_ADDBARSP)
1912 ieee80211_rx_ADDBARsp(ieee, skb);
1913 else if (*act == ACT_DELBA)
1914 ieee80211_rx_DELBA(ieee, skb);
1915 break;
1916 default:
1917 break;
1919 return;
1923 static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1924 struct sk_buff *skb)
1926 /* default support N mode, disable halfNmode */
1927 bool bSupportNmode = true, bHalfSupportNmode = false;
1928 u16 errcode;
1929 u8 *challenge;
1930 int chlen = 0;
1931 u32 iotAction;
1933 errcode = auth_parse(skb, &challenge, &chlen);
1934 if (!errcode) {
1935 if (ieee->open_wep || !challenge) {
1936 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1937 ieee->softmac_stats.rx_auth_rs_ok++;
1938 iotAction = ieee->pHTInfo->IOTAction;
1939 if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1940 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1941 /* WEP or TKIP encryption */
1942 if (IsHTHalfNmodeAPs(ieee)) {
1943 bSupportNmode = true;
1944 bHalfSupportNmode = true;
1945 } else {
1946 bSupportNmode = false;
1947 bHalfSupportNmode = false;
1949 netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1950 bSupportNmode,
1951 bHalfSupportNmode);
1954 /* Dummy wirless mode setting- avoid encryption issue */
1955 if (bSupportNmode) {
1956 /* N mode setting */
1957 ieee->SetWirelessMode(ieee->dev,
1958 ieee->current_network.mode);
1959 } else {
1960 /* b/g mode setting - TODO */
1961 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1964 if (ieee->current_network.mode == IEEE_N_24G &&
1965 bHalfSupportNmode) {
1966 netdev_dbg(ieee->dev, "enter half N mode\n");
1967 ieee->bHalfWirelessN24GMode = true;
1968 } else
1969 ieee->bHalfWirelessN24GMode = false;
1971 ieee80211_associate_step2(ieee);
1972 } else {
1973 ieee80211_auth_challenge(ieee, challenge, chlen);
1975 } else {
1976 ieee->softmac_stats.rx_auth_rs_err++;
1977 IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1978 ieee80211_associate_abort(ieee);
1982 inline int
1983 ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1984 struct ieee80211_rx_stats *rx_stats, u16 type,
1985 u16 stype)
1987 struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *) skb->data;
1988 u16 errcode;
1989 int aid;
1990 struct ieee80211_assoc_response_frame *assoc_resp;
1991 // struct ieee80211_info_element *info_element;
1993 if(!ieee->proto_started)
1994 return 0;
1996 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1997 ieee->iw_mode == IW_MODE_INFRA &&
1998 ieee->state == IEEE80211_LINKED))
2000 tasklet_schedule(&ieee->ps_task);
2002 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2003 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2004 ieee->last_rx_ps_time = jiffies;
2006 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2008 case IEEE80211_STYPE_ASSOC_RESP:
2009 case IEEE80211_STYPE_REASSOC_RESP:
2011 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2012 WLAN_FC_GET_STYPE(header->frame_ctl));
2013 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2014 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2015 ieee->iw_mode == IW_MODE_INFRA){
2016 struct ieee80211_network network_resp;
2017 struct ieee80211_network *network = &network_resp;
2019 errcode = assoc_parse(ieee, skb, &aid);
2020 if (!errcode) {
2021 ieee->state=IEEE80211_LINKED;
2022 ieee->assoc_id = aid;
2023 ieee->softmac_stats.rx_ass_ok++;
2024 /* station support qos */
2025 /* Let the register setting defaultly with Legacy station */
2026 if (ieee->qos_support) {
2027 assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
2028 memset(network, 0, sizeof(*network));
2029 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2030 rx_stats->len - sizeof(*assoc_resp),\
2031 network,rx_stats)){
2032 return 1;
2034 else
2035 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2036 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2037 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
2039 if (ieee->handle_assoc_response != NULL)
2040 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
2042 ieee80211_associate_complete(ieee);
2043 } else {
2044 /* aid could not been allocated */
2045 ieee->softmac_stats.rx_ass_err++;
2046 printk(
2047 "Association response status code 0x%x\n",
2048 errcode);
2049 IEEE80211_DEBUG_MGMT(
2050 "Association response status code 0x%x\n",
2051 errcode);
2052 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
2053 schedule_work(&ieee->associate_procedure_wq);
2054 } else {
2055 ieee80211_associate_abort(ieee);
2059 break;
2061 case IEEE80211_STYPE_ASSOC_REQ:
2062 case IEEE80211_STYPE_REASSOC_REQ:
2064 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2065 ieee->iw_mode == IW_MODE_MASTER)
2067 ieee80211_rx_assoc_rq(ieee, skb);
2068 break;
2070 case IEEE80211_STYPE_AUTH:
2072 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
2073 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
2074 && ieee->iw_mode == IW_MODE_INFRA) {
2076 IEEE80211_DEBUG_MGMT("Received auth response");
2077 ieee80211_check_auth_response(ieee, skb);
2078 } else if (ieee->iw_mode == IW_MODE_MASTER) {
2079 ieee80211_rx_auth_rq(ieee, skb);
2082 break;
2084 case IEEE80211_STYPE_PROBE_REQ:
2086 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2087 ((ieee->iw_mode == IW_MODE_ADHOC ||
2088 ieee->iw_mode == IW_MODE_MASTER) &&
2089 ieee->state == IEEE80211_LINKED)){
2090 ieee80211_rx_probe_rq(ieee, skb);
2092 break;
2094 case IEEE80211_STYPE_DISASSOC:
2095 case IEEE80211_STYPE_DEAUTH:
2096 /* FIXME for now repeat all the association procedure
2097 * both for disassociation and deauthentication
2099 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2100 ieee->state == IEEE80211_LINKED &&
2101 ieee->iw_mode == IW_MODE_INFRA){
2103 ieee->state = IEEE80211_ASSOCIATING;
2104 ieee->softmac_stats.reassoc++;
2106 notify_wx_assoc_event(ieee);
2107 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2108 RemovePeerTS(ieee, header->addr2);
2109 schedule_work(&ieee->associate_procedure_wq);
2111 break;
2112 case IEEE80211_STYPE_MANAGE_ACT:
2113 ieee80211_process_action(ieee, skb);
2114 break;
2115 default:
2116 return -1;
2119 //dev_kfree_skb_any(skb);
2120 return 0;
2123 /* The following are for a simpler TX queue management.
2124 * Instead of using netif_[stop/wake]_queue, the driver
2125 * will use these two functions (plus a reset one) that
2126 * will internally call the kernel netif_* and take care
2127 * of the ieee802.11 fragmentation.
2128 * So, the driver receives a fragment at a time and might
2129 * call the stop function when it wants, without taking
2130 * care to have enough room to TX an entire packet.
2131 * This might be useful if each fragment needs its own
2132 * descriptor. Thus, just keeping a total free memory > than
2133 * the max fragmentation threshold is not enough. If the
2134 * ieee802.11 stack passed a TXB struct, then you would need
2135 * to keep N free descriptors where
2136 * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
2137 * In this way you need just one and the 802.11 stack
2138 * will take care of buffering fragments and pass them to
2139 * to the driver later, when it wakes the queue.
2141 void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2144 unsigned int queue_index = txb->queue_index;
2145 unsigned long flags;
2146 int i;
2147 struct cb_desc *tcb_desc = NULL;
2149 spin_lock_irqsave(&ieee->lock, flags);
2151 /* called with 2nd parm 0, no tx mgmt lock required */
2152 ieee80211_sta_wakeup(ieee, 0);
2154 /* update the tx status */
2155 ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2156 ieee->stats.tx_packets++;
2157 tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2158 if (tcb_desc->bMulticast) {
2159 ieee->stats.multicast++;
2161 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2162 for(i = 0; i < txb->nr_frags; i++) {
2163 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2164 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2165 #else
2166 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2167 #endif
2168 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2169 (ieee->queue_stop)) {
2170 /* insert the skb packet to the wait queue */
2171 /* as for the completion function, it does not need
2172 * to check it any more.
2173 * */
2174 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2175 //ieee80211_stop_queue(ieee);
2176 #ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2177 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2178 #else
2179 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2180 #endif
2181 }else{
2182 ieee->softmac_data_hard_start_xmit(
2183 txb->fragments[i],
2184 ieee->dev, ieee->rate);
2185 //ieee->stats.tx_packets++;
2186 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2187 //ieee->dev->trans_start = jiffies;
2190 ieee80211_txb_free(txb);
2192 //exit:
2193 spin_unlock_irqrestore(&ieee->lock, flags);
2196 EXPORT_SYMBOL(ieee80211_softmac_xmit);
2198 /* called with ieee->lock acquired */
2199 static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2201 int i;
2202 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2204 if (ieee->queue_stop){
2205 ieee->tx_pending.frag = i;
2206 return;
2207 }else{
2209 ieee->softmac_data_hard_start_xmit(
2210 ieee->tx_pending.txb->fragments[i],
2211 ieee->dev, ieee->rate);
2212 //(i+1)<ieee->tx_pending.txb->nr_frags);
2213 ieee->stats.tx_packets++;
2214 netif_trans_update(ieee->dev);
2219 ieee80211_txb_free(ieee->tx_pending.txb);
2220 ieee->tx_pending.txb = NULL;
2224 void ieee80211_reset_queue(struct ieee80211_device *ieee)
2226 unsigned long flags;
2228 spin_lock_irqsave(&ieee->lock, flags);
2229 init_mgmt_queue(ieee);
2230 if (ieee->tx_pending.txb) {
2231 ieee80211_txb_free(ieee->tx_pending.txb);
2232 ieee->tx_pending.txb = NULL;
2234 ieee->queue_stop = 0;
2235 spin_unlock_irqrestore(&ieee->lock, flags);
2238 EXPORT_SYMBOL(ieee80211_reset_queue);
2240 void ieee80211_wake_queue(struct ieee80211_device *ieee)
2243 unsigned long flags;
2244 struct sk_buff *skb;
2245 struct rtl_80211_hdr_3addr *header;
2247 spin_lock_irqsave(&ieee->lock, flags);
2248 if (! ieee->queue_stop) goto exit;
2250 ieee->queue_stop = 0;
2252 if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2253 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2255 header = (struct rtl_80211_hdr_3addr *) skb->data;
2257 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2259 if (ieee->seq_ctrl[0] == 0xFFF)
2260 ieee->seq_ctrl[0] = 0;
2261 else
2262 ieee->seq_ctrl[0]++;
2264 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2265 //dev_kfree_skb_any(skb);//edit by thomas
2268 if (!ieee->queue_stop && ieee->tx_pending.txb)
2269 ieee80211_resume_tx(ieee);
2271 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2272 ieee->softmac_stats.swtxawake++;
2273 netif_wake_queue(ieee->dev);
2276 exit :
2277 spin_unlock_irqrestore(&ieee->lock, flags);
2279 EXPORT_SYMBOL(ieee80211_wake_queue);
2281 void ieee80211_stop_queue(struct ieee80211_device *ieee)
2283 //unsigned long flags;
2284 //spin_lock_irqsave(&ieee->lock,flags);
2286 if (!netif_queue_stopped(ieee->dev)) {
2287 netif_stop_queue(ieee->dev);
2288 ieee->softmac_stats.swtxstop++;
2290 ieee->queue_stop = 1;
2291 //spin_unlock_irqrestore(&ieee->lock,flags);
2294 EXPORT_SYMBOL(ieee80211_stop_queue);
2296 /* called in user context only */
2297 void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2299 ieee->assoc_id = 1;
2301 if (ieee->current_network.ssid_len == 0) {
2302 strncpy(ieee->current_network.ssid,
2303 IEEE80211_DEFAULT_TX_ESSID,
2304 IW_ESSID_MAX_SIZE);
2306 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2307 ieee->ssid_set = 1;
2310 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2312 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2313 ieee->state = IEEE80211_LINKED;
2314 ieee->link_change(ieee->dev);
2315 notify_wx_assoc_event(ieee);
2317 if (ieee->data_hard_resume)
2318 ieee->data_hard_resume(ieee->dev);
2320 netif_carrier_on(ieee->dev);
2323 static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2325 if (ieee->raw_tx) {
2327 if (ieee->data_hard_resume)
2328 ieee->data_hard_resume(ieee->dev);
2330 netif_carrier_on(ieee->dev);
2333 static void ieee80211_start_ibss_wq(struct work_struct *work)
2336 struct delayed_work *dwork = to_delayed_work(work);
2337 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2338 /* iwconfig mode ad-hoc will schedule this and return
2339 * on the other hand this will block further iwconfig SET
2340 * operations because of the wx_mutex hold.
2341 * Anyway some most set operations set a flag to speed-up
2342 * (abort) this wq (when syncro scanning) before sleeping
2343 * on the semaphore
2345 if (!ieee->proto_started) {
2346 printk("==========oh driver down return\n");
2347 return;
2349 mutex_lock(&ieee->wx_mutex);
2351 if (ieee->current_network.ssid_len == 0) {
2352 strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
2353 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2354 ieee->ssid_set = 1;
2357 /* check if we have this cell in our network list */
2358 ieee80211_softmac_check_all_nets(ieee);
2361 // if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2362 if (ieee->state == IEEE80211_NOLINK)
2363 ieee->current_network.channel = 6;
2364 /* if not then the state is not linked. Maybe the user switched to
2365 * ad-hoc mode just after being in monitor mode, or just after
2366 * being very few time in managed mode (so the card have had no
2367 * time to scan all the chans..) or we have just run up the iface
2368 * after setting ad-hoc mode. So we have to give another try..
2369 * Here, in ibss mode, should be safe to do this without extra care
2370 * (in bss mode we had to make sure no-one tryed to associate when
2371 * we had just checked the ieee->state and we was going to start the
2372 * scan) beacause in ibss mode the ieee80211_new_net function, when
2373 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2374 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2375 * scan, that will stop at the first round because it sees the state
2376 * associated.
2378 if (ieee->state == IEEE80211_NOLINK)
2379 ieee80211_start_scan_syncro(ieee);
2381 /* the network definitively is not here.. create a new cell */
2382 if (ieee->state == IEEE80211_NOLINK) {
2383 printk("creating new IBSS cell\n");
2384 if(!ieee->wap_set)
2385 random_ether_addr(ieee->current_network.bssid);
2387 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2389 ieee->current_network.rates_len = 4;
2391 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2392 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2393 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2394 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2396 }else
2397 ieee->current_network.rates_len = 0;
2399 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2400 ieee->current_network.rates_ex_len = 8;
2402 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2403 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2404 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2405 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2406 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2407 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2408 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2409 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2411 ieee->rate = 108;
2412 }else{
2413 ieee->current_network.rates_ex_len = 0;
2414 ieee->rate = 22;
2417 // By default, WMM function will be disabled in IBSS mode
2418 ieee->current_network.QoS_Enable = 0;
2419 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2420 ieee->current_network.atim_window = 0;
2421 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2422 if(ieee->short_slot)
2423 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2427 ieee->state = IEEE80211_LINKED;
2429 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2430 ieee->link_change(ieee->dev);
2432 notify_wx_assoc_event(ieee);
2434 ieee80211_start_send_beacons(ieee);
2436 if (ieee->data_hard_resume)
2437 ieee->data_hard_resume(ieee->dev);
2438 netif_carrier_on(ieee->dev);
2440 mutex_unlock(&ieee->wx_mutex);
2443 inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2445 schedule_delayed_work(&ieee->start_ibss_wq, 150);
2448 /* this is called only in user context, with wx_mutex held */
2449 void ieee80211_start_bss(struct ieee80211_device *ieee)
2451 unsigned long flags;
2453 // Ref: 802.11d 11.1.3.3
2454 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2456 if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
2458 if (! ieee->bGlobalDomain)
2460 return;
2463 /* check if we have already found the net we
2464 * are interested in (if any).
2465 * if not (we are disassociated and we are not
2466 * in associating / authenticating phase) start the background scanning.
2468 ieee80211_softmac_check_all_nets(ieee);
2470 /* ensure no-one start an associating process (thus setting
2471 * the ieee->state to ieee80211_ASSOCIATING) while we
2472 * have just cheked it and we are going to enable scan.
2473 * The ieee80211_new_net function is always called with
2474 * lock held (from both ieee80211_softmac_check_all_nets and
2475 * the rx path), so we cannot be in the middle of such function
2477 spin_lock_irqsave(&ieee->lock, flags);
2479 if (ieee->state == IEEE80211_NOLINK) {
2480 ieee->actscanning = true;
2481 ieee80211_start_scan(ieee);
2483 spin_unlock_irqrestore(&ieee->lock, flags);
2486 /* called only in userspace context */
2487 void ieee80211_disassociate(struct ieee80211_device *ieee)
2491 netif_carrier_off(ieee->dev);
2492 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2493 ieee80211_reset_queue(ieee);
2495 if (ieee->data_hard_stop)
2496 ieee->data_hard_stop(ieee->dev);
2497 if(IS_DOT11D_ENABLE(ieee))
2498 Dot11d_Reset(ieee);
2499 ieee->state = IEEE80211_NOLINK;
2500 ieee->is_set_key = false;
2501 ieee->link_change(ieee->dev);
2502 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2503 notify_wx_assoc_event(ieee);
2506 EXPORT_SYMBOL(ieee80211_disassociate);
2508 static void ieee80211_associate_retry_wq(struct work_struct *work)
2510 struct delayed_work *dwork = to_delayed_work(work);
2511 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2512 unsigned long flags;
2514 mutex_lock(&ieee->wx_mutex);
2515 if(!ieee->proto_started)
2516 goto exit;
2518 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2519 goto exit;
2521 /* until we do not set the state to IEEE80211_NOLINK
2522 * there are no possibility to have someone else trying
2523 * to start an association procedure (we get here with
2524 * ieee->state = IEEE80211_ASSOCIATING).
2525 * When we set the state to IEEE80211_NOLINK it is possible
2526 * that the RX path run an attempt to associate, but
2527 * both ieee80211_softmac_check_all_nets and the
2528 * RX path works with ieee->lock held so there are no
2529 * problems. If we are still disassociated then start a scan.
2530 * the lock here is necessary to ensure no one try to start
2531 * an association procedure when we have just checked the
2532 * state and we are going to start the scan.
2534 ieee->state = IEEE80211_NOLINK;
2536 ieee80211_softmac_check_all_nets(ieee);
2538 spin_lock_irqsave(&ieee->lock, flags);
2540 if(ieee->state == IEEE80211_NOLINK)
2541 ieee80211_start_scan(ieee);
2543 spin_unlock_irqrestore(&ieee->lock, flags);
2545 exit:
2546 mutex_unlock(&ieee->wx_mutex);
2549 struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2551 u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2553 struct sk_buff *skb;
2554 struct ieee80211_probe_response *b;
2556 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2558 if (!skb)
2559 return NULL;
2561 b = (struct ieee80211_probe_response *) skb->data;
2562 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2564 return skb;
2568 struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2570 struct sk_buff *skb;
2571 struct ieee80211_probe_response *b;
2573 skb = ieee80211_get_beacon_(ieee);
2574 if(!skb)
2575 return NULL;
2577 b = (struct ieee80211_probe_response *) skb->data;
2578 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2580 if (ieee->seq_ctrl[0] == 0xFFF)
2581 ieee->seq_ctrl[0] = 0;
2582 else
2583 ieee->seq_ctrl[0]++;
2585 return skb;
2587 EXPORT_SYMBOL(ieee80211_get_beacon);
2589 void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2591 ieee->sync_scan_hurryup = 1;
2592 mutex_lock(&ieee->wx_mutex);
2593 ieee80211_stop_protocol(ieee);
2594 mutex_unlock(&ieee->wx_mutex);
2596 EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2598 void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2600 if (!ieee->proto_started)
2601 return;
2603 ieee->proto_started = 0;
2605 ieee80211_stop_send_beacons(ieee);
2606 del_timer_sync(&ieee->associate_timer);
2607 cancel_delayed_work(&ieee->associate_retry_wq);
2608 cancel_delayed_work(&ieee->start_ibss_wq);
2609 ieee80211_stop_scan(ieee);
2611 ieee80211_disassociate(ieee);
2612 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2615 void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2617 ieee->sync_scan_hurryup = 0;
2618 mutex_lock(&ieee->wx_mutex);
2619 ieee80211_start_protocol(ieee);
2620 mutex_unlock(&ieee->wx_mutex);
2622 EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2624 void ieee80211_start_protocol(struct ieee80211_device *ieee)
2626 short ch = 0;
2627 int i = 0;
2629 if (ieee->proto_started)
2630 return;
2632 ieee->proto_started = 1;
2634 if (ieee->current_network.channel == 0) {
2636 ch++;
2637 if (ch > MAX_CHANNEL_NUMBER)
2638 return; /* no channel found */
2639 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2640 ieee->current_network.channel = ch;
2643 if (ieee->current_network.beacon_interval == 0)
2644 ieee->current_network.beacon_interval = 100;
2645 // printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2646 // ieee->set_chan(ieee->dev,ieee->current_network.channel);
2648 for(i = 0; i < 17; i++) {
2649 ieee->last_rxseq_num[i] = -1;
2650 ieee->last_rxfrag_num[i] = -1;
2651 ieee->last_packet_time[i] = 0;
2654 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2657 /* if the user set the MAC of the ad-hoc cell and then
2658 * switch to managed mode, shall we make sure that association
2659 * attempts does not fail just because the user provide the essid
2660 * and the nic is still checking for the AP MAC ??
2662 if (ieee->iw_mode == IW_MODE_INFRA)
2663 ieee80211_start_bss(ieee);
2665 else if (ieee->iw_mode == IW_MODE_ADHOC)
2666 ieee80211_start_ibss(ieee);
2668 else if (ieee->iw_mode == IW_MODE_MASTER)
2669 ieee80211_start_master_bss(ieee);
2671 else if(ieee->iw_mode == IW_MODE_MONITOR)
2672 ieee80211_start_monitor_mode(ieee);
2676 #define DRV_NAME "Ieee80211"
2677 void ieee80211_softmac_init(struct ieee80211_device *ieee)
2679 int i;
2680 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2682 ieee->state = IEEE80211_NOLINK;
2683 ieee->sync_scan_hurryup = 0;
2684 for(i = 0; i < 5; i++) {
2685 ieee->seq_ctrl[i] = 0;
2687 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_KERNEL);
2688 if (!ieee->pDot11dInfo)
2689 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2690 //added for AP roaming
2691 ieee->LinkDetectInfo.SlotNum = 2;
2692 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
2693 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
2695 ieee->assoc_id = 0;
2696 ieee->queue_stop = 0;
2697 ieee->scanning = 0;
2698 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2699 ieee->wap_set = 0;
2700 ieee->ssid_set = 0;
2701 ieee->proto_started = 0;
2702 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2703 ieee->rate = 22;
2704 ieee->ps = IEEE80211_PS_DISABLED;
2705 ieee->sta_sleep = 0;
2706 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2707 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2708 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2709 //added by amy
2710 ieee->actscanning = false;
2711 ieee->beinretry = false;
2712 ieee->is_set_key = false;
2713 init_mgmt_queue(ieee);
2715 ieee->sta_edca_param[0] = 0x0000A403;
2716 ieee->sta_edca_param[1] = 0x0000A427;
2717 ieee->sta_edca_param[2] = 0x005E4342;
2718 ieee->sta_edca_param[3] = 0x002F3262;
2719 ieee->aggregation = true;
2720 ieee->enable_rx_imm_BA = true;
2721 ieee->tx_pending.txb = NULL;
2723 timer_setup(&ieee->associate_timer, ieee80211_associate_abort_cb, 0);
2725 timer_setup(&ieee->beacon_timer, ieee80211_send_beacon_cb, 0);
2728 INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2729 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2730 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2731 INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2732 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2733 INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2736 mutex_init(&ieee->wx_mutex);
2737 mutex_init(&ieee->scan_mutex);
2739 spin_lock_init(&ieee->mgmt_tx_lock);
2740 spin_lock_init(&ieee->beacon_lock);
2742 tasklet_init(&ieee->ps_task,
2743 (void(*)(unsigned long)) ieee80211_sta_ps,
2744 (unsigned long)ieee);
2748 void ieee80211_softmac_free(struct ieee80211_device *ieee)
2750 mutex_lock(&ieee->wx_mutex);
2751 kfree(ieee->pDot11dInfo);
2752 ieee->pDot11dInfo = NULL;
2753 del_timer_sync(&ieee->associate_timer);
2755 cancel_delayed_work(&ieee->associate_retry_wq);
2757 mutex_unlock(&ieee->wx_mutex);
2760 /********************************************************
2761 * Start of WPA code. *
2762 * this is stolen from the ipw2200 driver *
2763 ********************************************************/
2766 static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2768 /* This is called when wpa_supplicant loads and closes the driver
2769 * interface. */
2770 printk("%s WPA\n", value ? "enabling" : "disabling");
2771 ieee->wpa_enabled = value;
2772 return 0;
2776 static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2777 char *wpa_ie, int wpa_ie_len)
2779 /* make sure WPA is enabled */
2780 ieee80211_wpa_enable(ieee, 1);
2782 ieee80211_disassociate(ieee);
2786 static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2789 int ret = 0;
2791 switch (command) {
2792 case IEEE_MLME_STA_DEAUTH:
2793 // silently ignore
2794 break;
2796 case IEEE_MLME_STA_DISASSOC:
2797 ieee80211_disassociate(ieee);
2798 break;
2800 default:
2801 printk("Unknown MLME request: %d\n", command);
2802 ret = -EOPNOTSUPP;
2805 return ret;
2809 static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2810 struct ieee_param *param, int plen)
2812 u8 *buf;
2814 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2815 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2816 return -EINVAL;
2818 if (param->u.wpa_ie.len) {
2819 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2820 GFP_KERNEL);
2821 if (buf == NULL)
2822 return -ENOMEM;
2824 kfree(ieee->wpa_ie);
2825 ieee->wpa_ie = buf;
2826 ieee->wpa_ie_len = param->u.wpa_ie.len;
2827 } else {
2828 kfree(ieee->wpa_ie);
2829 ieee->wpa_ie = NULL;
2830 ieee->wpa_ie_len = 0;
2833 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2834 return 0;
2837 #define AUTH_ALG_OPEN_SYSTEM 0x1
2838 #define AUTH_ALG_SHARED_KEY 0x2
2840 static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2843 struct ieee80211_security sec = {
2844 .flags = SEC_AUTH_MODE,
2847 if (value & AUTH_ALG_SHARED_KEY) {
2848 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2849 ieee->open_wep = 0;
2850 ieee->auth_mode = 1;
2851 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2852 sec.auth_mode = WLAN_AUTH_OPEN;
2853 ieee->open_wep = 1;
2854 ieee->auth_mode = 0;
2856 else if (value & IW_AUTH_ALG_LEAP){
2857 sec.auth_mode = WLAN_AUTH_LEAP;
2858 ieee->open_wep = 1;
2859 ieee->auth_mode = 2;
2863 if (ieee->set_security)
2864 ieee->set_security(ieee->dev, &sec);
2865 //else
2866 // ret = -EOPNOTSUPP;
2868 return 0;
2871 static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2873 int ret = 0;
2874 unsigned long flags;
2876 switch (name) {
2877 case IEEE_PARAM_WPA_ENABLED:
2878 ret = ieee80211_wpa_enable(ieee, value);
2879 break;
2881 case IEEE_PARAM_TKIP_COUNTERMEASURES:
2882 ieee->tkip_countermeasures = value;
2883 break;
2885 case IEEE_PARAM_DROP_UNENCRYPTED: {
2886 /* HACK:
2888 * wpa_supplicant calls set_wpa_enabled when the driver
2889 * is loaded and unloaded, regardless of if WPA is being
2890 * used. No other calls are made which can be used to
2891 * determine if encryption will be used or not prior to
2892 * association being expected. If encryption is not being
2893 * used, drop_unencrypted is set to false, else true -- we
2894 * can use this to determine if the CAP_PRIVACY_ON bit should
2895 * be set.
2897 struct ieee80211_security sec = {
2898 .flags = SEC_ENABLED,
2899 .enabled = value,
2901 ieee->drop_unencrypted = value;
2902 /* We only change SEC_LEVEL for open mode. Others
2903 * are set by ipw_wpa_set_encryption.
2905 if (!value) {
2906 sec.flags |= SEC_LEVEL;
2907 sec.level = SEC_LEVEL_0;
2909 else {
2910 sec.flags |= SEC_LEVEL;
2911 sec.level = SEC_LEVEL_1;
2913 if (ieee->set_security)
2914 ieee->set_security(ieee->dev, &sec);
2915 break;
2918 case IEEE_PARAM_PRIVACY_INVOKED:
2919 ieee->privacy_invoked = value;
2920 break;
2922 case IEEE_PARAM_AUTH_ALGS:
2923 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2924 break;
2926 case IEEE_PARAM_IEEE_802_1X:
2927 ieee->ieee802_1x = value;
2928 break;
2929 case IEEE_PARAM_WPAX_SELECT:
2930 // added for WPA2 mixed mode
2931 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2932 ieee->wpax_type_set = 1;
2933 ieee->wpax_type_notify = value;
2934 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2935 break;
2937 default:
2938 printk("Unknown WPA param: %d\n", name);
2939 ret = -EOPNOTSUPP;
2942 return ret;
2945 /* implementation borrowed from hostap driver */
2947 static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2948 struct ieee_param *param, int param_len)
2950 int ret = 0;
2951 const char *module = NULL;
2953 struct ieee80211_crypto_ops *ops = NULL;
2954 struct ieee80211_crypt_data **crypt;
2956 struct ieee80211_security sec = {
2957 .flags = 0,
2960 param->u.crypt.err = 0;
2961 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2963 if (param_len !=
2964 (int) ((char *) param->u.crypt.key - (char *) param) +
2965 param->u.crypt.key_len) {
2966 printk("Len mismatch %d, %d\n", param_len,
2967 param->u.crypt.key_len);
2968 return -EINVAL;
2970 if (is_broadcast_ether_addr(param->sta_addr)) {
2971 if (param->u.crypt.idx >= WEP_KEYS)
2972 return -EINVAL;
2973 crypt = &ieee->crypt[param->u.crypt.idx];
2974 } else {
2975 return -EINVAL;
2978 if (strcmp(param->u.crypt.alg, "none") == 0) {
2979 if (crypt) {
2980 sec.enabled = 0;
2981 // FIXME FIXME
2982 //sec.encrypt = 0;
2983 sec.level = SEC_LEVEL_0;
2984 sec.flags |= SEC_ENABLED | SEC_LEVEL;
2985 ieee80211_crypt_delayed_deinit(ieee, crypt);
2987 goto done;
2989 sec.enabled = 1;
2990 // FIXME FIXME
2991 // sec.encrypt = 1;
2992 sec.flags |= SEC_ENABLED;
2994 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2995 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2996 strcmp(param->u.crypt.alg, "TKIP"))
2997 goto skip_host_crypt;
2999 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3000 if (!strcmp(param->u.crypt.alg, "WEP"))
3001 module = "ieee80211_crypt_wep";
3002 else if (!strcmp(param->u.crypt.alg, "TKIP"))
3003 module = "ieee80211_crypt_tkip";
3004 else if (!strcmp(param->u.crypt.alg, "CCMP"))
3005 module = "ieee80211_crypt_ccmp";
3006 if (module)
3007 ops = try_then_request_module(ieee80211_get_crypto_ops(param->u.crypt.alg),
3008 module);
3009 if (!ops) {
3010 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3011 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3012 ret = -EINVAL;
3013 goto done;
3016 if (*crypt == NULL || (*crypt)->ops != ops) {
3017 struct ieee80211_crypt_data *new_crypt;
3019 ieee80211_crypt_delayed_deinit(ieee, crypt);
3021 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
3022 if (!new_crypt) {
3023 ret = -ENOMEM;
3024 goto done;
3026 new_crypt->ops = ops;
3027 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
3028 new_crypt->priv =
3029 new_crypt->ops->init(param->u.crypt.idx);
3031 if (new_crypt->priv == NULL) {
3032 kfree(new_crypt);
3033 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3034 ret = -EINVAL;
3035 goto done;
3038 *crypt = new_crypt;
3041 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3042 (*crypt)->ops->set_key(param->u.crypt.key,
3043 param->u.crypt.key_len, param->u.crypt.seq,
3044 (*crypt)->priv) < 0) {
3045 printk("key setting failed\n");
3046 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3047 ret = -EINVAL;
3048 goto done;
3051 skip_host_crypt:
3052 if (param->u.crypt.set_tx) {
3053 ieee->tx_keyidx = param->u.crypt.idx;
3054 sec.active_key = param->u.crypt.idx;
3055 sec.flags |= SEC_ACTIVE_KEY;
3056 } else
3057 sec.flags &= ~SEC_ACTIVE_KEY;
3059 memcpy(sec.keys[param->u.crypt.idx],
3060 param->u.crypt.key,
3061 param->u.crypt.key_len);
3062 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3063 sec.flags |= (1 << param->u.crypt.idx);
3065 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3066 sec.flags |= SEC_LEVEL;
3067 sec.level = SEC_LEVEL_1;
3068 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3069 sec.flags |= SEC_LEVEL;
3070 sec.level = SEC_LEVEL_2;
3071 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3072 sec.flags |= SEC_LEVEL;
3073 sec.level = SEC_LEVEL_3;
3075 done:
3076 if (ieee->set_security)
3077 ieee->set_security(ieee->dev, &sec);
3079 /* Do not reset port if card is in Managed mode since resetting will
3080 * generate new IEEE 802.11 authentication which may end up in looping
3081 * with IEEE 802.1X. If your hardware requires a reset after WEP
3082 * configuration (for example... Prism2), implement the reset_port in
3083 * the callbacks structures used to initialize the 802.11 stack. */
3084 if (ieee->reset_on_keychange &&
3085 ieee->iw_mode != IW_MODE_INFRA &&
3086 ieee->reset_port &&
3087 ieee->reset_port(ieee->dev)) {
3088 printk("reset_port failed\n");
3089 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3090 return -EINVAL;
3093 return ret;
3096 static inline struct sk_buff *ieee80211_disassociate_skb(
3097 struct ieee80211_network *beacon,
3098 struct ieee80211_device *ieee,
3099 u8 asRsn)
3101 struct sk_buff *skb;
3102 struct ieee80211_disassoc *disass;
3104 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3105 if (!skb)
3106 return NULL;
3108 disass = skb_put(skb, sizeof(struct ieee80211_disassoc));
3109 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3110 disass->header.duration_id = 0;
3112 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3113 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3114 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3116 disass->reason = cpu_to_le16(asRsn);
3117 return skb;
3121 void
3122 SendDisassociation(
3123 struct ieee80211_device *ieee,
3124 u8 *asSta,
3125 u8 asRsn
3128 struct ieee80211_network *beacon = &ieee->current_network;
3129 struct sk_buff *skb;
3131 skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
3132 if (skb) {
3133 softmac_mgmt_xmit(skb, ieee);
3134 //dev_kfree_skb_any(skb);//edit by thomas
3137 EXPORT_SYMBOL(SendDisassociation);
3139 int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3141 struct ieee_param *param;
3142 int ret = 0;
3144 mutex_lock(&ieee->wx_mutex);
3145 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3147 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
3148 ret = -EINVAL;
3149 goto out;
3152 param = memdup_user(p->pointer, p->length);
3153 if (IS_ERR(param)) {
3154 ret = PTR_ERR(param);
3155 goto out;
3158 switch (param->cmd) {
3160 case IEEE_CMD_SET_WPA_PARAM:
3161 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3162 param->u.wpa_param.value);
3163 break;
3165 case IEEE_CMD_SET_WPA_IE:
3166 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3167 break;
3169 case IEEE_CMD_SET_ENCRYPTION:
3170 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3171 break;
3173 case IEEE_CMD_MLME:
3174 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3175 param->u.mlme.reason_code);
3176 break;
3178 default:
3179 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3180 ret = -EOPNOTSUPP;
3181 break;
3184 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3185 ret = -EFAULT;
3187 kfree(param);
3188 out:
3189 mutex_unlock(&ieee->wx_mutex);
3191 return ret;
3193 EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3195 void notify_wx_assoc_event(struct ieee80211_device *ieee)
3197 union iwreq_data wrqu;
3199 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3200 if (ieee->state == IEEE80211_LINKED)
3201 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3202 else
3203 eth_zero_addr(wrqu.ap_addr.sa_data);
3204 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3206 EXPORT_SYMBOL(notify_wx_assoc_event);