linux/drivers/staging/rtl8712/rtl871x_cmd.c
<<
>>
Prefs
   1/******************************************************************************
   2 * rtl871x_cmd.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_CMD_C_
  30
  31#include <linux/compiler.h>
  32#include <linux/kernel.h>
  33#include <linux/errno.h>
  34#include <linux/init.h>
  35#include <linux/slab.h>
  36#include <linux/module.h>
  37#include <linux/kref.h>
  38#include <linux/netdevice.h>
  39#include <linux/skbuff.h>
  40#include <linux/usb.h>
  41#include <linux/usb/ch9.h>
  42#include <linux/circ_buf.h>
  43#include <linux/uaccess.h>
  44#include <asm/byteorder.h>
  45#include <linux/atomic.h>
  46#include <linux/semaphore.h>
  47#include <linux/rtnetlink.h>
  48
  49#include "osdep_service.h"
  50#include "drv_types.h"
  51#include "recv_osdep.h"
  52#include "mlme_osdep.h"
  53#include "rtl871x_byteorder.h"
  54
  55/*
  56Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
  57No irqsave is necessary.
  58*/
  59
  60static sint _init_cmd_priv(struct cmd_priv *pcmdpriv)
  61{
  62        sema_init(&(pcmdpriv->cmd_queue_sema), 0);
  63        sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0);
  64
  65        _init_queue(&(pcmdpriv->cmd_queue));
  66
  67        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  68        pcmdpriv->cmd_seq = 1;
  69        pcmdpriv->cmd_allocated_buf = _malloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ);
  70        if (pcmdpriv->cmd_allocated_buf == NULL)
  71                return _FAIL;
  72        pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf  +  CMDBUFF_ALIGN_SZ -
  73                            ((addr_t)(pcmdpriv->cmd_allocated_buf) &
  74                            (CMDBUFF_ALIGN_SZ-1));
  75        pcmdpriv->rsp_allocated_buf = _malloc(MAX_RSPSZ + 4);
  76        if (pcmdpriv->rsp_allocated_buf == NULL)
  77                return _FAIL;
  78        pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf  +  4 -
  79                            ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
  80        pcmdpriv->cmd_issued_cnt = 0;
  81        pcmdpriv->cmd_done_cnt = 0;
  82        pcmdpriv->rsp_cnt = 0;
  83        return _SUCCESS;
  84}
  85
  86static sint _init_evt_priv(struct evt_priv *pevtpriv)
  87{
  88        /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
  89        pevtpriv->event_seq = 0;
  90        pevtpriv->evt_allocated_buf = _malloc(MAX_EVTSZ + 4);
  91
  92        if (pevtpriv->evt_allocated_buf == NULL)
  93                return _FAIL;
  94        pevtpriv->evt_buf = pevtpriv->evt_allocated_buf  +  4 -
  95                            ((addr_t)(pevtpriv->evt_allocated_buf) & 3);
  96        pevtpriv->evt_done_cnt = 0;
  97        return _SUCCESS;
  98}
  99
 100static void _free_evt_priv(struct evt_priv *pevtpriv)
 101{
 102        kfree(pevtpriv->evt_allocated_buf);
 103}
 104
 105static void _free_cmd_priv(struct cmd_priv *pcmdpriv)
 106{
 107        if (pcmdpriv) {
 108                kfree(pcmdpriv->cmd_allocated_buf);
 109                kfree(pcmdpriv->rsp_allocated_buf);
 110        }
 111}
 112
 113/*
 114Calling Context:
 115
 116_enqueue_cmd can only be called between kernel thread,
 117since only spin_lock is used.
 118
 119ISR/Call-Back functions can't call this sub-function.
 120
 121*/
 122
 123static sint _enqueue_cmd(struct  __queue *queue, struct cmd_obj *obj)
 124{
 125        unsigned long irqL;
 126
 127        if (obj == NULL)
 128                return _SUCCESS;
 129        spin_lock_irqsave(&queue->lock, irqL);
 130        list_insert_tail(&obj->list, &queue->queue);
 131        spin_unlock_irqrestore(&queue->lock, irqL);
 132        return _SUCCESS;
 133}
 134
 135static struct cmd_obj *_dequeue_cmd(struct  __queue *queue)
 136{
 137        unsigned long irqL;
 138        struct cmd_obj *obj;
 139
 140        spin_lock_irqsave(&(queue->lock), irqL);
 141        if (is_list_empty(&(queue->queue)))
 142                obj = NULL;
 143        else {
 144                obj = LIST_CONTAINOR(get_next(&(queue->queue)),
 145                                     struct cmd_obj, list);
 146                list_delete(&obj->list);
 147        }
 148        spin_unlock_irqrestore(&(queue->lock), irqL);
 149        return obj;
 150}
 151
 152u32 r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
 153{
 154        return _init_cmd_priv(pcmdpriv);
 155}
 156
 157u32 r8712_init_evt_priv(struct evt_priv *pevtpriv)
 158{
 159        return _init_evt_priv(pevtpriv);
 160}
 161
 162void r8712_free_evt_priv(struct evt_priv *pevtpriv)
 163{
 164        _free_evt_priv(pevtpriv);
 165}
 166
 167void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
 168{
 169        _free_cmd_priv(pcmdpriv);
 170}
 171
 172u32 r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
 173{
 174        int res;
 175
 176        if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
 177                return _FAIL;
 178        res = _enqueue_cmd(&pcmdpriv->cmd_queue, obj);
 179        up(&pcmdpriv->cmd_queue_sema);
 180        return res;
 181}
 182
 183u32 r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
 184{
 185        unsigned long irqL;
 186        struct  __queue *queue;
 187
 188        if (obj == NULL)
 189                return _SUCCESS;
 190        if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag == true)
 191                return _FAIL;
 192        queue = &pcmdpriv->cmd_queue;
 193        spin_lock_irqsave(&queue->lock, irqL);
 194        list_insert_tail(&obj->list, &queue->queue);
 195        spin_unlock_irqrestore(&queue->lock, irqL);
 196        up(&pcmdpriv->cmd_queue_sema);
 197        return _SUCCESS;
 198}
 199
 200struct cmd_obj *r8712_dequeue_cmd(struct  __queue *queue)
 201{
 202        return _dequeue_cmd(queue);
 203}
 204
 205void r8712_free_cmd_obj(struct cmd_obj *pcmd)
 206{
 207        if ((pcmd->cmdcode != _JoinBss_CMD_) &&
 208            (pcmd->cmdcode != _CreateBss_CMD_))
 209                kfree((unsigned char *)pcmd->parmbuf);
 210        if (pcmd->rsp != NULL) {
 211                if (pcmd->rspsz != 0)
 212                        kfree((unsigned char *)pcmd->rsp);
 213        }
 214        kfree((unsigned char *)pcmd);
 215}
 216
 217/*
 218r8712_sitesurvey_cmd(~)
 219        ### NOTE:#### (!!!!)
 220        MUST TAKE CARE THAT BEFORE CALLING THIS FUNC,
 221         YOU SHOULD HAVE LOCKED pmlmepriv->lock
 222*/
 223u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
 224                        struct ndis_802_11_ssid *pssid)
 225{
 226        struct cmd_obj  *ph2c;
 227        struct sitesurvey_parm  *psurveyPara;
 228        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 229        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 230
 231        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 232        if (ph2c == NULL)
 233                return _FAIL;
 234        psurveyPara = (struct sitesurvey_parm *)_malloc(
 235                       sizeof(struct sitesurvey_parm));
 236        if (psurveyPara == NULL) {
 237                kfree((unsigned char *) ph2c);
 238                return _FAIL;
 239        }
 240        init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
 241                                   GEN_CMD_CODE(_SiteSurvey));
 242        psurveyPara->bsslimit = cpu_to_le32(48);
 243        psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
 244        psurveyPara->ss_ssidlen = 0;
 245        memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
 246        if ((pssid != NULL) && (pssid->SsidLength)) {
 247                memcpy(psurveyPara->ss_ssid, pssid->Ssid, pssid->SsidLength);
 248                psurveyPara->ss_ssidlen = cpu_to_le32(pssid->SsidLength);
 249        }
 250        set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 251        r8712_enqueue_cmd(pcmdpriv, ph2c);
 252        _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT);
 253        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
 254        padapter->blnEnableRxFF0Filter = 0;
 255        return _SUCCESS;
 256}
 257
 258u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
 259{
 260        struct cmd_obj          *ph2c;
 261        struct setdatarate_parm *pbsetdataratepara;
 262        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 263
 264        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 265        if (ph2c == NULL)
 266                return _FAIL;
 267        pbsetdataratepara = (struct setdatarate_parm *)_malloc(
 268                             sizeof(struct setdatarate_parm));
 269        if (pbsetdataratepara == NULL) {
 270                kfree((u8 *) ph2c);
 271                return _FAIL;
 272        }
 273        init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
 274                                   GEN_CMD_CODE(_SetDataRate));
 275        pbsetdataratepara->mac_id = 5;
 276        memcpy(pbsetdataratepara->datarates, rateset, NumRates);
 277        r8712_enqueue_cmd(pcmdpriv, ph2c);
 278        return _SUCCESS;
 279}
 280
 281u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
 282{
 283        struct cmd_obj *ph2c;
 284        struct SetChannelPlan_param *psetchplanpara;
 285        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 286
 287        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 288        if (ph2c == NULL)
 289                return _FAIL;
 290        psetchplanpara = (struct SetChannelPlan_param *)
 291                _malloc(sizeof(struct SetChannelPlan_param));
 292        if (psetchplanpara == NULL) {
 293                kfree((u8 *) ph2c);
 294                return _FAIL;
 295        }
 296        init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara,
 297                                GEN_CMD_CODE(_SetChannelPlan));
 298        psetchplanpara->ChannelPlan = chplan;
 299        r8712_enqueue_cmd(pcmdpriv, ph2c);
 300        return _SUCCESS;
 301}
 302
 303u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset)
 304{
 305        struct cmd_obj *ph2c;
 306        struct setbasicrate_parm *pssetbasicratepara;
 307        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 308
 309        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 310        if (ph2c == NULL)
 311                return _FAIL;
 312        pssetbasicratepara = (struct setbasicrate_parm *)_malloc(
 313                              sizeof(struct setbasicrate_parm));
 314        if (pssetbasicratepara == NULL) {
 315                kfree((u8 *) ph2c);
 316                return _FAIL;
 317        }
 318        init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara,
 319                _SetBasicRate_CMD_);
 320        memcpy(pssetbasicratepara->basicrates, rateset, NumRates);
 321        r8712_enqueue_cmd(pcmdpriv, ph2c);
 322        return _SUCCESS;
 323}
 324
 325/* power tracking mechanism setting */
 326u8 r8712_setptm_cmd(struct _adapter *padapter, u8 type)
 327{
 328        struct cmd_obj          *ph2c;
 329        struct writePTM_parm    *pwriteptmparm;
 330        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 331
 332        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 333        if (ph2c == NULL)
 334                return _FAIL;
 335        pwriteptmparm = (struct writePTM_parm *)
 336                _malloc(sizeof(struct writePTM_parm));
 337        if (pwriteptmparm == NULL) {
 338                kfree((u8 *) ph2c);
 339                return _FAIL;
 340        }
 341        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetPT));
 342        pwriteptmparm->type = type;
 343        r8712_enqueue_cmd(pcmdpriv, ph2c);
 344        return _SUCCESS;
 345}
 346
 347u8 r8712_setfwdig_cmd(struct _adapter *padapter, u8 type)
 348{
 349        struct cmd_obj *ph2c;
 350        struct writePTM_parm *pwriteptmparm;
 351        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 352
 353        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 354        if (ph2c == NULL)
 355                return _FAIL;
 356        pwriteptmparm = (struct writePTM_parm *)
 357                _malloc(sizeof(struct setdig_parm));
 358        if (pwriteptmparm == NULL) {
 359                kfree((u8 *) ph2c);
 360                return _FAIL;
 361        }
 362        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetDIG));
 363        pwriteptmparm->type = type;
 364        r8712_enqueue_cmd(pcmdpriv, ph2c);
 365        return _SUCCESS;
 366}
 367
 368u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type)
 369{
 370        struct cmd_obj *ph2c;
 371        struct writePTM_parm *pwriteptmparm;
 372        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 373
 374        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 375        if (ph2c == NULL)
 376                return _FAIL;
 377        pwriteptmparm = (struct writePTM_parm *)
 378                _malloc(sizeof(struct setra_parm));
 379        if (pwriteptmparm == NULL) {
 380                kfree((u8 *) ph2c);
 381                return _FAIL;
 382        }
 383        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetRA));
 384        pwriteptmparm->type = type;
 385        r8712_enqueue_cmd(pcmdpriv, ph2c);
 386        return _SUCCESS;
 387}
 388
 389u8 r8712_setrfreg_cmd(struct _adapter  *padapter, u8 offset, u32 val)
 390{
 391        struct cmd_obj *ph2c;
 392        struct writeRF_parm *pwriterfparm;
 393        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 394
 395        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 396        if (ph2c == NULL)
 397                return _FAIL;
 398        pwriterfparm = (struct writeRF_parm *)_malloc(
 399                        sizeof(struct writeRF_parm));
 400        if (pwriterfparm == NULL) {
 401                kfree((u8 *) ph2c);
 402                return _FAIL;
 403        }
 404        init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
 405        pwriterfparm->offset = offset;
 406        pwriterfparm->value = val;
 407        r8712_enqueue_cmd(pcmdpriv, ph2c);
 408        return _SUCCESS;
 409}
 410
 411u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
 412{
 413        struct cmd_obj *ph2c;
 414        struct readRF_parm *prdrfparm;
 415        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 416
 417        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 418        if (ph2c == NULL)
 419                return _FAIL;
 420        prdrfparm = (struct readRF_parm *)_malloc(sizeof(struct readRF_parm));
 421        if (prdrfparm == NULL) {
 422                kfree((u8 *) ph2c);
 423                return _FAIL;
 424        }
 425        _init_listhead(&ph2c->list);
 426        ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
 427        ph2c->parmbuf = (unsigned char *)prdrfparm;
 428        ph2c->cmdsz =  sizeof(struct readRF_parm);
 429        ph2c->rsp = pval;
 430        ph2c->rspsz = sizeof(struct readRF_rsp);
 431        prdrfparm->offset = offset;
 432        r8712_enqueue_cmd(pcmdpriv, ph2c);
 433        return _SUCCESS;
 434}
 435
 436void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
 437                                      struct cmd_obj *pcmd)
 438{
 439        kfree(pcmd->parmbuf);
 440        kfree(pcmd);
 441        padapter->mppriv.workparam.bcompleted = true;
 442}
 443
 444void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter,
 445                                struct cmd_obj *pcmd)
 446{
 447        kfree(pcmd->parmbuf);
 448        kfree(pcmd);
 449
 450        padapter->mppriv.workparam.bcompleted = true;
 451}
 452
 453u8 r8712_createbss_cmd(struct _adapter *padapter)
 454{
 455        struct cmd_obj *pcmd;
 456        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 457        struct wlan_bssid_ex *pdev_network =
 458                                 &padapter->registrypriv.dev_network;
 459
 460        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 461        pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 462        if (pcmd == NULL)
 463                return _FAIL;
 464        _init_listhead(&pcmd->list);
 465        pcmd->cmdcode = _CreateBss_CMD_;
 466        pcmd->parmbuf = (unsigned char *)pdev_network;
 467        pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz((
 468                        struct ndis_wlan_bssid_ex *)
 469                        pdev_network);
 470        pcmd->rsp = NULL;
 471        pcmd->rspsz = 0;
 472        /* notes: translate IELength & Length after assign to cmdsz; */
 473        pdev_network->Length = cpu_to_le32(pcmd->cmdsz);
 474        pdev_network->IELength = cpu_to_le32(pdev_network->IELength);
 475        pdev_network->Ssid.SsidLength = cpu_to_le32(
 476                                        pdev_network->Ssid.SsidLength);
 477        r8712_enqueue_cmd(pcmdpriv, pcmd);
 478        return _SUCCESS;
 479}
 480
 481u8 r8712_joinbss_cmd(struct _adapter  *padapter, struct wlan_network *pnetwork)
 482{
 483        u8 *auth;
 484        uint t_len = 0;
 485        struct ndis_wlan_bssid_ex *psecnetwork;
 486        struct cmd_obj          *pcmd;
 487        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 488        struct mlme_priv        *pmlmepriv = &padapter->mlmepriv;
 489        struct qos_priv         *pqospriv = &pmlmepriv->qospriv;
 490        struct security_priv    *psecuritypriv = &padapter->securitypriv;
 491        struct registry_priv    *pregistrypriv = &padapter->registrypriv;
 492        enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork->
 493                                                network.InfrastructureMode;
 494
 495        padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
 496        pcmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 497        if (pcmd == NULL)
 498                return _FAIL;
 499        t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 +
 500                        sizeof(struct ndis_802_11_ssid) + sizeof(u32) +
 501                        sizeof(s32) +
 502                        sizeof(enum NDIS_802_11_NETWORK_TYPE) +
 503                        sizeof(struct NDIS_802_11_CONFIGURATION) +
 504                        sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) +
 505                        sizeof(NDIS_802_11_RATES_EX) +
 506                        sizeof(u32) + MAX_IE_SZ;
 507
 508        /* for hidden ap to set fw_state here */
 509        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) !=
 510            true) {
 511                switch (ndis_network_mode) {
 512                case Ndis802_11IBSS:
 513                        pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
 514                        break;
 515                case Ndis802_11Infrastructure:
 516                        pmlmepriv->fw_state |= WIFI_STATION_STATE;
 517                        break;
 518                case Ndis802_11APMode:
 519                case Ndis802_11AutoUnknown:
 520                case Ndis802_11InfrastructureMax:
 521                        break;
 522                }
 523        }
 524        psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss;
 525        if (psecnetwork == NULL) {
 526                kfree(pcmd);
 527                return _FAIL;
 528        }
 529        memset(psecnetwork, 0, t_len);
 530        memcpy(psecnetwork, &pnetwork->network, t_len);
 531        auth = &psecuritypriv->authenticator_ie[0];
 532        psecuritypriv->authenticator_ie[0] = (unsigned char)
 533                                             psecnetwork->IELength;
 534        if ((psecnetwork->IELength-12) < (256 - 1))
 535                memcpy(&psecuritypriv->authenticator_ie[1],
 536                        &psecnetwork->IEs[12], psecnetwork->IELength-12);
 537        else
 538                memcpy(&psecuritypriv->authenticator_ie[1],
 539                        &psecnetwork->IEs[12], (256-1));
 540        psecnetwork->IELength = 0;
 541        /* If the the driver wants to use the bssid to create the connection.
 542         * If not,  we copy the connecting AP's MAC address to it so that
 543         * the driver just has the bssid information for PMKIDList searching.
 544         */
 545        if (pmlmepriv->assoc_by_bssid == false)
 546                memcpy(&pmlmepriv->assoc_bssid[0],
 547                        &pnetwork->network.MacAddress[0], ETH_ALEN);
 548        psecnetwork->IELength = r8712_restruct_sec_ie(padapter,
 549                                                &pnetwork->network.IEs[0],
 550                                                &psecnetwork->IEs[0],
 551                                                pnetwork->network.IELength);
 552        pqospriv->qos_option = 0;
 553        if (pregistrypriv->wmm_enable) {
 554                u32 tmp_len;
 555
 556                tmp_len = r8712_restruct_wmm_ie(padapter,
 557                                          &pnetwork->network.IEs[0],
 558                                          &psecnetwork->IEs[0],
 559                                          pnetwork->network.IELength,
 560                                          psecnetwork->IELength);
 561                if (psecnetwork->IELength != tmp_len) {
 562                        psecnetwork->IELength = tmp_len;
 563                        pqospriv->qos_option = 1; /* WMM IE in beacon */
 564                } else
 565                        pqospriv->qos_option = 0; /* no WMM IE in beacon */
 566        }
 567        if (pregistrypriv->ht_enable) {
 568                /* For WEP mode, we will use the bg mode to do the connection
 569                 * to avoid some IOT issues, especially for Realtek 8192u
 570                 * SoftAP.
 571                 */
 572                if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
 573                    (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
 574                        /* restructure_ht_ie */
 575                        r8712_restructure_ht_ie(padapter,
 576                                                &pnetwork->network.IEs[0],
 577                                                &psecnetwork->IEs[0],
 578                                                pnetwork->network.IELength,
 579                                                &psecnetwork->IELength);
 580                }
 581        }
 582        psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
 583        if (psecnetwork->IELength < 255)
 584                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 585                        psecnetwork->IELength);
 586        else
 587                memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
 588                        255);
 589        /* get cmdsz before endian conversion */
 590        pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork);
 591#ifdef __BIG_ENDIAN
 592        /* wlan_network endian conversion */
 593        psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
 594        psecnetwork->Ssid.SsidLength = cpu_to_le32(
 595                                       psecnetwork->Ssid.SsidLength);
 596        psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
 597        psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
 598        psecnetwork->NetworkTypeInUse = cpu_to_le32(
 599                                        psecnetwork->NetworkTypeInUse);
 600        psecnetwork->Configuration.ATIMWindow = cpu_to_le32(
 601                                psecnetwork->Configuration.ATIMWindow);
 602        psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(
 603                                 psecnetwork->Configuration.BeaconPeriod);
 604        psecnetwork->Configuration.DSConfig = cpu_to_le32(
 605                                psecnetwork->Configuration.DSConfig);
 606        psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(
 607                                psecnetwork->Configuration.FHConfig.DwellTime);
 608        psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(
 609                                psecnetwork->Configuration.FHConfig.HopPattern);
 610        psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(
 611                                psecnetwork->Configuration.FHConfig.HopSet);
 612        psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(
 613                                psecnetwork->Configuration.FHConfig.Length);
 614        psecnetwork->Configuration.Length = cpu_to_le32(
 615                                psecnetwork->Configuration.Length);
 616        psecnetwork->InfrastructureMode = cpu_to_le32(
 617                                psecnetwork->InfrastructureMode);
 618        psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
 619#endif
 620        _init_listhead(&pcmd->list);
 621        pcmd->cmdcode = _JoinBss_CMD_;
 622        pcmd->parmbuf = (unsigned char *)psecnetwork;
 623        pcmd->rsp = NULL;
 624        pcmd->rspsz = 0;
 625        r8712_enqueue_cmd(pcmdpriv, pcmd);
 626        return _SUCCESS;
 627}
 628
 629u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
 630{
 631        struct cmd_obj *pdisconnect_cmd;
 632        struct disconnect_parm *pdisconnect;
 633        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 634
 635        pdisconnect_cmd = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 636        if (pdisconnect_cmd == NULL)
 637                return _FAIL;
 638        pdisconnect = (struct disconnect_parm *)_malloc(
 639                      sizeof(struct disconnect_parm));
 640        if (pdisconnect == NULL) {
 641                kfree((u8 *)pdisconnect_cmd);
 642                return _FAIL;
 643        }
 644        init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect,
 645                                   _DisConnect_CMD_);
 646        r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
 647        return _SUCCESS;
 648}
 649
 650u8 r8712_setopmode_cmd(struct _adapter *padapter,
 651                 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
 652{
 653        struct cmd_obj *ph2c;
 654        struct setopmode_parm *psetop;
 655
 656        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 657
 658        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 659        if (ph2c == NULL)
 660                return _FAIL;
 661        psetop = (struct setopmode_parm *)_malloc(
 662                  sizeof(struct setopmode_parm));
 663        if (psetop == NULL) {
 664                kfree((u8 *) ph2c);
 665                return _FAIL;
 666        }
 667        init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
 668        psetop->mode = (u8)networktype;
 669        r8712_enqueue_cmd(pcmdpriv, ph2c);
 670        return _SUCCESS;
 671}
 672
 673u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
 674{
 675        struct cmd_obj *ph2c;
 676        struct set_stakey_parm *psetstakey_para;
 677        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 678        struct set_stakey_rsp *psetstakey_rsp = NULL;
 679        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 680        struct security_priv *psecuritypriv = &padapter->securitypriv;
 681        struct sta_info *sta = (struct sta_info *)psta;
 682
 683        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 684        if (ph2c == NULL)
 685                return _FAIL;
 686        psetstakey_para = (struct set_stakey_parm *)_malloc(
 687                          sizeof(struct set_stakey_parm));
 688        if (psetstakey_para == NULL) {
 689                kfree((u8 *) ph2c);
 690                return _FAIL;
 691        }
 692        psetstakey_rsp = (struct set_stakey_rsp *)_malloc(
 693                          sizeof(struct set_stakey_rsp));
 694        if (psetstakey_rsp == NULL) {
 695                kfree((u8 *) ph2c);
 696                kfree((u8 *) psetstakey_para);
 697                return _FAIL;
 698        }
 699        init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
 700        ph2c->rsp = (u8 *) psetstakey_rsp;
 701        ph2c->rspsz = sizeof(struct set_stakey_rsp);
 702        memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN);
 703        if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
 704                psetstakey_para->algorithm = (unsigned char)
 705                                            psecuritypriv->PrivacyAlgrthm;
 706        else
 707                GET_ENCRY_ALGO(psecuritypriv, sta,
 708                               psetstakey_para->algorithm, false);
 709        if (unicast_key == true)
 710                memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
 711        else
 712                memcpy(&psetstakey_para->key,
 713                        &psecuritypriv->XGrpKey[
 714                        psecuritypriv->XGrpKeyid - 1]. skey, 16);
 715        r8712_enqueue_cmd(pcmdpriv, ph2c);
 716        return _SUCCESS;
 717}
 718
 719u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode)
 720{
 721        struct cmd_obj *ph2c;
 722        struct setrfintfs_parm *psetrfintfsparm;
 723        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 724
 725        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 726        if (ph2c == NULL)
 727                return _FAIL;
 728        psetrfintfsparm = (struct setrfintfs_parm *)_malloc(
 729                           sizeof(struct setrfintfs_parm));
 730        if (psetrfintfsparm == NULL) {
 731                kfree((unsigned char *) ph2c);
 732                return _FAIL;
 733        }
 734        init_h2fwcmd_w_parm_no_rsp(ph2c, psetrfintfsparm,
 735                                   GEN_CMD_CODE(_SetRFIntFs));
 736        psetrfintfsparm->rfintfs = mode;
 737        r8712_enqueue_cmd(pcmdpriv, ph2c);
 738        return _SUCCESS;
 739}
 740
 741u8 r8712_setrttbl_cmd(struct _adapter *padapter,
 742                      struct setratable_parm *prate_table)
 743{
 744        struct cmd_obj *ph2c;
 745        struct setratable_parm *psetrttblparm;
 746        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 747
 748        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 749        if (ph2c == NULL)
 750                return _FAIL;
 751        psetrttblparm = (struct setratable_parm *)_malloc(
 752                        sizeof(struct setratable_parm));
 753        if (psetrttblparm == NULL) {
 754                kfree((unsigned char *)ph2c);
 755                return _FAIL;
 756        }
 757        init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm,
 758                                   GEN_CMD_CODE(_SetRaTable));
 759        memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm));
 760        r8712_enqueue_cmd(pcmdpriv, ph2c);
 761        return _SUCCESS;
 762}
 763
 764u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
 765{
 766        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 767        struct cmd_obj *ph2c;
 768        struct readTSSI_parm *prdtssiparm;
 769
 770        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 771        if (ph2c == NULL)
 772                return _FAIL;
 773        prdtssiparm = (struct readTSSI_parm *)
 774                _malloc(sizeof(struct readTSSI_parm));
 775        if (prdtssiparm == NULL) {
 776                kfree((unsigned char *) ph2c);
 777                return _FAIL;
 778        }
 779        _init_listhead(&ph2c->list);
 780        ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI);
 781        ph2c->parmbuf = (unsigned char *)prdtssiparm;
 782        ph2c->cmdsz = sizeof(struct readTSSI_parm);
 783        ph2c->rsp = pval;
 784        ph2c->rspsz = sizeof(struct readTSSI_rsp);
 785
 786        prdtssiparm->offset = offset;
 787        r8712_enqueue_cmd(pcmdpriv, ph2c);
 788        return _SUCCESS;
 789}
 790
 791u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr)
 792{
 793        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 794        struct cmd_obj *ph2c;
 795        struct SetMacAddr_param *psetMacAddr_para;
 796
 797        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 798        if (ph2c == NULL)
 799                return _FAIL;
 800        psetMacAddr_para = (struct SetMacAddr_param *)_malloc(
 801                           sizeof(struct SetMacAddr_param));
 802        if (psetMacAddr_para == NULL) {
 803                kfree((u8 *) ph2c);
 804                return _FAIL;
 805        }
 806        init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para,
 807                                   _SetMacAddress_CMD_);
 808        memcpy(psetMacAddr_para->MacAddr, mac_addr, ETH_ALEN);
 809        r8712_enqueue_cmd(pcmdpriv, ph2c);
 810        return _SUCCESS;
 811}
 812
 813u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr)
 814{
 815        struct cmd_priv                 *pcmdpriv = &padapter->cmdpriv;
 816        struct cmd_obj                  *ph2c;
 817        struct set_assocsta_parm        *psetassocsta_para;
 818        struct set_stakey_rsp           *psetassocsta_rsp = NULL;
 819
 820        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 821        if (ph2c == NULL)
 822                return _FAIL;
 823        psetassocsta_para = (struct set_assocsta_parm *)
 824                            _malloc(sizeof(struct set_assocsta_parm));
 825        if (psetassocsta_para == NULL) {
 826                kfree((u8 *) ph2c);
 827                return _FAIL;
 828        }
 829        psetassocsta_rsp = (struct set_stakey_rsp *)_malloc(
 830                            sizeof(struct set_assocsta_rsp));
 831        if (psetassocsta_rsp == NULL) {
 832                kfree((u8 *)ph2c);
 833                kfree((u8 *)psetassocsta_para);
 834                return _FAIL;
 835        }
 836        init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_);
 837        ph2c->rsp = (u8 *) psetassocsta_rsp;
 838        ph2c->rspsz = sizeof(struct set_assocsta_rsp);
 839        memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN);
 840        r8712_enqueue_cmd(pcmdpriv, ph2c);
 841        return _SUCCESS;
 842}
 843
 844u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
 845{
 846        struct cmd_priv         *pcmdpriv = &padapter->cmdpriv;
 847        struct cmd_obj          *ph2c;
 848        struct addBaReq_parm    *paddbareq_parm;
 849
 850        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 851        if (ph2c == NULL)
 852                return _FAIL;
 853        paddbareq_parm = (struct addBaReq_parm *)_malloc(
 854                          sizeof(struct addBaReq_parm));
 855        if (paddbareq_parm == NULL) {
 856                kfree((unsigned char *)ph2c);
 857                return _FAIL;
 858        }
 859        paddbareq_parm->tid = tid;
 860        init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm,
 861                                   GEN_CMD_CODE(_AddBAReq));
 862        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 863        return _SUCCESS;
 864}
 865
 866u8 r8712_wdg_wk_cmd(struct _adapter *padapter)
 867{
 868        struct cmd_obj *ph2c;
 869        struct drvint_cmd_parm  *pdrvintcmd_param;
 870        struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
 871
 872        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
 873        if (ph2c == NULL)
 874                return _FAIL;
 875        pdrvintcmd_param = (struct drvint_cmd_parm *)_malloc(
 876                           sizeof(struct drvint_cmd_parm));
 877        if (pdrvintcmd_param == NULL) {
 878                kfree((unsigned char *)ph2c);
 879                return _FAIL;
 880        }
 881        pdrvintcmd_param->i_cid = WDG_WK_CID;
 882        pdrvintcmd_param->sz = 0;
 883        pdrvintcmd_param->pbuf = NULL;
 884        init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
 885        r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
 886        return _SUCCESS;
 887}
 888
 889void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 890{
 891        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 892
 893        if (pcmd->res != H2C_SUCCESS)
 894                clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
 895        r8712_free_cmd_obj(pcmd);
 896}
 897
 898void r8712_disassoc_cmd_callback(struct _adapter *padapter,
 899                                 struct cmd_obj *pcmd)
 900{
 901        unsigned long irqL;
 902        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 903
 904        if (pcmd->res != H2C_SUCCESS) {
 905                spin_lock_irqsave(&pmlmepriv->lock, irqL);
 906                set_fwstate(pmlmepriv, _FW_LINKED);
 907                spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 908                return;
 909        }
 910        r8712_free_cmd_obj(pcmd);
 911}
 912
 913void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
 914{
 915        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
 916
 917        if ((pcmd->res != H2C_SUCCESS))
 918                _set_timer(&pmlmepriv->assoc_timer, 1);
 919        r8712_free_cmd_obj(pcmd);
 920}
 921
 922void r8712_createbss_cmd_callback(struct _adapter *padapter,
 923                                  struct cmd_obj *pcmd)
 924{
 925        unsigned long irqL;
 926        u8 timer_cancelled;
 927        struct sta_info *psta = NULL;
 928        struct wlan_network *pwlan = NULL;
 929        struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
 930        struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *)
 931                                              pcmd->parmbuf;
 932        struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
 933
 934        if ((pcmd->res != H2C_SUCCESS))
 935                _set_timer(&pmlmepriv->assoc_timer, 1);
 936        _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled);
 937#ifdef __BIG_ENDIAN
 938        /* endian_convert */
 939        pnetwork->Length = le32_to_cpu(pnetwork->Length);
 940        pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
 941        pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
 942        pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
 943        pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
 944        pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->
 945                                        Configuration.ATIMWindow);
 946        pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->
 947                                        Configuration.DSConfig);
 948        pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->
 949                                        Configuration.FHConfig.DwellTime);
 950        pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->
 951                                        Configuration.FHConfig.HopPattern);
 952        pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->
 953                                        Configuration.FHConfig.HopSet);
 954        pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->
 955                                        Configuration.FHConfig.Length);
 956        pnetwork->Configuration.Length = le32_to_cpu(pnetwork->
 957                                        Configuration.Length);
 958        pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->
 959                                           InfrastructureMode);
 960        pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
 961#endif
 962        spin_lock_irqsave(&pmlmepriv->lock, irqL);
 963        if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
 964                psta = r8712_get_stainfo(&padapter->stapriv,
 965                                         pnetwork->MacAddress);
 966                if (!psta) {
 967                        psta = r8712_alloc_stainfo(&padapter->stapriv,
 968                                                   pnetwork->MacAddress);
 969                        if (psta == NULL)
 970                                goto createbss_cmd_fail ;
 971                }
 972                r8712_indicate_connect(padapter);
 973        } else {
 974                pwlan = _r8712_alloc_network(pmlmepriv);
 975                if (pwlan == NULL) {
 976                        pwlan = r8712_get_oldest_wlan_network(
 977                                &pmlmepriv->scanned_queue);
 978                        if (pwlan == NULL)
 979                                goto createbss_cmd_fail;
 980                        pwlan->last_scanned = jiffies;
 981                } else
 982                        list_insert_tail(&(pwlan->list),
 983                                         &pmlmepriv->scanned_queue.queue);
 984                pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork);
 985                memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
 986                pwlan->fixed = true;
 987                memcpy(&tgt_network->network, pnetwork,
 988                        (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork)));
 989                if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
 990                        pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
 991                /* we will set _FW_LINKED when there is one more sat to
 992                 * join us (stassoc_event_callback) */
 993        }
 994createbss_cmd_fail:
 995        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
 996        r8712_free_cmd_obj(pcmd);
 997}
 998
 999void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter,
