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 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv) 371 { 372 return RNDIS_STATUS_SUCCESS; 373 } 374 375 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv 376 *poid_par_priv) 377 { 378 return RNDIS_STATUS_SUCCESS; 379 } 380 381 uint 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 389 uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv 390 *poid_par_priv) 391 { 392 return RNDIS_STATUS_SUCCESS; 393 } 394 395 uint 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 403 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv* 404 poid_par_priv) 405 { 406 return RNDIS_STATUS_SUCCESS; 407 } 408 409 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv) 410 { 411 return RNDIS_STATUS_SUCCESS; 412 } 413 414 uint 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 421 uint 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 442 uint 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 481 enum _CONNECT_STATE_ { 482 CHECKINGSTATUS, 483 ASSOCIATED, 484 ADHOCMODE, 485 NOTASSOCIATED 486 }; 487 488 uint 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 514 uint 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