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