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                                        memset(&pdev_network->Ssid, 0,
 608                                                sizeof(struct
 609                                                       ndis_802_11_ssid));
 610                                        memcpy(&pdev_network->Ssid,
 611                                                &pmlmepriv->assoc_ssid,
 612                                                sizeof(struct
 613                                                         ndis_802_11_ssid));
 614                                        r8712_update_registrypriv_dev_network
 615                                                (adapter);
 616                                        r8712_generate_random_ibss(pibss);
 617                                        pmlmepriv->fw_state =
 618                                                 WIFI_ADHOC_MASTER_STATE;
 619                                        pmlmepriv->to_join = false;
 620                                }
 621                        }
 622                } else {
 623                        pmlmepriv->to_join = false;
 624                        set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
 625                        if (r8712_select_and_join_from_scan(pmlmepriv) ==
 626                            _SUCCESS)
 627                                _set_timer(&pmlmepriv->assoc_timer,
 628                                           MAX_JOIN_TIMEOUT);
 629                        else
 630                                _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 631                }
 632        }
 633        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 634}
 635
 636/*
 637 *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
 638 */
 639void r8712_free_assoc_resources(struct _adapter *adapter)
 640{
 641        unsigned long irqL;
 642        struct wlan_network *pwlan = NULL;
 643        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 644        struct sta_priv *pstapriv = &adapter->stapriv;
 645        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 646
 647        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 648                                   tgt_network->network.MacAddress);
 649
 650        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_AP_STATE)) {
 651                struct sta_info *psta;
 652
 653                psta = r8712_get_stainfo(&adapter->stapriv,
 654                                         tgt_network->network.MacAddress);
 655
 656                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 657                r8712_free_stainfo(adapter,  psta);
 658                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 659        }
 660
 661        if (check_fwstate(pmlmepriv,
 662            WIFI_ADHOC_STATE|WIFI_ADHOC_MASTER_STATE|WIFI_AP_STATE))
 663                r8712_free_all_stainfo(adapter);
 664        if (pwlan)
 665                pwlan->fixed = false;
 666
 667        if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
 668             (adapter->stapriv.asoc_sta_count == 1)))
 669                free_network_nolock(pmlmepriv, pwlan);
 670}
 671
 672/*
 673*r8712_indicate_connect: the caller has to lock pmlmepriv->lock
 674*/
 675void r8712_indicate_connect(struct _adapter *padapter)
 676{
 677        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 678
 679        pmlmepriv->to_join = false;
 680        set_fwstate(pmlmepriv, _FW_LINKED);
 681        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
 682        r8712_os_indicate_connect(padapter);
 683        if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
 684                _set_timer(&pmlmepriv->dhcp_timer, 60000);
 685}
 686
 687
 688/*
 689*r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
 690*/
 691void r8712_ind_disconnect(struct _adapter *padapter)
 692{
 693        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 694
 695        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 696                _clr_fwstate_(pmlmepriv, _FW_LINKED);
 697                padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
 698                r8712_os_indicate_disconnect(padapter);
 699        }
 700        if (padapter->pwrctrlpriv.pwr_mode !=
 701            padapter->registrypriv.power_mgnt) {
 702                _cancel_timer_ex(&pmlmepriv->dhcp_timer);
 703                r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
 704                                  padapter->registrypriv.smart_ps);
 705        }
 706}
 707
 708/*Notes:
 709 *pnetwork : returns from r8712_joinbss_event_callback
 710 *ptarget_wlan: found from scanned_queue
 711 *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
 712 *  "ptarget_sta" & "ptarget_wlan" exist.
 713 *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
 714 * if "ptarget_wlan" exist.
 715 *if join_res > 0, update "cur_network->network" from
 716 * "pnetwork->network" if (ptarget_wlan !=NULL).
 717 */
 718void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
 719{
 720        unsigned long irqL = 0, irqL2;
 721        u8 timer_cancelled;
 722        struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
 723        struct sta_priv *pstapriv = &adapter->stapriv;
 724        struct mlme_priv        *pmlmepriv = &adapter->mlmepriv;
 725        struct wlan_network     *cur_network = &pmlmepriv->cur_network;
 726        struct wlan_network     *pcur_wlan = NULL, *ptarget_wlan = NULL;
 727        unsigned int            the_same_macaddr = false;
 728        struct wlan_network *pnetwork;
 729
 730        if (sizeof(struct list_head) == 4 * sizeof(u32)) {
 731                pnetwork = (struct wlan_network *)
 732                        _malloc(sizeof(struct wlan_network));
 733                memcpy((u8 *)pnetwork+16, (u8 *)pbuf + 8,
 734                        sizeof(struct wlan_network) - 16);
 735        } else
 736                pnetwork = (struct wlan_network *)pbuf;
 737
 738#ifdef __BIG_ENDIAN
 739        /* endian_convert */
 740        pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
 741        pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
 742        pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
 743        pnetwork->network.Ssid.SsidLength =
 744                 le32_to_cpu(pnetwork->network.Ssid.SsidLength);
 745        pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
 746        pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
 747        pnetwork->network.NetworkTypeInUse =
 748                 le32_to_cpu(pnetwork->network.NetworkTypeInUse);
 749        pnetwork->network.Configuration.ATIMWindow =
 750                 le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
 751        pnetwork->network.Configuration.BeaconPeriod =
 752                 le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
 753        pnetwork->network.Configuration.DSConfig =
 754                 le32_to_cpu(pnetwork->network.Configuration.DSConfig);
 755        pnetwork->network.Configuration.FHConfig.DwellTime =
 756                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.
 757                             DwellTime);
 758        pnetwork->network.Configuration.FHConfig.HopPattern =
 759                 le32_to_cpu(pnetwork->network.Configuration.
 760                             FHConfig.HopPattern);
 761        pnetwork->network.Configuration.FHConfig.HopSet =
 762                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
 763        pnetwork->network.Configuration.FHConfig.Length =
 764                 le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
 765        pnetwork->network.Configuration.Length =
 766                 le32_to_cpu(pnetwork->network.Configuration.Length);
 767        pnetwork->network.InfrastructureMode =
 768                 le32_to_cpu(pnetwork->network.InfrastructureMode);
 769        pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
 770#endif
 771
 772        the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
 773                                   cur_network->network.MacAddress, ETH_ALEN);
 774        pnetwork->network.Length =
 775                 r8712_get_ndis_wlan_bssid_ex_sz(&pnetwork->network);
 776        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 777        if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
 778                goto ignore_joinbss_callback;
 779        if (pnetwork->join_res > 0) {
 780                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
 781                        /*s1. find ptarget_wlan*/
 782                        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
 783                                if (the_same_macaddr == true)
 784                                        ptarget_wlan =
 785                                            r8712_find_network(&pmlmepriv->
 786                                            scanned_queue,
 787                                            cur_network->network.MacAddress);
 788                                else {
 789                                        pcur_wlan =
 790                                             r8712_find_network(&pmlmepriv->
 791                                             scanned_queue,
 792                                             cur_network->network.MacAddress);
 793                                        pcur_wlan->fixed = false;
 794
 795                                        pcur_sta = r8712_get_stainfo(pstapriv,
 796                                             cur_network->network.MacAddress);
 797                                        spin_lock_irqsave(&pstapriv->
 798                                                sta_hash_lock, irqL2);
 799                                        r8712_free_stainfo(adapter, pcur_sta);
 800                                        spin_unlock_irqrestore(&(pstapriv->
 801                                                sta_hash_lock), irqL2);
 802
 803                                        ptarget_wlan =
 804                                                 r8712_find_network(&pmlmepriv->
 805                                                 scanned_queue,
 806                                                 pnetwork->network.
 807                                                 MacAddress);
 808                                        if (ptarget_wlan)
 809                                                ptarget_wlan->fixed = true;
 810                                }
 811                        } else {
 812                                ptarget_wlan = r8712_find_network(&pmlmepriv->
 813                                                scanned_queue,
 814                                                pnetwork->network.MacAddress);
 815                                if (ptarget_wlan)
 816                                        ptarget_wlan->fixed = true;
 817                        }
 818
 819                        if (ptarget_wlan == NULL) {
 820                                if (check_fwstate(pmlmepriv,
 821                                        _FW_UNDER_LINKING))
 822                                        pmlmepriv->fw_state ^=
 823                                                 _FW_UNDER_LINKING;
 824                                goto ignore_joinbss_callback;
 825                        }
 826
 827                        /*s2. find ptarget_sta & update ptarget_sta*/
 828                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
 829                                if (the_same_macaddr == true) {
 830                                        ptarget_sta =
 831                                                 r8712_get_stainfo(pstapriv,
 832                                                 pnetwork->network.MacAddress);
 833                                        if (ptarget_sta == NULL)
 834                                                ptarget_sta =
 835                                                 r8712_alloc_stainfo(pstapriv,
 836                                                 pnetwork->network.MacAddress);
 837                                } else
 838                                        ptarget_sta =
 839                                                 r8712_alloc_stainfo(pstapriv,
 840                                                 pnetwork->network.MacAddress);
 841                                if (ptarget_sta) /*update ptarget_sta*/ {
 842                                        ptarget_sta->aid = pnetwork->join_res;
 843                                        ptarget_sta->qos_option = 1;
 844                                        ptarget_sta->mac_id = 5;
 845                                        if (adapter->securitypriv.
 846                                            AuthAlgrthm == 2) {
 847                                                adapter->securitypriv.
 848                                                        binstallGrpkey =
 849                                                         false;
 850                                                adapter->securitypriv.
 851                                                        busetkipkey =
 852                                                         false;
 853                                                adapter->securitypriv.
 854                                                        bgrpkey_handshake =
 855                                                         false;
 856                                                ptarget_sta->ieee8021x_blocked
 857                                                         = true;
 858                                                ptarget_sta->XPrivacy =
 859                                                         adapter->securitypriv.
 860                                                         PrivacyAlgrthm;
 861                                                memset((u8 *)&ptarget_sta->
 862                                                         x_UncstKey,
 863                                                         0,
 864                                                         sizeof(union Keytype));
 865                                                memset((u8 *)&ptarget_sta->
 866                                                         tkiprxmickey,
 867                                                         0,
 868                                                         sizeof(union Keytype));
 869                                                memset((u8 *)&ptarget_sta->
 870                                                         tkiptxmickey,
 871                                                         0,
 872                                                         sizeof(union Keytype));
 873                                                memset((u8 *)&ptarget_sta->
 874                                                         txpn, 0,
 875                                                         sizeof(union pn48));
 876                                                memset((u8 *)&ptarget_sta->
 877                                                         rxpn, 0,
 878                                                         sizeof(union pn48));
 879                                        }
 880                                } else {
 881                                        if (check_fwstate(pmlmepriv,
 882                                            _FW_UNDER_LINKING))
 883                                                pmlmepriv->fw_state ^=
 884                                                         _FW_UNDER_LINKING;
 885                                        goto ignore_joinbss_callback;
 886                                }
 887                        }
 888
 889                        /*s3. update cur_network & indicate connect*/
 890                        memcpy(&cur_network->network, &pnetwork->network,
 891                                pnetwork->network.Length);
 892                        cur_network->aid = pnetwork->join_res;
 893                        /*update fw_state will clr _FW_UNDER_LINKING*/
 894                        switch (pnetwork->network.InfrastructureMode) {
 895                        case Ndis802_11Infrastructure:
 896                                pmlmepriv->fw_state = WIFI_STATION_STATE;
 897                                break;
 898                        case Ndis802_11IBSS:
 899                                pmlmepriv->fw_state = WIFI_ADHOC_STATE;
 900                                break;
 901                        default:
 902                                pmlmepriv->fw_state = WIFI_NULL_STATE;
 903                                break;
 904                        }
 905                        r8712_update_protection(adapter,
 906                                          (cur_network->network.IEs) +
 907                                          sizeof(struct NDIS_802_11_FIXED_IEs),
 908                                          (cur_network->network.IELength));
 909                        /*TODO: update HT_Capability*/
 910                        update_ht_cap(adapter, cur_network->network.IEs,
 911                                      cur_network->network.IELength);
 912                        /*indicate connect*/
 913                        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)
 914                                == true)
 915                                r8712_indicate_connect(adapter);
 916                        _cancel_timer(&pmlmepriv->assoc_timer,
 917                                      &timer_cancelled);
 918                } else
 919                        goto ignore_joinbss_callback;
 920        } else {
 921                if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true) {
 922                        _set_timer(&pmlmepriv->assoc_timer, 1);
 923                        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
 924                }
 925        }
 926ignore_joinbss_callback:
 927        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 928        if (sizeof(struct list_head) == 4 * sizeof(u32))
 929                kfree((u8 *)pnetwork);
 930}
 931
 932void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
 933{
 934        unsigned long irqL;
 935        struct sta_info *psta;
 936        struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
 937        struct stassoc_event *pstassoc  = (struct stassoc_event *)pbuf;
 938
 939        /* to do: */
 940        if (r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr) == false)
 941                return;
 942        psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
 943        if (psta != NULL) {
 944                /*the sta have been in sta_info_queue => do nothing
 945                 *(between drv has received this event before and
 946                 *  fw have not yet to set key to CAM_ENTRY) */
 947                return;
 948        }
 949
 950        psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
 951        if (psta == NULL)
 952                return;
 953        /* to do : init sta_info variable */
 954        psta->qos_option = 0;
 955        psta->mac_id = le32_to_cpu((uint)pstassoc->cam_id);
 956        /* psta->aid = (uint)pstassoc->cam_id; */
 957
 958        if (adapter->securitypriv.AuthAlgrthm == 2)
 959                psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
 960        psta->ieee8021x_blocked = false;
 961        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 962        if ((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true) ||
 963            (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)) {
 964                if (adapter->stapriv.asoc_sta_count == 2) {
 965                        /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
 966                        r8712_indicate_connect(adapter);
 967                }
 968        }
 969        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 970}
 971
 972void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
 973{
 974        unsigned long irqL, irqL2;
 975        struct sta_info *psta;
 976        struct wlan_network *pwlan = NULL;
 977        struct wlan_bssid_ex *pdev_network = NULL;
 978        u8 *pibss = NULL;
 979        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
 980        struct stadel_event *pstadel = (struct stadel_event *)pbuf;
 981        struct sta_priv *pstapriv = &adapter->stapriv;
 982        struct wlan_network *tgt_network = &pmlmepriv->cur_network;
 983
 984        spin_lock_irqsave(&pmlmepriv->lock, irqL2);
 985        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) == true) {
 986                r8712_ind_disconnect(adapter);
 987                r8712_free_assoc_resources(adapter);
 988        }
 989        if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
 990            WIFI_ADHOC_STATE)) {
 991                psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
 992                spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
 993                r8712_free_stainfo(adapter, psta);
 994                spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
 995                if (adapter->stapriv.asoc_sta_count == 1) {
 996                        /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
 997                        pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
 998                                tgt_network->network.MacAddress);
 999                        if (pwlan) {
1000                                pwlan->fixed = false;
1001                                free_network_nolock(pmlmepriv, pwlan);
1002                        }
1003                        /*re-create ibss*/
1004                        pdev_network = &(adapter->registrypriv.dev_network);
1005                        pibss = adapter->registrypriv.dev_network.MacAddress;
1006                        memcpy(pdev_network, &tgt_network->network,
1007                                r8712_get_ndis_wlan_bssid_ex_sz(&tgt_network->
1008                                                        network));
1009                        memset(&pdev_network->Ssid, 0,
1010                                sizeof(struct ndis_802_11_ssid));
1011                        memcpy(&pdev_network->Ssid,
1012                                &pmlmepriv->assoc_ssid,
1013                                sizeof(struct ndis_802_11_ssid));
1014                        r8712_update_registrypriv_dev_network(adapter);
1015                        r8712_generate_random_ibss(pibss);
1016                        if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
1017                                _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
1018                                set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
1019                        }
1020                }
1021        }
1022        spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
1023}
1024
1025void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
1026{
1027        struct reportpwrstate_parm *preportpwrstate =
1028                         (struct reportpwrstate_parm *)pbuf;
1029
1030        preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
1031        r8712_cpwm_int_hdl(adapter, preportpwrstate);
1032}
1033
1034/*      When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
1035 *       the ADDBA req frame with start seq control = 0 to wifi client after
1036 *       the WPA handshake and the seqence number of following data packet
1037 *      will be 0. In this case, the Rx reorder sequence is not longer than 0
1038 *       and the WiFi client will drop the data with seq number 0.
1039 *      So, the 8712 firmware has to inform driver with receiving the
1040 *       ADDBA-Req frame so that the driver can reset the
1041 *      sequence value of Rx reorder control.
1042 */
1043void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
1044{
1045        struct  ADDBA_Req_Report_parm *pAddbareq_pram =
1046                         (struct ADDBA_Req_Report_parm *)pbuf;
1047        struct  sta_info *psta;
1048        struct  sta_priv *pstapriv = &adapter->stapriv;
1049        struct  recv_reorder_ctrl *precvreorder_ctrl = NULL;
1050
1051        printk(KERN_INFO "r8712u: [%s] mac = %pM, seq = %d, tid = %d\n",
1052             __func__, pAddbareq_pram->MacAddress,
1053            pAddbareq_pram->StartSeqNum, pAddbareq_pram->tid);
1054        psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
1055        if (psta) {
1056                precvreorder_ctrl =
1057                         &psta->recvreorder_ctrl[pAddbareq_pram->tid];
1058                /* set the indicate_seq to 0xffff so that the rx reorder
1059                 * can store any following data packet.
1060                 */
1061                precvreorder_ctrl->indicate_seq = 0xffff;
1062        }
1063}
1064
1065void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
1066{
1067        if (adapter->securitypriv.wps_hw_pbc_pressed == false)
1068                adapter->securitypriv.wps_hw_pbc_pressed = true;
1069}
1070
1071void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
1072{
1073        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1074        struct sitesurvey_ctrl  *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
1075        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1076        u64 current_tx_pkts;
1077        uint current_rx_pkts;
1078
1079        current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
1080                          (psitesurveyctrl->last_tx_pkts);
1081        current_rx_pkts = (adapter->recvpriv.rx_pkts) -
1082                          (psitesurveyctrl->last_rx_pkts);
1083        psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
1084        psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
1085        if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
1086            (current_rx_pkts > pregistrypriv->busy_thresh))
1087                psitesurveyctrl->traffic_busy = true;
1088        else
1089                psitesurveyctrl->traffic_busy = false;
1090}
1091
1092void _r8712_join_timeout_handler(struct _adapter *adapter)
1093{
1094        unsigned long irqL;
1095        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1096
1097        if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1098                return;
1099        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1100        _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
1101        pmlmepriv->to_join = false;
1102        if (check_fwstate(pmlmepriv, _FW_LINKED) == true) {
1103                r8712_os_indicate_disconnect(adapter);
1104                _clr_fwstate_(pmlmepriv, _FW_LINKED);
1105        }
1106        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
1107                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1108                                  adapter->registrypriv.smart_ps);
1109        }
1110        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1111}
1112
1113void r8712_scan_timeout_handler (struct _adapter *adapter)
1114{
1115        unsigned long irqL;
1116        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1117
1118        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1119        _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
1120        pmlmepriv->to_join = false;     /* scan fail, so clear to_join flag */
1121        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1122}
1123
1124void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
1125{
1126        if (adapter->bDriverStopped || adapter->bSurpriseRemoved)
1127                return;
1128        if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
1129                r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
1130                            adapter->registrypriv.smart_ps);
1131}
1132
1133void _r8712_wdg_timeout_handler(struct _adapter *adapter)
1134{
1135        r8712_wdg_wk_cmd(adapter);
1136}
1137
1138int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
1139{
1140        struct list_head *phead;
1141        unsigned char *dst_ssid, *src_ssid;
1142        struct _adapter *adapter;
1143        struct  __queue *queue = NULL;
1144        struct wlan_network *pnetwork = NULL;
1145        struct wlan_network *pnetwork_max_rssi = NULL;
1146
1147        adapter = (struct _adapter *)pmlmepriv->nic_hdl;
1148        queue = &pmlmepriv->scanned_queue;
1149        phead = get_list_head(queue);
1150        pmlmepriv->pscanned = get_next(phead);
1151        while (1) {
1152                if (end_of_queue_search(phead, pmlmepriv->pscanned) == true) {
1153                        if ((pmlmepriv->assoc_by_rssi == true) &&
1154                            (pnetwork_max_rssi != NULL)) {
1155                                pnetwork = pnetwork_max_rssi;
1156                                goto ask_for_joinbss;
1157                        }
1158                        return _FAIL;
1159                }
1160                pnetwork = LIST_CONTAINOR(pmlmepriv->pscanned,
1161                                          struct wlan_network, list);
1162                if (pnetwork == NULL)
1163                        return _FAIL;
1164                pmlmepriv->pscanned = get_next(pmlmepriv->pscanned);
1165                if (pmlmepriv->assoc_by_bssid == true) {
1166                        dst_ssid = pnetwork->network.MacAddress;
1167                        src_ssid = pmlmepriv->assoc_bssid;
1168                        if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
1169                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1170                                        if (is_same_network(&pmlmepriv->
1171                                            cur_network.network,
1172                                            &pnetwork->network)) {
1173                                                _clr_fwstate_(pmlmepriv,
1174                                                        _FW_UNDER_LINKING);
1175                                                /*r8712_indicate_connect again*/
1176                                                r8712_indicate_connect(adapter);
1177                                                return 2;
1178                                        }
1179                                        r8712_disassoc_cmd(adapter);
1180                                        r8712_ind_disconnect(adapter);
1181                                        r8712_free_assoc_resources(adapter);
1182                                }
1183                                goto ask_for_joinbss;
1184                        }
1185                } else if (pmlmepriv->assoc_ssid.SsidLength == 0)
1186                        goto ask_for_joinbss;
1187                dst_ssid = pnetwork->network.Ssid.Ssid;
1188                src_ssid = pmlmepriv->assoc_ssid.Ssid;
1189                if ((pnetwork->network.Ssid.SsidLength ==
1190                    pmlmepriv->assoc_ssid.SsidLength) &&
1191                    (!memcmp(dst_ssid, src_ssid,
1192                     pmlmepriv->assoc_ssid.SsidLength))) {
1193                        if (pmlmepriv->assoc_by_rssi == true) {
1194                                /* if the ssid is the same, select the bss
1195                                 *  which has the max rssi*/
1196                                if (pnetwork_max_rssi) {
1197                                        if (pnetwork->network.Rssi >
1198                                            pnetwork_max_rssi->network.Rssi)
1199                                                pnetwork_max_rssi = pnetwork;
1200                                } else
1201                                        pnetwork_max_rssi = pnetwork;
1202                        } else if (is_desired_network(adapter, pnetwork)) {
1203                                if (check_fwstate(pmlmepriv, _FW_LINKED)) {
1204                                        r8712_disassoc_cmd(adapter);
1205                                        r8712_free_assoc_resources(adapter);
1206                                }
1207                                goto ask_for_joinbss;
1208                        }
1209                }
1210        }
1211        return _FAIL;
1212ask_for_joinbss:
1213        return r8712_joinbss_cmd(adapter, pnetwork);
1214}
1215
1216sint r8712_set_auth(struct _adapter *adapter,
1217                    struct security_priv *psecuritypriv)
1218{
1219        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1220        struct cmd_obj *pcmd;
1221        struct setauth_parm *psetauthparm;
1222        sint ret = _SUCCESS;
1223
1224        pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
1225        if (pcmd == NULL)
1226                return _FAIL;
1227
1228        psetauthparm = (struct setauth_parm *)_malloc(
1229                        sizeof(struct setauth_parm));
1230        if (psetauthparm == NULL) {
1231                kfree((unsigned char *)pcmd);
1232                return _FAIL;
1233        }
1234        memset(psetauthparm, 0, sizeof(struct setauth_parm));
1235        psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
1236        pcmd->cmdcode = _SetAuth_CMD_;
1237        pcmd->parmbuf = (unsigned char *)psetauthparm;
1238        pcmd->cmdsz = sizeof(struct setauth_parm);
1239        pcmd->rsp = NULL;
1240        pcmd->rspsz = 0;
1241        _init_listhead(&pcmd->list);
1242        r8712_enqueue_cmd(pcmdpriv, pcmd);
1243        return ret;
1244}
1245
1246sint r8712_set_key(struct _adapter *adapter,
1247                   struct security_priv *psecuritypriv,
1248             sint keyid)
1249{
1250        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1251        struct cmd_obj *pcmd;
1252        struct setkey_parm *psetkeyparm;
1253        u8 keylen;
1254
1255        pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
1256        if (pcmd == NULL)
1257                return _FAIL;
1258        psetkeyparm = (struct setkey_parm *)_malloc(sizeof(struct setkey_parm));
1259        if (psetkeyparm == NULL) {
1260                kfree((unsigned char *)pcmd);
1261                return _FAIL;
1262        }
1263        memset(psetkeyparm, 0, sizeof(struct setkey_parm));
1264        if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
1265                psetkeyparm->algorithm =
1266                         (u8)psecuritypriv->XGrpPrivacy;
1267        } else { /* WEP */
1268                psetkeyparm->algorithm =
1269                         (u8)psecuritypriv->PrivacyAlgrthm;
1270        }
1271        psetkeyparm->keyid = (u8)keyid;
1272
1273        switch (psetkeyparm->algorithm) {
1274        case _WEP40_:
1275                keylen = 5;
1276                memcpy(psetkeyparm->key,
1277                        psecuritypriv->DefKey[keyid].skey, keylen);
1278                break;
1279        case _WEP104_:
1280                keylen = 13;
1281                memcpy(psetkeyparm->key,
1282                        psecuritypriv->DefKey[keyid].skey, keylen);
1283                break;
1284        case _TKIP_:
1285                if (keyid < 1 || keyid > 2)
1286                        return _FAIL;
1287                keylen = 16;
1288                memcpy(psetkeyparm->key,
1289                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1290                psetkeyparm->grpkey = 1;
1291                break;
1292        case _AES_:
1293                if (keyid < 1 || keyid > 2)
1294                        return _FAIL;
1295                keylen = 16;
1296                memcpy(psetkeyparm->key,
1297                        &psecuritypriv->XGrpKey[keyid - 1], keylen);
1298                psetkeyparm->grpkey = 1;
1299                break;
1300        default:
1301                return _FAIL;
1302        }
1303        pcmd->cmdcode = _SetKey_CMD_;
1304        pcmd->parmbuf = (u8 *)psetkeyparm;
1305        pcmd->cmdsz =  (sizeof(struct setkey_parm));
1306        pcmd->rsp = NULL;
1307        pcmd->rspsz = 0;
1308        _init_listhead(&pcmd->list);
1309        r8712_enqueue_cmd(pcmdpriv, pcmd);
1310        return _SUCCESS;
1311}
1312
1313/* adjust IEs for r8712_joinbss_cmd in WMM */
1314int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
1315                    uint in_len, uint initial_out_len)
1316{
1317        unsigned int ielength = 0;
1318        unsigned int i, j;
1319
1320        i = 12; /* after the fixed IE */
1321        while (i < in_len) {
1322                ielength = initial_out_len;
1323                if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
1324                    in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
1325                    in_ie[i + 5] == 0x02 && i + 5 < in_len) {
1326                        /*WMM element ID and OUI*/
1327                        for (j = i; j < i + 9; j++) {
1328                                out_ie[ielength] = in_ie[j];
1329                                ielength++;
1330                        }
1331                        out_ie[initial_out_len + 1] = 0x07;
1332                        out_ie[initial_out_len + 6] = 0x00;
1333                        out_ie[initial_out_len + 8] = 0x00;
1334                        break;
1335                }
1336                i += (in_ie[i + 1] + 2); /* to the next IE element */
1337        }
1338        return ielength;
1339}
1340
1341/*
1342 * Ported from 8185: IsInPreAuthKeyList().
1343 *
1344 * Search by BSSID,
1345 * Return Value:
1346 *      -1              :if there is no pre-auth key in the  table
1347 *      >=0             :if there is pre-auth key, and   return the entry id
1348 */
1349static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
1350{
1351        struct security_priv *psecuritypriv = &Adapter->securitypriv;
1352        int i = 0;
1353
1354        do {
1355                if (psecuritypriv->PMKIDList[i].bUsed &&
1356                   (!memcmp(psecuritypriv->PMKIDList[i].Bssid,
1357                            bssid, ETH_ALEN)))
1358                        break;
1359                else
1360                        i++;
1361        } while (i < NUM_PMKID_CACHE);
1362
1363        if (i == NUM_PMKID_CACHE) {
1364                i = -1; /* Could not find. */
1365        } else {
1366                ; /* There is one Pre-Authentication Key for the
1367                   * specific BSSID. */
1368        }
1369        return i;
1370}
1371
1372sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
1373                     u8 *out_ie, uint in_len)
1374{
1375        u8 authmode = 0, securitytype, match;
1376        u8 sec_ie[255], uncst_oui[4], bkup_ie[255];
1377        u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
1378        uint ielength, cnt, remove_cnt;
1379        int iEntry;
1380        struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
1381        struct security_priv *psecuritypriv = &adapter->securitypriv;
1382        uint ndisauthmode = psecuritypriv->ndisauthtype;
1383        uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
1384
1385        if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
1386            (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
1387                authmode = _WPA_IE_ID_;
1388                uncst_oui[0] = 0x0;
1389                uncst_oui[1] = 0x50;
1390                uncst_oui[2] = 0xf2;
1391        }
1392        if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
1393            (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
1394                authmode = _WPA2_IE_ID_;
1395                uncst_oui[0] = 0x0;
1396                uncst_oui[1] = 0x0f;
1397                uncst_oui[2] = 0xac;
1398        }
1399        switch (ndissecuritytype) {
1400        case Ndis802_11Encryption1Enabled:
1401        case Ndis802_11Encryption1KeyAbsent:
1402                securitytype = _WEP40_;
1403                uncst_oui[3] = 0x1;
1404                break;
1405        case Ndis802_11Encryption2Enabled:
1406        case Ndis802_11Encryption2KeyAbsent:
1407                securitytype = _TKIP_;
1408                uncst_oui[3] = 0x2;
1409                break;
1410        case Ndis802_11Encryption3Enabled:
1411        case Ndis802_11Encryption3KeyAbsent:
1412                securitytype = _AES_;
1413                uncst_oui[3] = 0x4;
1414                break;
1415        default:
1416                securitytype = _NO_PRIVACY_;
1417                break;
1418        }
1419        /*Search required WPA or WPA2 IE and copy to sec_ie[] */
1420        cnt = 12;
1421        match = false;
1422        while (cnt < in_len) {
1423                if (in_ie[cnt] == authmode) {
1424                        if ((authmode == _WPA_IE_ID_) &&
1425                            (!memcmp(&in_ie[cnt+2], &wpa_oui[0], 4))) {
1426                                memcpy(&sec_ie[0], &in_ie[cnt],
1427                                        in_ie[cnt + 1] + 2);
1428                                match = true;
1429                                break;
1430                        }
1431                        if (authmode == _WPA2_IE_ID_) {
1432                                memcpy(&sec_ie[0], &in_ie[cnt],
1433                                        in_ie[cnt + 1] + 2);
1434                                match = true;
1435                                break;
1436                        }
1437                        if (((authmode == _WPA_IE_ID_) &&
1438                             (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
1439                             (authmode == _WPA2_IE_ID_))
1440                                memcpy(&bkup_ie[0], &in_ie[cnt],
1441                                        in_ie[cnt + 1] + 2);
1442                }
1443                cnt += in_ie[cnt+1] + 2; /*get next*/
1444        }
1445        /*restruct WPA IE or WPA2 IE in sec_ie[] */
1446        if (match == true) {
1447                if (sec_ie[0] == _WPA_IE_ID_) {
1448                        /* parsing SSN IE to select required encryption
1449                         * algorithm, and set the bc/mc encryption algorithm */
1450                        while (true) {
1451                                /*check wpa_oui tag*/
1452                                if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
1453                                        match = false;
1454                                        break;
1455                                }
1456                                if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
1457                                        /*IE Ver error*/
1458                                        match = false;
1459                                        break;
1460                                }
1461                                if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
1462                                        /* get bc/mc encryption type (group
1463                                         * key type)*/
1464                                        switch (sec_ie[11]) {
1465                                        case 0x0: /*none*/
1466                                                psecuritypriv->XGrpPrivacy =
1467                                                                _NO_PRIVACY_;
1468                                                break;
1469                                        case 0x1: /*WEP_40*/
1470                                                psecuritypriv->XGrpPrivacy =
1471                                                                _WEP40_;
1472                                                break;
1473                                        case 0x2: /*TKIP*/
1474                                                psecuritypriv->XGrpPrivacy =
1475                                                                _TKIP_;
1476                                                break;
1477                                        case 0x3: /*AESCCMP*/
1478                                        case 0x4:
1479                                                psecuritypriv->XGrpPrivacy =
1480                                                                _AES_;
1481                                                break;
1482                                        case 0x5: /*WEP_104*/
1483                                                psecuritypriv->XGrpPrivacy =
1484                                                                _WEP104_;
1485                                                break;
1486                                        }
1487                                } else {
1488                                        match = false;
1489                                        break;
1490                                }
1491                                if (sec_ie[12] == 0x01) {
1492                                        /*check the unicast encryption type*/
1493                                        if (memcmp(&sec_ie[14],
1494                                            &uncst_oui[0], 4)) {
1495                                                match = false;
1496                                                break;
1497
1498                                        } /*else the uncst_oui is match*/
1499                                } else { /*mixed mode, unicast_enc_type > 1*/
1500                                        /*select the uncst_oui and remove
1501                                         * the other uncst_oui*/
1502                                        cnt = sec_ie[12];
1503                                        remove_cnt = (cnt-1) * 4;
1504                                        sec_ie[12] = 0x01;
1505                                        memcpy(&sec_ie[14], &uncst_oui[0], 4);
1506                                        /*remove the other unicast suit*/
1507                                        memcpy(&sec_ie[18],
1508                                                &sec_ie[18 + remove_cnt],
1509                                                sec_ie[1] - 18 + 2 -
1510                                                remove_cnt);
1511                                        sec_ie[1] = sec_ie[1] - remove_cnt;
1512                                }
1513                                break;
1514                        }
1515                }
1516                if (authmode == _WPA2_IE_ID_) {
1517                        /* parsing RSN IE to select required encryption
1518                         * algorithm, and set the bc/mc encryption algorithm */
1519                        while (true) {
1520                                if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
1521                                        /*IE Ver error*/
1522                                        match = false;
1523                                        break;
1524                                }
1525                                if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
1526                                        /*get bc/mc encryption type*/
1527                                        switch (sec_ie[7]) {
1528                                        case 0x1: /*WEP_40*/
1529                                                psecuritypriv->XGrpPrivacy =
1530                                                                _WEP40_;
1531                                                break;
1532                                        case 0x2: /*TKIP*/
1533                                                psecuritypriv->XGrpPrivacy =
1534                                                                _TKIP_;
1535                                                break;
1536                                        case 0x4: /*AESWRAP*/
1537                                                psecuritypriv->XGrpPrivacy =
1538                                                                _AES_;
1539                                                break;
1540                                        case 0x5: /*WEP_104*/
1541                                                psecuritypriv->XGrpPrivacy =
1542                                                                _WEP104_;
1543                                                break;
1544                                        default: /*one*/
1545                                                psecuritypriv->XGrpPrivacy =
1546                                                                _NO_PRIVACY_;
1547                                                break;
1548                                        }
1549                                } else {
1550                                        match = false;
1551                                        break;
1552                                }
1553                                if (sec_ie[8] == 0x01) {
1554                                        /*check the unicast encryption type*/
1555                                        if (memcmp(&sec_ie[10],
1556                                                     &uncst_oui[0], 4)) {
1557                                                match = false;
1558                                                break;
1559                                        } /*else the uncst_oui is match*/
1560                                } else { /*mixed mode, unicast_enc_type > 1*/
1561                                        /*select the uncst_oui and remove the
1562                                         * other uncst_oui*/
1563                                        cnt = sec_ie[8];
1564                                        remove_cnt = (cnt-1)*4;
1565                                        sec_ie[8] = 0x01;
1566                                        memcpy(&sec_ie[10], &uncst_oui[0], 4);
1567                                        /*remove the other unicast suit*/
1568                                        memcpy(&sec_ie[14],
1569                                                &sec_ie[14 + remove_cnt],
1570                                                (sec_ie[1] - 14 + 2 -
1571                                                remove_cnt));
1572                                        sec_ie[1] = sec_ie[1]-remove_cnt;
1573                                }
1574                                break;
1575                        }
1576                }
1577        }
1578        if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
1579                /*copy fixed ie*/
1580                memcpy(out_ie, in_ie, 12);
1581                ielength = 12;
1582                /*copy RSN or SSN*/
1583                if (match == true) {
1584                        memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1]+2);
1585                        ielength += sec_ie[1] + 2;
1586                        if (authmode == _WPA2_IE_ID_) {
1587                                /*the Pre-Authentication bit should be zero*/
1588                                out_ie[ielength - 1] = 0;
1589                                out_ie[ielength - 2] = 0;
1590                        }
1591                        r8712_report_sec_ie(adapter, authmode, sec_ie);
1592                }
1593        } else {
1594                /*copy fixed ie only*/
1595                memcpy(out_ie, in_ie, 12);
1596                ielength = 12;
1597                if (psecuritypriv->wps_phase == true) {
1598                        memcpy(out_ie+ielength, psecuritypriv->wps_ie,
1599                                psecuritypriv->wps_ie_len);
1600                        ielength += psecuritypriv->wps_ie_len;
1601                }
1602        }
1603        iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
1604        if (iEntry < 0)
1605                return ielength;
1606        else {
1607                if (authmode == _WPA2_IE_ID_) {
1608                        out_ie[ielength] = 1;
1609                        ielength++;
1610                        out_ie[ielength] = 0;   /*PMKID count = 0x0100*/
1611                        ielength++;
1612                        memcpy(&out_ie[ielength],
1613                                &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
1614                        ielength += 16;
1615                        out_ie[13] += 18;/*PMKID length = 2+16*/
1616                }
1617        }
1618        return ielength;
1619}
1620
1621void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
1622{
1623        struct registry_priv *pregistrypriv = &adapter->registrypriv;
1624        struct eeprom_priv *peepriv = &adapter->eeprompriv;
1625        struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
1626        u8 *myhwaddr = myid(peepriv);
1627
1628        memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
1629        memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
1630                sizeof(struct ndis_802_11_ssid));
1631        pdev_network->Configuration.Length =
1632                         sizeof(struct NDIS_802_11_CONFIGURATION);
1633        pdev_network->Configuration.BeaconPeriod = 100;
1634        pdev_network->Configuration.FHConfig.Length = 0;
1635        pdev_network->Configuration.FHConfig.HopPattern = 0;
1636        pdev_network->Configuration.FHConfig.HopSet = 0;
1637        pdev_network->Configuration.FHConfig.DwellTime = 0;
1638}
1639
1640void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
1641{
1642        int sz = 0;
1643        struct registry_priv    *pregistrypriv = &adapter->registrypriv;
1644        struct wlan_bssid_ex    *pdev_network = &pregistrypriv->dev_network;
1645        struct security_priv    *psecuritypriv = &adapter->securitypriv;
1646        struct wlan_network     *cur_network = &adapter->mlmepriv.cur_network;
1647
1648        pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
1649                                            > 0 ? 1 : 0) ; /* adhoc no 802.1x */
1650        pdev_network->Rssi = 0;
1651        switch (pregistrypriv->wireless_mode) {
1652        case WIRELESS_11B:
1653                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11DS);
1654                break;
1655        case WIRELESS_11G:
1656        case WIRELESS_11BG:
1657                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM24);
1658                break;
1659        case WIRELESS_11A:
1660                pdev_network->NetworkTypeInUse = cpu_to_le32(Ndis802_11OFDM5);
1661                break;
1662        default:
1663                /* TODO */
1664                break;
1665        }
1666        pdev_network->Configuration.DSConfig = cpu_to_le32(
1667                                               pregistrypriv->channel);
1668        if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
1669                pdev_network->Configuration.ATIMWindow = cpu_to_le32(3);
1670        pdev_network->InfrastructureMode = cpu_to_le32(
1671                                cur_network->network.InfrastructureMode);
1672        /* 1. Supported rates
1673         * 2. IE
1674         */
1675        sz = r8712_generate_ie(pregistrypriv);
1676        pdev_network->IELength = sz;
1677        pdev_network->Length = r8712_get_ndis_wlan_bssid_ex_sz(
1678                              (struct ndis_wlan_bssid_ex *)pdev_network);
1679}
1680
1681/*the function is at passive_level*/
1682void r8712_joinbss_reset(struct _adapter *padapter)
1683{
1684        int i;
1685        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
1686        struct ht_priv          *phtpriv = &pmlmepriv->htpriv;
1687
1688        /* todo: if you want to do something io/reg/hw setting before join_bss,
1689         * please add code here */
1690        phtpriv->ampdu_enable = false;/*reset to disabled*/
1691        for (i = 0; i < 16; i++)
1692                phtpriv->baddbareq_issued[i] = false;/*reset it*/
1693        if (phtpriv->ht_option) {
1694                /* validate  usb rx aggregation */
1695                r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
1696        } else {
1697                /* invalidate  usb rx aggregation */
1698                /* TH=1 => means that invalidate usb rx aggregation */
1699                r8712_write8(padapter, 0x102500D9, 1);
1700        }
1701}
1702
1703/*the function is >= passive_level*/
1704unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
1705                                     u8 *out_ie, uint in_len, uint *pout_len)
1706{
1707        u32 ielen, out_len;
1708        unsigned char *p, *pframe;
1709        struct ieee80211_ht_cap ht_capie;
1710        unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
1711        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1712        struct qos_priv *pqospriv = &pmlmepriv->qospriv;
1713        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1714
1715        phtpriv->ht_option = 0;
1716        p = r8712_get_ie(in_ie+12, _HT_CAPABILITY_IE_, &ielen, in_len-12);
1717        if (p && (ielen > 0)) {
1718                if (pqospriv->qos_option == 0) {
1719                        out_len = *pout_len;
1720                        pframe = r8712_set_ie(out_ie+out_len,
1721                                              _VENDOR_SPECIFIC_IE_,
1722                                              _WMM_IE_Length_,
1723                                               WMM_IE, pout_len);
1724                        pqospriv->qos_option = 1;
1725                }
1726                out_len = *pout_len;
1727                memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
1728                ht_capie.cap_info = IEEE80211_HT_CAP_SUP_WIDTH |
1729                                    IEEE80211_HT_CAP_SGI_20 |
1730                                    IEEE80211_HT_CAP_SGI_40 |
1731                                    IEEE80211_HT_CAP_TX_STBC |
1732                                    IEEE80211_HT_CAP_MAX_AMSDU |
1733                                    IEEE80211_HT_CAP_DSSSCCK40;
1734                ht_capie.ampdu_params_info = (IEEE80211_HT_CAP_AMPDU_FACTOR &
1735                                0x03) | (IEEE80211_HT_CAP_AMPDU_DENSITY & 0x00);
1736                pframe = r8712_set_ie(out_ie+out_len, _HT_CAPABILITY_IE_,
1737                                sizeof(struct ieee80211_ht_cap),
1738                                (unsigned char *)&ht_capie, pout_len);
1739                phtpriv->ht_option = 1;
1740        }
1741        return phtpriv->ht_option;
1742}
1743
1744/* the function is > passive_level (in critical_section) */
1745static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
1746{
1747        u8 *p, max_ampdu_sz;
1748        int i, len;
1749        struct sta_info *bmc_sta, *psta;
1750        struct ieee80211_ht_cap *pht_capie;
1751        struct ieee80211_ht_addt_info *pht_addtinfo;
1752        struct recv_reorder_ctrl *preorder_ctrl;
1753        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1754        struct ht_priv *phtpriv = &pmlmepriv->htpriv;
1755        struct registry_priv *pregistrypriv = &padapter->registrypriv;
1756        struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
1757
1758        if (!phtpriv->ht_option)
1759                return;
1760        /* maybe needs check if ap supports rx ampdu. */
1761        if ((phtpriv->ampdu_enable == false) &&
1762            (pregistrypriv->ampdu_enable == 1))
1763                phtpriv->ampdu_enable = true;
1764        /*check Max Rx A-MPDU Size*/
1765        len = 0;
1766        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1767                                _HT_CAPABILITY_IE_,
1768                                &len, ie_len -
1769                                sizeof(struct NDIS_802_11_FIXED_IEs));
1770        if (p && len > 0) {
1771                pht_capie = (struct ieee80211_ht_cap *)(p+2);
1772                max_ampdu_sz = (pht_capie->ampdu_params_info &
1773                                IEEE80211_HT_CAP_AMPDU_FACTOR);
1774                /* max_ampdu_sz (kbytes); */
1775                max_ampdu_sz = 1 << (max_ampdu_sz+3);
1776                phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
1777        }
1778        /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
1779         * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
1780         * wstart_b(indicate_seq) to default value=0xffff
1781         * todo: check if AP can send A-MPDU packets
1782         */
1783        bmc_sta = r8712_get_bcmc_stainfo(padapter);
1784        if (bmc_sta) {
1785                for (i = 0; i < 16; i++) {
1786                        preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
1787                        preorder_ctrl->indicate_seq = 0xffff;
1788                        preorder_ctrl->wend_b = 0xffff;
1789                }
1790        }
1791        psta = r8712_get_stainfo(&padapter->stapriv,
1792                                 pcur_network->network.MacAddress);
1793        if (psta) {
1794                for (i = 0; i < 16 ; i++) {
1795                        preorder_ctrl = &psta->recvreorder_ctrl[i];
1796                        preorder_ctrl->indicate_seq = 0xffff;
1797                        preorder_ctrl->wend_b = 0xffff;
1798                }
1799        }
1800        len = 0;
1801        p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
1802                   _HT_ADD_INFO_IE_, &len,
1803                   ie_len-sizeof(struct NDIS_802_11_FIXED_IEs));
1804        if (p && len > 0)
1805                pht_addtinfo = (struct ieee80211_ht_addt_info *)(p + 2);
1806}
1807
1808void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
1809{
1810        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1811        struct ht_priv   *phtpriv = &pmlmepriv->htpriv;
1812
1813        if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable == true)) {
1814                if (phtpriv->baddbareq_issued[priority] == false) {
1815                        r8712_addbareq_cmd(padapter, (u8)priority);
1816                        phtpriv->baddbareq_issued[priority] = true;
1817                }
1818        }
1819}
1820