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