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