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 placing the RATE MFIE
  37 * tag and the EXTENDED RATE MFIE tag if needed.
  38 * It includes 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/* place the MFIE rate, tag to the memory (double) pointer.
  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 temporarily '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 having the RX path possibly
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 check 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;
1915
1916                        network = kzalloc(sizeof(*network), GFP_KERNEL);
1917                        if (!network)
1918                                return -ENOMEM;
1919
1920                        errcode = assoc_parse(ieee, skb, &aid);
1921                        if (!errcode) {
1922                                ieee->state = IEEE80211_LINKED;
1923                                ieee->assoc_id = aid;
1924                                ieee->softmac_stats.rx_ass_ok++;
1925                                /* station support qos */
1926                                /* Let the register setting defaultly with Legacy station */
1927                                if (ieee->qos_support) {
1928                                        assoc_resp = (struct ieee80211_assoc_response_frame *)skb->data;
1929                                        if (ieee80211_parse_info_param(ieee, assoc_resp->info_element,\
1930                                                                       rx_stats->len - sizeof(*assoc_resp), \
1931                                                                       network, rx_stats)) {
1932                                                return 1;
1933                                        } else {
1934                                                //filling the PeerHTCap. //maybe not necessary as we can get its info from current_network.
1935                                                memcpy(ieee->pHTInfo->PeerHTCapBuf, network->bssht.bdHTCapBuf, network->bssht.bdHTCapLen);
1936                                                memcpy(ieee->pHTInfo->PeerHTInfoBuf, network->bssht.bdHTInfoBuf, network->bssht.bdHTInfoLen);
1937                                        }
1938                                        if (ieee->handle_assoc_response)
1939                                                ieee->handle_assoc_response(ieee->dev, (struct ieee80211_assoc_response_frame *)header, network);
1940                                }
1941                                ieee80211_associate_complete(ieee);
1942                        } else {
1943                                /* aid could not been allocated */
1944                                ieee->softmac_stats.rx_ass_err++;
1945                                printk("Association response status code 0x%x\n",
1946                                       errcode);
1947                                IEEE80211_DEBUG_MGMT("Association response status code 0x%x\n",
1948                                                     errcode);
1949                                if (ieee->AsocRetryCount < RT_ASOC_RETRY_LIMIT)
1950                                        schedule_work(&ieee->associate_procedure_wq);
1951                                else
1952                                        ieee80211_associate_abort(ieee);
1953                        }
1954                        kfree(network);
1955                }
1956                break;
1957
1958        case IEEE80211_STYPE_ASSOC_REQ:
1959        case IEEE80211_STYPE_REASSOC_REQ:
1960                if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1961                    ieee->iw_mode == IW_MODE_MASTER)
1962                        ieee80211_rx_assoc_rq(ieee, skb);
1963                break;
1964
1965        case IEEE80211_STYPE_AUTH:
1966                if (ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) {
1967                        if (ieee->state == IEEE80211_ASSOCIATING_AUTHENTICATING
1968                            && ieee->iw_mode == IW_MODE_INFRA) {
1969                                IEEE80211_DEBUG_MGMT("Received auth response");
1970                                ieee80211_check_auth_response(ieee, skb);
1971                        } else if (ieee->iw_mode == IW_MODE_MASTER) {
1972                                ieee80211_rx_auth_rq(ieee, skb);
1973                        }
1974                }
1975                break;
1976
1977        case IEEE80211_STYPE_PROBE_REQ:
1978                if ((ieee->softmac_features & IEEE_SOFTMAC_PROBERS) &&
1979                    ((ieee->iw_mode == IW_MODE_ADHOC ||
1980                      ieee->iw_mode == IW_MODE_MASTER) &&
1981                     ieee->state == IEEE80211_LINKED)) {
1982                        ieee80211_rx_probe_rq(ieee, skb);
1983                }
1984                break;
1985
1986        case IEEE80211_STYPE_DISASSOC:
1987        case IEEE80211_STYPE_DEAUTH:
1988                /* FIXME for now repeat all the association procedure
1989                * both for disassociation and deauthentication
1990                */
1991                if ((ieee->softmac_features & IEEE_SOFTMAC_ASSOCIATE) &&
1992                    ieee->state == IEEE80211_LINKED &&
1993                    ieee->iw_mode == IW_MODE_INFRA) {
1994                        ieee->state = IEEE80211_ASSOCIATING;
1995                        ieee->softmac_stats.reassoc++;
1996
1997                        notify_wx_assoc_event(ieee);
1998                        //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
1999                        RemovePeerTS(ieee, header->addr2);
2000                        schedule_work(&ieee->associate_procedure_wq);
2001                }
2002                break;
2003        case IEEE80211_STYPE_MANAGE_ACT:
2004                ieee80211_process_action(ieee, skb);
2005                break;
2006        default:
2007                return -1;
2008        }
2009
2010        //dev_kfree_skb_any(skb);
2011        return 0;
2012}
2013
2014/* The following are for a simpler TX queue management.
2015 * Instead of using netif_[stop/wake]_queue, the driver
2016 * will use these two functions (plus a reset one) that
2017 * will internally call the kernel netif_* and take care
2018 * of the ieee802.11 fragmentation.
2019 * So, the driver receives a fragment at a time and might
2020 * call the stop function when it wants, without taking
2021 * care to have enough room to TX an entire packet.
2022 * This might be useful if each fragment needs its own
2023 * descriptor. Thus, just keeping a total free memory > than
2024 * the max fragmentation threshold is not enough. If the
2025 * ieee802.11 stack passed a TXB struct, then you would need
2026 * to keep N free descriptors where
2027 * N = MAX_PACKET_SIZE / MIN_FRAG_THRESHOLD.
2028 * In this way you need just one and the 802.11 stack
2029 * will take care of buffering fragments and pass them to
2030 * to the driver later, when it wakes the queue.
2031 */
2032void ieee80211_softmac_xmit(struct ieee80211_txb *txb, struct ieee80211_device *ieee)
2033{
2034        unsigned int queue_index = txb->queue_index;
2035        unsigned long flags;
2036        int  i;
2037        struct cb_desc *tcb_desc = NULL;
2038
2039        spin_lock_irqsave(&ieee->lock, flags);
2040
2041        /* called with 2nd parm 0, no tx mgmt lock required */
2042        ieee80211_sta_wakeup(ieee, 0);
2043
2044        /* update the tx status */
2045        ieee->stats.tx_bytes += le16_to_cpu(txb->payload_size);
2046        ieee->stats.tx_packets++;
2047        tcb_desc = (struct cb_desc *)(txb->fragments[0]->cb + MAX_DEV_ADDR_SIZE);
2048        if (tcb_desc->bMulticast)
2049                ieee->stats.multicast++;
2050
2051        /* if xmit available, just xmit it immediately, else just insert it to the wait queue */
2052        for (i = 0; i < txb->nr_frags; i++) {
2053#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2054                if ((skb_queue_len(&ieee->skb_drv_aggQ[queue_index]) != 0) ||
2055#else
2056                if ((skb_queue_len(&ieee->skb_waitQ[queue_index]) != 0) ||
2057#endif
2058                    (!ieee->check_nic_enough_desc(ieee->dev, queue_index)) ||
2059                    (ieee->queue_stop)) {
2060                        /* insert the skb packet to the wait queue */
2061                        /* as for the completion function, it does not need
2062                         * to check it any more.
2063                         * */
2064                        //printk("error:no descriptor left@queue_index %d\n", queue_index);
2065                        //ieee80211_stop_queue(ieee);
2066#ifdef USB_TX_DRIVER_AGGREGATION_ENABLE
2067                        skb_queue_tail(&ieee->skb_drv_aggQ[queue_index], txb->fragments[i]);
2068#else
2069                        skb_queue_tail(&ieee->skb_waitQ[queue_index], txb->fragments[i]);
2070#endif
2071                } else {
2072                        ieee->softmac_data_hard_start_xmit(txb->fragments[i],
2073                                                           ieee->dev, ieee->rate);
2074                        //ieee->stats.tx_packets++;
2075                        //ieee->stats.tx_bytes += txb->fragments[i]->len;
2076                        //ieee->dev->trans_start = jiffies;
2077                }
2078        }
2079        ieee80211_txb_free(txb);
2080
2081//exit:
2082        spin_unlock_irqrestore(&ieee->lock, flags);
2083}
2084EXPORT_SYMBOL(ieee80211_softmac_xmit);
2085
2086/* called with ieee->lock acquired */
2087static void ieee80211_resume_tx(struct ieee80211_device *ieee)
2088{
2089        int i;
2090        for (i = ieee->tx_pending.frag; i < ieee->tx_pending.txb->nr_frags; i++) {
2091                if (ieee->queue_stop) {
2092                        ieee->tx_pending.frag = i;
2093                        return;
2094                } else {
2095                        ieee->softmac_data_hard_start_xmit(ieee->tx_pending.txb->fragments[i],
2096                                                           ieee->dev, ieee->rate);
2097                        //(i+1)<ieee->tx_pending.txb->nr_frags);
2098                        ieee->stats.tx_packets++;
2099                        netif_trans_update(ieee->dev);
2100                }
2101        }
2102
2103        ieee80211_txb_free(ieee->tx_pending.txb);
2104        ieee->tx_pending.txb = NULL;
2105}
2106
2107void ieee80211_reset_queue(struct ieee80211_device *ieee)
2108{
2109        unsigned long flags;
2110
2111        spin_lock_irqsave(&ieee->lock, flags);
2112        init_mgmt_queue(ieee);
2113        if (ieee->tx_pending.txb) {
2114                ieee80211_txb_free(ieee->tx_pending.txb);
2115                ieee->tx_pending.txb = NULL;
2116        }
2117        ieee->queue_stop = 0;
2118        spin_unlock_irqrestore(&ieee->lock, flags);
2119}
2120EXPORT_SYMBOL(ieee80211_reset_queue);
2121
2122void ieee80211_wake_queue(struct ieee80211_device *ieee)
2123{
2124        unsigned long flags;
2125        struct sk_buff *skb;
2126        struct rtl_80211_hdr_3addr  *header;
2127
2128        spin_lock_irqsave(&ieee->lock, flags);
2129        if (!ieee->queue_stop)
2130                goto exit;
2131
2132        ieee->queue_stop = 0;
2133
2134        if (ieee->softmac_features & IEEE_SOFTMAC_SINGLE_QUEUE) {
2135                while (!ieee->queue_stop && (skb = dequeue_mgmt(ieee))) {
2136                        header = (struct rtl_80211_hdr_3addr  *)skb->data;
2137
2138                        header->seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2139
2140                        if (ieee->seq_ctrl[0] == 0xFFF)
2141                                ieee->seq_ctrl[0] = 0;
2142                        else
2143                                ieee->seq_ctrl[0]++;
2144
2145                        ieee->softmac_data_hard_start_xmit(skb, ieee->dev, ieee->basic_rate);
2146                        //dev_kfree_skb_any(skb);//edit by thomas
2147                }
2148        }
2149        if (!ieee->queue_stop && ieee->tx_pending.txb)
2150                ieee80211_resume_tx(ieee);
2151
2152        if (!ieee->queue_stop && netif_queue_stopped(ieee->dev)) {
2153                ieee->softmac_stats.swtxawake++;
2154                netif_wake_queue(ieee->dev);
2155        }
2156exit:
2157        spin_unlock_irqrestore(&ieee->lock, flags);
2158}
2159EXPORT_SYMBOL(ieee80211_wake_queue);
2160
2161void ieee80211_stop_queue(struct ieee80211_device *ieee)
2162{
2163        //unsigned long flags;
2164        //spin_lock_irqsave(&ieee->lock,flags);
2165
2166        if (!netif_queue_stopped(ieee->dev)) {
2167                netif_stop_queue(ieee->dev);
2168                ieee->softmac_stats.swtxstop++;
2169        }
2170        ieee->queue_stop = 1;
2171        //spin_unlock_irqrestore(&ieee->lock,flags);
2172}
2173EXPORT_SYMBOL(ieee80211_stop_queue);
2174
2175/* called in user context only */
2176void ieee80211_start_master_bss(struct ieee80211_device *ieee)
2177{
2178        ieee->assoc_id = 1;
2179
2180        if (ieee->current_network.ssid_len == 0) {
2181                strncpy(ieee->current_network.ssid,
2182                        IEEE80211_DEFAULT_TX_ESSID,
2183                        IW_ESSID_MAX_SIZE);
2184
2185                ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2186                ieee->ssid_set = 1;
2187        }
2188
2189        memcpy(ieee->current_network.bssid, ieee->dev->dev_addr, ETH_ALEN);
2190
2191        ieee->set_chan(ieee->dev, ieee->current_network.channel);
2192        ieee->state = IEEE80211_LINKED;
2193        ieee->link_change(ieee->dev);
2194        notify_wx_assoc_event(ieee);
2195
2196        if (ieee->data_hard_resume)
2197                ieee->data_hard_resume(ieee->dev);
2198
2199        netif_carrier_on(ieee->dev);
2200}
2201
2202static void ieee80211_start_monitor_mode(struct ieee80211_device *ieee)
2203{
2204        if (ieee->raw_tx) {
2205                if (ieee->data_hard_resume)
2206                        ieee->data_hard_resume(ieee->dev);
2207
2208                netif_carrier_on(ieee->dev);
2209        }
2210}
2211static void ieee80211_start_ibss_wq(struct work_struct *work)
2212{
2213        struct delayed_work *dwork = to_delayed_work(work);
2214        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, start_ibss_wq);
2215        /* iwconfig mode ad-hoc will schedule this and return
2216         * on the other hand this will block further iwconfig SET
2217         * operations because of the wx_mutex hold.
2218         * Anyway some most set operations set a flag to speed-up
2219         * (abort) this wq (when syncro scanning) before sleeping
2220         * on the semaphore
2221         */
2222        if (!ieee->proto_started) {
2223                printk("==========oh driver down return\n");
2224                return;
2225        }
2226        mutex_lock(&ieee->wx_mutex);
2227
2228        if (ieee->current_network.ssid_len == 0) {
2229                strscpy(ieee->current_network.ssid, IEEE80211_DEFAULT_TX_ESSID,
2230                        sizeof(ieee->current_network.ssid));
2231                ieee->current_network.ssid_len = strlen(IEEE80211_DEFAULT_TX_ESSID);
2232                ieee->ssid_set = 1;
2233        }
2234
2235        /* check if we have this cell in our network list */
2236        ieee80211_softmac_check_all_nets(ieee);
2237
2238//      if((IS_DOT11D_ENABLE(ieee)) && (ieee->state == IEEE80211_NOLINK))
2239        if (ieee->state == IEEE80211_NOLINK)
2240                ieee->current_network.channel = 6;
2241        /* if not then the state is not linked. Maybe the user switched to
2242         * ad-hoc mode just after being in monitor mode, or just after
2243         * being very few time in managed mode (so the card have had no
2244         * time to scan all the chans..) or we have just run up the iface
2245         * after setting ad-hoc mode. So we have to give another try..
2246         * Here, in ibss mode, should be safe to do this without extra care
2247         * (in bss mode we had to make sure no-one tried to associate when
2248         * we had just checked the ieee->state and we was going to start the
2249         * scan) because in ibss mode the ieee80211_new_net function, when
2250         * finds a good net, just set the ieee->state to IEEE80211_LINKED,
2251         * so, at worst, we waste a bit of time to initiate an unneeded syncro
2252         * scan, that will stop at the first round because it sees the state
2253         * associated.
2254         */
2255        if (ieee->state == IEEE80211_NOLINK)
2256                ieee80211_start_scan_syncro(ieee);
2257
2258        /* the network definitively is not here.. create a new cell */
2259        if (ieee->state == IEEE80211_NOLINK) {
2260                printk("creating new IBSS cell\n");
2261                if (!ieee->wap_set)
2262                        eth_random_addr(ieee->current_network.bssid);
2263
2264                if (ieee->modulation & IEEE80211_CCK_MODULATION) {
2265                        ieee->current_network.rates_len = 4;
2266
2267                        ieee->current_network.rates[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
2268                        ieee->current_network.rates[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
2269                        ieee->current_network.rates[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
2270                        ieee->current_network.rates[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
2271                } else {
2272                        ieee->current_network.rates_len = 0;
2273                }
2274                if (ieee->modulation & IEEE80211_OFDM_MODULATION) {
2275                        ieee->current_network.rates_ex_len = 8;
2276
2277                        ieee->current_network.rates_ex[0] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
2278                        ieee->current_network.rates_ex[1] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
2279                        ieee->current_network.rates_ex[2] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
2280                        ieee->current_network.rates_ex[3] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
2281                        ieee->current_network.rates_ex[4] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
2282                        ieee->current_network.rates_ex[5] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
2283                        ieee->current_network.rates_ex[6] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
2284                        ieee->current_network.rates_ex[7] = IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
2285
2286                        ieee->rate = 108;
2287                } else {
2288                        ieee->current_network.rates_ex_len = 0;
2289                        ieee->rate = 22;
2290                }
2291
2292                // By default, WMM function will be disabled in IBSS mode
2293                ieee->current_network.QoS_Enable = 0;
2294                ieee->SetWirelessMode(ieee->dev, IEEE_G);
2295                ieee->current_network.atim_window = 0;
2296                ieee->current_network.capability = WLAN_CAPABILITY_IBSS;
2297                if (ieee->short_slot)
2298                        ieee->current_network.capability |= WLAN_CAPABILITY_SHORT_SLOT;
2299        }
2300
2301        ieee->state = IEEE80211_LINKED;
2302
2303        ieee->set_chan(ieee->dev, ieee->current_network.channel);
2304        ieee->link_change(ieee->dev);
2305
2306        notify_wx_assoc_event(ieee);
2307
2308        ieee80211_start_send_beacons(ieee);
2309
2310        if (ieee->data_hard_resume)
2311                ieee->data_hard_resume(ieee->dev);
2312        netif_carrier_on(ieee->dev);
2313
2314        mutex_unlock(&ieee->wx_mutex);
2315}
2316
2317inline void ieee80211_start_ibss(struct ieee80211_device *ieee)
2318{
2319        schedule_delayed_work(&ieee->start_ibss_wq, 150);
2320}
2321
2322/* this is called only in user context, with wx_mutex held */
2323void ieee80211_start_bss(struct ieee80211_device *ieee)
2324{
2325        unsigned long flags;
2326        //
2327        // Ref: 802.11d 11.1.3.3
2328        // STA shall not start a BSS unless properly formed Beacon frame including a Country IE.
2329        //
2330        if (IS_DOT11D_ENABLE(ieee) && !IS_COUNTRY_IE_VALID(ieee)) {
2331                if (!ieee->bGlobalDomain)
2332                        return;
2333        }
2334        /* check if we have already found the net we
2335         * are interested in (if any).
2336         * if not (we are disassociated and we are not
2337         * in associating / authenticating phase) start the background scanning.
2338         */
2339        ieee80211_softmac_check_all_nets(ieee);
2340
2341        /* ensure no-one start an associating process (thus setting
2342         * the ieee->state to ieee80211_ASSOCIATING) while we
2343         * have just checked it and we are going to enable scan.
2344         * The ieee80211_new_net function is always called with
2345         * lock held (from both ieee80211_softmac_check_all_nets and
2346         * the rx path), so we cannot be in the middle of such function
2347         */
2348        spin_lock_irqsave(&ieee->lock, flags);
2349
2350        if (ieee->state == IEEE80211_NOLINK) {
2351                ieee->actscanning = true;
2352                ieee80211_start_scan(ieee);
2353        }
2354        spin_unlock_irqrestore(&ieee->lock, flags);
2355}
2356
2357/* called only in userspace context */
2358void ieee80211_disassociate(struct ieee80211_device *ieee)
2359{
2360        netif_carrier_off(ieee->dev);
2361        if (ieee->softmac_features & IEEE_SOFTMAC_TX_QUEUE)
2362                ieee80211_reset_queue(ieee);
2363
2364        if (ieee->data_hard_stop)
2365                ieee->data_hard_stop(ieee->dev);
2366        if (IS_DOT11D_ENABLE(ieee))
2367                dot11d_reset(ieee);
2368        ieee->state = IEEE80211_NOLINK;
2369        ieee->is_set_key = false;
2370        ieee->link_change(ieee->dev);
2371        //HTSetConnectBwMode(ieee, HT_CHANNEL_WIDTH_20, HT_EXTCHNL_OFFSET_NO_EXT);
2372        notify_wx_assoc_event(ieee);
2373}
2374EXPORT_SYMBOL(ieee80211_disassociate);
2375
2376static void ieee80211_associate_retry_wq(struct work_struct *work)
2377{
2378        struct delayed_work *dwork = to_delayed_work(work);
2379        struct ieee80211_device *ieee = container_of(dwork, struct ieee80211_device, associate_retry_wq);
2380        unsigned long flags;
2381
2382        mutex_lock(&ieee->wx_mutex);
2383        if (!ieee->proto_started)
2384                goto exit;
2385
2386        if (ieee->state != IEEE80211_ASSOCIATING_RETRY)
2387                goto exit;
2388
2389        /* until we do not set the state to IEEE80211_NOLINK
2390        * there are no possibility to have someone else trying
2391        * to start an association procedure (we get here with
2392        * ieee->state = IEEE80211_ASSOCIATING).
2393        * When we set the state to IEEE80211_NOLINK it is possible
2394        * that the RX path run an attempt to associate, but
2395        * both ieee80211_softmac_check_all_nets and the
2396        * RX path works with ieee->lock held so there are no
2397        * problems. If we are still disassociated then start a scan.
2398        * the lock here is necessary to ensure no one try to start
2399        * an association procedure when we have just checked the
2400        * state and we are going to start the scan.
2401        */
2402        ieee->state = IEEE80211_NOLINK;
2403
2404        ieee80211_softmac_check_all_nets(ieee);
2405
2406        spin_lock_irqsave(&ieee->lock, flags);
2407
2408        if (ieee->state == IEEE80211_NOLINK)
2409                ieee80211_start_scan(ieee);
2410
2411        spin_unlock_irqrestore(&ieee->lock, flags);
2412
2413exit:
2414        mutex_unlock(&ieee->wx_mutex);
2415}
2416
2417struct sk_buff *ieee80211_get_beacon_(struct ieee80211_device *ieee)
2418{
2419        u8 broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
2420
2421        struct sk_buff *skb;
2422        struct ieee80211_probe_response *b;
2423
2424        skb = ieee80211_probe_resp(ieee, broadcast_addr);
2425
2426        if (!skb)
2427                return NULL;
2428
2429        b = (struct ieee80211_probe_response *)skb->data;
2430        b->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_BEACON);
2431
2432        return skb;
2433}
2434
2435struct sk_buff *ieee80211_get_beacon(struct ieee80211_device *ieee)
2436{
2437        struct sk_buff *skb;
2438        struct ieee80211_probe_response *b;
2439
2440        skb = ieee80211_get_beacon_(ieee);
2441        if (!skb)
2442                return NULL;
2443
2444        b = (struct ieee80211_probe_response *)skb->data;
2445        b->header.seq_ctl = cpu_to_le16(ieee->seq_ctrl[0] << 4);
2446
2447        if (ieee->seq_ctrl[0] == 0xFFF)
2448                ieee->seq_ctrl[0] = 0;
2449        else
2450                ieee->seq_ctrl[0]++;
2451
2452        return skb;
2453}
2454EXPORT_SYMBOL(ieee80211_get_beacon);
2455
2456void ieee80211_softmac_stop_protocol(struct ieee80211_device *ieee)
2457{
2458        ieee->sync_scan_hurryup = 1;
2459        mutex_lock(&ieee->wx_mutex);
2460        ieee80211_stop_protocol(ieee);
2461        mutex_unlock(&ieee->wx_mutex);
2462}
2463EXPORT_SYMBOL(ieee80211_softmac_stop_protocol);
2464
2465void ieee80211_stop_protocol(struct ieee80211_device *ieee)
2466{
2467        if (!ieee->proto_started)
2468                return;
2469
2470        ieee->proto_started = 0;
2471
2472        ieee80211_stop_send_beacons(ieee);
2473        del_timer_sync(&ieee->associate_timer);
2474        cancel_delayed_work(&ieee->associate_retry_wq);
2475        cancel_delayed_work(&ieee->start_ibss_wq);
2476        ieee80211_stop_scan(ieee);
2477
2478        ieee80211_disassociate(ieee);
2479        RemoveAllTS(ieee); //added as we disconnect from the previous BSS, Remove all TS
2480}
2481
2482void ieee80211_softmac_start_protocol(struct ieee80211_device *ieee)
2483{
2484        ieee->sync_scan_hurryup = 0;
2485        mutex_lock(&ieee->wx_mutex);
2486        ieee80211_start_protocol(ieee);
2487        mutex_unlock(&ieee->wx_mutex);
2488}
2489EXPORT_SYMBOL(ieee80211_softmac_start_protocol);
2490
2491void ieee80211_start_protocol(struct ieee80211_device *ieee)
2492{
2493        short ch = 0;
2494        int i = 0;
2495
2496        if (ieee->proto_started)
2497                return;
2498
2499        ieee->proto_started = 1;
2500
2501        if (ieee->current_network.channel == 0) {
2502                do {
2503                        ch++;
2504                        if (ch > MAX_CHANNEL_NUMBER)
2505                                return; /* no channel found */
2506                } while (!GET_DOT11D_INFO(ieee)->channel_map[ch]);
2507                ieee->current_network.channel = ch;
2508        }
2509
2510        if (ieee->current_network.beacon_interval == 0)
2511                ieee->current_network.beacon_interval = 100;
2512//      printk("===>%s(), chan:%d\n", __func__, ieee->current_network.channel);
2513//      ieee->set_chan(ieee->dev,ieee->current_network.channel);
2514
2515        for (i = 0; i < 17; i++) {
2516                ieee->last_rxseq_num[i] = -1;
2517                ieee->last_rxfrag_num[i] = -1;
2518                ieee->last_packet_time[i] = 0;
2519        }
2520
2521        ieee->init_wmmparam_flag = 0;//reinitialize AC_xx_PARAM registers.
2522
2523        /* if the user set the MAC of the ad-hoc cell and then
2524         * switch to managed mode, shall we  make sure that association
2525         * attempts does not fail just because the user provide the essid
2526         * and the nic is still checking for the AP MAC ??
2527         */
2528        if (ieee->iw_mode == IW_MODE_INFRA)
2529                ieee80211_start_bss(ieee);
2530
2531        else if (ieee->iw_mode == IW_MODE_ADHOC)
2532                ieee80211_start_ibss(ieee);
2533
2534        else if (ieee->iw_mode == IW_MODE_MASTER)
2535                ieee80211_start_master_bss(ieee);
2536
2537        else if (ieee->iw_mode == IW_MODE_MONITOR)
2538                ieee80211_start_monitor_mode(ieee);
2539}
2540
2541#define DRV_NAME  "Ieee80211"
2542void ieee80211_softmac_init(struct ieee80211_device *ieee)
2543{
2544        int i;
2545        memset(&ieee->current_network, 0, sizeof(struct ieee80211_network));
2546
2547        ieee->state = IEEE80211_NOLINK;
2548        ieee->sync_scan_hurryup = 0;
2549        for (i = 0; i < 5; i++)
2550                ieee->seq_ctrl[i] = 0;
2551
2552        ieee->dot11d_info = kzalloc(sizeof(struct rt_dot11d_info), GFP_KERNEL);
2553        if (!ieee->dot11d_info)
2554                IEEE80211_DEBUG(IEEE80211_DL_ERR, "can't alloc memory for DOT11D\n");
2555        //added for  AP roaming
2556        ieee->LinkDetectInfo.SlotNum = 2;
2557        ieee->LinkDetectInfo.NumRecvBcnInPeriod = 0;
2558        ieee->LinkDetectInfo.NumRecvDataInPeriod = 0;
2559
2560        ieee->assoc_id = 0;
2561        ieee->queue_stop = 0;
2562        ieee->scanning = 0;
2563        ieee->softmac_features = 0; //so IEEE2100-like driver are happy
2564        ieee->wap_set = 0;
2565        ieee->ssid_set = 0;
2566        ieee->proto_started = 0;
2567        ieee->basic_rate = IEEE80211_DEFAULT_BASIC_RATE;
2568        ieee->rate = 22;
2569        ieee->ps = IEEE80211_PS_DISABLED;
2570        ieee->sta_sleep = 0;
2571        ieee->Regdot11HTOperationalRateSet[0] = 0xff;//support MCS 0~7
2572        ieee->Regdot11HTOperationalRateSet[1] = 0xff;//support MCS 8~15
2573        ieee->Regdot11HTOperationalRateSet[4] = 0x01;
2574        //added by amy
2575        ieee->actscanning = false;
2576        ieee->beinretry = false;
2577        ieee->is_set_key = false;
2578        init_mgmt_queue(ieee);
2579
2580        ieee->sta_edca_param[0] = 0x0000A403;
2581        ieee->sta_edca_param[1] = 0x0000A427;
2582        ieee->sta_edca_param[2] = 0x005E4342;
2583        ieee->sta_edca_param[3] = 0x002F3262;
2584        ieee->aggregation = true;
2585        ieee->enable_rx_imm_BA = true;
2586        ieee->tx_pending.txb = NULL;
2587
2588        timer_setup(&ieee->associate_timer, ieee80211_associate_abort_cb, 0);
2589
2590        timer_setup(&ieee->beacon_timer, ieee80211_send_beacon_cb, 0);
2591
2592        INIT_DELAYED_WORK(&ieee->start_ibss_wq, ieee80211_start_ibss_wq);
2593        INIT_WORK(&ieee->associate_complete_wq, ieee80211_associate_complete_wq);
2594        INIT_WORK(&ieee->associate_procedure_wq, ieee80211_associate_procedure_wq);
2595        INIT_DELAYED_WORK(&ieee->softmac_scan_wq, ieee80211_softmac_scan_wq);
2596        INIT_DELAYED_WORK(&ieee->associate_retry_wq, ieee80211_associate_retry_wq);
2597        INIT_WORK(&ieee->wx_sync_scan_wq, ieee80211_wx_sync_scan_wq);
2598
2599        mutex_init(&ieee->wx_mutex);
2600        mutex_init(&ieee->scan_mutex);
2601
2602        spin_lock_init(&ieee->mgmt_tx_lock);
2603        spin_lock_init(&ieee->beacon_lock);
2604
2605        tasklet_setup(&ieee->ps_task, ieee80211_sta_ps);
2606}
2607
2608void ieee80211_softmac_free(struct ieee80211_device *ieee)
2609{
2610        mutex_lock(&ieee->wx_mutex);
2611        kfree(ieee->dot11d_info);
2612        ieee->dot11d_info = NULL;
2613        del_timer_sync(&ieee->associate_timer);
2614
2615        cancel_delayed_work(&ieee->associate_retry_wq);
2616
2617        mutex_unlock(&ieee->wx_mutex);
2618}
2619
2620/********************************************************
2621 * Start of WPA code.                                   *
2622 * this is stolen from the ipw2200 driver               *
2623 ********************************************************/
2624static int ieee80211_wpa_enable(struct ieee80211_device *ieee, int value)
2625{
2626        /* This is called when wpa_supplicant loads and closes the driver
2627         * interface. */
2628        printk("%s WPA\n", value ? "enabling" : "disabling");
2629        ieee->wpa_enabled = value;
2630        return 0;
2631}
2632
2633static void ieee80211_wpa_assoc_frame(struct ieee80211_device *ieee,
2634                                      char *wpa_ie, int wpa_ie_len)
2635{
2636        /* make sure WPA is enabled */
2637        ieee80211_wpa_enable(ieee, 1);
2638
2639        ieee80211_disassociate(ieee);
2640}
2641
2642static int ieee80211_wpa_mlme(struct ieee80211_device *ieee, int command, int reason)
2643{
2644        int ret = 0;
2645
2646        switch (command) {
2647        case IEEE_MLME_STA_DEAUTH:
2648                // silently ignore
2649                break;
2650
2651        case IEEE_MLME_STA_DISASSOC:
2652                ieee80211_disassociate(ieee);
2653                break;
2654
2655        default:
2656                printk("Unknown MLME request: %d\n", command);
2657                ret = -EOPNOTSUPP;
2658        }
2659
2660        return ret;
2661}
2662
2663static int ieee80211_wpa_set_wpa_ie(struct ieee80211_device *ieee,
2664                              struct ieee_param *param, int plen)
2665{
2666        u8 *buf;
2667
2668        if (param->u.wpa_ie.len > MAX_WPA_IE_LEN)
2669                return -EINVAL;
2670
2671        if (param->u.wpa_ie.len) {
2672                buf = kmemdup(param->u.wpa_ie.data, param->u.wpa_ie.len,
2673                              GFP_KERNEL);
2674                if (!buf)
2675                        return -ENOMEM;
2676
2677                kfree(ieee->wpa_ie);
2678                ieee->wpa_ie = buf;
2679                ieee->wpa_ie_len = param->u.wpa_ie.len;
2680        } else {
2681                kfree(ieee->wpa_ie);
2682                ieee->wpa_ie = NULL;
2683                ieee->wpa_ie_len = 0;
2684        }
2685
2686        ieee80211_wpa_assoc_frame(ieee, ieee->wpa_ie, ieee->wpa_ie_len);
2687        return 0;
2688}
2689
2690#define AUTH_ALG_OPEN_SYSTEM                    0x1
2691#define AUTH_ALG_SHARED_KEY                     0x2
2692
2693static int ieee80211_wpa_set_auth_algs(struct ieee80211_device *ieee, int value)
2694{
2695        struct ieee80211_security sec = {
2696                .flags = SEC_AUTH_MODE,
2697        };
2698
2699        if (value & AUTH_ALG_SHARED_KEY) {
2700                sec.auth_mode = WLAN_AUTH_SHARED_KEY;
2701                ieee->open_wep = 0;
2702                ieee->auth_mode = 1;
2703        } else if (value & AUTH_ALG_OPEN_SYSTEM) {
2704                sec.auth_mode = WLAN_AUTH_OPEN;
2705                ieee->open_wep = 1;
2706                ieee->auth_mode = 0;
2707        } else if (value & IW_AUTH_ALG_LEAP) {
2708                sec.auth_mode = WLAN_AUTH_LEAP;
2709                ieee->open_wep = 1;
2710                ieee->auth_mode = 2;
2711        }
2712
2713        if (ieee->set_security)
2714                ieee->set_security(ieee->dev, &sec);
2715        //else
2716        //      ret = -EOPNOTSUPP;
2717
2718        return 0;
2719}
2720
2721static int ieee80211_wpa_set_param(struct ieee80211_device *ieee, u8 name, u32 value)
2722{
2723        int ret = 0;
2724        unsigned long flags;
2725
2726        switch (name) {
2727        case IEEE_PARAM_WPA_ENABLED:
2728                ret = ieee80211_wpa_enable(ieee, value);
2729                break;
2730
2731        case IEEE_PARAM_TKIP_COUNTERMEASURES:
2732                ieee->tkip_countermeasures = value;
2733                break;
2734
2735        case IEEE_PARAM_DROP_UNENCRYPTED: {
2736                /* HACK:
2737                 *
2738                 * wpa_supplicant calls set_wpa_enabled when the driver
2739                 * is loaded and unloaded, regardless of if WPA is being
2740                 * used.  No other calls are made which can be used to
2741                 * determine if encryption will be used or not prior to
2742                 * association being expected.  If encryption is not being
2743                 * used, drop_unencrypted is set to false, else true -- we
2744                 * can use this to determine if the CAP_PRIVACY_ON bit should
2745                 * be set.
2746                 */
2747                struct ieee80211_security sec = {
2748                        .flags = SEC_ENABLED,
2749                        .enabled = value,
2750                };
2751                ieee->drop_unencrypted = value;
2752                /* We only change SEC_LEVEL for open mode. Others
2753                 * are set by ipw_wpa_set_encryption.
2754                 */
2755                if (!value) {
2756                        sec.flags |= SEC_LEVEL;
2757                        sec.level = SEC_LEVEL_0;
2758                } else {
2759                        sec.flags |= SEC_LEVEL;
2760                        sec.level = SEC_LEVEL_1;
2761                }
2762                if (ieee->set_security)
2763                        ieee->set_security(ieee->dev, &sec);
2764                break;
2765        }
2766
2767        case IEEE_PARAM_PRIVACY_INVOKED:
2768                ieee->privacy_invoked = value;
2769                break;
2770
2771        case IEEE_PARAM_AUTH_ALGS:
2772                ret = ieee80211_wpa_set_auth_algs(ieee, value);
2773                break;
2774
2775        case IEEE_PARAM_IEEE_802_1X:
2776                ieee->ieee802_1x = value;
2777                break;
2778        case IEEE_PARAM_WPAX_SELECT:
2779                // added for WPA2 mixed mode
2780                spin_lock_irqsave(&ieee->wpax_suitlist_lock, flags);
2781                ieee->wpax_type_set = 1;
2782                ieee->wpax_type_notify = value;
2783                spin_unlock_irqrestore(&ieee->wpax_suitlist_lock, flags);
2784                break;
2785
2786        default:
2787                printk("Unknown WPA param: %d\n", name);
2788                ret = -EOPNOTSUPP;
2789        }
2790
2791        return ret;
2792}
2793
2794/* implementation borrowed from hostap driver */
2795static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
2796                                  struct ieee_param *param, int param_len)
2797{
2798        int ret = 0;
2799        const char *module = NULL;
2800
2801        struct ieee80211_crypto_ops *ops = NULL;
2802        struct ieee80211_crypt_data **crypt;
2803
2804        struct ieee80211_security sec = {
2805                .flags = 0,
2806        };
2807
2808        param->u.crypt.err = 0;
2809        param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
2810
2811        if (param_len !=
2812            (int)((char *)param->u.crypt.key - (char *)param) +
2813            param->u.crypt.key_len) {
2814                printk("Len mismatch %d, %d\n", param_len,
2815                               param->u.crypt.key_len);
2816                return -EINVAL;
2817        }
2818        if (is_broadcast_ether_addr(param->sta_addr)) {
2819                if (param->u.crypt.idx >= WEP_KEYS)
2820                        return -EINVAL;
2821                crypt = &ieee->crypt[param->u.crypt.idx];
2822        } else {
2823                return -EINVAL;
2824        }
2825
2826        if (strcmp(param->u.crypt.alg, "none") == 0) {
2827                if (crypt) {
2828                        sec.enabled = 0;
2829                        // FIXME FIXME
2830                        //sec.encrypt = 0;
2831                        sec.level = SEC_LEVEL_0;
2832                        sec.flags |= SEC_ENABLED | SEC_LEVEL;
2833                        ieee80211_crypt_delayed_deinit(ieee, crypt);
2834                }
2835                goto done;
2836        }
2837        sec.enabled = 1;
2838// FIXME FIXME
2839//      sec.encrypt = 1;
2840        sec.flags |= SEC_ENABLED;
2841
2842        /* IPW HW cannot build TKIP MIC, host decryption still needed. */
2843        if (!(ieee->host_encrypt || ieee->host_decrypt) &&
2844            strcmp(param->u.crypt.alg, "TKIP"))
2845                goto skip_host_crypt;
2846
2847        //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
2848        if (!strcmp(param->u.crypt.alg, "WEP"))
2849                module = "ieee80211_crypt_wep";
2850        else if (!strcmp(param->u.crypt.alg, "TKIP"))
2851                module = "ieee80211_crypt_tkip";
2852        else if (!strcmp(param->u.crypt.alg, "CCMP"))
2853                module = "ieee80211_crypt_ccmp";
2854        if (module)
2855                ops = try_then_request_module(ieee80211_get_crypto_ops(param->u.crypt.alg),
2856                                              module);
2857        if (!ops) {
2858                printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
2859                param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
2860                ret = -EINVAL;
2861                goto done;
2862        }
2863
2864        if (!*crypt || (*crypt)->ops != ops) {
2865                struct ieee80211_crypt_data *new_crypt;
2866
2867                ieee80211_crypt_delayed_deinit(ieee, crypt);
2868
2869                new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL);
2870                if (!new_crypt) {
2871                        ret = -ENOMEM;
2872                        goto done;
2873                }
2874                new_crypt->ops = ops;
2875                if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
2876                        new_crypt->priv =
2877                                new_crypt->ops->init(param->u.crypt.idx);
2878
2879                if (!new_crypt->priv) {
2880                        kfree(new_crypt);
2881                        param->u.crypt.err = IEEE_CRYPT_ERR_CRYPT_INIT_FAILED;
2882                        ret = -EINVAL;
2883                        goto done;
2884                }
2885
2886                *crypt = new_crypt;
2887        }
2888
2889        if (param->u.crypt.key_len > 0 && (*crypt)->ops->set_key &&
2890            (*crypt)->ops->set_key(param->u.crypt.key,
2891                                   param->u.crypt.key_len, param->u.crypt.seq,
2892                                   (*crypt)->priv) < 0) {
2893                printk("key setting failed\n");
2894                param->u.crypt.err = IEEE_CRYPT_ERR_KEY_SET_FAILED;
2895                ret = -EINVAL;
2896                goto done;
2897        }
2898
2899 skip_host_crypt:
2900        if (param->u.crypt.set_tx) {
2901                ieee->tx_keyidx = param->u.crypt.idx;
2902                sec.active_key = param->u.crypt.idx;
2903                sec.flags |= SEC_ACTIVE_KEY;
2904        } else {
2905                sec.flags &= ~SEC_ACTIVE_KEY;
2906        }
2907        memcpy(sec.keys[param->u.crypt.idx],
2908               param->u.crypt.key,
2909               param->u.crypt.key_len);
2910        sec.key_sizes[param->u.crypt.idx] = param->u.crypt.key_len;
2911        sec.flags |= (1 << param->u.crypt.idx);
2912
2913        if (strcmp(param->u.crypt.alg, "WEP") == 0) {
2914                sec.flags |= SEC_LEVEL;
2915                sec.level = SEC_LEVEL_1;
2916        } else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
2917                sec.flags |= SEC_LEVEL;
2918                sec.level = SEC_LEVEL_2;
2919        } else if (strcmp(param->u.crypt.alg, "CCMP") == 0) {
2920                sec.flags |= SEC_LEVEL;
2921                sec.level = SEC_LEVEL_3;
2922        }
2923 done:
2924        if (ieee->set_security)
2925                ieee->set_security(ieee->dev, &sec);
2926
2927        /* Do not reset port if card is in Managed mode since resetting will
2928         * generate new IEEE 802.11 authentication which may end up in looping
2929         * with IEEE 802.1X.  If your hardware requires a reset after WEP
2930         * configuration (for example... Prism2), implement the reset_port in
2931         * the callbacks structures used to initialize the 802.11 stack. */
2932        if (ieee->reset_on_keychange &&
2933            ieee->iw_mode != IW_MODE_INFRA &&
2934            ieee->reset_port &&
2935            ieee->reset_port(ieee->dev)) {
2936                printk("reset_port failed\n");
2937                param->u.crypt.err = IEEE_CRYPT_ERR_CARD_CONF_FAILED;
2938                return -EINVAL;
2939        }
2940
2941        return ret;
2942}
2943
2944static inline struct sk_buff *ieee80211_disassociate_skb(struct ieee80211_network *beacon,
2945                                                         struct ieee80211_device *ieee,
2946                                                         u8     asRsn)
2947{
2948        struct sk_buff *skb;
2949        struct ieee80211_disassoc *disass;
2950
2951        skb = dev_alloc_skb(sizeof(struct ieee80211_disassoc));
2952        if (!skb)
2953                return NULL;
2954
2955        disass = skb_put(skb, sizeof(struct ieee80211_disassoc));
2956        disass->header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_DISASSOC);
2957        disass->header.duration_id = 0;
2958
2959        memcpy(disass->header.addr1, beacon->bssid, ETH_ALEN);
2960        memcpy(disass->header.addr2, ieee->dev->dev_addr, ETH_ALEN);
2961        memcpy(disass->header.addr3, beacon->bssid, ETH_ALEN);
2962
2963        disass->reason = cpu_to_le16(asRsn);
2964        return skb;
2965}
2966
2967void
2968SendDisassociation(struct ieee80211_device *ieee,
2969                   u8                      *asSta,
2970                   u8                       asRsn
2971)
2972{
2973        struct ieee80211_network *beacon = &ieee->current_network;
2974        struct sk_buff *skb;
2975
2976        skb = ieee80211_disassociate_skb(beacon, ieee, asRsn);
2977        if (skb) {
2978                softmac_mgmt_xmit(skb, ieee);
2979                //dev_kfree_skb_any(skb);//edit by thomas
2980        }
2981}
2982EXPORT_SYMBOL(SendDisassociation);
2983
2984int ieee80211_wpa_supplicant_ioctl(struct ieee80211_device *ieee, struct iw_point *p)
2985{
2986        struct ieee_param *param;
2987        int ret = 0;
2988
2989        mutex_lock(&ieee->wx_mutex);
2990        //IEEE_DEBUG_INFO("wpa_supplicant: len=%d\n", p->length);
2991
2992        if (p->length < sizeof(struct ieee_param) || !p->pointer) {
2993                ret = -EINVAL;
2994                goto out;
2995        }
2996
2997        param = memdup_user(p->pointer, p->length);
2998        if (IS_ERR(param)) {
2999                ret = PTR_ERR(param);
3000                goto out;
3001        }
3002
3003        switch (param->cmd) {
3004        case IEEE_CMD_SET_WPA_PARAM:
3005                ret = ieee80211_wpa_set_param(ieee, param->u.wpa_param.name,
3006                                        param->u.wpa_param.value);
3007                break;
3008
3009        case IEEE_CMD_SET_WPA_IE:
3010                ret = ieee80211_wpa_set_wpa_ie(ieee, param, p->length);
3011                break;
3012
3013        case IEEE_CMD_SET_ENCRYPTION:
3014                ret = ieee80211_wpa_set_encryption(ieee, param, p->length);
3015                break;
3016
3017        case IEEE_CMD_MLME:
3018                ret = ieee80211_wpa_mlme(ieee, param->u.mlme.command,
3019                                   param->u.mlme.reason_code);
3020                break;
3021
3022        default:
3023                printk("Unknown WPA supplicant request: %d\n", param->cmd);
3024                ret = -EOPNOTSUPP;
3025                break;
3026        }
3027
3028        if (ret == 0 && copy_to_user(p->pointer, param, p->length))
3029                ret = -EFAULT;
3030
3031        kfree(param);
3032out:
3033        mutex_unlock(&ieee->wx_mutex);
3034
3035        return ret;
3036}
3037EXPORT_SYMBOL(ieee80211_wpa_supplicant_ioctl);
3038
3039void notify_wx_assoc_event(struct ieee80211_device *ieee)
3040{
3041        union iwreq_data wrqu;
3042
3043        wrqu.ap_addr.sa_family = ARPHRD_ETHER;
3044        if (ieee->state == IEEE80211_LINKED)
3045                memcpy(wrqu.ap_addr.sa_data, ieee->current_network.bssid, ETH_ALEN);
3046        else
3047                eth_zero_addr(wrqu.ap_addr.sa_data);
3048        wireless_send_event(ieee->dev, SIOCGIWAP, &wrqu, NULL);
3049}
3050EXPORT_SYMBOL(notify_wx_assoc_event);
3051