1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6 * Linux device driver for RTL8192SU
8 * Modifications for inclusion into the Linux staging tree are
9 * Copyright(c) 2010 Larry Finger. All rights reserved.
11 * Contact information:
12 * WLAN FAE <wlanfae@realtek.com>
13 * Larry Finger <Larry.Finger@lwfinger.net>
15 ******************************************************************************/
17 #define _RTL871X_IOCTL_RTL_C_
19 #include <linux/rndis.h>
20 #include "osdep_service.h"
21 #include "drv_types.h"
22 #include "wlan_bssdef.h"
24 #include "rtl871x_ioctl.h"
25 #include "rtl871x_ioctl_set.h"
26 #include "rtl871x_ioctl_rtl.h"
27 #include "mp_custom_oid.h"
28 #include "rtl871x_mp.h"
29 #include "rtl871x_mp_ioctl.h"
31 uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
33 if (poid_par_priv->type_of_oid != QUERY_OID)
34 return RNDIS_STATUS_NOT_ACCEPTED;
35 return RNDIS_STATUS_SUCCESS;
38 uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
40 struct _adapter *padapter = poid_par_priv->adapter_context;
42 if (poid_par_priv->type_of_oid != QUERY_OID)
43 return RNDIS_STATUS_NOT_ACCEPTED;
44 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
45 *(u32 *)poid_par_priv->information_buf =
46 padapter->recvpriv.rx_smallpacket_crcerr;
47 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
49 return RNDIS_STATUS_INVALID_LENGTH;
51 return RNDIS_STATUS_SUCCESS;
54 uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
56 struct _adapter *padapter = poid_par_priv->adapter_context;
58 if (poid_par_priv->type_of_oid != QUERY_OID)
59 return RNDIS_STATUS_NOT_ACCEPTED;
60 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
61 *(u32 *)poid_par_priv->information_buf =
62 padapter->recvpriv.rx_middlepacket_crcerr;
63 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
65 return RNDIS_STATUS_INVALID_LENGTH;
67 return RNDIS_STATUS_SUCCESS;
70 uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
72 struct _adapter *padapter = poid_par_priv->adapter_context;
74 if (poid_par_priv->type_of_oid != QUERY_OID)
75 return RNDIS_STATUS_NOT_ACCEPTED;
76 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
77 *(u32 *)poid_par_priv->information_buf =
78 padapter->recvpriv.rx_largepacket_crcerr;
79 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
81 return RNDIS_STATUS_INVALID_LENGTH;
83 return RNDIS_STATUS_SUCCESS;
86 uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
88 if (poid_par_priv->type_of_oid != QUERY_OID)
89 return RNDIS_STATUS_NOT_ACCEPTED;
90 return RNDIS_STATUS_SUCCESS;
93 uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
95 if (poid_par_priv->type_of_oid != QUERY_OID)
96 return RNDIS_STATUS_NOT_ACCEPTED;
97 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
98 return RNDIS_STATUS_SUCCESS;
101 uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
103 struct _adapter *padapter = poid_par_priv->adapter_context;
105 if (poid_par_priv->type_of_oid != QUERY_OID)
106 return RNDIS_STATUS_NOT_ACCEPTED;
107 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
108 *(u32 *)poid_par_priv->information_buf =
109 padapter->recvpriv.rx_pkts +
110 padapter->recvpriv.rx_drop;
111 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
113 return RNDIS_STATUS_INVALID_LENGTH;
115 return RNDIS_STATUS_SUCCESS;
118 uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
120 if (poid_par_priv->type_of_oid != QUERY_OID)
121 return RNDIS_STATUS_NOT_ACCEPTED;
122 return RNDIS_STATUS_SUCCESS;
125 uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
127 if (poid_par_priv->type_of_oid != QUERY_OID)
128 return RNDIS_STATUS_NOT_ACCEPTED;
129 return RNDIS_STATUS_SUCCESS;
132 uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
134 struct _adapter *padapter = poid_par_priv->adapter_context;
136 if (poid_par_priv->type_of_oid != QUERY_OID)
137 return RNDIS_STATUS_NOT_ACCEPTED;
138 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
139 *(uint *)poid_par_priv->information_buf =
140 padapter->recvpriv.rx_icv_err;
141 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
143 return RNDIS_STATUS_INVALID_LENGTH;
145 return RNDIS_STATUS_SUCCESS;
148 uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
151 if (poid_par_priv->type_of_oid != SET_OID)
152 return RNDIS_STATUS_NOT_ACCEPTED;
153 return RNDIS_STATUS_SUCCESS;
156 uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
158 struct _adapter *padapter = poid_par_priv->adapter_context;
159 u32 preamblemode = 0;
161 if (poid_par_priv->type_of_oid != QUERY_OID)
162 return RNDIS_STATUS_NOT_ACCEPTED;
163 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
164 if (padapter->registrypriv.preamble == PREAMBLE_LONG)
166 else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
168 else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
170 *(u32 *)poid_par_priv->information_buf = preamblemode;
171 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
173 return RNDIS_STATUS_INVALID_LENGTH;
175 return RNDIS_STATUS_SUCCESS;
178 uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
180 if (poid_par_priv->type_of_oid != QUERY_OID)
181 return RNDIS_STATUS_NOT_ACCEPTED;
182 return RNDIS_STATUS_SUCCESS;
185 uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
187 struct _adapter *padapter = poid_par_priv->adapter_context;
188 struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
190 if (poid_par_priv->type_of_oid != QUERY_OID)
191 return RNDIS_STATUS_NOT_ACCEPTED;
192 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
193 *(u16 *)poid_par_priv->information_buf = peeprompriv->channel_plan;
194 return RNDIS_STATUS_SUCCESS;
197 uint oid_rt_set_channelplan_hdl(struct oid_par_priv
200 struct _adapter *padapter = poid_par_priv->adapter_context;
201 struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
203 if (poid_par_priv->type_of_oid != SET_OID)
204 return RNDIS_STATUS_NOT_ACCEPTED;
205 peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf;
206 return RNDIS_STATUS_SUCCESS;
209 uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
212 struct _adapter *padapter = poid_par_priv->adapter_context;
213 u32 preamblemode = 0;
215 if (poid_par_priv->type_of_oid != SET_OID)
216 return RNDIS_STATUS_NOT_ACCEPTED;
217 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
218 preamblemode = *(u32 *)poid_par_priv->information_buf;
219 if (preamblemode == 0)
220 padapter->registrypriv.preamble = PREAMBLE_LONG;
221 else if (preamblemode == 1)
222 padapter->registrypriv.preamble = PREAMBLE_AUTO;
223 else if (preamblemode == 2)
224 padapter->registrypriv.preamble = PREAMBLE_SHORT;
225 *(u32 *)poid_par_priv->information_buf = preamblemode;
226 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
228 return RNDIS_STATUS_INVALID_LENGTH;
230 return RNDIS_STATUS_SUCCESS;
233 uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
235 if (poid_par_priv->type_of_oid != SET_OID)
236 return RNDIS_STATUS_NOT_ACCEPTED;
237 return RNDIS_STATUS_SUCCESS;
240 uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
243 return RNDIS_STATUS_SUCCESS;
246 uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
249 struct _adapter *padapter = poid_par_priv->adapter_context;
251 if (poid_par_priv->type_of_oid != QUERY_OID)
252 return RNDIS_STATUS_NOT_ACCEPTED;
253 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
254 *(u32 *)poid_par_priv->information_buf =
255 padapter->xmitpriv.tx_bytes;
256 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
258 return RNDIS_STATUS_INVALID_LENGTH;
260 return RNDIS_STATUS_SUCCESS;
263 uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
266 struct _adapter *padapter = poid_par_priv->adapter_context;
268 if (poid_par_priv->type_of_oid != QUERY_OID)
269 return RNDIS_STATUS_NOT_ACCEPTED;
270 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
271 *(u32 *)poid_par_priv->information_buf =
272 padapter->recvpriv.rx_bytes;
273 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
275 return RNDIS_STATUS_INVALID_LENGTH;
277 return RNDIS_STATUS_SUCCESS;
280 uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
283 return RNDIS_STATUS_SUCCESS;
286 uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
289 if (poid_par_priv->type_of_oid != QUERY_OID)
290 return RNDIS_STATUS_NOT_ACCEPTED;
291 return RNDIS_STATUS_SUCCESS;
294 uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
297 if (poid_par_priv->type_of_oid != QUERY_OID)
298 return RNDIS_STATUS_NOT_ACCEPTED;
299 return RNDIS_STATUS_SUCCESS;
302 uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
304 struct _adapter *padapter = poid_par_priv->adapter_context;
305 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
306 struct NDIS_802_11_CONFIGURATION *pnic_Config;
309 if (poid_par_priv->type_of_oid != QUERY_OID)
310 return RNDIS_STATUS_NOT_ACCEPTED;
311 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
312 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
313 pnic_Config = &pmlmepriv->cur_network.network.Configuration;
315 pnic_Config = &padapter->registrypriv.dev_network.Configuration;
316 channelnum = pnic_Config->DSConfig;
317 *(u32 *)poid_par_priv->information_buf = channelnum;
318 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
319 return RNDIS_STATUS_SUCCESS;
322 uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
325 if (poid_par_priv->type_of_oid != QUERY_OID)
326 return RNDIS_STATUS_NOT_ACCEPTED;
327 return RNDIS_STATUS_SUCCESS;
330 uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
332 if (poid_par_priv->type_of_oid != QUERY_OID)
333 return RNDIS_STATUS_NOT_ACCEPTED;
334 return RNDIS_STATUS_SUCCESS;
337 uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
342 if (poid_par_priv->type_of_oid != QUERY_OID)
343 return RNDIS_STATUS_NOT_ACCEPTED;
344 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
345 ulInfo |= 0x0100; /* WIRELESS_MODE_B */
346 ulInfo |= 0x0200; /* WIRELESS_MODE_G */
347 ulInfo |= 0x0400; /* WIRELESS_MODE_A */
348 *(u32 *) poid_par_priv->information_buf = ulInfo;
349 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
351 return RNDIS_STATUS_INVALID_LENGTH;
353 return RNDIS_STATUS_SUCCESS;
356 uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
358 if (poid_par_priv->type_of_oid != QUERY_OID)
359 return RNDIS_STATUS_NOT_ACCEPTED;
360 return RNDIS_STATUS_SUCCESS;
363 uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
365 if (poid_par_priv->type_of_oid != QUERY_OID)
366 return RNDIS_STATUS_NOT_ACCEPTED;
367 return RNDIS_STATUS_SUCCESS;
371 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
373 return RNDIS_STATUS_SUCCESS;
376 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
379 return RNDIS_STATUS_SUCCESS;
382 uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
385 if (poid_par_priv->type_of_oid != QUERY_OID)
386 return RNDIS_STATUS_NOT_ACCEPTED;
387 return RNDIS_STATUS_SUCCESS;
390 uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
393 return RNDIS_STATUS_SUCCESS;
396 uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
399 if (poid_par_priv->type_of_oid != QUERY_OID)
400 return RNDIS_STATUS_NOT_ACCEPTED;
401 return RNDIS_STATUS_SUCCESS;
404 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
407 return RNDIS_STATUS_SUCCESS;
410 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
412 return RNDIS_STATUS_SUCCESS;
415 uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
417 if (poid_par_priv->type_of_oid != SET_OID)
418 return RNDIS_STATUS_NOT_ACCEPTED;
419 return RNDIS_STATUS_SUCCESS;
422 uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
425 uint status = RNDIS_STATUS_SUCCESS;
426 struct _adapter *Adapter = poid_par_priv->adapter_context;
428 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
429 return RNDIS_STATUS_NOT_ACCEPTED;
430 if (poid_par_priv->information_buf_len ==
431 (sizeof(unsigned long) * 3)) {
432 if (r8712_setrfreg_cmd(Adapter,
433 *(unsigned char *)poid_par_priv->information_buf,
434 (unsigned long)(*((unsigned long *)
435 poid_par_priv->information_buf + 2))))
436 status = RNDIS_STATUS_NOT_ACCEPTED;
438 status = RNDIS_STATUS_INVALID_LENGTH;
443 uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
445 uint status = RNDIS_STATUS_SUCCESS;
446 struct _adapter *Adapter = poid_par_priv->adapter_context;
448 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
449 return RNDIS_STATUS_NOT_ACCEPTED;
450 if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
452 if (Adapter->mppriv.act_in_progress) {
453 status = RNDIS_STATUS_NOT_ACCEPTED;
456 Adapter->mppriv.act_in_progress = true;
457 Adapter->mppriv.workparam.bcompleted = false;
458 Adapter->mppriv.workparam.act_type = MPT_READ_RF;
459 Adapter->mppriv.workparam.io_offset = *(unsigned long *)
460 poid_par_priv->information_buf;
461 Adapter->mppriv.workparam.io_value = 0xcccccccc;
463 /* RegOffsetValue - The offset of RF register to read.
464 * RegDataWidth - The data width of RF register to read.
465 * RegDataValue - The value to read.
466 * RegOffsetValue = *((unsigned long *)InformationBuffer);
467 * RegDataWidth = *((unsigned long *)InformationBuffer+1);
468 * RegDataValue = *((unsigned long *)InformationBuffer+2);
470 if (r8712_getrfreg_cmd(Adapter,
471 *(unsigned char *)poid_par_priv->information_buf,
472 (unsigned char *)&Adapter->mppriv.workparam.io_value
474 status = RNDIS_STATUS_NOT_ACCEPTED;
477 status = RNDIS_STATUS_INVALID_LENGTH;
482 enum _CONNECT_STATE_ {
489 uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
491 struct _adapter *padapter = poid_par_priv->adapter_context;
492 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
495 if (poid_par_priv->type_of_oid != QUERY_OID)
496 return RNDIS_STATUS_NOT_ACCEPTED;
497 /* nStatus==0 CheckingStatus
498 * nStatus==1 Associated
499 * nStatus==2 AdHocMode
500 * nStatus==3 NotAssociated
502 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
503 ulInfo = CHECKINGSTATUS;
504 else if (check_fwstate(pmlmepriv, _FW_LINKED))
506 else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
509 ulInfo = NOTASSOCIATED;
510 *(u32 *)poid_par_priv->information_buf = ulInfo;
511 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
512 return RNDIS_STATUS_SUCCESS;
515 uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
517 if (poid_par_priv->type_of_oid != SET_OID)
518 return RNDIS_STATUS_NOT_ACCEPTED;
519 return RNDIS_STATUS_SUCCESS;