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