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