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 <linux/rndis.h>
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
36 #include "rtl871x_ioctl.h"
37 #include "rtl871x_ioctl_set.h"
38 #include "rtl871x_ioctl_rtl.h"
39 #include "mp_custom_oid.h"
40 #include "rtl871x_mp.h"
41 #include "rtl871x_mp_ioctl.h"
43 uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
45 if (poid_par_priv->type_of_oid != QUERY_OID)
46 return RNDIS_STATUS_NOT_ACCEPTED;
47 return RNDIS_STATUS_SUCCESS;
50 uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
52 struct _adapter *padapter = poid_par_priv->adapter_context;
54 if (poid_par_priv->type_of_oid != QUERY_OID)
55 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
63 return RNDIS_STATUS_SUCCESS;
66 uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
68 struct _adapter *padapter = poid_par_priv->adapter_context;
70 if (poid_par_priv->type_of_oid != QUERY_OID)
71 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
79 return RNDIS_STATUS_SUCCESS;
82 uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
84 struct _adapter *padapter = poid_par_priv->adapter_context;
86 if (poid_par_priv->type_of_oid != QUERY_OID)
87 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
95 return RNDIS_STATUS_SUCCESS;
98 uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
100 if (poid_par_priv->type_of_oid != QUERY_OID)
101 return RNDIS_STATUS_NOT_ACCEPTED;
102 return RNDIS_STATUS_SUCCESS;
105 uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
107 if (poid_par_priv->type_of_oid != QUERY_OID)
108 return RNDIS_STATUS_NOT_ACCEPTED;
109 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
110 return RNDIS_STATUS_SUCCESS;
113 uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
115 struct _adapter *padapter = poid_par_priv->adapter_context;
117 if (poid_par_priv->type_of_oid != QUERY_OID)
118 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
127 return RNDIS_STATUS_SUCCESS;
130 uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
132 if (poid_par_priv->type_of_oid != QUERY_OID)
133 return RNDIS_STATUS_NOT_ACCEPTED;
134 return RNDIS_STATUS_SUCCESS;
137 uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
139 if (poid_par_priv->type_of_oid != QUERY_OID)
140 return RNDIS_STATUS_NOT_ACCEPTED;
141 return RNDIS_STATUS_SUCCESS;
144 uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
146 struct _adapter *padapter = poid_par_priv->adapter_context;
148 if (poid_par_priv->type_of_oid != QUERY_OID)
149 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
157 return RNDIS_STATUS_SUCCESS;
160 uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
163 if (poid_par_priv->type_of_oid != SET_OID)
164 return RNDIS_STATUS_NOT_ACCEPTED;
165 return RNDIS_STATUS_SUCCESS;
168 uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
170 struct _adapter *padapter = poid_par_priv->adapter_context;
171 u32 preamblemode = 0;
173 if (poid_par_priv->type_of_oid != QUERY_OID)
174 return RNDIS_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 RNDIS_STATUS_INVALID_LENGTH;
187 return RNDIS_STATUS_SUCCESS;
190 uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
192 if (poid_par_priv->type_of_oid != QUERY_OID)
193 return RNDIS_STATUS_NOT_ACCEPTED;
194 return RNDIS_STATUS_SUCCESS;
197 uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
199 struct _adapter *padapter = poid_par_priv->adapter_context;
200 struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
202 if (poid_par_priv->type_of_oid != QUERY_OID)
203 return RNDIS_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 RNDIS_STATUS_SUCCESS;
209 uint oid_rt_set_channelplan_hdl(struct oid_par_priv
212 struct _adapter *padapter = poid_par_priv->adapter_context;
213 struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
215 if (poid_par_priv->type_of_oid != SET_OID)
216 return RNDIS_STATUS_NOT_ACCEPTED;
217 peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf;
218 return RNDIS_STATUS_SUCCESS;
221 uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
224 struct _adapter *padapter = poid_par_priv->adapter_context;
225 u32 preamblemode = 0;
227 if (poid_par_priv->type_of_oid != SET_OID)
228 return RNDIS_STATUS_NOT_ACCEPTED;
229 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
230 preamblemode = *(u32 *)poid_par_priv->information_buf;
231 if (preamblemode == 0)
232 padapter->registrypriv.preamble = PREAMBLE_LONG;
233 else if (preamblemode == 1)
234 padapter->registrypriv.preamble = PREAMBLE_AUTO;
235 else if (preamblemode == 2)
236 padapter->registrypriv.preamble = PREAMBLE_SHORT;
237 *(u32 *)poid_par_priv->information_buf = preamblemode;
238 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
240 return RNDIS_STATUS_INVALID_LENGTH;
242 return RNDIS_STATUS_SUCCESS;
245 uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
247 if (poid_par_priv->type_of_oid != SET_OID)
248 return RNDIS_STATUS_NOT_ACCEPTED;
249 return RNDIS_STATUS_SUCCESS;
252 uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
255 return RNDIS_STATUS_SUCCESS;
258 uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
261 struct _adapter *padapter = poid_par_priv->adapter_context;
263 if (poid_par_priv->type_of_oid != QUERY_OID)
264 return RNDIS_STATUS_NOT_ACCEPTED;
265 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
266 *(u32 *)poid_par_priv->information_buf =
267 padapter->xmitpriv.tx_bytes;
268 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
270 return RNDIS_STATUS_INVALID_LENGTH;
272 return RNDIS_STATUS_SUCCESS;
275 uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
278 struct _adapter *padapter = poid_par_priv->adapter_context;
280 if (poid_par_priv->type_of_oid != QUERY_OID)
281 return RNDIS_STATUS_NOT_ACCEPTED;
282 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
283 *(u32 *)poid_par_priv->information_buf =
284 padapter->recvpriv.rx_bytes;
285 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
287 return RNDIS_STATUS_INVALID_LENGTH;
289 return RNDIS_STATUS_SUCCESS;
292 uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
295 return RNDIS_STATUS_SUCCESS;
298 uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
301 if (poid_par_priv->type_of_oid != QUERY_OID)
302 return RNDIS_STATUS_NOT_ACCEPTED;
303 return RNDIS_STATUS_SUCCESS;
306 uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
309 if (poid_par_priv->type_of_oid != QUERY_OID)
310 return RNDIS_STATUS_NOT_ACCEPTED;
311 return RNDIS_STATUS_SUCCESS;
314 uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
316 struct _adapter *padapter = poid_par_priv->adapter_context;
317 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
318 struct NDIS_802_11_CONFIGURATION *pnic_Config;
321 if (poid_par_priv->type_of_oid != QUERY_OID)
322 return RNDIS_STATUS_NOT_ACCEPTED;
323 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
324 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
325 pnic_Config = &pmlmepriv->cur_network.network.Configuration;
327 pnic_Config = &padapter->registrypriv.dev_network.Configuration;
328 channelnum = pnic_Config->DSConfig;
329 *(u32 *)poid_par_priv->information_buf = channelnum;
330 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
331 return RNDIS_STATUS_SUCCESS;
334 uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
337 if (poid_par_priv->type_of_oid != QUERY_OID)
338 return RNDIS_STATUS_NOT_ACCEPTED;
339 return RNDIS_STATUS_SUCCESS;
342 uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
344 if (poid_par_priv->type_of_oid != QUERY_OID)
345 return RNDIS_STATUS_NOT_ACCEPTED;
346 return RNDIS_STATUS_SUCCESS;
349 uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
354 if (poid_par_priv->type_of_oid != QUERY_OID)
355 return RNDIS_STATUS_NOT_ACCEPTED;
356 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
357 ulInfo |= 0x0100; /* WIRELESS_MODE_B */
358 ulInfo |= 0x0200; /* WIRELESS_MODE_G */
359 ulInfo |= 0x0400; /* WIRELESS_MODE_A */
360 *(u32 *) poid_par_priv->information_buf = ulInfo;
361 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
363 return RNDIS_STATUS_INVALID_LENGTH;
365 return RNDIS_STATUS_SUCCESS;
368 uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
370 if (poid_par_priv->type_of_oid != QUERY_OID)
371 return RNDIS_STATUS_NOT_ACCEPTED;
372 return RNDIS_STATUS_SUCCESS;
375 uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
377 if (poid_par_priv->type_of_oid != QUERY_OID)
378 return RNDIS_STATUS_NOT_ACCEPTED;
379 return RNDIS_STATUS_SUCCESS;
383 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
385 return RNDIS_STATUS_SUCCESS;
388 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
391 return RNDIS_STATUS_SUCCESS;
394 uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
397 if (poid_par_priv->type_of_oid != QUERY_OID)
398 return RNDIS_STATUS_NOT_ACCEPTED;
399 return RNDIS_STATUS_SUCCESS;
402 uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
405 return RNDIS_STATUS_SUCCESS;
408 uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
411 if (poid_par_priv->type_of_oid != QUERY_OID)
412 return RNDIS_STATUS_NOT_ACCEPTED;
413 return RNDIS_STATUS_SUCCESS;
416 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
419 return RNDIS_STATUS_SUCCESS;
422 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
424 return RNDIS_STATUS_SUCCESS;
427 uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
429 if (poid_par_priv->type_of_oid != SET_OID)
430 return RNDIS_STATUS_NOT_ACCEPTED;
431 return RNDIS_STATUS_SUCCESS;
434 uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
437 uint status = RNDIS_STATUS_SUCCESS;
438 struct _adapter *Adapter = poid_par_priv->adapter_context;
440 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
441 return RNDIS_STATUS_NOT_ACCEPTED;
442 if (poid_par_priv->information_buf_len ==
443 (sizeof(unsigned long) * 3)) {
444 if (!r8712_setrfreg_cmd(Adapter,
445 *(unsigned char *)poid_par_priv->information_buf,
446 (unsigned long)(*((unsigned long *)
447 poid_par_priv->information_buf + 2))))
448 status = RNDIS_STATUS_NOT_ACCEPTED;
450 status = RNDIS_STATUS_INVALID_LENGTH;
455 uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
457 uint status = RNDIS_STATUS_SUCCESS;
458 struct _adapter *Adapter = poid_par_priv->adapter_context;
460 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
461 return RNDIS_STATUS_NOT_ACCEPTED;
462 if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
464 if (Adapter->mppriv.act_in_progress) {
465 status = RNDIS_STATUS_NOT_ACCEPTED;
468 Adapter->mppriv.act_in_progress = true;
469 Adapter->mppriv.workparam.bcompleted = false;
470 Adapter->mppriv.workparam.act_type = MPT_READ_RF;
471 Adapter->mppriv.workparam.io_offset = *(unsigned long *)
472 poid_par_priv->information_buf;
473 Adapter->mppriv.workparam.io_value = 0xcccccccc;
475 /* RegOffsetValue - The offset of RF register to read.
476 * RegDataWidth - The data width of RF register to read.
477 * RegDataValue - The value to read.
478 * RegOffsetValue = *((unsigned long *)InformationBuffer);
479 * RegDataWidth = *((unsigned long *)InformationBuffer+1);
480 * RegDataValue = *((unsigned long *)InformationBuffer+2);
482 if (!r8712_getrfreg_cmd(Adapter,
483 *(unsigned char *)poid_par_priv->information_buf,
484 (unsigned char *)&Adapter->mppriv.workparam.io_value
486 status = RNDIS_STATUS_NOT_ACCEPTED;
489 status = RNDIS_STATUS_INVALID_LENGTH;
494 enum _CONNECT_STATE_ {
501 uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
503 struct _adapter *padapter = poid_par_priv->adapter_context;
504 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
507 if (poid_par_priv->type_of_oid != QUERY_OID)
508 return RNDIS_STATUS_NOT_ACCEPTED;
509 /* nStatus==0 CheckingStatus
510 * nStatus==1 Associated
511 * nStatus==2 AdHocMode
512 * nStatus==3 NotAssociated
514 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
515 ulInfo = CHECKINGSTATUS;
516 else if (check_fwstate(pmlmepriv, _FW_LINKED))
518 else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
521 ulInfo = NOTASSOCIATED;
522 *(u32 *)poid_par_priv->information_buf = ulInfo;
523 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
524 return RNDIS_STATUS_SUCCESS;
527 uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
529 if (poid_par_priv->type_of_oid != SET_OID)
530 return RNDIS_STATUS_NOT_ACCEPTED;
531 return RNDIS_STATUS_SUCCESS;