linux/drivers/staging/rtl8712/rtl871x_mlme.c
<<
>>
Prefs
   1/******************************************************************************
   2 * rtl871x_mlme.c
   3 *
   4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
   5 * Linux device driver for RTL8192SU
   6 *
   7 * This program is free software; you can redistribute it and/or modify it
   8 * under the terms of version 2 of the GNU General Public License as
   9 * published by the Free Software Foundation.
  10 *
  11 * This program is distributed in the hope that it will be useful, but WITHOUT
  12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  14 * more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along with
  17 * this program; if not, write to the Free Software Foundation, Inc.,
  18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
  19 *
  20 * Modifications for inclusion into the Linux staging tree are
  21 * Copyright(c) 2010 Larry Finger. All rights reserved.
  22 *
  23 * Contact information:
  24 * WLAN FAE <wlanfae@realtek.com>
  25 * Larry Finger <Larry.Finger@lwfinger.net>
  26 *
  27 ******************************************************************************/
  28
  29#define _RTL871X_MLME_C_
  30
  31#include <linux/etherdevice.h>
  32
  33#include "osdep_service.h"
  34#include "drv_types.h"
  35#include "recv_osdep.h"
  36#include "xmit_osdep.h"
  37#include "mlme_osdep.h"
  38#include "sta_info.h"
  39#include "wifi.h"
  40#include "wlan_bssdef.h"
  41
  42static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
  43
  44static sint _init_mlme_priv(struct _adapter *padapter)
  45{
  46        sint    i;
  47        u8      *pbuf;
  48        struct wlan_network     *pnetwork;
  49        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
  50
  51        memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
  52        pmlmepriv->nic_hdl = (u8 *)padapter;
  53        pmlmepriv->pscanned = NULL;
  54        pmlmepriv->fw_state = 0;
  55        pmlmepriv->cur_network.network.InfrastructureMode =
  56                                 Ndis802_11AutoUnknown;
  57        /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
  58        pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
  59        spin_lock_init(&(pmlmepriv->lock));
  60        spin_lock_init(&(pmlmepriv->lock2));
  61        _init_queue(&(pmlmepriv->free_bss_pool));
  62        _init_queue(&(pmlmepriv->scanned_queue));
  63        set_scanned_network_val(pmlmepriv, 0);
  64        memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
  65        pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
  66                             GFP_ATOMIC);
  67        if (!pbuf)
  68                return _FAIL;
  69        pmlmepriv->free_bss_buf = pbuf;
  70        pnetwork = (struct wlan_network *)pbuf;
  71        for (i = 0; i < MAX_BSS_CNT; i++) {
  72                INIT_LIST_HEAD(&(pnetwork->list));
  73                list_add_tail(&(pnetwork->list),
  74                                 &(pmlmepriv->free_bss_pool.queue));
  75                pnetwork++;
  76        }
  77        pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
  78        pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
  79        pmlmepriv->sitesurveyctrl.traffic_busy = false;
  80        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  81        r8712_init_mlme_timer(padapter);
  82        return _SUCCESS;
  83}
  84
  85struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
  86{
  87        unsigned long irqL;
  88        struct wlan_network *pnetwork;
  89        struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
  90
  91        spin_lock_irqsave(&free_queue->lock, irqL);
  92        pnetwork = list_first_entry_or_null(&free_queue->queue,
  93                                            struct wlan_network, list);
  94        if (pnetwork) {
  95                list_del_init(&pnetwork->list);
  96                pnetwork->last_scanned = jiffies;
  97                pmlmepriv->num_of_scanned++;
  98        }
  99        spin_unlock_irqrestore(&free_queue->lock, irqL);
 100        return pnetwork;
 101}
 102
 103static void _free_network(struct mlme_priv *pmlmepriv,
 104                          struct wlan_network *pnetwork)
 105{
 106        u32 curr_time, delta_time;
 107        unsigned long irqL;
 108        struct  __queue *free_queue = &(pmlmepriv->free_bss_pool);
 109
 110        if (pnetwork == NULL)
 111                return;
 112        if (pnetwork->fixed)
 113                return;
 114        curr_time = jiffies;
 115        delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
 116        if (delta_time < SCANQUEUE_LIFETIME)
 117                return;
 118        spin_lock_irqsave(&free_queue->lock, irqL);
 119        list_del_init(&pnetwork->list);
 120        list_add_tail(&pnetwork->list, &free_queue->queue);
 121        pmlmepriv->num_of_scanned--;
 122        spin_unlock_irqrestore(&free_queue->lock, irqL);
 123}
 124
 125static void free_network_nolock(struct mlme_priv *pmlmepriv,
 126                          struct wlan_network *pnetwork)
 127{
 128        struct  __queue *free_queue = &pmlmepriv->free_bss_pool;
 129
 130        if (pnetwork == NULL)
 131                return;
 132        if (pnetwork->fixed)
 133                return;
 134        list_del_init(&pnetwork->list);
 135        list_add_tail(&pnetwork->list, &free_queue->queue);
 136        pmlmepriv->num_of_scanned--;
 137}
 138
 139
 140/*
 141        return the wlan_network with the matching addr
 142        Shall be called under atomic context...
 143        to avoid possible racing condition...
 144*/
 145static struct wlan_network *_r8712_find_network(struct  __queue *scanned_queue,
 146                                         u8 *addr)
 147{
 148        unsigned long irqL;
 149        struct list_head *phead, *plist;
 150        struct wlan_network *pnetwork = NULL;
 151
 152        if (is_zero_ether_addr(addr))
 153                return NULL;
 154        spin_lock_irqsave(&scanned_queue->lock, irqL);
 155        phead = &scanned_queue->queue;
 156        plist = phead->next;
 157        while (plist != phead) {
 158                pnetwork = container_of(plist, struct wlan_network, list);
 159                plist = plist->next;
 160                if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
 161                        break;
 162        }
 163        spin_unlock_irqrestore(&scanned_queue->lock, irqL);
 164        return pnetwork;
 165}
 166
 167static void _free_network_queue(struct _adapter *padapter)
 168{
 169        unsigned long irqL;
 170        struct list_head *phead, *plist;
 171        struct wlan_network *pnetwork;
 172        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 173        struct  __queue *scanned_queue = &pmlmepriv->scanned_queue;
 174
 175        spin_lock_irqsave(&scanned_queue->lock, irqL);
 176        phead = &scanned_queue->queue;
 177        plist = phead->next;
 178        while (!end_of_queue_search(phead, plist)) {
 179                pnetwork = container_of(plist, struct wlan_network, list);
 180                plist = plist->next;
 181                _free_network(pmlmepriv, pnetwork);
 182        }
 183        spin_unlock_irqrestore(&scanned_queue->lock, irqL);
 184}
 185
 186sint r8712_if_up(struct _adapter *padapter)
 187{
 188        sint res;
 189
 190        if (padapter->bDriverStopped || padapter->bSurpriseRemoved ||
 191            !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
 192                res = false;
 193        } else {
 194                res = true;
 195        }
 196        return res;
 197}
 198
 199void r8712_generate_random_ibss(u8 *pibss)
 200{
 201        u32 curtime = jiffies;
 202
 203        pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
 204        pibss[1] = 0x11;
 205        pibss[2] = 0x87;
 206        pibss[3] = (u8)(curtime & 0xff);
 207        pibss[4] = (u8)((curtime >> 8) & 0xff);
 208        pibss[5] = (u8)((curtime >> 16) & 0xff);
 209}
 210
 211uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
 212{
 213        return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
 214}
 215
 216u8 *r8712_get_capability_from_ie(u8 *ie)
 217{
 218        return ie + 8 + 2;
 219}
 220
 221int r8712_init_mlme_priv(struct _adapter *padapter)
 222{
 223        return _init_mlme_priv(padapter);
 224}
 225
 226void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
 227{
 228        kfree(pmlmepriv->free_bss_buf);
 229}
 230
 231static struct   wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
 232{
 233        return _r8712_alloc_network(pmlmepriv);
 234}
 235
 236void r8712_free_network_queue(struct _adapter *dev)
 237{
 238        _free_network_queue(dev);
 239}
 240
 241/*
 242        return the wlan_network with the matching addr
 243
 244        Shall be called under atomic context...
 245        to avoid possible racing condition...
 246*/
 247static struct wlan_network *r8712_find_network(struct  __queue *scanned_queue,
 248                                               u8 *addr)
 249{
 250        struct wlan_network *pnetwork = _r8712_find_network(scanned_queue,
 251                                                            addr);
 252
 253        return pnetwork;
 254}
 255
 256int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
 257{
 258        int ret = true;
 259        struct security_priv *psecuritypriv = &adapter->securitypriv;
 260
 261        if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
 262                    (pnetwork->network.Privacy == 0))
 263                ret = false;
 264        else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
 265                 (pnetwork->network.Privacy == 1))
 266                ret = false;
 267        else
 268                ret = true;
 269        return ret;
 270
 271}
 272
 273static int is_same_network(struct wlan_bssid_ex *src,
 274                           struct wlan_bssid_ex *dst)
 275{
 276         u16 s_cap, d_cap;
 277
 278        memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
 279        memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
 280        return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
 281                        (src->Configuration.DSConfig ==
 282                        dst->Configuration.DSConfig) &&
 283                        ((!memcmp(src->MacAddress, dst->MacAddress,
 284                        ETH_ALEN))) &&
 285                        ((!memcmp(src->Ssid.Ssid,
 286                          dst->Ssid.Ssid,
 287                          src->Ssid.SsidLength))) &&
 288                        ((s_cap & WLAN_CAPABILITY_IBSS) ==
 289                        (d_cap & WLAN_CAPABILITY_IBSS)) &&
 290                        ((s_cap & WLAN_CAPABILITY_BSS) ==
 291                        (d_cap & WLAN_CAPABILITY_BSS));
 292
 293}
 294
 295struct  wlan_network *r8712_get_oldest_wlan_network(
 296                                struct  __queue *scanned_queue)
 297{
 298        struct list_head *plist, *phead;
 299        struct  wlan_network    *pwlan = NULL;
 300        struct  wlan_network    *oldest = NULL;
 301
 302        phead = &scanned_queue->queue;
 303        plist = phead->next;
 304        while (1) {
 305                if (end_of_queue_search(phead, plist) ==  true)
 306                        break;
 307                pwlan = container_of(plist, struct wlan_network, list);
 308                if (pwlan->fixed != true) {
 309                        if (oldest == NULL ||
 310                            time_after((unsigned long)oldest->last_scanned,
 311                            (unsigned long)pwlan->last_scanned))
 312                                oldest = pwlan;
 313                }
 314                plist = plist->next;
 315        }
 316        return oldest;
 317}
 318
 319static void update_network(struct wlan_bssid_ex *dst,
 320                           struct wlan_bssid_ex *src,
 321                           struct _adapter *padapter)
 322{
 323        u32 last_evm = 0, tmpVal;
 324
 325        if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
 326            is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
 327                if (padapter->recvpriv.signal_qual_data.total_num++ >=
 328                    PHY_LINKQUALITY_SLID_WIN_MAX) {
 329                        padapter->recvpriv.signal_qual_data.total_num =
 330                                   PHY_LINKQUALITY_SLID_WIN_MAX;
 331                        last_evm = padapter->recvpriv.signal_qual_data.
 332                                   elements[padapter->recvpriv.
 333                                   signal_qual_data.index];
 334                        padapter->recvpriv.signal_qual_data.total_val -=
 335                                 last_evm;
 336                }
 337                padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
 338
 339                padapter->recvpriv.signal_qual_data.
 340                          elements[padapter->recvpriv.signal_qual_data.
 341                          index++] = src->Rssi;
 342                if (padapter->recvpriv.signal_qual_data.index >=
 343                    PHY_LINKQUALITY_SLID_WIN_MAX)
 344                        padapter->recvpriv.signal_qual_data.index = 0;
 345                /* <1> Showed on UI for user, in percentage. */
 346                tmpVal = padapter->recvpriv.signal_qual_data.total_val /
 347                         padapter->recvpriv.signal_qual_data.total_num;
 348                padapter->recvpriv.signal = (u8)tmpVal;
 349
 350                src->Rssi = padapter->recvpriv.signal;
 351        } else {
 352                src->Rssi = (src->Rssi + dst->Rssi) / 2;
 353        }
 354        memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
 355}
 356
 357static void update_current_network(struct _adapter *adapter,
 358                                   struct wlan_bssid_ex *pnetwork)
 359{
 360        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 361
 362        if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
 363                update_network(&(pmlmepriv->cur_network.network),
 364                               pnetwork, adapter);
 365                r8712_update_protection(adapter,
 366                               (pmlmepriv->cur_network.network.IEs) +
 367                               sizeof(struct NDIS_802_11_FIXED_IEs),
 368                               pmlmepriv->cur_network.network.IELength);
 369        }
 370}
 371
 372/*
 373Caller must hold pmlmepriv->lock first.
 374*/
 375static void update_scanned_network(struct _adapter *adapter,
 376                            struct wlan_bssid_ex *target)
 377{
 378        struct list_head *plist, *phead;
 379
 380        u32 bssid_ex_sz;
 381        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 382        struct  __queue *queue = &pmlmepriv->scanned_queue;
 383        struct wlan_network *pnetwork = NULL;
 384        struct wlan_network *oldest = NULL;
 385
 386        phead = &queue->queue;
 387        plist = phead->next;
 388
 389        while (1) {
 390                if (end_of_queue_search(phead, plist))
 391                        break;
 392
 393                pnetwork = container_of(plist, struct wlan_network, list);
 394                if (is_same_network(&pnetwork->network, target))
 395                        break;
 396                if ((oldest == ((struct wlan_network *)0)) ||
 397                    time_after((unsigned long)oldest->last_scanned,
 398                                (unsigned long)pnetwork->last_scanned))
 399                        oldest = pnetwork;
 400
 401                plist = plist->next;
 402        }
 403
 404
 405        /* If we didn't find a match, then get a new network slot to initialize
 406         * with this beacon's information
 407         */
 408        if (end_of_queue_search(phead, plist)) {
 409                if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
 410                        /* If there are no more slots, expire the oldest */
 411                        pnetwork = oldest;
 412                        target->Rssi = (pnetwork->network.Rssi +
 413                                        target->Rssi) / 2;
 414                        memcpy(&pnetwork->network, target,
 415                                r8712_get_wlan_bssid_ex_sz(target));
 416                        pnetwork->last_scanned = jiffies;
 417                } else {
 418                        /* Otherwise just pull from the free list */
 419                        /* update scan_time */
 420                        pnetwork = alloc_network(pmlmepriv);
 421                        if (pnetwork == NULL)
 422                                return;
 423                        bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
 424                        target->Length = bssid_ex_sz;
 425                        memcpy(&pnetwork->network, target, bssid_ex_sz);
 426                        list_add_tail(&pnetwork->list, &queue->queue);
 427                }
 428        } else {
 429                /* we have an entry and we are going to update it. But
 430                 * this entry may be already expired. In this case we
 431                 * do the same as we found a new net and call the new_net
 432                 * handler
 433                 */
 434                update_network(&pnetwork->network, target, adapter);
 435                pnetwork->last_scanned = jiffies;
 436        }
 437}
 438
 439static void rtl8711_add_network(struct _adapter *adapter,
 440                         struct wlan_bssid_ex *pnetwork)
 441{
 442        unsigned long irqL;
 443        struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
 444        struct  __queue *queue = &pmlmepriv->scanned_queue;
 445
 446        spin_lock_irqsave(&queue->lock, irqL);
 447        update_current_network(adapter, pnetwork);
 448        update_scanned_network(adapter, pnetwork);
 449        spin_unlock_irqrestore(&queue->lock, irqL);
 450}
 451
 452/*select the desired network based on the capability of the (i)bss.
 453 * check items:         (1) security
 454 *                      (2) network_type
 455 *                      (3) WMM
 456 *                      (4) HT
 457 *                      (5) others
 458 */
 459static int is_desired_network(struct _adapter *adapter,
 460                                struct wlan_network *pnetwork)
 461{
 462        u8 wps_ie[512];
 463        uint wps_ielen;
 464        int bselected = true;
 465        struct  security_priv *psecuritypriv = &adapter->securitypriv;
 466
 467        if (psecuritypriv->wps_phase) {
 468                if (r8712_get_wps_ie(pnetwork->network.IEs,
 469                    pnetwork->network.IELength, wps_ie,
 470                    &wps_ielen))
 471                        return true;
 472                return false;
 473        }
 474        if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
 475                    (pnetwork->network.Privacy == 0))
 476                bselected = false;
 477        if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
 478                if (pnetwork->network.InfrastructureMode !=
 479                        adapter->mlmepriv.cur_network.network.
 480                        InfrastructureMode)
 481                        bselected = false;
 482        }
 483        return bselected;
 484}
 485
 486/* TODO: Perry : For Power Management */
 487void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
 488{
 489}
 490
 491void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
 492{
 493        unsigned long flags;
 494        u32 len;
 495        struct wlan_bssid_ex *pnetwork;
 496        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 497
 498        pnetwork = (struct wlan_bssid_ex *)pbuf;
 499#ifdef __BIG_ENDIAN
 500        /* endian_convert */
 501        pnetwork->Length = le32_to_cpu(pnetwork->Length);
 502        pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
 503        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
 504        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
 505        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
 506        pnetwork->Configuration.ATIMWindow =
 507                 le32_to_cpu(pnetwork->Configuration.ATIMWindow);
 508        pnetwork->Configuration.BeaconPeriod =
 509                 le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
 510        pnetwork->Configuration.DSConfig =
 511                 le32_to_cpu(pnetwork->Configuration.DSConfig);
 512        pnetwork->Configuration.FHConfig.DwellTime =
 513                 le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
 514        pnetwork->Configuration.FHConfig.HopPattern =
 515                 le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
 516        pnetwork->Configuration.FHConfig.HopSet =
 517                 le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
 518        pnetwork->Configuration.FHConfig.Length =
 519                 le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
 520        pnetwork->Configuration.Length =
 521                 le32_to_cpu(pnetwork->Configuration.Length);
 522        pnetwork->InfrastructureMode =
 523                 le32_to_cpu(pnetwork->InfrastructureMode);
 524        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 525#endif
 526        len = r8712_get_wlan_bssid_ex_sz(pnetwork);
 527        if (len > sizeof(struct wlan_bssid_ex))
 528                return;
 529        spin_lock_irqsave(&pmlmepriv->lock2, flags);
 530        /* update IBSS_network 's timestamp */
 531        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
 532                if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
 533                    pnetwork->MacAddress, ETH_ALEN)) {
 534                        struct wlan_network *ibss_wlan = NULL;
 535
 536                        memcpy(pmlmepriv->cur_network.network.IEs,
 537                                pnetwork->IEs, 8);
 538                        ibss_wlan = r8712_find_network(
 539                                                &pmlmepriv->scanned_queue,
 540                                                pnetwork->MacAddress);
 541                        if (ibss_wlan) {
 542                                memcpy(ibss_wlan->network.IEs,
 543                                        pnetwork->IEs, 8);
 544                                goto exit;
 545                        }
 546                }
 547        }
 548        /* lock pmlmepriv->lock when you accessing network_q */
 549        if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 550                if (pnetwork->Ssid.Ssid[0] != 0) {
 551                        rtl8711_add_network(adapter, pnetwork);
 552                } else {
 553                        pnetwork->Ssid.SsidLength = 8;
 554                        memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
 555                        rtl8711_add_network(adapter, pnetwork);
 556                }
 557        }
 558exit:
 559        spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
 560}
 561
 562void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
 563{
 564        unsigned long irqL;
 565        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 566
 567        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 568
 569        if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
 570                del_timer(&pmlmepriv->scan_to_timer);
 571
 572                _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
 573        }
 574
 575        if (pmlmepriv->to_join) {
 576                if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 577                        if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
 578                                set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 579
 580                                if (r8712_select_and_join_from_scan(pmlmepriv)
 581                                    == _SUCCESS)
 582                                        mod_timer(&pmlmepriv->assoc_timer, jiffies +
 583                                                  msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 584                                else {
 585                                        struct wlan_bssid_ex *pdev_network =
 586                                          &(adapter->registrypriv.dev_network);
 587                                        u8 *pibss =
 588                                                 adapter->registrypriv.
 589                                                        dev_network.MacAddress;
 590                                        pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
 591                                        memcpy(&pdev_network->Ssid,
 592                                                &pmlmepriv->assoc_ssid,
 593                                                sizeof(struct
 594                                                         ndis_802_11_ssid));
 595                                        r8712_update_registrypriv_dev_network
 596                                                (adapter);
 597                                        r8712_generate_random_ibss(pibss);
 598                                        pmlmepriv->fw_state =
 599                                                 WIFI_ADHOC_MASTER_STATE;
 600                                        pmlmepriv->to_join = false;
 601                                }
 602                        }
 603                } else {
 604                        pmlmepriv->to_join = false;
 605                        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 606                        if (r8712_select_and_join_from_scan(pmlmepriv) ==
 607                            _SUCCESS)
 608                                mod_timer(&pmlmepriv->assoc_timer, jiffies +
 609                                          msecs_to_jiffies(MAX_JOIN_TIMEOUT));
 610                        else
 611                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 612                }
 613        }
 614        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 615}
 616
 617/*
 618 *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
 619 */
 620void r8712_free_assoc_resources(struct _adapter *adapter)
 621{
 622        unsigned long irqL;
 623        struct wlan_network *pwlan = NULL;
 624        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 625        struct sta_priv *pstapriv = &adapter->stapriv;
 626        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 627
 628        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 629                                   tgt_network->network.MacAddress);
 630
 631        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
 632                struct sta_info *psta;
 633
 634                psta = r8712_get_stainfo(&adapter->stapriv,
 635                                         tgt_network->network.MacAddress);
 636
 637                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 638                r8712_free_stainfo(adapter,  psta);
 639                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 640        }
 641
 642        if (check_fwstate(pmlmepriv,
 643            WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
 644                r8712_free_all_stainfo(adapter);
 645        if (pwlan)
 646                pwlan->fixed = false;
 647
 648        if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
 649             (adapter->stapriv.asoc_sta_count == 1)))
 650                free_network_nolock(pmlmepriv, pwlan);
 651}
 652
 653/*
 654*r8712_indicate_connect: the caller has to lock pmlmepriv->lock
 655*/
 656void r8712_indicate_connect(struct _adapter *padapter)
 657{
 658        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 659
 660        pmlmepriv->to_join = false;
 661        set_fwstate(pmlmepriv, _FW_LINKED);
 662        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
 663        r8712_os_indicate_connect(padapter);
 664        if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
 665                mod_timer(&pmlmepriv->dhcp_timer,
 666                          jiffies + msecs_to_jiffies(60000));
 667}
 668
 669
 670/*
 671*r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
 672*/
 673void r8712_ind_disconnect(struct _adapter *padapter)
 674{
 675        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 676
 677        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 678                _clr_fwstate_(pmlmepriv, _FW_LINKED);
 679                padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
 680                r8712_os_indicate_disconnect(padapter);
 681        }
 682        if (padapter->pwrctrlpriv.pwr_mode !=
 683            padapter->registrypriv.power_mgnt) {
 684                del_timer(&pmlmepriv->dhcp_timer);
 685                r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
 686                                  padapter->registrypriv.smart_ps);
 687        }
 688}
 689
 690/*Notes:
 691 *pnetwork : returns from r8712_joinbss_event_callback
 692 *ptarget_wlan: found from scanned_queue
 693 *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
 694 *  "ptarget_sta" & "ptarget_wlan" exist.
 695 *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
 696 * if "ptarget_wlan" exist.
 697 *if join_res > 0, update "cur_network->network" from
 698 * "pnetwork->network" if (ptarget_wlan !=NULL).
 699 */
 700void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
 701{
 702        unsigned long irqL = 0, irqL2;
 703        struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
 704        struct sta_priv *pstapriv = &adapter->stapriv;
 705        struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
 706        struct wlan_network     *cur_network = &pmlmepriv->cur_network;
 707        struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
 708        unsigned int            the_same_macaddr = false;
 709        struct wlan_network *pnetwork;
 710
 711        if (sizeof(struct list_head) == 4 * sizeof(u32)) {
 712                pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
 713                if (!pnetwork)
 714                        return;
 715                memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
 716                       sizeof(struct wlan_network) - 16);
 717        } else {
 718                pnetwork = (struct wlan_network *)pbuf;
 719        }
 720
 721#ifdef __BIG_ENDIAN
 722        /* endian_convert */
 723        pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
 724        pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
 725        pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
 726        pnetwork->network.Ssid.SsidLength =
 727                 le32_to_cpu(pnetwork->network.Ssid.SsidLength);
 728        pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
 729        pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
 730        pnetwork->network.NetworkTypeInUse =
 731                 le32_to_cpu(pnetwork->network.NetworkTypeInUse);
 732        pnetwork->network.Configuration.ATIMWindow =
 733                 le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
 734        pnetwork->network.Configuration.BeaconPeriod =
 735                 le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
 736        pnetwork->network.Configuration.DSConfig =
 737                 le32_to_cpu(pnetwork->network.Configuration.DSConfig);
 738        pnetwork->network.Configuration.FHConfig.DwellTime =
 739                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.
 740                             DwellTime);
 741        pnetwork->network.Configuration.FHConfig.HopPattern =
 742                 le32_to_cpu(pnetwork->network.Configuration.
 743                             FHConfig.HopPattern);
 744        pnetwork->network.Configuration.FHConfig.HopSet =
 745                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
 746        pnetwork->network.Configuration.FHConfig.Length =
 747                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
 748        pnetwork->network.Configuration.Length =
 749                 le32_to_cpu(pnetwork->network.Configuration.Length);
 750        pnetwork->network.InfrastructureMode =
 751                 le32_to_cpu(pnetwork->network.InfrastructureMode);
 752        pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
 753#endif
 754
 755        the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
 756                                   cur_network->network.MacAddress, ETH_ALEN);
 757        pnetwork->network.Length =
 758                 r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
 759        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 760        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
 761                goto ignore_joinbss_callback;
 762        if (pnetwork->join_res > 0) {
 763                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 764                        /*s1. find ptarget_wlan*/
 765                        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
 766                                if (the_same_macaddr) {
 767                                        ptarget_wlan =
 768                                            r8712_find_network(&pmlmepriv->
 769                                            scanned_queue,
 770                                            cur_network->network.MacAddress);
 771                                } else {
 772                                        pcur_wlan =
 773                                             r8712_find_network(&pmlmepriv->
 774                                             scanned_queue,
 775                                             cur_network->network.MacAddress);
 776                                        pcur_wlan->fixed = false;
 777
 778                                        pcur_sta = r8712_get_stainfo(pstapriv,
 779                                             cur_network->network.MacAddress);
 780                                        spin_lock_irqsave(&pstapriv->
 781                                                sta_hash_lock, irqL2);
 782                                        r8712_free_stainfo(adapter, pcur_sta);
 783                                        spin_unlock_irqrestore(&(pstapriv->
 784                                                sta_hash_lock), irqL2);
 785
 786                                        ptarget_wlan =
 787                                                 r8712_find_network(&pmlmepriv->
 788                                                 scanned_queue,
 789                                                 pnetwork->network.
 790                                                 MacAddress);
 791                                        if (ptarget_wlan)
 792                                                ptarget_wlan->fixed = true;
 793                                }
 794                        } else {
 795                                ptarget_wlan = r8712_find_network(&pmlmepriv->
 796                                                scanned_queue,
 797                                                pnetwork->network.MacAddress);
 798                                if (ptarget_wlan)
 799                                        ptarget_wlan->fixed = true;
 800                        }
 801
 802                        if (ptarget_wlan == NULL) {
 803                                if (check_fwstate(pmlmepriv,
 804                                        _FW_UNDER_LINKING))
 805                                        pmlmepriv->fw_state ^=
 806                                                 _FW_UNDER_LINKING;
 807                                goto ignore_joinbss_callback;
 808                        }
 809
 810                        /*s2. find ptarget_sta & update ptarget_sta*/
 811                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 812                                if (the_same_macaddr) {
 813                                        ptarget_sta =
 814                                                 r8712_get_stainfo(pstapriv,
 815                                                 pnetwork->network.MacAddress);
 816                                        if (ptarget_sta == NULL)
 817                                                ptarget_sta =
 818                                                 r8712_alloc_stainfo(pstapriv,
 819                                                 pnetwork->network.MacAddress);
 820                                } else {
 821                                        ptarget_sta =
 822                                                 r8712_alloc_stainfo(pstapriv,
 823                                                 pnetwork->network.MacAddress);
 824                                }
 825                                if (ptarget_sta) /*update ptarget_sta*/ {
 826                                        ptarget_sta->aid = pnetwork->join_res;
 827                                        ptarget_sta->qos_option = 1;
 828                                        ptarget_sta->mac_id = 5;
 829                                        if (adapter->securitypriv.
 830                                            AuthAlgrthm == 2) {
 831                                                adapter->securitypriv.
 832                                                        binstallGrpkey =
 833                                                         false;
 834                                                adapter->securitypriv.
 835                                                        busetkipkey =
 836                                                         false;
 837                                                adapter->securitypriv.
 838                                                        bgrpkey_handshake =
 839                                                         false;
 840                                                ptarget_sta->ieee8021x_blocked
 841                                                         = true;
 842                                                ptarget_sta->XPrivacy =
 843                                                         adapter->securitypriv.
 844                                                         PrivacyAlgrthm;
 845                                                memset((u8 *)&ptarget_sta->
 846                                                         x_UncstKey,
 847                                                         0,
 848                                                         sizeof(union Keytype));
 849                                                memset((u8 *)&ptarget_sta->
 850                                                         tkiprxmickey,
 851                                                         0,
 852                                                         sizeof(union Keytype));
 853                                                memset((u8 *)&ptarget_sta->
 854                                                         tkiptxmickey,
 855                                                         0,
 856                                                         sizeof(union Keytype));
 857                                                memset((u8 *)&ptarget_sta->
 858                                                         txpn, 0,
 859                                                         sizeof(union pn48));
 860                                                memset((u8 *)&ptarget_sta->
 861                                                         rxpn, 0,
 862                                                         sizeof(union pn48));
 863                                        }
 864                                } else {
 865                                        if (check_fwstate(pmlmepriv,
 866                                            _FW_UNDER_LINKING))
 867                                                pmlmepriv->fw_state ^=
 868                                                         _FW_UNDER_LINKING;
 869                                        goto ignore_joinbss_callback;
 870                                }
 871                        }
 872
 873                        /*s3. update cur_network & indicate connect*/
 874                        memcpy(&cur_network->network, &pnetwork->network,
 875                                pnetwork->network.Length);
 876                        cur_network->aid = pnetwork->join_res;
 877                        /*update fw_state will clr _FW_UNDER_LINKING*/
 878                        switch (pnetwork->network.InfrastructureMode) {
 879                        case Ndis802_11Infrastructure:
 880                                pmlmepriv->fw_state = WIFI_STATION_STATE;
 881                                break;
 882                        case Ndis802_11IBSS:
 883                                pmlmepriv->fw_state = WIFI_ADHOC_STATE;
 884                                break;
 885                        default:
 886                                pmlmepriv->fw_state = WIFI_NULL_STATE;
 887                                break;
 888                        }
 889                        r8712_update_protection(adapter,
 890                                          (cur_network->network.IEs) +
 891                                          sizeof(struct NDIS_802_11_FIXED_IEs),
 892                                          (cur_network->network.IELength));
 893                        /*TODO: update HT_Capability*/
 894                        update_ht_cap(adapter, cur_network->network.IEs,
 895                                      cur_network->network.IELength);
 896                        /*indicate connect*/
 897                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 898                                r8712_indicate_connect(adapter);
 899                        del_timer(&pmlmepriv->assoc_timer);
 900                } else {
 901                        goto ignore_joinbss_callback;
 902                }
 903        } else {
 904                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
 905                        mod_timer(&pmlmepriv->assoc_timer,
 906                                  jiffies + msecs_to_jiffies(1));
 907                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 908                }
 909        }
 910ignore_joinbss_callback:
 911        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 912        if (sizeof(struct list_head) == 4 * sizeof(u32))
 913                kfree(pnetwork);
 914}
 915
 916void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
 917{
 918        unsigned long irqL;
 919        struct sta_info *psta;
 920        struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
 921        struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
 922
 923        /* to do: */
 924        if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
 925                return;
 926        psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
 927        if (psta != NULL) {
 928                /*the sta have been in sta_info_queue => do nothing
 929                 *(between drv has received this event before and
 930                 * fw have not yet to set key to CAM_ENTRY)
 931                 */
 932                return;
 933        }
 934
 935        psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
 936        if (psta == NULL)
 937                return;
 938        /* to do : init sta_info variable */
 939        psta->qos_option = 0;
 940        psta->mac_id = le32_to_cpu((uint)pstassoc->cam_id);
 941        /* psta->aid = (uint)pstassoc->cam_id; */
 942
 943        if (adapter->securitypriv.AuthAlgrthm == 2)
 944                psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
 945        psta->ieee8021x_blocked = false;
 946        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 947        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
 948            check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
 949                if (adapter->stapriv.asoc_sta_count == 2) {
 950                        /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
 951                        r8712_indicate_connect(adapter);
 952                }
 953        }
 954        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 955}
 956
 957void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
 958{
 959        unsigned long irqL, irqL2;
 960        struct sta_info *psta;
 961        struct wlan_network *pwlan = NULL;
 962        struct wlan_bssid_ex *pdev_network = NULL;
 963        u8 *pibss = NULL;
 964        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 965        struct stadel_event *pstadel = (struct stadel_event *)pbuf;
 966        struct sta_priv *pstapriv = &adapter->stapriv;
 967        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 968
 969        spin_lock_irqsave(&pmlmepriv->lock, irqL2);
 970        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 971                r8712_ind_disconnect(adapter);
 972                r8712_free_assoc_resources(adapter);
 973        }
 974        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
 975            WIFI_ADHOC_STATE)) {
 976                psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
 977                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 978                r8712_free_stainfo(adapter, psta);
 979                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 980                if (adapter->stapriv.asoc_sta_count == 1) {
 981                        /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
 982                        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 983                                tgt_network->network.MacAddress);
 984                        if (pwlan) {
 985                                pwlan->fixed = false;
 986                                free_network_nolock(pmlmepriv, pwlan);
 987                        }
 988                        /*re-create ibss*/
 989                        pdev_network = &(adapter->registrypriv.dev_network);
 990                        pibss = adapter->registrypriv.dev_network.MacAddress;
 991                        memcpy(pdev_network, &tgt_network->network,
 992                                r8712_get_wlan_bssid_ex_sz(&tgt_network->
 993                                                        network));
 994                        memcpy(&pdev_network->Ssid,
 995                                &pmlmepriv->assoc_ssid,
 996                                sizeof(struct ndis_802_11_ssid));
 997                        r8712_update_registrypriv_dev_network(adapter);
 998                        r8712_generate_random_ibss(pibss);
 999                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1000                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1001                                set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1002                        }
