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_IOCTL_RTL_C_
31 #include "osdep_service.h"
32 #include "drv_types.h"
33 #include "wlan_bssdef.h"
35 #include "rtl871x_ioctl.h"
36 #include "rtl871x_ioctl_set.h"
37 #include "rtl871x_ioctl_rtl.h"
38 #include "mp_custom_oid.h"
39 #include "rtl871x_mp.h"
40 #include "rtl871x_mp_ioctl.h"
42 uint
oid_rt_get_signal_quality_hdl(struct oid_par_priv
*poid_par_priv
)
44 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
45 return NDIS_STATUS_NOT_ACCEPTED
;
46 return NDIS_STATUS_SUCCESS
;
49 uint
oid_rt_get_small_packet_crc_hdl(struct oid_par_priv
*poid_par_priv
)
51 struct _adapter
*padapter
= (struct _adapter
*)
52 (poid_par_priv
->adapter_context
);
54 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
55 return NDIS_STATUS_NOT_ACCEPTED
;
56 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
57 *(u32
*)poid_par_priv
->information_buf
=
58 padapter
->recvpriv
.rx_smallpacket_crcerr
;
59 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
61 return NDIS_STATUS_INVALID_LENGTH
;
62 return NDIS_STATUS_SUCCESS
;
65 uint
oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv
*poid_par_priv
)
67 struct _adapter
*padapter
= (struct _adapter
*)
68 (poid_par_priv
->adapter_context
);
70 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
71 return NDIS_STATUS_NOT_ACCEPTED
;
72 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
73 *(u32
*)poid_par_priv
->information_buf
=
74 padapter
->recvpriv
.rx_middlepacket_crcerr
;
75 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
77 return NDIS_STATUS_INVALID_LENGTH
;
78 return NDIS_STATUS_SUCCESS
;
81 uint
oid_rt_get_large_packet_crc_hdl(struct oid_par_priv
*poid_par_priv
)
83 struct _adapter
*padapter
= (struct _adapter
*)
84 (poid_par_priv
->adapter_context
);
86 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
87 return NDIS_STATUS_NOT_ACCEPTED
;
88 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
89 *(u32
*)poid_par_priv
->information_buf
=
90 padapter
->recvpriv
.rx_largepacket_crcerr
;
91 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
93 return NDIS_STATUS_INVALID_LENGTH
;
94 return NDIS_STATUS_SUCCESS
;
97 uint
oid_rt_get_tx_retry_hdl(struct oid_par_priv
*poid_par_priv
)
99 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
100 return NDIS_STATUS_NOT_ACCEPTED
;
101 return NDIS_STATUS_SUCCESS
;
104 uint
oid_rt_get_rx_retry_hdl(struct oid_par_priv
*poid_par_priv
)
106 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
107 return NDIS_STATUS_NOT_ACCEPTED
;
108 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
109 return NDIS_STATUS_SUCCESS
;
112 uint
oid_rt_get_rx_total_packet_hdl(struct oid_par_priv
*poid_par_priv
)
114 struct _adapter
*padapter
= (struct _adapter
*)
115 (poid_par_priv
->adapter_context
);
117 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
118 return NDIS_STATUS_NOT_ACCEPTED
;
119 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
120 *(u32
*)poid_par_priv
->information_buf
=
121 padapter
->recvpriv
.rx_pkts
+
122 padapter
->recvpriv
.rx_drop
;
123 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
125 return NDIS_STATUS_INVALID_LENGTH
;
126 return NDIS_STATUS_SUCCESS
;
129 uint
oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv
*poid_par_priv
)
131 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
132 return NDIS_STATUS_NOT_ACCEPTED
;
133 return NDIS_STATUS_SUCCESS
;
136 uint
oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv
*poid_par_priv
)
138 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
139 return NDIS_STATUS_NOT_ACCEPTED
;
140 return NDIS_STATUS_SUCCESS
;
143 uint
oid_rt_get_rx_icv_err_hdl(struct oid_par_priv
*poid_par_priv
)
145 struct _adapter
*padapter
= (struct _adapter
*)
146 (poid_par_priv
->adapter_context
);
148 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
149 return NDIS_STATUS_NOT_ACCEPTED
;
150 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
151 *(uint
*)poid_par_priv
->information_buf
=
152 padapter
->recvpriv
.rx_icv_err
;
153 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
155 return NDIS_STATUS_INVALID_LENGTH
;
156 return NDIS_STATUS_SUCCESS
;
159 uint
oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
162 if (poid_par_priv
->type_of_oid
!= SET_OID
)
163 return NDIS_STATUS_NOT_ACCEPTED
;
164 return NDIS_STATUS_SUCCESS
;
167 uint
oid_rt_get_preamble_mode_hdl(struct oid_par_priv
*poid_par_priv
)
169 struct _adapter
*padapter
= (struct _adapter
*)
170 (poid_par_priv
->adapter_context
);
171 u32 preamblemode
= 0 ;
173 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
174 return NDIS_STATUS_NOT_ACCEPTED
;
175 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
176 if (padapter
->registrypriv
.preamble
== PREAMBLE_LONG
)
178 else if (padapter
->registrypriv
.preamble
== PREAMBLE_AUTO
)
180 else if (padapter
->registrypriv
.preamble
== PREAMBLE_SHORT
)
182 *(u32
*)poid_par_priv
->information_buf
= preamblemode
;
183 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
185 return NDIS_STATUS_INVALID_LENGTH
;
186 return NDIS_STATUS_SUCCESS
;
189 uint
oid_rt_get_ap_ip_hdl(struct oid_par_priv
*poid_par_priv
)
191 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
192 return NDIS_STATUS_NOT_ACCEPTED
;
193 return NDIS_STATUS_SUCCESS
;
196 uint
oid_rt_get_channelplan_hdl(struct oid_par_priv
*poid_par_priv
)
198 struct _adapter
*padapter
= (struct _adapter
*)
199 (poid_par_priv
->adapter_context
);
200 struct eeprom_priv
*peeprompriv
= &padapter
->eeprompriv
;
202 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
203 return NDIS_STATUS_NOT_ACCEPTED
;
204 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
205 *(u16
*)poid_par_priv
->information_buf
= peeprompriv
->channel_plan
;
206 return NDIS_STATUS_SUCCESS
;
209 uint
oid_rt_set_channelplan_hdl(struct oid_par_priv
212 struct _adapter
*padapter
= (struct _adapter
*)
213 (poid_par_priv
->adapter_context
);
214 struct eeprom_priv
*peeprompriv
= &padapter
->eeprompriv
;
216 if (poid_par_priv
->type_of_oid
!= SET_OID
)
217 return NDIS_STATUS_NOT_ACCEPTED
;
218 peeprompriv
->channel_plan
= *(u16
*)poid_par_priv
->information_buf
;
219 return NDIS_STATUS_SUCCESS
;
222 uint
oid_rt_set_preamble_mode_hdl(struct oid_par_priv
225 struct _adapter
*padapter
= (struct _adapter
*)
226 (poid_par_priv
->adapter_context
);
227 u32 preamblemode
= 0;
229 if (poid_par_priv
->type_of_oid
!= SET_OID
)
230 return NDIS_STATUS_NOT_ACCEPTED
;
231 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
232 preamblemode
= *(u32
*)poid_par_priv
->information_buf
;
233 if (preamblemode
== 0)
234 padapter
->registrypriv
.preamble
= PREAMBLE_LONG
;
235 else if (preamblemode
== 1)
236 padapter
->registrypriv
.preamble
= PREAMBLE_AUTO
;
237 else if (preamblemode
== 2)
238 padapter
->registrypriv
.preamble
= PREAMBLE_SHORT
;
239 *(u32
*)poid_par_priv
->information_buf
= preamblemode
;
240 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
242 return NDIS_STATUS_INVALID_LENGTH
;
243 return NDIS_STATUS_SUCCESS
;
246 uint
oid_rt_set_bcn_intvl_hdl(struct oid_par_priv
*poid_par_priv
)
248 if (poid_par_priv
->type_of_oid
!= SET_OID
)
249 return NDIS_STATUS_NOT_ACCEPTED
;
250 return NDIS_STATUS_SUCCESS
;
253 uint
oid_rt_dedicate_probe_hdl(struct oid_par_priv
256 return NDIS_STATUS_SUCCESS
;
259 uint
oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
262 struct _adapter
*padapter
= (struct _adapter
*)
263 (poid_par_priv
->adapter_context
);
265 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
266 return NDIS_STATUS_NOT_ACCEPTED
;
267 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
268 *(u32
*)poid_par_priv
->information_buf
=
269 padapter
->xmitpriv
.tx_bytes
;
270 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
272 return NDIS_STATUS_INVALID_LENGTH
;
273 return NDIS_STATUS_SUCCESS
;
276 uint
oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
279 struct _adapter
*padapter
= (struct _adapter
*)
280 (poid_par_priv
->adapter_context
);
282 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
283 return NDIS_STATUS_NOT_ACCEPTED
;
284 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
285 *(u32
*)poid_par_priv
->information_buf
=
286 padapter
->recvpriv
.rx_bytes
;
287 *poid_par_priv
->bytes_rw
= poid_par_priv
->
290 return NDIS_STATUS_INVALID_LENGTH
;
291 return NDIS_STATUS_SUCCESS
;
294 uint
oid_rt_current_tx_power_level_hdl(struct oid_par_priv
297 return NDIS_STATUS_SUCCESS
;
300 uint
oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
303 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
304 return NDIS_STATUS_NOT_ACCEPTED
;
305 return NDIS_STATUS_SUCCESS
;
308 uint
oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
311 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
312 return NDIS_STATUS_NOT_ACCEPTED
;
313 return NDIS_STATUS_SUCCESS
;
316 uint
oid_rt_get_channel_hdl(struct oid_par_priv
*poid_par_priv
)
318 struct _adapter
*padapter
= (struct _adapter
*)
319 (poid_par_priv
->adapter_context
);
320 struct mlme_priv
*pmlmepriv
= &padapter
->mlmepriv
;
321 struct NDIS_802_11_CONFIGURATION
*pnic_Config
;
324 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
325 return NDIS_STATUS_NOT_ACCEPTED
;
326 if ((check_fwstate(pmlmepriv
, _FW_LINKED
) == true) ||
327 (check_fwstate(pmlmepriv
, WIFI_ADHOC_MASTER_STATE
) == true))
328 pnic_Config
= &pmlmepriv
->cur_network
.network
.Configuration
;
330 pnic_Config
= &padapter
->registrypriv
.dev_network
.
332 channelnum
= pnic_Config
->DSConfig
;
333 *(u32
*)poid_par_priv
->information_buf
= channelnum
;
334 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
335 return NDIS_STATUS_SUCCESS
;
338 uint
oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
341 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
342 return NDIS_STATUS_NOT_ACCEPTED
;
343 return NDIS_STATUS_SUCCESS
;
346 uint
oid_rt_get_key_mismatch_hdl(struct oid_par_priv
*poid_par_priv
)
348 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
349 return NDIS_STATUS_NOT_ACCEPTED
;
350 return NDIS_STATUS_SUCCESS
;
353 uint
oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
358 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
359 return NDIS_STATUS_NOT_ACCEPTED
;
360 if (poid_par_priv
->information_buf_len
>= sizeof(u32
)) {
361 ulInfo
|= 0x0100; /* WIRELESS_MODE_B */
362 ulInfo
|= 0x0200; /* WIRELESS_MODE_G */
363 ulInfo
|= 0x0400; /* WIRELESS_MODE_A */
364 *(u32
*) poid_par_priv
->information_buf
= ulInfo
;
365 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
367 return NDIS_STATUS_INVALID_LENGTH
;
368 return NDIS_STATUS_SUCCESS
;
371 uint
oid_rt_get_channel_list_hdl(struct oid_par_priv
*poid_par_priv
)
373 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
374 return NDIS_STATUS_NOT_ACCEPTED
;
375 return NDIS_STATUS_SUCCESS
;
378 uint
oid_rt_get_scan_in_progress_hdl(struct oid_par_priv
*poid_par_priv
)
380 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
381 return NDIS_STATUS_NOT_ACCEPTED
;
382 return NDIS_STATUS_SUCCESS
;
386 uint
oid_rt_forced_data_rate_hdl(struct oid_par_priv
*poid_par_priv
)
388 return NDIS_STATUS_SUCCESS
;
391 uint
oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
394 return NDIS_STATUS_SUCCESS
;
397 uint
oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
400 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
401 return NDIS_STATUS_NOT_ACCEPTED
;
402 return NDIS_STATUS_SUCCESS
;
405 uint
oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
408 return NDIS_STATUS_SUCCESS
;
411 uint
oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
414 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
415 return NDIS_STATUS_NOT_ACCEPTED
;
416 return NDIS_STATUS_SUCCESS
;
419 uint
oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv
*
422 return NDIS_STATUS_SUCCESS
;
425 uint
oid_rt_ap_supported_hdl(struct oid_par_priv
*poid_par_priv
)
427 return NDIS_STATUS_SUCCESS
;
430 uint
oid_rt_ap_set_passphrase_hdl(struct oid_par_priv
*poid_par_priv
)
432 if (poid_par_priv
->type_of_oid
!= SET_OID
)
433 return NDIS_STATUS_NOT_ACCEPTED
;
434 return NDIS_STATUS_SUCCESS
;
437 uint
oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv
*
440 uint status
= NDIS_STATUS_SUCCESS
;
441 struct _adapter
*Adapter
= (struct _adapter
*)
442 (poid_par_priv
->adapter_context
);
444 if (poid_par_priv
->type_of_oid
!= SET_OID
) /* QUERY_OID */
445 return NDIS_STATUS_NOT_ACCEPTED
;
446 if (poid_par_priv
->information_buf_len
==
447 (sizeof(unsigned long) * 3)) {
448 if (!r8712_setrfreg_cmd(Adapter
,
449 *(unsigned char *)poid_par_priv
->information_buf
,
450 (unsigned long)(*((unsigned long *)
451 poid_par_priv
->information_buf
+ 2))))
452 status
= NDIS_STATUS_NOT_ACCEPTED
;
454 status
= NDIS_STATUS_INVALID_LENGTH
;
458 uint
oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv
*poid_par_priv
)
460 uint status
= NDIS_STATUS_SUCCESS
;
461 struct _adapter
*Adapter
= (struct _adapter
*)
462 (poid_par_priv
->adapter_context
);
464 if (poid_par_priv
->type_of_oid
!= SET_OID
) /* QUERY_OID */
465 return NDIS_STATUS_NOT_ACCEPTED
;
466 if (poid_par_priv
->information_buf_len
== (sizeof(unsigned long)*3)) {
467 if (Adapter
->mppriv
.act_in_progress
== true)
468 status
= NDIS_STATUS_NOT_ACCEPTED
;
471 Adapter
->mppriv
.act_in_progress
= true;
472 Adapter
->mppriv
.workparam
.bcompleted
= false;
473 Adapter
->mppriv
.workparam
.act_type
= MPT_READ_RF
;
474 Adapter
->mppriv
.workparam
.io_offset
= *(unsigned long *)
475 poid_par_priv
->information_buf
;
476 Adapter
->mppriv
.workparam
.io_value
= 0xcccccccc;
478 /* RegOffsetValue - The offset of RF register to read.
479 * RegDataWidth - The data width of RF register to read.
480 * RegDataValue - The value to read.
481 * RegOffsetValue = *((unsigned long *)InformationBuffer);
482 * RegDataWidth = *((unsigned long *)InformationBuffer+1);
483 * RegDataValue = *((unsigned long *)InformationBuffer+2);
485 if (!r8712_getrfreg_cmd(Adapter
,
486 *(unsigned char *)poid_par_priv
->information_buf
,
487 (unsigned char *)&Adapter
->mppriv
.workparam
.
489 status
= NDIS_STATUS_NOT_ACCEPTED
;
492 status
= NDIS_STATUS_INVALID_LENGTH
;
496 enum _CONNECT_STATE_
{
503 uint
oid_rt_get_connect_state_hdl(struct oid_par_priv
*poid_par_priv
)
505 struct _adapter
*padapter
= (struct _adapter
*)
506 (poid_par_priv
->adapter_context
);
507 struct mlme_priv
*pmlmepriv
= &(padapter
->mlmepriv
);
510 if (poid_par_priv
->type_of_oid
!= QUERY_OID
)
511 return NDIS_STATUS_NOT_ACCEPTED
;
512 /* nStatus==0 CheckingStatus
513 * nStatus==1 Associated
514 * nStatus==2 AdHocMode
515 * nStatus==3 NotAssociated
517 if (check_fwstate(pmlmepriv
, _FW_UNDER_LINKING
) == true)
518 ulInfo
= CHECKINGSTATUS
;
519 else if (check_fwstate(pmlmepriv
, _FW_LINKED
) == true)
521 else if (check_fwstate(pmlmepriv
, WIFI_ADHOC_STATE
) == true)
524 ulInfo
= NOTASSOCIATED
;
525 *(u32
*)poid_par_priv
->information_buf
= ulInfo
;
526 *poid_par_priv
->bytes_rw
= poid_par_priv
->information_buf_len
;
527 return NDIS_STATUS_SUCCESS
;
530 uint
oid_rt_set_default_key_id_hdl(struct oid_par_priv
*poid_par_priv
)
532 if (poid_par_priv
->type_of_oid
!= SET_OID
)
533 return NDIS_STATUS_NOT_ACCEPTED
;
534 return NDIS_STATUS_SUCCESS
;