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