1000                                     struct cmd_obj *pcmd)
1001{
1002        struct sta_priv *pstapriv = &padapter->stapriv;
1003        struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *)
1004                                                (pcmd->rsp);
1005        struct sta_info *psta = r8712_get_stainfo(pstapriv,
1006                                                  psetstakey_rsp->addr);
1007
1008        if (psta == NULL)
1009                goto exit;
1010        psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
1011exit:
1012        r8712_free_cmd_obj(pcmd);
1013}
1014
1015void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
1016                                       struct cmd_obj *pcmd)
1017{
1018        unsigned long   irqL;
1019        struct sta_priv *pstapriv = &padapter->stapriv;
1020        struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
1021        struct set_assocsta_parm *passocsta_parm =
1022                                (struct set_assocsta_parm *)(pcmd->parmbuf);
1023        struct set_assocsta_rsp *passocsta_rsp =
1024                                (struct set_assocsta_rsp *) (pcmd->rsp);
1025        struct sta_info *psta = r8712_get_stainfo(pstapriv,
1026                                                  passocsta_parm->addr);
1027
1028        if (psta == NULL)
1029                return;
1030        psta->aid = psta->mac_id = passocsta_rsp->cam_id;
1031        spin_lock_irqsave(&pmlmepriv->lock, irqL);
1032        if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) &&
1033            (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
1034                pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
1035        set_fwstate(pmlmepriv, _FW_LINKED);
1036        spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
1037        r8712_free_cmd_obj(pcmd);
1038}
1039
1040u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl,
1041                        u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO)
1042{
1043        struct cmd_obj *ph2c;
1044        struct DisconnectCtrlEx_param *param;
1045        struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
1046
1047        ph2c = (struct cmd_obj *)_malloc(sizeof(struct cmd_obj));
1048        if (ph2c == NULL)
1049                return _FAIL;
1050        param = (struct DisconnectCtrlEx_param *)
1051                _malloc(sizeof(struct DisconnectCtrlEx_param));
1052        if (param == NULL) {
1053                kfree((unsigned char *) ph2c);
1054                return _FAIL;
1055        }
1056        memset(param, 0, sizeof(struct DisconnectCtrlEx_param));
1057
1058        param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
1059        param->TryPktCnt = (unsigned char)tryPktCnt;
1060        param->TryPktInterval = (unsigned char)tryPktInterval;
1061        param->FirstStageTO = (unsigned int)firstStageTO;
1062
1063        init_h2fwcmd_w_parm_no_rsp(ph2c, param,
1064                                GEN_CMD_CODE(_DisconnectCtrlEx));
1065        r8712_enqueue_cmd(pcmdpriv, ph2c);
1066        return _SUCCESS;
1067}
1068