~ubuntu-branches/ubuntu/saucy/linux-n900/saucy

« back to all changes in this revision

Viewing changes to drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Poirier
  • Date: 2011-02-18 09:43:31 UTC
  • Revision ID: james.westby@ubuntu.com-20110218094331-eyubsja4f9k0yhmq
Tags: 2.6.35-1.1
Initial release.

Show diffs side-by-side

added added

removed removed

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