1 /******************************************************************************
4 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5 * Linux device driver for RTL8192SU
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.
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
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
20 * Modifications for inclusion into the Linux staging tree are
21 * Copyright(c) 2010 Larry Finger. All rights reserved.
23 * Contact information:
24 * WLAN FAE <wlanfae@realtek.com>
25 * Larry Finger <Larry.Finger@lwfinger.net>
27 ******************************************************************************/
29 #define _RTL871X_CMD_C_
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>
49 #include "osdep_service.h"
50 #include "drv_types.h"
51 #include "recv_osdep.h"
52 #include "mlme_osdep.h"
53 #include "rtl871x_byteorder.h"
56 Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
57 No irqsave is necessary.
60 static sint
_init_cmd_priv(struct cmd_priv
*pcmdpriv
)
62 sema_init(&(pcmdpriv
->cmd_queue_sema
), 0);
63 sema_init(&(pcmdpriv
->terminate_cmdthread_sema
), 0);
65 _init_queue(&(pcmdpriv
->cmd_queue
));
67 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
68 pcmdpriv
->cmd_seq
= 1;
69 pcmdpriv
->cmd_allocated_buf
= _malloc(MAX_CMDSZ
+ CMDBUFF_ALIGN_SZ
);
70 if (pcmdpriv
->cmd_allocated_buf
== NULL
)
72 pcmdpriv
->cmd_buf
= pcmdpriv
->cmd_allocated_buf
+ CMDBUFF_ALIGN_SZ
-
73 ((addr_t
)(pcmdpriv
->cmd_allocated_buf
) &
74 (CMDBUFF_ALIGN_SZ
-1));
75 pcmdpriv
->rsp_allocated_buf
= _malloc(MAX_RSPSZ
+ 4);
76 if (pcmdpriv
->rsp_allocated_buf
== NULL
)
78 pcmdpriv
->rsp_buf
= pcmdpriv
->rsp_allocated_buf
+ 4 -
79 ((addr_t
)(pcmdpriv
->rsp_allocated_buf
) & 3);
80 pcmdpriv
->cmd_issued_cnt
= 0;
81 pcmdpriv
->cmd_done_cnt
= 0;
82 pcmdpriv
->rsp_cnt
= 0;
86 static sint
_init_evt_priv(struct evt_priv
*pevtpriv
)
88 /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
89 pevtpriv
->event_seq
= 0;
90 pevtpriv
->evt_allocated_buf
= _malloc(MAX_EVTSZ
+ 4);
92 if (pevtpriv
->evt_allocated_buf
== NULL
)
94 pevtpriv
->evt_buf
= pevtpriv
->evt_allocated_buf
+ 4 -
95 ((addr_t
)(pevtpriv
->evt_allocated_buf
) & 3);
96 pevtpriv
->evt_done_cnt
= 0;
100 static void _free_evt_priv(struct evt_priv
*pevtpriv
)
102 kfree(pevtpriv
->evt_allocated_buf
);
105 static void _free_cmd_priv(struct cmd_priv
*pcmdpriv
)
108 kfree(pcmdpriv
->cmd_allocated_buf
);
109 kfree(pcmdpriv
->rsp_allocated_buf
);
116 _enqueue_cmd can only be called between kernel thread,
117 since only spin_lock is used.
119 ISR/Call-Back functions can't call this sub-function.
123 static sint
_enqueue_cmd(struct __queue
*queue
, struct cmd_obj
*obj
)
129 spin_lock_irqsave(&queue
->lock
, irqL
);
130 list_insert_tail(&obj
->list
, &queue
->queue
);
131 spin_unlock_irqrestore(&queue
->lock
, irqL
);
135 static struct cmd_obj
*_dequeue_cmd(struct __queue
*queue
)
140 spin_lock_irqsave(&(queue
->lock
), irqL
);
141 if (is_list_empty(&(queue
->queue
)))
144 obj
= LIST_CONTAINOR(get_next(&(queue
->queue
)),
145 struct cmd_obj
, list
);
146 list_delete(&obj
->list
);
148 spin_unlock_irqrestore(&(queue
->lock
), irqL
);
152 u32
r8712_init_cmd_priv(struct cmd_priv
*pcmdpriv
)
154 return _init_cmd_priv(pcmdpriv
);
157 u32
r8712_init_evt_priv(struct evt_priv
*pevtpriv
)
159 return _init_evt_priv(pevtpriv
);
162 void r8712_free_evt_priv(struct evt_priv
*pevtpriv
)
164 _free_evt_priv(pevtpriv
);
167 void r8712_free_cmd_priv(struct cmd_priv
*pcmdpriv
)
169 _free_cmd_priv(pcmdpriv
);
172 u32
r8712_enqueue_cmd(struct cmd_priv
*pcmdpriv
, struct cmd_obj
*obj
)
176 if (pcmdpriv
->padapter
->eeprompriv
.bautoload_fail_flag
== true)
178 res
= _enqueue_cmd(&pcmdpriv
->cmd_queue
, obj
);
179 up(&pcmdpriv
->cmd_queue_sema
);
183 u32
r8712_enqueue_cmd_ex(struct cmd_priv
*pcmdpriv
, struct cmd_obj
*obj
)
186 struct __queue
*queue
;
190 if (pcmdpriv
->padapter
->eeprompriv
.bautoload_fail_flag
== true)
192 queue
= &pcmdpriv
->cmd_queue
;
193 spin_lock_irqsave(&queue
->lock
, irqL
);
194 list_insert_tail(&obj
->list
, &queue
->queue
);
195 spin_unlock_irqrestore(&queue
->lock
, irqL
);
196 up(&pcmdpriv
->cmd_queue_sema
);
200 struct cmd_obj
*r8712_dequeue_cmd(struct __queue
*queue
)
202 return _dequeue_cmd(queue
);
205 void r8712_free_cmd_obj(struct cmd_obj
*pcmd
)
207 if ((pcmd
->cmdcode
!= _JoinBss_CMD_
) &&
208 (pcmd
->cmdcode
!= _CreateBss_CMD_
))
209 kfree((unsigned char *)pcmd
->parmbuf
);
210 if (pcmd
->rsp
!= NULL
) {
211 if (pcmd
->rspsz
!= 0)
212 kfree((unsigned char *)pcmd
->rsp
);
214 kfree((unsigned char *)pcmd
);
218 r8712_sitesurvey_cmd(~)
220 MUST TAKE CARE THAT BEFORE CALLING THIS FUNC,
221 YOU SHOULD HAVE LOCKED pmlmepriv->lock
223 u8
r8712_sitesurvey_cmd(struct _adapter
*padapter
,
224 struct ndis_802_11_ssid
*pssid
)
226 struct cmd_obj
*ph2c
;
227 struct sitesurvey_parm
*psurveyPara
;
228 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
229 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
231 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
234 psurveyPara
= (struct sitesurvey_parm
*)_malloc(
235 sizeof(struct sitesurvey_parm
));
236 if (psurveyPara
== NULL
) {
237 kfree((unsigned char *) ph2c
);
240 init_h2fwcmd_w_parm_no_rsp(ph2c
, psurveyPara
,
241 GEN_CMD_CODE(_SiteSurvey
));
242 psurveyPara
->bsslimit
= cpu_to_le32(48);
243 psurveyPara
->passive_mode
= cpu_to_le32(pmlmepriv
->passive_mode
);
244 psurveyPara
->ss_ssidlen
= 0;
245 memset(psurveyPara
->ss_ssid
, 0, IW_ESSID_MAX_SIZE
+ 1);
246 if ((pssid
!= NULL
) && (pssid
->SsidLength
)) {
247 memcpy(psurveyPara
->ss_ssid
, pssid
->Ssid
, pssid
->SsidLength
);
248 psurveyPara
->ss_ssidlen
= cpu_to_le32(pssid
->SsidLength
);
250 set_fwstate(pmlmepriv
, _FW_UNDER_SURVEY
);
251 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
252 _set_timer(&pmlmepriv
->scan_to_timer
, SCANNING_TIMEOUT
);
253 padapter
->ledpriv
.LedControlHandler(padapter
, LED_CTL_SITE_SURVEY
);
254 padapter
->blnEnableRxFF0Filter
= 0;
258 u8
r8712_setdatarate_cmd(struct _adapter
*padapter
, u8
*rateset
)
260 struct cmd_obj
*ph2c
;
261 struct setdatarate_parm
*pbsetdataratepara
;
262 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
264 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
267 pbsetdataratepara
= (struct setdatarate_parm
*)_malloc(
268 sizeof(struct setdatarate_parm
));
269 if (pbsetdataratepara
== NULL
) {
273 init_h2fwcmd_w_parm_no_rsp(ph2c
, pbsetdataratepara
,
274 GEN_CMD_CODE(_SetDataRate
));
275 pbsetdataratepara
->mac_id
= 5;
276 memcpy(pbsetdataratepara
->datarates
, rateset
, NumRates
);
277 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
281 u8
r8712_set_chplan_cmd(struct _adapter
*padapter
, int chplan
)
283 struct cmd_obj
*ph2c
;
284 struct SetChannelPlan_param
*psetchplanpara
;
285 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
287 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
290 psetchplanpara
= (struct SetChannelPlan_param
*)
291 _malloc(sizeof(struct SetChannelPlan_param
));
292 if (psetchplanpara
== NULL
) {
296 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetchplanpara
,
297 GEN_CMD_CODE(_SetChannelPlan
));
298 psetchplanpara
->ChannelPlan
= chplan
;
299 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
303 u8
r8712_setbasicrate_cmd(struct _adapter
*padapter
, u8
*rateset
)
305 struct cmd_obj
*ph2c
;
306 struct setbasicrate_parm
*pssetbasicratepara
;
307 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
309 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
312 pssetbasicratepara
= (struct setbasicrate_parm
*)_malloc(
313 sizeof(struct setbasicrate_parm
));
314 if (pssetbasicratepara
== NULL
) {
318 init_h2fwcmd_w_parm_no_rsp(ph2c
, pssetbasicratepara
,
320 memcpy(pssetbasicratepara
->basicrates
, rateset
, NumRates
);
321 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
325 /* power tracking mechanism setting */
326 u8
r8712_setptm_cmd(struct _adapter
*padapter
, u8 type
)
328 struct cmd_obj
*ph2c
;
329 struct writePTM_parm
*pwriteptmparm
;
330 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
332 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
335 pwriteptmparm
= (struct writePTM_parm
*)
336 _malloc(sizeof(struct writePTM_parm
));
337 if (pwriteptmparm
== NULL
) {
341 init_h2fwcmd_w_parm_no_rsp(ph2c
, pwriteptmparm
, GEN_CMD_CODE(_SetPT
));
342 pwriteptmparm
->type
= type
;
343 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
347 u8
r8712_setfwdig_cmd(struct _adapter
*padapter
, u8 type
)
349 struct cmd_obj
*ph2c
;
350 struct writePTM_parm
*pwriteptmparm
;
351 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
353 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
356 pwriteptmparm
= (struct writePTM_parm
*)
357 _malloc(sizeof(struct setdig_parm
));
358 if (pwriteptmparm
== NULL
) {
362 init_h2fwcmd_w_parm_no_rsp(ph2c
, pwriteptmparm
, GEN_CMD_CODE(_SetDIG
));
363 pwriteptmparm
->type
= type
;
364 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
368 u8
r8712_setfwra_cmd(struct _adapter
*padapter
, u8 type
)
370 struct cmd_obj
*ph2c
;
371 struct writePTM_parm
*pwriteptmparm
;
372 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
374 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
377 pwriteptmparm
= (struct writePTM_parm
*)
378 _malloc(sizeof(struct setra_parm
));
379 if (pwriteptmparm
== NULL
) {
383 init_h2fwcmd_w_parm_no_rsp(ph2c
, pwriteptmparm
, GEN_CMD_CODE(_SetRA
));
384 pwriteptmparm
->type
= type
;
385 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
389 u8
r8712_setrfreg_cmd(struct _adapter
*padapter
, u8 offset
, u32 val
)
391 struct cmd_obj
*ph2c
;
392 struct writeRF_parm
*pwriterfparm
;
393 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
395 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
398 pwriterfparm
= (struct writeRF_parm
*)_malloc(
399 sizeof(struct writeRF_parm
));
400 if (pwriterfparm
== NULL
) {
404 init_h2fwcmd_w_parm_no_rsp(ph2c
, pwriterfparm
, GEN_CMD_CODE(_SetRFReg
));
405 pwriterfparm
->offset
= offset
;
406 pwriterfparm
->value
= val
;
407 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
411 u8
r8712_getrfreg_cmd(struct _adapter
*padapter
, u8 offset
, u8
*pval
)
413 struct cmd_obj
*ph2c
;
414 struct readRF_parm
*prdrfparm
;
415 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
417 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
420 prdrfparm
= (struct readRF_parm
*)_malloc(sizeof(struct readRF_parm
));
421 if (prdrfparm
== NULL
) {
425 _init_listhead(&ph2c
->list
);
426 ph2c
->cmdcode
= GEN_CMD_CODE(_GetRFReg
);
427 ph2c
->parmbuf
= (unsigned char *)prdrfparm
;
428 ph2c
->cmdsz
= sizeof(struct readRF_parm
);
430 ph2c
->rspsz
= sizeof(struct readRF_rsp
);
431 prdrfparm
->offset
= offset
;
432 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
436 void r8712_getbbrfreg_cmdrsp_callback(struct _adapter
*padapter
,
437 struct cmd_obj
*pcmd
)
439 kfree(pcmd
->parmbuf
);
441 padapter
->mppriv
.workparam
.bcompleted
= true;
444 void r8712_readtssi_cmdrsp_callback(struct _adapter
*padapter
,
445 struct cmd_obj
*pcmd
)
447 kfree(pcmd
->parmbuf
);
450 padapter
->mppriv
.workparam
.bcompleted
= true;
453 u8
r8712_createbss_cmd(struct _adapter
*padapter
)
455 struct cmd_obj
*pcmd
;
456 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
457 struct wlan_bssid_ex
*pdev_network
=
458 &padapter
->registrypriv
.dev_network
;
460 padapter
->ledpriv
.LedControlHandler(padapter
, LED_CTL_START_TO_LINK
);
461 pcmd
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
464 _init_listhead(&pcmd
->list
);
465 pcmd
->cmdcode
= _CreateBss_CMD_
;
466 pcmd
->parmbuf
= (unsigned char *)pdev_network
;
467 pcmd
->cmdsz
= r8712_get_ndis_wlan_bssid_ex_sz((
468 struct ndis_wlan_bssid_ex
*)
472 /* notes: translate IELength & Length after assign to cmdsz; */
473 pdev_network
->Length
= cpu_to_le32(pcmd
->cmdsz
);
474 pdev_network
->IELength
= cpu_to_le32(pdev_network
->IELength
);
475 pdev_network
->Ssid
.SsidLength
= cpu_to_le32(
476 pdev_network
->Ssid
.SsidLength
);
477 r8712_enqueue_cmd(pcmdpriv
, pcmd
);
481 u8
r8712_joinbss_cmd(struct _adapter
*padapter
, struct wlan_network
*pnetwork
)
485 struct ndis_wlan_bssid_ex
*psecnetwork
;
486 struct cmd_obj
*pcmd
;
487 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
488 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
489 struct qos_priv
*pqospriv
= &pmlmepriv
->qospriv
;
490 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
491 struct registry_priv
*pregistrypriv
= &padapter
->registrypriv
;
492 enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode
= pnetwork
->
493 network
.InfrastructureMode
;
495 padapter
->ledpriv
.LedControlHandler(padapter
, LED_CTL_START_TO_LINK
);
496 pcmd
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
499 t_len
= sizeof(u32
) + 6 * sizeof(unsigned char) + 2 +
500 sizeof(struct ndis_802_11_ssid
) + sizeof(u32
) +
502 sizeof(enum NDIS_802_11_NETWORK_TYPE
) +
503 sizeof(struct NDIS_802_11_CONFIGURATION
) +
504 sizeof(enum NDIS_802_11_NETWORK_INFRASTRUCTURE
) +
505 sizeof(NDIS_802_11_RATES_EX
) +
506 sizeof(u32
) + MAX_IE_SZ
;
508 /* for hidden ap to set fw_state here */
509 if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
|WIFI_ADHOC_STATE
) !=
511 switch (ndis_network_mode
) {
513 pmlmepriv
->fw_state
|= WIFI_ADHOC_STATE
;
515 case Ndis802_11Infrastructure
:
516 pmlmepriv
->fw_state
|= WIFI_STATION_STATE
;
518 case Ndis802_11APMode
:
519 case Ndis802_11AutoUnknown
:
520 case Ndis802_11InfrastructureMax
:
524 psecnetwork
= (struct ndis_wlan_bssid_ex
*)&psecuritypriv
->sec_bss
;
525 if (psecnetwork
== NULL
) {
529 memset(psecnetwork
, 0, t_len
);
530 memcpy(psecnetwork
, &pnetwork
->network
, t_len
);
531 auth
= &psecuritypriv
->authenticator_ie
[0];
532 psecuritypriv
->authenticator_ie
[0] = (unsigned char)
533 psecnetwork
->IELength
;
534 if ((psecnetwork
->IELength
-12) < (256 - 1))
535 memcpy(&psecuritypriv
->authenticator_ie
[1],
536 &psecnetwork
->IEs
[12], psecnetwork
->IELength
-12);
538 memcpy(&psecuritypriv
->authenticator_ie
[1],
539 &psecnetwork
->IEs
[12], (256-1));
540 psecnetwork
->IELength
= 0;
541 /* If the the driver wants to use the bssid to create the connection.
542 * If not, we copy the connecting AP's MAC address to it so that
543 * the driver just has the bssid information for PMKIDList searching.
545 if (pmlmepriv
->assoc_by_bssid
== false)
546 memcpy(&pmlmepriv
->assoc_bssid
[0],
547 &pnetwork
->network
.MacAddress
[0], ETH_ALEN
);
548 psecnetwork
->IELength
= r8712_restruct_sec_ie(padapter
,
549 &pnetwork
->network
.IEs
[0],
550 &psecnetwork
->IEs
[0],
551 pnetwork
->network
.IELength
);
552 pqospriv
->qos_option
= 0;
553 if (pregistrypriv
->wmm_enable
) {
556 tmp_len
= r8712_restruct_wmm_ie(padapter
,
557 &pnetwork
->network
.IEs
[0],
558 &psecnetwork
->IEs
[0],
559 pnetwork
->network
.IELength
,
560 psecnetwork
->IELength
);
561 if (psecnetwork
->IELength
!= tmp_len
) {
562 psecnetwork
->IELength
= tmp_len
;
563 pqospriv
->qos_option
= 1; /* WMM IE in beacon */
565 pqospriv
->qos_option
= 0; /* no WMM IE in beacon */
567 if (pregistrypriv
->ht_enable
) {
568 /* For WEP mode, we will use the bg mode to do the connection
569 * to avoid some IOT issues, especially for Realtek 8192u
572 if ((padapter
->securitypriv
.PrivacyAlgrthm
!= _WEP40_
) &&
573 (padapter
->securitypriv
.PrivacyAlgrthm
!= _WEP104_
)) {
574 /* restructure_ht_ie */
575 r8712_restructure_ht_ie(padapter
,
576 &pnetwork
->network
.IEs
[0],
577 &psecnetwork
->IEs
[0],
578 pnetwork
->network
.IELength
,
579 &psecnetwork
->IELength
);
582 psecuritypriv
->supplicant_ie
[0] = (u8
)psecnetwork
->IELength
;
583 if (psecnetwork
->IELength
< 255)
584 memcpy(&psecuritypriv
->supplicant_ie
[1], &psecnetwork
->IEs
[0],
585 psecnetwork
->IELength
);
587 memcpy(&psecuritypriv
->supplicant_ie
[1], &psecnetwork
->IEs
[0],
589 /* get cmdsz before endian conversion */
590 pcmd
->cmdsz
= r8712_get_ndis_wlan_bssid_ex_sz(psecnetwork
);
592 /* wlan_network endian conversion */
593 psecnetwork
->Length
= cpu_to_le32(psecnetwork
->Length
);
594 psecnetwork
->Ssid
.SsidLength
= cpu_to_le32(
595 psecnetwork
->Ssid
.SsidLength
);
596 psecnetwork
->Privacy
= cpu_to_le32(psecnetwork
->Privacy
);
597 psecnetwork
->Rssi
= cpu_to_le32(psecnetwork
->Rssi
);
598 psecnetwork
->NetworkTypeInUse
= cpu_to_le32(
599 psecnetwork
->NetworkTypeInUse
);
600 psecnetwork
->Configuration
.ATIMWindow
= cpu_to_le32(
601 psecnetwork
->Configuration
.ATIMWindow
);
602 psecnetwork
->Configuration
.BeaconPeriod
= cpu_to_le32(
603 psecnetwork
->Configuration
.BeaconPeriod
);
604 psecnetwork
->Configuration
.DSConfig
= cpu_to_le32(
605 psecnetwork
->Configuration
.DSConfig
);
606 psecnetwork
->Configuration
.FHConfig
.DwellTime
= cpu_to_le32(
607 psecnetwork
->Configuration
.FHConfig
.DwellTime
);
608 psecnetwork
->Configuration
.FHConfig
.HopPattern
= cpu_to_le32(
609 psecnetwork
->Configuration
.FHConfig
.HopPattern
);
610 psecnetwork
->Configuration
.FHConfig
.HopSet
= cpu_to_le32(
611 psecnetwork
->Configuration
.FHConfig
.HopSet
);
612 psecnetwork
->Configuration
.FHConfig
.Length
= cpu_to_le32(
613 psecnetwork
->Configuration
.FHConfig
.Length
);
614 psecnetwork
->Configuration
.Length
= cpu_to_le32(
615 psecnetwork
->Configuration
.Length
);
616 psecnetwork
->InfrastructureMode
= cpu_to_le32(
617 psecnetwork
->InfrastructureMode
);
618 psecnetwork
->IELength
= cpu_to_le32(psecnetwork
->IELength
);
620 _init_listhead(&pcmd
->list
);
621 pcmd
->cmdcode
= _JoinBss_CMD_
;
622 pcmd
->parmbuf
= (unsigned char *)psecnetwork
;
625 r8712_enqueue_cmd(pcmdpriv
, pcmd
);
629 u8
r8712_disassoc_cmd(struct _adapter
*padapter
) /* for sta_mode */
631 struct cmd_obj
*pdisconnect_cmd
;
632 struct disconnect_parm
*pdisconnect
;
633 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
635 pdisconnect_cmd
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
636 if (pdisconnect_cmd
== NULL
)
638 pdisconnect
= (struct disconnect_parm
*)_malloc(
639 sizeof(struct disconnect_parm
));
640 if (pdisconnect
== NULL
) {
641 kfree((u8
*)pdisconnect_cmd
);
644 init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd
, pdisconnect
,
646 r8712_enqueue_cmd(pcmdpriv
, pdisconnect_cmd
);
650 u8
r8712_setopmode_cmd(struct _adapter
*padapter
,
651 enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype
)
653 struct cmd_obj
*ph2c
;
654 struct setopmode_parm
*psetop
;
656 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
658 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
661 psetop
= (struct setopmode_parm
*)_malloc(
662 sizeof(struct setopmode_parm
));
663 if (psetop
== NULL
) {
667 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetop
, _SetOpMode_CMD_
);
668 psetop
->mode
= (u8
)networktype
;
669 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
673 u8
r8712_setstakey_cmd(struct _adapter
*padapter
, u8
*psta
, u8 unicast_key
)
675 struct cmd_obj
*ph2c
;
676 struct set_stakey_parm
*psetstakey_para
;
677 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
678 struct set_stakey_rsp
*psetstakey_rsp
= NULL
;
679 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
680 struct security_priv
*psecuritypriv
= &padapter
->securitypriv
;
681 struct sta_info
*sta
= (struct sta_info
*)psta
;
683 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
686 psetstakey_para
= (struct set_stakey_parm
*)_malloc(
687 sizeof(struct set_stakey_parm
));
688 if (psetstakey_para
== NULL
) {
692 psetstakey_rsp
= (struct set_stakey_rsp
*)_malloc(
693 sizeof(struct set_stakey_rsp
));
694 if (psetstakey_rsp
== NULL
) {
696 kfree((u8
*) psetstakey_para
);
699 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetstakey_para
, _SetStaKey_CMD_
);
700 ph2c
->rsp
= (u8
*) psetstakey_rsp
;
701 ph2c
->rspsz
= sizeof(struct set_stakey_rsp
);
702 memcpy(psetstakey_para
->addr
, sta
->hwaddr
, ETH_ALEN
);
703 if (check_fwstate(pmlmepriv
, WIFI_STATION_STATE
))
704 psetstakey_para
->algorithm
= (unsigned char)
705 psecuritypriv
->PrivacyAlgrthm
;
707 GET_ENCRY_ALGO(psecuritypriv
, sta
,
708 psetstakey_para
->algorithm
, false);
709 if (unicast_key
== true)
710 memcpy(&psetstakey_para
->key
, &sta
->x_UncstKey
, 16);
712 memcpy(&psetstakey_para
->key
,
713 &psecuritypriv
->XGrpKey
[
714 psecuritypriv
->XGrpKeyid
- 1]. skey
, 16);
715 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
719 u8
r8712_setrfintfs_cmd(struct _adapter
*padapter
, u8 mode
)
721 struct cmd_obj
*ph2c
;
722 struct setrfintfs_parm
*psetrfintfsparm
;
723 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
725 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
728 psetrfintfsparm
= (struct setrfintfs_parm
*)_malloc(
729 sizeof(struct setrfintfs_parm
));
730 if (psetrfintfsparm
== NULL
) {
731 kfree((unsigned char *) ph2c
);
734 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetrfintfsparm
,
735 GEN_CMD_CODE(_SetRFIntFs
));
736 psetrfintfsparm
->rfintfs
= mode
;
737 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
741 u8
r8712_setrttbl_cmd(struct _adapter
*padapter
,
742 struct setratable_parm
*prate_table
)
744 struct cmd_obj
*ph2c
;
745 struct setratable_parm
*psetrttblparm
;
746 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
748 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
751 psetrttblparm
= (struct setratable_parm
*)_malloc(
752 sizeof(struct setratable_parm
));
753 if (psetrttblparm
== NULL
) {
754 kfree((unsigned char *)ph2c
);
757 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetrttblparm
,
758 GEN_CMD_CODE(_SetRaTable
));
759 memcpy(psetrttblparm
, prate_table
, sizeof(struct setratable_parm
));
760 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
764 u8
r8712_gettssi_cmd(struct _adapter
*padapter
, u8 offset
, u8
*pval
)
766 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
767 struct cmd_obj
*ph2c
;
768 struct readTSSI_parm
*prdtssiparm
;
770 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
773 prdtssiparm
= (struct readTSSI_parm
*)
774 _malloc(sizeof(struct readTSSI_parm
));
775 if (prdtssiparm
== NULL
) {
776 kfree((unsigned char *) ph2c
);
779 _init_listhead(&ph2c
->list
);
780 ph2c
->cmdcode
= GEN_CMD_CODE(_ReadTSSI
);
781 ph2c
->parmbuf
= (unsigned char *)prdtssiparm
;
782 ph2c
->cmdsz
= sizeof(struct readTSSI_parm
);
784 ph2c
->rspsz
= sizeof(struct readTSSI_rsp
);
786 prdtssiparm
->offset
= offset
;
787 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
791 u8
r8712_setMacAddr_cmd(struct _adapter
*padapter
, u8
*mac_addr
)
793 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
794 struct cmd_obj
*ph2c
;
795 struct SetMacAddr_param
*psetMacAddr_para
;
797 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
800 psetMacAddr_para
= (struct SetMacAddr_param
*)_malloc(
801 sizeof(struct SetMacAddr_param
));
802 if (psetMacAddr_para
== NULL
) {
806 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetMacAddr_para
,
807 _SetMacAddress_CMD_
);
808 memcpy(psetMacAddr_para
->MacAddr
, mac_addr
, ETH_ALEN
);
809 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
813 u8
r8712_setassocsta_cmd(struct _adapter
*padapter
, u8
*mac_addr
)
815 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
816 struct cmd_obj
*ph2c
;
817 struct set_assocsta_parm
*psetassocsta_para
;
818 struct set_stakey_rsp
*psetassocsta_rsp
= NULL
;
820 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
823 psetassocsta_para
= (struct set_assocsta_parm
*)
824 _malloc(sizeof(struct set_assocsta_parm
));
825 if (psetassocsta_para
== NULL
) {
829 psetassocsta_rsp
= (struct set_stakey_rsp
*)_malloc(
830 sizeof(struct set_assocsta_rsp
));
831 if (psetassocsta_rsp
== NULL
) {
833 kfree((u8
*)psetassocsta_para
);
836 init_h2fwcmd_w_parm_no_rsp(ph2c
, psetassocsta_para
, _SetAssocSta_CMD_
);
837 ph2c
->rsp
= (u8
*) psetassocsta_rsp
;
838 ph2c
->rspsz
= sizeof(struct set_assocsta_rsp
);
839 memcpy(psetassocsta_para
->addr
, mac_addr
, ETH_ALEN
);
840 r8712_enqueue_cmd(pcmdpriv
, ph2c
);
844 u8
r8712_addbareq_cmd(struct _adapter
*padapter
, u8 tid
)
846 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
847 struct cmd_obj
*ph2c
;
848 struct addBaReq_parm
*paddbareq_parm
;
850 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
853 paddbareq_parm
= (struct addBaReq_parm
*)_malloc(
854 sizeof(struct addBaReq_parm
));
855 if (paddbareq_parm
== NULL
) {
856 kfree((unsigned char *)ph2c
);
859 paddbareq_parm
->tid
= tid
;
860 init_h2fwcmd_w_parm_no_rsp(ph2c
, paddbareq_parm
,
861 GEN_CMD_CODE(_AddBAReq
));
862 r8712_enqueue_cmd_ex(pcmdpriv
, ph2c
);
866 u8
r8712_wdg_wk_cmd(struct _adapter
*padapter
)
868 struct cmd_obj
*ph2c
;
869 struct drvint_cmd_parm
*pdrvintcmd_param
;
870 struct cmd_priv
*pcmdpriv
= &padapter
->cmdpriv
;
872 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
875 pdrvintcmd_param
= (struct drvint_cmd_parm
*)_malloc(
876 sizeof(struct drvint_cmd_parm
));
877 if (pdrvintcmd_param
== NULL
) {
878 kfree((unsigned char *)ph2c
);
881 pdrvintcmd_param
->i_cid
= WDG_WK_CID
;
882 pdrvintcmd_param
->sz
= 0;
883 pdrvintcmd_param
->pbuf
= NULL
;
884 init_h2fwcmd_w_parm_no_rsp(ph2c
, pdrvintcmd_param
, _DRV_INT_CMD_
);
885 r8712_enqueue_cmd_ex(pcmdpriv
, ph2c
);
889 void r8712_survey_cmd_callback(struct _adapter
*padapter
, struct cmd_obj
*pcmd
)
891 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
893 if (pcmd
->res
!= H2C_SUCCESS
)
894 clr_fwstate(pmlmepriv
, _FW_UNDER_SURVEY
);
895 r8712_free_cmd_obj(pcmd
);
898 void r8712_disassoc_cmd_callback(struct _adapter
*padapter
,
899 struct cmd_obj
*pcmd
)
902 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
904 if (pcmd
->res
!= H2C_SUCCESS
) {
905 spin_lock_irqsave(&pmlmepriv
->lock
, irqL
);
906 set_fwstate(pmlmepriv
, _FW_LINKED
);
907 spin_unlock_irqrestore(&pmlmepriv
->lock
, irqL
);
910 r8712_free_cmd_obj(pcmd
);
913 void r8712_joinbss_cmd_callback(struct _adapter
*padapter
, struct cmd_obj
*pcmd
)
915 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
917 if ((pcmd
->res
!= H2C_SUCCESS
))
918 _set_timer(&pmlmepriv
->assoc_timer
, 1);
919 r8712_free_cmd_obj(pcmd
);
922 void r8712_createbss_cmd_callback(struct _adapter
*padapter
,
923 struct cmd_obj
*pcmd
)
927 struct sta_info
*psta
= NULL
;
928 struct wlan_network
*pwlan
= NULL
;
929 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
930 struct ndis_wlan_bssid_ex
*pnetwork
= (struct ndis_wlan_bssid_ex
*)
932 struct wlan_network
*tgt_network
= &(pmlmepriv
->cur_network
);
934 if ((pcmd
->res
!= H2C_SUCCESS
))
935 _set_timer(&pmlmepriv
->assoc_timer
, 1);
936 _cancel_timer(&pmlmepriv
->assoc_timer
, &timer_cancelled
);
939 pnetwork
->Length
= le32_to_cpu(pnetwork
->Length
);
940 pnetwork
->Ssid
.SsidLength
= le32_to_cpu(pnetwork
->Ssid
.SsidLength
);
941 pnetwork
->Privacy
= le32_to_cpu(pnetwork
->Privacy
);
942 pnetwork
->Rssi
= le32_to_cpu(pnetwork
->Rssi
);
943 pnetwork
->NetworkTypeInUse
= le32_to_cpu(pnetwork
->NetworkTypeInUse
);
944 pnetwork
->Configuration
.ATIMWindow
= le32_to_cpu(pnetwork
->
945 Configuration
.ATIMWindow
);
946 pnetwork
->Configuration
.DSConfig
= le32_to_cpu(pnetwork
->
947 Configuration
.DSConfig
);
948 pnetwork
->Configuration
.FHConfig
.DwellTime
= le32_to_cpu(pnetwork
->
949 Configuration
.FHConfig
.DwellTime
);
950 pnetwork
->Configuration
.FHConfig
.HopPattern
= le32_to_cpu(pnetwork
->
951 Configuration
.FHConfig
.HopPattern
);
952 pnetwork
->Configuration
.FHConfig
.HopSet
= le32_to_cpu(pnetwork
->
953 Configuration
.FHConfig
.HopSet
);
954 pnetwork
->Configuration
.FHConfig
.Length
= le32_to_cpu(pnetwork
->
955 Configuration
.FHConfig
.Length
);
956 pnetwork
->Configuration
.Length
= le32_to_cpu(pnetwork
->
957 Configuration
.Length
);
958 pnetwork
->InfrastructureMode
= le32_to_cpu(pnetwork
->
960 pnetwork
->IELength
= le32_to_cpu(pnetwork
->IELength
);
962 spin_lock_irqsave(&pmlmepriv
->lock
, irqL
);
963 if ((pmlmepriv
->fw_state
) & WIFI_AP_STATE
) {
964 psta
= r8712_get_stainfo(&padapter
->stapriv
,
965 pnetwork
->MacAddress
);
967 psta
= r8712_alloc_stainfo(&padapter
->stapriv
,
968 pnetwork
->MacAddress
);
970 goto createbss_cmd_fail
;
972 r8712_indicate_connect(padapter
);
974 pwlan
= _r8712_alloc_network(pmlmepriv
);
976 pwlan
= r8712_get_oldest_wlan_network(
977 &pmlmepriv
->scanned_queue
);
979 goto createbss_cmd_fail
;
980 pwlan
->last_scanned
= jiffies
;
982 list_insert_tail(&(pwlan
->list
),
983 &pmlmepriv
->scanned_queue
.queue
);
984 pnetwork
->Length
= r8712_get_ndis_wlan_bssid_ex_sz(pnetwork
);
985 memcpy(&(pwlan
->network
), pnetwork
, pnetwork
->Length
);
987 memcpy(&tgt_network
->network
, pnetwork
,
988 (r8712_get_ndis_wlan_bssid_ex_sz(pnetwork
)));
989 if (pmlmepriv
->fw_state
& _FW_UNDER_LINKING
)
990 pmlmepriv
->fw_state
^= _FW_UNDER_LINKING
;
991 /* we will set _FW_LINKED when there is one more sat to
992 * join us (stassoc_event_callback) */
995 spin_unlock_irqrestore(&pmlmepriv
->lock
, irqL
);
996 r8712_free_cmd_obj(pcmd
);
999 void r8712_setstaKey_cmdrsp_callback(struct _adapter
*padapter
,
1000 struct cmd_obj
*pcmd
)
1002 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1003 struct set_stakey_rsp
*psetstakey_rsp
= (struct set_stakey_rsp
*)
1005 struct sta_info
*psta
= r8712_get_stainfo(pstapriv
,
1006 psetstakey_rsp
->addr
);
1010 psta
->aid
= psta
->mac_id
= psetstakey_rsp
->keyid
; /*CAM_ID(CAM_ENTRY)*/
1012 r8712_free_cmd_obj(pcmd
);
1015 void r8712_setassocsta_cmdrsp_callback(struct _adapter
*padapter
,
1016 struct cmd_obj
*pcmd
)
1019 struct sta_priv
*pstapriv
= &padapter
->stapriv
;
1020 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
1021 struct set_assocsta_parm
*passocsta_parm
=
1022 (struct set_assocsta_parm
*)(pcmd
->parmbuf
);
1023 struct set_assocsta_rsp
*passocsta_rsp
=
1024 (struct set_assocsta_rsp
*) (pcmd
->rsp
);
1025 struct sta_info
*psta
= r8712_get_stainfo(pstapriv
,
1026 passocsta_parm
->addr
);
1030 psta
->aid
= psta
->mac_id
= passocsta_rsp
->cam_id
;
1031 spin_lock_irqsave(&pmlmepriv
->lock
, irqL
);
1032 if ((check_fwstate(pmlmepriv
, WIFI_MP_STATE
)) &&
1033 (check_fwstate(pmlmepriv
, _FW_UNDER_LINKING
)))
1034 pmlmepriv
->fw_state
^= _FW_UNDER_LINKING
;
1035 set_fwstate(pmlmepriv
, _FW_LINKED
);
1036 spin_unlock_irqrestore(&pmlmepriv
->lock
, irqL
);
1037 r8712_free_cmd_obj(pcmd
);
1040 u8
r8712_disconnectCtrlEx_cmd(struct _adapter
*adapter
, u32 enableDrvCtrl
,
1041 u32 tryPktCnt
, u32 tryPktInterval
, u32 firstStageTO
)
1043 struct cmd_obj
*ph2c
;
1044 struct DisconnectCtrlEx_param
*param
;
1045 struct cmd_priv
*pcmdpriv
= &adapter
->cmdpriv
;
1047 ph2c
= (struct cmd_obj
*)_malloc(sizeof(struct cmd_obj
));
1050 param
= (struct DisconnectCtrlEx_param
*)
1051 _malloc(sizeof(struct DisconnectCtrlEx_param
));
1052 if (param
== NULL
) {
1053 kfree((unsigned char *) ph2c
);
1056 memset(param
, 0, sizeof(struct DisconnectCtrlEx_param
));
1058 param
->EnableDrvCtrl
= (unsigned char)enableDrvCtrl
;
1059 param
->TryPktCnt
= (unsigned char)tryPktCnt
;
1060 param
->TryPktInterval
= (unsigned char)tryPktInterval
;
1061 param
->FirstStageTO
= (unsigned int)firstStageTO
;
1063 init_h2fwcmd_w_parm_no_rsp(ph2c
, param
,
1064 GEN_CMD_CODE(_DisconnectCtrlEx
));
1065 r8712_enqueue_cmd(pcmdpriv
, ph2c
);