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        netdev_alert(ieee->dev, "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        if (encrypt)
 747                beacon_buf->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 748
 749        beacon_buf->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_RESP);
 750        beacon_buf->info_element[0].id = MFIE_TYPE_SSID;
 751        beacon_buf->info_element[0].len = ssid_len;
 752
 753        tag = (u8 *)beacon_buf->info_element[0].data;
 754
 755        memcpy(tag, ssid, ssid_len);
 756
 757        tag += ssid_len;
 758
 759        *(tag++) = MFIE_TYPE_RATES;
 760        *(tag++) = rate_len - 2;
 761        memcpy(tag, ieee->current_network.rates, rate_len - 2);
 762        tag += rate_len - 2;
 763
 764        *(tag++) = MFIE_TYPE_DS_SET;
 765        *(tag++) = 1;
 766        *(tag++) = ieee->current_network.channel;
 767
 768        if (atim_len) {
 769                *(tag++) = MFIE_TYPE_IBSS_SET;
 770                *(tag++) = 2;
 771
 772                put_unaligned_le16(ieee->current_network.atim_window,
 773                                   tag);
 774                tag += 2;
 775        }
 776
 777        if (erp_len) {
 778                *(tag++) = MFIE_TYPE_ERP;
 779                *(tag++) = 1;
 780                *(tag++) = erpinfo_content;
 781        }
 782        if (rate_ex_len) {
 783                *(tag++) = MFIE_TYPE_RATES_EX;
 784                *(tag++) = rate_ex_len - 2;
 785                memcpy(tag, ieee->current_network.rates_ex, rate_ex_len - 2);
 786                tag += rate_ex_len - 2;
 787        }
 788
 789        if (wpa_ie_len) {
 790                if (ieee->iw_mode == IW_MODE_ADHOC) {
 791                        //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
 792                        memcpy(&ieee->wpa_ie[14], &ieee->wpa_ie[8], 4);
 793                }
 794                memcpy(tag, ieee->wpa_ie, ieee->wpa_ie_len);
 795                tag += wpa_ie_len;
 796        }
 797
 798        //skb->dev = ieee->dev;
 799        return skb;
 800}
 801
 802static struct sk_buff *ieee80211_assoc_resp(struct ieee80211_device *ieee,
 803                                            u8 *dest)
 804{
 805        struct sk_buff *skb;
 806        u8 *tag;
 807
 808        struct ieee80211_crypt_data *crypt;
 809        struct ieee80211_assoc_response_frame *assoc;
 810        short encrypt;
 811
 812        unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
 813        int len = sizeof(struct ieee80211_assoc_response_frame) + rate_len + ieee->tx_headroom;
 814
 815        skb = dev_alloc_skb(len);
 816
 817        if (!skb)
 818                return NULL;
 819
 820        skb_reserve(skb, ieee->tx_headroom);
 821
 822        assoc = skb_put(skb, sizeof(struct ieee80211_assoc_response_frame));
 823
 824        assoc->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP);
 825        memcpy(assoc->header.addr1, dest, ETH_ALEN);
 826        memcpy(assoc->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
 827        memcpy(assoc->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 828        assoc->capability = cpu_to_le16(ieee->iw_mode == IW_MODE_MASTER ?
 829                WLAN_CAPABILITY_BSS : WLAN_CAPABILITY_IBSS);
 830
 831        if (ieee->short_slot)
 832                assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
 833
 834        if (ieee->host_encrypt)
 835                crypt = ieee->crypt[ieee->tx_keyidx];
 836        else
 837                crypt = NULL;
 838
 839        encrypt = crypt && crypt->ops;
 840
 841        if (encrypt)
 842                assoc->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
 843
 844        assoc->status = 0;
 845        assoc->aid = cpu_to_le16(ieee->assoc_id);
 846        if (ieee->assoc_id == 0x2007)
 847                ieee->assoc_id = 0;
 848        else
 849                ieee->assoc_id++;
 850
 851        tag = skb_put(skb, rate_len);
 852
 853        ieee80211_MFIE_Brate(ieee, &tag);
 854        ieee80211_MFIE_Grate(ieee, &tag);
 855
 856        return skb;
 857}
 858
 859static struct sk_buff *ieee80211_auth_resp(struct ieee80211_device *ieee,
 860                                           int status, u8 *dest)
 861{
 862        struct sk_buff *skb;
 863        struct ieee80211_authentication *auth;
 864        int len = ieee->tx_headroom + sizeof(struct ieee80211_authentication) + 1;
 865
 866        skb = dev_alloc_skb(len);
 867
 868        if (!skb)
 869                return NULL;
 870
 871        skb->len = sizeof(struct ieee80211_authentication);
 872
 873        auth = (struct ieee80211_authentication *)skb->data;
 874
 875        auth->status = cpu_to_le16(status);
 876        auth->transaction = cpu_to_le16(2);
 877        auth->algorithm = cpu_to_le16(WLAN_AUTH_OPEN);
 878
 879        memcpy(auth->header.addr3, ieee->dev->dev_addr, ETH_ALEN);
 880        memcpy(auth->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
 881        memcpy(auth->header.addr1, dest, ETH_ALEN);
 882        auth->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_AUTH);
 883        return skb;
 884}
 885
 886static struct sk_buff *ieee80211_null_func(struct ieee80211_device *ieee,
 887                                           short pwr)
 888{
 889        struct sk_buff *skb;
 890        struct rtl_80211_hdr_3addr *hdr;
 891
 892        skb = dev_alloc_skb(sizeof(struct rtl_80211_hdr_3addr));
 893
 894        if (!skb)
 895                return NULL;
 896
 897        hdr = skb_put(skb, sizeof(struct rtl_80211_hdr_3addr));
 898
 899        memcpy(hdr->addr1, ieee->current_network.bssid, ETH_ALEN);
 900        memcpy(hdr->addr2, ieee->dev->dev_addr, ETH_ALEN);
 901        memcpy(hdr->addr3, ieee->current_network.bssid, ETH_ALEN);
 902
 903        hdr->frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
 904                                     IEEE80211_STYPE_NULLFUNC | IEEE80211_FCTL_TODS |
 905                                     (pwr ? IEEE80211_FCTL_PM : 0));
 906
 907        return skb;
 908}
 909
 910static void ieee80211_resp_to_assoc_rq(struct ieee80211_device *ieee, u8 *dest)
 911{
 912        struct sk_buff *buf = ieee80211_assoc_resp(ieee, dest);
 913
 914        if (buf)
 915                softmac_mgmt_xmit(buf, ieee);
 916}
 917
 918static void ieee80211_resp_to_auth(struct ieee80211_device *ieee, int s,
 919                                   u8 *dest)
 920{
 921        struct sk_buff *buf = ieee80211_auth_resp(ieee, s, dest);
 922
 923        if (buf)
 924                softmac_mgmt_xmit(buf, ieee);
 925}
 926
 927static void ieee80211_resp_to_probe(struct ieee80211_device *ieee, u8 *dest)
 928{
 929        struct sk_buff *buf = ieee80211_probe_resp(ieee, dest);
 930        if (buf)
 931                softmac_mgmt_xmit(buf, ieee);
 932}
 933
 934static inline struct sk_buff *
 935ieee80211_association_req(struct ieee80211_network *beacon,
 936                          struct ieee80211_device *ieee)
 937{
 938        struct sk_buff *skb;
 939        //unsigned long flags;
 940
 941        struct ieee80211_assoc_request_frame *hdr;
 942        u8 *tag;//,*rsn_ie;
 943        //short info_addr = 0;
 944        //int i;
 945        //u16 suite_count = 0;
 946        //u8 suit_select = 0;
 947        //unsigned int wpa_len = beacon->wpa_ie_len;
 948        //for HT
 949        u8 *ht_cap_buf = NULL;
 950        u8 ht_cap_len = 0;
 951        u8 *realtek_ie_buf = NULL;
 952        u8 realtek_ie_len = 0;
 953        int wpa_ie_len = ieee->wpa_ie_len;
 954        unsigned int ckip_ie_len = 0;
 955        unsigned int ccxrm_ie_len = 0;
 956        unsigned int cxvernum_ie_len = 0;
 957        struct ieee80211_crypt_data *crypt;
 958        int encrypt;
 959
 960        unsigned int rate_len = ieee80211_MFIE_rate_len(ieee);
 961        unsigned int wmm_info_len = beacon->qos_data.supported ? 9 : 0;
 962#ifdef THOMAS_TURBO
 963        unsigned int turbo_info_len = beacon->Turbo_Enable ? 9 : 0;
 964#endif
 965
 966        int len = 0;
 967
 968        crypt = ieee->crypt[ieee->tx_keyidx];
 969        encrypt = ieee->host_encrypt && crypt && crypt->ops && ((0 == strcmp(crypt->ops->name, "WEP") || wpa_ie_len));
 970
 971        /* Include High Throuput capability && Realtek proprietary */
 972        if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
 973                ht_cap_buf = (u8 *)&ieee->pHTInfo->SelfHTCap;
 974                ht_cap_len = sizeof(ieee->pHTInfo->SelfHTCap);
 975                HTConstructCapabilityElement(ieee, ht_cap_buf, &ht_cap_len, encrypt);
 976                if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
 977                        realtek_ie_buf = ieee->pHTInfo->szRT2RTAggBuffer;
 978                        realtek_ie_len = sizeof(ieee->pHTInfo->szRT2RTAggBuffer);
 979                        HTConstructRT2RTAggElement(ieee, realtek_ie_buf, &realtek_ie_len);
 980                }
 981        }
 982        if (ieee->qos_support)
 983                wmm_info_len = beacon->qos_data.supported ? 9 : 0;
 984
 985        if (beacon->bCkipSupported)
 986                ckip_ie_len = 30 + 2;
 987
 988        if (beacon->bCcxRmEnable)
 989                ccxrm_ie_len = 6 + 2;
 990
 991        if (beacon->BssCcxVerNumber >= 2)
 992                cxvernum_ie_len = 5 + 2;
 993
 994#ifdef THOMAS_TURBO
 995        len = sizeof(struct ieee80211_assoc_request_frame) + 2
 996                + beacon->ssid_len      /* essid tagged val */
 997                + rate_len      /* rates tagged val */
 998                + wpa_ie_len
 999                + wmm_info_len
