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