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