1003                }
1004        }
1005        spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
1006}
1007
1008void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
1009{
1010        struct reportpwrstate_parm *preportpwrstate =
1011                         (struct reportpwrstate_parm *)pbuf;
1012
1013        preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
1014        r8712_cpwm_int_hdl(adapter, preportpwrstate);
1015}
1016
1017/*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
1018 *       the ADDBA req frame with start seq control = 0 to wifi client after
1019 *       the WPA handshake and the seqence number of following data packet
1020 *      will be 0. In this case, the Rx reorder sequence is not longer than 0
1021 *       and the WiFi client will drop the data with seq number 0.
1022 *      So, the 8712 firmware has to inform driver with receiving the
1023 *       ADDBA-Req frame so that the driver can reset the
1024 *      sequence value of Rx reorder control.
1025 */
1026void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
1027{
1028        struct  ADDBA_Req_Report_parm *pAddbareq_pram =
1029                         (struct ADDBA_Req_Report_parm *)pbuf;
1030        struct  sta_info *psta;
1031        struct  sta_priv *pstapriv = &adapter->stapriv;
1032        struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
1033
1034        psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
1035        if (psta) {
1036                precvreorder_ctrl =
1037                         &psta->recvreorder_ctrl[pAddbareq_pram->tid];
1038                /* set the indicate_seq to 0xffff so that the rx reorder
1039                 * can store any following data packet.
1040                 */
1041                precvreorder_ctrl->indicate_seq = 0xffff;
1042        }
1043}
1044
1045void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
1046{
1047        if (!adapter->securitypriv.wps_hw_pbc_pressed)
1048                adapter->securitypriv.wps_hw_pbc_pressed = true;
1049}
1050
1051void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
1052{
1053        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1054        struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
1055        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1056        u64 current_tx_pkts;
1057        uint current_rx_pkts;
1058
1059        current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
1060                          (psitesurveyctrl->last_tx_pkts);
1061        current_rx_pkts = (adapter->recvpriv.rx_pkts) -
1062                          (psitesurveyctrl->last_rx_pkts);
1063        psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
1064        psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
1065        if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
1066            (current_rx_pkts > pregistrypriv->busy_thresh))
1067                psitesurveyctrl->traffic_busy = true;
1068        else
1069                psitesurveyctrl->traffic_busy = false;
1070}
1071
1072void _r8712_join_timeout_handler(struct _adapter *adapter)
1073{
1074        unsigned long irqL;
1075        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1076
1077        if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1078                return;
1079        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1080        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1081        pmlmepriv->to_join = false;
1082        if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1083                r8712_os_indicate_disconnect(adapter);
1084                _clr_fwstate_(pmlmepriv, _FW_LINKED);
1085        }
1086        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1087                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1088                                  adapter->registrypriv.smart_ps);
1089        }
1090        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1091}
1092
1093void r8712_scan_timeout_handler (struct _adapter *adapter)
1094{
1095        unsigned long irqL;
1096        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1097
1098        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1099        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1100        pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1101        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1102}
1103
1104void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1105{
1106        if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1107                return;
1108        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1109                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1110                            adapter->registrypriv.smart_ps);
1111}
1112
1113void _r8712_wdg_timeout_handler(struct _adapter *adapter)
1114{
1115        r8712_wdg_wk_cmd(adapter);
1116}
1117
1118int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1119{
1120        struct list_head *phead;
1121        unsigned char *dst_ssid, *src_ssid;
1122        struct _adapter *adapter;
1123        struct  __queue *queue = NULL;
1124        struct wlan_network *pnetwork = NULL;
1125        struct wlan_network *pnetwork_max_rssi = NULL;
1126
1127        adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1128        queue = &pmlmepriv->scanned_queue;
1129        phead = &queue->queue;
1130        pmlmepriv->pscanned = phead->next;
1131        while (1) {
1132                if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
1133                        if ((pmlmepriv->assoc_by_rssi) &&
1134                            (pnetwork_max_rssi != NULL)) {
1135                                pnetwork = pnetwork_max_rssi;
1136                                goto ask_for_joinbss;
1137                        }
1138                        return _FAIL;
1139                }
1140                pnetwork = container_of(pmlmepriv->pscanned,
1141                                        struct wlan_network, list);
1142                if (pnetwork == NULL)
1143                        return _FAIL;
1144                pmlmepriv->pscanned = pmlmepriv->pscanned->next;
1145                if (pmlmepriv->assoc_by_bssid) {
1146                        dst_ssid = pnetwork->network.MacAddress;
1147                        src_ssid = pmlmepriv->assoc_bssid;
1148                        if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1149                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1150                                        if (is_same_network(&pmlmepriv->
1151                                            cur_network.network,
1152                                            &pnetwork->network)) {
1153                                                _clr_fwstate_(pmlmepriv,
1154                                                        _FW_UNDER_LINKING);
1155                                                /*r8712_indicate_connect again*/
1156                                                r8712_indicate_connect(adapter);
1157                                                return 2;
1158                                        }
1159                                        r8712_disassoc_cmd(adapter);
1160                                        r8712_ind_disconnect(adapter);
1161                                        r8712_free_assoc_resources(adapter);
1162                                }
1163                                goto ask_for_joinbss;
1164                        }
1165                } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
1166                        goto ask_for_joinbss;
1167                }
1168                dst_ssid = pnetwork->network.Ssid.Ssid;
1169                src_ssid = pmlmepriv->assoc_ssid.Ssid;
1170                if ((pnetwork->network.Ssid.SsidLength ==
1171                    pmlmepriv->assoc_ssid.SsidLength) &&
1172                    (!memcmp(dst_ssid, src_ssid,
1173                     pmlmepriv->assoc_ssid.SsidLength))) {
1174                        if (pmlmepriv->assoc_by_rssi) {
1175                                /* if the ssid is the same, select the bss
1176                                 * which has the max rssi
1177                                 */
1178                                if (pnetwork_max_rssi) {
1179                                        if (pnetwork->network.Rssi >
1180                                            pnetwork_max_rssi->network.Rssi)
1181                                                pnetwork_max_rssi = pnetwork;
1182                                } else {
1183                                        pnetwork_max_rssi = pnetwork;
1184                                }
1185                        } else if (is_desired_network(adapter, pnetwork)) {
1186                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1187                                        r8712_disassoc_cmd(adapter);
1188                                        r8712_free_assoc_resources(adapter);
1189                                }
1190                                goto ask_for_joinbss;
1191                        }
1192                }
1193        }
1194
1195ask_for_joinbss:
1196        return r8712_joinbss_cmd(adapter, pnetwork);
1197}
1198
1199sint r8712_set_auth(struct _adapter *adapter,
1200                    struct security_priv *psecuritypriv)
1201{
1202        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1203        struct cmd_obj *pcmd;
1204        struct setauth_parm *psetauthparm;
1205
1206        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1207        if (!pcmd)
1208                return _FAIL;
1209
1210        psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
1211        if (!psetauthparm) {
1212                kfree(pcmd);
1213                return _FAIL;
1214        }
1215        psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1216        pcmd->cmdcode = _SetAuth_CMD_;
1217        pcmd->parmbuf = (unsigned char *)psetauthparm;
1218        pcmd->cmdsz = sizeof(struct setauth_parm);
1219        pcmd->rsp = NULL;
1220        pcmd->rspsz = 0;
1221        INIT_LIST_HEAD(&pcmd->list);
1222        r8712_enqueue_cmd(pcmdpriv, pcmd);
1223        return _SUCCESS;
1224}
1225
1226sint r8712_set_key(struct _adapter *adapter,
1227                   struct security_priv *psecuritypriv,
1228             sint keyid)
1229{
1230        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1231        struct cmd_obj *pcmd;
1232        struct setkey_parm *psetkeyparm;
1233        u8 keylen;
1234        sint ret = _SUCCESS;
1235
1236        pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
1237        if (!pcmd)
1238                return _FAIL;
1239        psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
1240        if (!psetkeyparm) {
1241                ret = _FAIL;
1242                goto err_free_cmd;
1243        }
1244        if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1245                psetkeyparm->algorithm =
1246                         (u8)psecuritypriv->XGrpPrivacy;
1247        } else { /* WEP */
1248                psetkeyparm->algorithm =
1249                         (u8)psecuritypriv->PrivacyAlgrthm;
1250        }
1251        psetkeyparm->keyid = (u8)keyid;
1252
1253        switch (psetkeyparm->algorithm) {
1254        case _WEP40_:
1255                keylen = 5;
1256                memcpy(psetkeyparm->key,
1257                        psecuritypriv->DefKey[keyid].skey, keylen);
1258                break;
1259        case _WEP104_:
1260                keylen = 13;
1261                memcpy(psetkeyparm->key,
1262                        psecuritypriv->DefKey[keyid].skey, keylen);
1263                break;
1264        case _TKIP_:
1265                if (keyid < 1 || keyid > 2) {
1266                        ret = _FAIL;
1267                        goto err_free_parm;
1268                }
1269                keylen = 16;
1270                memcpy(psetkeyparm->key,
1271                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1272                psetkeyparm->grpkey = 1;
1273                break;
1274        case _AES_:
1275                if (keyid < 1 || keyid > 2) {
1276                        ret = _FAIL;
1277                        goto err_free_parm;
1278                }
1279                keylen = 16;
1280                memcpy(psetkeyparm->key,
1281                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1282                psetkeyparm->grpkey = 1;
1283                break;
1284        default:
1285                ret = _FAIL;
1286                goto err_free_parm;
1287        }
1288        pcmd->cmdcode = _SetKey_CMD_;
1289        pcmd->parmbuf = (u8 *)psetkeyparm;
1290        pcmd->cmdsz =  (sizeof(struct setkey_parm));
1291        pcmd->rsp = NULL;
1292        pcmd->rspsz = 0;
1293        INIT_LIST_HEAD(&pcmd->list);
1294        r8712_enqueue_cmd(pcmdpriv, pcmd);
1295        return ret;
1296
1297err_free_parm:
1298        kfree(psetkeyparm);
1299err_free_cmd:
1300        kfree(pcmd);
1301        return ret;
1302}
1303
1304/* adjust IEs for r8712_joinbss_cmd in WMM */
1305int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1306                    uint in_len, uint initial_out_len)
1307{
1308        unsigned int ielength = 0;
1309        unsigned int i, j;
1310
1311        i = 12; /* after the fixed IE */
1312        while (i < in_len) {
1313                ielength = initial_out_len;
1314                if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1315                    in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1316                    in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1317                        /*WMM element ID and OUI*/
1318                        for (j = i; j < i + 9; j++) {
1319                                out_ie[ielength] = in_ie[j];
1320                                ielength++;
1321                        }
1322                        out_ie[initial_out_len + 1] = 0x07;
1323                        out_ie[initial_out_len + 6] = 0x00;
1324                        out_ie[initial_out_len + 8] = 0x00;
1325                        break;
1326                }
1327                i += (in_ie[i + 1] + 2); /* to the next IE element */
1328        }
1329        return ielength;
1330}
1331
1332/*
1333 * Ported from 8185: IsInPreAuthKeyList().
1334 *
1335 * Search by BSSID,
1336 * Return Value:
1337 *      -1              :if there is no pre-auth key in the  table
1338 *      >=0             :if there is pre-auth key, and   return the entry id
1339 */
1340static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1341{
1342        struct security_priv *psecuritypriv = &Adapter->securitypriv;
1343        int i = 0;
1344
1345        do {
1346                if (psecuritypriv->PMKIDList[i].bUsed &&
1347                   (!memcmp(psecuritypriv->PMKIDList[i].Bssid,
1348                            bssid, ETH_ALEN)))
1349                        break;
1350                else
1351                        i++;
1352        } while (i < NUM_PMKID_CACHE);
1353
1354        if (i == NUM_PMKID_CACHE) {
1355                i = -1; /* Could not find. */
1356        } else {
1357                ; /* There is one Pre-Authentication Key for the
1358                   * specific BSSID.
1359                   */
1360        }
1361        return i;
1362}
1363
1364sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1365                     u8 *out_ie, uint in_len)
1366{
1367        u8 authmode = 0, match;
1368        u8 sec_ie[255], uncst_oui[4], bkup_ie[255];
1369        u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1370        uint ielength, cnt, remove_cnt;
1371        int iEntry;
1372        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1373        struct security_priv *psecuritypriv = &adapter->securitypriv;
1374        uint ndisauthmode = psecuritypriv->ndisauthtype;
1375        uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1376
1377        if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1378            (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1379                authmode = _WPA_IE_ID_;
1380                uncst_oui[0] = 0x0;
1381                uncst_oui[1] = 0x50;
1382                uncst_oui[2] = 0xf2;
1383        }
1384        if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1385            (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1386                authmode = _WPA2_IE_ID_;
1387                uncst_oui[0] = 0x0;
1388                uncst_oui[1] = 0x0f;
1389                uncst_oui[2] = 0xac;
1390        }
1391        switch (ndissecuritytype) {
1392        case Ndis802_11Encryption1Enabled:
1393        case Ndis802_11Encryption1KeyAbsent:
1394                uncst_oui[3] = 0x1;
1395                break;
1396        case Ndis802_11Encryption2Enabled:
1397        case Ndis802_11Encryption2KeyAbsent:
1398                uncst_oui[3] = 0x2;
1399                break;
1400        case Ndis802_11Encryption3Enabled:
1401        case Ndis802_11Encryption3KeyAbsent:
1402                uncst_oui[3] = 0x4;
1403                break;
1404        default:
1405                break;
1406        }
1407        /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1408        cnt = 12;
1409        match = false;
1410        while (cnt < in_len) {
1411                if (in_ie[cnt] == authmode) {
1412                        if ((authmode == _WPA_IE_ID_) &&
1413                            (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
1414                                memcpy(&sec_ie[0], &in_ie[cnt],
1415                                        in_ie[cnt + 1] + 2);
1416                                match = true;
1417                                break;
1418                        }
1419                        if (authmode == _WPA2_IE_ID_) {
1420                                memcpy(&sec_ie[0], &in_ie[cnt],
1421                                        in_ie[cnt + 1] + 2);
1422                                match = true;
1423                                break;
1424                        }
1425                        if (((authmode == _WPA_IE_ID_) &&
1426                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1427                             (authmode == _WPA2_IE_ID_))
1428                                memcpy(&bkup_ie[0], &in_ie[cnt],
1429                                        in_ie[cnt + 1] + 2);
1430                }
1431                cnt += in_ie[cnt + 1] + 2; /*get next*/
1432        }
1433        /*restruct WPA IE or WPA2 IE in sec_ie[] */
1434        if (match) {
1435                if (sec_ie[0] == _WPA_IE_ID_) {
1436                        /* parsing SSN IE to select required encryption
1437                         * algorithm, and set the bc/mc encryption algorithm
1438                         */
1439                        while (true) {
1440                                /*check wpa_oui tag*/
1441                                if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1442                                        match = false;
1443                                        break;
1444                                }
1445                                if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1446                                        /*IE Ver error*/
1447                                        match = false;
1448                                        break;
1449                                }
1450                                if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1451                                        /* get bc/mc encryption type (group
1452                                         * key type)
1453                                         */
1454                                        switch (sec_ie[11]) {
1455                                        case 0x0: /*none*/
1456                                                psecuritypriv->XGrpPrivacy =
1457                                                                _NO_PRIVACY_;
1458                                                break;
1459                                        case 0x1: /*WEP_40*/
1460                                                psecuritypriv->XGrpPrivacy =
1461                                                                _WEP40_;
1462                                                break;
1463                                        case 0x2: /*TKIP*/
1464                                                psecuritypriv->XGrpPrivacy =
1465                                                                _TKIP_;
1466                                                break;
1467                                        case 0x3: /*AESCCMP*/
1468                                        case 0x4:
1469                                                psecuritypriv->XGrpPrivacy =
1470                                                                _AES_;
1471                                                break;
1472                                        case 0x5: /*WEP_104*/
1473                                                psecuritypriv->XGrpPrivacy =
1474                                                                _WEP104_;
1475                                                break;
1476                                        }
1477                                } else {
1478                                        match = false;
1479                                        break;
1480                                }
1481                                if (sec_ie[12] == 0x01) {
1482                                        /*check the unicast encryption type*/
1483                                        if (memcmp(&sec_ie[14],
1484                                            &uncst_oui[0], 4)) {
1485                                                match = false;
1486                                                break;
1487
1488                                        } /*else the uncst_oui is match*/
1489                                } else { /*mixed mode, unicast_enc_type > 1*/
1490                                        /*select the uncst_oui and remove
1491                                         * the other uncst_oui
1492                                         */
1493                                        cnt = sec_ie[12];
1494                                        remove_cnt = (cnt - 1) * 4;
1495                                        sec_ie[12] = 0x01;
1496                                        memcpy(&sec_ie[14], &uncst_oui[0], 4);
1497                                        /*remove the other unicast suit*/
1498                                        memcpy(&sec_ie[18],
1499                                                &sec_ie[18 + remove_cnt],
1500                                                sec_ie[1] - 18 + 2 -
1501                                                remove_cnt);
1502                                        sec_ie[1] = sec_ie[1] - remove_cnt;
1503                                }
1504                                break;
1505                        }
1506                }
1507                if (authmode == _WPA2_IE_ID_) {
1508                        /* parsing RSN IE to select required encryption
1509                         * algorithm, and set the bc/mc encryption algorithm
1510                         */
1511                        while (true) {
1512                                if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1513                                        /*IE Ver error*/
1514                                        match = false;
1515                                        break;
1516                                }
1517                                if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1518                                        /*get bc/mc encryption type*/
1519                                        switch (sec_ie[7]) {
1520                                        case 0x1: /*WEP_40*/
1521                                                psecuritypriv->XGrpPrivacy =
1522                                                                _WEP40_;
1523                                                break;
1524                                        case 0x2: /*TKIP*/
1525                                                psecuritypriv->XGrpPrivacy =
1526                                                                _TKIP_;
1527                                                break;
1528                                        case 0x4: /*AESWRAP*/
1529                                                psecuritypriv->XGrpPrivacy =
1530                                                                _AES_;
1531                                                break;
1532                                        case 0x5: /*WEP_104*/
1533                                                psecuritypriv->XGrpPrivacy =
1534                                                                _WEP104_;
1535                                                break;
1536                                        default: /*one*/
1537                                                psecuritypriv->XGrpPrivacy =
1538                                                                _NO_PRIVACY_;
1539                                                break;
1540                                        }
1541                                } else {
1542                                        match = false;
1543                                        break;
1544                                }
1545                                if (sec_ie[8] == 0x01) {
1546                                        /*check the unicast encryption type*/
1547                                        if (memcmp(&sec_ie[10],
1548                                                     &uncst_oui[0], 4)) {
1549                                                match = false;
1550                                                break;
1551                                        } /*else the uncst_oui is match*/
1552                                } else { /*mixed mode, unicast_enc_type > 1*/
1553                                        /*select the uncst_oui and remove the
1554                                         * other uncst_oui
1555                                         */
1556                                        cnt = sec_ie[8];
1557                                        remove_cnt = (cnt - 1) * 4;
1558                                        sec_ie[8] = 0x01;
1559                                        memcpy(&sec_ie[10], &uncst_oui[0], 4);
1560                                        /*remove the other unicast suit*/
1561                                        memcpy(&sec_ie[14],
1562                                                &sec_ie[14 + remove_cnt],
1563                                                (sec_ie[1] - 14 + 2 -
1564                                                remove_cnt));
1565                                        sec_ie[1] = sec_ie[1] - remove_cnt;
1566                                }
1567                                break;
1568                        }
1569                }
1570        }
1571        if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1572                /*copy fixed ie*/
1573                memcpy(out_ie, in_ie, 12);
1574                ielength = 12;
1575                /*copy RSN or SSN*/
1576                if (match) {
1577                        memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
1578                        ielength += sec_ie[1] + 2;
1579                        if (authmode == _WPA2_IE_ID_) {
1580                                /*the Pre-Authentication bit should be zero*/
1581                                out_ie[ielength - 1] = 0;
1582                                out_ie[ielength - 2] = 0;
1583                        }
1584                        r8712_report_sec_ie(adapter, authmode, sec_ie);
1585                }
1586        } else {
1587                /*copy fixed ie only*/
1588                memcpy(out_ie, in_ie, 12);
1589                ielength = 12;
1590                if (psecuritypriv->wps_phase) {
1591                        memcpy(out_ie + ielength, psecuritypriv->wps_ie,
1592                               psecuritypriv->wps_ie_len);
1593                        ielength += psecuritypriv->wps_ie_len;
1594                }
1595        }
1596        iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1597        if (iEntry < 0)
1598                return ielength;
1599        if (authmode == _WPA2_IE_ID_) {
1600                out_ie[ielength] = 1;
1601                ielength++;
1602                out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1603                ielength++;
1604                memcpy(&out_ie[ielength],
1605                        &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1606                ielength += 16;
1607                out_ie[13] += 18;/*PMKID length = 2+16*/
1608        }
1609        return ielength;
1610}
1611
1612void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1613{
1614        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1615        struct eeprom_priv *peepriv = &adapter->eeprompriv;
1616        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1617        u8 *myhwaddr = myid(peepriv);
1618
1619        memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1620        memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1621                sizeof(struct ndis_802_11_ssid));
1622        pdev_network->Configuration.Length =
1623                         sizeof(struct NDIS_802_11_CONFIGURATION);
1624        pdev_network->Configuration.BeaconPeriod = 100;
1625        pdev_network->Configuration.FHConfig.Length = 0;
1626        pdev_network->Configuration.FHConfig.HopPattern = 0;
1627        pdev_network->Configuration.FHConfig.HopSet = 0;
1628        pdev_network->Configuration.FHConfig.DwellTime = 0;
1629}
1630
1631void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1632{
1633        int sz = 0;
1634        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1635        struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1636        struct security_priv    *psecuritypriv = &adapter->securitypriv;
1637        struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1638
1639        pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1640                                            > 0 ? 1 : 0); /* adhoc no 802.1x */
1641        pdev_network->Rssi = 0;
1642        switch (pregistrypriv->wireless_mode) {
1643        case WIRELESS_11B:
1644                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11DS);
1645                break;
1646        case WIRELESS_11G:
1647        case WIRELESS_11BG:
1648                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM24);
1649                break;
1650        case WIRELESS_11A:
1651                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM5);
1652                break;
1653        default:
1654                /* TODO */
1655                break;
1656        }
1657        pdev_network->Configuration.DSConfig = cpu_to_le32(
1658                                               pregistrypriv->channel);
1659        if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1660                pdev_network->Configuration.ATIMWindow = cpu_to_le32(3);
1661        pdev_network->InfrastructureMode = cpu_to_le32(
1662                                cur_network->network.InfrastructureMode);
1663        /* 1. Supported rates
1664         * 2. IE
1665         */
1666        sz = r8712_generate_ie(pregistrypriv);
1667        pdev_network->IELength = sz;
1668        pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
1669}
1670
1671/*the function is at passive_level*/
1672void r8712_joinbss_reset(struct _adapter *padapter)
1673{
1674        int i;
1675        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1676        struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1677
1678        /* todo: if you want to do something io/reg/hw setting before join_bss,
1679         * please add code here
1680         */
1681        phtpriv->ampdu_enable = false;/*reset to disabled*/
1682        for (i = 0; i < 16; i++)
1683                phtpriv->baddbareq_issued[i] = false;/*reset it*/
1684        if (phtpriv->ht_option) {
1685                /* validate  usb rx aggregation */
1686                r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1687        } else {
1688                /* invalidate  usb rx aggregation */
1689                /* TH=1 => means that invalidate usb rx aggregation */
1690                r8712_write8(padapter, 0x102500D9, 1);
1691        }
1692}
1693
1694/*the function is >= passive_level*/
1695unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1696                                     u8 *out_ie, uint in_len, uint *pout_len)
1697{
1698        u32 ielen, out_len;
1699        unsigned char *p;
1700        struct ieee80211_ht_cap ht_capie;
1701        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1702        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1703        struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1704        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1705
1706        phtpriv->ht_option = 0;
1707        p = r8712_get_ie(in_ie + 12, _HT_CAPABILITY_IE_, &ielen, in_len - 12);
1708        if (p && (ielen > 0)) {
1709                if (pqospriv->qos_option == 0) {
1710                        out_len = *pout_len;
1711                        r8712_set_ie(out_ie + out_len, _VENDOR_SPECIFIC_IE_,
1712                                     _WMM_IE_Length_, WMM_IE, pout_len);
1713                        pqospriv->qos_option = 1;
1714                }
1715                out_len = *pout_len;
1716                memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1717                ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
1718                                    IEEE80211_HT_CAP_SGI_20 |
1719                                    IEEE80211_HT_CAP_SGI_40 |
1720                                    IEEE80211_HT_CAP_TX_STBC |
1721                                    IEEE80211_HT_CAP_MAX_AMSDU |
1722                                    IEEE80211_HT_CAP_DSSSCCK40;
1723                ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR &
1724                                0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
1725                r8712_set_ie(out_ie + out_len, _HT_CAPABILITY_IE_,
1726                             sizeof(struct ieee80211_ht_cap),
1727                             (unsigned char *)&ht_capie, pout_len);
1728                phtpriv->ht_option = 1;
1729        }
1730        return phtpriv->ht_option;
1731}
1732
1733/* the function is > passive_level (in critical_section) */
1734static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1735{
1736        u8 *p, max_ampdu_sz;
1737        int i, len;
1738        struct sta_info *bmc_sta, *psta;
1739        struct ieee80211_ht_cap *pht_capie;
1740        struct recv_reorder_ctrl *preorder_ctrl;
1741        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1742        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1743        struct registry_priv *pregistrypriv = &padapter->registrypriv;
1744        struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1745
1746        if (!phtpriv->ht_option)
1747                return;
1748        /* maybe needs check if ap supports rx ampdu. */
1749        if (!phtpriv->ampdu_enable &&
1750            (pregistrypriv->ampdu_enable == 1))
1751                phtpriv->ampdu_enable = true;
1752        /*check Max Rx A-MPDU Size*/
1753        len = 0;
1754        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1755                                _HT_CAPABILITY_IE_,
1756                                &len, ie_len -
1757                                sizeof(struct NDIS_802_11_FIXED_IEs));
1758        if (p && len > 0) {
1759                pht_capie = (struct ieee80211_ht_cap *)(p + 2);
1760                max_ampdu_sz = (pht_capie->ampdu_params_info &
1761                                IEEE80211_HT_CAP_AMPDU_FACTOR);
1762                /* max_ampdu_sz (kbytes); */
1763                max_ampdu_sz = 1 << (max_ampdu_sz + 3);
1764                phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1765        }
1766        /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1767         * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1768         * wstart_b(indicate_seq) to default value=0xffff
1769         * todo: check if AP can send A-MPDU packets
1770         */
1771        bmc_sta = r8712_get_bcmc_stainfo(padapter);
1772        if (bmc_sta) {
1773                for (i = 0; i < 16; i++) {
1774                        preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1775                        preorder_ctrl->indicate_seq = 0xffff;
1776                        preorder_ctrl->wend_b = 0xffff;
1777                }
1778        }
1779        psta = r8712_get_stainfo(&padapter->stapriv,
1780                                 pcur_network->network.MacAddress);
1781        if (psta) {
1782                for (i = 0; i < 16; i++) {
1783                        preorder_ctrl = &psta->recvreorder_ctrl[i];
1784                        preorder_ctrl->indicate_seq = 0xffff;
1785                        preorder_ctrl->wend_b = 0xffff;
1786                }
1787        }
1788        len = 0;
1789        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1790                   _HT_ADD_INFO_IE_, &len,
1791                   ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
1792}
1793
1794void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1795{
1796        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1797        struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1798
1799        if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
1800                if (!phtpriv->baddbareq_issued[priority]) {
1801                        r8712_addbareq_cmd(padapter, (u8)priority);
1802                        phtpriv->baddbareq_issued[priority] = true;
1803                }
1804        }
1805}
1806