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