1// SPDX-License-Identifier: GPL-2.0
2/******************************************************************************
3 * rtl871x_ioctl_rtl.c
4 *
5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
6 * Linux device driver for RTL8192SU
7 *
8 * Modifications for inclusion into the Linux staging tree are
9 * Copyright(c) 2010 Larry Finger. All rights reserved.
10 *
11 * Contact information:
12 * WLAN FAE <wlanfae@realtek.com>
13 * Larry Finger <Larry.Finger@lwfinger.net>
14 *
15 ******************************************************************************/
16
17#define  _RTL871X_IOCTL_RTL_C_
18
19#include <linux/rndis.h>
20#include "osdep_service.h"
21#include "drv_types.h"
22#include "wlan_bssdef.h"
23#include "wifi.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"
30
31uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
32{
33	if (poid_par_priv->type_of_oid != QUERY_OID)
34		return RNDIS_STATUS_NOT_ACCEPTED;
35	return RNDIS_STATUS_SUCCESS;
36}
37
38uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
39{
40	struct _adapter *padapter = poid_par_priv->adapter_context;
41
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;
48	} else {
49		return RNDIS_STATUS_INVALID_LENGTH;
50	}
51	return RNDIS_STATUS_SUCCESS;
52}
53
54uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
55{
56	struct _adapter *padapter = poid_par_priv->adapter_context;
57
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;
64	} else {
65		return RNDIS_STATUS_INVALID_LENGTH;
66	}
67	return RNDIS_STATUS_SUCCESS;
68}
69
70uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
71{
72	struct _adapter *padapter = poid_par_priv->adapter_context;
73
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;
80	} else {
81		return RNDIS_STATUS_INVALID_LENGTH;
82	}
83	return RNDIS_STATUS_SUCCESS;
84}
85
86uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
87{
88	if (poid_par_priv->type_of_oid != QUERY_OID)
89		return RNDIS_STATUS_NOT_ACCEPTED;
90	return RNDIS_STATUS_SUCCESS;
91}
92
93uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
94{
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;
99}
100
101uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
102{
103	struct _adapter *padapter = poid_par_priv->adapter_context;
104
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;
112	} else {
113		return RNDIS_STATUS_INVALID_LENGTH;
114	}
115	return RNDIS_STATUS_SUCCESS;
116}
117
118uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
119{
120	if (poid_par_priv->type_of_oid != QUERY_OID)
121		return RNDIS_STATUS_NOT_ACCEPTED;
122	return RNDIS_STATUS_SUCCESS;
123}
124
125uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
126{
127	if (poid_par_priv->type_of_oid != QUERY_OID)
128		return RNDIS_STATUS_NOT_ACCEPTED;
129	return RNDIS_STATUS_SUCCESS;
130}
131
132uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
133{
134	struct _adapter *padapter = poid_par_priv->adapter_context;
135
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;
142	} else {
143		return RNDIS_STATUS_INVALID_LENGTH;
144	}
145	return RNDIS_STATUS_SUCCESS;
146}
147
148uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
149						*poid_par_priv)
150{
151	if (poid_par_priv->type_of_oid != SET_OID)
152		return RNDIS_STATUS_NOT_ACCEPTED;
153	return RNDIS_STATUS_SUCCESS;
154}
155
156uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
157{
158	struct _adapter *padapter = poid_par_priv->adapter_context;
159	u32 preamblemode = 0;
160
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)
165			preamblemode = 0;
166		else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
167			preamblemode = 1;
168		else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
169			preamblemode = 2;
170		*(u32 *)poid_par_priv->information_buf = preamblemode;
171		*poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
172	} else {
173		return RNDIS_STATUS_INVALID_LENGTH;
174	}
175	return RNDIS_STATUS_SUCCESS;
176}
177
178uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
179{
180	if (poid_par_priv->type_of_oid != QUERY_OID)
181		return RNDIS_STATUS_NOT_ACCEPTED;
182	return RNDIS_STATUS_SUCCESS;
183}
184
185uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
186{
187	struct _adapter *padapter = poid_par_priv->adapter_context;
188	struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
189
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;
195}
196
197uint oid_rt_set_channelplan_hdl(struct oid_par_priv
198				       *poid_par_priv)
199{
200	struct _adapter *padapter = poid_par_priv->adapter_context;
201	struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
202
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;
207}
208
209uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
210					 *poid_par_priv)
211{
212	struct _adapter *padapter = poid_par_priv->adapter_context;
213	u32 preamblemode = 0;
214
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;
227	} else {
228		return RNDIS_STATUS_INVALID_LENGTH;
229	}
230	return RNDIS_STATUS_SUCCESS;
231}
232
233uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
234{
235	if (poid_par_priv->type_of_oid != SET_OID)
236		return RNDIS_STATUS_NOT_ACCEPTED;
237	return RNDIS_STATUS_SUCCESS;
238}
239
240uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
241				      *poid_par_priv)
242{
243	return RNDIS_STATUS_SUCCESS;
244}
245
246uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
247					  *poid_par_priv)
248{
249	struct _adapter *padapter = poid_par_priv->adapter_context;
250
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;
257	} else {
258		return RNDIS_STATUS_INVALID_LENGTH;
259	}
260	return RNDIS_STATUS_SUCCESS;
261}
262
263uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
264					  *poid_par_priv)
265{
266	struct _adapter *padapter = poid_par_priv->adapter_context;
267
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;
274	} else {
275		return RNDIS_STATUS_INVALID_LENGTH;
276	}
277	return RNDIS_STATUS_SUCCESS;
278}
279
280uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
281					      *poid_par_priv)
282{
283	return RNDIS_STATUS_SUCCESS;
284}
285
286uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
287						  *poid_par_priv)
288{
289	if (poid_par_priv->type_of_oid != QUERY_OID)
290		return RNDIS_STATUS_NOT_ACCEPTED;
291	return RNDIS_STATUS_SUCCESS;
292}
293
294uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
295					       *poid_par_priv)
296{
297	if (poid_par_priv->type_of_oid != QUERY_OID)
298		return RNDIS_STATUS_NOT_ACCEPTED;
299	return RNDIS_STATUS_SUCCESS;
300}
301
302uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
303{
304	struct _adapter *padapter = poid_par_priv->adapter_context;
305	struct	mlme_priv *pmlmepriv = &padapter->mlmepriv;
306	struct NDIS_802_11_CONFIGURATION *pnic_Config;
307	u32   channelnum;
308
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;
314	else
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;
320}
321
322uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
323			 *poid_par_priv)
324{
325	if (poid_par_priv->type_of_oid != QUERY_OID)
326		return RNDIS_STATUS_NOT_ACCEPTED;
327	return RNDIS_STATUS_SUCCESS;
328}
329
330uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
331{
332	if (poid_par_priv->type_of_oid != QUERY_OID)
333		return RNDIS_STATUS_NOT_ACCEPTED;
334	return RNDIS_STATUS_SUCCESS;
335}
336
337uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
338					       *poid_par_priv)
339{
340	u32 ulInfo = 0;
341
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;
350	} else {
351		return RNDIS_STATUS_INVALID_LENGTH;
352	}
353	return RNDIS_STATUS_SUCCESS;
354}
355
356uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
357{
358	if (poid_par_priv->type_of_oid != QUERY_OID)
359		return RNDIS_STATUS_NOT_ACCEPTED;
360	return RNDIS_STATUS_SUCCESS;
361}
362
363uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
364{
365	if (poid_par_priv->type_of_oid != QUERY_OID)
366		return RNDIS_STATUS_NOT_ACCEPTED;
367	return RNDIS_STATUS_SUCCESS;
368}
369
370uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
371{
372	return RNDIS_STATUS_SUCCESS;
373}
374
375uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
376						   *poid_par_priv)
377{
378	return RNDIS_STATUS_SUCCESS;
379}
380
381uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
382					     *poid_par_priv)
383{
384	if (poid_par_priv->type_of_oid != QUERY_OID)
385		return RNDIS_STATUS_NOT_ACCEPTED;
386	return RNDIS_STATUS_SUCCESS;
387}
388
389uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
390					      *poid_par_priv)
391{
392	return RNDIS_STATUS_SUCCESS;
393}
394
395uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
396						      *poid_par_priv)
397{
398	if (poid_par_priv->type_of_oid != QUERY_OID)
399		return RNDIS_STATUS_NOT_ACCEPTED;
400	return RNDIS_STATUS_SUCCESS;
401}
402
403uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
404					      poid_par_priv)
405{
406	return RNDIS_STATUS_SUCCESS;
407}
408
409uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
410{
411	return RNDIS_STATUS_SUCCESS;
412}
413
414uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
415{
416	if (poid_par_priv->type_of_oid != SET_OID)
417		return RNDIS_STATUS_NOT_ACCEPTED;
418	return RNDIS_STATUS_SUCCESS;
419}
420
421uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
422					     poid_par_priv)
423{
424	uint status = RNDIS_STATUS_SUCCESS;
425	struct _adapter *Adapter = poid_par_priv->adapter_context;
426
427	if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
428		return RNDIS_STATUS_NOT_ACCEPTED;
429	if (poid_par_priv->information_buf_len ==
430	   (sizeof(unsigned long) * 3)) {
431		if (r8712_setrfreg_cmd(Adapter,
432			*(unsigned char *)poid_par_priv->information_buf,
433			(unsigned long)(*((unsigned long *)
434					poid_par_priv->information_buf + 2))))
435			status = RNDIS_STATUS_NOT_ACCEPTED;
436	} else {
437		status = RNDIS_STATUS_INVALID_LENGTH;
438	}
439	return status;
440}
441
442uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
443{
444	uint status = RNDIS_STATUS_SUCCESS;
445	struct _adapter *Adapter = poid_par_priv->adapter_context;
446
447	if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
448		return RNDIS_STATUS_NOT_ACCEPTED;
449	if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
450						   3)) {
451		if (Adapter->mppriv.act_in_progress) {
452			status = RNDIS_STATUS_NOT_ACCEPTED;
453		} else {
454			/* init workparam */
455			Adapter->mppriv.act_in_progress = true;
456			Adapter->mppriv.workparam.bcompleted = false;
457			Adapter->mppriv.workparam.act_type = MPT_READ_RF;
458			Adapter->mppriv.workparam.io_offset = *(unsigned long *)
459						poid_par_priv->information_buf;
460			Adapter->mppriv.workparam.io_value = 0xcccccccc;
461
462		/* RegOffsetValue	- The offset of RF register to read.
463		 * RegDataWidth	- The data width of RF register to read.
464		 * RegDataValue	- The value to read.
465		 * RegOffsetValue = *((unsigned long *)InformationBuffer);
466		 * RegDataWidth = *((unsigned long *)InformationBuffer+1);
467		 * RegDataValue =  *((unsigned long *)InformationBuffer+2);
468		 */
469			if (r8712_getrfreg_cmd(Adapter,
470			    *(unsigned char *)poid_par_priv->information_buf,
471			    (unsigned char *)&Adapter->mppriv.workparam.io_value
472			    ))
473				status = RNDIS_STATUS_NOT_ACCEPTED;
474		}
475	} else {
476		status = RNDIS_STATUS_INVALID_LENGTH;
477	}
478	return status;
479}
480
481enum _CONNECT_STATE_ {
482	CHECKINGSTATUS,
483	ASSOCIATED,
484	ADHOCMODE,
485	NOTASSOCIATED
486};
487
488uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
489{
490	struct _adapter *padapter = poid_par_priv->adapter_context;
491	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
492	u32 ulInfo;
493
494	if (poid_par_priv->type_of_oid != QUERY_OID)
495		return RNDIS_STATUS_NOT_ACCEPTED;
496	/* nStatus==0	CheckingStatus
497	 * nStatus==1	Associated
498	 * nStatus==2	AdHocMode
499	 * nStatus==3	NotAssociated
500	 */
501	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
502		ulInfo = CHECKINGSTATUS;
503	else if (check_fwstate(pmlmepriv, _FW_LINKED))
504		ulInfo = ASSOCIATED;
505	else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
506		ulInfo = ADHOCMODE;
507	else
508		ulInfo = NOTASSOCIATED;
509	*(u32 *)poid_par_priv->information_buf = ulInfo;
510	*poid_par_priv->bytes_rw =  poid_par_priv->information_buf_len;
511	return RNDIS_STATUS_SUCCESS;
512}
513
514uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
515{
516	if (poid_par_priv->type_of_oid != SET_OID)
517		return RNDIS_STATUS_NOT_ACCEPTED;
518	return RNDIS_STATUS_SUCCESS;
519}
520