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/* 54Caller and the r8712_cmd_thread can protect cmd_q by spin_lock. 55No irqsave is necessary. 56*/ 57 58static sint _init_cmd_priv(struct cmd_priv *pcmdpriv) 59{ 60 sema_init(&(pcmdpriv->cmd_queue_sema), 0); 61 sema_init(&(pcmdpriv->terminate_cmdthread_sema), 0); 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 == 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 = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC); 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 = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC); 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_add_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 (list_empty(&(queue->queue))) 141 obj = NULL; 142 else { 143 obj = LIST_CONTAINOR(queue->queue.next, 144 struct cmd_obj, list); 145 list_del_init(&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_add_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 = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 231 if (ph2c == NULL) 232 return _FAIL; 233 psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC); 234 if (psurveyPara == NULL) { 235 kfree((unsigned char *) 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 _set_timer(&pmlmepriv->scan_to_timer, SCANNING_TIMEOUT); 251 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY); 252 padapter->blnEnableRxFF0Filter = 0; 253 return _SUCCESS; 254} 255 256u8 r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset) 257{ 258 struct cmd_obj *ph2c; 259 struct setdatarate_parm *pbsetdataratepara; 260 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 261 262 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 263 if (ph2c == NULL) 264 return _FAIL; 265 pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC); 266 if (pbsetdataratepara == NULL) { 267 kfree((u8 *) ph2c); 268 return _FAIL; 269 } 270 init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara, 271 GEN_CMD_CODE(_SetDataRate)); 272 pbsetdataratepara->mac_id = 5; 273 memcpy(pbsetdataratepara->datarates, rateset, NumRates); 274 r8712_enqueue_cmd(pcmdpriv, ph2c); 275 return _SUCCESS; 276} 277 278u8 r8712_set_chplan_cmd(struct _adapter *padapter, int chplan) 279{ 280 struct cmd_obj *ph2c; 281 struct SetChannelPlan_param *psetchplanpara; 282 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 283 284 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 285 if (ph2c == NULL) 286 return _FAIL; 287 psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC); 288 if (psetchplanpara == NULL) { 289 kfree((u8 *) ph2c); 290 return _FAIL; 291 } 292 init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara, 293 GEN_CMD_CODE(_SetChannelPlan)); 294 psetchplanpara->ChannelPlan = chplan; 295 r8712_enqueue_cmd(pcmdpriv, ph2c); 296 return _SUCCESS; 297} 298 299u8 r8712_setbasicrate_cmd(struct _adapter *padapter, u8 *rateset) 300{ 301 struct cmd_obj *ph2c; 302 struct setbasicrate_parm *pssetbasicratepara; 303 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 304 305 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 306 if (ph2c == NULL) 307 return _FAIL; 308 pssetbasicratepara = kmalloc(sizeof(*pssetbasicratepara), GFP_ATOMIC); 309 if (pssetbasicratepara == NULL) { 310 kfree((u8 *) ph2c); 311 return _FAIL; 312 } 313 init_h2fwcmd_w_parm_no_rsp(ph2c, pssetbasicratepara, 314 _SetBasicRate_CMD_); 315 memcpy(pssetbasicratepara->basicrates, rateset, NumRates); 316 r8712_enqueue_cmd(pcmdpriv, ph2c); 317 return _SUCCESS; 318} 319 320/* power tracking mechanism setting */ 321u8 r8712_setptm_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 == NULL) 329 return _FAIL; 330 pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); 331 if (pwriteptmparm == NULL) { 332 kfree((u8 *) ph2c); 333 return _FAIL; 334 } 335 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetPT)); 336 pwriteptmparm->type = type; 337 r8712_enqueue_cmd(pcmdpriv, ph2c); 338 return _SUCCESS; 339} 340 341u8 r8712_setfwdig_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 == NULL) 349 return _FAIL; 350 pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); 351 if (pwriteptmparm == NULL) { 352 kfree((u8 *) ph2c); 353 return _FAIL; 354 } 355 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetDIG)); 356 pwriteptmparm->type = type; 357 r8712_enqueue_cmd(pcmdpriv, ph2c); 358 return _SUCCESS; 359} 360 361u8 r8712_setfwra_cmd(struct _adapter *padapter, u8 type) 362{ 363 struct cmd_obj *ph2c; 364 struct writePTM_parm *pwriteptmparm; 365 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 366 367 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 368 if (ph2c == NULL) 369 return _FAIL; 370 pwriteptmparm = kmalloc(sizeof(*pwriteptmparm), GFP_ATOMIC); 371 if (pwriteptmparm == NULL) { 372 kfree((u8 *) ph2c); 373 return _FAIL; 374 } 375 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriteptmparm, GEN_CMD_CODE(_SetRA)); 376 pwriteptmparm->type = type; 377 r8712_enqueue_cmd(pcmdpriv, ph2c); 378 return _SUCCESS; 379} 380 381u8 r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val) 382{ 383 struct cmd_obj *ph2c; 384 struct writeRF_parm *pwriterfparm; 385 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 386 387 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 388 if (ph2c == NULL) 389 return _FAIL; 390 pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC); 391 if (pwriterfparm == NULL) { 392 kfree((u8 *) ph2c); 393 return _FAIL; 394 } 395 init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg)); 396 pwriterfparm->offset = offset; 397 pwriterfparm->value = val; 398 r8712_enqueue_cmd(pcmdpriv, ph2c); 399 return _SUCCESS; 400} 401 402u8 r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval) 403{ 404 struct cmd_obj *ph2c; 405 struct readRF_parm *prdrfparm; 406 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 407 408 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 409 if (ph2c == NULL) 410 return _FAIL; 411 prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC); 412 if (prdrfparm == NULL) { 413 kfree((u8 *) ph2c); 414 return _FAIL; 415 } 416 INIT_LIST_HEAD(&ph2c->list); 417 ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg); 418 ph2c->parmbuf = (unsigned char *)prdrfparm; 419 ph2c->cmdsz = sizeof(struct readRF_parm); 420 ph2c->rsp = pval; 421 ph2c->rspsz = sizeof(struct readRF_rsp); 422 prdrfparm->offset = offset; 423 r8712_enqueue_cmd(pcmdpriv, ph2c); 424 return _SUCCESS; 425} 426 427void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, 428 struct cmd_obj *pcmd) 429{ 430 kfree(pcmd->parmbuf); 431 kfree(pcmd); 432 padapter->mppriv.workparam.bcompleted = true; 433} 434 435void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, 436 struct cmd_obj *pcmd) 437{ 438 kfree(pcmd->parmbuf); 439 kfree(pcmd); 440 441 padapter->mppriv.workparam.bcompleted = true; 442} 443 444u8 r8712_createbss_cmd(struct _adapter *padapter) 445{ 446 struct cmd_obj *pcmd; 447 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 448 struct wlan_bssid_ex *pdev_network = 449 &padapter->registrypriv.dev_network; 450 451 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); 452 pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); 453 if (pcmd == NULL) 454 return _FAIL; 455 INIT_LIST_HEAD(&pcmd->list); 456 pcmd->cmdcode = _CreateBss_CMD_; 457 pcmd->parmbuf = (unsigned char *)pdev_network; 458 pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(( 459 struct ndis_wlan_bssid_ex *) 460 pdev_network); 461 pcmd->rsp = NULL; 462 pcmd->rspsz = 0; 463 /* notes: translate IELength & Length after assign to cmdsz; */ 464 pdev_network->Length = pcmd->cmdsz; 465 pdev_network->IELength = pdev_network->IELength; 466 pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength; 467 r8712_enqueue_cmd(pcmdpriv, pcmd); 468 return _SUCCESS; 469} 470 471u8 r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork) 472{ 473 u8 *auth; 474 uint t_len = 0; 475 struct ndis_wlan_bssid_ex *psecnetwork; 476 struct cmd_obj *pcmd; 477 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 478 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 479 struct qos_priv *pqospriv = &pmlmepriv->qospriv; 480 struct security_priv *psecuritypriv = &padapter->securitypriv; 481 struct registry_priv *pregistrypriv = &padapter->registrypriv; 482 enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode = pnetwork-> 483 network.InfrastructureMode; 484 485 padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK); 486 pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC); 487 if (pcmd == NULL) 488 return _FAIL; 489 t_len = sizeof(u32) + 6 * sizeof(unsigned char) + 2 + 490 sizeof(struct ndis_802_11_ssid) + sizeof(u32) + 491 sizeof(s32) + 492 sizeof(enum NDIS_802_11_NETWORK_TYPE) + 493 sizeof(struct NDIS_802_11_CONFIGURATION) + 494 sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE) + 495 sizeof(NDIS_802_11_RATES_EX) + 496 sizeof(u32) + MAX_IE_SZ; 497 498 /* for hidden ap to set fw_state here */ 499 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE|WIFI_ADHOC_STATE) != 500 true) { 501 switch (ndis_network_mode) { 502 case Ndis802_11IBSS: 503 pmlmepriv->fw_state |= WIFI_ADHOC_STATE; 504 break; 505 case Ndis802_11Infrastructure: 506 pmlmepriv->fw_state |= WIFI_STATION_STATE; 507 break; 508 case Ndis802_11APMode: 509 case Ndis802_11AutoUnknown: 510 case Ndis802_11InfrastructureMax: 511 break; 512 } 513 } 514 psecnetwork = (struct ndis_wlan_bssid_ex *)&psecuritypriv->sec_bss; 515 if (psecnetwork == NULL) { 516 kfree(pcmd); 517 return _FAIL; 518 } 519 memcpy(psecnetwork, &pnetwork->network, t_len); 520 auth = &psecuritypriv->authenticator_ie[0]; 521 psecuritypriv->authenticator_ie[0] = (unsigned char) 522 psecnetwork->IELength; 523 if ((psecnetwork->IELength-12) < (256 - 1)) 524 memcpy(&psecuritypriv->authenticator_ie[1], 525 &psecnetwork->IEs[12], psecnetwork->IELength-12); 526 else 527 memcpy(&psecuritypriv->authenticator_ie[1], 528 &psecnetwork->IEs[12], (256-1)); 529 psecnetwork->IELength = 0; 530 /* If the the driver wants to use the bssid to create the connection. 531 * If not, we copy the connecting AP's MAC address to it so that 532 * the driver just has the bssid information for PMKIDList searching. 533 */ 534 if (pmlmepriv->assoc_by_bssid == false) 535 memcpy(&pmlmepriv->assoc_bssid[0], 536 &pnetwork->network.MacAddress[0], ETH_ALEN); 537 psecnetwork->IELength = r8712_restruct_sec_ie(padapter, 538 &pnetwork->network.IEs[0], 539 &psecnetwork->IEs[0], 540 pnetwork->network.IELength); 541 pqospriv->qos_option = 0; 542 if (pregistrypriv->wmm_enable) { 543 u32 tmp_len; 544 545 tmp_len = r8712_restruct_wmm_ie(padapter, 546 &pnetwork->network.IEs[0], 547 &psecnetwork->IEs[0], 548 pnetwork->network.IELength, 549 psecnetwork->IELength); 550 if (psecnetwork->IELength != tmp_len) { 551 psecnetwork->IELength = tmp_len; 552 pqospriv->qos_option = 1; /* WMM IE in beacon */ 553 } else 554 pqospriv->qos_option = 0; /* no WMM IE in beacon */ 555 } 556 if (pregistrypriv->ht_enable) { 557 /* For WEP mode, we will use the bg mode to do the connection 558 * to avoid some IOT issues, especially for Realtek 8192u 559 * SoftAP. 560 */ 561 if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) && 562 (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) { 563 /* restructure_ht_ie */ 564 r8712_restructure_ht_ie(padapter, 565 &pnetwork->network.IEs[0], 566 &psecnetwork->IEs[0], 567 pnetwork->network.IELength, 568 &psecnetwork->IELength); 569 } 570 } 571 psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength; 572 if (psecnetwork->IELength < 255) 573 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], 574 psecnetwork->IELength); 575 else 576 memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0], 577 255); 578 /* get cmdsz before endian conversion */ 579 pcmd->cmdsz = r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork); 580#ifdef __BIG_ENDIAN 581 /* wlan_network endian conversion */ 582 psecnetwork->Length = cpu_to_le32(psecnetwork->Length); 583 psecnetwork->Ssid.SsidLength = cpu_to_le32( 584 psecnetwork->Ssid.SsidLength); 585 psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy); 586 psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi); 587 psecnetwork->NetworkTypeInUse = cpu_to_le32( 588 psecnetwork->NetworkTypeInUse); 589 psecnetwork->Configuration.ATIMWindow = cpu_to_le32( 590 psecnetwork->Configuration.ATIMWindow); 591 psecnetwork->Configuration.BeaconPeriod = cpu_to_le32( 592 psecnetwork->Configuration.BeaconPeriod); 593 psecnetwork->Configuration.DSConfig = cpu_to_le32( 594 psecnetwork->Configuration.DSConfig); 595 psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32( 596 psecnetwork->Configuration.FHConfig.DwellTime); 597 psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32( 598 psecnetwork->Configuration.FHConfig.HopPattern); 599 psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32( 600 psecnetwork->Configuration.FHConfig.HopSet); 601 psecnetwork->Configuration.FHConfig.Length = cpu_to_le32( 602 psecnetwork->Configuration.FHConfig.Length); 603 psecnetwork->Configuration.Length = cpu_to_le32( 604 psecnetwork->Configuration.Length); 605 psecnetwork->InfrastructureMode = cpu_to_le32( 606 psecnetwork->InfrastructureMode); 607 psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength); 608#endif 609 INIT_LIST_HEAD(&pcmd->list); 610 pcmd->cmdcode = _JoinBss_CMD_; 611 pcmd->parmbuf = (unsigned char *)psecnetwork; 612 pcmd->rsp = NULL; 613 pcmd->rspsz = 0; 614 r8712_enqueue_cmd(pcmdpriv, pcmd); 615 return _SUCCESS; 616} 617 618u8 r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */ 619{ 620 struct cmd_obj *pdisconnect_cmd; 621 struct disconnect_parm *pdisconnect; 622 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 623 624 pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC); 625 if (pdisconnect_cmd == NULL) 626 return _FAIL; 627 pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC); 628 if (pdisconnect == NULL) { 629 kfree((u8 *)pdisconnect_cmd); 630 return _FAIL; 631 } 632 init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect, 633 _DisConnect_CMD_); 634 r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd); 635 return _SUCCESS; 636} 637 638u8 r8712_setopmode_cmd(struct _adapter *padapter, 639 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype) 640{ 641 struct cmd_obj *ph2c; 642 struct setopmode_parm *psetop; 643 644 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 645 646 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 647 if (ph2c == NULL) 648 return _FAIL; 649 psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC); 650 if (psetop == NULL) { 651 kfree((u8 *) ph2c); 652 return _FAIL; 653 } 654 init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_); 655 psetop->mode = (u8)networktype; 656 r8712_enqueue_cmd(pcmdpriv, ph2c); 657 return _SUCCESS; 658} 659 660u8 r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key) 661{ 662 struct cmd_obj *ph2c; 663 struct set_stakey_parm *psetstakey_para; 664 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 665 struct set_stakey_rsp *psetstakey_rsp = NULL; 666 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 667 struct security_priv *psecuritypriv = &padapter->securitypriv; 668 struct sta_info *sta = (struct sta_info *)psta; 669 670 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 671 if (ph2c == NULL) 672 return _FAIL; 673 psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC); 674 if (psetstakey_para == NULL) { 675 kfree((u8 *) ph2c); 676 return _FAIL; 677 } 678 psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC); 679 if (psetstakey_rsp == NULL) { 680 kfree((u8 *) ph2c); 681 kfree((u8 *) psetstakey_para); 682 return _FAIL; 683 } 684 init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_); 685 ph2c->rsp = (u8 *) psetstakey_rsp; 686 ph2c->rspsz = sizeof(struct set_stakey_rsp); 687 memcpy(psetstakey_para->addr, sta->hwaddr, ETH_ALEN); 688 if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) 689 psetstakey_para->algorithm = (unsigned char) 690 psecuritypriv->PrivacyAlgrthm; 691 else 692 GET_ENCRY_ALGO(psecuritypriv, sta, 693 psetstakey_para->algorithm, false); 694 if (unicast_key == true) 695 memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16); 696 else 697 memcpy(&psetstakey_para->key, 698 &psecuritypriv->XGrpKey[ 699 psecuritypriv->XGrpKeyid - 1]. skey, 16); 700 r8712_enqueue_cmd(pcmdpriv, ph2c); 701 return _SUCCESS; 702} 703 704u8 r8712_setrfintfs_cmd(struct _adapter *padapter, u8 mode) 705{ 706 struct cmd_obj *ph2c; 707 struct setrfintfs_parm *psetrfintfsparm; 708 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 709 710 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 711 if (ph2c == NULL) 712 return _FAIL; 713 psetrfintfsparm = kmalloc(sizeof(*psetrfintfsparm), GFP_ATOMIC); 714 if (psetrfintfsparm == NULL) { 715 kfree((unsigned char *) ph2c); 716 return _FAIL; 717 } 718 init_h2fwcmd_w_parm_no_rsp(ph2c, psetrfintfsparm, 719 GEN_CMD_CODE(_SetRFIntFs)); 720 psetrfintfsparm->rfintfs = mode; 721 r8712_enqueue_cmd(pcmdpriv, ph2c); 722 return _SUCCESS; 723} 724 725u8 r8712_setrttbl_cmd(struct _adapter *padapter, 726 struct setratable_parm *prate_table) 727{ 728 struct cmd_obj *ph2c; 729 struct setratable_parm *psetrttblparm; 730 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 731 732 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 733 if (ph2c == NULL) 734 return _FAIL; 735 psetrttblparm = kmalloc(sizeof(*psetrttblparm), GFP_ATOMIC); 736 if (psetrttblparm == NULL) { 737 kfree((unsigned char *)ph2c); 738 return _FAIL; 739 } 740 init_h2fwcmd_w_parm_no_rsp(ph2c, psetrttblparm, 741 GEN_CMD_CODE(_SetRaTable)); 742 memcpy(psetrttblparm, prate_table, sizeof(struct setratable_parm)); 743 r8712_enqueue_cmd(pcmdpriv, ph2c); 744 return _SUCCESS; 745} 746 747u8 r8712_gettssi_cmd(struct _adapter *padapter, u8 offset, u8 *pval) 748{ 749 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 750 struct cmd_obj *ph2c; 751 struct readTSSI_parm *prdtssiparm; 752 753 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 754 if (ph2c == NULL) 755 return _FAIL; 756 prdtssiparm = kmalloc(sizeof(*prdtssiparm), GFP_ATOMIC); 757 if (prdtssiparm == NULL) { 758 kfree((unsigned char *) ph2c); 759 return _FAIL; 760 } 761 INIT_LIST_HEAD(&ph2c->list); 762 ph2c->cmdcode = GEN_CMD_CODE(_ReadTSSI); 763 ph2c->parmbuf = (unsigned char *)prdtssiparm; 764 ph2c->cmdsz = sizeof(struct readTSSI_parm); 765 ph2c->rsp = pval; 766 ph2c->rspsz = sizeof(struct readTSSI_rsp); 767 768 prdtssiparm->offset = offset; 769 r8712_enqueue_cmd(pcmdpriv, ph2c); 770 return _SUCCESS; 771} 772 773u8 r8712_setMacAddr_cmd(struct _adapter *padapter, u8 *mac_addr) 774{ 775 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 776 struct cmd_obj *ph2c; 777 struct SetMacAddr_param *psetMacAddr_para; 778 779 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 780 if (ph2c == NULL) 781 return _FAIL; 782 psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC); 783 if (psetMacAddr_para == NULL) { 784 kfree((u8 *) ph2c); 785 return _FAIL; 786 } 787 init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para, 788 _SetMacAddress_CMD_); 789 memcpy(psetMacAddr_para->MacAddr, mac_addr, ETH_ALEN); 790 r8712_enqueue_cmd(pcmdpriv, ph2c); 791 return _SUCCESS; 792} 793 794u8 r8712_setassocsta_cmd(struct _adapter *padapter, u8 *mac_addr) 795{ 796 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 797 struct cmd_obj *ph2c; 798 struct set_assocsta_parm *psetassocsta_para; 799 struct set_assocsta_rsp *psetassocsta_rsp = NULL; 800 801 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 802 if (ph2c == NULL) 803 return _FAIL; 804 psetassocsta_para = kmalloc(sizeof(*psetassocsta_para), GFP_ATOMIC); 805 if (psetassocsta_para == NULL) { 806 kfree((u8 *) ph2c); 807 return _FAIL; 808 } 809 psetassocsta_rsp = kmalloc(sizeof(*psetassocsta_rsp), GFP_ATOMIC); 810 if (psetassocsta_rsp == NULL) { 811 kfree((u8 *)ph2c); 812 kfree((u8 *)psetassocsta_para); 813 return _FAIL; 814 } 815 init_h2fwcmd_w_parm_no_rsp(ph2c, psetassocsta_para, _SetAssocSta_CMD_); 816 ph2c->rsp = (u8 *) psetassocsta_rsp; 817 ph2c->rspsz = sizeof(struct set_assocsta_rsp); 818 memcpy(psetassocsta_para->addr, mac_addr, ETH_ALEN); 819 r8712_enqueue_cmd(pcmdpriv, ph2c); 820 return _SUCCESS; 821} 822 823u8 r8712_addbareq_cmd(struct _adapter *padapter, u8 tid) 824{ 825 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 826 struct cmd_obj *ph2c; 827 struct addBaReq_parm *paddbareq_parm; 828 829 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 830 if (ph2c == NULL) 831 return _FAIL; 832 paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC); 833 if (paddbareq_parm == NULL) { 834 kfree((unsigned char *)ph2c); 835 return _FAIL; 836 } 837 paddbareq_parm->tid = tid; 838 init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, 839 GEN_CMD_CODE(_AddBAReq)); 840 r8712_enqueue_cmd_ex(pcmdpriv, ph2c); 841 return _SUCCESS; 842} 843 844u8 r8712_wdg_wk_cmd(struct _adapter *padapter) 845{ 846 struct cmd_obj *ph2c; 847 struct drvint_cmd_parm *pdrvintcmd_param; 848 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 849 850 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 851 if (ph2c == NULL) 852 return _FAIL; 853 pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC); 854 if (pdrvintcmd_param == NULL) { 855 kfree((unsigned char *)ph2c); 856 return _FAIL; 857 } 858 pdrvintcmd_param->i_cid = WDG_WK_CID; 859 pdrvintcmd_param->sz = 0; 860 pdrvintcmd_param->pbuf = NULL; 861 init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_); 862 r8712_enqueue_cmd_ex(pcmdpriv, ph2c); 863 return _SUCCESS; 864} 865 866void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) 867{ 868 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 869 870 if (pcmd->res != H2C_SUCCESS) 871 clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY); 872 r8712_free_cmd_obj(pcmd); 873} 874 875void r8712_disassoc_cmd_callback(struct _adapter *padapter, 876 struct cmd_obj *pcmd) 877{ 878 unsigned long irqL; 879 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 880 881 if (pcmd->res != H2C_SUCCESS) { 882 spin_lock_irqsave(&pmlmepriv->lock, irqL); 883 set_fwstate(pmlmepriv, _FW_LINKED); 884 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 885 return; 886 } 887 r8712_free_cmd_obj(pcmd); 888} 889 890void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd) 891{ 892 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 893 894 if (pcmd->res != H2C_SUCCESS) 895 _set_timer(&pmlmepriv->assoc_timer, 1); 896 r8712_free_cmd_obj(pcmd); 897} 898 899void r8712_createbss_cmd_callback(struct _adapter *padapter, 900 struct cmd_obj *pcmd) 901{ 902 unsigned long irqL; 903 u8 timer_cancelled; 904 struct sta_info *psta = NULL; 905 struct wlan_network *pwlan = NULL; 906 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 907 struct ndis_wlan_bssid_ex *pnetwork = (struct ndis_wlan_bssid_ex *) 908 pcmd->parmbuf; 909 struct wlan_network *tgt_network = &(pmlmepriv->cur_network); 910 911 if (pcmd->res != H2C_SUCCESS) 912 _set_timer(&pmlmepriv->assoc_timer, 1); 913 _cancel_timer(&pmlmepriv->assoc_timer, &timer_cancelled); 914#ifdef __BIG_ENDIAN 915 /* endian_convert */ 916 pnetwork->Length = le32_to_cpu(pnetwork->Length); 917 pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength); 918 pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy); 919 pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi); 920 pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse); 921 pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork-> 922 Configuration.ATIMWindow); 923 pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork-> 924 Configuration.DSConfig); 925 pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork-> 926 Configuration.FHConfig.DwellTime); 927 pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork-> 928 Configuration.FHConfig.HopPattern); 929 pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork-> 930 Configuration.FHConfig.HopSet); 931 pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork-> 932 Configuration.FHConfig.Length); 933 pnetwork->Configuration.Length = le32_to_cpu(pnetwork-> 934 Configuration.Length); 935 pnetwork->InfrastructureMode = le32_to_cpu(pnetwork-> 936 InfrastructureMode); 937 pnetwork->IELength = le32_to_cpu(pnetwork->IELength); 938#endif 939 spin_lock_irqsave(&pmlmepriv->lock, irqL); 940 if ((pmlmepriv->fw_state) & WIFI_AP_STATE) { 941 psta = r8712_get_stainfo(&padapter->stapriv, 942 pnetwork->MacAddress); 943 if (!psta) { 944 psta = r8712_alloc_stainfo(&padapter->stapriv, 945 pnetwork->MacAddress); 946 if (psta == NULL) 947 goto createbss_cmd_fail; 948 } 949 r8712_indicate_connect(padapter); 950 } else { 951 pwlan = _r8712_alloc_network(pmlmepriv); 952 if (pwlan == NULL) { 953 pwlan = r8712_get_oldest_wlan_network( 954 &pmlmepriv->scanned_queue); 955 if (pwlan == NULL) 956 goto createbss_cmd_fail; 957 pwlan->last_scanned = jiffies; 958 } else 959 list_add_tail(&(pwlan->list), 960 &pmlmepriv->scanned_queue.queue); 961 pnetwork->Length = r8712_get_ndis_wlan_bssid_ex_sz(pnetwork); 962 memcpy(&(pwlan->network), pnetwork, pnetwork->Length); 963 pwlan->fixed = true; 964 memcpy(&tgt_network->network, pnetwork, 965 (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork))); 966 if (pmlmepriv->fw_state & _FW_UNDER_LINKING) 967 pmlmepriv->fw_state ^= _FW_UNDER_LINKING; 968 /* we will set _FW_LINKED when there is one more sat to 969 * join us (stassoc_event_callback) */ 970 } 971createbss_cmd_fail: 972 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 973 r8712_free_cmd_obj(pcmd); 974} 975 976void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, 977 struct cmd_obj *pcmd) 978{ 979 struct sta_priv *pstapriv = &padapter->stapriv; 980 struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) 981 (pcmd->rsp); 982 struct sta_info *psta = r8712_get_stainfo(pstapriv, 983 psetstakey_rsp->addr); 984 985 if (psta == NULL) 986 goto exit; 987 psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/ 988exit: 989 r8712_free_cmd_obj(pcmd); 990} 991 992void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, 993 struct cmd_obj *pcmd) 994{ 995 unsigned long irqL; 996 struct sta_priv *pstapriv = &padapter->stapriv; 997 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 998 struct set_assocsta_parm *passocsta_parm = 999 (struct set_assocsta_parm *)(pcmd->parmbuf); 1000 struct set_assocsta_rsp *passocsta_rsp = 1001 (struct set_assocsta_rsp *) (pcmd->rsp); 1002 struct sta_info *psta = r8712_get_stainfo(pstapriv, 1003 passocsta_parm->addr); 1004 1005 if (psta == NULL) 1006 return; 1007 psta->aid = psta->mac_id = passocsta_rsp->cam_id; 1008 spin_lock_irqsave(&pmlmepriv->lock, irqL); 1009 if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && 1010 (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))) 1011 pmlmepriv->fw_state ^= _FW_UNDER_LINKING; 1012 set_fwstate(pmlmepriv, _FW_LINKED); 1013 spin_unlock_irqrestore(&pmlmepriv->lock, irqL); 1014 r8712_free_cmd_obj(pcmd); 1015} 1016 1017u8 r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, 1018 u32 tryPktCnt, u32 tryPktInterval, u32 firstStageTO) 1019{ 1020 struct cmd_obj *ph2c; 1021 struct DisconnectCtrlEx_param *param; 1022 struct cmd_priv *pcmdpriv = &adapter->cmdpriv; 1023 1024 ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC); 1025 if (ph2c == NULL) 1026 return _FAIL; 1027 param = kzalloc(sizeof(*param), GFP_ATOMIC); 1028 if (param == NULL) { 1029 kfree((unsigned char *) ph2c); 1030 return _FAIL; 1031 } 1032 1033 param->EnableDrvCtrl = (unsigned char)enableDrvCtrl; 1034 param->TryPktCnt = (unsigned char)tryPktCnt; 1035 param->TryPktInterval = (unsigned char)tryPktInterval; 1036 param->FirstStageTO = (unsigned int)firstStageTO; 1037 1038 init_h2fwcmd_w_parm_no_rsp(ph2c, param, 1039 GEN_CMD_CODE(_DisconnectCtrlEx)); 1040 r8712_enqueue_cmd(pcmdpriv, ph2c); 1041 return _SUCCESS; 1042} 1043