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