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