]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - drivers/staging/rtl8192u/ieee80211/ieee80211_softmac.c
networking: introduce and use skb_put_data()
[mirror_ubuntu-artful-kernel.git] / drivers / staging / rtl8192u / ieee80211 / ieee80211_softmac.c
CommitLineData
8fc8598e 1/* IEEE 802.11 SoftMAC layer
559a4c31 2 * Copyright (c) 2005 Andrea Merello <andrea.merello@gmail.com>
8fc8598e
JC
3 *
4 * Mostly extracted from the rtl8180-sa2400 driver for the
5 * in-kernel generic ieee802.11 stack.
6 *
7 * Few lines might be stolen from other part of the ieee80211
8 * stack. Copyright who own it's copyright
9 *
10 * WPA code stolen from the ipw2200 driver.
11 * Copyright who own it's copyright.
12 *
13 * released under the GPL
14 */
15
16
17#include "ieee80211.h"
18
19#include <linux/random.h>
20#include <linux/delay.h>
5a0e3ad6 21#include <linux/slab.h>
03c7da4f 22#include <linux/uaccess.h>
8cfbc9dc
WY
23#include <linux/etherdevice.h>
24
8fc8598e 25#include "dot11d.h"
8fc8598e 26
58af5800 27short ieee80211_is_54g(const struct ieee80211_network *net)
8fc8598e 28{
58af5800 29 return (net->rates_ex_len > 0) || (net->rates_len > 4);
8fc8598e 30}
539b4f72 31EXPORT_SYMBOL(ieee80211_is_54g);
8fc8598e 32
58af5800 33short ieee80211_is_shortslot(const struct ieee80211_network *net)
8fc8598e 34{
58af5800 35 return net->capability & WLAN_CAPABILITY_SHORT_SLOT;
8fc8598e 36}
539b4f72 37EXPORT_SYMBOL(ieee80211_is_shortslot);
8fc8598e
JC
38
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
42 */
fabdbdb2 43static unsigned int ieee80211_MFIE_rate_len(struct ieee80211_device *ieee)
8fc8598e
JC
44{
45 unsigned int rate_len = 0;
46
47 if (ieee->modulation & IEEE80211_CCK_MODULATION)
48 rate_len = IEEE80211_CCK_RATE_LEN + 2;
49
50 if (ieee->modulation & IEEE80211_OFDM_MODULATION)
51
52 rate_len += IEEE80211_OFDM_RATE_LEN + 2;
53
54 return rate_len;
55}
56
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.
60 */
fabdbdb2 61static void ieee80211_MFIE_Brate(struct ieee80211_device *ieee, u8 **tag_p)
8fc8598e
JC
62{
63 u8 *tag = *tag_p;
64
f53cb7b1 65 if (ieee->modulation & IEEE80211_CCK_MODULATION) {
8fc8598e
JC
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;
72 }
73
74 /* We may add an option for custom rates that specific HW might support */
75 *tag_p = tag;
76}
77
fabdbdb2 78static void ieee80211_MFIE_Grate(struct ieee80211_device *ieee, u8 **tag_p)
8fc8598e
JC
79{
80 u8 *tag = *tag_p;
81
f53cb7b1 82 if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
8fc8598e
JC
83
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;
94
95 }
96
97 /* We may add an option for custom rates that specific HW might support */
98 *tag_p = tag;
99}
100
101
fabdbdb2
AR
102static void ieee80211_WMM_Info(struct ieee80211_device *ieee, u8 **tag_p)
103{
8fc8598e
JC
104 u8 *tag = *tag_p;
105
04bdfd20 106 *tag++ = MFIE_TYPE_GENERIC; /* 0 */
8fc8598e
JC
107 *tag++ = 7;
108 *tag++ = 0x00;
109 *tag++ = 0x50;
110 *tag++ = 0xf2;
04bdfd20 111 *tag++ = 0x02; /* 5 */
8fc8598e
JC
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;
119 }
120#else
121 *tag++ = MAX_SP_Len;
122#endif
123 *tag_p = tag;
124}
125
126#ifdef THOMAS_TURBO
c24cdca0
MC
127static void ieee80211_TURBO_Info(struct ieee80211_device *ieee, u8 **tag_p)
128{
8fc8598e
JC
129 u8 *tag = *tag_p;
130
04bdfd20 131 *tag++ = MFIE_TYPE_GENERIC; /* 0 */
e406322b
MCC
132 *tag++ = 7;
133 *tag++ = 0x00;
134 *tag++ = 0xe0;
135 *tag++ = 0x4c;
04bdfd20 136 *tag++ = 0x01; /* 5 */
e406322b
MCC
137 *tag++ = 0x02;
138 *tag++ = 0x11;
8fc8598e
JC
139 *tag++ = 0x00;
140
141 *tag_p = tag;
142 printk(KERN_ALERT "This is enable turbo mode IE process\n");
143}
144#endif
145
fabdbdb2 146static void enqueue_mgmt(struct ieee80211_device *ieee, struct sk_buff *skb)
8fc8598e
JC
147{
148 int nh;
360daa82 149
8fc8598e
JC
150 nh = (ieee->mgmt_queue_head +1) % MGMT_QUEUE_NUM;
151
152/*
153 * if the queue is full but we have newer frames then
154 * just overwrites the oldest.
155 *
156 * if (nh == ieee->mgmt_queue_tail)
157 * return -1;
158 */
159 ieee->mgmt_queue_head = nh;
160 ieee->mgmt_queue_ring[nh] = skb;
161
162 //return 0;
163}
164
fabdbdb2 165static struct sk_buff *dequeue_mgmt(struct ieee80211_device *ieee)
8fc8598e
JC
166{
167 struct sk_buff *ret;
168
169 if(ieee->mgmt_queue_tail == ieee->mgmt_queue_head)
170 return NULL;
171
172 ret = ieee->mgmt_queue_ring[ieee->mgmt_queue_tail];
173
174 ieee->mgmt_queue_tail =
175 (ieee->mgmt_queue_tail+1) % MGMT_QUEUE_NUM;
176
177 return ret;
178}
179
fabdbdb2 180static void init_mgmt_queue(struct ieee80211_device *ieee)
8fc8598e
JC
181{
182 ieee->mgmt_queue_tail = ieee->mgmt_queue_head = 0;
183}
184
fabdbdb2 185static u8 MgntQuery_MgntFrameTxRate(struct ieee80211_device *ieee)
8fc8598e
JC
186{
187 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
188 u8 rate;
189
04bdfd20 190 /* 2008/01/25 MH For broadcom, MGNT frame set as OFDM 6M. */
8fc8598e
JC
191 if(pHTInfo->IOTAction & HT_IOT_ACT_MGNT_USE_CCK_6M)
192 rate = 0x0c;
193 else
194 rate = ieee->basic_rate & 0x7f;
195
f53cb7b1 196 if (rate == 0) {
04bdfd20 197 /* 2005.01.26, by rcnjko. */
8fc8598e
JC
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;
204 }
205
206 /*
207 // Data rate of ProbeReq is already decided. Annie, 2005-03-31
208 if( pMgntInfo->bScanInProgress || (pMgntInfo->bDualModeScanStep!=0) )
209 {
210 if(pMgntInfo->dot11CurrentWirelessMode==WIRELESS_MODE_A)
211 rate = 0x0c;
212 else
213 rate = 0x02;
214 }
215 */
216 return rate;
217}
218
219
220void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl);
221
222inline void softmac_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
223{
224 unsigned long flags;
225 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
5c2918a5
PG
226 struct rtl_80211_hdr_3addr *header=
227 (struct rtl_80211_hdr_3addr *) skb->data;
8fc8598e 228
20f896c4 229 struct cb_desc *tcb_desc = (struct cb_desc *)(skb->cb + 8);
360daa82 230
8fc8598e
JC
231 spin_lock_irqsave(&ieee->lock, flags);
232
233 /* called with 2nd param 0, no mgmt lock required */
0b4ef0a6 234 ieee80211_sta_wakeup(ieee, 0);
8fc8598e
JC
235
236 tcb_desc->queue_index = MGNT_QUEUE;
237 tcb_desc->data_rate = MgntQuery_MgntFrameTxRate(ieee);
e406322b
MCC
238 tcb_desc->RATRIndex = 7;
239 tcb_desc->bTxDisableRateFallBack = 1;
240 tcb_desc->bTxUseDriverAssingedRate = 1;
8fc8598e
JC
241
242 if(single){
243 if(ieee->queue_stop){
0b4ef0a6 244 enqueue_mgmt(ieee, skb);
8fc8598e
JC
245 }else{
246 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0]<<4);
247
248 if (ieee->seq_ctrl[0] == 0xFFF)
249 ieee->seq_ctrl[0] = 0;
250 else
251 ieee->seq_ctrl[0]++;
252
253 /* avoid watchdog triggers */
860e9538 254 netif_trans_update(ieee->dev);
8fc8598e
JC
255 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
256 //dev_kfree_skb_any(skb);//edit by thomas
257 }
258
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);
263
264 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
265
266 if (ieee->seq_ctrl[0] == 0xFFF)
267 ieee->seq_ctrl[0] = 0;
268 else
269 ieee->seq_ctrl[0]++;
270
f2635894 271 /* check whether the managed packet queued greater than 5 */
8fc8598e
JC
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 * */
f8628a47 279 printk("%s():insert to waitqueue!\n",__func__);
8fc8598e
JC
280 skb_queue_tail(&ieee->skb_waitQ[tcb_desc->queue_index], skb);
281 } else {
0b4ef0a6 282 ieee->softmac_hard_start_xmit(skb, ieee->dev);
8fc8598e
JC
283 //dev_kfree_skb_any(skb);//edit by thomas
284 }
285 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags);
286 }
287}
288
3590e78a
BX
289static inline void
290softmac_ps_mgmt_xmit(struct sk_buff *skb, struct ieee80211_device *ieee)
8fc8598e
JC
291{
292
293 short single = ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE;
5c2918a5
PG
294 struct rtl_80211_hdr_3addr *header =
295 (struct rtl_80211_hdr_3addr *) skb->data;
8fc8598e
JC
296
297
298 if(single){
299
300 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
301
302 if (ieee->seq_ctrl[0] == 0xFFF)
303 ieee->seq_ctrl[0] = 0;
304 else
305 ieee->seq_ctrl[0]++;
306
307 /* avoid watchdog triggers */
860e9538 308 netif_trans_update(ieee->dev);
8fc8598e
JC
309 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
310
311 }else{
312
313 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
314
315 if (ieee->seq_ctrl[0] == 0xFFF)
316 ieee->seq_ctrl[0] = 0;
317 else
318 ieee->seq_ctrl[0]++;
319
0b4ef0a6 320 ieee->softmac_hard_start_xmit(skb, ieee->dev);
8fc8598e
JC
321
322 }
323 //dev_kfree_skb_any(skb);//edit by thomas
324}
325
3590e78a 326static inline struct sk_buff *ieee80211_probe_req(struct ieee80211_device *ieee)
8fc8598e 327{
0b4ef0a6 328 unsigned int len, rate_len;
8fc8598e
JC
329 u8 *tag;
330 struct sk_buff *skb;
331 struct ieee80211_probe_request *req;
332
333 len = ieee->current_network.ssid_len;
334
335 rate_len = ieee80211_MFIE_rate_len(ieee);
336
337 skb = dev_alloc_skb(sizeof(struct ieee80211_probe_request) +
338 2 + len + rate_len + ieee->tx_headroom);
339 if (!skb)
340 return NULL;
341
342 skb_reserve(skb, ieee->tx_headroom);
343
344 req = (struct ieee80211_probe_request *) skb_put(skb,sizeof(struct ieee80211_probe_request));
345 req->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
04bdfd20 346 req->header.duration_id = 0; /* FIXME: is this OK? */
8fc8598e 347
f80c1d57 348 eth_broadcast_addr(req->header.addr1);
8fc8598e 349 memcpy(req->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
f80c1d57 350 eth_broadcast_addr(req->header.addr3);
8fc8598e
JC
351
352 tag = (u8 *) skb_put(skb,len+2+rate_len);
353
354 *tag++ = MFIE_TYPE_SSID;
355 *tag++ = len;
356 memcpy(tag, ieee->current_network.ssid, len);
357 tag += len;
358
359 ieee80211_MFIE_Brate(ieee,&tag);
360 ieee80211_MFIE_Grate(ieee,&tag);
361 return skb;
362}
363
364struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee);
fabdbdb2
AR
365
366static void ieee80211_send_beacon(struct ieee80211_device *ieee)
8fc8598e
JC
367{
368 struct sk_buff *skb;
360daa82 369
8fc8598e
JC
370 if(!ieee->ieee_up)
371 return;
372 //unsigned long flags;
373 skb = ieee80211_get_beacon_(ieee);
374
f53cb7b1 375 if (skb) {
8fc8598e
JC
376 softmac_mgmt_xmit(skb, ieee);
377 ieee->softmac_stats.tx_beacons++;
378 //dev_kfree_skb_any(skb);//edit by thomas
379 }
380// ieee->beacon_timer.expires = jiffies +
381// (MSECS( ieee->current_network.beacon_interval -5));
382
383 //spin_lock_irqsave(&ieee->beacon_lock,flags);
f53cb7b1 384 if (ieee->beacon_txing && ieee->ieee_up) {
8fc8598e
JC
385// if(!timer_pending(&ieee->beacon_timer))
386// add_timer(&ieee->beacon_timer);
4763a752
AKC
387 mod_timer(&ieee->beacon_timer,
388 jiffies + msecs_to_jiffies(ieee->current_network.beacon_interval-5));
8fc8598e
JC
389 }
390 //spin_unlock_irqrestore(&ieee->beacon_lock,flags);
391}
392
393
fabdbdb2 394static void ieee80211_send_beacon_cb(unsigned long _ieee)
8fc8598e
JC
395{
396 struct ieee80211_device *ieee =
397 (struct ieee80211_device *) _ieee;
398 unsigned long flags;
399
400 spin_lock_irqsave(&ieee->beacon_lock, flags);
401 ieee80211_send_beacon(ieee);
402 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
403}
404
405
fabdbdb2 406static void ieee80211_send_probe(struct ieee80211_device *ieee)
8fc8598e
JC
407{
408 struct sk_buff *skb;
409
410 skb = ieee80211_probe_req(ieee);
f53cb7b1 411 if (skb) {
8fc8598e
JC
412 softmac_mgmt_xmit(skb, ieee);
413 ieee->softmac_stats.tx_probe_rq++;
414 //dev_kfree_skb_any(skb);//edit by thomas
415 }
416}
417
c7a348cf 418static void ieee80211_send_probe_requests(struct ieee80211_device *ieee)
8fc8598e 419{
f53cb7b1 420 if (ieee->active_scan && (ieee->softmac_features & IEEE_SOFTMAC_PROBERQ)) {
8fc8598e
JC
421 ieee80211_send_probe(ieee);
422 ieee80211_send_probe(ieee);
423 }
424}
425
426/* this performs syncro scan blocking the caller until all channels
427 * in the allowed channel map has been checked.
428 */
429void ieee80211_softmac_scan_syncro(struct ieee80211_device *ieee)
430{
431 short ch = 0;
8fc8598e 432 u8 channel_map[MAX_CHANNEL_NUMBER+1];
360daa82 433
8fc8598e 434 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
87d63bcc 435 mutex_lock(&ieee->scan_mutex);
8fc8598e
JC
436
437 while(1)
438 {
439
440 do{
441 ch++;
442 if (ch > MAX_CHANNEL_NUMBER)
443 goto out; /* scan completed */
8fc8598e 444 }while(!channel_map[ch]);
8fc8598e 445
39831861 446 /* this function can be called in two situations
8fc8598e
JC
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
463 */
464
465 if (ieee->state == IEEE80211_LINKED)
466 goto out;
467 ieee->set_chan(ieee->dev, ch);
8fc8598e 468 if(channel_map[ch] == 1)
8ad835b9 469 ieee80211_send_probe_requests(ieee);
8fc8598e
JC
470
471 /* this prevent excessive time wait when we
472 * need to wait for a syncro scan to end..
473 */
4b6a8799 474 if (ieee->state >= IEEE80211_LINKED && ieee->sync_scan_hurryup)
8fc8598e
JC
475 goto out;
476
3a341db3 477 msleep_interruptible(IEEE80211_SOFTMAC_SCAN_TIME);
8fc8598e
JC
478
479 }
480out:
481 if(ieee->state < IEEE80211_LINKED){
482 ieee->actscanning = false;
87d63bcc 483 mutex_unlock(&ieee->scan_mutex);
8fc8598e
JC
484 }
485 else{
486 ieee->sync_scan_hurryup = 0;
8fc8598e
JC
487 if(IS_DOT11D_ENABLE(ieee))
488 DOT11D_ScanComplete(ieee);
87d63bcc 489 mutex_unlock(&ieee->scan_mutex);
8fc8598e
JC
490}
491}
539b4f72 492EXPORT_SYMBOL(ieee80211_softmac_scan_syncro);
8fc8598e 493
fabdbdb2 494static void ieee80211_softmac_scan_wq(struct work_struct *work)
8fc8598e 495{
a5959f3f 496 struct delayed_work *dwork = to_delayed_work(work);
e406322b 497 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, softmac_scan_wq);
de13a3da 498 static short watchdog;
8fc8598e 499 u8 channel_map[MAX_CHANNEL_NUMBER+1];
360daa82 500
8fc8598e 501 memcpy(channel_map, GET_DOT11D_INFO(ieee)->channel_map, MAX_CHANNEL_NUMBER+1);
8fc8598e
JC
502 if(!ieee->ieee_up)
503 return;
87d63bcc 504 mutex_lock(&ieee->scan_mutex);
8fc8598e
JC
505 do{
506 ieee->current_network.channel =
507 (ieee->current_network.channel + 1) % MAX_CHANNEL_NUMBER;
508 if (watchdog++ > MAX_CHANNEL_NUMBER)
509 {
510 //if current channel is not in channel map, set to default channel.
e91eb2ff 511 if (!channel_map[ieee->current_network.channel]) {
8fc8598e
JC
512 ieee->current_network.channel = 6;
513 goto out; /* no good chans */
e91eb2ff 514 }
8fc8598e 515 }
e406322b 516 }while(!channel_map[ieee->current_network.channel]);
8fc8598e
JC
517 if (ieee->scanning == 0 )
518 goto out;
519 ieee->set_chan(ieee->dev, ieee->current_network.channel);
8fc8598e 520 if(channel_map[ieee->current_network.channel] == 1)
f9eb26cf 521 ieee80211_send_probe_requests(ieee);
8fc8598e
JC
522
523
1761a85c 524 schedule_delayed_work(&ieee->softmac_scan_wq, IEEE80211_SOFTMAC_SCAN_TIME);
8fc8598e 525
87d63bcc 526 mutex_unlock(&ieee->scan_mutex);
8fc8598e
JC
527 return;
528out:
8fc8598e
JC
529 if(IS_DOT11D_ENABLE(ieee))
530 DOT11D_ScanComplete(ieee);
e406322b 531 ieee->actscanning = false;
8fc8598e
JC
532 watchdog = 0;
533 ieee->scanning = 0;
87d63bcc 534 mutex_unlock(&ieee->scan_mutex);
8fc8598e
JC
535}
536
8fc8598e
JC
537
538
fabdbdb2 539static void ieee80211_beacons_start(struct ieee80211_device *ieee)
8fc8598e
JC
540{
541 unsigned long flags;
542 spin_lock_irqsave(&ieee->beacon_lock,flags);
543
544 ieee->beacon_txing = 1;
545 ieee80211_send_beacon(ieee);
546
0b4ef0a6 547 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
8fc8598e
JC
548}
549
fabdbdb2 550static void ieee80211_beacons_stop(struct ieee80211_device *ieee)
8fc8598e
JC
551{
552 unsigned long flags;
553
0b4ef0a6 554 spin_lock_irqsave(&ieee->beacon_lock, flags);
8fc8598e
JC
555
556 ieee->beacon_txing = 0;
e406322b 557 del_timer_sync(&ieee->beacon_timer);
8fc8598e 558
0b4ef0a6 559 spin_unlock_irqrestore(&ieee->beacon_lock, flags);
8fc8598e
JC
560
561}
562
563
564void ieee80211_stop_send_beacons(struct ieee80211_device *ieee)
565{
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);
570}
539b4f72 571EXPORT_SYMBOL(ieee80211_stop_send_beacons);
8fc8598e
JC
572
573void ieee80211_start_send_beacons(struct ieee80211_device *ieee)
574{
575 if(ieee->start_send_beacons)
0b4ef0a6 576 ieee->start_send_beacons(ieee->dev, ieee->basic_rate);
8fc8598e
JC
577 if(ieee->softmac_features & IEEE_SOFTMAC_BEACONS)
578 ieee80211_beacons_start(ieee);
579}
539b4f72 580EXPORT_SYMBOL(ieee80211_start_send_beacons);
8fc8598e 581
fabdbdb2 582static void ieee80211_softmac_stop_scan(struct ieee80211_device *ieee)
8fc8598e
JC
583{
584// unsigned long flags;
585
586 //ieee->sync_scan_hurryup = 1;
587
87d63bcc 588 mutex_lock(&ieee->scan_mutex);
8fc8598e
JC
589// spin_lock_irqsave(&ieee->lock, flags);
590
f53cb7b1 591 if (ieee->scanning == 1) {
8fc8598e
JC
592 ieee->scanning = 0;
593
8fc8598e 594 cancel_delayed_work(&ieee->softmac_scan_wq);
8fc8598e
JC
595 }
596
597// spin_unlock_irqrestore(&ieee->lock, flags);
87d63bcc 598 mutex_unlock(&ieee->scan_mutex);
8fc8598e
JC
599}
600
601void ieee80211_stop_scan(struct ieee80211_device *ieee)
602{
603 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN)
604 ieee80211_softmac_stop_scan(ieee);
605 else
606 ieee->stop_scan(ieee->dev);
607}
539b4f72 608EXPORT_SYMBOL(ieee80211_stop_scan);
8fc8598e
JC
609
610/* called with ieee->lock held */
fabdbdb2 611static void ieee80211_start_scan(struct ieee80211_device *ieee)
8fc8598e 612{
dde48b99 613 if (IS_DOT11D_ENABLE(ieee) )
8fc8598e 614 {
dde48b99 615 if (IS_COUNTRY_IE_VALID(ieee))
8fc8598e
JC
616 {
617 RESET_CIE_WATCHDOG(ieee);
618 }
619 }
8fc8598e 620 if (ieee->softmac_features & IEEE_SOFTMAC_SCAN){
f53cb7b1 621 if (ieee->scanning == 0) {
8fc8598e 622 ieee->scanning = 1;
1761a85c 623 schedule_delayed_work(&ieee->softmac_scan_wq, 0);
8fc8598e
JC
624 }
625 }else
626 ieee->start_scan(ieee->dev);
627
628}
629
e379a9a8 630/* called with wx_mutex held */
8fc8598e
JC
631void ieee80211_start_scan_syncro(struct ieee80211_device *ieee)
632{
dde48b99 633 if (IS_DOT11D_ENABLE(ieee) )
8fc8598e 634 {
dde48b99 635 if (IS_COUNTRY_IE_VALID(ieee))
8fc8598e
JC
636 {
637 RESET_CIE_WATCHDOG(ieee);
638 }
639 }
8fc8598e
JC
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);
645
646}
539b4f72 647EXPORT_SYMBOL(ieee80211_start_scan_syncro);
8fc8598e 648
3590e78a
BX
649static inline struct sk_buff *
650ieee80211_authentication_req(struct ieee80211_network *beacon,
651 struct ieee80211_device *ieee, int challengelen)
8fc8598e
JC
652{
653 struct sk_buff *skb;
654 struct ieee80211_authentication *auth;
655 int len = sizeof(struct ieee80211_authentication) + challengelen + ieee->tx_headroom;
656
657
658 skb = dev_alloc_skb(len);
659 if (!skb) return NULL;
660
661 skb_reserve(skb, ieee->tx_headroom);
662 auth = (struct ieee80211_authentication *)
663 skb_put(skb, sizeof(struct ieee80211_authentication));
664
bf95628e
GG
665 if (challengelen)
666 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH
667 | IEEE80211_FCTL_WEP);
668 else
669 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
8fc8598e 670
25e2704c 671 auth->header.duration_id = cpu_to_le16(0x013a);
8fc8598e
JC
672
673 memcpy(auth->header.addr1, beacon->bssid, ETH_ALEN);
674 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
675 memcpy(auth->header.addr3, beacon->bssid, ETH_ALEN);
676
677 //auth->algorithm = ieee->open_wep ? WLAN_AUTH_OPEN : WLAN_AUTH_SHARED_KEY;
678 if(ieee->auth_mode == 0)
679 auth->algorithm = WLAN_AUTH_OPEN;
680 else if(ieee->auth_mode == 1)
25e2704c 681 auth->algorithm = cpu_to_le16(WLAN_AUTH_SHARED_KEY);
8fc8598e 682 else if(ieee->auth_mode == 2)
04bdfd20 683 auth->algorithm = WLAN_AUTH_OPEN; /* 0x80; */
f8628a47 684 printk("=================>%s():auth->algorithm is %d\n",__func__,auth->algorithm);
8fc8598e
JC
685 auth->transaction = cpu_to_le16(ieee->associate_seq);
686 ieee->associate_seq++;
687
688 auth->status = cpu_to_le16(WLAN_STATUS_SUCCESS);
689
690 return skb;
691
692}
693
694
2639ae97 695static struct sk_buff *ieee80211_probe_resp(struct ieee80211_device *ieee, u8 *dest)
8fc8598e
JC
696{
697 u8 *tag;
698 int beacon_size;
699 struct ieee80211_probe_response *beacon_buf;
700 struct sk_buff *skb = NULL;
701 int encrypt;
0b4ef0a6 702 int atim_len, erp_len;
2639ae97 703 struct ieee80211_crypt_data *crypt;
8fc8598e
JC
704
705 char *ssid = ieee->current_network.ssid;
706 int ssid_len = ieee->current_network.ssid_len;
707 int rate_len = ieee->current_network.rates_len+2;
708 int rate_ex_len = ieee->current_network.rates_ex_len;
709 int wpa_ie_len = ieee->wpa_ie_len;
710 u8 erpinfo_content = 0;
711
2639ae97 712 u8 *tmp_ht_cap_buf;
8fc8598e 713 u8 tmp_ht_cap_len=0;
2639ae97 714 u8 *tmp_ht_info_buf;
8fc8598e
JC
715 u8 tmp_ht_info_len=0;
716 PRT_HIGH_THROUGHPUT pHTInfo = ieee->pHTInfo;
2639ae97 717 u8 *tmp_generic_ie_buf=NULL;
8fc8598e
JC
718 u8 tmp_generic_ie_len=0;
719
720 if(rate_ex_len > 0) rate_ex_len+=2;
721
722 if(ieee->current_network.capability & WLAN_CAPABILITY_IBSS)
723 atim_len = 4;
724 else
725 atim_len = 0;
726
58af5800 727 if(ieee80211_is_54g(&ieee->current_network))
8fc8598e
JC
728 erp_len = 3;
729 else
730 erp_len = 0;
8fc8598e
JC
731
732
733 crypt = ieee->crypt[ieee->tx_keyidx];
734
735
736 encrypt = ieee->host_encrypt && crypt && crypt->ops &&
737 ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
04bdfd20 738 /* HT ralated element */
2639ae97 739 tmp_ht_cap_buf =(u8 *) &(ieee->pHTInfo->SelfHTCap);
8fc8598e 740 tmp_ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
2639ae97 741 tmp_ht_info_buf =(u8 *) &(ieee->pHTInfo->SelfHTInfo);
8fc8598e
JC
742 tmp_ht_info_len = sizeof(ieee->pHTInfo->SelfHTInfo);
743 HTConstructCapabilityElement(ieee, tmp_ht_cap_buf, &tmp_ht_cap_len,encrypt);
744 HTConstructInfoElement(ieee,tmp_ht_info_buf,&tmp_ht_info_len, encrypt);
745
746
dde48b99 747 if (pHTInfo->bRegRT2RTAggregation)
e406322b
MCC
748 {
749 tmp_generic_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
8fc8598e
JC
750 tmp_generic_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
751 HTConstructRT2RTAggElement(ieee, tmp_generic_ie_buf, &tmp_generic_ie_len);
e406322b 752 }
8fc8598e 753// 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);
8fc8598e
JC
754 beacon_size = sizeof(struct ieee80211_probe_response)+2+
755 ssid_len
756 +3 //channel
757 +rate_len
758 +rate_ex_len
759 +atim_len
760 +erp_len
e406322b 761 +wpa_ie_len
8fc8598e
JC
762 // +tmp_ht_cap_len
763 // +tmp_ht_info_len
764 // +tmp_generic_ie_len
765// +wmm_len+2
766 +ieee->tx_headroom;
767 skb = dev_alloc_skb(beacon_size);
768 if (!skb)
769 return NULL;
770 skb_reserve(skb, ieee->tx_headroom);
2639ae97 771 beacon_buf = (struct ieee80211_probe_response *) skb_put(skb, (beacon_size - ieee->tx_headroom));
8fc8598e
JC
772 memcpy (beacon_buf->header.addr1, dest,ETH_ALEN);
773 memcpy (beacon_buf->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
774 memcpy (beacon_buf->header.addr3, ieee->current_network.bssid, ETH_ALEN);
775
04bdfd20 776 beacon_buf->header.duration_id = 0; /* FIXME */
8fc8598e
JC
777 beacon_buf->beacon_interval =
778 cpu_to_le16(ieee->current_network.beacon_interval);
779 beacon_buf->capability =
780 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_IBSS);
781 beacon_buf->capability |=
04bdfd20 782 cpu_to_le16(ieee->current_network.capability & WLAN_CAPABILITY_SHORT_PREAMBLE); /* add short preamble here */
8fc8598e
JC
783
784 if(ieee->short_slot && (ieee->current_network.capability & WLAN_CAPABILITY_SHORT_SLOT))
20a45d66 785 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
8fc8598e
JC
786
787 crypt = ieee->crypt[ieee->tx_keyidx];
8fc8598e
JC
788 if (encrypt)
789 beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
790
791
792 beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
793 beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
794 beacon_buf->info_element[0].len = ssid_len;
795
2639ae97 796 tag = (u8 *) beacon_buf->info_element[0].data;
8fc8598e
JC
797
798 memcpy(tag, ssid, ssid_len);
799
800 tag += ssid_len;
801
802 *(tag++) = MFIE_TYPE_RATES;
803 *(tag++) = rate_len-2;
0b4ef0a6 804 memcpy(tag, ieee->current_network.rates, rate_len-2);
8fc8598e
JC
805 tag+=rate_len-2;
806
807 *(tag++) = MFIE_TYPE_DS_SET;
808 *(tag++) = 1;
809 *(tag++) = ieee->current_network.channel;
810
f53cb7b1 811 if (atim_len) {
8fc8598e
JC
812 *(tag++) = MFIE_TYPE_IBSS_SET;
813 *(tag++) = 2;
19e016c3
VT
814
815 put_unaligned_le16(ieee->current_network.atim_window,
efdcb35a 816 tag);
8fc8598e
JC
817 tag+=2;
818 }
819
f53cb7b1 820 if (erp_len) {
8fc8598e
JC
821 *(tag++) = MFIE_TYPE_ERP;
822 *(tag++) = 1;
823 *(tag++) = erpinfo_content;
824 }
f53cb7b1 825 if (rate_ex_len) {
8fc8598e
JC
826 *(tag++) = MFIE_TYPE_RATES_EX;
827 *(tag++) = rate_ex_len-2;
0b4ef0a6 828 memcpy(tag, ieee->current_network.rates_ex, rate_ex_len-2);
8fc8598e
JC
829 tag+=rate_ex_len-2;
830 }
831
8fc8598e
JC
832 if (wpa_ie_len)
833 {
834 if (ieee->iw_mode == IW_MODE_ADHOC)
835 {//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
836 memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
837 }
838 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
839 tag += wpa_ie_len;
840 }
841
8fc8598e
JC
842 //skb->dev = ieee->dev;
843 return skb;
844}
845
846
fabdbdb2
AR
847static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
848 u8 *dest)
8fc8598e
JC
849{
850 struct sk_buff *skb;
2639ae97 851 u8 *tag;
8fc8598e 852
2639ae97 853 struct ieee80211_crypt_data *crypt;
8fc8598e
JC
854 struct ieee80211_assoc_response_frame *assoc;
855 short encrypt;
856
857 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
858 int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
859
860 skb = dev_alloc_skb(len);
861
862 if (!skb)
863 return NULL;
864
865 skb_reserve(skb, ieee->tx_headroom);
866
867 assoc = (struct ieee80211_assoc_response_frame *)
0b4ef0a6 868 skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
8fc8598e
JC
869
870 assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
871 memcpy(assoc->header.addr1, dest,ETH_ALEN);
872 memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
873 memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
874 assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
875 WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
876
877
878 if(ieee->short_slot)
879 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
880
881 if (ieee->host_encrypt)
882 crypt = ieee->crypt[ieee->tx_keyidx];
883 else crypt = NULL;
884
2060f31a 885 encrypt = crypt && crypt->ops;
8fc8598e
JC
886
887 if (encrypt)
888 assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
889
890 assoc->status = 0;
891 assoc->aid = cpu_to_le16(ieee->assoc_id);
892 if (ieee->assoc_id == 0x2007) ieee->assoc_id=0;
893 else ieee->assoc_id++;
894
2639ae97 895 tag = (u8 *) skb_put(skb, rate_len);
8fc8598e
JC
896
897 ieee80211_MFIE_Brate(ieee, &tag);
898 ieee80211_MFIE_Grate(ieee, &tag);
899
900 return skb;
901}
902
fabdbdb2
AR
903static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
904 int status, u8 *dest)
8fc8598e
JC
905{
906 struct sk_buff *skb;
907 struct ieee80211_authentication *auth;
908 int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication)+1;
909
910 skb = dev_alloc_skb(len);
911
912 if (!skb)
913 return NULL;
914
915 skb->len = sizeof(struct ieee80211_authentication);
916
917 auth = (struct ieee80211_authentication *)skb->data;
918
919 auth->status = cpu_to_le16(status);
920 auth->transaction = cpu_to_le16(2);
921 auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
922
923 memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
924 memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
925 memcpy(auth->header.addr1, dest, ETH_ALEN);
926 auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
927 return skb;
928
929
930}
931
fabdbdb2
AR
932static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
933 short pwr)
8fc8598e
JC
934{
935 struct sk_buff *skb;
5c2918a5 936 struct rtl_80211_hdr_3addr *hdr;
8fc8598e 937
5c2918a5 938 skb = dev_alloc_skb(sizeof(struct rtl_80211_hdr_3addr));
8fc8598e
JC
939
940 if (!skb)
941 return NULL;
942
5c2918a5 943 hdr = (struct rtl_80211_hdr_3addr *)skb_put(skb,sizeof(struct rtl_80211_hdr_3addr));
8fc8598e
JC
944
945 memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
946 memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
947 memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
948
949 hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
950 IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
951 (pwr ? IEEE80211_FCTL_PM:0));
952
953 return skb;
954
955
956}
957
958
fabdbdb2 959static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
8fc8598e
JC
960{
961 struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
962
963 if (buf)
964 softmac_mgmt_xmit(buf, ieee);
965}
966
967
fabdbdb2
AR
968static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
969 u8 *dest)
8fc8598e
JC
970{
971 struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
972
973 if (buf)
974 softmac_mgmt_xmit(buf, ieee);
975}
976
977
fabdbdb2 978static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
8fc8598e
JC
979{
980
981
982 struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
983 if (buf)
984 softmac_mgmt_xmit(buf, ieee);
985}
986
987
3590e78a
BX
988static inline struct sk_buff *
989ieee80211_association_req(struct ieee80211_network *beacon,
990 struct ieee80211_device *ieee)
8fc8598e
JC
991{
992 struct sk_buff *skb;
993 //unsigned long flags;
994
995 struct ieee80211_assoc_request_frame *hdr;
996 u8 *tag;//,*rsn_ie;
997 //short info_addr = 0;
998 //int i;
999 //u16 suite_count = 0;
1000 //u8 suit_select = 0;
1001 //unsigned int wpa_len = beacon->wpa_ie_len;
1002 //for HT
2639ae97 1003 u8 *ht_cap_buf = NULL;
8fc8598e 1004 u8 ht_cap_len=0;
2639ae97 1005 u8 *realtek_ie_buf=NULL;
8fc8598e
JC
1006 u8 realtek_ie_len=0;
1007 int wpa_ie_len= ieee->wpa_ie_len;
1008 unsigned int ckip_ie_len=0;
1009 unsigned int ccxrm_ie_len=0;
1010 unsigned int cxvernum_ie_len=0;
2639ae97 1011 struct ieee80211_crypt_data *crypt;
8fc8598e
JC
1012 int encrypt;
1013
1014 unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
1015 unsigned int wmm_info_len = beacon->qos_data.supported?9:0;
1016#ifdef THOMAS_TURBO
1017 unsigned int turbo_info_len = beacon->Turbo_Enable?9:0;
1018#endif
1019
1020 int len = 0;
1021
1022 crypt = ieee->crypt[ieee->tx_keyidx];
1023 encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name,"WEP") || wpa_ie_len));
1024
04bdfd20 1025 /* Include High Throuput capability && Realtek proprietary */
dde48b99 1026 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
8fc8598e 1027 {
2639ae97 1028 ht_cap_buf = (u8 *)&(ieee->pHTInfo->SelfHTCap);
8fc8598e
JC
1029 ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
1030 HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
dde48b99 1031 if (ieee->pHTInfo->bCurrentRT2RTAggregation)
8fc8598e
JC
1032 {
1033 realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
1034 realtek_ie_len = sizeof( ieee->pHTInfo->szRT2RTAggBuffer);
1035 HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
1036
1037 }
1038 }
f53cb7b1 1039 if (ieee->qos_support) {
8fc8598e
JC
1040 wmm_info_len = beacon->qos_data.supported?9:0;
1041 }
1042
1043
dde48b99 1044 if (beacon->bCkipSupported)
8fc8598e
JC
1045 {
1046 ckip_ie_len = 30+2;
1047 }
dde48b99 1048 if (beacon->bCcxRmEnable)
8fc8598e
JC
1049 {
1050 ccxrm_ie_len = 6+2;
1051 }
d59d6f5d 1052 if (beacon->BssCcxVerNumber >= 2)
8fc8598e 1053 cxvernum_ie_len = 5+2;
d59d6f5d 1054
8fc8598e
JC
1055#ifdef THOMAS_TURBO
1056 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
04bdfd20
JR
1057 + beacon->ssid_len /* essid tagged val */
1058 + rate_len /* rates tagged val */
8fc8598e
JC
1059 + wpa_ie_len
1060 + wmm_info_len
1061 + turbo_info_len
e406322b 1062 + ht_cap_len
8fc8598e
JC
1063 + realtek_ie_len
1064 + ckip_ie_len
1065 + ccxrm_ie_len
1066 + cxvernum_ie_len
1067 + ieee->tx_headroom;
1068#else
1069 len = sizeof(struct ieee80211_assoc_request_frame)+ 2
04bdfd20
JR
1070 + beacon->ssid_len /* essid tagged val */
1071 + rate_len /* rates tagged val */
8fc8598e
JC
1072 + wpa_ie_len
1073 + wmm_info_len
e406322b 1074 + ht_cap_len
8fc8598e
JC
1075 + realtek_ie_len
1076 + ckip_ie_len
1077 + ccxrm_ie_len
1078 + cxvernum_ie_len
1079 + ieee->tx_headroom;
1080#endif
1081
1082 skb = dev_alloc_skb(len);
1083
1084 if (!skb)
1085 return NULL;
1086
1087 skb_reserve(skb, ieee->tx_headroom);
1088
1089 hdr = (struct ieee80211_assoc_request_frame *)
1090 skb_put(skb, sizeof(struct ieee80211_assoc_request_frame)+2);
1091
1092
1093 hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
25e2704c 1094 hdr->header.duration_id = cpu_to_le16(37);
8fc8598e
JC
1095 memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1096 memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1097 memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1098
1099 memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1100
1101 hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1102 if (beacon->capability & WLAN_CAPABILITY_PRIVACY )
1103 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1104
1105 if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1106 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1107
1108 if(ieee->short_slot)
1109 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
e406322b 1110 if (wmm_info_len) //QOS
f9eb26cf 1111 hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
8fc8598e 1112
25e2704c 1113 hdr->listen_interval = cpu_to_le16(0xa);
8fc8598e
JC
1114
1115 hdr->info_element[0].id = MFIE_TYPE_SSID;
1116
1117 hdr->info_element[0].len = beacon->ssid_len;
59ae1d12 1118 tag = skb_put_data(skb, beacon->ssid, beacon->ssid_len);
8fc8598e
JC
1119
1120 tag = skb_put(skb, rate_len);
1121
1122 ieee80211_MFIE_Brate(ieee, &tag);
1123 ieee80211_MFIE_Grate(ieee, &tag);
1124 // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
d59d6f5d 1125 if (beacon->bCkipSupported) {
8fc8598e
JC
1126 static u8 AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1127 u8 CcxAironetBuf[30];
1128 OCTET_STRING osCcxAironetIE;
1129
0b4ef0a6 1130 memset(CcxAironetBuf, 0, 30);
8fc8598e
JC
1131 osCcxAironetIE.Octet = CcxAironetBuf;
1132 osCcxAironetIE.Length = sizeof(CcxAironetBuf);
1133 //
1134 // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1135 // We want to make the device type as "4500-client". 060926, by CCW.
1136 //
1137 memcpy(osCcxAironetIE.Octet, AironetIeOui, sizeof(AironetIeOui));
1138
1139 // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1140 // "The CKIP negotiation is started with the associate request from the client to the access point,
1141 // containing an Aironet element with both the MIC and KP bits set."
1142 osCcxAironetIE.Octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK|SUPPORT_CKIP_MIC) ;
1143 tag = skb_put(skb, ckip_ie_len);
1144 *tag++ = MFIE_TYPE_AIRONET;
1145 *tag++ = osCcxAironetIE.Length;
0b4ef0a6 1146 memcpy(tag, osCcxAironetIE.Octet, osCcxAironetIE.Length);
8fc8598e
JC
1147 tag += osCcxAironetIE.Length;
1148 }
1149
dde48b99 1150 if (beacon->bCcxRmEnable)
8fc8598e
JC
1151 {
1152 static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1153 OCTET_STRING osCcxRmCap;
1154
1155 osCcxRmCap.Octet = CcxRmCapBuf;
1156 osCcxRmCap.Length = sizeof(CcxRmCapBuf);
0b4ef0a6 1157 tag = skb_put(skb, ccxrm_ie_len);
8fc8598e
JC
1158 *tag++ = MFIE_TYPE_GENERIC;
1159 *tag++ = osCcxRmCap.Length;
0b4ef0a6 1160 memcpy(tag, osCcxRmCap.Octet, osCcxRmCap.Length);
8fc8598e
JC
1161 tag += osCcxRmCap.Length;
1162 }
1163
d59d6f5d 1164 if (beacon->BssCcxVerNumber >= 2) {
8fc8598e
JC
1165 u8 CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1166 OCTET_STRING osCcxVerNum;
1167 CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1168 osCcxVerNum.Octet = CcxVerNumBuf;
1169 osCcxVerNum.Length = sizeof(CcxVerNumBuf);
0b4ef0a6 1170 tag = skb_put(skb, cxvernum_ie_len);
8fc8598e
JC
1171 *tag++ = MFIE_TYPE_GENERIC;
1172 *tag++ = osCcxVerNum.Length;
0b4ef0a6 1173 memcpy(tag, osCcxVerNum.Octet, osCcxVerNum.Length);
8fc8598e
JC
1174 tag += osCcxVerNum.Length;
1175 }
e406322b 1176 //HT cap element
f53cb7b1 1177 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
dde48b99 1178 if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC)
8fc8598e
JC
1179 {
1180 tag = skb_put(skb, ht_cap_len);
1181 *tag++ = MFIE_TYPE_HT_CAP;
1182 *tag++ = ht_cap_len - 2;
e60b6538 1183 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
8fc8598e
JC
1184 tag += ht_cap_len -2;
1185 }
1186 }
1187
1188
1189 //choose what wpa_supplicant gives to associate.
1190 tag = skb_put(skb, wpa_ie_len);
f53cb7b1 1191 if (wpa_ie_len) {
8fc8598e
JC
1192 memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
1193 }
1194
0b4ef0a6 1195 tag = skb_put(skb, wmm_info_len);
dde48b99 1196 if (wmm_info_len) {
8fc8598e
JC
1197 ieee80211_WMM_Info(ieee, &tag);
1198 }
1199#ifdef THOMAS_TURBO
0b4ef0a6 1200 tag = skb_put(skb, turbo_info_len);
dde48b99 1201 if (turbo_info_len) {
e406322b
MCC
1202 ieee80211_TURBO_Info(ieee, &tag);
1203 }
8fc8598e
JC
1204#endif
1205
f53cb7b1 1206 if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
8fc8598e
JC
1207 if(ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC)
1208 {
1209 tag = skb_put(skb, ht_cap_len);
1210 *tag++ = MFIE_TYPE_GENERIC;
1211 *tag++ = ht_cap_len - 2;
0b4ef0a6 1212 memcpy(tag, ht_cap_buf, ht_cap_len - 2);
8fc8598e
JC
1213 tag += ht_cap_len -2;
1214 }
1215
f53cb7b1 1216 if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
8fc8598e
JC
1217 tag = skb_put(skb, realtek_ie_len);
1218 *tag++ = MFIE_TYPE_GENERIC;
1219 *tag++ = realtek_ie_len - 2;
e60b6538 1220 memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
8fc8598e
JC
1221 }
1222 }
f8628a47 1223// printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
8fc8598e
JC
1224// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1225 return skb;
1226}
1227
1228void ieee80211_associate_abort(struct ieee80211_device *ieee)
1229{
1230
1231 unsigned long flags;
1232 spin_lock_irqsave(&ieee->lock, flags);
1233
1234 ieee->associate_seq++;
1235
1236 /* don't scan, and avoid to have the RX path possibily
1237 * try again to associate. Even do not react to AUTH or
1238 * ASSOC response. Just wait for the retry wq to be scheduled.
1239 * Here we will check if there are good nets to associate
1240 * with, so we retry or just get back to NO_LINK and scanning
1241 */
1242 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING){
1243 IEEE80211_DEBUG_MGMT("Authentication failed\n");
1244 ieee->softmac_stats.no_auth_rs++;
1245 }else{
1246 IEEE80211_DEBUG_MGMT("Association failed\n");
1247 ieee->softmac_stats.no_ass_rs++;
1248 }
1249
1250 ieee->state = IEEE80211_ASSOCIATING_RETRY;
1251
1761a85c 1252 schedule_delayed_work(&ieee->associate_retry_wq, \
e406322b 1253 IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
8fc8598e
JC
1254
1255 spin_unlock_irqrestore(&ieee->lock, flags);
1256}
1257
fabdbdb2 1258static void ieee80211_associate_abort_cb(unsigned long dev)
8fc8598e
JC
1259{
1260 ieee80211_associate_abort((struct ieee80211_device *) dev);
1261}
1262
1263
fabdbdb2 1264static void ieee80211_associate_step1(struct ieee80211_device *ieee)
8fc8598e
JC
1265{
1266 struct ieee80211_network *beacon = &ieee->current_network;
1267 struct sk_buff *skb;
1268
1269 IEEE80211_DEBUG_MGMT("Stopping scan\n");
1270
1271 ieee->softmac_stats.tx_auth_rq++;
1272 skb=ieee80211_authentication_req(beacon, ieee, 0);
1273
1274 if (!skb)
1275 ieee80211_associate_abort(ieee);
1276 else{
1277 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING ;
1278 IEEE80211_DEBUG_MGMT("Sending authentication request\n");
8fc8598e
JC
1279 softmac_mgmt_xmit(skb, ieee);
1280 //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
f53cb7b1 1281 if (!timer_pending(&ieee->associate_timer)) {
8fc8598e
JC
1282 ieee->associate_timer.expires = jiffies + (HZ / 2);
1283 add_timer(&ieee->associate_timer);
1284 }
1285 //dev_kfree_skb_any(skb);//edit by thomas
1286 }
1287}
1288
fabdbdb2
AR
1289static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1290 u8 *challenge,
1291 int chlen)
8fc8598e
JC
1292{
1293 u8 *c;
1294 struct sk_buff *skb;
1295 struct ieee80211_network *beacon = &ieee->current_network;
1296// int hlen = sizeof(struct ieee80211_authentication);
1297
1298 ieee->associate_seq++;
1299 ieee->softmac_stats.tx_auth_rq++;
1300
1301 skb = ieee80211_authentication_req(beacon, ieee, chlen+2);
1302 if (!skb)
1303 ieee80211_associate_abort(ieee);
1304 else{
1305 c = skb_put(skb, chlen+2);
1306 *(c++) = MFIE_TYPE_CHALLENGE;
1307 *(c++) = chlen;
1308 memcpy(c, challenge, chlen);
1309
1310 IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1311
5c2918a5 1312 ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr ));
8fc8598e
JC
1313
1314 softmac_mgmt_xmit(skb, ieee);
1315 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
8fc8598e
JC
1316 //dev_kfree_skb_any(skb);//edit by thomas
1317 }
1318 kfree(challenge);
1319}
1320
fabdbdb2 1321static void ieee80211_associate_step2(struct ieee80211_device *ieee)
8fc8598e 1322{
2639ae97 1323 struct sk_buff *skb;
8fc8598e
JC
1324 struct ieee80211_network *beacon = &ieee->current_network;
1325
1326 del_timer_sync(&ieee->associate_timer);
1327
1328 IEEE80211_DEBUG_MGMT("Sending association request\n");
1329
1330 ieee->softmac_stats.tx_ass_rq++;
1331 skb=ieee80211_association_req(beacon, ieee);
1332 if (!skb)
1333 ieee80211_associate_abort(ieee);
1334 else{
1335 softmac_mgmt_xmit(skb, ieee);
1336 mod_timer(&ieee->associate_timer, jiffies + (HZ/2));
8fc8598e
JC
1337 //dev_kfree_skb_any(skb);//edit by thomas
1338 }
1339}
fabdbdb2 1340static void ieee80211_associate_complete_wq(struct work_struct *work)
8fc8598e 1341{
e406322b 1342 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
8fc8598e 1343 printk(KERN_INFO "Associated successfully\n");
58af5800 1344 if(ieee80211_is_54g(&ieee->current_network) &&
8fc8598e
JC
1345 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1346
1347 ieee->rate = 108;
1348 printk(KERN_INFO"Using G rates:%d\n", ieee->rate);
1349 }else{
1350 ieee->rate = 22;
1351 printk(KERN_INFO"Using B rates:%d\n", ieee->rate);
1352 }
1353 if (ieee->pHTInfo->bCurrentHTSupport&&ieee->pHTInfo->bEnableHT)
1354 {
1355 printk("Successfully associated, ht enabled\n");
1356 HTOnAssocRsp(ieee);
1357 }
1358 else
1359 {
1360 printk("Successfully associated, ht not enabled(%d, %d)\n", ieee->pHTInfo->bCurrentHTSupport, ieee->pHTInfo->bEnableHT);
1361 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1362 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1363 }
1364 ieee->LinkDetectInfo.SlotNum = 2 * (1 + ieee->current_network.beacon_interval/500);
1365 // To prevent the immediately calling watch_dog after association.
dde48b99 1366 if (ieee->LinkDetectInfo.NumRecvBcnInPeriod==0||ieee->LinkDetectInfo.NumRecvDataInPeriod==0 )
8fc8598e
JC
1367 {
1368 ieee->LinkDetectInfo.NumRecvBcnInPeriod = 1;
1369 ieee->LinkDetectInfo.NumRecvDataInPeriod= 1;
1370 }
1371 ieee->link_change(ieee->dev);
a4f649bd 1372 if (!ieee->is_silent_reset) {
8fc8598e 1373 printk("============>normal associate\n");
9c708f94 1374 notify_wx_assoc_event(ieee);
a4f649bd 1375 } else {
8fc8598e 1376 printk("==================>silent reset associate\n");
19cd2297 1377 ieee->is_silent_reset = false;
8fc8598e
JC
1378 }
1379
1380 if (ieee->data_hard_resume)
1381 ieee->data_hard_resume(ieee->dev);
1382 netif_carrier_on(ieee->dev);
1383}
1384
fabdbdb2 1385static void ieee80211_associate_complete(struct ieee80211_device *ieee)
8fc8598e
JC
1386{
1387// int i;
1388// struct net_device* dev = ieee->dev;
1389 del_timer_sync(&ieee->associate_timer);
1390
8fc8598e 1391 ieee->state = IEEE80211_LINKED;
8fc8598e 1392 //ieee->UpdateHalRATRTableHandler(dev, ieee->dot11HTOperationalRateSet);
1761a85c 1393 schedule_work(&ieee->associate_complete_wq);
8fc8598e
JC
1394}
1395
fabdbdb2 1396static void ieee80211_associate_procedure_wq(struct work_struct *work)
8fc8598e 1397{
e406322b 1398 struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_procedure_wq);
8fc8598e 1399 ieee->sync_scan_hurryup = 1;
e379a9a8 1400 mutex_lock(&ieee->wx_mutex);
8fc8598e
JC
1401
1402 if (ieee->data_hard_stop)
1403 ieee->data_hard_stop(ieee->dev);
1404
1405 ieee80211_stop_scan(ieee);
f8628a47 1406 printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
8fc8598e
JC
1407 //ieee->set_chan(ieee->dev, ieee->current_network.channel);
1408 HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1409
1410 ieee->associate_seq = 1;
1411 ieee80211_associate_step1(ieee);
1412
e379a9a8 1413 mutex_unlock(&ieee->wx_mutex);
8fc8598e
JC
1414}
1415
1416inline void ieee80211_softmac_new_net(struct ieee80211_device *ieee, struct ieee80211_network *net)
1417{
1418 u8 tmp_ssid[IW_ESSID_MAX_SIZE+1];
1419 int tmp_ssid_len = 0;
1420
0b4ef0a6 1421 short apset, ssidset, ssidbroad, apmatch, ssidmatch;
8fc8598e
JC
1422
1423 /* we are interested in new new only if we are not associated
1424 * and we are not associating / authenticating
1425 */
1426 if (ieee->state != IEEE80211_NOLINK)
1427 return;
1428
1429 if ((ieee->iw_mode == IW_MODE_INFRA) && !(net->capability & WLAN_CAPABILITY_BSS))
1430 return;
1431
1432 if ((ieee->iw_mode == IW_MODE_ADHOC) && !(net->capability & WLAN_CAPABILITY_IBSS))
1433 return;
1434
1435
f53cb7b1 1436 if (ieee->iw_mode == IW_MODE_INFRA || ieee->iw_mode == IW_MODE_ADHOC) {
8fc8598e
JC
1437 /* if the user specified the AP MAC, we need also the essid
1438 * This could be obtained by beacons or, if the network does not
1439 * broadcast it, it can be put manually.
1440 */
1441 apset = ieee->wap_set;//(memcmp(ieee->current_network.bssid, zero,ETH_ALEN)!=0 );
1442 ssidset = ieee->ssid_set;//ieee->current_network.ssid[0] != '\0';
1443 ssidbroad = !(net->ssid_len == 0 || net->ssid[0]== '\0');
1444 apmatch = (memcmp(ieee->current_network.bssid, net->bssid, ETH_ALEN)==0);
1445 ssidmatch = (ieee->current_network.ssid_len == net->ssid_len)&&\
1446 (!strncmp(ieee->current_network.ssid, net->ssid, net->ssid_len));
1447
1448
1449 if ( /* if the user set the AP check if match.
e406322b 1450 * if the network does not broadcast essid we check the user supplyed ANY essid
8fc8598e
JC
1451 * if the network does broadcast and the user does not set essid it is OK
1452 * if the network does broadcast and the user did set essid chech if essid match
1453 */
8048ed5b 1454 (apset && apmatch &&
8fc8598e
JC
1455 ((ssidset && ssidbroad && ssidmatch) || (ssidbroad && !ssidset) || (!ssidbroad && ssidset)) ) ||
1456 /* if the ap is not set, check that the user set the bssid
935d59ff 1457 * and the network does broadcast and that those two bssid matches
8fc8598e
JC
1458 */
1459 (!apset && ssidset && ssidbroad && ssidmatch)
1460 ){
1461 /* if the essid is hidden replace it with the
1462 * essid provided by the user.
1463 */
f53cb7b1 1464 if (!ssidbroad) {
8fc8598e
JC
1465 strncpy(tmp_ssid, ieee->current_network.ssid, IW_ESSID_MAX_SIZE);
1466 tmp_ssid_len = ieee->current_network.ssid_len;
1467 }
1468 memcpy(&ieee->current_network, net, sizeof(struct ieee80211_network));
1469
afd0fea4
SB
1470 strncpy(ieee->current_network.ssid, tmp_ssid, IW_ESSID_MAX_SIZE);
1471 ieee->current_network.ssid_len = tmp_ssid_len;
8fc8598e
JC
1472 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);
1473
1474 //ieee->pHTInfo->IOTAction = 0;
1475 HTResetIOTSetting(ieee->pHTInfo);
1476 if (ieee->iw_mode == IW_MODE_INFRA){
1477 /* Join the network for the first time */
1478 ieee->AsocRetryCount = 0;
1479 //for HT by amy 080514
1480 if((ieee->current_network.qos_data.supported == 1) &&
1481 // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1482 ieee->current_network.bssht.bdSupportHT)
1483/*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.*/
1484 {
1485 // ieee->pHTInfo->bCurrentHTSupport = true;
1486 HTResetSelfAndSavePeerSetting(ieee, &(ieee->current_network));
1487 }
1488 else
1489 {
1490 ieee->pHTInfo->bCurrentHTSupport = false;
1491 }
1492
1493 ieee->state = IEEE80211_ASSOCIATING;
1761a85c 1494 schedule_work(&ieee->associate_procedure_wq);
8fc8598e 1495 }else{
58af5800 1496 if(ieee80211_is_54g(&ieee->current_network) &&
8fc8598e
JC
1497 (ieee->modulation & IEEE80211_OFDM_MODULATION)){
1498 ieee->rate = 108;
1499 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1500 printk(KERN_INFO"Using G rates\n");
1501 }else{
1502 ieee->rate = 22;
1503 ieee->SetWirelessMode(ieee->dev, IEEE_B);
1504 printk(KERN_INFO"Using B rates\n");
1505 }
1506 memset(ieee->dot11HTOperationalRateSet, 0, 16);
1507 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1508 ieee->state = IEEE80211_LINKED;
1509 }
1510
1511 }
1512 }
1513
1514}
1515
1516void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1517{
1518 unsigned long flags;
1519 struct ieee80211_network *target;
1520
1521 spin_lock_irqsave(&ieee->lock, flags);
1522
1523 list_for_each_entry(target, &ieee->network_list, list) {
1524
1525 /* if the state become different that NOLINK means
1526 * we had found what we are searching for
1527 */
1528
1529 if (ieee->state != IEEE80211_NOLINK)
1530 break;
1531
1532 if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
f9eb26cf 1533 ieee80211_softmac_new_net(ieee, target);
8fc8598e
JC
1534 }
1535
1536 spin_unlock_irqrestore(&ieee->lock, flags);
1537
1538}
1539
1540
2639ae97 1541static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
8fc8598e
JC
1542{
1543 struct ieee80211_authentication *a;
1544 u8 *t;
f53cb7b1 1545 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
8fc8598e
JC
1546 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n",skb->len);
1547 return 0xcafe;
1548 }
1549 *challenge = NULL;
2639ae97 1550 a = (struct ieee80211_authentication *) skb->data;
f53cb7b1 1551 if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
8fc8598e
JC
1552 t = skb->data + sizeof(struct ieee80211_authentication);
1553
f53cb7b1 1554 if (*(t++) == MFIE_TYPE_CHALLENGE) {
8fc8598e 1555 *chlen = *(t++);
94002c07 1556 *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
dde27e03 1557 if (!*challenge)
1558 return -ENOMEM;
8fc8598e
JC
1559 }
1560 }
1561
2bd239d7 1562 return le16_to_cpu(a->status);
8fc8598e
JC
1563
1564}
1565
1566
fabdbdb2 1567static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
8fc8598e
JC
1568{
1569 struct ieee80211_authentication *a;
1570
f53cb7b1 1571 if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
8fc8598e
JC
1572 IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n",skb->len);
1573 return -1;
1574 }
2639ae97 1575 a = (struct ieee80211_authentication *) skb->data;
8fc8598e
JC
1576
1577 memcpy(dest,a->header.addr2, ETH_ALEN);
1578
1579 if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1580 return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1581
1582 return WLAN_STATUS_SUCCESS;
1583}
1584
1585static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1586{
1587 u8 *tag;
1588 u8 *skbend;
1589 u8 *ssid=NULL;
1590 u8 ssidlen = 0;
1591
5c2918a5
PG
1592 struct rtl_80211_hdr_3addr *header =
1593 (struct rtl_80211_hdr_3addr *) skb->data;
8fc8598e 1594
5c2918a5 1595 if (skb->len < sizeof (struct rtl_80211_hdr_3addr ))
8fc8598e
JC
1596 return -1; /* corrupted */
1597
1598 memcpy(src,header->addr2, ETH_ALEN);
1599
2639ae97 1600 skbend = (u8 *)skb->data + skb->len;
8fc8598e 1601
5c2918a5 1602 tag = skb->data + sizeof (struct rtl_80211_hdr_3addr );
8fc8598e
JC
1603
1604 while (tag+1 < skbend){
f53cb7b1 1605 if (*tag == 0) {
8fc8598e
JC
1606 ssid = tag+2;
1607 ssidlen = *(tag+1);
1608 break;
1609 }
1610 tag++; /* point to the len field */
1611 tag = tag + *(tag); /* point to the last data byte of the tag */
1612 tag++; /* point to the next tag */
1613 }
1614
1615 //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1616 if (ssidlen == 0) return 1;
1617
1618 if (!ssid) return 1; /* ssid not found in tagged param */
1619 return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1620
1621}
1622
fabdbdb2 1623static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
8fc8598e
JC
1624{
1625 struct ieee80211_assoc_request_frame *a;
1626
1627 if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1628 sizeof(struct ieee80211_info_element))) {
1629
1630 IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1631 return -1;
1632 }
1633
2639ae97 1634 a = (struct ieee80211_assoc_request_frame *) skb->data;
8fc8598e
JC
1635
1636 memcpy(dest,a->header.addr2,ETH_ALEN);
1637
1638 return 0;
1639}
1640
1641static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1642{
1643 struct ieee80211_assoc_response_frame *response_head;
1644 u16 status_code;
1645
f53cb7b1 1646 if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
8fc8598e
JC
1647 IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1648 return 0xcafe;
1649 }
1650
2639ae97 1651 response_head = (struct ieee80211_assoc_response_frame *) skb->data;
8fc8598e
JC
1652 *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1653
1654 status_code = le16_to_cpu(response_head->status);
1655 if((status_code==WLAN_STATUS_ASSOC_DENIED_RATES || \
1656 status_code==WLAN_STATUS_CAPS_UNSUPPORTED)&&
1657 ((ieee->mode == IEEE_G) &&
1658 (ieee->current_network.mode == IEEE_N_24G) &&
e406322b
MCC
1659 (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT-1)))) {
1660 ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
8fc8598e
JC
1661 }else {
1662 ieee->AsocRetryCount = 0;
1663 }
1664
1665 return le16_to_cpu(response_head->status);
1666}
1667
1668static inline void
1669ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1670{
1671 u8 dest[ETH_ALEN];
1672
1673 //IEEE80211DMESG("Rx probe");
1674 ieee->softmac_stats.rx_probe_rq++;
1675 //DMESG("Dest is "MACSTR, MAC2STR(dest));
f53cb7b1 1676 if (probe_rq_parse(ieee, skb, dest)) {
8fc8598e
JC
1677 //IEEE80211DMESG("Was for me!");
1678 ieee->softmac_stats.tx_probe_rs++;
1679 ieee80211_resp_to_probe(ieee, dest);
1680 }
1681}
1682
1683static inline void
1684ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1685{
1686 u8 dest[ETH_ALEN];
1687 int status;
1688 //IEEE80211DMESG("Rx probe");
1689 ieee->softmac_stats.rx_auth_rq++;
1690
d10219fc
JP
1691 status = auth_rq_parse(skb, dest);
1692 if (status != -1) {
8fc8598e
JC
1693 ieee80211_resp_to_auth(ieee, status, dest);
1694 }
1695 //DMESG("Dest is "MACSTR, MAC2STR(dest));
1696
1697}
1698
1699static inline void
1700ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1701{
1702
1703 u8 dest[ETH_ALEN];
1704 //unsigned long flags;
1705
1706 ieee->softmac_stats.rx_ass_rq++;
f53cb7b1 1707 if (assoc_rq_parse(skb, dest) != -1) {
8fc8598e
JC
1708 ieee80211_resp_to_assoc_rq(ieee, dest);
1709 }
1710
0ee9f67c 1711 printk(KERN_INFO"New client associated: %pM\n", dest);
8fc8598e 1712 //FIXME
8fc8598e
JC
1713}
1714
fabdbdb2
AR
1715static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1716 short pwr)
8fc8598e
JC
1717{
1718
1719 struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1720
1721 if (buf)
1722 softmac_ps_mgmt_xmit(buf, ieee);
1723
1724}
539b4f72 1725/* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
8fc8598e 1726
fabdbdb2
AR
1727static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1728 u32 *time_l)
8fc8598e
JC
1729{
1730 int timeout = ieee->ps_timeout;
1731 u8 dtim;
1732 /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1733 ieee->iw_mode != IW_MODE_INFRA ||
1734 ieee->state != IEEE80211_LINKED)
1735
1736 return 0;
1737 */
1738 dtim = ieee->current_network.dtim_data;
8fc8598e
JC
1739 if(!(dtim & IEEE80211_DTIM_VALID))
1740 return 0;
1741 timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
8fc8598e
JC
1742 ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1743
1744 if(dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST)& ieee->ps))
1745 return 2;
1746
4763a752 1747 if(!time_after(jiffies,
4d0e9657 1748 dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
8fc8598e
JC
1749 return 0;
1750
4763a752
AKC
1751 if(!time_after(jiffies,
1752 ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
8fc8598e
JC
1753 return 0;
1754
1755 if((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE ) &&
1756 (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1757 return 0;
1758
f53cb7b1 1759 if (time_l) {
8fc8598e
JC
1760 *time_l = ieee->current_network.last_dtim_sta_time[0]
1761 + (ieee->current_network.beacon_interval
1762 * ieee->current_network.dtim_period) * 1000;
1763 }
1764
f53cb7b1 1765 if (time_h) {
8fc8598e
JC
1766 *time_h = ieee->current_network.last_dtim_sta_time[1];
1767 if(time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1768 *time_h += 1;
1769 }
1770
1771 return 1;
1772
1773
1774}
1775
fabdbdb2 1776static inline void ieee80211_sta_ps(struct ieee80211_device *ieee)
8fc8598e
JC
1777{
1778
0b4ef0a6 1779 u32 th, tl;
8fc8598e
JC
1780 short sleep;
1781
0b4ef0a6 1782 unsigned long flags, flags2;
8fc8598e
JC
1783
1784 spin_lock_irqsave(&ieee->lock, flags);
1785
dde48b99 1786 if ((ieee->ps == IEEE80211_PS_DISABLED ||
8fc8598e
JC
1787 ieee->iw_mode != IW_MODE_INFRA ||
1788 ieee->state != IEEE80211_LINKED)){
1789
1790 // #warning CHECK_LOCK_HERE
1791 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1792
1793 ieee80211_sta_wakeup(ieee, 1);
1794
1795 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1796 }
1797
1798 sleep = ieee80211_sta_ps_sleep(ieee,&th, &tl);
1799 /* 2 wake, 1 sleep, 0 do nothing */
1800 if(sleep == 0)
1801 goto out;
1802
1803 if(sleep == 1){
1804
1805 if(ieee->sta_sleep == 1)
0b4ef0a6 1806 ieee->enter_sleep_state(ieee->dev, th, tl);
8fc8598e
JC
1807
1808 else if(ieee->sta_sleep == 0){
1809 // printk("send null 1\n");
1810 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1811
1812 if(ieee->ps_is_queue_empty(ieee->dev)){
1813
1814
1815 ieee->sta_sleep = 2;
1816
1817 ieee->ps_request_tx_ack(ieee->dev);
1818
0b4ef0a6 1819 ieee80211_sta_ps_send_null_frame(ieee, 1);
8fc8598e
JC
1820
1821 ieee->ps_th = th;
1822 ieee->ps_tl = tl;
1823 }
1824 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1825
1826 }
1827
1828
1829 }else if(sleep == 2){
1830//#warning CHECK_LOCK_HERE
1831 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1832
0b4ef0a6 1833 ieee80211_sta_wakeup(ieee, 1);
8fc8598e
JC
1834
1835 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1836 }
1837
1838out:
1839 spin_unlock_irqrestore(&ieee->lock, flags);
1840
1841}
1842
1843void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1844{
f53cb7b1
HM
1845 if (ieee->sta_sleep == 0) {
1846 if (nl) {
8fc8598e
JC
1847 printk("Warning: driver is probably failing to report TX ps error\n");
1848 ieee->ps_request_tx_ack(ieee->dev);
1849 ieee80211_sta_ps_send_null_frame(ieee, 0);
1850 }
1851 return;
1852
1853 }
1854
1855 if(ieee->sta_sleep == 1)
1856 ieee->sta_wake_up(ieee->dev);
1857
1858 ieee->sta_sleep = 0;
1859
f53cb7b1 1860 if (nl) {
8fc8598e
JC
1861 ieee->ps_request_tx_ack(ieee->dev);
1862 ieee80211_sta_ps_send_null_frame(ieee, 0);
1863 }
1864}
1865
1866void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1867{
0b4ef0a6 1868 unsigned long flags, flags2;
8fc8598e
JC
1869
1870 spin_lock_irqsave(&ieee->lock, flags);
1871
1872 if(ieee->sta_sleep == 2){
1873 /* Null frame with PS bit set */
f53cb7b1 1874 if (success) {
8fc8598e
JC
1875 ieee->sta_sleep = 1;
1876 ieee->enter_sleep_state(ieee->dev,ieee->ps_th,ieee->ps_tl);
1877 }
1878 /* if the card report not success we can't be sure the AP
1879 * has not RXed so we can't assume the AP believe us awake
1880 */
1881 }
1882 /* 21112005 - tx again null without PS bit if lost */
1883 else {
1884
f53cb7b1 1885 if ((ieee->sta_sleep == 0) && !success) {
8fc8598e
JC
1886 spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1887 ieee80211_sta_ps_send_null_frame(ieee, 0);
1888 spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1889 }
1890 }
1891 spin_unlock_irqrestore(&ieee->lock, flags);
1892}
539b4f72
BT
1893EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1894
fabdbdb2
AR
1895static void ieee80211_process_action(struct ieee80211_device *ieee,
1896 struct sk_buff *skb)
8fc8598e 1897{
5c2918a5 1898 struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
2639ae97 1899 u8 *act = ieee80211_get_payload(header);
8fc8598e
JC
1900 u8 tmp = 0;
1901// IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1902 if (act == NULL)
1903 {
1904 IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1905 return;
1906 }
1907 tmp = *act;
1908 act ++;
ab0fbdc2
DC
1909 switch (tmp) {
1910 case ACT_CAT_BA:
1911 if (*act == ACT_ADDBAREQ)
8fc8598e 1912 ieee80211_rx_ADDBAReq(ieee, skb);
ab0fbdc2 1913 else if (*act == ACT_ADDBARSP)
8fc8598e 1914 ieee80211_rx_ADDBARsp(ieee, skb);
ab0fbdc2 1915 else if (*act == ACT_DELBA)
8fc8598e 1916 ieee80211_rx_DELBA(ieee, skb);
ab0fbdc2
DC
1917 break;
1918 default:
1919 break;
8fc8598e
JC
1920 }
1921 return;
1922
1923}
5b2965b6 1924
d9e048cd
CA
1925static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1926 struct sk_buff *skb)
5b2965b6
CO
1927{
1928 /* default support N mode, disable halfNmode */
1929 bool bSupportNmode = true, bHalfSupportNmode = false;
1930 u16 errcode;
1931 u8 *challenge;
1932 int chlen = 0;
1933 u32 iotAction;
1934
1935 errcode = auth_parse(skb, &challenge, &chlen);
1936 if (!errcode) {
1937 if (ieee->open_wep || !challenge) {
1938 ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1939 ieee->softmac_stats.rx_auth_rs_ok++;
1940 iotAction = ieee->pHTInfo->IOTAction;
1941 if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1942 if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1943 /* WEP or TKIP encryption */
1944 if (IsHTHalfNmodeAPs(ieee)) {
1945 bSupportNmode = true;
1946 bHalfSupportNmode = true;
1947 } else {
1948 bSupportNmode = false;
1949 bHalfSupportNmode = false;
1950 }
b4e3e6ee
CO
1951 netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1952 bSupportNmode,
1953 bHalfSupportNmode);
5b2965b6
CO
1954 }
1955 }
1956 /* Dummy wirless mode setting- avoid encryption issue */
1957 if (bSupportNmode) {
1958 /* N mode setting */
1959 ieee->SetWirelessMode(ieee->dev,
1960 ieee->current_network.mode);
1961 } else {
1962 /* b/g mode setting - TODO */
1963 ieee->SetWirelessMode(ieee->dev, IEEE_G);
1964 }
1965
1966 if (ieee->current_network.mode == IEEE_N_24G &&
f9bd549a 1967 bHalfSupportNmode) {
b4e3e6ee 1968 netdev_dbg(ieee->dev, "enter half N mode\n");
5b2965b6
CO
1969 ieee->bHalfWirelessN24GMode = true;
1970 } else
1971 ieee->bHalfWirelessN24GMode = false;
1972
1973 ieee80211_associate_step2(ieee);
1974 } else {
1975 ieee80211_auth_challenge(ieee, challenge, chlen);
1976 }
1977 } else {
1978 ieee->softmac_stats.rx_auth_rs_err++;
1979 IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1980 ieee80211_associate_abort(ieee);
1981 }
1982}
1983
8fc8598e
JC
1984inline int
1985ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1986 struct ieee80211_rx_stats *rx_stats, u16 type,
1987 u16 stype)
1988{
5c2918a5 1989 struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *) skb->data;
8fc8598e 1990 u16 errcode;
8fc8598e
JC
1991 int aid;
1992 struct ieee80211_assoc_response_frame *assoc_resp;
1993// struct ieee80211_info_element *info_element;
8fc8598e
JC
1994
1995 if(!ieee->proto_started)
1996 return 0;
1997
1998 if(ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1999 ieee->iw_mode == IW_MODE_INFRA &&
2000 ieee->state == IEEE80211_LINKED))
2001
2002 tasklet_schedule(&ieee->ps_task);
2003
2004 if(WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
2005 WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
2006 ieee->last_rx_ps_time = jiffies;
2007
2008 switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
2009
24fbe875
SH
2010 case IEEE80211_STYPE_ASSOC_RESP:
2011 case IEEE80211_STYPE_REASSOC_RESP:
2012
2013 IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
2014 WLAN_FC_GET_STYPE(header->frame_ctl));
2015 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2016 ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
2017 ieee->iw_mode == IW_MODE_INFRA){
2018 struct ieee80211_network network_resp;
2019 struct ieee80211_network *network = &network_resp;
2020
09adb6e7
CP
2021 errcode = assoc_parse(ieee, skb, &aid);
2022 if (!errcode) {
24fbe875
SH
2023 ieee->state=IEEE80211_LINKED;
2024 ieee->assoc_id = aid;
2025 ieee->softmac_stats.rx_ass_ok++;
2026 /* station support qos */
2027 /* Let the register setting defaultly with Legacy station */
dde48b99 2028 if (ieee->qos_support) {
2639ae97 2029 assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
24fbe875
SH
2030 memset(network, 0, sizeof(*network));
2031 if (ieee80211_parse_info_param(ieee,assoc_resp->info_element,\
2032 rx_stats->len - sizeof(*assoc_resp),\
2033 network,rx_stats)){
2034 return 1;
8fc8598e 2035 }
24fbe875
SH
2036 else
2037 { //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
2038 memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
2039 memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
8fc8598e 2040 }
24fbe875 2041 if (ieee->handle_assoc_response != NULL)
2639ae97 2042 ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
24fbe875
SH
2043 }
2044 ieee80211_associate_complete(ieee);
2045 } else {
2046 /* aid could not been allocated */
2047 ieee->softmac_stats.rx_ass_err++;
2048 printk(
2049 "Association response status code 0x%x\n",
2050 errcode);
2051 IEEE80211_DEBUG_MGMT(
2052 "Association response status code 0x%x\n",
2053 errcode);
2054 if(ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT) {
1761a85c 2055 schedule_work(&ieee->associate_procedure_wq);
24fbe875
SH
2056 } else {
2057 ieee80211_associate_abort(ieee);
8fc8598e
JC
2058 }
2059 }
24fbe875
SH
2060 }
2061 break;
8fc8598e 2062
24fbe875
SH
2063 case IEEE80211_STYPE_ASSOC_REQ:
2064 case IEEE80211_STYPE_REASSOC_REQ:
8fc8598e 2065
24fbe875
SH
2066 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2067 ieee->iw_mode == IW_MODE_MASTER)
8fc8598e 2068
24fbe875
SH
2069 ieee80211_rx_assoc_rq(ieee, skb);
2070 break;
8fc8598e 2071
24fbe875 2072 case IEEE80211_STYPE_AUTH:
8fc8598e 2073
f53cb7b1 2074 if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
5b2965b6
CO
2075 if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
2076 && ieee->iw_mode == IW_MODE_INFRA) {
8fc8598e 2077
5b2965b6
CO
2078 IEEE80211_DEBUG_MGMT("Received auth response");
2079 ieee80211_check_auth_response(ieee, skb);
2080 } else if (ieee->iw_mode == IW_MODE_MASTER) {
2081 ieee80211_rx_auth_rq(ieee, skb);
8fc8598e 2082 }
5b2965b6 2083 }
24fbe875 2084 break;
8fc8598e 2085
24fbe875
SH
2086 case IEEE80211_STYPE_PROBE_REQ:
2087
2088 if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
2089 ((ieee->iw_mode == IW_MODE_ADHOC ||
2090 ieee->iw_mode == IW_MODE_MASTER) &&
2091 ieee->state == IEEE80211_LINKED)){
2092 ieee80211_rx_probe_rq(ieee, skb);
2093 }
2094 break;
2095
2096 case IEEE80211_STYPE_DISASSOC:
2097 case IEEE80211_STYPE_DEAUTH:
2098 /* FIXME for now repeat all the association procedure
2099 * both for disassociation and deauthentication
2100 */
2101 if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
2102 ieee->state == IEEE80211_LINKED &&
2103 ieee->iw_mode == IW_MODE_INFRA){
2104
2105 ieee->state = IEEE80211_ASSOCIATING;
2106 ieee->softmac_stats.reassoc++;
2107
2108 notify_wx_assoc_event(ieee);
2109 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2110 RemovePeerTS(ieee, header->addr2);
1761a85c 2111 schedule_work(&ieee->associate_procedure_wq);
24fbe875
SH
2112 }
2113 break;
2114 case IEEE80211_STYPE_MANAGE_ACT:
0b4ef0a6 2115 ieee80211_process_action(ieee, skb);
24fbe875
SH
2116 break;
2117 default:
2118 return -1;
8fc8598e
JC
2119 }
2120
2121 //dev_kfree_skb_any(skb);
2122 return 0;
2123}
2124
c3bb4545
CO
2125/* The following are for a simpler TX queue management.
2126 * Instead of using netif_[stop/wake]_queue, the driver
2127 * will use these two functions (plus a reset one) that
2128 * will internally call the kernel netif_* and take care
2129 * of the ieee802.11 fragmentation.
2130 * So, the driver receives a fragment at a time and might
2131 * call the stop function when it wants, without taking
2132 * care to have enough room to TX an entire packet.
2133 * This might be useful if each fragment needs its own
2134 * descriptor. Thus, just keeping a total free memory > than
2135 * the max fragmentation threshold is not enough. If the
2136 * ieee802.11 stack passed a TXB struct, then you would need
8fc8598e 2137 * to keep N free descriptors where
c3bb4545 2138 * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
8fc8598e
JC
2139 * In this way you need just one and the 802.11 stack
2140 * will take care of buffering fragments and pass them to
2141 * to the driver later, when it wakes the queue.
2142 */
2143void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2144{
2145
2146 unsigned int queue_index = txb->queue_index;
2147 unsigned long flags;
2148 int i;
20f896c4 2149 struct cb_desc *tcb_desc = NULL;
8fc8598e 2150
0b4ef0a6 2151 spin_lock_irqsave(&ieee->lock, flags);
8fc8598e
JC
2152
2153 /* called with 2nd parm 0, no tx mgmt lock required */
0b4ef0a6 2154 ieee80211_sta_wakeup(ieee, 0);
8fc8598e
JC
2155
2156 /* update the tx status */
80cf407f 2157 ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
8fc8598e 2158 ieee->stats.tx_packets++;
20f896c4 2159 tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
dde48b99 2160 if (tcb_desc->bMulticast) {
8fc8598e
JC
2161 ieee->stats.multicast++;
2162 }
8fc8598e
JC
2163 /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2164 for(i = 0; i < txb->nr_frags; i++) {
2165#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2166 if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2167#else
2168 if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2169#endif
2170 (!ieee->check_nic_enough_desc(ieee->dev,queue_index))||\
2171 (ieee->queue_stop)) {
2172 /* insert the skb packet to the wait queue */
2173 /* as for the completion function, it does not need
2174 * to check it any more.
2175 * */
2176 //printk("error:no descriptor left@queue_index %d\n", queue_index);
2177 //ieee80211_stop_queue(ieee);
2178#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2179 skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2180#else
2181 skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2182#endif
2183 }else{
2184 ieee->softmac_data_hard_start_xmit(
2185 txb->fragments[i],
0b4ef0a6 2186 ieee->dev, ieee->rate);
8fc8598e
JC
2187 //ieee->stats.tx_packets++;
2188 //ieee->stats.tx_bytes += txb->fragments[i]->len;
2189 //ieee->dev->trans_start = jiffies;
2190 }
2191 }
8fc8598e
JC
2192 ieee80211_txb_free(txb);
2193
2194//exit:
0b4ef0a6 2195 spin_unlock_irqrestore(&ieee->lock, flags);
8fc8598e
JC
2196
2197}
539b4f72 2198EXPORT_SYMBOL(ieee80211_softmac_xmit);
8fc8598e
JC
2199
2200/* called with ieee->lock acquired */
fabdbdb2 2201static void ieee80211_resume_tx(struct ieee80211_device *ieee)
8fc8598e
JC
2202{
2203 int i;
2204 for(i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2205
2206 if (ieee->queue_stop){
2207 ieee->tx_pending.frag = i;
2208 return;
2209 }else{
2210
2211 ieee->softmac_data_hard_start_xmit(
2212 ieee->tx_pending.txb->fragments[i],
0b4ef0a6 2213 ieee->dev, ieee->rate);
8fc8598e
JC
2214 //(i+1)<ieee->tx_pending.txb->nr_frags);
2215 ieee->stats.tx_packets++;
860e9538 2216 netif_trans_update(ieee->dev);
8fc8598e
JC
2217 }
2218 }
2219
2220
2221 ieee80211_txb_free(ieee->tx_pending.txb);
2222 ieee->tx_pending.txb = NULL;
2223}
2224
2225
2226void ieee80211_reset_queue(struct ieee80211_device *ieee)
2227{
2228 unsigned long flags;
2229
0b4ef0a6 2230 spin_lock_irqsave(&ieee->lock, flags);
8fc8598e 2231 init_mgmt_queue(ieee);
f53cb7b1 2232 if (ieee->tx_pending.txb) {
8fc8598e
JC
2233 ieee80211_txb_free(ieee->tx_pending.txb);
2234 ieee->tx_pending.txb = NULL;
2235 }
2236 ieee->queue_stop = 0;
0b4ef0a6 2237 spin_unlock_irqrestore(&ieee->lock, flags);
8fc8598e
JC
2238
2239}
539b4f72 2240EXPORT_SYMBOL(ieee80211_reset_queue);
8fc8598e
JC
2241
2242void ieee80211_wake_queue(struct ieee80211_device *ieee)
2243{
2244
2245 unsigned long flags;
2246 struct sk_buff *skb;
5c2918a5 2247 struct rtl_80211_hdr_3addr *header;
8fc8598e 2248
0b4ef0a6 2249 spin_lock_irqsave(&ieee->lock, flags);
8fc8598e
JC
2250 if (! ieee->queue_stop) goto exit;
2251
2252 ieee->queue_stop = 0;
2253
f53cb7b1 2254 if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
8fc8598e
JC
2255 while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))){
2256
5c2918a5 2257 header = (struct rtl_80211_hdr_3addr *) skb->data;
8fc8598e
JC
2258
2259 header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2260
2261 if (ieee->seq_ctrl[0] == 0xFFF)
2262 ieee->seq_ctrl[0] = 0;
2263 else
2264 ieee->seq_ctrl[0]++;
2265
2266 ieee->softmac_data_hard_start_xmit(skb,ieee->dev,ieee->basic_rate);
2267 //dev_kfree_skb_any(skb);//edit by thomas
2268 }
2269 }
2270 if (!ieee->queue_stop && ieee->tx_pending.txb)
2271 ieee80211_resume_tx(ieee);
2272
f53cb7b1 2273 if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
8fc8598e
JC
2274 ieee->softmac_stats.swtxawake++;
2275 netif_wake_queue(ieee->dev);
2276 }
2277
2278exit :
0b4ef0a6 2279 spin_unlock_irqrestore(&ieee->lock, flags);
8fc8598e 2280}
539b4f72 2281EXPORT_SYMBOL(ieee80211_wake_queue);
8fc8598e
JC
2282
2283void ieee80211_stop_queue(struct ieee80211_device *ieee)
2284{
2285 //unsigned long flags;
2286 //spin_lock_irqsave(&ieee->lock,flags);
2287
f53cb7b1 2288 if (!netif_queue_stopped(ieee->dev)) {
8fc8598e
JC
2289 netif_stop_queue(ieee->dev);
2290 ieee->softmac_stats.swtxstop++;
2291 }
2292 ieee->queue_stop = 1;
2293 //spin_unlock_irqrestore(&ieee->lock,flags);
2294
2295}
539b4f72 2296EXPORT_SYMBOL(ieee80211_stop_queue);
8fc8598e 2297
8fc8598e
JC
2298/* called in user context only */
2299void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2300{
2301 ieee->assoc_id = 1;
2302
f53cb7b1 2303 if (ieee->current_network.ssid_len == 0) {
8fc8598e
JC
2304 strncpy(ieee->current_network.ssid,
2305 IEEE80211_DEFAULT_TX_ESSID,
2306 IW_ESSID_MAX_SIZE);
2307
2308 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2309 ieee->ssid_set = 1;
2310 }
2311
2312 memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2313
2314 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2315 ieee->state = IEEE80211_LINKED;
2316 ieee->link_change(ieee->dev);
2317 notify_wx_assoc_event(ieee);
2318
2319 if (ieee->data_hard_resume)
2320 ieee->data_hard_resume(ieee->dev);
2321
2322 netif_carrier_on(ieee->dev);
2323}
2324
fabdbdb2 2325static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
8fc8598e 2326{
f53cb7b1 2327 if (ieee->raw_tx) {
8fc8598e
JC
2328
2329 if (ieee->data_hard_resume)
2330 ieee->data_hard_resume(ieee->dev);
2331
2332 netif_carrier_on(ieee->dev);
2333 }
2334}
fabdbdb2 2335static void ieee80211_start_ibss_wq(struct work_struct *work)
8fc8598e
JC
2336{
2337
a5959f3f 2338 struct delayed_work *dwork = to_delayed_work(work);
e406322b 2339 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
8fc8598e
JC
2340 /* iwconfig mode ad-hoc will schedule this and return
2341 * on the other hand this will block further iwconfig SET
e379a9a8 2342 * operations because of the wx_mutex hold.
8fc8598e
JC
2343 * Anyway some most set operations set a flag to speed-up
2344 * (abort) this wq (when syncro scanning) before sleeping
2345 * on the semaphore
2346 */
f53cb7b1 2347 if (!ieee->proto_started) {
8fc8598e
JC
2348 printk("==========oh driver down return\n");
2349 return;
2350 }
e379a9a8 2351 mutex_lock(&ieee->wx_mutex);
8fc8598e 2352
f53cb7b1 2353 if (ieee->current_network.ssid_len == 0) {
0b4ef0a6 2354 strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
8fc8598e
JC
2355 ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2356 ieee->ssid_set = 1;
2357 }
2358
2359 /* check if we have this cell in our network list */
2360 ieee80211_softmac_check_all_nets(ieee);
2361
2362
8fc8598e
JC
2363// if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2364 if (ieee->state == IEEE80211_NOLINK)
2365 ieee->current_network.channel = 6;
c6efb58d 2366 /* if not then the state is not linked. Maybe the user switched to
8fc8598e
JC
2367 * ad-hoc mode just after being in monitor mode, or just after
2368 * being very few time in managed mode (so the card have had no
2369 * time to scan all the chans..) or we have just run up the iface
2370 * after setting ad-hoc mode. So we have to give another try..
2371 * Here, in ibss mode, should be safe to do this without extra care
2372 * (in bss mode we had to make sure no-one tryed to associate when
2373 * we had just checked the ieee->state and we was going to start the
2374 * scan) beacause in ibss mode the ieee80211_new_net function, when
2375 * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2376 * so, at worst, we waste a bit of time to initiate an unneeded syncro
2377 * scan, that will stop at the first round because it sees the state
2378 * associated.
2379 */
2380 if (ieee->state == IEEE80211_NOLINK)
2381 ieee80211_start_scan_syncro(ieee);
2382
2383 /* the network definitively is not here.. create a new cell */
f53cb7b1 2384 if (ieee->state == IEEE80211_NOLINK) {
8fc8598e
JC
2385 printk("creating new IBSS cell\n");
2386 if(!ieee->wap_set)
0834ffac 2387 random_ether_addr(ieee->current_network.bssid);
8fc8598e
JC
2388
2389 if(ieee->modulation & IEEE80211_CCK_MODULATION){
2390
2391 ieee->current_network.rates_len = 4;
2392
2393 ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2394 ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2395 ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2396 ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2397
2398 }else
2399 ieee->current_network.rates_len = 0;
2400
2401 if(ieee->modulation & IEEE80211_OFDM_MODULATION){
2402 ieee->current_network.rates_ex_len = 8;
2403
2404 ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2405 ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2406 ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2407 ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2408 ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2409 ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2410 ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2411 ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2412
2413 ieee->rate = 108;
2414 }else{
2415 ieee->current_network.rates_ex_len = 0;
2416 ieee->rate = 22;
2417 }
2418
2419 // By default, WMM function will be disabled in IBSS mode
2420 ieee->current_network.QoS_Enable = 0;
2421 ieee->SetWirelessMode(ieee->dev, IEEE_G);
2422 ieee->current_network.atim_window = 0;
2423 ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2424 if(ieee->short_slot)
2425 ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2426
2427 }
2428
2429 ieee->state = IEEE80211_LINKED;
2430
2431 ieee->set_chan(ieee->dev, ieee->current_network.channel);
2432 ieee->link_change(ieee->dev);
2433
2434 notify_wx_assoc_event(ieee);
2435
2436 ieee80211_start_send_beacons(ieee);
2437
2438 if (ieee->data_hard_resume)
2439 ieee->data_hard_resume(ieee->dev);
2440 netif_carrier_on(ieee->dev);
2441
e379a9a8 2442 mutex_unlock(&ieee->wx_mutex);
8fc8598e
JC
2443}
2444
2445inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2446{
1761a85c 2447 schedule_delayed_work(&ieee->start_ibss_wq, 150);
8fc8598e
JC
2448}
2449
e379a9a8 2450/* this is called only in user context, with wx_mutex held */
8fc8598e
JC
2451void ieee80211_start_bss(struct ieee80211_device *ieee)
2452{
2453 unsigned long flags;
8fc8598e
JC
2454 //
2455 // Ref: 802.11d 11.1.3.3
2456 // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2457 //
dde48b99 2458 if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee))
8fc8598e 2459 {
dde48b99 2460 if (! ieee->bGlobalDomain)
8fc8598e
JC
2461 {
2462 return;
2463 }
2464 }
8fc8598e
JC
2465 /* check if we have already found the net we
2466 * are interested in (if any).
2467 * if not (we are disassociated and we are not
2468 * in associating / authenticating phase) start the background scanning.
2469 */
2470 ieee80211_softmac_check_all_nets(ieee);
2471
2472 /* ensure no-one start an associating process (thus setting
2473 * the ieee->state to ieee80211_ASSOCIATING) while we
2474 * have just cheked it and we are going to enable scan.
2475 * The ieee80211_new_net function is always called with
2476 * lock held (from both ieee80211_softmac_check_all_nets and
2477 * the rx path), so we cannot be in the middle of such function
2478 */
2479 spin_lock_irqsave(&ieee->lock, flags);
2480
f53cb7b1 2481 if (ieee->state == IEEE80211_NOLINK) {
8fc8598e
JC
2482 ieee->actscanning = true;
2483 ieee80211_start_scan(ieee);
2484 }
2485 spin_unlock_irqrestore(&ieee->lock, flags);
2486}
2487
2488/* called only in userspace context */
2489void ieee80211_disassociate(struct ieee80211_device *ieee)
2490{
2491
2492
2493 netif_carrier_off(ieee->dev);
2494 if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2495 ieee80211_reset_queue(ieee);
2496
2497 if (ieee->data_hard_stop)
2498 ieee->data_hard_stop(ieee->dev);
8fc8598e
JC
2499 if(IS_DOT11D_ENABLE(ieee))
2500 Dot11d_Reset(ieee);
8fc8598e
JC
2501 ieee->state = IEEE80211_NOLINK;
2502 ieee->is_set_key = false;
2503 ieee->link_change(ieee->dev);
2504 //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2505 notify_wx_assoc_event(ieee);
2506
2507}
539b4f72
BT
2508EXPORT_SYMBOL(ieee80211_disassociate);
2509
fabdbdb2 2510static void ieee80211_associate_retry_wq(struct work_struct *work)
8fc8598e 2511{
a5959f3f 2512 struct delayed_work *dwork = to_delayed_work(work);
fdc64a9e 2513 struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
8fc8598e
JC
2514 unsigned long flags;
2515
e379a9a8 2516 mutex_lock(&ieee->wx_mutex);
8fc8598e
JC
2517 if(!ieee->proto_started)
2518 goto exit;
2519
2520 if(ieee->state != IEEE80211_ASSOCIATING_RETRY)
2521 goto exit;
2522
2523 /* until we do not set the state to IEEE80211_NOLINK
2524 * there are no possibility to have someone else trying
935d59ff 2525 * to start an association procedure (we get here with
8fc8598e
JC
2526 * ieee->state = IEEE80211_ASSOCIATING).
2527 * When we set the state to IEEE80211_NOLINK it is possible
2528 * that the RX path run an attempt to associate, but
2529 * both ieee80211_softmac_check_all_nets and the
2530 * RX path works with ieee->lock held so there are no
2531 * problems. If we are still disassociated then start a scan.
2532 * the lock here is necessary to ensure no one try to start
2533 * an association procedure when we have just checked the
2534 * state and we are going to start the scan.
2535 */
2536 ieee->state = IEEE80211_NOLINK;
2537
2538 ieee80211_softmac_check_all_nets(ieee);
2539
2540 spin_lock_irqsave(&ieee->lock, flags);
2541
2542 if(ieee->state == IEEE80211_NOLINK)
2543 ieee80211_start_scan(ieee);
2544
2545 spin_unlock_irqrestore(&ieee->lock, flags);
2546
2547exit:
e379a9a8 2548 mutex_unlock(&ieee->wx_mutex);
8fc8598e
JC
2549}
2550
2551struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2552{
0b4ef0a6 2553 u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
8fc8598e
JC
2554
2555 struct sk_buff *skb;
2556 struct ieee80211_probe_response *b;
2557
2558 skb = ieee80211_probe_resp(ieee, broadcast_addr);
2559
2560 if (!skb)
2561 return NULL;
2562
2563 b = (struct ieee80211_probe_response *) skb->data;
2564 b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2565
2566 return skb;
2567
2568}
2569
2570struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2571{
2572 struct sk_buff *skb;
2573 struct ieee80211_probe_response *b;
2574
2575 skb = ieee80211_get_beacon_(ieee);
2576 if(!skb)
2577 return NULL;
2578
2579 b = (struct ieee80211_probe_response *) skb->data;
2580 b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2581
2582 if (ieee->seq_ctrl[0] == 0xFFF)
2583 ieee->seq_ctrl[0] = 0;
2584 else
2585 ieee->seq_ctrl[0]++;
2586
2587 return skb;
2588}
539b4f72 2589EXPORT_SYMBOL(ieee80211_get_beacon);
8fc8598e
JC
2590
2591void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2592{
2593 ieee->sync_scan_hurryup = 1;
e379a9a8 2594 mutex_lock(&ieee->wx_mutex);
8fc8598e 2595 ieee80211_stop_protocol(ieee);
e379a9a8 2596 mutex_unlock(&ieee->wx_mutex);
8fc8598e 2597}
539b4f72 2598EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
8fc8598e
JC
2599
2600void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2601{
2602 if (!ieee->proto_started)
2603 return;
2604
2605 ieee->proto_started = 0;
2606
2607 ieee80211_stop_send_beacons(ieee);
2608 del_timer_sync(&ieee->associate_timer);
8fc8598e
JC
2609 cancel_delayed_work(&ieee->associate_retry_wq);
2610 cancel_delayed_work(&ieee->start_ibss_wq);
8fc8598e
JC
2611 ieee80211_stop_scan(ieee);
2612
2613 ieee80211_disassociate(ieee);
2614 RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2615}
2616
2617void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2618{
2619 ieee->sync_scan_hurryup = 0;
e379a9a8 2620 mutex_lock(&ieee->wx_mutex);
8fc8598e 2621 ieee80211_start_protocol(ieee);
e379a9a8 2622 mutex_unlock(&ieee->wx_mutex);
8fc8598e 2623}
539b4f72 2624EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
8fc8598e
JC
2625
2626void ieee80211_start_protocol(struct ieee80211_device *ieee)
2627{
2628 short ch = 0;
e406322b 2629 int i = 0;
360daa82 2630
8fc8598e
JC
2631 if (ieee->proto_started)
2632 return;
2633
2634 ieee->proto_started = 1;
2635
f53cb7b1 2636 if (ieee->current_network.channel == 0) {
8fc8598e
JC
2637 do{
2638 ch++;
2639 if (ch > MAX_CHANNEL_NUMBER)
2640 return; /* no channel found */
8fc8598e 2641 }while(!GET_DOT11D_INFO(ieee)->channel_map[ch]);
8fc8598e
JC
2642 ieee->current_network.channel = ch;
2643 }
2644
2645 if (ieee->current_network.beacon_interval == 0)
2646 ieee->current_network.beacon_interval = 100;
f8628a47 2647// printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
8fc8598e
JC
2648// ieee->set_chan(ieee->dev,ieee->current_network.channel);
2649
e406322b 2650 for(i = 0; i < 17; i++) {
8fc8598e
JC
2651 ieee->last_rxseq_num[i] = -1;
2652 ieee->last_rxfrag_num[i] = -1;
2653 ieee->last_packet_time[i] = 0;
2654 }
2655
2656 ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2657
2658
2659 /* if the user set the MAC of the ad-hoc cell and then
2660 * switch to managed mode, shall we make sure that association
2661 * attempts does not fail just because the user provide the essid
2662 * and the nic is still checking for the AP MAC ??
2663 */
2664 if (ieee->iw_mode == IW_MODE_INFRA)
2665 ieee80211_start_bss(ieee);
2666
2667 else if (ieee->iw_mode == IW_MODE_ADHOC)
2668 ieee80211_start_ibss(ieee);
2669
2670 else if (ieee->iw_mode == IW_MODE_MASTER)
2671 ieee80211_start_master_bss(ieee);
2672
2673 else if(ieee->iw_mode == IW_MODE_MONITOR)
2674 ieee80211_start_monitor_mode(ieee);
2675}
2676
2677
2678#define DRV_NAME "Ieee80211"
2679void ieee80211_softmac_init(struct ieee80211_device *ieee)
2680{
2681 int i;
2682 memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2683
2684 ieee->state = IEEE80211_NOLINK;
2685 ieee->sync_scan_hurryup = 0;
2686 for(i = 0; i < 5; i++) {
2687 ieee->seq_ctrl[i] = 0;
2688 }
7a6cb0d5 2689 ieee->pDot11dInfo = kzalloc(sizeof(RT_DOT11D_INFO), GFP_ATOMIC);
8fc8598e
JC
2690 if (!ieee->pDot11dInfo)
2691 IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
8fc8598e
JC
2692 //added for AP roaming
2693 ieee->LinkDetectInfo.SlotNum = 2;
2694 ieee->LinkDetectInfo.NumRecvBcnInPeriod=0;
e406322b 2695 ieee->LinkDetectInfo.NumRecvDataInPeriod=0;
8fc8598e
JC
2696
2697 ieee->assoc_id = 0;
2698 ieee->queue_stop = 0;
2699 ieee->scanning = 0;
2700 ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2701 ieee->wap_set = 0;
2702 ieee->ssid_set = 0;
2703 ieee->proto_started = 0;
2704 ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2705 ieee->rate = 22;
2706 ieee->ps = IEEE80211_PS_DISABLED;
2707 ieee->sta_sleep = 0;
2708 ieee->Regdot11HTOperationalRateSet[0]= 0xff;//support MCS 0~7
2709 ieee->Regdot11HTOperationalRateSet[1]= 0xff;//support MCS 8~15
2710 ieee->Regdot11HTOperationalRateSet[4]= 0x01;
2711 //added by amy
2712 ieee->actscanning = false;
2713 ieee->beinretry = false;
2714 ieee->is_set_key = false;
2715 init_mgmt_queue(ieee);
2716
2717 ieee->sta_edca_param[0] = 0x0000A403;
2718 ieee->sta_edca_param[1] = 0x0000A427;
2719 ieee->sta_edca_param[2] = 0x005E4342;
2720 ieee->sta_edca_param[3] = 0x002F3262;
2721 ieee->aggregation = true;
19cd2297 2722 ieee->enable_rx_imm_BA = true;
8fc8598e
JC
2723 ieee->tx_pending.txb = NULL;
2724
4fde58bb
AM
2725 setup_timer(&ieee->associate_timer, ieee80211_associate_abort_cb,
2726 (unsigned long)ieee);
8fc8598e 2727
4fde58bb
AM
2728 setup_timer(&ieee->beacon_timer, ieee80211_send_beacon_cb,
2729 (unsigned long)ieee);
8fc8598e 2730
8fc8598e 2731
0b4ef0a6 2732 INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
e406322b
MCC
2733 INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2734 INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
0b4ef0a6 2735 INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
e406322b 2736 INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
0b4ef0a6 2737 INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
8fc8598e 2738
8fc8598e 2739
e379a9a8 2740 mutex_init(&ieee->wx_mutex);
87d63bcc 2741 mutex_init(&ieee->scan_mutex);
8fc8598e
JC
2742
2743 spin_lock_init(&ieee->mgmt_tx_lock);
2744 spin_lock_init(&ieee->beacon_lock);
2745
2746 tasklet_init(&ieee->ps_task,
2747 (void(*)(unsigned long)) ieee80211_sta_ps,
2748 (unsigned long)ieee);
2749
2750}
2751
2752void ieee80211_softmac_free(struct ieee80211_device *ieee)
2753{
e379a9a8 2754 mutex_lock(&ieee->wx_mutex);
e72714fb
IM
2755 kfree(ieee->pDot11dInfo);
2756 ieee->pDot11dInfo = NULL;
8fc8598e
JC
2757 del_timer_sync(&ieee->associate_timer);
2758
8fc8598e 2759 cancel_delayed_work(&ieee->associate_retry_wq);
8fc8598e 2760
e379a9a8 2761 mutex_unlock(&ieee->wx_mutex);
8fc8598e
JC
2762}
2763
2764/********************************************************
2765 * Start of WPA code. *
2766 * this is stolen from the ipw2200 driver *
2767 ********************************************************/
2768
2769
2770static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2771{
2772 /* This is called when wpa_supplicant loads and closes the driver
2773 * interface. */
3e99c2d2 2774 printk("%s WPA\n", value ? "enabling" : "disabling");
8fc8598e
JC
2775 ieee->wpa_enabled = value;
2776 return 0;
2777}
2778
2779
fabdbdb2
AR
2780static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2781 char *wpa_ie, int wpa_ie_len)
8fc8598e
JC
2782{
2783 /* make sure WPA is enabled */
2784 ieee80211_wpa_enable(ieee, 1);
2785
2786 ieee80211_disassociate(ieee);
2787}
2788
2789
2790static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2791{
2792
2793 int ret = 0;
2794
2795 switch (command) {
2796 case IEEE_MLME_STA_DEAUTH:
2797 // silently ignore
2798 break;
2799
2800 case IEEE_MLME_STA_DISASSOC:
2801 ieee80211_disassociate(ieee);
2802 break;
2803
2804 default:
2805 printk("Unknown MLME request: %d\n", command);
2806 ret = -EOPNOTSUPP;
2807 }
2808
2809 return ret;
2810}
2811
2812
2813static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2814 struct ieee_param *param, int plen)
2815{
2816 u8 *buf;
2817
2818 if (param->u.wpa_ie.len > MAX_WPA_IE_LEN ||
2819 (param->u.wpa_ie.len && param->u.wpa_ie.data == NULL))
2820 return -EINVAL;
2821
2822 if (param->u.wpa_ie.len) {
94002c07
JL
2823 buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2824 GFP_KERNEL);
8fc8598e
JC
2825 if (buf == NULL)
2826 return -ENOMEM;
2827
8fc8598e
JC
2828 kfree(ieee->wpa_ie);
2829 ieee->wpa_ie = buf;
2830 ieee->wpa_ie_len = param->u.wpa_ie.len;
2831 } else {
2832 kfree(ieee->wpa_ie);
2833 ieee->wpa_ie = NULL;
2834 ieee->wpa_ie_len = 0;
2835 }
2836
2837 ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2838 return 0;
2839}
2840
2841#define AUTH_ALG_OPEN_SYSTEM 0x1
2842#define AUTH_ALG_SHARED_KEY 0x2
2843
2844static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2845{
2846
2847 struct ieee80211_security sec = {
2848 .flags = SEC_AUTH_MODE,
2849 };
8fc8598e
JC
2850
2851 if (value & AUTH_ALG_SHARED_KEY) {
2852 sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2853 ieee->open_wep = 0;
2854 ieee->auth_mode = 1;
2855 } else if (value & AUTH_ALG_OPEN_SYSTEM){
2856 sec.auth_mode = WLAN_AUTH_OPEN;
2857 ieee->open_wep = 1;
2858 ieee->auth_mode = 0;
2859 }
2860 else if (value & IW_AUTH_ALG_LEAP){
2861 sec.auth_mode = WLAN_AUTH_LEAP;
2862 ieee->open_wep = 1;
2863 ieee->auth_mode = 2;
2864 }
2865
2866
2867 if (ieee->set_security)
2868 ieee->set_security(ieee->dev, &sec);
2869 //else
2870 // ret = -EOPNOTSUPP;
2871
4764ca98 2872 return 0;
8fc8598e
JC
2873}
2874
2875static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2876{
fa687e73 2877 int ret = 0;
8fc8598e
JC
2878 unsigned long flags;
2879
2880 switch (name) {
2881 case IEEE_PARAM_WPA_ENABLED:
2882 ret = ieee80211_wpa_enable(ieee, value);
2883 break;
2884
2885 case IEEE_PARAM_TKIP_COUNTERMEASURES:
fa687e73 2886 ieee->tkip_countermeasures = value;
8fc8598e
JC
2887 break;
2888
2889 case IEEE_PARAM_DROP_UNENCRYPTED: {
2890 /* HACK:
2891 *
2892 * wpa_supplicant calls set_wpa_enabled when the driver
2893 * is loaded and unloaded, regardless of if WPA is being
2894 * used. No other calls are made which can be used to
2895 * determine if encryption will be used or not prior to
2896 * association being expected. If encryption is not being
2897 * used, drop_unencrypted is set to false, else true -- we
2898 * can use this to determine if the CAP_PRIVACY_ON bit should
2899 * be set.
2900 */
2901 struct ieee80211_security sec = {
2902 .flags = SEC_ENABLED,
2903 .enabled = value,
2904 };
e406322b 2905 ieee->drop_unencrypted = value;
8fc8598e
JC
2906 /* We only change SEC_LEVEL for open mode. Others
2907 * are set by ipw_wpa_set_encryption.
2908 */
2909 if (!value) {
2910 sec.flags |= SEC_LEVEL;
2911 sec.level = SEC_LEVEL_0;
2912 }
2913 else {
2914 sec.flags |= SEC_LEVEL;
2915 sec.level = SEC_LEVEL_1;
2916 }
2917 if (ieee->set_security)
2918 ieee->set_security(ieee->dev, &sec);
2919 break;
2920 }
2921
2922 case IEEE_PARAM_PRIVACY_INVOKED:
fa687e73 2923 ieee->privacy_invoked = value;
8fc8598e
JC
2924 break;
2925
2926 case IEEE_PARAM_AUTH_ALGS:
2927 ret = ieee80211_wpa_set_auth_algs(ieee, value);
2928 break;
2929
2930 case IEEE_PARAM_IEEE_802_1X:
fa687e73 2931 ieee->ieee802_1x = value;
8fc8598e
JC
2932 break;
2933 case IEEE_PARAM_WPAX_SELECT:
2934 // added for WPA2 mixed mode
0b4ef0a6 2935 spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
8fc8598e
JC
2936 ieee->wpax_type_set = 1;
2937 ieee->wpax_type_notify = value;
0b4ef0a6 2938 spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
8fc8598e
JC
2939 break;
2940
2941 default:
3e99c2d2 2942 printk("Unknown WPA param: %d\n", name);
8fc8598e
JC
2943 ret = -EOPNOTSUPP;
2944 }
2945
2946 return ret;
2947}
2948
2949/* implementation borrowed from hostap driver */
2950
2951static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2952 struct ieee_param *param, int param_len)
2953{
2954 int ret = 0;
2955
2956 struct ieee80211_crypto_ops *ops;
2957 struct ieee80211_crypt_data **crypt;
2958
2959 struct ieee80211_security sec = {
2960 .flags = 0,
2961 };
2962
2963 param->u.crypt.err = 0;
2964 param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2965
2966 if (param_len !=
2967 (int) ((char *) param->u.crypt.key - (char *) param) +
2968 param->u.crypt.key_len) {
2969 printk("Len mismatch %d, %d\n", param_len,
2970 param->u.crypt.key_len);
2971 return -EINVAL;
2972 }
8cfbc9dc 2973 if (is_broadcast_ether_addr(param->sta_addr)) {
8fc8598e
JC
2974 if (param->u.crypt.idx >= WEP_KEYS)
2975 return -EINVAL;
2976 crypt = &ieee->crypt[param->u.crypt.idx];
2977 } else {
2978 return -EINVAL;
2979 }
2980
2981 if (strcmp(param->u.crypt.alg, "none") == 0) {
2982 if (crypt) {
2983 sec.enabled = 0;
2984 // FIXME FIXME
2985 //sec.encrypt = 0;
2986 sec.level = SEC_LEVEL_0;
2987 sec.flags |= SEC_ENABLED | SEC_LEVEL;
2988 ieee80211_crypt_delayed_deinit(ieee, crypt);
2989 }
2990 goto done;
2991 }
2992 sec.enabled = 1;
2993// FIXME FIXME
2994// sec.encrypt = 1;
2995 sec.flags |= SEC_ENABLED;
2996
2997 /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2998 if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2999 strcmp(param->u.crypt.alg, "TKIP"))
3000 goto skip_host_crypt;
3001
3002 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3003 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
3004 request_module("ieee80211_crypt_wep");
3005 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3006 //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
3007 } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
3008 request_module("ieee80211_crypt_tkip");
3009 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3010 } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
3011 request_module("ieee80211_crypt_ccmp");
3012 ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
3013 }
3014 if (ops == NULL) {
3015 printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
3016 param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
3017 ret = -EINVAL;
3018 goto done;
3019 }
3020
3021 if (*crypt == NULL || (*crypt)->ops != ops) {
3022 struct ieee80211_crypt_data *new_crypt;
3023
3024 ieee80211_crypt_delayed_deinit(ieee, crypt);
3025
a774fe09 3026 new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
3956c8ac 3027 if (!new_crypt) {
8fc8598e
JC
3028 ret = -ENOMEM;
3029 goto done;
3030 }
8fc8598e 3031 new_crypt->ops = ops;
8fc8598e 3032 if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
8fc8598e
JC
3033 new_crypt->priv =
3034 new_crypt->ops->init(param->u.crypt.idx);
3035
3036 if (new_crypt->priv == NULL) {
3037 kfree(new_crypt);
3038 param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
3039 ret = -EINVAL;
3040 goto done;
3041 }
3042
3043 *crypt = new_crypt;
3044 }
3045
3046 if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
3047 (*crypt)->ops->set_key(param->u.crypt.key,
3048 param->u.crypt.key_len, param->u.crypt.seq,
3049 (*crypt)->priv) < 0) {
3050 printk("key setting failed\n");
3051 param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
3052 ret = -EINVAL;
3053 goto done;
3054 }
3055
3056 skip_host_crypt:
3057 if (param->u.crypt.set_tx) {
3058 ieee->tx_keyidx = param->u.crypt.idx;
3059 sec.active_key = param->u.crypt.idx;
3060 sec.flags |= SEC_ACTIVE_KEY;
3061 } else
3062 sec.flags &= ~SEC_ACTIVE_KEY;
3063
0840ff76
CIK
3064 memcpy(sec.keys[param->u.crypt.idx],
3065 param->u.crypt.key,
3066 param->u.crypt.key_len);
3067 sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
3068 sec.flags |= (1 << param->u.crypt.idx);
3069
3070 if (strcmp(param->u.crypt.alg, "WEP") == 0) {
3071 sec.flags |= SEC_LEVEL;
3072 sec.level = SEC_LEVEL_1;
3073 } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
3074 sec.flags |= SEC_LEVEL;
3075 sec.level = SEC_LEVEL_2;
3076 } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
3077 sec.flags |= SEC_LEVEL;
3078 sec.level = SEC_LEVEL_3;
8fc8598e
JC
3079 }
3080 done:
3081 if (ieee->set_security)
3082 ieee->set_security(ieee->dev, &sec);
3083
3084 /* Do not reset port if card is in Managed mode since resetting will
3085 * generate new IEEE 802.11 authentication which may end up in looping
3086 * with IEEE 802.1X. If your hardware requires a reset after WEP
3087 * configuration (for example... Prism2), implement the reset_port in
3088 * the callbacks structures used to initialize the 802.11 stack. */
3089 if (ieee->reset_on_keychange &&
3090 ieee->iw_mode != IW_MODE_INFRA &&
3091 ieee->reset_port &&
3092 ieee->reset_port(ieee->dev)) {
3093 printk("reset_port failed\n");
3094 param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
3095 return -EINVAL;
3096 }
3097
3098 return ret;
3099}
3100
3590e78a 3101static inline struct sk_buff *ieee80211_disassociate_skb(
8fc8598e
JC
3102 struct ieee80211_network *beacon,
3103 struct ieee80211_device *ieee,
3104 u8 asRsn)
3105{
3106 struct sk_buff *skb;
3107 struct ieee80211_disassoc *disass;
3108
3109 skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
3110 if (!skb)
3111 return NULL;
3112
3e99c2d2 3113 disass = (struct ieee80211_disassoc *) skb_put(skb, sizeof(struct ieee80211_disassoc));
8fc8598e
JC
3114 disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
3115 disass->header.duration_id = 0;
3116
3117 memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
3118 memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
3119 memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
3120
25e2704c 3121 disass->reason = cpu_to_le16(asRsn);
8fc8598e
JC
3122 return skb;
3123}
3124
3125
3126void
3127SendDisassociation(
3128 struct ieee80211_device *ieee,
2639ae97 3129 u8 *asSta,
8fc8598e
JC
3130 u8 asRsn
3131)
3132{
3133 struct ieee80211_network *beacon = &ieee->current_network;
3134 struct sk_buff *skb;
360daa82 3135
3e99c2d2 3136 skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
f53cb7b1 3137 if (skb) {
8fc8598e
JC
3138 softmac_mgmt_xmit(skb, ieee);
3139 //dev_kfree_skb_any(skb);//edit by thomas
3140 }
3141}
539b4f72 3142EXPORT_SYMBOL(SendDisassociation);
8fc8598e
JC
3143
3144int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
3145{
3146 struct ieee_param *param;
d0f619b2 3147 int ret = 0;
8fc8598e 3148
e379a9a8 3149 mutex_lock(&ieee->wx_mutex);
8fc8598e
JC
3150 //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
3151
f53cb7b1 3152 if (p->length < sizeof(struct ieee_param) || !p->pointer) {
8fc8598e
JC
3153 ret = -EINVAL;
3154 goto out;
3155 }
3156
38272d20
TB
3157 param = memdup_user(p->pointer, p->length);
3158 if (IS_ERR(param)) {
3159 ret = PTR_ERR(param);
8fc8598e
JC
3160 goto out;
3161 }
3162
3163 switch (param->cmd) {
3164
3165 case IEEE_CMD_SET_WPA_PARAM:
3166 ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3167 param->u.wpa_param.value);
3168 break;
3169
3170 case IEEE_CMD_SET_WPA_IE:
3171 ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3172 break;
3173
3174 case IEEE_CMD_SET_ENCRYPTION:
3175 ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3176 break;
3177
3178 case IEEE_CMD_MLME:
3179 ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3180 param->u.mlme.reason_code);
3181 break;
3182
3183 default:
3184 printk("Unknown WPA supplicant request: %d\n",param->cmd);
3185 ret = -EOPNOTSUPP;
3186 break;
3187 }
3188
3189 if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3190 ret = -EFAULT;
3191
3192 kfree(param);
3193out:
e379a9a8 3194 mutex_unlock(&ieee->wx_mutex);
8fc8598e
JC
3195
3196 return ret;
3197}
539b4f72 3198EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
8fc8598e
JC
3199
3200void notify_wx_assoc_event(struct ieee80211_device *ieee)
3201{
3202 union iwreq_data wrqu;
360daa82 3203
8fc8598e
JC
3204 wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3205 if (ieee->state == IEEE80211_LINKED)
3206 memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3207 else
21f5690e 3208 eth_zero_addr(wrqu.ap_addr.sa_data);
8fc8598e
JC
3209 wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3210}
8fc8598e 3211EXPORT_SYMBOL(notify_wx_assoc_event);