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