Add the rt linux 4.1.3-rt3 as base
[kvmfornfv.git] / kernel / drivers / staging / rtl8712 / rtl871x_ioctl_rtl.c
1 /******************************************************************************
2  * rtl871x_ioctl_rtl.c
3  *
4  * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
5  * Linux device driver for RTL8192SU
6  *
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.
10  *
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
14  * more details.
15  *
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
19  *
20  * Modifications for inclusion into the Linux staging tree are
21  * Copyright(c) 2010 Larry Finger. All rights reserved.
22  *
23  * Contact information:
24  * WLAN FAE <wlanfae@realtek.com>
25  * Larry Finger <Larry.Finger@lwfinger.net>
26  *
27  ******************************************************************************/
28
29 #define  _RTL871X_IOCTL_RTL_C_
30
31 #include <linux/rndis.h>
32 #include "osdep_service.h"
33 #include "drv_types.h"
34 #include "wlan_bssdef.h"
35 #include "wifi.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"
42
43 uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
44 {
45         if (poid_par_priv->type_of_oid != QUERY_OID)
46                 return RNDIS_STATUS_NOT_ACCEPTED;
47         return RNDIS_STATUS_SUCCESS;
48 }
49
50 uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
51 {
52         struct _adapter *padapter = (struct _adapter *)
53                                     (poid_par_priv->adapter_context);
54
55         if (poid_par_priv->type_of_oid != QUERY_OID)
56                 return RNDIS_STATUS_NOT_ACCEPTED;
57         if (poid_par_priv->information_buf_len >=  sizeof(u32)) {
58                 *(u32 *)poid_par_priv->information_buf =
59                                 padapter->recvpriv.rx_smallpacket_crcerr;
60                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
61         } else
62                 return RNDIS_STATUS_INVALID_LENGTH;
63         return RNDIS_STATUS_SUCCESS;
64 }
65
66 uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
67 {
68         struct _adapter *padapter = (struct _adapter *)
69                                     (poid_par_priv->adapter_context);
70
71         if (poid_par_priv->type_of_oid != QUERY_OID)
72                 return RNDIS_STATUS_NOT_ACCEPTED;
73         if (poid_par_priv->information_buf_len >=  sizeof(u32)) {
74                 *(u32 *)poid_par_priv->information_buf =
75                                 padapter->recvpriv.rx_middlepacket_crcerr;
76                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
77         } else
78                 return RNDIS_STATUS_INVALID_LENGTH;
79         return RNDIS_STATUS_SUCCESS;
80 }
81
82 uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
83 {
84         struct _adapter *padapter = (struct _adapter *)
85                                     (poid_par_priv->adapter_context);
86
87         if (poid_par_priv->type_of_oid != QUERY_OID)
88                 return RNDIS_STATUS_NOT_ACCEPTED;
89         if (poid_par_priv->information_buf_len >=  sizeof(u32)) {
90                 *(u32 *)poid_par_priv->information_buf =
91                                  padapter->recvpriv.rx_largepacket_crcerr;
92                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
93         } else
94                 return RNDIS_STATUS_INVALID_LENGTH;
95         return RNDIS_STATUS_SUCCESS;
96 }
97
98 uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
99 {
100         if (poid_par_priv->type_of_oid != QUERY_OID)
101                 return RNDIS_STATUS_NOT_ACCEPTED;
102         return RNDIS_STATUS_SUCCESS;
103 }
104
105 uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
106 {
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;
111 }
112
113 uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
114 {
115         struct _adapter *padapter = (struct _adapter *)
116                                     (poid_par_priv->adapter_context);
117
118         if (poid_par_priv->type_of_oid != QUERY_OID)
119                 return RNDIS_STATUS_NOT_ACCEPTED;
120         if (poid_par_priv->information_buf_len >=  sizeof(u32)) {
121                 *(u32 *)poid_par_priv->information_buf =
122                                          padapter->recvpriv.rx_pkts +
123                                          padapter->recvpriv.rx_drop;
124                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
125         } else
126                 return RNDIS_STATUS_INVALID_LENGTH;
127         return RNDIS_STATUS_SUCCESS;
128 }
129
130 uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
131 {
132         if (poid_par_priv->type_of_oid != QUERY_OID)
133                 return RNDIS_STATUS_NOT_ACCEPTED;
134         return RNDIS_STATUS_SUCCESS;
135 }
136
137 uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
138 {
139         if (poid_par_priv->type_of_oid != QUERY_OID)
140                 return RNDIS_STATUS_NOT_ACCEPTED;
141         return RNDIS_STATUS_SUCCESS;
142 }
143
144 uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
145 {
146         struct _adapter *padapter = (struct _adapter *)
147                                     (poid_par_priv->adapter_context);
148
149         if (poid_par_priv->type_of_oid != QUERY_OID)
150                 return RNDIS_STATUS_NOT_ACCEPTED;
151         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
152                 *(uint *)poid_par_priv->information_buf =
153                                          padapter->recvpriv.rx_icv_err;
154                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
155         } else
156                 return RNDIS_STATUS_INVALID_LENGTH;
157         return RNDIS_STATUS_SUCCESS;
158 }
159
160 uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
161                                                 *poid_par_priv)
162 {
163         if (poid_par_priv->type_of_oid != SET_OID)
164                 return RNDIS_STATUS_NOT_ACCEPTED;
165         return RNDIS_STATUS_SUCCESS;
166 }
167
168 uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
169 {
170         struct _adapter *padapter = (struct _adapter *)
171                                     (poid_par_priv->adapter_context);
172         u32 preamblemode = 0;
173
174         if (poid_par_priv->type_of_oid != QUERY_OID)
175                 return RNDIS_STATUS_NOT_ACCEPTED;
176         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
177                 if (padapter->registrypriv.preamble == PREAMBLE_LONG)
178                         preamblemode = 0;
179                 else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
180                         preamblemode = 1;
181                 else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
182                         preamblemode = 2;
183                 *(u32 *)poid_par_priv->information_buf = preamblemode;
184                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
185         } else
186                 return RNDIS_STATUS_INVALID_LENGTH;
187         return RNDIS_STATUS_SUCCESS;
188 }
189
190 uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
191 {
192         if (poid_par_priv->type_of_oid != QUERY_OID)
193                 return RNDIS_STATUS_NOT_ACCEPTED;
194         return RNDIS_STATUS_SUCCESS;
195 }
196
197 uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
198 {
199         struct _adapter *padapter = (struct _adapter *)
200                                     (poid_par_priv->adapter_context);
201         struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
202
203         if (poid_par_priv->type_of_oid != QUERY_OID)
204                 return RNDIS_STATUS_NOT_ACCEPTED;
205         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
206         *(u16 *)poid_par_priv->information_buf = peeprompriv->channel_plan;
207         return RNDIS_STATUS_SUCCESS;
208 }
209
210 uint oid_rt_set_channelplan_hdl(struct oid_par_priv
211                                        *poid_par_priv)
212 {
213         struct _adapter *padapter = (struct _adapter *)
214                                     (poid_par_priv->adapter_context);
215         struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
216
217         if (poid_par_priv->type_of_oid != SET_OID)
218                 return RNDIS_STATUS_NOT_ACCEPTED;
219         peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf;
220         return RNDIS_STATUS_SUCCESS;
221 }
222
223 uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
224                                          *poid_par_priv)
225 {
226         struct _adapter *padapter = (struct _adapter *)
227                                     (poid_par_priv->adapter_context);
228         u32 preamblemode = 0;
229
230         if (poid_par_priv->type_of_oid != SET_OID)
231                 return RNDIS_STATUS_NOT_ACCEPTED;
232         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
233                 preamblemode = *(u32 *)poid_par_priv->information_buf;
234                 if (preamblemode == 0)
235                         padapter->registrypriv.preamble = PREAMBLE_LONG;
236                 else if (preamblemode == 1)
237                         padapter->registrypriv.preamble = PREAMBLE_AUTO;
238                 else if (preamblemode == 2)
239                         padapter->registrypriv.preamble = PREAMBLE_SHORT;
240                 *(u32 *)poid_par_priv->information_buf = preamblemode;
241                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
242         } else
243                 return RNDIS_STATUS_INVALID_LENGTH;
244         return RNDIS_STATUS_SUCCESS;
245 }
246
247 uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
248 {
249         if (poid_par_priv->type_of_oid != SET_OID)
250                 return RNDIS_STATUS_NOT_ACCEPTED;
251         return RNDIS_STATUS_SUCCESS;
252 }
253
254 uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
255                                       *poid_par_priv)
256 {
257         return RNDIS_STATUS_SUCCESS;
258 }
259
260 uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
261                                           *poid_par_priv)
262 {
263         struct _adapter *padapter = (struct _adapter *)
264                                     (poid_par_priv->adapter_context);
265
266         if (poid_par_priv->type_of_oid != QUERY_OID)
267                 return RNDIS_STATUS_NOT_ACCEPTED;
268         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
269                 *(u32 *)poid_par_priv->information_buf =
270                                                  padapter->xmitpriv.tx_bytes;
271                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
272         } else
273                 return RNDIS_STATUS_INVALID_LENGTH;
274         return RNDIS_STATUS_SUCCESS;
275 }
276
277 uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
278                                           *poid_par_priv)
279 {
280         struct _adapter *padapter = (struct _adapter *)
281                                     (poid_par_priv->adapter_context);
282
283         if (poid_par_priv->type_of_oid != QUERY_OID)
284                 return RNDIS_STATUS_NOT_ACCEPTED;
285         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
286                 *(u32 *)poid_par_priv->information_buf =
287                                            padapter->recvpriv.rx_bytes;
288                 *poid_par_priv->bytes_rw = poid_par_priv->
289                                            information_buf_len;
290         } else
291                 return RNDIS_STATUS_INVALID_LENGTH;
292         return RNDIS_STATUS_SUCCESS;
293 }
294
295 uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
296                                               *poid_par_priv)
297 {
298         return RNDIS_STATUS_SUCCESS;
299 }
300
301 uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
302                                                   *poid_par_priv)
303 {
304         if (poid_par_priv->type_of_oid != QUERY_OID)
305                 return RNDIS_STATUS_NOT_ACCEPTED;
306         return RNDIS_STATUS_SUCCESS;
307 }
308
309 uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
310                                                *poid_par_priv)
311 {
312         if (poid_par_priv->type_of_oid != QUERY_OID)
313                 return RNDIS_STATUS_NOT_ACCEPTED;
314         return RNDIS_STATUS_SUCCESS;
315 }
316
317 uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
318 {
319         struct _adapter *padapter = (struct _adapter *)
320                                     (poid_par_priv->adapter_context);
321         struct  mlme_priv *pmlmepriv = &padapter->mlmepriv;
322         struct NDIS_802_11_CONFIGURATION *pnic_Config;
323         u32   channelnum;
324
325         if (poid_par_priv->type_of_oid != QUERY_OID)
326                 return RNDIS_STATUS_NOT_ACCEPTED;
327         if ((check_fwstate(pmlmepriv, _FW_LINKED) == true) ||
328             (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) == true))
329                 pnic_Config = &pmlmepriv->cur_network.network.Configuration;
330         else
331                 pnic_Config = &padapter->registrypriv.dev_network.
332                               Configuration;
333         channelnum = pnic_Config->DSConfig;
334         *(u32 *)poid_par_priv->information_buf = channelnum;
335         *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
336         return RNDIS_STATUS_SUCCESS;
337 }
338
339 uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
340                          *poid_par_priv)
341 {
342         if (poid_par_priv->type_of_oid != QUERY_OID)
343                 return RNDIS_STATUS_NOT_ACCEPTED;
344         return RNDIS_STATUS_SUCCESS;
345 }
346
347 uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
348 {
349         if (poid_par_priv->type_of_oid != QUERY_OID)
350                 return RNDIS_STATUS_NOT_ACCEPTED;
351         return RNDIS_STATUS_SUCCESS;
352 }
353
354 uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
355                                                *poid_par_priv)
356 {
357         u32 ulInfo = 0;
358
359         if (poid_par_priv->type_of_oid != QUERY_OID)
360                 return RNDIS_STATUS_NOT_ACCEPTED;
361         if (poid_par_priv->information_buf_len >= sizeof(u32)) {
362                 ulInfo |= 0x0100; /* WIRELESS_MODE_B */
363                 ulInfo |= 0x0200; /* WIRELESS_MODE_G */
364                 ulInfo |= 0x0400; /* WIRELESS_MODE_A */
365                 *(u32 *) poid_par_priv->information_buf = ulInfo;
366                 *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
367         } else
368                 return RNDIS_STATUS_INVALID_LENGTH;
369         return RNDIS_STATUS_SUCCESS;
370 }
371
372 uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
373 {
374         if (poid_par_priv->type_of_oid != QUERY_OID)
375                 return RNDIS_STATUS_NOT_ACCEPTED;
376         return RNDIS_STATUS_SUCCESS;
377 }
378
379 uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
380 {
381         if (poid_par_priv->type_of_oid != QUERY_OID)
382                 return RNDIS_STATUS_NOT_ACCEPTED;
383         return RNDIS_STATUS_SUCCESS;
384 }
385
386
387 uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
388 {
389         return RNDIS_STATUS_SUCCESS;
390 }
391
392 uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
393                                                    *poid_par_priv)
394 {
395         return RNDIS_STATUS_SUCCESS;
396 }
397
398 uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
399                                              *poid_par_priv)
400 {
401         if (poid_par_priv->type_of_oid != QUERY_OID)
402                 return RNDIS_STATUS_NOT_ACCEPTED;
403         return RNDIS_STATUS_SUCCESS;
404 }
405
406 uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
407                                               *poid_par_priv)
408 {
409         return RNDIS_STATUS_SUCCESS;
410 }
411
412 uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
413                                                       *poid_par_priv)
414 {
415         if (poid_par_priv->type_of_oid != QUERY_OID)
416                 return RNDIS_STATUS_NOT_ACCEPTED;
417         return RNDIS_STATUS_SUCCESS;
418 }
419
420 uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
421                                               poid_par_priv)
422 {
423         return RNDIS_STATUS_SUCCESS;
424 }
425
426 uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
427 {
428         return RNDIS_STATUS_SUCCESS;
429 }
430
431 uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
432 {
433         if (poid_par_priv->type_of_oid != SET_OID)
434                 return RNDIS_STATUS_NOT_ACCEPTED;
435         return RNDIS_STATUS_SUCCESS;
436 }
437
438 uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
439                                              poid_par_priv)
440 {
441         uint status = RNDIS_STATUS_SUCCESS;
442         struct _adapter *Adapter = (struct _adapter *)
443                         (poid_par_priv->adapter_context);
444
445         if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
446                 return RNDIS_STATUS_NOT_ACCEPTED;
447         if (poid_par_priv->information_buf_len ==
448            (sizeof(unsigned long) * 3)) {
449                 if (!r8712_setrfreg_cmd(Adapter,
450                         *(unsigned char *)poid_par_priv->information_buf,
451                         (unsigned long)(*((unsigned long *)
452                                         poid_par_priv->information_buf + 2))))
453                         status = RNDIS_STATUS_NOT_ACCEPTED;
454         } else
455                 status = RNDIS_STATUS_INVALID_LENGTH;
456         return status;
457 }
458
459 uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
460 {
461         uint status = RNDIS_STATUS_SUCCESS;
462         struct _adapter *Adapter = (struct _adapter *)
463                         (poid_par_priv->adapter_context);
464
465         if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
466                 return RNDIS_STATUS_NOT_ACCEPTED;
467         if (poid_par_priv->information_buf_len == (sizeof(unsigned long)*3)) {
468                 if (Adapter->mppriv.act_in_progress == true)
469                         status = RNDIS_STATUS_NOT_ACCEPTED;
470                 else {
471                         /* init workparam */
472                         Adapter->mppriv.act_in_progress = true;
473                         Adapter->mppriv.workparam.bcompleted = false;
474                         Adapter->mppriv.workparam.act_type = MPT_READ_RF;
475                         Adapter->mppriv.workparam.io_offset = *(unsigned long *)
476                                                 poid_par_priv->information_buf;
477                         Adapter->mppriv.workparam.io_value = 0xcccccccc;
478
479                 /* RegOffsetValue       - The offset of RF register to read.
480                  * RegDataWidth - The data width of RF register to read.
481                  * RegDataValue - The value to read.
482                  * RegOffsetValue = *((unsigned long *)InformationBuffer);
483                  * RegDataWidth = *((unsigned long *)InformationBuffer+1);
484                  * RegDataValue =  *((unsigned long *)InformationBuffer+2);
485                  */
486                         if (!r8712_getrfreg_cmd(Adapter,
487                             *(unsigned char *)poid_par_priv->information_buf,
488                             (unsigned char *)&Adapter->mppriv.workparam.
489                             io_value))
490                                 status = RNDIS_STATUS_NOT_ACCEPTED;
491                 }
492         } else
493                 status = RNDIS_STATUS_INVALID_LENGTH;
494         return status;
495 }
496
497 enum _CONNECT_STATE_ {
498         CHECKINGSTATUS,
499         ASSOCIATED,
500         ADHOCMODE,
501         NOTASSOCIATED
502 };
503
504 uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
505 {
506         struct _adapter *padapter = (struct _adapter *)
507                                      (poid_par_priv->adapter_context);
508         struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
509         u32 ulInfo;
510
511         if (poid_par_priv->type_of_oid != QUERY_OID)
512                 return RNDIS_STATUS_NOT_ACCEPTED;
513         /* nStatus==0   CheckingStatus
514          * nStatus==1   Associated
515          * nStatus==2   AdHocMode
516          * nStatus==3   NotAssociated
517          */
518         if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING) == true)
519                 ulInfo = CHECKINGSTATUS;
520         else if (check_fwstate(pmlmepriv, _FW_LINKED) == true)
521                 ulInfo = ASSOCIATED;
522         else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) == true)
523                 ulInfo = ADHOCMODE;
524         else
525                 ulInfo = NOTASSOCIATED;
526         *(u32 *)poid_par_priv->information_buf = ulInfo;
527         *poid_par_priv->bytes_rw =  poid_par_priv->information_buf_len;
528         return RNDIS_STATUS_SUCCESS;
529 }
530
531 uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
532 {
533         if (poid_par_priv->type_of_oid != SET_OID)
534                 return RNDIS_STATUS_NOT_ACCEPTED;
535         return RNDIS_STATUS_SUCCESS;
536 }