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 
31 uint 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 
38 uint 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 
54 uint 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 
70 uint 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 
86 uint 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 
93 uint 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 
101 uint 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 
118 uint 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 
125 uint 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 
132 uint 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 
148 uint 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 
156 uint 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 
178 uint 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 
185 uint 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 
197 uint 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 
209 uint 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 
233 uint 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 
240 uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
241 				      *poid_par_priv)
242 {
243 	return RNDIS_STATUS_SUCCESS;
244 }
245 
246 uint 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 
263 uint 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 
280 uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
281 					      *poid_par_priv)
282 {
283 	return RNDIS_STATUS_SUCCESS;
284 }
285 
286 uint 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 
294 uint 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 
302 uint 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 
322 uint 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 
330 uint 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 
337 uint 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 
356 uint 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 
363 uint 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 
370 
371 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
372 {
373 	return RNDIS_STATUS_SUCCESS;
374 }
375 
376 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
377 						   *poid_par_priv)
378 {
379 	return RNDIS_STATUS_SUCCESS;
380 }
381 
382 uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
383 					     *poid_par_priv)
384 {
385 	if (poid_par_priv->type_of_oid != QUERY_OID)
386 		return RNDIS_STATUS_NOT_ACCEPTED;
387 	return RNDIS_STATUS_SUCCESS;
388 }
389 
390 uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
391 					      *poid_par_priv)
392 {
393 	return RNDIS_STATUS_SUCCESS;
394 }
395 
396 uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
397 						      *poid_par_priv)
398 {
399 	if (poid_par_priv->type_of_oid != QUERY_OID)
400 		return RNDIS_STATUS_NOT_ACCEPTED;
401 	return RNDIS_STATUS_SUCCESS;
402 }
403 
404 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
405 					      poid_par_priv)
406 {
407 	return RNDIS_STATUS_SUCCESS;
408 }
409 
410 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
411 {
412 	return RNDIS_STATUS_SUCCESS;
413 }
414 
415 uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
416 {
417 	if (poid_par_priv->type_of_oid != SET_OID)
418 		return RNDIS_STATUS_NOT_ACCEPTED;
419 	return RNDIS_STATUS_SUCCESS;
420 }
421 
422 uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
423 					     poid_par_priv)
424 {
425 	uint status = RNDIS_STATUS_SUCCESS;
426 	struct _adapter *Adapter = poid_par_priv->adapter_context;
427 
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;
437 	} else {
438 		status = RNDIS_STATUS_INVALID_LENGTH;
439 	}
440 	return status;
441 }
442 
443 uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
444 {
445 	uint status = RNDIS_STATUS_SUCCESS;
446 	struct _adapter *Adapter = poid_par_priv->adapter_context;
447 
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) *
451 						   3)) {
452 		if (Adapter->mppriv.act_in_progress) {
453 			status = RNDIS_STATUS_NOT_ACCEPTED;
454 		} else {
455 			/* init workparam */
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;
462 
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);
469 		 */
470 			if (!r8712_getrfreg_cmd(Adapter,
471 			    *(unsigned char *)poid_par_priv->information_buf,
472 			    (unsigned char *)&Adapter->mppriv.workparam.io_value
473 			    ))
474 				status = RNDIS_STATUS_NOT_ACCEPTED;
475 		}
476 	} else {
477 		status = RNDIS_STATUS_INVALID_LENGTH;
478 	}
479 	return status;
480 }
481 
482 enum _CONNECT_STATE_ {
483 	CHECKINGSTATUS,
484 	ASSOCIATED,
485 	ADHOCMODE,
486 	NOTASSOCIATED
487 };
488 
489 uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
490 {
491 	struct _adapter *padapter = poid_par_priv->adapter_context;
492 	struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
493 	u32 ulInfo;
494 
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
501 	 */
502 	if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
503 		ulInfo = CHECKINGSTATUS;
504 	else if (check_fwstate(pmlmepriv, _FW_LINKED))
505 		ulInfo = ASSOCIATED;
506 	else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
507 		ulInfo = ADHOCMODE;
508 	else
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;
513 }
514 
515 uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
516 {
517 	if (poid_par_priv->type_of_oid != SET_OID)
518 		return RNDIS_STATUS_NOT_ACCEPTED;
519 	return RNDIS_STATUS_SUCCESS;
520 }
521