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