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