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->
288 return RNDIS_STATUS_INVALID_LENGTH;
290 return RNDIS_STATUS_SUCCESS;
293 uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
296 return RNDIS_STATUS_SUCCESS;
299 uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
302 if (poid_par_priv->type_of_oid != QUERY_OID)
303 return RNDIS_STATUS_NOT_ACCEPTED;
304 return RNDIS_STATUS_SUCCESS;
307 uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
310 if (poid_par_priv->type_of_oid != QUERY_OID)
311 return RNDIS_STATUS_NOT_ACCEPTED;
312 return RNDIS_STATUS_SUCCESS;
315 uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
317 struct _adapter *padapter = poid_par_priv->adapter_context;
318 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
319 struct NDIS_802_11_CONFIGURATION *pnic_Config;
322 if (poid_par_priv->type_of_oid != QUERY_OID)
323 return RNDIS_STATUS_NOT_ACCEPTED;
324 if (check_fwstate(pmlmepriv, _FW_LINKED) ||
325 check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
326 pnic_Config = &pmlmepriv->cur_network.network.Configuration;
328 pnic_Config = &padapter->registrypriv.dev_network.
330 channelnum = pnic_Config->DSConfig;
331 *(u32 *)poid_par_priv->information_buf = channelnum;
332 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
333 return RNDIS_STATUS_SUCCESS;
336 uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
339 if (poid_par_priv->type_of_oid != QUERY_OID)
340 return RNDIS_STATUS_NOT_ACCEPTED;
341 return RNDIS_STATUS_SUCCESS;
344 uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
346 if (poid_par_priv->type_of_oid != QUERY_OID)
347 return RNDIS_STATUS_NOT_ACCEPTED;
348 return RNDIS_STATUS_SUCCESS;
351 uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
356 if (poid_par_priv->type_of_oid != QUERY_OID)
357 return RNDIS_STATUS_NOT_ACCEPTED;
358 if (poid_par_priv->information_buf_len >= sizeof(u32)) {
359 ulInfo |= 0x0100; /* WIRELESS_MODE_B */
360 ulInfo |= 0x0200; /* WIRELESS_MODE_G */
361 ulInfo |= 0x0400; /* WIRELESS_MODE_A */
362 *(u32 *) poid_par_priv->information_buf = ulInfo;
363 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
365 return RNDIS_STATUS_INVALID_LENGTH;
367 return RNDIS_STATUS_SUCCESS;
370 uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
372 if (poid_par_priv->type_of_oid != QUERY_OID)
373 return RNDIS_STATUS_NOT_ACCEPTED;
374 return RNDIS_STATUS_SUCCESS;
377 uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
379 if (poid_par_priv->type_of_oid != QUERY_OID)
380 return RNDIS_STATUS_NOT_ACCEPTED;
381 return RNDIS_STATUS_SUCCESS;
385 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
387 return RNDIS_STATUS_SUCCESS;
390 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
393 return RNDIS_STATUS_SUCCESS;
396 uint oid_rt_get_bss_wireless_mode_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_scan_with_magic_packet_hdl(struct oid_par_priv
407 return RNDIS_STATUS_SUCCESS;
410 uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
413 if (poid_par_priv->type_of_oid != QUERY_OID)
414 return RNDIS_STATUS_NOT_ACCEPTED;
415 return RNDIS_STATUS_SUCCESS;
418 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
421 return RNDIS_STATUS_SUCCESS;
424 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
426 return RNDIS_STATUS_SUCCESS;
429 uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
431 if (poid_par_priv->type_of_oid != SET_OID)
432 return RNDIS_STATUS_NOT_ACCEPTED;
433 return RNDIS_STATUS_SUCCESS;
436 uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
439 uint status = RNDIS_STATUS_SUCCESS;
440 struct _adapter *Adapter = poid_par_priv->adapter_context;
442 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
443 return RNDIS_STATUS_NOT_ACCEPTED;
444 if (poid_par_priv->information_buf_len ==
445 (sizeof(unsigned long) * 3)) {
446 if (!r8712_setrfreg_cmd(Adapter,
447 *(unsigned char *)poid_par_priv->information_buf,
448 (unsigned long)(*((unsigned long *)
449 poid_par_priv->information_buf + 2))))
450 status = RNDIS_STATUS_NOT_ACCEPTED;
452 status = RNDIS_STATUS_INVALID_LENGTH;
457 uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
459 uint status = RNDIS_STATUS_SUCCESS;
460 struct _adapter *Adapter = poid_par_priv->adapter_context;
462 if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
463 return RNDIS_STATUS_NOT_ACCEPTED;
464 if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
466 if (Adapter->mppriv.act_in_progress) {
467 status = RNDIS_STATUS_NOT_ACCEPTED;
470 Adapter->mppriv.act_in_progress = true;
471 Adapter->mppriv.workparam.bcompleted = false;
472 Adapter->mppriv.workparam.act_type = MPT_READ_RF;
473 Adapter->mppriv.workparam.io_offset = *(unsigned long *)
474 poid_par_priv->information_buf;
475 Adapter->mppriv.workparam.io_value = 0xcccccccc;
477 /* RegOffsetValue - The offset of RF register to read.
478 * RegDataWidth - The data width of RF register to read.
479 * RegDataValue - The value to read.
480 * RegOffsetValue = *((unsigned long *)InformationBuffer);
481 * RegDataWidth = *((unsigned long *)InformationBuffer+1);
482 * RegDataValue = *((unsigned long *)InformationBuffer+2);
484 if (!r8712_getrfreg_cmd(Adapter,
485 *(unsigned char *)poid_par_priv->information_buf,
486 (unsigned char *)&Adapter->mppriv.workparam.
488 status = RNDIS_STATUS_NOT_ACCEPTED;
491 status = RNDIS_STATUS_INVALID_LENGTH;
496 enum _CONNECT_STATE_ {
503 uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
505 struct _adapter *padapter = poid_par_priv->adapter_context;
506 struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
509 if (poid_par_priv->type_of_oid != QUERY_OID)
510 return RNDIS_STATUS_NOT_ACCEPTED;
511 /* nStatus==0 CheckingStatus
512 * nStatus==1 Associated
513 * nStatus==2 AdHocMode
514 * nStatus==3 NotAssociated
516 if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
517 ulInfo = CHECKINGSTATUS;
518 else if (check_fwstate(pmlmepriv, _FW_LINKED))
520 else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
523 ulInfo = NOTASSOCIATED;
524 *(u32 *)poid_par_priv->information_buf = ulInfo;
525 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
526 return RNDIS_STATUS_SUCCESS;
529 uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
531 if (poid_par_priv->type_of_oid != SET_OID)
532 return RNDIS_STATUS_NOT_ACCEPTED;
533 return RNDIS_STATUS_SUCCESS;