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