1000                + turbo_info_len
1001                + ht_cap_len
1002                + realtek_ie_len
1003                + ckip_ie_len
1004                + ccxrm_ie_len
1005                + cxvernum_ie_len
1006                + ieee->tx_headroom;
1007#else
1008        len = sizeof(struct ieee80211_assoc_request_frame) + 2
1009                + beacon->ssid_len      /* essid tagged val */
1010                + rate_len      /* rates tagged val */
1011                + wpa_ie_len
1012                + wmm_info_len
1013                + ht_cap_len
1014                + realtek_ie_len
1015                + ckip_ie_len
1016                + ccxrm_ie_len
1017                + cxvernum_ie_len
1018                + ieee->tx_headroom;
1019#endif
1020        skb = dev_alloc_skb(len);
1021
1022        if (!skb)
1023                return NULL;
1024
1025        skb_reserve(skb, ieee->tx_headroom);
1026
1027        hdr = skb_put(skb, sizeof(struct ieee80211_assoc_request_frame) + 2);
1028
1029        hdr->header.frame_ctl = IEEE80211_STYPE_ASSOC_REQ;
1030        hdr->header.duration_id = cpu_to_le16(37);
1031        memcpy(hdr->header.addr1, beacon->bssid, ETH_ALEN);
1032        memcpy(hdr->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
1033        memcpy(hdr->header.addr3, beacon->bssid, ETH_ALEN);
1034
1035        memcpy(ieee->ap_mac_addr, beacon->bssid, ETH_ALEN);//for HW security, John
1036
1037        hdr->capability = cpu_to_le16(WLAN_CAPABILITY_BSS);
1038        if (beacon->capability & WLAN_CAPABILITY_PRIVACY)
1039                hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
1040
1041        if (beacon->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
1042                hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); //add short_preamble here
1043
1044        if (ieee->short_slot)
1045                hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT);
1046        if (wmm_info_len) //QOS
1047                hdr->capability |= cpu_to_le16(WLAN_CAPABILITY_QOS);
1048
1049        hdr->listen_interval = cpu_to_le16(0xa);
1050
1051        hdr->info_element[0].id = MFIE_TYPE_SSID;
1052
1053        hdr->info_element[0].len = beacon->ssid_len;
1054        skb_put_data(skb, beacon->ssid, beacon->ssid_len);
1055
1056        tag = skb_put(skb, rate_len);
1057
1058        ieee80211_MFIE_Brate(ieee, &tag);
1059        ieee80211_MFIE_Grate(ieee, &tag);
1060        // For CCX 1 S13, CKIP. Added by Annie, 2006-08-14.
1061        if (beacon->bCkipSupported) {
1062                static u8       AironetIeOui[] = {0x00, 0x01, 0x66}; // "4500-client"
1063                u8      CcxAironetBuf[30];
1064                struct octet_string     osCcxAironetIE;
1065
1066                memset(CcxAironetBuf, 0, 30);
1067                osCcxAironetIE.octet = CcxAironetBuf;
1068                osCcxAironetIE.length = sizeof(CcxAironetBuf);
1069                //
1070                // Ref. CCX test plan v3.61, 3.2.3.1 step 13.
1071                // We want to make the device type as "4500-client". 060926, by CCW.
1072                //
1073                memcpy(osCcxAironetIE.octet, AironetIeOui, sizeof(AironetIeOui));
1074
1075                // CCX1 spec V1.13, A01.1 CKIP Negotiation (page23):
1076                // "The CKIP negotiation is started with the associate request from the client to the access point,
1077                //  containing an Aironet element with both the MIC and KP bits set."
1078                osCcxAironetIE.octet[IE_CISCO_FLAG_POSITION] |= (SUPPORT_CKIP_PK | SUPPORT_CKIP_MIC);
1079                tag = skb_put(skb, ckip_ie_len);
1080                *tag++ = MFIE_TYPE_AIRONET;
1081                *tag++ = osCcxAironetIE.length;
1082                memcpy(tag, osCcxAironetIE.octet, osCcxAironetIE.length);
1083                tag += osCcxAironetIE.length;
1084        }
1085
1086        if (beacon->bCcxRmEnable) {
1087                static u8 CcxRmCapBuf[] = {0x00, 0x40, 0x96, 0x01, 0x01, 0x00};
1088                struct octet_string osCcxRmCap;
1089
1090                osCcxRmCap.octet = CcxRmCapBuf;
1091                osCcxRmCap.length = sizeof(CcxRmCapBuf);
1092                tag = skb_put(skb, ccxrm_ie_len);
1093                *tag++ = MFIE_TYPE_GENERIC;
1094                *tag++ = osCcxRmCap.length;
1095                memcpy(tag, osCcxRmCap.octet, osCcxRmCap.length);
1096                tag += osCcxRmCap.length;
1097        }
1098
1099        if (beacon->BssCcxVerNumber >= 2) {
1100                u8                      CcxVerNumBuf[] = {0x00, 0x40, 0x96, 0x03, 0x00};
1101                struct octet_string     osCcxVerNum;
1102                CcxVerNumBuf[4] = beacon->BssCcxVerNumber;
1103                osCcxVerNum.octet = CcxVerNumBuf;
1104                osCcxVerNum.length = sizeof(CcxVerNumBuf);
1105                tag = skb_put(skb, cxvernum_ie_len);
1106                *tag++ = MFIE_TYPE_GENERIC;
1107                *tag++ = osCcxVerNum.length;
1108                memcpy(tag, osCcxVerNum.octet, osCcxVerNum.length);
1109                tag += osCcxVerNum.length;
1110        }
1111        //HT cap element
1112        if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1113                if (ieee->pHTInfo->ePeerHTSpecVer != HT_SPEC_VER_EWC) {
1114                        tag = skb_put(skb, ht_cap_len);
1115                        *tag++ = MFIE_TYPE_HT_CAP;
1116                        *tag++ = ht_cap_len - 2;
1117                        memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1118                        tag += ht_cap_len - 2;
1119                }
1120        }
1121
1122        //choose what wpa_supplicant gives to associate.
1123        if (wpa_ie_len)
1124                skb_put_data(skb, ieee->wpa_ie, wpa_ie_len);
1125
1126        if (wmm_info_len) {
1127                tag = skb_put(skb, wmm_info_len);
1128                ieee80211_WMM_Info(ieee, &tag);
1129        }
1130#ifdef THOMAS_TURBO
1131        if (turbo_info_len) {
1132                tag = skb_put(skb, turbo_info_len);
1133                ieee80211_TURBO_Info(ieee, &tag);
1134        }
1135#endif
1136
1137        if (ieee->pHTInfo->bCurrentHTSupport && ieee->pHTInfo->bEnableHT) {
1138                if (ieee->pHTInfo->ePeerHTSpecVer == HT_SPEC_VER_EWC) {
1139                        tag = skb_put(skb, ht_cap_len);
1140                        *tag++ = MFIE_TYPE_GENERIC;
1141                        *tag++ = ht_cap_len - 2;
1142                        memcpy(tag, ht_cap_buf, ht_cap_len - 2);
1143                        tag += ht_cap_len - 2;
1144                }
1145
1146                if (ieee->pHTInfo->bCurrentRT2RTAggregation) {
1147                        tag = skb_put(skb, realtek_ie_len);
1148                        *tag++ = MFIE_TYPE_GENERIC;
1149                        *tag++ = realtek_ie_len - 2;
1150                        memcpy(tag, realtek_ie_buf, realtek_ie_len - 2);
1151                }
1152        }
1153//      printk("<=====%s(), %p, %p\n", __func__, ieee->dev, ieee->dev->dev_addr);
1154//      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA, skb->data, skb->len);
1155        return skb;
1156}
1157
1158void ieee80211_associate_abort(struct ieee80211_device *ieee)
1159{
1160        unsigned long flags;
1161        spin_lock_irqsave(&ieee->lock, flags);
1162
1163        ieee->associate_seq++;
1164
1165        /* don't scan, and avoid to have the RX path possibily
1166         * try again to associate. Even do not react to AUTH or
1167         * ASSOC response. Just wait for the retry wq to be scheduled.
1168         * Here we will check if there are good nets to associate
1169         * with, so we retry or just get back to NO_LINK and scanning
1170         */
1171        if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING) {
1172                IEEE80211_DEBUG_MGMT("Authentication failed\n");
1173                ieee->softmac_stats.no_auth_rs++;
1174        } else {
1175                IEEE80211_DEBUG_MGMT("Association failed\n");
1176                ieee->softmac_stats.no_ass_rs++;
1177        }
1178
1179        ieee->state = IEEE80211_ASSOCIATING_RETRY;
1180
1181        schedule_delayed_work(&ieee->associate_retry_wq, \
1182                              IEEE80211_SOFTMAC_ASSOC_RETRY_TIME);
1183
1184        spin_unlock_irqrestore(&ieee->lock, flags);
1185}
1186
1187static void ieee80211_associate_abort_cb(struct timer_list *t)
1188{
1189        struct ieee80211_device *dev = from_timer(dev, t, associate_timer);
1190
1191        ieee80211_associate_abort(dev);
1192}
1193
1194static void ieee80211_associate_step1(struct ieee80211_device *ieee)
1195{
1196        struct ieee80211_network *beacon = &ieee->current_network;
1197        struct sk_buff *skb;
1198
1199        IEEE80211_DEBUG_MGMT("Stopping scan\n");
1200
1201        ieee->softmac_stats.tx_auth_rq++;
1202        skb = ieee80211_authentication_req(beacon, ieee, 0);
1203
1204        if (!skb) {
1205                ieee80211_associate_abort(ieee);
1206        } else {
1207                ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATING;
1208                IEEE80211_DEBUG_MGMT("Sending authentication request\n");
1209                softmac_mgmt_xmit(skb, ieee);
1210                //BUGON when you try to add_timer twice, using mod_timer may be better, john0709
1211                if (!timer_pending(&ieee->associate_timer)) {
1212                        ieee->associate_timer.expires = jiffies + (HZ / 2);
1213                        add_timer(&ieee->associate_timer);
1214                }
1215                //dev_kfree_skb_any(skb);//edit by thomas
1216        }
1217}
1218
1219static void ieee80211_auth_challenge(struct ieee80211_device *ieee,
1220                                     u8 *challenge,
1221                                     int chlen)
1222{
1223        u8 *c;
1224        struct sk_buff *skb;
1225        struct ieee80211_network *beacon = &ieee->current_network;
1226//      int hlen = sizeof(struct ieee80211_authentication);
1227
1228        ieee->associate_seq++;
1229        ieee->softmac_stats.tx_auth_rq++;
1230
1231        skb = ieee80211_authentication_req(beacon, ieee, chlen + 2);
1232        if (!skb) {
1233                ieee80211_associate_abort(ieee);
1234        } else {
1235                c = skb_put(skb, chlen + 2);
1236                *(c++) = MFIE_TYPE_CHALLENGE;
1237                *(c++) = chlen;
1238                memcpy(c, challenge, chlen);
1239
1240                IEEE80211_DEBUG_MGMT("Sending authentication challenge response\n");
1241
1242                ieee80211_encrypt_fragment(ieee, skb, sizeof(struct rtl_80211_hdr_3addr));
1243
1244                softmac_mgmt_xmit(skb, ieee);
1245                mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1246                //dev_kfree_skb_any(skb);//edit by thomas
1247        }
1248        kfree(challenge);
1249}
1250
1251static void ieee80211_associate_step2(struct ieee80211_device *ieee)
1252{
1253        struct sk_buff *skb;
1254        struct ieee80211_network *beacon = &ieee->current_network;
1255
1256        del_timer_sync(&ieee->associate_timer);
1257
1258        IEEE80211_DEBUG_MGMT("Sending association request\n");
1259
1260        ieee->softmac_stats.tx_ass_rq++;
1261        skb = ieee80211_association_req(beacon, ieee);
1262        if (!skb) {
1263                ieee80211_associate_abort(ieee);
1264        } else {
1265                softmac_mgmt_xmit(skb, ieee);
1266                mod_timer(&ieee->associate_timer, jiffies + (HZ / 2));
1267                //dev_kfree_skb_any(skb);//edit by thomas
1268        }
1269}
1270static void ieee80211_associate_complete_wq(struct work_struct *work)
1271{
1272        struct ieee80211_device *ieee = container_of(work, struct ieee80211_device, associate_complete_wq);
1273
1274        netdev_info(ieee->dev, "Associated successfully\n");
1275        if (ieee80211_is_54g(&ieee->current_network) &&
1276            (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1277                ieee->rate = 108;
1278                netdev_info(ieee->dev, "Using G rates:%d\n", ieee->rate);
1279        } else {
1280                ieee->rate = 22;
1281                netdev_info(ieee->dev, "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                        netdev_info(ieee->dev,
1396                                    "Linking with %s,channel:%d, qos:%d, myHT:%d, networkHT:%d\n",
1397                                    ieee->current_network.ssid,
1398                                    ieee->current_network.channel,
1399                                    ieee->current_network.qos_data.supported,
1400                                    ieee->pHTInfo->bEnableHT,
1401                                    ieee->current_network.bssht.bdSupportHT);
1402
1403                        //ieee->pHTInfo->IOTAction = 0;
1404                        HTResetIOTSetting(ieee->pHTInfo);
1405                        if (ieee->iw_mode == IW_MODE_INFRA) {
1406                                /* Join the network for the first time */
1407                                ieee->AsocRetryCount = 0;
1408                                //for HT by amy 080514
1409                                if ((ieee->current_network.qos_data.supported == 1) &&
1410                                    // (ieee->pHTInfo->bEnableHT && ieee->current_network.bssht.bdSupportHT))
1411                                    ieee->current_network.bssht.bdSupportHT) {
1412/*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.*/
1413                                        //      ieee->pHTInfo->bCurrentHTSupport = true;
1414                                        HTResetSelfAndSavePeerSetting(ieee, &ieee->current_network);
1415                                } else {
1416                                        ieee->pHTInfo->bCurrentHTSupport = false;
1417                                }
1418
1419                                ieee->state = IEEE80211_ASSOCIATING;
1420                                schedule_work(&ieee->associate_procedure_wq);
1421                        } else {
1422                                if (ieee80211_is_54g(&ieee->current_network) &&
1423                                    (ieee->modulation & IEEE80211_OFDM_MODULATION)) {
1424                                        ieee->rate = 108;
1425                                        ieee->SetWirelessMode(ieee->dev, IEEE_G);
1426                                        netdev_info(ieee->dev,
1427                                                    "Using G rates\n");
1428                                } else {
1429                                        ieee->rate = 22;
1430                                        ieee->SetWirelessMode(ieee->dev, IEEE_B);
1431                                        netdev_info(ieee->dev,
1432                                                    "Using B rates\n");
1433                                }
1434                                memset(ieee->dot11HTOperationalRateSet, 0, 16);
1435                                //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1436                                ieee->state = IEEE80211_LINKED;
1437                        }
1438                }
1439        }
1440}
1441
1442void ieee80211_softmac_check_all_nets(struct ieee80211_device *ieee)
1443{
1444        unsigned long flags;
1445        struct ieee80211_network *target;
1446
1447        spin_lock_irqsave(&ieee->lock, flags);
1448
1449        list_for_each_entry(target, &ieee->network_list, list) {
1450                /* if the state become different that NOLINK means
1451                 * we had found what we are searching for
1452                 */
1453
1454                if (ieee->state != IEEE80211_NOLINK)
1455                        break;
1456
1457                if (ieee->scan_age == 0 || time_after(target->last_scanned + ieee->scan_age, jiffies))
1458                        ieee80211_softmac_new_net(ieee, target);
1459        }
1460
1461        spin_unlock_irqrestore(&ieee->lock, flags);
1462}
1463
1464static inline u16 auth_parse(struct sk_buff *skb, u8 **challenge, int *chlen)
1465{
1466        struct ieee80211_authentication *a;
1467        u8 *t;
1468        if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1469                IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1470                return 0xcafe;
1471        }
1472        *challenge = NULL;
1473        a = (struct ieee80211_authentication *)skb->data;
1474        if (skb->len > (sizeof(struct ieee80211_authentication) + 3)) {
1475                t = skb->data + sizeof(struct ieee80211_authentication);
1476
1477                if (*(t++) == MFIE_TYPE_CHALLENGE) {
1478                        *chlen = *(t++);
1479                        *challenge = kmemdup(t, *chlen, GFP_ATOMIC);
1480                        if (!*challenge)
1481                                return -ENOMEM;
1482                }
1483        }
1484
1485        return le16_to_cpu(a->status);
1486}
1487
1488static int auth_rq_parse(struct sk_buff *skb, u8 *dest)
1489{
1490        struct ieee80211_authentication *a;
1491
1492        if (skb->len < (sizeof(struct ieee80211_authentication) - sizeof(struct ieee80211_info_element))) {
1493                IEEE80211_DEBUG_MGMT("invalid len in auth request: %d\n", skb->len);
1494                return -1;
1495        }
1496        a = (struct ieee80211_authentication *)skb->data;
1497
1498        memcpy(dest, a->header.addr2, ETH_ALEN);
1499
1500        if (le16_to_cpu(a->algorithm) != WLAN_AUTH_OPEN)
1501                return  WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG;
1502
1503        return WLAN_STATUS_SUCCESS;
1504}
1505
1506static short probe_rq_parse(struct ieee80211_device *ieee, struct sk_buff *skb, u8 *src)
1507{
1508        u8 *tag;
1509        u8 *skbend;
1510        u8 *ssid = NULL;
1511        u8 ssidlen = 0;
1512
1513        struct rtl_80211_hdr_3addr   *header =
1514                (struct rtl_80211_hdr_3addr   *)skb->data;
1515
1516        if (skb->len < sizeof(struct rtl_80211_hdr_3addr))
1517                return -1; /* corrupted */
1518
1519        memcpy(src, header->addr2, ETH_ALEN);
1520
1521        skbend = (u8 *)skb->data + skb->len;
1522
1523        tag = skb->data + sizeof(struct rtl_80211_hdr_3addr);
1524
1525        while (tag + 1 < skbend) {
1526                if (*tag == 0) {
1527                        ssid = tag + 2;
1528                        ssidlen = *(tag + 1);
1529                        break;
1530                }
1531                tag++; /* point to the len field */
1532                tag = tag + *(tag); /* point to the last data byte of the tag */
1533                tag++; /* point to the next tag */
1534        }
1535
1536        //IEEE80211DMESG("Card MAC address is "MACSTR, MAC2STR(src));
1537        if (ssidlen == 0)
1538                return 1;
1539
1540        if (!ssid)
1541                return 1; /* ssid not found in tagged param */
1542
1543        return (!strncmp(ssid, ieee->current_network.ssid, ssidlen));
1544}
1545
1546static int assoc_rq_parse(struct sk_buff *skb, u8 *dest)
1547{
1548        struct ieee80211_assoc_request_frame *a;
1549
1550        if (skb->len < (sizeof(struct ieee80211_assoc_request_frame) -
1551                sizeof(struct ieee80211_info_element))) {
1552                IEEE80211_DEBUG_MGMT("invalid len in auth request:%d \n", skb->len);
1553                return -1;
1554        }
1555
1556        a = (struct ieee80211_assoc_request_frame *)skb->data;
1557
1558        memcpy(dest, a->header.addr2, ETH_ALEN);
1559
1560        return 0;
1561}
1562
1563static inline u16 assoc_parse(struct ieee80211_device *ieee, struct sk_buff *skb, int *aid)
1564{
1565        struct ieee80211_assoc_response_frame *response_head;
1566        u16 status_code;
1567
1568        if (skb->len < sizeof(struct ieee80211_assoc_response_frame)) {
1569                IEEE80211_DEBUG_MGMT("invalid len in auth resp: %d\n", skb->len);
1570                return 0xcafe;
1571        }
1572
1573        response_head = (struct ieee80211_assoc_response_frame *)skb->data;
1574        *aid = le16_to_cpu(response_head->aid) & 0x3fff;
1575
1576        status_code = le16_to_cpu(response_head->status);
1577        if ((status_code == WLAN_STATUS_ASSOC_DENIED_RATES ||
1578             status_code == WLAN_STATUS_CAPS_UNSUPPORTED) &&
1579            ((ieee->mode == IEEE_G) &&
1580             (ieee->current_network.mode == IEEE_N_24G) &&
1581             (ieee->AsocRetryCount++ < (RT_ASOC_RETRY_LIMIT - 1)))) {
1582                ieee->pHTInfo->IOTAction |= HT_IOT_ACT_PURE_N_MODE;
1583        } else {
1584                ieee->AsocRetryCount = 0;
1585        }
1586
1587        return le16_to_cpu(response_head->status);
1588}
1589
1590static inline void
1591ieee80211_rx_probe_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1592{
1593        u8 dest[ETH_ALEN];
1594
1595        //IEEE80211DMESG("Rx probe");
1596        ieee->softmac_stats.rx_probe_rq++;
1597        //DMESG("Dest is "MACSTR, MAC2STR(dest));
1598        if (probe_rq_parse(ieee, skb, dest)) {
1599                //IEEE80211DMESG("Was for me!");
1600                ieee->softmac_stats.tx_probe_rs++;
1601                ieee80211_resp_to_probe(ieee, dest);
1602        }
1603}
1604
1605static inline void
1606ieee80211_rx_auth_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1607{
1608        u8 dest[ETH_ALEN];
1609        int status;
1610        //IEEE80211DMESG("Rx probe");
1611        ieee->softmac_stats.rx_auth_rq++;
1612
1613        status = auth_rq_parse(skb, dest);
1614        if (status != -1)
1615                ieee80211_resp_to_auth(ieee, status, dest);
1616        //DMESG("Dest is "MACSTR, MAC2STR(dest));
1617}
1618
1619static inline void
1620ieee80211_rx_assoc_rq(struct ieee80211_device *ieee, struct sk_buff *skb)
1621{
1622        u8 dest[ETH_ALEN];
1623        //unsigned long flags;
1624
1625        ieee->softmac_stats.rx_ass_rq++;
1626        if (assoc_rq_parse(skb, dest) != -1)
1627                ieee80211_resp_to_assoc_rq(ieee, dest);
1628
1629        netdev_info(ieee->dev, "New client associated: %pM\n", dest);
1630        //FIXME
1631}
1632
1633static void ieee80211_sta_ps_send_null_frame(struct ieee80211_device *ieee,
1634                                             short pwr)
1635{
1636        struct sk_buff *buf = ieee80211_null_func(ieee, pwr);
1637
1638        if (buf)
1639                softmac_ps_mgmt_xmit(buf, ieee);
1640}
1641/* EXPORT_SYMBOL(ieee80211_sta_ps_send_null_frame); */
1642
1643static short ieee80211_sta_ps_sleep(struct ieee80211_device *ieee, u32 *time_h,
1644                                    u32 *time_l)
1645{
1646        int timeout;
1647        u8 dtim;
1648        /*if(ieee->ps == IEEE80211_PS_DISABLED ||
1649                ieee->iw_mode != IW_MODE_INFRA ||
1650                ieee->state != IEEE80211_LINKED)
1651
1652                return 0;
1653        */
1654        dtim = ieee->current_network.dtim_data;
1655        if (!(dtim & IEEE80211_DTIM_VALID))
1656                return 0;
1657        timeout = ieee->current_network.beacon_interval; //should we use ps_timeout value or beacon_interval
1658        ieee->current_network.dtim_data = IEEE80211_DTIM_INVALID;
1659
1660        if (dtim & ((IEEE80211_DTIM_UCAST | IEEE80211_DTIM_MBCAST) & ieee->ps))
1661                return 2;
1662
1663        if (!time_after(jiffies,
1664                        dev_trans_start(ieee->dev) + msecs_to_jiffies(timeout)))
1665                return 0;
1666
1667        if (!time_after(jiffies,
1668                        ieee->last_rx_ps_time + msecs_to_jiffies(timeout)))
1669                return 0;
1670
1671        if ((ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) &&
1672            (ieee->mgmt_queue_tail != ieee->mgmt_queue_head))
1673                return 0;
1674
1675        if (time_l) {
1676                *time_l = ieee->current_network.last_dtim_sta_time[0]
1677                        + (ieee->current_network.beacon_interval
1678                           * ieee->current_network.dtim_period) * 1000;
1679        }
1680
1681        if (time_h) {
1682                *time_h = ieee->current_network.last_dtim_sta_time[1];
1683                if (time_l && *time_l < ieee->current_network.last_dtim_sta_time[0])
1684                        *time_h += 1;
1685        }
1686
1687        return 1;
1688}
1689
1690static inline void ieee80211_sta_ps(struct tasklet_struct *t)
1691{
1692        struct ieee80211_device *ieee = from_tasklet(ieee, t, ps_task);
1693        u32 th, tl;
1694        short sleep;
1695
1696        unsigned long flags, flags2;
1697
1698        spin_lock_irqsave(&ieee->lock, flags);
1699
1700        if ((ieee->ps == IEEE80211_PS_DISABLED ||
1701             ieee->iw_mode != IW_MODE_INFRA ||
1702             ieee->state != IEEE80211_LINKED)) {
1703                //      #warning CHECK_LOCK_HERE
1704                spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1705
1706                ieee80211_sta_wakeup(ieee, 1);
1707
1708                spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1709        }
1710
1711        sleep = ieee80211_sta_ps_sleep(ieee, &th, &tl);
1712        /* 2 wake, 1 sleep, 0 do nothing */
1713        if (sleep == 0)
1714                goto out;
1715
1716        if (sleep == 1) {
1717                if (ieee->sta_sleep == 1) {
1718                        ieee->enter_sleep_state(ieee->dev, th, tl);
1719                } else if (ieee->sta_sleep == 0) {
1720                //      printk("send null 1\n");
1721                        spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1722
1723                        if (ieee->ps_is_queue_empty(ieee->dev)) {
1724                                ieee->sta_sleep = 2;
1725
1726                                ieee->ps_request_tx_ack(ieee->dev);
1727
1728                                ieee80211_sta_ps_send_null_frame(ieee, 1);
1729
1730                                ieee->ps_th = th;
1731                                ieee->ps_tl = tl;
1732                        }
1733                        spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1734                }
1735        } else if (sleep == 2) {
1736//#warning CHECK_LOCK_HERE
1737                spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1738
1739                ieee80211_sta_wakeup(ieee, 1);
1740
1741                spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1742        }
1743out:
1744        spin_unlock_irqrestore(&ieee->lock, flags);
1745}
1746
1747void ieee80211_sta_wakeup(struct ieee80211_device *ieee, short nl)
1748{
1749        if (ieee->sta_sleep == 0) {
1750                if (nl) {
1751                        printk("Warning: driver is probably failing to report TX ps error\n");
1752                        ieee->ps_request_tx_ack(ieee->dev);
1753                        ieee80211_sta_ps_send_null_frame(ieee, 0);
1754                }
1755                return;
1756        }
1757
1758        if (ieee->sta_sleep == 1)
1759                ieee->sta_wake_up(ieee->dev);
1760
1761        ieee->sta_sleep = 0;
1762
1763        if (nl) {
1764                ieee->ps_request_tx_ack(ieee->dev);
1765                ieee80211_sta_ps_send_null_frame(ieee, 0);
1766        }
1767}
1768
1769void ieee80211_ps_tx_ack(struct ieee80211_device *ieee, short success)
1770{
1771        unsigned long flags, flags2;
1772
1773        spin_lock_irqsave(&ieee->lock, flags);
1774
1775        if (ieee->sta_sleep == 2) {
1776                /* Null frame with PS bit set */
1777                if (success) {
1778                        ieee->sta_sleep = 1;
1779                        ieee->enter_sleep_state(ieee->dev, ieee->ps_th, ieee->ps_tl);
1780                }
1781                /* if the card report not success we can't be sure the AP
1782                 * has not RXed so we can't assume the AP believe us awake
1783                 */
1784        } else {
1785                /* 21112005 - tx again null without PS bit if lost */
1786                if ((ieee->sta_sleep == 0) && !success) {
1787                        spin_lock_irqsave(&ieee->mgmt_tx_lock, flags2);
1788                        ieee80211_sta_ps_send_null_frame(ieee, 0);
1789                        spin_unlock_irqrestore(&ieee->mgmt_tx_lock, flags2);
1790                }
1791        }
1792        spin_unlock_irqrestore(&ieee->lock, flags);
1793}
1794EXPORT_SYMBOL(ieee80211_ps_tx_ack);
1795
1796static void ieee80211_process_action(struct ieee80211_device *ieee,
1797                                     struct sk_buff *skb)
1798{
1799        struct rtl_80211_hdr *header = (struct rtl_80211_hdr *)skb->data;
1800        u8 *act = ieee80211_get_payload(header);
1801        u8 tmp = 0;
1802//      IEEE80211_DEBUG_DATA(IEEE80211_DL_DATA|IEEE80211_DL_BA, skb->data, skb->len);
1803        if (!act) {
1804                IEEE80211_DEBUG(IEEE80211_DL_ERR, "error to get payload of action frame\n");
1805                return;
1806        }
1807        tmp = *act;
1808        act++;
1809        switch (tmp) {
1810        case ACT_CAT_BA:
1811                if (*act == ACT_ADDBAREQ)
1812                        ieee80211_rx_ADDBAReq(ieee, skb);
1813                else if (*act == ACT_ADDBARSP)
1814                        ieee80211_rx_ADDBARsp(ieee, skb);
1815                else if (*act == ACT_DELBA)
1816                        ieee80211_rx_DELBA(ieee, skb);
1817                break;
1818        default:
1819                break;
1820        }
1821        return;
1822}
1823
1824static void ieee80211_check_auth_response(struct ieee80211_device *ieee,
1825                                          struct sk_buff *skb)
1826{
1827        /* default support N mode, disable halfNmode */
1828        bool bSupportNmode = true, bHalfSupportNmode = false;
1829        u16 errcode;
1830        u8 *challenge;
1831        int chlen = 0;
1832        u32 iotAction;
1833
1834        errcode = auth_parse(skb, &challenge, &chlen);
1835        if (!errcode) {
1836                if (ieee->open_wep || !challenge) {
1837                        ieee->state = IEEE80211_ASSOCIATING_AUTHENTICATED;
1838                        ieee->softmac_stats.rx_auth_rs_ok++;
1839                        iotAction = ieee->pHTInfo->IOTAction;
1840                        if (!(iotAction & HT_IOT_ACT_PURE_N_MODE)) {
1841                                if (!ieee->GetNmodeSupportBySecCfg(ieee->dev)) {
1842                                        /* WEP or TKIP encryption */
1843                                        if (IsHTHalfNmodeAPs(ieee)) {
1844                                                bSupportNmode = true;
1845                                                bHalfSupportNmode = true;
1846                                        } else {
1847                                                bSupportNmode = false;
1848                                                bHalfSupportNmode = false;
1849                                        }
1850                                        netdev_dbg(ieee->dev, "SEC(%d, %d)\n",
1851                                                        bSupportNmode,
1852                                                        bHalfSupportNmode);
1853                                }
1854                        }
1855                        /* Dummy wirless mode setting- avoid encryption issue */
1856                        if (bSupportNmode) {
1857                                /* N mode setting */
1858                                ieee->SetWirelessMode(ieee->dev,
1859                                                ieee->current_network.mode);
1860                        } else {
1861                                /* b/g mode setting - TODO */
1862                                ieee->SetWirelessMode(ieee->dev, IEEE_G);
1863                        }
1864
1865                        if (ieee->current_network.mode == IEEE_N_24G &&
1866                                        bHalfSupportNmode) {
1867                                netdev_dbg(ieee->dev, "enter half N mode\n");
1868                                ieee->bHalfWirelessN24GMode = true;
1869                        } else {
1870                                ieee->bHalfWirelessN24GMode = false;
1871                        }
1872                        ieee80211_associate_step2(ieee);
1873                } else {
1874                        ieee80211_auth_challenge(ieee, challenge, chlen);
1875                }
1876        } else {
1877                ieee->softmac_stats.rx_auth_rs_err++;
1878                IEEE80211_DEBUG_MGMT("Auth response status code 0x%x", errcode);
1879                ieee80211_associate_abort(ieee);
1880        }
1881}
1882
1883inline int
1884ieee80211_rx_frame_softmac(struct ieee80211_device *ieee, struct sk_buff *skb,
1885                           struct ieee80211_rx_stats *rx_stats, u16 type,
1886                           u16 stype)
1887{
1888        struct rtl_80211_hdr_3addr *header = (struct rtl_80211_hdr_3addr *)skb->data;
1889        u16 errcode;
1890        int aid;
1891        struct ieee80211_assoc_response_frame *assoc_resp;
1892//      struct ieee80211_info_element *info_element;
1893
1894        if (!ieee->proto_started)
1895                return 0;
1896
1897        if (ieee->sta_sleep || (ieee->ps != IEEE80211_PS_DISABLED &&
1898                                ieee->iw_mode == IW_MODE_INFRA &&
1899                                ieee->state == IEEE80211_LINKED))
1900                tasklet_schedule(&ieee->ps_task);
1901
1902        if (WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_PROBE_RESP &&
1903            WLAN_FC_GET_STYPE(header->frame_ctl) != IEEE80211_STYPE_BEACON)
1904                ieee->last_rx_ps_time = jiffies;
1905
1906        switch (WLAN_FC_GET_STYPE(header->frame_ctl)) {
1907        case IEEE80211_STYPE_ASSOC_RESP:
1908        case IEEE80211_STYPE_REASSOC_RESP:
1909                IEEE80211_DEBUG_MGMT("received [RE]ASSOCIATION RESPONSE (%d)\n",
1910                                WLAN_FC_GET_STYPE(header->frame_ctl));
1911                if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1912                    ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATED &&
1913                    ieee->iw_mode == IW_MODE_INFRA) {
1914                        struct ieee80211_network network_resp;
1915                        struct ieee80211_network *network = &network_resp;
1916
1917                        errcode = assoc_parse(ieee, skb, &aid);
1918                        if (!errcode) {
1919                                ieee->state = IEEE80211_LINKED;
1920                                ieee->assoc_id = aid;
1921                                ieee->softmac_stats.rx_ass_ok++;
1922                                /* station support qos */
1923                                /* Let the register setting defaultly with Legacy station */
1924                                if (ieee->qos_support) {
1925                                        assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
1926                                        memset(network, 0, sizeof(*network));
1927                                        if (ieee80211_parse_info_param(ieee, assoc_resp->info_element,\
1928                                                                       rx_stats->len - sizeof(*assoc_resp), \
1929                                                                       network, rx_stats)) {
1930                                                return 1;
1931                                        } else {
1932                                                //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
1933                                                memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1934                                                memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1935                                        }
1936                                        if (ieee->handle_assoc_response)
1937                                                ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
1938                                }
1939                                ieee80211_associate_complete(ieee);
1940                        } else {
1941                                /* aid could not been allocated */
1942                                ieee->softmac_stats.rx_ass_err++;
1943                                printk("Association response status code 0x%x\n",
1944                                       errcode);
1945                                IEEE80211_DEBUG_MGMT("Association response status code 0x%x\n",
1946                                                     errcode);
1947                                if (ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT)
1948                                        schedule_work(&ieee->associate_procedure_wq);
1949                                else
1950                                        ieee80211_associate_abort(ieee);
1951                        }
1952                }
1953                break;
1954
1955        case IEEE80211_STYPE_ASSOC_REQ:
1956        case IEEE80211_STYPE_REASSOC_REQ:
1957                if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1958                    ieee->iw_mode == IW_MODE_MASTER)
1959                        ieee80211_rx_assoc_rq(ieee, skb);
1960                break;
1961
1962        case IEEE80211_STYPE_AUTH:
1963                if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
1964                        if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
1965                            && ieee->iw_mode == IW_MODE_INFRA) {
1966                                IEEE80211_DEBUG_MGMT("Received auth response");
1967                                ieee80211_check_auth_response(ieee, skb);
1968                        } else if (ieee->iw_mode == IW_MODE_MASTER) {
1969                                ieee80211_rx_auth_rq(ieee, skb);
1970                        }
1971                }
1972                break;
1973
1974        case IEEE80211_STYPE_PROBE_REQ:
1975                if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
1976                    ((ieee->iw_mode == IW_MODE_ADHOC ||
1977                      ieee->iw_mode == IW_MODE_MASTER) &&
1978                     ieee->state == IEEE80211_LINKED)) {
1979                        ieee80211_rx_probe_rq(ieee, skb);
1980                }
1981                break;
1982
1983        case IEEE80211_STYPE_DISASSOC:
1984        case IEEE80211_STYPE_DEAUTH:
1985                /* FIXME for now repeat all the association procedure
1986                * both for disassociation and deauthentication
1987                */
1988                if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1989                    ieee->state == IEEE80211_LINKED &&
1990                    ieee->iw_mode == IW_MODE_INFRA) {
1991                        ieee->state = IEEE80211_ASSOCIATING;
1992                        ieee->softmac_stats.reassoc++;
1993
1994                        notify_wx_assoc_event(ieee);
1995                        //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1996                        RemovePeerTS(ieee, header->addr2);
1997                        schedule_work(&ieee->associate_procedure_wq);
1998                }
1999                break;
2000        case IEEE80211_STYPE_MANAGE_ACT:
2001                ieee80211_process_action(ieee, skb);
2002                break;
2003        default:
2004                return -1;
2005        }
2006
2007        //dev_kfree_skb_any(skb);
2008        return 0;
2009}
2010
2011/* The following are for a simpler TX queue management.
2012 * Instead of using netif_[stop/wake]_queue, the driver
2013 * will use these two functions (plus a reset one) that
2014 * will internally call the kernel netif_* and take care
2015 * of the ieee802.11 fragmentation.
2016 * So, the driver receives a fragment at a time and might
2017 * call the stop function when it wants, without taking
2018 * care to have enough room to TX an entire packet.
2019 * This might be useful if each fragment needs its own
2020 * descriptor. Thus, just keeping a total free memory > than
2021 * the max fragmentation threshold is not enough. If the
2022 * ieee802.11 stack passed a TXB struct, then you would need
2023 * to keep N free descriptors where
2024 * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
2025 * In this way you need just one and the 802.11 stack
2026 * will take care of buffering fragments and pass them to
2027 * to the driver later, when it wakes the queue.
2028 */
2029void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2030{
2031        unsigned int queue_index = txb->queue_index;
2032        unsigned long flags;
2033        int  i;
2034        struct cb_desc *tcb_desc = NULL;
2035
2036        spin_lock_irqsave(&ieee->lock, flags);
2037
2038        /* called with 2nd parm 0, no tx mgmt lock required */
2039        ieee80211_sta_wakeup(ieee, 0);
2040
2041        /* update the tx status */
2042        ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2043        ieee->stats.tx_packets++;
2044        tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2045        if (tcb_desc->bMulticast)
2046                ieee->stats.multicast++;
2047
2048        /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2049        for (i = 0; i < txb->nr_frags; i++) {
2050#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2051                if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2052#else
2053                if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2054#endif
2055                    (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) || \
2056                    (ieee->queue_stop)) {
2057                        /* insert the skb packet to the wait queue */
2058                        /* as for the completion function, it does not need
2059                         * to check it any more.
2060                         * */
2061                        //printk("error:no descriptor left@queue_index %d\n", queue_index);
2062                        //ieee80211_stop_queue(ieee);
2063#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2064                        skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2065#else
2066                        skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2067#endif
2068                } else {
2069                        ieee->softmac_data_hard_start_xmit(txb->fragments[i],
2070                                                           ieee->dev, ieee->rate);
2071                        //ieee->stats.tx_packets++;
2072                        //ieee->stats.tx_bytes += txb->fragments[i]->len;
2073                        //ieee->dev->trans_start = jiffies;
2074                }
2075        }
2076        ieee80211_txb_free(txb);
2077
2078//exit:
2079        spin_unlock_irqrestore(&ieee->lock, flags);
2080}
2081EXPORT_SYMBOL(ieee80211_softmac_xmit);
2082
2083/* called with ieee->lock acquired */
2084static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2085{
2086        int i;
2087        for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2088                if (ieee->queue_stop) {
2089                        ieee->tx_pending.frag = i;
2090                        return;
2091                } else {
2092                        ieee->softmac_data_hard_start_xmit(ieee->tx_pending.txb->fragments[i],
2093                                                           ieee->dev, ieee->rate);
2094                        //(i+1)<ieee->tx_pending.txb->nr_frags);
2095                        ieee->stats.tx_packets++;
2096                        netif_trans_update(ieee->dev);
2097                }
2098        }
2099
2100        ieee80211_txb_free(ieee->tx_pending.txb);
2101        ieee->tx_pending.txb = NULL;
2102}
2103
2104void ieee80211_reset_queue(struct ieee80211_device *ieee)
2105{
2106        unsigned long flags;
2107
2108        spin_lock_irqsave(&ieee->lock, flags);
2109        init_mgmt_queue(ieee);
2110        if (ieee->tx_pending.txb) {
2111                ieee80211_txb_free(ieee->tx_pending.txb);
2112                ieee->tx_pending.txb = NULL;
2113        }
2114        ieee->queue_stop = 0;
2115        spin_unlock_irqrestore(&ieee->lock, flags);
2116}
2117EXPORT_SYMBOL(ieee80211_reset_queue);
2118
2119void ieee80211_wake_queue(struct ieee80211_device *ieee)
2120{
2121        unsigned long flags;
2122        struct sk_buff *skb;
2123        struct rtl_80211_hdr_3addr  *header;
2124
2125        spin_lock_irqsave(&ieee->lock, flags);
2126        if (!ieee->queue_stop)
2127                goto exit;
2128
2129        ieee->queue_stop = 0;
2130
2131        if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2132                while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
2133                        header = (struct rtl_80211_hdr_3addr  *)skb->data;
2134
2135                        header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2136
2137                        if (ieee->seq_ctrl[0] == 0xFFF)
2138                                ieee->seq_ctrl[0] = 0;
2139                        else
2140                                ieee->seq_ctrl[0]++;
2141
2142                        ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
2143                        //dev_kfree_skb_any(skb);//edit by thomas
2144                }
2145        }
2146        if (!ieee->queue_stop && ieee->tx_pending.txb)
2147                ieee80211_resume_tx(ieee);
2148
2149        if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2150                ieee->softmac_stats.swtxawake++;
2151                netif_wake_queue(ieee->dev);
2152        }
2153exit:
2154        spin_unlock_irqrestore(&ieee->lock, flags);
2155}
2156EXPORT_SYMBOL(ieee80211_wake_queue);
2157
2158void ieee80211_stop_queue(struct ieee80211_device *ieee)
2159{
2160        //unsigned long flags;
2161        //spin_lock_irqsave(&ieee->lock,flags);
2162
2163        if (!netif_queue_stopped(ieee->dev)) {
2164                netif_stop_queue(ieee->dev);
2165                ieee->softmac_stats.swtxstop++;
2166        }
2167        ieee->queue_stop = 1;
2168        //spin_unlock_irqrestore(&ieee->lock,flags);
2169}
2170EXPORT_SYMBOL(ieee80211_stop_queue);
2171
2172/* called in user context only */
2173void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2174{
2175        ieee->assoc_id = 1;
2176
2177        if (ieee->current_network.ssid_len == 0) {
2178                strncpy(ieee->current_network.ssid,
2179                        IEEE80211_DEFAULT_TX_ESSID,
2180                        IW_ESSID_MAX_SIZE);
2181
2182                ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2183                ieee->ssid_set = 1;
2184        }
2185
2186        memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2187
2188        ieee->set_chan(ieee->dev, ieee->current_network.channel);
2189        ieee->state = IEEE80211_LINKED;
2190        ieee->link_change(ieee->dev);
2191        notify_wx_assoc_event(ieee);
2192
2193        if (ieee->data_hard_resume)
2194                ieee->data_hard_resume(ieee->dev);
2195
2196        netif_carrier_on(ieee->dev);
2197}
2198
2199static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2200{
2201        if (ieee->raw_tx) {
2202                if (ieee->data_hard_resume)
2203                        ieee->data_hard_resume(ieee->dev);
2204
2205                netif_carrier_on(ieee->dev);
2206        }
2207}
2208static void ieee80211_start_ibss_wq(struct work_struct *work)
2209{
2210        struct delayed_work *dwork = to_delayed_work(work);
2211        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2212        /* iwconfig mode ad-hoc will schedule this and return
2213         * on the other hand this will block further iwconfig SET
2214         * operations because of the wx_mutex hold.
2215         * Anyway some most set operations set a flag to speed-up
2216         * (abort) this wq (when syncro scanning) before sleeping
2217         * on the semaphore
2218         */
2219        if (!ieee->proto_started) {
2220                printk("==========oh driver down return\n");
2221                return;
2222        }
2223        mutex_lock(&ieee->wx_mutex);
2224
2225        if (ieee->current_network.ssid_len == 0) {
2226                strcpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID);
2227                ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2228                ieee->ssid_set = 1;
2229        }
2230
2231        /* check if we have this cell in our network list */
2232        ieee80211_softmac_check_all_nets(ieee);
2233
2234//      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2235        if (ieee->state == IEEE80211_NOLINK)
2236                ieee->current_network.channel = 6;
2237        /* if not then the state is not linked. Maybe the user switched to
2238         * ad-hoc mode just after being in monitor mode, or just after
2239         * being very few time in managed mode (so the card have had no
2240         * time to scan all the chans..) or we have just run up the iface
2241         * after setting ad-hoc mode. So we have to give another try..
2242         * Here, in ibss mode, should be safe to do this without extra care
2243         * (in bss mode we had to make sure no-one tryed to associate when
2244         * we had just checked the ieee->state and we was going to start the
2245         * scan) beacause in ibss mode the ieee80211_new_net function, when
2246         * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2247         * so, at worst, we waste a bit of time to initiate an unneeded syncro
2248         * scan, that will stop at the first round because it sees the state
2249         * associated.
2250         */
2251        if (ieee->state == IEEE80211_NOLINK)
2252                ieee80211_start_scan_syncro(ieee);
2253
2254        /* the network definitively is not here.. create a new cell */
2255        if (ieee->state == IEEE80211_NOLINK) {
2256                printk("creating new IBSS cell\n");
2257                if (!ieee->wap_set)
2258                        eth_random_addr(ieee->current_network.bssid);
2259
2260                if (ieee->modulation & IEEE80211_CCK_MODULATION) {
2261                        ieee->current_network.rates_len = 4;
2262
2263                        ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2264                        ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2265                        ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2266                        ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2267                } else {
2268                        ieee->current_network.rates_len = 0;
2269                }
2270                if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
2271                        ieee->current_network.rates_ex_len = 8;
2272
2273                        ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2274                        ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2275                        ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2276                        ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2277                        ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2278                        ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2279                        ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2280                        ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2281
2282                        ieee->rate = 108;
2283                } else {
2284                        ieee->current_network.rates_ex_len = 0;
2285                        ieee->rate = 22;
2286                }
2287
2288                // By default, WMM function will be disabled in IBSS mode
2289                ieee->current_network.QoS_Enable = 0;
2290                ieee->SetWirelessMode(ieee->dev, IEEE_G);
2291                ieee->current_network.atim_window = 0;
2292                ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2293                if (ieee->short_slot)
2294                        ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2295        }
2296
2297        ieee->state = IEEE80211_LINKED;
2298
2299        ieee->set_chan(ieee->dev, ieee->current_network.channel);
2300        ieee->link_change(ieee->dev);
2301
2302        notify_wx_assoc_event(ieee);
2303
2304        ieee80211_start_send_beacons(ieee);
2305
2306        if (ieee->data_hard_resume)
2307                ieee->data_hard_resume(ieee->dev);
2308        netif_carrier_on(ieee->dev);
2309
2310        mutex_unlock(&ieee->wx_mutex);
2311}
2312
2313inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2314{
2315        schedule_delayed_work(&ieee->start_ibss_wq, 150);
2316}
2317
2318/* this is called only in user context, with wx_mutex held */
2319void ieee80211_start_bss(struct ieee80211_device *ieee)
2320{
2321        unsigned long flags;
2322        //
2323        // Ref: 802.11d 11.1.3.3
2324        // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2325        //
2326        if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
2327                if (!ieee->bGlobalDomain)
2328                        return;
2329        }
2330        /* check if we have already found the net we
2331         * are interested in (if any).
2332         * if not (we are disassociated and we are not
2333         * in associating / authenticating phase) start the background scanning.
2334         */
2335        ieee80211_softmac_check_all_nets(ieee);
2336
2337        /* ensure no-one start an associating process (thus setting
2338         * the ieee->state to ieee80211_ASSOCIATING) while we
2339         * have just checked it and we are going to enable scan.
2340         * The ieee80211_new_net function is always called with
2341         * lock held (from both ieee80211_softmac_check_all_nets and
2342         * the rx path), so we cannot be in the middle of such function
2343         */
2344        spin_lock_irqsave(&ieee->lock, flags);
2345
2346        if (ieee->state == IEEE80211_NOLINK) {
2347                ieee->actscanning = true;
2348                ieee80211_start_scan(ieee);
2349        }
2350        spin_unlock_irqrestore(&ieee->lock, flags);
2351}
2352
2353/* called only in userspace context */
2354void ieee80211_disassociate(struct ieee80211_device *ieee)
2355{
2356        netif_carrier_off(ieee->dev);
2357        if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2358                ieee80211_reset_queue(ieee);
2359
2360        if (ieee->data_hard_stop)
2361                ieee->data_hard_stop(ieee->dev);
2362        if (IS_DOT11D_ENABLE(ieee))
2363                dot11d_reset(ieee);
2364        ieee->state = IEEE80211_NOLINK;
2365        ieee->is_set_key = false;
2366        ieee->link_change(ieee->dev);
2367        //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2368        notify_wx_assoc_event(ieee);
2369}
2370EXPORT_SYMBOL(ieee80211_disassociate);
2371
2372static void ieee80211_associate_retry_wq(struct work_struct *work)
2373{
2374        struct delayed_work *dwork = to_delayed_work(work);
2375        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2376        unsigned long flags;
2377
2378        mutex_lock(&ieee->wx_mutex);
2379        if (!ieee->proto_started)
2380                goto exit;
2381
2382        if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
2383                goto exit;
2384
2385        /* until we do not set the state to IEEE80211_NOLINK
2386        * there are no possibility to have someone else trying
2387        * to start an association procedure (we get here with
2388        * ieee->state = IEEE80211_ASSOCIATING).
2389        * When we set the state to IEEE80211_NOLINK it is possible
2390        * that the RX path run an attempt to associate, but
2391        * both ieee80211_softmac_check_all_nets and the
2392        * RX path works with ieee->lock held so there are no
2393        * problems. If we are still disassociated then start a scan.
2394        * the lock here is necessary to ensure no one try to start
2395        * an association procedure when we have just checked the
2396        * state and we are going to start the scan.
2397        */
2398        ieee->state = IEEE80211_NOLINK;
2399
2400        ieee80211_softmac_check_all_nets(ieee);
2401
2402        spin_lock_irqsave(&ieee->lock, flags);
2403
2404        if (ieee->state == IEEE80211_NOLINK)
2405                ieee80211_start_scan(ieee);
2406
2407        spin_unlock_irqrestore(&ieee->lock, flags);
2408
2409exit:
2410        mutex_unlock(&ieee->wx_mutex);
2411}
2412
2413struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2414{
2415        u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2416
2417        struct sk_buff *skb;
2418        struct ieee80211_probe_response *b;
2419
2420        skb = ieee80211_probe_resp(ieee, broadcast_addr);
2421
2422        if (!skb)
2423                return NULL;
2424
2425        b = (struct ieee80211_probe_response *)skb->data;
2426        b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2427
2428        return skb;
2429}
2430
2431struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2432{
2433        struct sk_buff *skb;
2434        struct ieee80211_probe_response *b;
2435
2436        skb = ieee80211_get_beacon_(ieee);
2437        if (!skb)
2438                return NULL;
2439
2440        b = (struct ieee80211_probe_response *)skb->data;
2441        b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2442
2443        if (ieee->seq_ctrl[0] == 0xFFF)
2444                ieee->seq_ctrl[0] = 0;
2445        else
2446                ieee->seq_ctrl[0]++;
2447
2448        return skb;
2449}
2450EXPORT_SYMBOL(ieee80211_get_beacon);
2451
2452void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2453{
2454        ieee->sync_scan_hurryup = 1;
2455        mutex_lock(&ieee->wx_mutex);
2456        ieee80211_stop_protocol(ieee);
2457        mutex_unlock(&ieee->wx_mutex);
2458}
2459EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2460
2461void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2462{
2463        if (!ieee->proto_started)
2464                return;
2465
2466        ieee->proto_started = 0;
2467
2468        ieee80211_stop_send_beacons(ieee);
2469        del_timer_sync(&ieee->associate_timer);
2470        cancel_delayed_work(&ieee->associate_retry_wq);
2471        cancel_delayed_work(&ieee->start_ibss_wq);
2472        ieee80211_stop_scan(ieee);
2473
2474        ieee80211_disassociate(ieee);
2475        RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2476}
2477
2478void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2479{
2480        ieee->sync_scan_hurryup = 0;
2481        mutex_lock(&ieee->wx_mutex);
2482        ieee80211_start_protocol(ieee);
2483        mutex_unlock(&ieee->wx_mutex);
2484}
2485EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2486
2487void ieee80211_start_protocol(struct ieee80211_device *ieee)
2488{
2489        short ch = 0;
2490        int i = 0;
2491
2492        if (ieee->proto_started)
2493                return;
2494
2495        ieee->proto_started = 1;
2496
2497        if (ieee->current_network.channel == 0) {
2498                do {
2499                        ch++;
2500                        if (ch > MAX_CHANNEL_NUMBER)
2501                                return; /* no channel found */
2502                } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2503                ieee->current_network.channel = ch;
2504        }
2505
2506        if (ieee->current_network.beacon_interval == 0)
2507                ieee->current_network.beacon_interval = 100;
2508//      printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2509//      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2510
2511        for (i = 0; i < 17; i++) {
2512                ieee->last_rxseq_num[i] = -1;
2513                ieee->last_rxfrag_num[i] = -1;
2514                ieee->last_packet_time[i] = 0;
2515        }
2516
2517        ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2518
2519        /* if the user set the MAC of the ad-hoc cell and then
2520         * switch to managed mode, shall we  make sure that association
2521         * attempts does not fail just because the user provide the essid
2522         * and the nic is still checking for the AP MAC ??
2523         */
2524        if (ieee->iw_mode == IW_MODE_INFRA)
2525                ieee80211_start_bss(ieee);
2526
2527        else if (ieee->iw_mode == IW_MODE_ADHOC)
2528                ieee80211_start_ibss(ieee);
2529
2530        else if (ieee->iw_mode == IW_MODE_MASTER)
2531                ieee80211_start_master_bss(ieee);
2532
2533        else if (ieee->iw_mode == IW_MODE_MONITOR)
2534                ieee80211_start_monitor_mode(ieee);
2535}
2536
2537#define DRV_NAME  "Ieee80211"
2538void ieee80211_softmac_init(struct ieee80211_device *ieee)
2539{
2540        int i;
2541        memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2542
2543        ieee->state = IEEE80211_NOLINK;
2544        ieee->sync_scan_hurryup = 0;
2545        for (i = 0; i < 5; i++)
2546                ieee->seq_ctrl[i] = 0;
2547
2548        ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_KERNEL);
2549        if (!ieee->dot11d_info)
2550                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2551        //added for  AP roaming
2552        ieee->LinkDetectInfo.SlotNum = 2;
2553        ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
2554        ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
2555
2556        ieee->assoc_id = 0;
2557        ieee->queue_stop = 0;
2558        ieee->scanning = 0;
2559        ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2560        ieee->wap_set = 0;
2561        ieee->ssid_set = 0;
2562        ieee->proto_started = 0;
2563        ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2564        ieee->rate = 22;
2565        ieee->ps = IEEE80211_PS_DISABLED;
2566        ieee->sta_sleep = 0;
2567        ieee->Regdot11HTOperationalRateSet[0] = 0xff;//support MCS 0~7
2568        ieee->Regdot11HTOperationalRateSet[1] = 0xff;//support MCS 8~15
2569        ieee->Regdot11HTOperationalRateSet[4] = 0x01;
2570        //added by amy
2571        ieee->actscanning = false;
2572        ieee->beinretry = false;
2573        ieee->is_set_key = false;
2574        init_mgmt_queue(ieee);
2575
2576        ieee->sta_edca_param[0] = 0x0000A403;
2577        ieee->sta_edca_param[1] = 0x0000A427;
2578        ieee->sta_edca_param[2] = 0x005E4342;
2579        ieee->sta_edca_param[3] = 0x002F3262;
2580        ieee->aggregation = true;
2581        ieee->enable_rx_imm_BA = true;
2582        ieee->tx_pending.txb = NULL;
2583
2584        timer_setup(&ieee->associate_timer, ieee80211_associate_abort_cb, 0);
2585
2586        timer_setup(&ieee->beacon_timer, ieee80211_send_beacon_cb, 0);
2587
2588        INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2589        INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2590        INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2591        INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2592        INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2593        INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2594
2595        mutex_init(&ieee->wx_mutex);
2596        mutex_init(&ieee->scan_mutex);
2597
2598        spin_lock_init(&ieee->mgmt_tx_lock);
2599        spin_lock_init(&ieee->beacon_lock);
2600
2601        tasklet_setup(&ieee->ps_task, ieee80211_sta_ps);
2602}
2603
2604void ieee80211_softmac_free(struct ieee80211_device *ieee)
2605{
2606        mutex_lock(&ieee->wx_mutex);
2607        kfree(ieee->dot11d_info);
2608        ieee->dot11d_info = NULL;
2609        del_timer_sync(&ieee->associate_timer);
2610
2611        cancel_delayed_work(&ieee->associate_retry_wq);
2612
2613        mutex_unlock(&ieee->wx_mutex);
2614}
2615
2616/********************************************************
2617 * Start of WPA code.                                   *
2618 * this is stolen from the ipw2200 driver               *
2619 ********************************************************/
2620static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2621{
2622        /* This is called when wpa_supplicant loads and closes the driver
2623         * interface. */
2624        printk("%s WPA\n", value ? "enabling" : "disabling");
2625        ieee->wpa_enabled = value;
2626        return 0;
2627}
2628
2629static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2630                                      char *wpa_ie, int wpa_ie_len)
2631{
2632        /* make sure WPA is enabled */
2633        ieee80211_wpa_enable(ieee, 1);
2634
2635        ieee80211_disassociate(ieee);
2636}
2637
2638static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2639{
2640        int ret = 0;
2641
2642        switch (command) {
2643        case IEEE_MLME_STA_DEAUTH:
2644                // silently ignore
2645                break;
2646
2647        case IEEE_MLME_STA_DISASSOC:
2648                ieee80211_disassociate(ieee);
2649                break;
2650
2651        default:
2652                printk("Unknown MLME request: %d\n", command);
2653                ret = -EOPNOTSUPP;
2654        }
2655
2656        return ret;
2657}
2658
2659static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2660                              struct ieee_param *param, int plen)
2661{
2662        u8 *buf;
2663
2664        if (param->u.wpa_ie.len > MAX_WPA_IE_LEN)
2665                return -EINVAL;
2666
2667        if (param->u.wpa_ie.len) {
2668                buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2669                              GFP_KERNEL);
2670                if (!buf)
2671                        return -ENOMEM;
2672
2673                kfree(ieee->wpa_ie);
2674                ieee->wpa_ie = buf;
2675                ieee->wpa_ie_len = param->u.wpa_ie.len;
2676        } else {
2677                kfree(ieee->wpa_ie);
2678                ieee->wpa_ie = NULL;
2679                ieee->wpa_ie_len = 0;
2680        }
2681
2682        ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2683        return 0;
2684}
2685
2686#define AUTH_ALG_OPEN_SYSTEM                    0x1
2687#define AUTH_ALG_SHARED_KEY                     0x2
2688
2689static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2690{
2691        struct ieee80211_security sec = {
2692                .flags = SEC_AUTH_MODE,
2693        };
2694
2695        if (value & AUTH_ALG_SHARED_KEY) {
2696                sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2697                ieee->open_wep = 0;
2698                ieee->auth_mode = 1;
2699        } else if (value & AUTH_ALG_OPEN_SYSTEM) {
2700                sec.auth_mode = WLAN_AUTH_OPEN;
2701                ieee->open_wep = 1;
2702                ieee->auth_mode = 0;
2703        } else if (value & IW_AUTH_ALG_LEAP) {
2704                sec.auth_mode = WLAN_AUTH_LEAP;
2705                ieee->open_wep = 1;
2706                ieee->auth_mode = 2;
2707        }
2708
2709        if (ieee->set_security)
2710                ieee->set_security(ieee->dev, &sec);
2711        //else
2712        //      ret = -EOPNOTSUPP;
2713
2714        return 0;
2715}
2716
2717static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2718{
2719        int ret = 0;
2720        unsigned long flags;
2721
2722        switch (name) {
2723        case IEEE_PARAM_WPA_ENABLED:
2724                ret = ieee80211_wpa_enable(ieee, value);
2725                break;
2726
2727        case IEEE_PARAM_TKIP_COUNTERMEASURES:
2728                ieee->tkip_countermeasures = value;
2729                break;
2730
2731        case IEEE_PARAM_DROP_UNENCRYPTED: {
2732                /* HACK:
2733                 *
2734                 * wpa_supplicant calls set_wpa_enabled when the driver
2735                 * is loaded and unloaded, regardless of if WPA is being
2736                 * used.  No other calls are made which can be used to
2737                 * determine if encryption will be used or not prior to
2738                 * association being expected.  If encryption is not being
2739                 * used, drop_unencrypted is set to false, else true -- we
2740                 * can use this to determine if the CAP_PRIVACY_ON bit should
2741                 * be set.
2742                 */
2743                struct ieee80211_security sec = {
2744                        .flags = SEC_ENABLED,
2745                        .enabled = value,
2746                };
2747                ieee->drop_unencrypted = value;
2748                /* We only change SEC_LEVEL for open mode. Others
2749                 * are set by ipw_wpa_set_encryption.
2750                 */
2751                if (!value) {
2752                        sec.flags |= SEC_LEVEL;
2753                        sec.level = SEC_LEVEL_0;
2754                } else {
2755                        sec.flags |= SEC_LEVEL;
2756                        sec.level = SEC_LEVEL_1;
2757                }
2758                if (ieee->set_security)
2759                        ieee->set_security(ieee->dev, &sec);
2760                break;
2761        }
2762
2763        case IEEE_PARAM_PRIVACY_INVOKED:
2764                ieee->privacy_invoked = value;
2765                break;
2766
2767        case IEEE_PARAM_AUTH_ALGS:
2768                ret = ieee80211_wpa_set_auth_algs(ieee, value);
2769                break;
2770
2771        case IEEE_PARAM_IEEE_802_1X:
2772                ieee->ieee802_1x = value;
2773                break;
2774        case IEEE_PARAM_WPAX_SELECT:
2775                // added for WPA2 mixed mode
2776                spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2777                ieee->wpax_type_set = 1;
2778                ieee->wpax_type_notify = value;
2779                spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2780                break;
2781
2782        default:
2783                printk("Unknown WPA param: %d\n", name);
2784                ret = -EOPNOTSUPP;
2785        }
2786
2787        return ret;
2788}
2789
2790/* implementation borrowed from hostap driver */
2791static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2792                                  struct ieee_param *param, int param_len)
2793{
2794        int ret = 0;
2795        const char *module = NULL;
2796
2797        struct ieee80211_crypto_ops *ops = NULL;
2798        struct ieee80211_crypt_data **crypt;
2799
2800        struct ieee80211_security sec = {
2801                .flags = 0,
2802        };
2803
2804        param->u.crypt.err = 0;
2805        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2806
2807        if (param_len !=
2808            (int)((char *)param->u.crypt.key - (char *)param) +
2809            param->u.crypt.key_len) {
2810                printk("Len mismatch %d, %d\n", param_len,
2811                               param->u.crypt.key_len);
2812                return -EINVAL;
2813        }
2814        if (is_broadcast_ether_addr(param->sta_addr)) {
2815                if (param->u.crypt.idx >= WEP_KEYS)
2816                        return -EINVAL;
2817                crypt = &ieee->crypt[param->u.crypt.idx];
2818        } else {
2819                return -EINVAL;
2820        }
2821
2822        if (strcmp(param->u.crypt.alg, "none") == 0) {
2823                if (crypt) {
2824                        sec.enabled = 0;
2825                        // FIXME FIXME
2826                        //sec.encrypt = 0;
2827                        sec.level = SEC_LEVEL_0;
2828                        sec.flags |= SEC_ENABLED | SEC_LEVEL;
2829                        ieee80211_crypt_delayed_deinit(ieee, crypt);
2830                }
2831                goto done;
2832        }
2833        sec.enabled = 1;
2834// FIXME FIXME
2835//      sec.encrypt = 1;
2836        sec.flags |= SEC_ENABLED;
2837
2838        /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2839        if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2840            strcmp(param->u.crypt.alg, "TKIP"))
2841                goto skip_host_crypt;
2842
2843        //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
2844        if (!strcmp(param->u.crypt.alg, "WEP"))
2845                module = "ieee80211_crypt_wep";
2846        else if (!strcmp(param->u.crypt.alg, "TKIP"))
2847                module = "ieee80211_crypt_tkip";
2848        else if (!strcmp(param->u.crypt.alg, "CCMP"))
2849                module = "ieee80211_crypt_ccmp";
2850        if (module)
2851                ops = try_then_request_module(ieee80211_get_crypto_ops(param->u.crypt.alg),
2852                                              module);
2853        if (!ops) {
2854                printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
2855                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
2856                ret = -EINVAL;
2857                goto done;
2858        }
2859
2860        if (!*crypt || (*crypt)->ops != ops) {
2861                struct ieee80211_crypt_data *new_crypt;
2862
2863                ieee80211_crypt_delayed_deinit(ieee, crypt);
2864
2865                new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
2866                if (!new_crypt) {
2867                        ret = -ENOMEM;
2868                        goto done;
2869                }
2870                new_crypt->ops = ops;
2871                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
2872                        new_crypt->priv =
2873                                new_crypt->ops->init(param->u.crypt.idx);
2874
2875                if (!new_crypt->priv) {
2876                        kfree(new_crypt);
2877                        param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
2878                        ret = -EINVAL;
2879                        goto done;
2880                }
2881
2882                *crypt = new_crypt;
2883        }
2884
2885        if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
2886            (*crypt)->ops->set_key(param->u.crypt.key,
2887                                   param->u.crypt.key_len, param->u.crypt.seq,
2888                                   (*crypt)->priv) < 0) {
2889                printk("key setting failed\n");
2890                param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
2891                ret = -EINVAL;
2892                goto done;
2893        }
2894
2895 skip_host_crypt:
2896        if (param->u.crypt.set_tx) {
2897                ieee->tx_keyidx = param->u.crypt.idx;
2898                sec.active_key = param->u.crypt.idx;
2899                sec.flags |= SEC_ACTIVE_KEY;
2900        } else {
2901                sec.flags &= ~SEC_ACTIVE_KEY;
2902        }
2903        memcpy(sec.keys[param->u.crypt.idx],
2904               param->u.crypt.key,
2905               param->u.crypt.key_len);
2906        sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
2907        sec.flags |= (1 << param->u.crypt.idx);
2908
2909        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2910                sec.flags |= SEC_LEVEL;
2911                sec.level = SEC_LEVEL_1;
2912        } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2913                sec.flags |= SEC_LEVEL;
2914                sec.level = SEC_LEVEL_2;
2915        } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2916                sec.flags |= SEC_LEVEL;
2917                sec.level = SEC_LEVEL_3;
2918        }
2919 done:
2920        if (ieee->set_security)
2921                ieee->set_security(ieee->dev, &sec);
2922
2923        /* Do not reset port if card is in Managed mode since resetting will
2924         * generate new IEEE 802.11 authentication which may end up in looping
2925         * with IEEE 802.1X.  If your hardware requires a reset after WEP
2926         * configuration (for example... Prism2), implement the reset_port in
2927         * the callbacks structures used to initialize the 802.11 stack. */
2928        if (ieee->reset_on_keychange &&
2929            ieee->iw_mode != IW_MODE_INFRA &&
2930            ieee->reset_port &&
2931            ieee->reset_port(ieee->dev)) {
2932                printk("reset_port failed\n");
2933                param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
2934                return -EINVAL;
2935        }
2936
2937        return ret;
2938}
2939
2940static inline struct sk_buff *ieee80211_disassociate_skb(struct ieee80211_network *beacon,
2941                                                         struct ieee80211_device *ieee,
2942                                                         u8     asRsn)
2943{
2944        struct sk_buff *skb;
2945        struct ieee80211_disassoc *disass;
2946
2947        skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
2948        if (!skb)
2949                return NULL;
2950
2951        disass = skb_put(skb, sizeof(struct ieee80211_disassoc));
2952        disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
2953        disass->header.duration_id = 0;
2954
2955        memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
2956        memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
2957        memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
2958
2959        disass->reason = cpu_to_le16(asRsn);
2960        return skb;
2961}
2962
2963void
2964SendDisassociation(struct ieee80211_device *ieee,
2965                   u8                      *asSta,
2966                   u8                       asRsn
2967)
2968{
2969        struct ieee80211_network *beacon = &ieee->current_network;
2970        struct sk_buff *skb;
2971
2972        skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
2973        if (skb) {
2974                softmac_mgmt_xmit(skb, ieee);
2975                //dev_kfree_skb_any(skb);//edit by thomas
2976        }
2977}
2978EXPORT_SYMBOL(SendDisassociation);
2979
2980int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
2981{
2982        struct ieee_param *param;
2983        int ret = 0;
2984
2985        mutex_lock(&ieee->wx_mutex);
2986        //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
2987
2988        if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2989                ret = -EINVAL;
2990                goto out;
2991        }
2992
2993        param = memdup_user(p->pointer, p->length);
2994        if (IS_ERR(param)) {
2995                ret = PTR_ERR(param);
2996                goto out;
2997        }
2998
2999        switch (param->cmd) {
3000        case IEEE_CMD_SET_WPA_PARAM:
3001                ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3002                                        param->u.wpa_param.value);
3003                break;
3004
3005        case IEEE_CMD_SET_WPA_IE:
3006                ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3007                break;
3008
3009        case IEEE_CMD_SET_ENCRYPTION:
3010                ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3011                break;
3012
3013        case IEEE_CMD_MLME:
3014                ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3015                                   param->u.mlme.reason_code);
3016                break;
3017
3018        default:
3019                printk("Unknown WPA supplicant request: %d\n", param->cmd);
3020                ret = -EOPNOTSUPP;
3021                break;
3022        }
3023
3024        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3025                ret = -EFAULT;
3026
3027        kfree(param);
3028out:
3029        mutex_unlock(&ieee->wx_mutex);
3030
3031        return ret;
3032}
3033EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3034
3035void notify_wx_assoc_event(struct ieee80211_device *ieee)
3036{
3037        union iwreq_data wrqu;
3038
3039        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3040        if (ieee->state == IEEE80211_LINKED)
3041                memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3042        else
3043                eth_zero_addr(wrqu.ap_addr.sa_data);
3044        wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3045}
3046EXPORT_SYMBOL(notify_wx_assoc_event);
3047