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